RPC Replies

When responding to RPC requests originating from clients, Volity entities must format their responses as arrays, with the structure described on this page. This is because, when playing games, there are really two distinct levels of error that a client can make through RPC: either a malformed or mistimed request, which will result in a fault, or a perfectly fine request that tries to make an illegal move of some sort, which will result in the return of a localizable RPC reply as described below.

Generally, other sorts of requests (usually between two automated entities, or from a referee to the client) should either return some expected value (according to the nature of the request) or throw a fault. In many cases (as with ref-to-client requests) the caller won't even pay particular attention to the return value.

Flags

The first member of the response array is a flag (a string) whose dot-delimited namespace signals it as being defined by either the core Volity platform or a specific ruleset. This first token basically describes the success of the original request. (The namespace of the flag is orthogonal to the namespace of the RPC request that's being replied to.)

A flag of volity.ok signals success. If the original request is returning a value, the second member of the array is this value (which may be of any Jabber-RPC type). An array beginning with volity.ok may not have more than two members.

A flag of anything else signals failure. Specifically, it means that, while the sender understood the original request well enough to not throw back an RPC fault, it still wishes to signal a failure to carry out the request's instructions. Most commonly, this is due to a game player requesting the referee to make an illegal move. Arrays signalling failure may have any length (except zero). All array members must be strings, and will be interpreted as tokens. When the client receives a failure array, it will display the localized failure message (and take no other action).

Core-defined flags

These are tokens of the volity namespace, and their English translations.

(Italicized comments are not translations; they are comments, explaining when the given token can occur.)

volity.ok
(Generic success -- what follows is data. This token has no translation, because only failures are translated.)
volity.unknown_token
(Untranslatable message: \1) (Can be generated client-side for unrecognized tokens.)
volity.invalid_seat
(Invalid seat "\1")
volity.offline
The service has been disabled by the administrator.
volity.no_seat
No seats are available. (The requester's sit() request was received but refused.)
volity.seat_not_available
That seat is not available. The sit() request is refused, because the requested seat is not part of the current game configuration.
volity.bad_config
The game cannot begin, because the current table configuration is not allowed. (The requester's ready() request was received but refused, because the table's current configuration can't support a new game.)
volity.empty_seats
The game cannot begin, because not all required seats have players. (The requester's ready() request was received but refused, because there are mandatory seats still empty.)
volity.referee_not_ready
The referee is not yet ready to service requests.
volity.game_in_progress
The game is in progress.
volity.game_not_in_progress
The game has not yet started.
volity.authorizing_in_progress
The game is still authorizing.
volity.jid_present
The player \1 has already joined the table.
volity.jid_not_present
The player \1 has not joined the table.
volity.jid_not_ready
The player \1 is not yet ready to take part in the game. (The player's client has joined, but hasn't sent its first send_state RPC yet. It's also possible that the named client is not a Volity client at all, but a plain Jabber MUC client.)
volity.not_seated
You are not seated.
volity.are_seated
You are seated.
volity.not_your_turn
It's not your turn.
volity.relay_failed
Your message could not be delivered to \1. (Used when the referee tries to send an invitation on behalf of a player.)
volity.no_bots_provided
This game parlor does not provide bots.
volity.bot_not_available
That bot is not available.
volity.not_bot
The player \1 is not a bot.
volity.bot_seated
That bot is seated.
volity.players_not_responding
The following player(s) cannot be located by the bookkeeper: \1
volity.players_not_authorized
The following player(s) are not authorized to play: \1
volity.game_record_conflict
A game record already exists for this referee.
volity.game_record_missing
No game record exists for this referee.
volity.prepare_game_failure
The bookkeeper could not authorize this game: \1
volity.unknown_uri
The bookkeeper does not recognize the URI: \1
volity.unknown_url
The bookkeeper does not recognize the URL: \1

Data

The remaining members of the array are data that provide any additional return values (on success) or failure information (on failure).

In the latter case, to support internationalization, ruleset-defined responses will likely contain tokens. In this case, the flag prompts the client to pass the flag itself, and all its data, to the UI file's localize() function.


Old stuff follows... will move or delete if the protocol defined above is generally accepted.

The "rpc_requests.html" class=wikipagelink>RPC requests all define their own reply values and fault codes.

The "game." namespace is more of a problem, since the semantics are all game-specific. The game developer has to decide all the argument types, reply values, and fault codes.

My (Zarf's) thesis is that Jabber-RPC fault codes are not rich enough to be used for game-specific error messages. A fault contains an integer code and a string. (See the XML-RPC spec.) Integers are a headache for everybody (player, UI file author, referee author) because you have to keep looking them up. Strings make good programming identifiers ("ENOTYOURMOVE", etc), but can't be presented to the user in the common case, because of i18n issues.

I figure we can use RPC faults to indicate bugs -- situations which a player will not see, if he's playing a well-written game with a well-written UI. We should not recommend using RPC faults to reject bad player moves. Instead, the referee should reject an illegal move by sending back either

Either way, the referee can include arbitrary information, instead of being limited to integer-and-one-string.

We can get away with a short (fixed!) list of RPC faults, because there aren't that many things that can go wrong with client-ref communication. The client's normal behavior for all of these would be to display a technical error message, including the RPC name and arguments that triggered the error. The player would then report it to the game developer. (Or, getting fancier, the game developer could scan referee logs for errors.)

(In all cases, an informational string can accompany the code. It doesn't have to be internationalized, because it's a message to the game developer, not the player.)

See RPC faults for said list.

"Identity rejected" means the caller isn't a player of this game. That would be tested by common Volity::Game code, not game-developer-written referee code.

"Call illegal in this game state" is a generic fallback for "illegal move" or "not your move". As I said, it's better if the referee sends a game-specific RPC response or method for these situations. But it's still worth having the fault code, as a fallback.

External links

[JEP-0086: Error Condition Mappings]