| | |
- zymb.jabber.rpc.MethodOpset(zymb.jabber.rpc.Opset)
-
- RefAdminOpset
- RefVolityOpset
- Player
- Validator
- volity.volent.VolEntity(zymb.sched.Agent)
-
- Referee
- zymb.jabber.rpc.WrapperOpset(zymb.jabber.rpc.Opset)
-
- WrapGameOpset
class Player |
| |
Player: Represents a player at a table.
A player is identified by a full JID (including resource string).
During setup (and suspension), the referee only tracks players who are
actually present at the table; if a player becomes unavailable, his
Player object is removed. However, while the game is in progress,
the referee tracks everyone who is supposed to be seated at the table.
(Unavailable players remain in the Players list, so that they can be
recognized should they return.)
Player(ref, jid, nick, isbot=False) -- constructor.
The *ref* is the Referee which created this Player. The *jid* is the
player's (real) JID; *nick* is his MUC nickname (the resource part only).
The *isbot* flag indicates whether the player is known to be a robot.
Public methods:
send() -- send an RPC to this player.
Publicly-readable fields:
jid -- the player's real JID, as a JID object.
jidstr -- the player's real JID, as a string.
nick -- the MUC nickname (resource part only).
isbot -- is this player a robot?
live -- is this player available at the table?
aware -- is the player's client capable of receiving RPCs?
seat -- the Seat the player is sitting in, or None.
ready -- is the player "ready"? (Can only be True if seated.) |
| |
Methods defined here:
- __init__(self, ref, jid, nick, isbot=False)
- __str__(self)
- __unicode__(self)
- send(self, methname, *args, **keywords)
- send(methname, *args, **keywords)
Send an RPC to this player. See the description of the sendplayer()
method in the game.Game class.
|
class RefAdminOpset(zymb.jabber.rpc.MethodOpset) |
| |
RefAdminOpset: The Opset which responds to admin.* namespace
RPCs.
RefAdminOpset(ref) -- constructor.
The *ref* is the Referee to which this Opset is attached.
Methods:
precondition() -- checks authorization before an RPC handler.
Handler methods:
rpc_status() -- return assorted status information.
rpc_players() -- return a list of player JIDs at the table.
rpc_bots() -- return a list of bot JIDs at the table.
rpc_seats() -- return the list of seats; also the sublists of required
seats, occupied seats, and (if the game is in progress) the seats
involved in the current game.
rpc_seat -- return details about a seat and who is sitting there.
rpc_announce() -- yell a message to the table.
rpc_shutdown() -- immediately shut down this Referee and its table. |
| |
- Method resolution order:
- RefAdminOpset
- zymb.jabber.rpc.MethodOpset
- zymb.jabber.rpc.Opset
Methods defined here:
- __init__(self, ref)
- precondition(self, sender, namehead, nametail, *callargs)
- precondition(sender, namehead, nametail, *callargs)
Checks authorization before an RPC handler. Only the admin JID
is permitted to send admin.* namespace RPCs. If no admin JID was
set, then all admin.* RPCs are rejected.
- rpc_announce(self, sender, *args)
- rpc_announce(msg) -> str
Yell a message on the table. The message is broadcast as an ordinary
group-chat message, so all connected clients will see it.
Returns a message saying that the message was sent.
- rpc_bots(self, sender, *args)
- rpc_bots() -> list
Return a list of the (real) JIDs of all bots at this table.
- rpc_players(self, sender, *args)
- rpc_players() -> list
Return a list of the (real) JIDs of all players at this table
(including bots).
- rpc_seat(self, sender, *args)
- rpc_seat(seatid) -> dict
Return information about the seat *seatid*. This returns a Jabber-RPC
struct containing these fields:
id: The seat ID.
required: Whether this is a required seat.
ingame: Whether this seat is involved in the current game.
players: A list of the players currently in this seat.
history: A list of the players who have sat in this seat at any
time in the current game.
- rpc_seats(self, sender, *args)
- rpc_seats() -> dict
This returns a Jabber-RPC struct containing these fields:
allseats: The IDs of all seats in the game configuration.
reqseats: The IDs of all required seats.
occupiedseats: The IDs of all occupied seats.
gameseats: The IDs of all seats involved in the current game.
(Only present if a game is in progress.)
- rpc_shutdown(self, sender, *args)
- rpc_shutdown() -> str
Immediately shut down this Referee and its table. This kills the game
if it is in progress, so use it considerately.
- rpc_status(self, sender, *args)
- rpc_status() -> dict
Return assorted status information. This returns a Jabber-RPC struct
containing these fields:
agentstate: The Zymb agent state ("running" is normal operation).
state: The Volity referee state ("setup", "active", "disrupted",
"abandoned", "suspended").
players: The number of players (including bots).
bots: The number of bots.
startup_time: When this table was started.
startup_at: How long it's been since the table was started.
last_activity_at: How long it's been since there was any activity
at the table.
games_completed: How many games have been completed at the table.
Methods inherited from zymb.jabber.rpc.MethodOpset:
- __call__(self, sender, callname, *callargs)
- __call__(sender, callname, *callargs) -> value
Accept, parse, and handle a call. The *sender* is a JID object.
The *callname* is the method name (or fraction of a name, if
the opset is nested inside another opset which parsed the
namespace). The *callargs* are the RPC arguments, in the form
of Python objects (ints, strings, etc).
This method looks for an instance method named 'rpc_'+*callname*.
It invokes this (after calling
precondition(sender, callname, '', *callargs). The third argument
is empty because, in a MethodOpset, there is no more of the
callname to be matched after the method lookup.)
|
class RefVolityOpset(zymb.jabber.rpc.MethodOpset) |
| |
RefVolityOpset: The Opset which responds to volity.* namespace
RPCs.
RefVolityOpset(ref) -- constructor.
The *ref* is the Referee to which this Opset is attached.
Methods:
precondition() -- checks authorization and argument types before an
RPC handler.
Handler methods:
rpc_sit() -- handle a player sit request.
rpc_stand() -- handle a player stand request.
rpc_ready() -- handle a player ready request.
rpc_unready() -- handle a player unready request.
rpc_add_bot() -- handle a player request for a new bot.
rpc_remove_bot() -- handle a player request to remove a bot.
rpc_suspend_game() -- handle a player game-suspend request.
rpc_set_language() -- handle a player request to change the table language.
rpc_record_games() -- handle a player request to change the game-record
flag.
rpc_show_table() -- handle a player request to change the show-table flag.
rpc_kill_game() -- handle a player request to change the kill-game flag.
rpc_send_state() -- handle a player request for the complete table state.
rpc_invite_player() -- handle a player request to invite another player to
the table. |
| |
- Method resolution order:
- RefVolityOpset
- zymb.jabber.rpc.MethodOpset
- zymb.jabber.rpc.Opset
Methods defined here:
- __init__(self, ref)
- precondition(self, sender, namehead, nametail, *callargs)
- precondition(sender, namehead, nametail, *callargs)
Checks authorization and argument types before an RPC handler.
Only players at the table are permitted to send RPCs. We also use
Validators to check the number and type of the RPC arguments.
- rpc_add_bot(self, sender, *args)
- rpc_invite_player(self, sender, *args)
- rpc_kill_game(self, sender, *args)
- rpc_ready(self, sender, *args)
- rpc_record_games(self, sender, *args)
- rpc_remove_bot(self, sender, *args)
- rpc_send_state(self, sender, *args)
- rpc_set_language(self, sender, *args)
- rpc_show_table(self, sender, *args)
- rpc_sit(self, sender, *args)
- rpc_stand(self, sender, *args)
- rpc_suspend_game(self, sender, *args)
- rpc_unready(self, sender, *args)
Methods inherited from zymb.jabber.rpc.MethodOpset:
- __call__(self, sender, callname, *callargs)
- __call__(sender, callname, *callargs) -> value
Accept, parse, and handle a call. The *sender* is a JID object.
The *callname* is the method name (or fraction of a name, if
the opset is nested inside another opset which parsed the
namespace). The *callargs* are the RPC arguments, in the form
of Python objects (ints, strings, etc).
This method looks for an instance method named 'rpc_'+*callname*.
It invokes this (after calling
precondition(sender, callname, '', *callargs). The third argument
is empty because, in a MethodOpset, there is no more of the
callname to be matched after the method lookup.)
|
class Referee(volity.volent.VolEntity) |
| |
Referee: The implementation of a Volity referee.
A Referee is dedicated to running a particular kind of game. However,
there is no game-specific code in Referee (nor is it subclassed for
a particular game). Instead, the game-specific code is in a subclass
of the Game class. The game implementor creates this class; the Parlor
loads its module; and the Referee instantiates it (at constructor time).
The Game subclass handles all game.* RPCs, and provides assorted other
methods which the Referee calls to decide what to do.
Referee is a Jabber client (although it is not a subclass of the
Zymb Jabber client agent; instead, it creates one as a subsidiary
object). It is created by a Parlor when someone requests a new game
table. The Referee is responsible for managing one game table, at which
a bunch of players play one game. Or rather, a sequence of games. (When
a game finishes, the players have the option of setting up a new one at
the same table.)
Referee(parlor, jid, password, resource, muc) -- constructor.
All of the constructor arguments are passed in from the Parlor. First
is the parlor itself. The *jid*, *password*, and *resource* are used
to connect to the Jabber server. (The Referee connects with the same
parameters as the original Parlor, except for the *resource* string,
which is unique for each Referee.) The *muc* is the JID of the Jabber
Multi-User Chat room (which the Referee is responsible for creating).
Agent states and events:
state 'start': Initial state. Start up the Jabber connection process.
When Jabber is fully connected, jump to 'ready'.
state 'ready': Send out initial presence. Do a disco query of the MUC
host, to see if it's up. Request the creation of the MUC room,
and then jump to 'configuring'.
state 'configuring': Complete the MUC configuration process. Jump to
'running'.
state 'running': At this point the Referee is considered to be complete.
It begins watching for game activity.
state 'end': The connection is closed.
Public methods:
start() -- begin activity. (inherited)
stop() -- stop activity. (inherited)
Significant fields:
jid -- the JID by which this Referee is connected.
conn -- the Jabber client agent.
parlor -- the Parlor which created this Referee.
game -- the Game object.
refstate -- the referee state (STATE_SETUP, etc).
players -- dict mapping players' real JIDs to Player objects.
playernicks -- dict mapping players' MUC nicknames to Player objects.
seats -- dict mapping seat IDs to Seat objects.
seatlist -- list of Seat objects in the game's order.
gameseatlist -- during a game, the list of Seats involved in the game.
(A subset of seatlist.)
Internal methods:
addseat() -- add a seat to the game's permanent list.
setseatsrequired() -- mark certain seats as required or optional.
sendone() -- send an RPC to a single player.
sendall() -- send an RPC to all players at the table.
sendbookkeeper() -- send an RPC to the Volity bookkeeper.
defaultcallback() -- generic RPC callback, used to catch errors.
handlemessage() -- handle a Jabber message stanza.
handlepresence() -- handle a Jabber presence stanza.
handlemucpresence() -- handle a Jabber MUC presence stanza.
beginwork() -- 'ready' state handler.
gotquerymuc() -- disco query callback.
configuremuc() -- begin the configuration of a MUC room.
handle_stanza_configuremuc() -- MUC configuration callback.
buildconfigmuc() -- construct a form to configure a MUC room.
handle_stanza_configuremucresult() -- second MUC configuration callback.
checktimersetting() -- check whether the Referee needs a state timer.
settimer() -- set a state timer.
deadconfigtimer() -- abandoned-in-configuration timer callback.
abandonedtimer() -- abandoned-during-game timer callback.
playerarrived() -- handle a player joining the table.
playerleft() -- handle a player leaving the table.
playersit() -- handle a player sit request.
playerstand() -- handle a player stand request.
playerready() -- handle a player ready request.
playerunready() -- handle a player unready request.
playeraddbot() -- handle a player request for a new bot.
playerremovebot() -- handle a player request to remove a bot.
botready() -- callback invoked when a bot is successfully
(or unsuccessfully) created.
playersuspend() -- handle a player game-suspend request.
playerinvite() -- handle a player request to invite another player to the
table.
gotinvitereply() -- callback invoked when an invitation is replied to.
playerinvitecont() -- callback which replies to the original invite
request.
configsetlanguage() -- handle a player request to change the table
language.
configrecordgames() -- handle a player request to change the game-record
flag.
configshowtable() -- handle a player request to change the show-table
flag.
configkillgame() -- handle a player request to change the kill-game flag.
unreadyall() -- mark all players as unready.
sendfullstate() -- send the complete table state to a player.
reportsit() -- report a player sitting.
reportstand() -- report a player standing.
reportreadiness() -- report a player changing readiness.
reportunreadylist() -- report several players becoming unready.
announce() -- yell a message to everyone at the table.
updatediscoinfo() -- update and return the disco-info form.
parsewinners() -- turn a list of game seats (in winning order) into
a standardized winners list (a list of lists of lists of players).
begingame() -- game-start handler.
endgame() -- game-end handler.
suspendgame() -- game-suspend handler.
unsuspendgame() -- game-resume handler.
endwork() -- 'end' state handler.
Static methods:
resolvemetharg() -- convert some Volity objects into Jabber-RPC types. |
| |
- Method resolution order:
- Referee
- volity.volent.VolEntity
- zymb.sched.Agent
Methods defined here:
- __init__(self, parlor, jid, password, resource, muc)
- abandonedtimer(self)
- abandonedtimer() -> None
Abandoned-during-game timer callback. This suspends the game.
- addseat(self, seat)
- addseat(seat) -> None
Add a seat to the game's permanent list. This can only be done
during the Game constructor.
- announce(self, data)
- announce(data) -> None
Yell a message to everyone at the table. The *data* string is sent
as a group-chat message in the MUC room. (This method is used by
adminstrative commands, not by players or the referee.)
- begingame(self)
- begingame() -> None
Game-start handler. Sets up all the internal state which we will
use to track the game. (Game-specific setup is handled by the
game's begingame() method.)
This creates the gameseatlist, which is the list of seats that are
involved in this particular game. It also adds the current seated
players to each seat's history -- the list which will be used when
creating the game record.
- beginwork(self)
- beginwork() -> None
The 'ready' state handler. Send out initial presence. Do a disco
query of the MUC host, to see if it's up.
- botready(self, act, res)
- botready(act, res) -> <RPC outcome>
Callback invoked when an Actor is successfully (or unsuccessfully)
created. This is the continuation of playeraddbot(). The *act* is
the Actor object that was created, and *res* is either 'running',
'end', or 'timeout'.
- buildconfigmuc(self, origform)
- buildconfigmuc(origform) -> Node
Construct a form to configure a MUC room. The *origform* is an XML
Node object containing a JEP-0004 data form. This method returns
a new form which comes from filling the original form out.
We are really only interested in three fields: the room name,
the maximum number of users, and whether the room will be anonymous
(permit people to see each others' real JIDs). Unfortunately,
different MUC hosts use different names for these fields, so we
have to cover a lot of possibilities.
Fields which we don't care about keep their default values.
- checktimersetting(self)
- checktimersetting() -> None
Check whether the Referee needs a state timer. This is called after
any referee state change that might start or stop a timer. There
are two timers that might be running:
'deadconfig': Starts whenever there are no (human) players in
the MUC, in either 'setup' or 'suspended' state. After 90 seconds,
shuts down the MUC.
'abandoned': Starts whenever there are no seated (human) players
in the MUC, in the 'active', 'disrupted', or 'abandoned' state.
After 3 minutes, suspends the game.
This method determines which of the above should be running, and
calls settimer() with that string. If no timer should be running,
it calls settimer(None).
In the 'active', 'disrupted', or 'abandoned' states, this method also
decides whether the referee should jump to a different one of those
three states. The 'abandoned' timer is always associated with the
'abandoned' state; if the timer is not running, the referee might
be 'active' or 'disrupted'.
- configkillgame(self, sender, flag)
- configkillgame(sender, flag) -> None
Handle a player request to change the kill-game flag. The *sender*
is the player's JID; *flag* indicates whether the referee should
kill the game when it unsuspends.
- configrecordgames(self, sender, flag)
- configrecordgames(sender, flag) -> None
Handle a player request to change the game-record flag. The *sender*
is the player's JID; *flag* indicates whether to record games at
the bookkeeper.
- configsetlanguage(self, sender, lang)
- configsetlanguage(sender, lang) -> None
Handle a player request to change the table language. The *sender*
is the player's JID; *lang* is the language requested.
- configshowtable(self, sender, flag)
- configshowtable(sender, flag) -> None
Handle a player request to change the show-table flag. The *sender*
is the player's JID; *flag* indicates whether the parlor should
display this game.
- configuremuc(self)
- configuremuc() -> None
Begin the configuration of a MUC room. Send out the query stanza
which begins the process.
- deadconfigtimer(self)
- deadconfigtimer() -> None
Abandoned-in-configuration timer callback. This shuts down the
referee.
- defaultcallback(self, tup)
- defaultcallback(tup) -> None
Generic RPC callback, used to catch errors.
When an RPC completes (in any sense), the Zymb RPC-sending service
calls a completion routine. By default, it's this one. The callback
invokes sched.Deferred.extract(tup) on its *tup* argument to extract
the RPC outcome. This may return a value, or one of the following
exceptions might be raised:
TimeoutException: The RPC timed out.
RPCFault: The RPC response was an RPC fault.
StanzaError: The response was a Jabber stanza-level error.
Exception: Something else went wrong.
The defaultcallback() method logs all exceptions, ignores all normal
RPC responses, and that's all it does.
- endgame(self, winners, cancelled=False)
- endgame() -> None
Game-end handler. (Game-specific shutdown is handled by the game's
endgame() method.)
This creates and fires off the game record, if that's desired. It
also removes any Player objects corresponding to players who have
left the MUC. (Remember, we keep Player objects for unavailable
seated players, but only during of the game.)
- endwork(self)
- endwork() -> None
The 'end' state handler. This destroys the MUC room. Then, it does
its best to blow away all of the referee's member fields, so that
everything can be garbage-collected efficiently.
- gotinvitereply(self, tup, defer, jidstr)
- gotinvitereply(tup, defer, jidstr) -> None
Callback invoked when an invitation is replied to. The *tup* contains
the RPC result; the *defer* and *jidstr* are passed down from
playerinvite().
This just extracts the RPC result from *tup*, catching all the
possible things which could go wrong. Then it invokes the
playerinvitecont() callback.
(Yes, there's probably some way to combine gotinvitereply() and
playerinvitecont() into one function. Never bothered to work out
how.)
- gotquerymuc(self, tup)
- gotquerymuc(tup) -> None
Disco query callback. If the disco query failed, try again. (But
after three failures, give up and shut down the referee.) If the
query succeeds, send a command to create the new MUC room, and
jump to state 'configuring'.
- handle_stanza_configuremuc(self, msg)
- handle_stanza_configuremuc(msg) -> <stanza outcome>
MUC configuration callback. If the config query failed, shut down
the referee. If it succeeded, extract the MUC configuration form,
build a response form, and send it back.
- handle_stanza_configuremucresult(self, msg)
- handle_stanza_configuremucresult(msg) -> <stanza outcome>
Second MUC configuration callback. If our config form failed, shut
down the referee. If it succeeded, jump to state 'running'.
- handlemessage(self, msg)
- handlemessage(msg) -> <stanza outcome>
Handle a Jabber message stanza. The Referee does not react to messages,
so this just raises StanzaHandled to end processing for the stanza.
- handlemucpresence(self, typestr, resource, msg)
- handlemucpresence(typestr, resource, msg) -> None
Handle a Jabber MUC presence stanza. The *typestr* is the presence
type (with '' representing default "I'm here" presence). The
*resource* is the resource part of the MUC JID -- that is to say,
the MUC nick. The *msg* is the full presence stanza, which we
need for further analysis.
MUC presence is interesting in two cases. First, when the referee
is first creating the MUC, it watches for a status code 201, which
indicates that it's time to configure the new MUC room.
Second, as players join and leave the MUC room, the referee must
track them. It calls playerarrived() and playerleft() when it
detects these events.
- handlepresence(self, msg)
- handlepresence(msg) -> <stanza outcome>
Handle a Jabber presence stanza. If it comes from the referee's MUC
room, it is passed along to handlemucpresence(). Otherwise, it is
ignored.
- parsewinners(self, ls)
- parsewinners(ls) -> list
Turn a list of game seats (in winning order) into a standardized
winners list (a list of lists of lists of players). This is called
by the game-ending methods of Game. Since the *ls* comes from
game-specific code, we do lots of consistency-checking on it.
Each element of *ls* must be either a Seat object, or a list of
Seat objects. The latter indicates a tie at that position. Not
all Seats in the game have to be included; if any are missing,
they are tacked onto the end as a "tie for last place".
As a special case, if *ls* has the sole element None, then everybody
is considered to have tied.
- playeraddbot(self, sender)
- playeraddbot(sender) -> None
Handle a player request for a new bot. The *sender* is the player's
JID.
This creates an Actor, which is a Volity entity that connects to
the Jabber server and plays as a player would. (The Bot is the game-
specific "brain" inside the Actor, much as the Game object is the
game-specific part of the Referee.)
- playerarrived(self, jid, nick, isbot=False)
- playerarrived(jid, nick, isbot=False) -> None
Handle a player joining the table. His real JID is *jid*, his
room nickname is *nick*, and *isbot* flags whether we think he's
a bot.
This may be a player changing his MUC nickname; we detect that
by checking the real JID. Otherwise, it's someone genuinely joining.
If we're in the middle of a game, it might be a disconnected player
returning to his seat. If so, mark his Player object as live.
Otherwise, create a new Player object for the new player.
- playerinvite(self, sender, jidstr, msg=None)
- playerinvite(sender, jidstr, msg=None):
Handle a player request to invite another player to the table. The
*sender* is the player's JID; the *jidstr* is the recipient of the
invitation; and *msg* is an additional message from the inviter to
the invitee.
- playerinvitecont(self, jidstr, res, ex=None)
- playerinvitecont(jidstr, res, ex=None) -> <RPC outcome>
Callback which replies to the original invite request. The *jidstr*
is the JID we sent the invitation to; *res* describes whether the
invitation succeeded; and *ex* is the exception that caused the
problem, if there was a problem.
If the invitation succeeded, we just return cleanly to the original
invite RPC. If there was any problem, we return a 'relay_failed'
failure token, with *jidstr* in the spot.
- playerleft(self, jid, nick)
- playerleft(jid, nick) -> None
Handle a player leaving the table. His real jid is *jid*, his
room nickname is *nick.
If it's a seated player during a game, we keep the Player object.
(But we mark it non-live.) Otherwise, throw away the Player.
- playerready(self, sender)
- playerready(sender) -> None
Handle a player ready request. The *sender* is the player's JID.
This can trigger the beginning (or resumption) of a game, so we do
a lot of checking. If we're in 'setup' state, we ask the game whether
its state is legal, by calling checkconfig() and checkseating().
If we're in 'suspended', then we just have to check that all the
game's seats are occupied... unless the players have voted to
kill off the game, in which case we don't need to check anything.
Finally, if all seated players are ready, the game actually begins
(or resumes, or is killed).
- playerremovebot(self, sender, jidstr)
- playerremovebot(sender, jid) -> None
Handle a player request to remove a bot. The *sender* is the player's
JID. The *jid* is the bot's JID.
This only works on bots that were added by playeraddbot. It also
only works on unseated bots.
- playersit(self, sender, jidstr, seatid=None)
- playersit(sender, jidstr, seatid=None) -> str
Handle a player sit request. The *sender* is the JID which made the
request; *jidstr* is the player the request is about. This returns
the ID of the seat which the player actually winds up in.
If *seatid* is None, the referee gets to choose a seat. We call
the game's requestanyseat() method (or requestanyseatingame() if
the game is in progress). By default, these methods pick the first
empty seat, preferring required seats over optional ones. However,
the game may have a better scheme.
If *seatid* is not None, the request is for a particular seat. We
let the game vet that, by calling its requestparticularseat()
method. By default, the request is permitted.
- playerstand(self, sender, jidstr)
- playerstand(sender, jidstr) -> None
Handle a player stand request. The *sender* is the JID which made the
request; *jidstr* is the player the request is about.
- playersuspend(self, sender=None)
- playersuspend(sender=None) -> None
Handle a player game-suspend request. The *sender* is the player's
JID.
It's also possible that the game was suspended by the referee, due
to the 'abandoned' timer. In that case, *sender* will be None.
- playerunready(self, sender)
- playerunready(sender) -> None
Handle a player unready request. The *sender* is the player's JID.
- reportreadiness(self, player)
- reportreadiness(player) -> None
Report a player changing readiness. The *player*'s current state
determines whether this sends a player_ready() or player_unready()
RPC.
- reportsit(self, player, seat)
- reportsit(player, seat) -> None
Report a player sitting. The *player* has sat in Seat *seat*.
- reportstand(self, player, seat)
- reportstand(player, seat) -> None
Report a player standing. The *player* has stood from Seat *seat*.
- reportunreadylist(self, ls)
- reportunreadylist(ls) -> None
Report several players becoming unready. The *ls* is a list of
Players.
- sendall(self, methname, *methargs, **keywords)
- sendall(methname, *methargs, **keywords) -> None
Send an RPC to all players at the table.
The *methname* and *methargs* describe the RPC. The *keywords* may
contain either or both of:
timeout: How long to wait (in seconds) before considering the
RPC to have failed.
callback: A deferral callback to invoke when the outcome of
the RPC is known. See the defaultcallback() method for an
example of the callback model.
- sendbookkeeper(self, methname, *methargs, **keywords)
- sendbookkeeper(methname, *methargs, **keywords) -> None
Send an RPC to the Volity bookkeeper.
The *methname* and *methargs* describe the RPC. The *keywords* may
contain either or both of:
timeout: How long to wait (in seconds) before considering the
RPC to have failed.
callback: A deferral callback to invoke when the outcome of
the RPC is known. See the defaultcallback() method for an
example of the callback model.
- sendfullstate(self, player)
- sendfullstate(player) -> None
Send the complete table state to a player. The argument is a
Player object. This also serves as notice that the Player is
ready to receive RPCs, so we mark it aware.
This includes seating information, table configuration, and the
state of the game (if in progress). And it's all wrapped in a
receive_state() / state_sent() pair, so the client knows when the
burst is over.
- sendone(self, player, methname, *methargs, **keywords)
- sendone(player, methname, *methargs, **keywords) -> None
Send an RPC to a single player.
The *player* is the Player object to send to. The *methname* and
*methargs* describe the RPC. The *keywords* may contain either or
both of:
timeout: How long to wait (in seconds) before considering the
RPC to have failed.
callback: A deferral callback to invoke when the outcome of
the RPC is known. See the defaultcallback() method for an
example of the callback model.
- setseatsrequired(self, setseats=[], clearseats=[])
- setseatsrequired(setseats=[], clearseats=[]) -> None
Mark certain seats as required or optional. The seats listed in
*setseats* become required; the ones listed in *clearseats* become
optional. If this results in any seats actually changing state,
required_seat_list RPCs are sent.
- settimer(self, reason)
- settimer(reason) -> None
Set a state timer. The *reason* is 'deadconfig', 'abandoned', or
None (for no timer). If the given timer is already set (or not set),
this does nothing.
- suspendgame(self, jidstr=None)
- suspendgame() -> None
Game-suspension handler. (Game-specific work is handled by the
game's suspendgame() method.)
This removes any Player objects corresponding to players who have
left the MUC. (Remember, we keep Player objects for unavailable
seated players, but only during of the game.)
- unreadyall(self, notify=True)
- unreadyall(notify=True) -> None
Mark all players as unready. If *notify* is True, this sends
out unready() RPCs for all players who changed state. If False,
there is no notification.
(The False form of this method is used when handling RPCs that
are documented as automatically unreadying all players. (Sit, stand,
and so on.) The client is required to know about this automatic
unreadying, so there's no need for us to send out notices about
it.)
- unsuspendgame(self)
- unsuspendgame() -> None
Game-resumption handler. (Game-specific work is handled by the
game's unsuspendgame() method.)
This does not modify gameseatlist, but it does add the current
seated players to each seat's history.
- updatediscoinfo(self)
- updatediscoinfo() -> DiscoInfo
Update and return the disco-info form. We keep a DiscoInfo object
lying around, but before we can send it, we have to update some
fields to represent the current referee state. This method does
that.
Static methods defined here:
- resolvemetharg(val, gameresolve=None)
- resolvemetharg(val) -> val
Convert some Volity objects into Jabber-RPC types. This is called
on all RPC arguments before they are sent out.
If *gameresolve* is not None, it is invoked on the value (and on each
member of list and tuple values). If it returns non-None, then that
is the conversion.
Otherwise, a Seat object is converted to a string (the seat ID).
A Player object is converted to a string (the player's real JID).
All other types are left alone.
Data and other attributes defined here:
- logprefix = 'volity.referee'
- maxmucusers = 60
- volityrole = 'referee'
Methods inherited from volity.volent.VolEntity:
- authed(self)
- authed() -- handler for Jabber client 'authresource' state.
The Jabber client has finished connecting. Jump to 'ready'.
- cappresencehook(self, msg)
- cappresencehook() -- callback for presence stanza generation.
This hook is called whenever we generate a presence stanza. It adds
a JEP-0115 Entity Capabilities tag to the stanza.
- finalize(self)
- finalize() -- 'end' state handler.
Shut down the Jabber client agent.
- rpcnotfound(self, msg, callname, callargs)
- rpcnotfound() -- callback for RPC method-not-found case.
When an RPC arrives that we do not recognize, we want to respond
with an RPC fault. (As opposed to the default behavior, which is
an <item-not-found> stanza error.)
- startpresence(self)
- startpresence() -- 'ready' state handler.
Send out initial presence.
- startup(self)
- startup() -- 'start' state handler.
Start the Jabber client agent, and then wait for it to finish
connecting.
Static methods inherited from volity.volent.VolEntity:
- uniquestamp()
- uniquestamp() -> int
Generate a number which is unique within this process. It is
approximately a Unix timestamp, but incremented when necessary
to avoid repeats.
Data and other attributes inherited from volity.volent.VolEntity:
- laststamp = 0
Methods inherited from zymb.sched.Agent:
- __str__(self)
- addcleanupaction(self, ac)
- addcleanupaction(action) -> None
Add *action* to the list of actions to be removed when the agent
stops (i.e., jumps to the 'end' state).
This is intended for actions that an agent adds as handlers to
other agents. For example:
ac = otheragent.addhandler('event', self.foreigneventhandler)
# Ensure that ac is removed when *self* shuts down.
addcleanupaction(ac)
You do not need to list pollers or socket-checkers as cleanup
actions. Nor do you need to list handlers that an agent adds
to itself. (All these are automatically removed when the agent
shuts down.) You also don't have to worry about the case of
*otheragent* shutting down; when that happens, all handlers added
to it are removed.
- addhandler(self, state, op, *args)
- addhandler(eventname, op, *args) -> action
Add a state or event handler. The *eventname* is a string naming
the state or event you want to handle. The *op* and *args* are
the operation to perform when that state or event occurs.
(See queueaction() for the use of *op* and *args*.)
Handlers are invoked in last-added-first-run order. If an agent
has a built-in handler, it is added first, so it runs last. Handlers
that you add on later run earlier.
Returns the Action. (You can cancel the handler by calling
ac.remove().)
- addtimer(self, op, *args, **dic)
- addtimer(op, *args, delay=num, when=num, periodic=bool) -> action
Add a timed event. You must supply exactly one of the keyword
arguments *delay* and *when*. A *when* is an absolute time,
expressed as a number of seconds since the epoch (e.g., the kind
of value returned by time.time()). A *delay* is a relative time,
expressed as a number of seconds in the future.
It is legal to give a time in the past (or a negative *delay*).
In that case, this is similar to queueaction() -- the operation
will occur very soon. (Although it's still a "low priority"
action.)
If you supply *periodic*=True, the event will occur repeatedly,
every *delay* seconds. (The interval is inferred if you give
*when*.) In this case, you may NOT give a negative *delay* or
a time in the past -- it is meaningless for a periodic event to
have a period less than or equal to zero.
You can also create a periodic timer by calling addtimer with
a PeriodicAction, which is a subclass of Action. This is slightly
more flexible; the interval between calls is specified when
you create the PeriodicAction, but the delay before the first
call may be specified with *delay* or *when*.
See queueaction() for the use of *op* and *args*.
Returns the Action. (You can cancel the timer by calling
ac.remove().)
- basicerror(self, exc, agent)
- basicerror(exc, agent) -> None
A simple event handler for 'error'. This simply writes the
received data to stdout:
sys.stdout.write('Error: ' + str(agent) + ': ' + str(exc) + '
')
This handler is not installed by default. You can enable it by
calling:
ag.addhandler('error', ag.basicerror)
- jump(self, st, *exargs)
- jump(state, *args) -> None
Jump to a different operating state. (If the agent is already
in the given state, nothing happens.)
This queues up all the state transition handlers registered
for the new state. If you provide *args*, they are passed to the
handlers when they are called.
- perform(self, name, *exargs)
- perform(eventname, *args) -> None
Trigger an event.
This queues up all the event handlers registered for the given
event. If you provide *args*, they are passed to the handlers when
they are called.
- queueaction(self, op, *args)
- queueaction(op, *args) -> action
Invoke an action. The action will be handed to the scheduler, which
will run it very soon.
("Very soon" means "before the next timed event or network message
is handled." However, if you queue several actions, they will be
handled in the order you queued them.)
You can pass any callable as *op*; the (optional) *args* will be
passed to it as arguments. You can also, if you like, create
an Action object and pass it as *op*. You can still pass *args*
in this case; they'll be appended to the arguments bound into
the Action.
Returns the Action.
- registerpoll(self, op, *args, **dic)
- registerpoll(op, *args, interval=num) -> action
Add a repeating activity check. *interval* is a (mandatory) keyword
argument; the scheduler will invoke your operation at least every
*interval* seconds. (And at least once per sched.process() call.)
See queueaction() for the use of *op* and *args*. Your operation
should not do any work except for absorbing input and queueing
actions. Typically, it will collect the input and then call
perform(), triggering an event, so that the agent's event
handlers can do something with the input.
Returns the Action. (You can cancel it by calling ac.remove().)
- registersocket(self, fileno, op, *args)
- registersocket(socket, op, *args) -> action
Add a socket-based activity check. The *socket* may be a socket
object, or a number representing a fileno, or any object which
provides a fileno() method.
See queueaction() for the use of *op* and *args*. Your operation
should not do any work except for absorbing input and queueing
actions. Typically, it will collect the input and then call
perform(), triggering an event, so that the agent's event
handlers can do something with the input.
Returns the Action. (You can cancel it by calling ac.remove().)
- shutdown(self)
- shutdown() -- internal 'end' state handler. Do not call.
This is the final 'end' handler. It removes the agent from the
scheduler, and cancels all its remaining actions, timed events,
etc.
- start(self)
- start() -> None
Begin activity. The agent adds itself to the scheduler and moves
to the 'start' state. It does not actually begin doing work in
this call; that happens the next time the scheduler is invoked
(sched.process).
You should only call this once per agent.
- stop(self)
- stop() -> None
Stop activity. The agent moves to the 'end' state. Its 'end'
state handlers will take care of shutting it down and removing
it from the scheduler.
It is safe to call this on an agent which is already in 'end',
or which is completely shut down. (Nothing further will happen.)
(Remember, state handlers are not called as part of the stop()
method. They are run by the scheduler "soon" after stop() is
called. If you want to be sure the agent is completely stopped,
you can check the agent.live field. However, it is better to
register your own 'end' state handler, and consider the agent
stopped when that it called.)
Data and other attributes inherited from zymb.sched.Agent:
- agentcounter = 1
- hidden = False
|
class Validator |
| |
Validator: Represents a set of argument-type restrictions on a
Jabber RPC call.
Various parts of the Volity system accept RPCs. Most of them want to
check the number and type of the RPC arguments, and return appropriate
RPC faults if the arguments are wrong. However, type-checking code is
prolix and tedious. This class allows an RPC opset to check the arguments
easily.
A Validator also allows you to check other Volity state conditions. For
example, you can set a Validator to reject its RPC while the game is
in progress.
By default, a Validator is completely permissive. You set the conditions
that it checks by specifying a mapping of keywords to values. You may
set these either when the Validator is constructed, or afterwards (using
the set() method).
These are the keywords which Validators understand:
state=*str*
Require the referee to be in a particular state. The state
may be one of 'setup', 'active', 'disrupted', 'suspended',
'abandoned'. Or, it may contain several of those values,
as a space-delimited string.
afoot=*bool*
If the value is True, this requires the referee to be 'active',
'disrupted', or 'abandoned'. If False, it requires the referee
to be in 'setup' or 'suspended'.
seated=*bool*
Requires the sending player to be seated (if True) or standing
(if False).
admin=*bool*
If True, requires the sending player to be a parlor administrator.
argcount=*int*
Require the given number of arguments.
args=*typespec*
Specify the number and type of arguments. This is complicated,
so we will explain it by example.
args=None: Require there to be no arguments. (This is equivalent
to argcount=0.)
args=int: Exactly one argument, of type integer.
args=str: Exactly one argument, of type string.
args=bool: Exactly one argument, of type boolean.
args=float: Exactly one argument, of type float or integer.
args=list: Exactly one argument, of type list (array).
args=dict: Exactly one argument, of type dict (struct).
args=[int, int]: Exactly two arguments, both integers.
args=[int, str]: Exactly two arguments; the first an integer, the
second a string.
args=(int, str): Exactly one argument, which may be either an int
or a string.
args=[str, (int, str)]: Exactly two arguments. The first must be
a string; the second may be an integer or a string.
args=(int, None): One optional argument; if present, must be
an integer.
args=[str, (int, None)]: Either one or two arguments. The first
must be a string. The second, if present, must an an integer.
args=[int, '...']: One or more arguments. The first must be an
integer. The following arguments are not checked.
For the purposes of validation, unicode arguments count as strings.
Integers are accepted as floats. The RPC 'base64' type appears
as a string. The RPC 'dateTime.iso8601' is not recognized by
this class.
You may use the Python built-in object Ellipsis instead of the
literal '...'.
If you set contradictory conditions, the resulting behavior is poorly
defined. For example, if you set state='setup' and then set afoot=True,
the Validator may ignore one condition; or it may try to verify both,
and therefore reject all RPCs. Similarly, setting args=None and
argcount=1 would cause problems.
Validator(**keywords) -- constructor.
Create a Validator with the given conditions. You might say, for example:
val = Validator(argcount=2, afoot=False)
Public methods:
set() -- set more conditions.
check() -- check the validity of an RPC call.
Static method:
typespecstring() -- turn one or more types into a human-readable string. |
| |
Methods defined here:
- __init__(self, **keywords)
- check(self, ref, sender, callname, callargs)
- check(ref, sender, callname, callargs) -> None
Checks the validity of an RPC invocation. The *ref* is the referee
which received the RPC; the *sender* is the JID which sent the
RPC; *callname* and *callargs* describe the RPC invocation.
If a problem is detected, this method generates either a Volity
failure token or an RPC fault. If the invocation is valid, this
simply returns.
(Note that no conditions check the *callname*, since this is the
Validator for that callname. It is used only to generate readable
RPC faults.)
- set(self, arg_=None, **keywords)
- set(arg_=None, **keywords) -> None
Set more conditions. You have several options for setting keyword-
value pairs:
validator.set( argcount=2 )
validator.set( {'argcount': 2} )
validator.set( [ ('argcount' , 2) ] )
validator.set(val) # *val* is anything which can be cast to a dict
See the class documentation for the list of keywords.
If you call this multiple times, or call it on a Validator which
was constructed with conditions, then the conditions accumulate.
(But see the class documentation for warnings about contradictory
conditions.)
Static methods defined here:
- typespecstring(typ)
- typespecstring(typ) -> str
Turn a type, or a tuple of types, into a human-readable string.
The *typ* must be a Python type object (str, int, or so forth),
or else a tuple of type objects. The result is a string of the
form 'string or int or ...'
|
class WrapGameOpset(zymb.jabber.rpc.WrapperOpset) |
| |
WrapGameOpset: An Opset which wraps all RPCs in the game.* namespace.
This Opset provides checking of argument types. It also checks a few
other universal conditions: you cannot send RPCs before the referee is
ready, and you cannot send RPCs unless you are present at the table.
WrapGameOpset(ref, subopset)
Public methods:
setopset() -- change the contained opset. (inherited)
validation() -- define argument-type checking for an RPC.
precondition() -- checks authorization and argument types before an
RPC handler.
__call__() -- invoke an RPC. |
| |
- Method resolution order:
- WrapGameOpset
- zymb.jabber.rpc.WrapperOpset
- zymb.jabber.rpc.Opset
Methods defined here:
- __call__(self, sender, callname, *callargs)
- __call__(sender, callname, *callargs) -> <rpc outcome>
Invoke an RPC. This is invoked by the Zymb RPC-handling service.
- __init__(self, ref, subopset)
- precondition(self, sender, namehead, nametail, *callargs)
- precondition(sender, namehead, nametail, *callargs)
Checks authorization and argument types before an RPC handler.
Only players at the table are permitted to send RPCs. We also use
Validators to check the number and type of the RPC arguments.
- validation(self, callname, **keywords)
- validation(callname, **keywords) -> None
Define argument-type checking for an RPC. The *callname* is the
name part of the RPC (that is, excluding the namespace). For the
possible *keywords*, see the Validator class.
If you call this multiple times for the same RPC, the keywords are
accumulated.
Methods inherited from zymb.jabber.rpc.WrapperOpset:
- getopset(self)
- getopset() -> Opset
Retrieve the contained opset.
- setopset(self, subopset)
- setopset(subopset) -> None
Change the contained opset.
| |