Commit 080f399f authored by Jonathan Michalon's avatar Jonathan Michalon

Implement playing table listing and selection in libs and server

parent 163cd4e8
......@@ -32,7 +32,8 @@ libovcc_la_SOURCES = ovcc-board.vala \
network/ovcc-network-signals.vala \
network/ovcc-network-disconnect-message.vala \
network/ovcc-network-welcome-message.vala \
network/ovcc-network-error-message.vala
network/ovcc-network-error-message.vala \
network/ovcc-network-list-tables-message.vala
ovccinclude_HEADERS = ovcc.h
vapi_DATA = ovcc.vapi
......
/*
*
* Copyright (C) 2019 Colomban Wendling <ban@herbesfolles.org>
* Jonathan Michalon <studios.chalmion@no-log.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
public class OVCC.Network.ListTablesMessage : VariantMessage
{
public override MessageType message_type { get { return MessageType.LIST_TABLES; } }
public GameDescription[] descriptions;
public ListTablesMessage (GameDescription[] descriptions = {})
{
this.descriptions = descriptions;
}
protected override Variant build_variant ()
{
Variant[] list = {};
foreach (var d in descriptions) {
Variant tmp = d.player_nicks; // triggers internal vala magics with VariantBuilder etc.
list += new Variant ("(siv)", d.name, d.state, tmp);
}
Variant v = list; // triggers internal vala magics with VariantBuilder etc.
return v;
}
protected override void parse_variant (uint8[] data)
{
Variant[] list;
GameDescription[] tmplist = {};
list = (Variant[]) Variant.new_from_data<Object> (new VariantType ("av"), data, false, this);
foreach (var v in list) {
string name = v.get_child_value (0).get_string ();
GameState state = (GameState) v.get_child_value (1).get_int32 ();
string[] player_nicks = (string[]) v.get_child_value (2).get_variant ();
tmplist += new GameDescription (name, state, player_nicks);
}
descriptions = tmplist;
}
}
......@@ -18,9 +18,10 @@
*
*/
/**
/*
* How to add a new message:
* 1) Subclass OVCC.Network.Message (or one of its subclass)
* 1) Subclass OVCC.Network.Message (or one of its subclass);
* don't forget to append your filename to Makefile.am's libovcc_la_SOURCES
* 2) Implement the abstract methods and properties
* 3) Append the message type in OVCC.Network.MessageType
* 4) Append the type of your class in OVCC.Network.Message.message_types
......@@ -45,6 +46,7 @@ namespace OVCC.Network
GAMEDATA,
SIGNAL,
DISCONNECT,
LIST_TABLES,
INVALID
}
......@@ -58,7 +60,8 @@ namespace OVCC.Network
typeof (JoinMessage),
typeof (GamedataMessage),
typeof (SignalMessage),
typeof (DisconnectMessage)
typeof (DisconnectMessage),
typeof (ListTablesMessage)
};
public abstract MessageType message_type { get; }
......
......@@ -52,6 +52,29 @@ namespace OVCC
ABORTED
}
/**
* A class providing the description of a Game.
* This is a stripped-down group of data typically to descibe a Game over network.
*/
public class GameDescription : Object
{
public string name { get; construct; }
public GameState state { get; construct; }
public string[] player_nicks { get; construct; }
public GameDescription (string name, GameState state, string[] player_nicks)
{
Object(name: name, state: state, player_nicks: player_nicks);
}
public string to_string ()
{
return "Game '%s' in '%s' state with players '%s'".printf (name,
state.to_string(),
string.joinv(", ", player_nicks));
}
}
/**
* The main part of OVCC. This is the glue connecting all the game's parts to
* make a playable game, and play it.
......@@ -488,5 +511,16 @@ namespace OVCC
}
return nicks;
}
/**
* Generate the {@link GameDescription} corresponding to this Game instance.
*
* @return A {@link GameDescription} describing us.
*/
public GameDescription describe ()
{
/* FIXME table name */
return new GameDescription ("Unnamed Game", state, get_player_nicks());
}
}
}
......@@ -444,12 +444,23 @@ namespace OVCCClient
* matching the given filter
*
* @param filter the {@link TablesFilter} to use
* @return A list of table indexes on the remote server matching //filter//
* @return A list of {@link GameDescription} on the remote server matching //filter//
*/
public List<int>? enumerate_tables (TablesFilter filter)
public async GameDescription[]? enumerate_tables (TablesFilter filter,
Cancellable? cancellable = null)
throws ServerError, IOError
requires (connection != null)
{
return null;
/* ask the server to send the list */
yield send_message (new ListTablesMessage (), cancellable);
/* wait for answer */
Message msg = yield receive_type (MessageType.LIST_TABLES, cancellable);
ListTablesMessage list = msg as ListTablesMessage;
/* FIXME implement filter */
return list.descriptions;
}
/**
......@@ -482,7 +493,7 @@ namespace OVCCClient
if (index == -1) {
throw new ServerError.NO_OPEN_TABLE ("Server said that no open table is available");
} else {
throw new ServerError.NO_OPEN_TABLE ("Server said that the table is not open");
throw new ServerError.NO_OPEN_TABLE ("Server said that it is not an open table");
}
}
......
......@@ -72,7 +72,7 @@ public class Server: ThreadedSocketService
if (candidate == null && n_open_tables < max_tables) {
candidate = new Game (tileset, null);
tables.prepend (candidate);
debug ("Added table %p", candidate);
debug ("Added table %p, which describes as '%s'", candidate, candidate.describe().to_string());
}
}
......@@ -137,10 +137,15 @@ public class Server: ThreadedSocketService
private bool handle_join (JoinMessage msg, Client client)
throws Error
{
/* FIXME handle precise table joins (not only -1/any) */
Game? table = pick_open_table ();
Game? table = null;
if (msg.table_index == -1) {
table = pick_open_table ();
} else {
table = tables.nth_data (msg.table_index);
  • isn't using straight indexes from the message a good idea? what if a table is closed during request?

  • Yeah, better use some sort of GLib.Uuid (but needs a more recent glib than my current workstation so either someone under sid for example or wait a bit :P)

  • Fair enough. Let's put a big blinking red FIXME so we, well, fix that, at some point 🙂

  • It's in my local TODO but not sure where to drop the FIXME, since it may be wise to use UUIDs at several locations…

  • yeah… I'd drop a FIXME: somewhere the ID used is clearly just an index in a list, not necessarily everywhere, but everywhere wouldn't hurt either.

  • I thought to write the field in Game object, as if working but commented out, to remember implement and use it? Would be a central place…

  • Yeah sounds good

  • Done in a402453d

Please register or sign in to reply
}
if (table == null) {
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);
join.status = JoinMessage.State.FAILED;
client.send (join);
......@@ -162,6 +167,19 @@ public class Server: ThreadedSocketService
return true;
}
private bool handle_list_tables (ListTablesMessage msg, Client client)
throws Error
{
GameDescription[] list = {};
foreach (var t in tables) {
list += t.describe ();
}
var data = new ListTablesMessage (list);
client.send (data);
return true;
}
private bool handle_connection (ThreadedSocketService service,
SocketConnection connection,
Object? source)
......@@ -221,6 +239,14 @@ public class Server: ThreadedSocketService
warning ("Problems handling a client join... left in unknown state");
}
break;
case MessageType.LIST_TABLES:
try {
handle_list_tables (msg as ListTablesMessage, client);
} catch (Error e) {
/* FIXME send error message */
warning ("Problems handling a list table action...");
}
break;
case MessageType.SIGNAL:
client.signal_handle.emit_received (msg as SignalMessage);
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment