#include <ggz.h>
#include <ggz_common.h>
Go to the source code of this file.
Classes | |
| struct | GGZSeat |
| A seat at a GGZ game table. More... | |
Defines | |
| #define | GGZDMOD_VERSION_MAJOR 0 |
| #define | GGZDMOD_VERSION_MINOR 0 |
| #define | GGZDMOD_VERSION_MICRO 14 |
| #define | GGZDMOD_VERSION_IFACE "6:0:0" |
| #define | GGZSpectator GGZSeat |
Typedefs | |
| typedef GGZdMod | GGZdMod |
| A GGZdmod object, used for tracking a ggzd<->table connection. | |
| typedef void(*) | GGZdModHandler (GGZdMod *mod, GGZdModEvent event, const void *data) |
| Event handler prototype. | |
Enumerations | |
| enum | GGZdModState { GGZDMOD_STATE_CREATED, GGZDMOD_STATE_WAITING, GGZDMOD_STATE_PLAYING, GGZDMOD_STATE_DONE } |
| Table states. More... | |
| enum | GGZdModEvent { GGZDMOD_EVENT_STATE, GGZDMOD_EVENT_JOIN, GGZDMOD_EVENT_LEAVE, GGZDMOD_EVENT_SEAT, GGZDMOD_EVENT_SPECTATOR_JOIN, GGZDMOD_EVENT_SPECTATOR_LEAVE, GGZDMOD_EVENT_SPECTATOR_SEAT, GGZDMOD_EVENT_PLAYER_DATA, GGZDMOD_EVENT_SPECTATOR_DATA, GGZDMOD_EVENT_ERROR } |
| Callback events. More... | |
| enum | GGZdModType { GGZDMOD_GGZ, GGZDMOD_GAME } |
| The "type" of ggzdmod. More... | |
| enum | GGZGameResult { GGZ_GAME_WIN, GGZ_GAME_LOSS, GGZ_GAME_TIE, GGZ_GAME_FORFEIT, GGZ_GAME_NONE } |
Functions | |
| int | ggzdmod_is_ggz_mode (void) |
| Is the program running in GGZ mode? | |
| GGZdMod * | ggzdmod_new (GGZdModType type) |
| Create a new ggzdmod object. | |
| void | ggzdmod_free (GGZdMod *ggzdmod) |
| Destroy a finished ggzdmod object. | |
| int | ggzdmod_get_fd (GGZdMod *ggzdmod) |
| Get the file descriptor for the GGZdMod socket. | |
| GGZdModType | ggzdmod_get_type (GGZdMod *ggzdmod) |
| Get the type of the ggzdmod object. | |
| GGZdModState | ggzdmod_get_state (GGZdMod *ggzdmod) |
| Get the current state of the table. | |
| int | ggzdmod_get_num_seats (GGZdMod *ggzdmod) |
| Get the total number of seats at the table. | |
| GGZSeat | ggzdmod_get_seat (GGZdMod *ggzdmod, int seat) |
| Get all data for the specified seat. | |
| char * | ggzdmod_get_bot_class (GGZdMod *ggzdmod, const char *name) |
| Return class for named bot. | |
| void | ggzdmod_set_playerdata (GGZdMod *ggzdmod, bool is_spectator, int seat_num, void *playerdata) |
| Set a playerdata pointer. | |
| void * | ggzdmod_get_gamedata (GGZdMod *ggzdmod) |
| Return gamedata pointer. | |
| void | ggzdmod_set_gamedata (GGZdMod *ggzdmod, void *data) |
| Set gamedata pointer. | |
| int | ggzdmod_get_max_num_spectators (GGZdMod *ggzdmod) |
| Get the maximum number of spectators. This function returns the maximum number of spectator seats available. A game can use this to iterate over the spectator seats to look for spectators occupying them. Since spectators may come and go at any point and there is no theoretical limit on the number of spectators, you should consider this value to be dynamic and call this function again each time you're looking for spectators. | |
| GGZSeat | ggzdmod_get_spectator (GGZdMod *ggzdmod, int spectator) |
| Get a spectator's data. | |
| int | ggzdmod_set_handler (GGZdMod *ggzdmod, GGZdModEvent e, GGZdModHandler func) |
| Set a handler for the given event. | |
| int | ggzdmod_count_seats (GGZdMod *ggzdmod, GGZSeatType seat_type) |
| Count seats of the given type. | |
| int | ggzdmod_count_spectators (GGZdMod *ggzdmod) |
| Count current number of spectators. | |
| int | ggzdmod_dispatch (GGZdMod *ggzdmod) |
| Check for and handle input. | |
| int | ggzdmod_loop (GGZdMod *ggzdmod) |
| Loop while handling input. | |
| int | ggzdmod_set_state (GGZdMod *ggzdmod, GGZdModState state) |
| Change the table's state. | |
| int | ggzdmod_connect (GGZdMod *ggzdmod) |
| Connect to ggz. | |
| int | ggzdmod_disconnect (GGZdMod *ggzdmod) |
| Disconnect from ggz. | |
| int | ggzdmod_log (GGZdMod *ggzdmod, const char *fmt,...) ggz__attribute((format(printf |
| Log data. | |
| int void | ggzdmod_check (GGZdMod *ggzdmod) |
| Log all information about the ggzdmod. | |
| void | ggzdmod_report_game (GGZdMod *ggzdmod, int *teams, GGZGameResult *results, int *scores) |
| Report the results of a game to GGZ. | |
| void | ggzdmod_report_savegame (GGZdMod *ggzdmod, const char *savegame) |
| Report the savegame to GGZ. | |
| void | ggzdmod_request_num_seats (GGZdMod *ggzdmod, int num_seats) |
| Tell GGZ to change the number of seats at this table. | |
| void | ggzdmod_request_boot (GGZdMod *ggzdmod, const char *name) |
| Tell GGZ to boot the given player from this table. | |
| void | ggzdmod_request_bot (GGZdMod *ggzdmod, int seat_num) |
| Tell GGZ to change the given seat from OPEN to BOT. | |
| void | ggzdmod_request_open (GGZdMod *ggzdmod, int seat_num) |
| Tell GGZ to change the given seat from BOT/RESERVED to OPEN. | |
This file contains all libggzdmod functions used by game servers to interface with GGZ (and vice versa). Just include ggzdmod.h and make sure your program is linked with libggzdmod. Then use the functions below as appropriate.
GGZdmod currently provides an event-driven interface. Data from communication sockets is read in by the library, and a handler function (registered as a callback) is invoked to handle any events. The calling program should not read/write data from/to the GGZ socket unless it really knows what it is doing.
That this does not apply to the client sockets: ggzdmod provides one file desriptor for communicating (TCP) to each client. If data is ready to be read by one of these file descriptors ggzdmod may invoke the appropriate handler (see below), but will never actually read any data.
Here is a fairly complete example. In this game we register a handler for each of the possible callbacks. This particular game is played only when all seats are full; when any seats are empty it must wait (much like a card or board game).
// Game-defined handler functions for GGZ events; see below. void handle_state_change(GGZdMod* ggz, GGZdModEvent event, const void *data); void handle_player_seat(GGZdMod* ggz, GGZdModEvent event, const void *data); void handle_player_data(GGZdMod* ggz, GGZdModEvent event, const void *data); // Other game-defined functions (not ggz-related). void game_init(GGZdMod *ggz); // initialize a game void game_launch(void); // handle a game "launch" void game_end(void); // called before the table shuts down void resume_playing(void); // we have enough players to play void stop_playing(void); // not enough players to play int main() { GGZdMod *ggz = ggzdmod_new(GGZ_GAME); // First we register functions to handle some events. ggzdmod_set_handler(ggz, GGZDMOD_EVENT_STATE, &handle_state_change); ggzdmod_set_handler(ggz, GGZDMOD_EVENT_JOIN, &handle_player_seat); ggzdmod_set_handler(ggz, GGZDMOD_EVENT_LEAVE, &handle_player_seat); ggzdmod_set_handler(ggz, GGZDMOD_EVENT_SEAT, &handle_player_seat); ggzdmod_set_handler(ggz, GGZDMOD_EVENT_PLAYER_DATA, &handle_player_data); // Do any other game initializations. You'll probably want to // track "ggz" globally. game_init(mod); // Then we must connect to GGZ if (ggzdmod_connect(ggz) < 0) exit(-1); (void) ggzdmod_log(ggz, "Starting game."); // ggzdmod_loop does most of the work, dispatching handlers // above as necessary. (void) ggzdmod_loop(ggz); // At the end, we disconnect and destroy the ggzdmod object. (void) ggzdmod_log(ggz, "Ending game."); (void) ggzdmod_disconnect(ggz); ggzdmod_free(ggz); } void handle_state_change(GGZdMod* ggz, GGZdModEvent event, const void *data) { const GGZdModState *old_state = data; GGZdModState new_state = ggzdmod_get_state(ggz); if (*old_state == GGZDMOD_STATE_CREATED) // ggzdmod data isn't initialized until it connects with GGZ // during the game launch, so some initializations should wait // until here. game_launch(); switch (new_state) { case GGZDMOD_STATE_WAITING: // At this point we've entered the "waiting" state where we // aren't actually playing. This is generally triggered by // the game calling ggzdmod_set_state, which happens when // a player leaves (down below). It may also be triggered // by GGZ automatically. stop_playing(); break; case GGZDMOD_STATE_PLAYING: // At this point we've entered the "playing" state, so we // should resume play. This is generally triggered by // the game calling ggzdmod_set_state, which happens when // all seats are full (down below). It may also be // triggered by GGZ automatically. resume_playing(); break; case GGZDMOD_STATE_DONE: // at this point ggzdmod_loop will stop looping, so we'd // better close up shop fast. This will only happen // automatically if all players leave, but we can force it // using ggzdmod_set_state. game_end(); break; } } void handle_player_seat(GGZdMod* ggz, GGZdModEvent event, const void *data) { const GGZSeat *old_seat = data; GGZSeat new_seat = ggzdmod_get_seat(ggz, old_seat->num); if (new_seat.type == GGZ_SEAT_PLAYER && old_seat->type != GGZ_SEAT_PLAYER) { // join event ... do player initializations ... if (ggzdmod_count_seats(ggz, GGZ_SEAT_OPEN) == 0) { // this particular game will only play when all seats are full. // calling this function triggers the STATE event, so we'll end // up executing resume_playing() above. ggzdmod_set_state(ggz, GGZDMOD_STATE_PLAYING); } } else if (new_seat.type != GGZ_SEAT_PLAYER && old_seat->type == GGZ_SEAT_PLAYER) { // leave event ... do de-initialization ... if (ggzdmod_count_seats(ggz, GGZ_SEAT_PLAYER) == 0) // the game will exit when all human players are gone ggzdmod_set_state(ggz, GGZDMOD_STATE_DONE); else // this particular game will only play when all seats are full. // calling this function triggers the STATE event, so we'll end // up executing stop_playing() above. ggzdmod_set_state(ggz, GGZDMOD_STATE_WAITING); } } void handle_player_data(GGZdMod* ggz, GGZdModEvent event, const void *data) { const int *player = data; int socket_fd = ggzdmod_get_seat(ggz, *player).fd; // ... read a packet from the socket ... }
For more information, see the documentation at http://www.ggzgamingzone.org/.
A GGZdmod object, used for tracking a ggzd<->table connection.
A game server should track a pointer to a GGZdMod object; it contains all the state information for communicating with GGZ. The GGZ server will track one such object for every game table that is running.
| typedef void(*) GGZdModHandler(GGZdMod *mod, GGZdModEvent event, const void *data) |
Event handler prototype.
A function of this type will be called to handle a ggzdmod event.
| mod | The ggzdmod state object. | |
| event | The event that has occured. | |
| data | Pointer to additional data for the event. The additional data will be of the following form:
|
| enum GGZdModEvent |
Callback events.
Each of these is a possible GGZdmod event. For each event, the table may register a handler with GGZdmod to handle that event.
| GGZDMOD_EVENT_STATE |
Module status changed This event occurs when the game's status changes. The old state (a GGZdModState*) is passed as the event's data.
|
| GGZDMOD_EVENT_JOIN | Player joined This event occurs when a player joins the table. The old seat (a GGZSeat*) is passed as the event's data. The seat information will be updated before the event is invoked. |
| GGZDMOD_EVENT_LEAVE | Player left This event occurs when a player leaves the table. The old seat (a GGZSeat*) is passed as the event's data. The seat information will be updated before the event is invoked. |
| GGZDMOD_EVENT_SEAT | General seat change This event occurs when a seat change other than a player leave/join happens. The old seat (a GGZSeat*) is passed as the event's data. The seat information will be updated before the event is invoked. Operations include changing of reserved or abandoned seats to open, swapping bot players in and out, making a reservation on an open seat, or even an open seat changing to a player seat if a player changes seats. Note that no new connections are provided nor are connections removed in a SEAT event; thus, if a player is removed via this event you can be sure another SEAT or SPECTATOR_SEAT event will be provided shortly to re-add him to a new location. |
| GGZDMOD_EVENT_SPECTATOR_JOIN | A spectator joins the game. The data of the old spectator (GGZSeat*) is passed as the data for the event. It can be assumed that the spectator seat was previously empty, so the name and socket given will be invalid (NULL/-1). |
| GGZDMOD_EVENT_SPECTATOR_LEAVE | A spectator left the game The old spectator data can be obtained via the (GGZSeat*) which is passed as the event data. |
| GGZDMOD_EVENT_SPECTATOR_SEAT |
A spectator seat changed. The old spectator data can be obtained via the (GGZSeat*) which is passed as the event data. The same caveats apply as to GGZDMOD_EVENT_SEAT.
|
| GGZDMOD_EVENT_PLAYER_DATA | Data available from player This event occurs when there is data ready to be read from one of the player sockets. The player number (an int*) is passed as the event's data. |
| GGZDMOD_EVENT_SPECTATOR_DATA | Data available from spectator For games which support spectators, this indicates that one of them sent some data to the game server. |
| GGZDMOD_EVENT_ERROR | An error has occurred This event occurs when a GGZdMod error has occurred. An error message (a char*) will be passed as the event's data. GGZdMod may attempt to recover from the error, but it is not guaranteed that the GGZ connection will continue to work after an error has happened. |
| enum GGZdModState |
Table states.
Each table has a current "state" that is tracked by ggzdmod. First the table is executed and begins running. Then it receives a launch event from GGZD and begins waiting for players. At some point a game will be started and played at the table, after which it may return to waiting. Eventually the table will probably halt and then the program will exit.
More specifically, the game is in the CREATED state when it is first executed. It moves to the WAITING state after GGZ first communicates with it. After this, the game server may use ggzdmod_set_state to change between WAITING, PLAYING, and DONE states. A WAITING game is considered waiting for players (or whatever), while a PLAYING game is actively being played (this information may be, but currently is not, propogated back to GGZ for display purposes). Once the state is changed to DONE, the table is considered dead and will exit shortly thereafter (ggzdmod_loop will stop looping, etc.) (see the kill_on_exit game option).
Each time the game state changes, a GGZDMOD_EVENT_STATE event will be propogated to the game server.
| enum GGZdModType |
| enum GGZGameResult |
| int void ggzdmod_check | ( | GGZdMod * | ggzdmod | ) |
Log all information about the ggzdmod.
This is a debugging function that will log all available information about the GGZdMod object. It uses ggzdmod_log for logging.
| ggzdmod | The GGZdMod object. |
| int ggzdmod_connect | ( | GGZdMod * | ggzdmod | ) |
Connect to ggz.
Call this function to make an initial GGZ <-> game connection.
| ggzdmod | The ggzdmod object. |
| int ggzdmod_count_seats | ( | GGZdMod * | ggzdmod, | |
| GGZSeatType | seat_type | |||
| ) |
Count seats of the given type.
This is a convenience function that counts how many seats there are that have the given type. For instance, giving seat_type==GGZ_SEAT_OPEN will count the number of open seats.
| ggzdmod | The ggzdmod object. | |
| seat_type | The type of seat to be counted. |
| int ggzdmod_count_spectators | ( | GGZdMod * | ggzdmod | ) |
Count current number of spectators.
This function returns the number of spectators watching the game. Note that the spectator numbers may not match up: if there are two spectators they could be numbered 0 and 4. If you're trying to iterate through the existing spectators, you probably want ggzdmod_get_max_num_spectators() instead.
| ggzdmod | The ggzdmod object |
| int ggzdmod_disconnect | ( | GGZdMod * | ggzdmod | ) |
Disconnect from ggz.
| ggzdmod | The ggzdmod object. |
| int ggzdmod_dispatch | ( | GGZdMod * | ggzdmod | ) |
Check for and handle input.
This function handles input from the communications sockets:
| ggzdmod | The ggzdmod object. |
| void ggzdmod_free | ( | GGZdMod * | ggzdmod | ) |
Destroy a finished ggzdmod object.
After the connection is through, the object may be freed.
| ggzdmod | The GGZdMod object. |
| char* ggzdmod_get_bot_class | ( | GGZdMod * | ggzdmod, | |
| const char * | name | |||
| ) |
Return class for named bot.
| ggzdmod | The GGZdMod object. | |
| name | Name of the bot. |
| int ggzdmod_get_fd | ( | GGZdMod * | ggzdmod | ) |
Get the file descriptor for the GGZdMod socket.
| ggzdmod | The GGZdMod object. |
| void* ggzdmod_get_gamedata | ( | GGZdMod * | ggzdmod | ) |
Return gamedata pointer.
Each GGZdMod object can be given a "gamedata" pointer that is returned by this function. This is useful for when a single process serves multiple GGZdmod's.
| ggzdmod | The GGZdMod object. |
| int ggzdmod_get_max_num_spectators | ( | GGZdMod * | ggzdmod | ) |
Get the maximum number of spectators. This function returns the maximum number of spectator seats available. A game can use this to iterate over the spectator seats to look for spectators occupying them. Since spectators may come and go at any point and there is no theoretical limit on the number of spectators, you should consider this value to be dynamic and call this function again each time you're looking for spectators.
| int ggzdmod_get_num_seats | ( | GGZdMod * | ggzdmod | ) |
Get the total number of seats at the table.
While in GGZDMOD_STATE_CREATED, we don't know the number of seats.
Get all data for the specified seat.
| ggzdmod | The GGZdMod object. | |
| seat | The seat number (0..(number of seats - 1)). |
Get a spectator's data.
| ggzdmod | The GGZdMod object. | |
| spectator | The number, between 0 and (number of spectators - 1). |
| GGZdModState ggzdmod_get_state | ( | GGZdMod * | ggzdmod | ) |
Get the current state of the table.
| ggzdmod | The GGZdMod object. |
| GGZdModType ggzdmod_get_type | ( | GGZdMod * | ggzdmod | ) |
Get the type of the ggzdmod object.
| ggzdmod | The GGZdMod object. |
| int ggzdmod_is_ggz_mode | ( | void | ) |
Is the program running in GGZ mode?
Call this function to see if the program was actually launched by GGZ. This can be used to give an error message if the executable is run outside of the GGZ environment, or for games that will run both inside and outside of GGZ.
| int ggzdmod_log | ( | GGZdMod * | ggzdmod, | |
| const char * | fmt, | |||
| ... | ||||
| ) |
Log data.
This function sends the specified string (printf-style) to the GGZ server to be logged.
| ggzdmod | The GGZdmod object. | |
| fmt | A printf-style format string. |
| int ggzdmod_loop | ( | GGZdMod * | ggzdmod | ) |
Loop while handling input.
This function repeatedly handles input from all sockets. It will only stop once the game state has been changed to DONE (or if there has been an error).
| ggzdmod | The ggzdmod object. |
| GGZdMod* ggzdmod_new | ( | GGZdModType | type | ) |
Create a new ggzdmod object.
Before connecting through ggzdmod, a new ggzdmod object is needed.
| type | The type of ggzdmod. Should be GGZDMOD_GAME for game servers. |
| void ggzdmod_report_game | ( | GGZdMod * | ggzdmod, | |
| int * | teams, | |||
| GGZGameResult * | results, | |||
| int * | scores | |||
| ) |
Report the results of a game to GGZ.
After a game has completed, the game server should call this function to report the results to GGZ. GGZ can then use the information to track player statistics - including an ELO-style rating, win-loss records, etc.
| ggzdmod | The ggzdmod object. | |
| teams | An array listing a team number for each player, or NULL. | |
| results | An array listing the result of the game for each player. | |
| scores | The scores for all players (may be NULL) |
| void ggzdmod_report_savegame | ( | GGZdMod * | ggzdmod, | |
| const char * | savegame | |||
| ) |
Report the savegame to GGZ.
If a game saves the game data to disk, the directory name, file name or any other associated token can be reported to GGZ. In the case of a continuous game log, the reporting should happen at the beginning as to allow the continuation of the saved game.
| ggzdmod | The ggzdmod object. | |
| savegame | Name of the savegame file within the game's directory. |
| void ggzdmod_request_num_seats | ( | GGZdMod * | ggzdmod, | |
| int | num_seats | |||
| ) |
Tell GGZ to change the number of seats at this table.
| void ggzdmod_set_gamedata | ( | GGZdMod * | ggzdmod, | |
| void * | data | |||
| ) |
Set gamedata pointer.
| ggzdmod | The GGZdMod object. | |
| data | The gamedata block (or NULL for none). |
| int ggzdmod_set_handler | ( | GGZdMod * | ggzdmod, | |
| GGZdModEvent | e, | |||
| GGZdModHandler | func | |||
| ) |
Set a handler for the given event.
As described above, GGZdmod uses an event-driven structure. Each time an event is called, the event handler (there can be only one) for that event will be called. This function registers such an event handler.
| ggzdmod | The GGZdmod object. | |
| e | The GGZdmod event. | |
| func | The handler function being registered. |
| void ggzdmod_set_playerdata | ( | GGZdMod * | ggzdmod, | |
| bool | is_spectator, | |||
| int | seat_num, | |||
| void * | playerdata | |||
| ) |
Set a playerdata pointer.
Each GGZ seat (regular or spectator) can be given a "playerdata" pointer that is available through ggzdmod_get_seat. This is useful for preserving state data when a particular player changes seat, as the playerdata will be preserved across the seat change.
| ggzdmod | The GGZdMod object. | |
| is_spectator | true iff it is a spectator seat | |
| seat_num | The number of the seat | |
| playerdata | An arbitrary pointer to be set as the playerdata |
| int ggzdmod_set_state | ( | GGZdMod * | ggzdmod, | |
| GGZdModState | state | |||
| ) |
Change the table's state.
This function should be called to change the state of a table. A game can use this function to change state between WAITING and PLAYING, or to set it to DONE.
| ggzdmod | The ggzdmod object. | |
| state | The new state. |
1.5.1