diff options
Diffstat (limited to 'appl/spree/man/gamesrv.man2')
| -rw-r--r-- | appl/spree/man/gamesrv.man2 | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/appl/spree/man/gamesrv.man2 b/appl/spree/man/gamesrv.man2 new file mode 100644 index 00000000..fd910519 --- /dev/null +++ b/appl/spree/man/gamesrv.man2 @@ -0,0 +1,471 @@ +.TH GAMESRV 2 +.SH NAME +Gamesrv \- game server module +.SH SYNOPSIS +.EX +.ps -1 +.vs -1 +include "draw.m"; +include "gamesrv.m"; +gamesrv := load Gamesrv Gamesrv->PATH; +Range, Object, Game, Player: import gamesrv; + +Range: adt { + start: int; + end: int; +}; + +Object: adt { + transfer: fn(o: self ref Object, + r: Range, dst: ref Object, i: int); + setvisibility: fn(o: self ref Object, + visibility: int); + setattrvisibility: fn(o: self ref Object, + name: string, visibility: int); + setattr: fn(o: self ref Object, + name: string, val: string, vis: int); + getattr: fn(o: self ref Object, name: string): string; + delete: fn(o: self ref Object); + deletechildren: fn(o: self ref Object, r: Range); + + id: int; + parentid: int; + children: array of ref Object; + objtype: string; + visibility: int; + # ...private data + +}; + +Game: adt { + newobject: fn(game: self ref Game, parent: ref Object, + visibility: int, objtype: string): ref Object; + action: fn(game: self ref Game, cmd: string, + objs: list of int, rest: string, whoto: int); + player: fn(game: self ref Game, id: int): ref Player; + + objects: array of ref Object; + # ...private data +}; + +Player: adt { + name: fn(player: self ref Player): string; + hangup: fn(player: self ref Player); + obj: fn(player: self ref Player, id: int): ref Object; + + id: int; + # ...private data +}; + +Gamemodule: module { + clienttype: fn(): string; + init: fn(game: ref Gamesrv->Game, srvmod: Gamesrv): string; + command: fn(player: ref Gamesrv->Player, e: string): string; + join: fn(player: ref Gamesrv->Player): string; + leave: fn(player: ref Gamesrv->Player); +}; + +rand: fn(n: int): int; +.ps +1 +.vs +1 +.EE +.SH DESCRIPTION +.I Gamesrv +provides a general server interface that allows distributed +clients to interact in a controlled manner, with the +interaction mediated +by Limbo modules, known as +.IR "game engines" , +or just +.I engines +for short. +Each engine decides on the rules +of its particular game; the engine interface is described +at the end of this manual page, under +``Module Interface''. +.PP +This manual page describes the +interface as presented to an engine +once it has been loaded by +.IR gamesrv . +An engine is responsible for a particular +.IR game , +in which one or more +.I players +participate. Messages sent by players +are interpreted by the game engine, which +responds by making changes to the hierarchical +.I object +database held by the game. +Behind the scenes +.I gamesrv +distributes updates to this database to players +of the game as appropriate. +.SS "Objects and visibility" +Objects hold a game's visible state. An object +has a unique integer +.IR id , +which is an index into the array +.IB game .objects\fR;\fP +it also holds a set of attribute-value pairs, a type, and +zero or more child objects. Together, all the objects +in the game form a hierarchical tree, rooted at +the +.IR "root object" +(id 0), which always exists. +Each attribute and each object also has an associated +.IR "visibility set" , +the set of players that sees updates to the attribute or the children +of the object. A visibility set is an integer, a bitmask where each +bit represents one player, hence +.B ~0 +is visible to all players, and +.B 0 +is visible to no-one. +In general, each player has a unique +identifier +.IR id ; +in an integer +.I i +representing a set of players, +the +.IR id th +bit represents the presence of the player with +identifier +.IR id . +Thus, for a player +.IR p , +.BI "(1<<" p ".id)" +is the set containing only +.IR p , +.BI "(" i "&~(1<<" p ".id))" +excludes +.I p +from the set, and +.BI "(" i "|(1<<" p ".id))" +includes +.I p +in the set. +.PP +Note that the visibility set of an object does not alter the visibility +of that object's attributes, but only that of its children (and of +their children: in general an object is visible to a player if the +intersection of all its ancestors' visibility sets contains that +player). +.PP +Objects can be transferred inside the hierarchy from one parent to +another. If an object is moved to a parent whose visibility conceals it +from a player, then it will appear to that player to have been deleted; +if it is later made visible, then it will be recreated for that +player. +A game engine can almost always ignore this technicality, +except for one thing: the identifier used by a particular player to +identify an object is not necessarily the same as that used by the game +engine. Thus when an engine receives an object id in a player's +message, it should convert it using the +.IB player .obj() +function. +.SS \fBGame\fP +The +.B Game +type holds all the objects in a game. It allows the +creation of new objects, and provides way of communicating +with players outside the object hierarchy. +All data members of a +.B Game +should be treated as read-only. +.TP 10 +.IB game .objects +This array holds the objects in the game. An object with +identifier +.I id +is found at +.IB game .objects[ id ]\fR.\fP +.TP +.IB game .newobject(\fIparent\fP,\ \fIvisibility\fP,\ \fIobjtype\fP) +.B Newobject +creates a new object at the end +of +.IR parent 's +children; +If +.I parent +is nil, the new object is created under the root object. +The new object has visibility +.IR visibility , +and type +.IR objtype . +An object's type cannot be changed once +it has been created. +.TP +.IB game .action(\fIcmd\fP,\ \fIobjs\fP,\ \fIrest\fP,\ \fIwhoto\fP) +.B Action +sends a message to some players without affecting +the object hierarchy. It can be used to send transient +events that have no meaning when stored statically +(for example, network latency probes). +The message is sent to the set of players given by +.IR whoto . +.I Objs +is assumed to be a list of object ids, which are +converted appropriately for each player +receiving the message; the final +message is a string built by concatenating +.IR cmd , +the list of object ids, and +.IR rest , +separated by spaces. +.TP +.IB game .player(\fIid\fP) +.B Player +yields the player corresponding to identifier +.IR id , +or +.B nil +if there is none. +.SS Player +The +.B Player +type represents a player of a game. +.TP 10 +.IB player .id +The player's identifier, an integer between +0 and 31. This is unique across all current players, +but ids of players that have left the game will +be reused. +.TP +.IB player .obj(\fIid\fP) +.B Obj +converts from a player's external object +identifier to the game's local +.B Object +that it represents. It returns +.B nil +if there is no such object. +.TP +.IB player .hangup() +.B Hangup +hangs up a player's connection to the game; +no more requests from +.I player +will be received by the game engine. +.TP +.IB player .name() +.B Name +yields the authenticated name of the player. +This is not necessarily unique over the players +of a game. +.SS \fBObject\fP +The +.B Object +type is the basic unit of game engine state. +An object's children can be selectively concealed +from players; it holds a set of +.RI ( attribute ,\ value ) +pairs, each of which can be concealed likewise. +Where an argument +.IR r , +of +.B Range +type is used, it refers to a range of an object's +children starting at index +.IB r .start\fR,\fP +and finishing at +.IB r .end-1\fR.\fP +All the data members of an +.B Object +should be treated as read-only. +.TP 10 +.IB obj .setattr(\fIname\fP,\ \fIval\fP,\ \fIvis\fP) +.B Setattr +sets attribute +.I name +in +.I obj +to +.IR val. +If the attribute is being created for the +first time, then it will be given visibility +.IR vis . +.I Name +should be non-empty, and should not +contain any space characters. +Note that it is not possible for an attribute +to refer directly to an object by its identifier; +if this facility is needed, another identifying +scheme should be used. This also applies +to player identifiers, which will change +if the game is saved and loaded again (not +implemented yet). +.TP +.IB obj .getattr(\fIname\fP) +.B Getattr +yields the current value of the +attribute +.I name +in +.IR obj . +If an attribute is not set, it yields +.BR nil . +.TP +.IB obj .delete() +.B Delete +removes +.I obj +from the object +hierarchy. +.TP +.IB obj .deletechildren(\fIr\fP) +.B Deletechildren +deletes children in range +.I r +from +.IR obj . +.TP +.IB obj .transfer(\fIr\fP,\ \fIdst\fP,\ \fIi\fP) +.B Transfer +transfers the children in range +.I r +from +.I obj +to just before the object at index +.I i +in +.IR dst . +It is permissible for +.I obj +and +.I dst +to be the same object. +.TP +.IB obj .setvisibility(\fIvisibility\fP) +.B Setvisibility +allows the set of players +given in +.I visibility +to see the children of +.IR obj , +and denies access to all others. +Players are notified of the change. +.TP +.IB obj .setattrvisibility(\fIname\fP,\ \fIvisibility\fP) +.B Setattrvisibility +allows the set of players +given in +.I visibility +to see the value of +.IR obj 's +attribute +.IR name , +and denies access to all others. +Players are not notified of the change; +if there is a need to communicate +the fact of an attribute becoming invisible to +players, it should be done by using another +(visible) attribute to communicate the change. +.SS "Module Interface" +A game engine module, +.IR mod , +must implement the +following functions. Where a function returns a string, +it is interpreted as an error response to the player +responsible for the request; an empty string signifies +no error. +.TP +.IB mod .clienttype() +.B Clienttype +should return the type of client required +by the engine (e.g. +.B cards +for the card-game client). +Each client type has its own conventions +as to the meaning of object types and attribute +names and values. +This function may be called before +.BR init() . +.TP +.IB mod .init(\fIgame\fP,\ \fIsrvmod\fP) +.B Init +initialises the game engine. +.I Game +is the game that the engine is controlling, +and +.I srvmod +is the +.B Gamesrv +module holding its associated data. +An error response from this function +causes the game to be aborted. +.TP +.IB mod .join(\fIplayer\fP) +.I Player +has made a request to join the game; +an error response causes the request to be +refused, otherwise the player joins the +game. +.TP +.IB mod .leave(\fIplayer\fP) +.I Player +has left the game. +.TP +.IB mod .command(\fIplayer\fP,\ \fIe\fP) +.I Player +has sent the command +.IR e . +The command usually follows +the simple message conventions +used in +.IR gamesrv (4), +i.e. simple space-separated tokens. +.SH EXAMPLE +The following is a small, but working example +of a game engine that acts as a chat server +(parsing error checking omitted, and white-space +compressed to save paper): +.PP +.EX +.ps -1 +.vs -1 +implement Gamemodule; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "../gamesrv.m"; + gamesrv: Gamesrv; + Game, Player: import gamesrv; +game: ref Game; +clienttype(): string +{ + return "chat"; +} +init(g: ref Game, srvmod: Gamesrv): string +{ + (sys, game, gamesrv) = (load Sys Sys->PATH, g, srvmod); + return nil; +} +join(nil: ref Player): string +{ + return nil; +} +leave(nil: ref Player) +{ +} +command(player: ref Player, cmd: string): string +{ + game.action("say " + string player.id + " " + cmd, nil, nil, ~0); + return nil; +} +.ps +1 +.vs +1 +.EE +.SH SOURCE +.B /appl/cmd/games/gamesrv.b +.SH "SEE ALSO" +.IR gamesrv (4) +.SH BUGS +The reuse of object ids can lead to +problems when objects are deleted and +recreated on the server before clients become +aware of the changes. +.PP +This interface is new and will change. |
