From 7f24d557df904491ea8f78cb7a64dca540494a73 Mon Sep 17 00:00:00 2001 From: Jonathan Michalon Date: Fri, 17 May 2019 15:32:45 +0200 Subject: [PATCH] Fix game state confusion and "table" naming mess There was a confusion between a "game" and a "table". "tables" was just a list of Game's. Also a table was "open" as long as it was created but a Game in state "open" meant that it was open to new players. This commit removes the "table" terminology, merges TablesFilters into GameState and implements filtering in the enumeration method. --- clients/bot/src/main.vala | 18 ++--- clients/ovcc-gtk/src/main.c | 6 +- clients/ovcc-gtk/src/ovccgtk-client.c | 20 ++--- libovcc/src/Makefile.am | 2 +- .../network/ovcc-network-join-message.vala | 8 +- ...a => ovcc-network-list-games-message.vala} | 6 +- libovcc/src/network/ovcc-network-message.vala | 4 +- libovcc/src/network/ovcc-network-signals.vala | 1 - libovcc/src/ovcc-game.vala | 33 ++++++-- libovccclient/src/ovccclient-client.vala | 12 +-- libovccclient/src/ovccclient-server.vala | 75 ++++++++---------- server/src/server.vala | 76 +++++++++---------- 12 files changed, 134 insertions(+), 127 deletions(-) rename libovcc/src/network/{ovcc-network-list-tables-message.vala => ovcc-network-list-games-message.vala} (92%) diff --git a/clients/bot/src/main.vala b/clients/bot/src/main.vala index f171af6..a2a505f 100644 --- a/clients/bot/src/main.vala +++ b/clients/bot/src/main.vala @@ -13,7 +13,7 @@ public class Bot : OVCCClient.Client throws Error { uint player_suffix = 7; - int table_to_join = -1; + int game_to_join = -1; /* connect to the server */ yield bind_to (server); @@ -36,29 +36,29 @@ public class Bot : OVCCClient.Client } debug ("Logged in with player_suffix = %u", player_suffix); - /* join an open table */ + /* join an open game */ - var list = yield server.enumerate_tables(OVCCClient.TablesFilter.OPEN); - print ("List of open tables:\n"); + var list = yield server.enumerate_games (OVCC.GameState.NEW | OVCC.GameState.PLAYER_WAITING); + print ("List of open games:\n"); var idx = 0; foreach (var d in list) { print (" - %02i: %s\n", idx, d.to_string()); idx++; } if (list.length == 0) { - print ("(currently no table)\n"); + print ("(currently no game)\n"); } - print ("What table index to join? (-1 or empty for any open table) "); + print ("What game index to join? (-1 or empty for any open game) "); string? line = interactive ? stdin.read_line () : ""; if (line != null && line != "") { - table_to_join = int.parse(line); + game_to_join = int.parse (line); } - debug ("Trying to join table %i...", table_to_join); + debug ("Trying to join game %i...", game_to_join); try { - yield join_table (table_to_join); + yield join_game (game_to_join); } catch (Error e4) { leave (); throw e4; diff --git a/clients/ovcc-gtk/src/main.c b/clients/ovcc-gtk/src/main.c index 3a85817..d82a82f 100644 --- a/clients/ovcc-gtk/src/main.c +++ b/clients/ovcc-gtk/src/main.c @@ -284,7 +284,7 @@ G_MODULE_EXPORT void game_start_activate_handler (GtkAction *action, App *app) { - if (app->game && ovcc_game_get_state (app->game) == OVCC_GAME_STATE_STOPPED) { + if (app->game && ovcc_game_state_can_start (ovcc_game_get_state (app->game))) { GError *err = NULL; if (! ovcc_game_start (app->game, &err)) { @@ -406,8 +406,8 @@ on_game_state_changed (OVCCGame *game, started = TRUE; break; - case OVCC_GAME_STATE_STOPPED: - app_set_status (app, _("Game stopped")); + case OVCC_GAME_STATE_PLAYER_WAITING: + app_set_status (app, _("Game now waiting player")); can_start = TRUE; break; } diff --git a/clients/ovcc-gtk/src/ovccgtk-client.c b/clients/ovcc-gtk/src/ovccgtk-client.c index 2e22801..4d575d5 100644 --- a/clients/ovcc-gtk/src/ovccgtk-client.c +++ b/clients/ovcc-gtk/src/ovccgtk-client.c @@ -141,16 +141,16 @@ ovccgtk_client_new (const gchar *name) static void -ovccgtk_client_join_table_ready (GObject *object, - GAsyncResult *result, - gpointer data) +ovccgtk_client_join_game_ready (GObject *object, + GAsyncResult *result, + gpointer data) { GTask *task = data; GError *error = NULL; - g_debug ("ovccclient_client_join_table_finish()"); - if (! ovccclient_client_join_table_finish (OVCCCLIENT_CLIENT (object), - result, &error)) { + g_debug ("ovccclient_client_join_game_finish()"); + if (! ovccclient_client_join_game_finish (OVCCCLIENT_CLIENT (object), + result, &error)) { ovccclient_client_leave (OVCCCLIENT_CLIENT (object), NULL); g_task_return_error (task, error); g_object_unref (task); @@ -176,10 +176,10 @@ ovccgtk_client_login_ready (GObject *object, g_task_return_error (task, error); g_object_unref (task); } else { - g_debug ("ovccclient_client_join_table()"); - ovccclient_client_join_table (OVCCCLIENT_CLIENT (object), -1, - g_task_get_cancellable (task), - ovccgtk_client_join_table_ready, task); + g_debug ("ovccclient_client_join_game()"); + ovccclient_client_join_game (OVCCCLIENT_CLIENT (object), -1, + g_task_get_cancellable (task), + ovccgtk_client_join_game_ready, task); } } diff --git a/libovcc/src/Makefile.am b/libovcc/src/Makefile.am index 9fb7c27..e77eb56 100644 --- a/libovcc/src/Makefile.am +++ b/libovcc/src/Makefile.am @@ -33,7 +33,7 @@ libovcc_la_SOURCES = ovcc-board.vala \ network/ovcc-network-disconnect-message.vala \ network/ovcc-network-welcome-message.vala \ network/ovcc-network-error-message.vala \ - network/ovcc-network-list-tables-message.vala + network/ovcc-network-list-games-message.vala ovccinclude_HEADERS = ovcc.h vapi_DATA = ovcc.vapi diff --git a/libovcc/src/network/ovcc-network-join-message.vala b/libovcc/src/network/ovcc-network-join-message.vala index a20c192..0ff1ad8 100644 --- a/libovcc/src/network/ovcc-network-join-message.vala +++ b/libovcc/src/network/ovcc-network-join-message.vala @@ -25,7 +25,7 @@ public class OVCC.Network.JoinMessage : VariantMessage { public override MessageType message_type { get { return MessageType.JOIN; } } - public int table_index { get; set; default = -1; } + public int game_index { get; set; default = -1; } public State status { get; set; default = State.QUERY; } public enum State @@ -38,12 +38,12 @@ public class OVCC.Network.JoinMessage : VariantMessage public JoinMessage (int idx) { - Object (table_index: idx); + Object (game_index: idx); } protected override Variant build_variant () { - return new Variant ("(ii)", status, table_index); + return new Variant ("(ii)", status, game_index); } protected override void parse_variant (uint8[] data) { @@ -51,6 +51,6 @@ public class OVCC.Network.JoinMessage : VariantMessage int idx; parse_data (data, "(ii)", out s, out idx); status = s; - table_index = idx; + game_index = idx; } } diff --git a/libovcc/src/network/ovcc-network-list-tables-message.vala b/libovcc/src/network/ovcc-network-list-games-message.vala similarity index 92% rename from libovcc/src/network/ovcc-network-list-tables-message.vala rename to libovcc/src/network/ovcc-network-list-games-message.vala index ed9cfe4..e03fd54 100644 --- a/libovcc/src/network/ovcc-network-list-tables-message.vala +++ b/libovcc/src/network/ovcc-network-list-games-message.vala @@ -18,13 +18,13 @@ * */ -public class OVCC.Network.ListTablesMessage : VariantMessage +public class OVCC.Network.ListGamesMessage : VariantMessage { - public override MessageType message_type { get { return MessageType.LIST_TABLES; } } + public override MessageType message_type { get { return MessageType.LIST_GAMES; } } public GameDescription[] descriptions; - public ListTablesMessage (GameDescription[] descriptions = {}) + public ListGamesMessage (GameDescription[] descriptions = {}) { this.descriptions = descriptions; } diff --git a/libovcc/src/network/ovcc-network-message.vala b/libovcc/src/network/ovcc-network-message.vala index ce7bf2c..7de6326 100644 --- a/libovcc/src/network/ovcc-network-message.vala +++ b/libovcc/src/network/ovcc-network-message.vala @@ -46,7 +46,7 @@ namespace OVCC.Network GAMEDATA, SIGNAL, DISCONNECT, - LIST_TABLES, + LIST_GAMES, INVALID } @@ -61,7 +61,7 @@ namespace OVCC.Network typeof (GamedataMessage), typeof (SignalMessage), typeof (DisconnectMessage), - typeof (ListTablesMessage) + typeof (ListGamesMessage) }; public abstract MessageType message_type { get; } diff --git a/libovcc/src/network/ovcc-network-signals.vala b/libovcc/src/network/ovcc-network-signals.vala index f8dc2b9..760951f 100644 --- a/libovcc/src/network/ovcc-network-signals.vala +++ b/libovcc/src/network/ovcc-network-signals.vala @@ -166,7 +166,6 @@ namespace OVCC.Network } break; case OVCC.GameState.FINISHED: - case OVCC.GameState.STOPPED: break; /* should be automatic */ case OVCC.GameState.ABORTED: game_object.abort(); diff --git a/libovcc/src/ovcc-game.vala b/libovcc/src/ovcc-game.vala index a85e484..3b9c2f3 100644 --- a/libovcc/src/ovcc-game.vala +++ b/libovcc/src/ovcc-game.vala @@ -38,18 +38,35 @@ namespace OVCC /** * Possible states of a game. + * Only one state at a time. "Flags" type is used for filtering only. * - * @param STOPPED The game is stopped (not started or finished) + * @param NEW The game is just created but no player joined + * @param PLAYER_WAITING The game has players but is not started yet * @param STARTED The game is started * @param FINISHED The game is finished * @param ABORTED The game is stopped, but not finished */ + [Flags] public enum GameState { - STOPPED, + NEW, + PLAYER_WAITING, STARTED, FINISHED, - ABORTED + ABORTED; + + public bool is_open() + { + return NEW in this || PLAYER_WAITING in this; + } + public bool is_done() + { + return FINISHED in this || ABORTED in this; + } + public bool can_start() + { + return PLAYER_WAITING in this; + } } /** @@ -83,7 +100,7 @@ namespace OVCC { private SList _players = null; - public GameState state { get; private set; default = GameState.STOPPED; } + public GameState state { get; private set; default = GameState.NEW; } public Stack stack { private get; construct; } public Board board { get; construct; } public unowned SList players { get { return this._players; } } @@ -130,9 +147,15 @@ namespace OVCC }); this.player_added.connect ((p) => { this.notify_property ("players"); + if (players.length() == 1 && this.state == GameState.NEW) { + this.state = GameState.PLAYER_WAITING; + } }); this.player_removed.connect ((p) => { this.notify_property ("players"); + if (players.length() < 1 && this.state == GameState.PLAYER_WAITING) { + this.state = GameState.NEW; + } }); this.turn_finished.connect (() => next_player ()); @@ -519,7 +542,7 @@ namespace OVCC */ public GameDescription describe () { - /* FIXME table name */ + /* FIXME game name */ return new GameDescription ("Unnamed Game", state, get_player_nicks()); } } diff --git a/libovccclient/src/ovccclient-client.vala b/libovccclient/src/ovccclient-client.vala index 405640f..f3baf79 100644 --- a/libovccclient/src/ovccclient-client.vala +++ b/libovccclient/src/ovccclient-client.vala @@ -147,17 +147,17 @@ namespace OVCCClient } /** - * Joins a table asynchronously + * Joins a game asynchronously * - * @param index The index of the table to join, -1 means any open table + * @param index The index of the game to join, -1 means any open game * @param cancellable a Cancellable object or null - * @return The game corresponding to that table + * @return The joined Game */ - public async Game join_table (int index, - Cancellable? cancellable = null) + public async Game join_game (int index, + Cancellable? cancellable = null) throws ServerError, IOError { - game = yield server.join_table (index, player, cancellable); + game = yield server.join_game (index, player, cancellable); sigqueue.add (game, game.notify["current-player"].connect (() => { debug ("Current player changed to \"%s\"", game.current_player.nick); diff --git a/libovccclient/src/ovccclient-server.vala b/libovccclient/src/ovccclient-server.vala index b740ce4..9ef9e70 100644 --- a/libovccclient/src/ovccclient-server.vala +++ b/libovccclient/src/ovccclient-server.vala @@ -63,9 +63,9 @@ namespace OVCCClient */ MISSING_AUTHENTICATION, /** - * No open table available + * No open game available */ - NO_OPEN_TABLE, + NO_OPEN_GAME, /** * Data could not be reached where it was searched for */ @@ -75,32 +75,7 @@ namespace OVCCClient */ FAILED } - - /** - * Flags for filtering table list - */ - [Flags] - public enum TablesFilter - { - /** - * All tables - */ - ALL, - /** - * Only open tables - */ - OPEN, - /** - * Only tables with people waiting - */ - PEOPLE_WAITING, - /** - * Only tables where people ask for other players - */ - ASKING_FOR_PEOPLE - } - /** * A class representing the server side of the network clients * @@ -438,44 +413,54 @@ namespace OVCCClient } /** - * Enumerate some tables available on the server + * Enumerate some games available on the server * - * This method retrieves a list of available tables currently on the server + * This method retrieves a list of available games currently on the server * matching the given filter * - * @param filter the {@link TablesFilter} to use + * @param a mask of {@link GameState}s to filter in * @return A list of {@link GameDescription} on the remote server matching //filter// */ - public async GameDescription[]? enumerate_tables (TablesFilter filter, - Cancellable? cancellable = null) + public async GameDescription[]? enumerate_games (GameState? filter = null, + Cancellable? cancellable = null) throws ServerError, IOError requires (connection != null) { /* ask the server to send the list */ - yield send_message (new ListTablesMessage (), cancellable); + yield send_message (new ListGamesMessage (), cancellable); /* wait for answer */ - Message msg = yield receive_type (MessageType.LIST_TABLES, cancellable); - ListTablesMessage list = msg as ListTablesMessage; + Message msg = yield receive_type (MessageType.LIST_GAMES, cancellable); + ListGamesMessage list = msg as ListGamesMessage; - /* FIXME implement filter */ + /* filter the list */ + GameDescription[] filtered = {}; + if (filter != null) { + foreach (var d in list.descriptions) { + if (d.state in filter) { + filtered += d; + } + } + } else { + filtered = list.descriptions; + } - return list.descriptions; + return filtered; } /** - * Join a table, index -1 means any open table + * Join a game, index -1 means any open game * - * The index is typically within the list returned by enumerate_tables() + * The index is typically within the list returned by enumerate_games() * - * @param index The table index + * @param index The game index * @param player The player to make join * @param cancellable a Cancellable object or null * @return The game instance corresponding to the one joint on the remote server */ - public async Game join_table (int index, - Player player, - Cancellable? cancellable = null) + public async Game join_game (int index, + Player player, + Cancellable? cancellable = null) throws ServerError, IOError requires (connection != null) { @@ -491,9 +476,9 @@ namespace OVCCClient JoinMessage join = msg as JoinMessage; if (join.status != JoinMessage.State.OK) { if (index == -1) { - throw new ServerError.NO_OPEN_TABLE ("Server said that no open table is available"); + throw new ServerError.NO_OPEN_GAME ("Server said that no open game is available"); } else { - throw new ServerError.NO_OPEN_TABLE ("Server said that it is not an open table"); + throw new ServerError.NO_OPEN_GAME ("Server said that it is not an open game"); } } diff --git a/server/src/server.vala b/server/src/server.vala index da27246..4bc55a9 100644 --- a/server/src/server.vala +++ b/server/src/server.vala @@ -29,7 +29,7 @@ static const string TILESET_FILE = "tileset.xml"; public class Server: ThreadedSocketService { private List clients = null; - private List tables = null; + private List games = null; private TilesDef tiles = new TilesDef (); private TileSet tileset = new TileSet (); private string tiles_data; @@ -37,42 +37,42 @@ public class Server: ThreadedSocketService public string name { get; construct; } public uint port { get; construct; default = 0xdead; } - public uint max_tables { get; set; default = 1; } + public uint max_games { get; set; default = 5; } public signal void stopped (); - /* removes old tables */ - private void cleanup_tables () + /* removes old games */ + private void cleanup_games () { - lock (tables) { - foreach (var game in tables) { - if (game.state != GameState.STOPPED && game.players.length() < 1) { - tables.remove (game); - debug ("Cleaned up table %p", game); + lock (games) { + foreach (var game in games) { + if (game.players.length () < 1 && !game.state.is_open ()) { + games.remove (game); + debug ("Cleaned up game %p", game); } } } } - /* get the most populated open table available, maybe creating one */ - private Game? pick_open_table () + /* get the most populated open game available, maybe creating one */ + private Game? pick_open_game () { Game? candidate = null; - uint n_open_tables = 0; + uint n_open_games = 0; - lock (tables) { - foreach (var game in tables) { - if (game.state == GameState.STOPPED && + lock (games) { + foreach (var game in games) { + if (game.state.is_open() && (candidate == null || candidate.players.length() < game.players.length())) { candidate = game; } - n_open_tables++; + n_open_games++; } - /* if there is no open tables but room for more, create a new one */ - if (candidate == null && n_open_tables < max_tables) { + /* if there is no open games but room for more, create a new one */ + if (candidate == null && n_open_games < max_games) { candidate = new Game (tileset, null); - tables.prepend (candidate); - debug ("Added table %p, which describes as '%s'", candidate, candidate.describe().to_string()); + games.prepend (candidate); + debug ("Added game %p, which describes as '%s'", candidate, candidate.describe().to_string()); } } @@ -137,27 +137,27 @@ public class Server: ThreadedSocketService private bool handle_join (JoinMessage msg, Client client) throws Error { - Game? table = null; - if (msg.table_index == -1) { - table = pick_open_table (); + Game? game = null; + if (msg.game_index == -1) { + game = pick_open_game (); } else { - table = tables.nth_data (msg.table_index); + game = games.nth_data (msg.game_index); } - - if (table == null || table.state != GameState.STOPPED) { - debug ("Bad table %d, sending fail join message", msg.table_index); - var join = new JoinMessage (msg.table_index); + + if (game == null || !game.state.is_open()) { + debug ("Bad game %d, sending fail join message", msg.game_index); + var join = new JoinMessage (msg.game_index); join.status = JoinMessage.State.FAILED; client.send (join); return false; } - debug ("Accepting table join"); - var join = new JoinMessage (msg.table_index); + debug ("Accepting game join"); + var join = new JoinMessage (msg.game_index); join.status = JoinMessage.State.OK; client.send (join); - client.join (table); + client.join (game); debug ("Sending game data"); var data = new GamedataMessage (client.game.get_stack_ids(), @@ -167,14 +167,14 @@ public class Server: ThreadedSocketService return true; } - private bool handle_list_tables (ListTablesMessage msg, Client client) + private bool handle_list_games (ListGamesMessage msg, Client client) throws Error { GameDescription[] list = {}; - foreach (var t in tables) { + foreach (var t in games) { list += t.describe (); } - var data = new ListTablesMessage (list); + var data = new ListGamesMessage (list); client.send (data); return true; @@ -239,12 +239,12 @@ public class Server: ThreadedSocketService warning ("Problems handling a client join... left in unknown state"); } break; - case MessageType.LIST_TABLES: + case MessageType.LIST_GAMES: try { - handle_list_tables (msg as ListTablesMessage, client); + handle_list_games (msg as ListGamesMessage, client); } catch (Error e) { /* FIXME send error message */ - warning ("Problems handling a list table action..."); + warning ("Problems handling a list game action..."); } break; case MessageType.SIGNAL: @@ -257,7 +257,7 @@ public class Server: ThreadedSocketService this.clients.remove (client); } try { client.disconnect (); } catch { /* we don't care if disconnection failed */ } - cleanup_tables (); + cleanup_games (); debug ("Closed connection"); return true; } -- GitLab