From 0a1c05e0f4a249f97e738a98eb20e373874550df Mon Sep 17 00:00:00 2001 From: Jonathan Michalon Date: Fri, 22 Mar 2019 17:31:09 +0100 Subject: [PATCH] better handle resources (tiles/tileset) loading and sharing Now the resources are installed and a lookup is performed to find them from either (respectively) an environment var, the user's datadir and the compile-time datadir. Also the server is responsible for sharing the xml data so that all clients get the same thing, from him over network. Also libovcc is responsible for the DTD files (since it's a sort of spec) while the actual XML data belongs to the server. --- libovcc/Makefile.am | 3 + libovcc/configure.ac | 2 + libovcc/data/xml/tiles.xml | 103 ------------------ libovcc/data/xml/tileset.xml | 12 -- libovcc/src/Makefile.am | 3 +- libovcc/src/hack.vapi | 5 + .../ovcc-network-gamedata-message.vala | 14 +-- libovcc/src/network/ovcc-network-message.vala | 2 +- libovcc/src/ovcc-tile-set.vala | 27 +++-- libovcc/src/ovcc-tiles-def.vala | 24 ++-- libovcc/src/ovcc-utils.vala | 27 +++++ libovccclient/src/ovccclient-server.vala | 12 +- server/Makefile.am | 3 + server/configure.ac | 3 + .../data/xml/tiles.xml | 0 .../data/xml/tileset.xml | 0 server/src/server.vala | 19 +++- 17 files changed, 107 insertions(+), 152 deletions(-) delete mode 100644 libovcc/data/xml/tiles.xml delete mode 100644 libovcc/data/xml/tileset.xml rename libovcc/data/xml/tiles_original.xml => server/data/xml/tiles.xml (100%) rename libovcc/data/xml/tileset_original.xml => server/data/xml/tileset.xml (100%) diff --git a/libovcc/Makefile.am b/libovcc/Makefile.am index 73668cf..e408ba0 100644 --- a/libovcc/Makefile.am +++ b/libovcc/Makefile.am @@ -4,6 +4,9 @@ ACLOCAL_AMFLAGS = -I build/m4 -I build pkgconfig_DATA=ovcc.pc +dist_pkgdata_DATA = data/xml/tiles.dtd \ + data/xml/tileset.dtd + doc: $(MAKE) $@ -C docs diff --git a/libovcc/configure.ac b/libovcc/configure.ac index 82301dd..f31852d 100644 --- a/libovcc/configure.ac +++ b/libovcc/configure.ac @@ -11,9 +11,11 @@ AC_CONFIG_HEADERS([config.h]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) +pkgdatadir="${datadir}/ovcc/" pkgconfigdir="${libdir}/pkgconfig" vapidir="${datadir}/vala/vapi" ovccincludedir="${includedir}/ovcc" +AC_SUBST(pkgdatadir) AC_SUBST(pkgconfigdir) AC_SUBST(vapidir) AC_SUBST(ovccincludedir) diff --git a/libovcc/data/xml/tiles.xml b/libovcc/data/xml/tiles.xml deleted file mode 100644 index 0e657b7..0000000 --- a/libovcc/data/xml/tiles.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - -
None
- - Path - - True - - - - Field - - True - - -
- - - -
None
- - Path - - True - - - - Field - - True - - - - Field - - True - - - - Path - - True - - -
- - -
Monastery
- - field - - true - true - - - - path - -
- - - - City - - true - true - - - - Field - - - - - - City - - - Field - - - Field - - true - - - - - - - City - - true - true - true - - - - - -
diff --git a/libovcc/data/xml/tileset.xml b/libovcc/data/xml/tileset.xml deleted file mode 100644 index 1be1bc7..0000000 --- a/libovcc/data/xml/tileset.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - Example set - - - - - - - - diff --git a/libovcc/src/Makefile.am b/libovcc/src/Makefile.am index ecc528a..8e6a1a9 100644 --- a/libovcc/src/Makefile.am +++ b/libovcc/src/Makefile.am @@ -6,7 +6,8 @@ EXTRA_DIST = hack.h hack.vapi \ ovcc.h ovcc.vapi libovcc_la_CPPFLAGS = -DG_LOG_DOMAIN=\"LibOVCC\" -libovcc_la_CFLAGS = $(LIBOVCC_CFLAGS) +libovcc_la_CFLAGS = $(LIBOVCC_CFLAGS) \ + -DDATADIR='"$(pkgdatadir)"' libovcc_la_LIBADD = $(LIBOVCC_LIBS) libovcc_la_VALAFLAGS = $(LIBOVCC_VALAFLAGS) --library=ovcc --header=ovcc.h \ --vapidir=. --pkg=hack diff --git a/libovcc/src/hack.vapi b/libovcc/src/hack.vapi index 4c7e973..276cf90 100644 --- a/libovcc/src/hack.vapi +++ b/libovcc/src/hack.vapi @@ -21,6 +21,11 @@ [CCode (cheader_filename = "hack.h")] namespace OVCC { + [CCode (cprefix = "", lower_case_cprefix = "")] + namespace Config { + public const string DATADIR; + } + [SimpleType] [CCode (type_id = "G_TYPE_UINT", marshaller_type_name = "UINT", diff --git a/libovcc/src/network/ovcc-network-gamedata-message.vala b/libovcc/src/network/ovcc-network-gamedata-message.vala index 3205b81..f63663a 100644 --- a/libovcc/src/network/ovcc-network-gamedata-message.vala +++ b/libovcc/src/network/ovcc-network-gamedata-message.vala @@ -27,8 +27,8 @@ public class OVCC.Network.GamedataMessage : VariantMessage public uint[] stack_ids = null; public string[] player_nicks = null; - public string tiles_filename { get; set; default = null; } - public string tileset_filename { get; set; default = null; } + public string tiles_data { get; set; default = null; } + public string tileset_data { get; set; default = null; } public State status { get; set; default = State.OK; } @@ -41,7 +41,7 @@ public class OVCC.Network.GamedataMessage : VariantMessage public GamedataMessage (uint[] ids, string[] nicks, string tiles, string tileset) { - Object (tiles_filename: tiles, tileset_filename: tileset); + Object (tiles_data: tiles, tileset_data: tileset); stack_ids = ids; player_nicks = nicks; } @@ -50,8 +50,8 @@ public class OVCC.Network.GamedataMessage : VariantMessage { Variant ids = stack_ids; Variant nicks = player_nicks; - - return new Variant ("(ivvss)", status, ids, nicks, tiles_filename, tileset_filename); + + return new Variant ("(ivvss)", status, ids, nicks, tiles_data, tileset_data); } protected override void parse_variant (uint8[] data) { @@ -64,7 +64,7 @@ public class OVCC.Network.GamedataMessage : VariantMessage status = s; stack_ids = (uint[]) ids; player_nicks = (string[]) nicks; - tiles_filename = t; - tileset_filename = ts; + tiles_data = t; + tileset_data = ts; } } diff --git a/libovcc/src/network/ovcc-network-message.vala b/libovcc/src/network/ovcc-network-message.vala index 3980bbc..d300fce 100644 --- a/libovcc/src/network/ovcc-network-message.vala +++ b/libovcc/src/network/ovcc-network-message.vala @@ -148,7 +148,7 @@ namespace OVCC.Network throws Error { var len = stream.read_uint16 (cancel); - if (len < 1 || len > 0x400 /* arbitrary limit not to fulfill memory */) { + if (len < 1 || len > 0x4000 /* arbitrary limit not to fulfill memory */) { throw new MessageError.MALFORMED_MESSAGE ("Invalid message length %u", len); } diff --git a/libovcc/src/ovcc-tile-set.vala b/libovcc/src/ovcc-tile-set.vala index 486508c..4328340 100644 --- a/libovcc/src/ovcc-tile-set.vala +++ b/libovcc/src/ovcc-tile-set.vala @@ -259,21 +259,16 @@ namespace OVCC return true; } - public bool load (TilesDef tiles, - File file) + public bool load_from_string (TilesDef tiles, + string data) throws Error { - uint8[] data; - - var uri = file.get_uri (); - debug ("Loading tileset file %s...", uri); - file.load_contents (null, out data, null); - var doc = Xml.Parser.read_memory ((string)data, data.length, uri, null, + File dtd = Utils.lookup_resource_path("tileset.dtd"); + var doc = Xml.Parser.read_memory (data, data.length, dtd.get_path(), null, Xml.ParserOption.DTDVALID | Xml.ParserOption.PEDANTIC); if (doc == null) { - throw new MarkupError.INVALID_CONTENT ("""File "%s" is not valid XML""", - uri); + throw new MarkupError.INVALID_CONTENT ("""Data is not valid XML"""); } else { if (! this.xml_read_tileset_doc (doc->get_root_element (), tiles)) { warning ("Document loading failed"); @@ -282,5 +277,17 @@ namespace OVCC return true; } + + public bool load (TilesDef tiles, + string filename) + throws Error + { + uint8[] data; + + File file = Utils.lookup_resource_path(filename); + debug ("""Loading tileset definitions from "%s"...""", file.get_path()); + file.load_contents (null, out data, null); + return load_from_string (tiles, (string)data); + } } } diff --git a/libovcc/src/ovcc-tiles-def.vala b/libovcc/src/ovcc-tiles-def.vala index bc13f6c..f07e124 100644 --- a/libovcc/src/ovcc-tiles-def.vala +++ b/libovcc/src/ovcc-tiles-def.vala @@ -235,20 +235,15 @@ namespace OVCC return true; } - public bool load (File file) + public bool load_from_string (string data) throws Error { - uint8[] data; - - var uri = file.get_uri (); - debug ("""Loading tiles definitions from "%s"...""", uri); - file.load_contents (null, out data, null); - var doc = Xml.Parser.read_memory ((string)data, data.length, uri, null, + File dtd = Utils.lookup_resource_path("tiles.dtd"); + var doc = Xml.Parser.read_memory (data, data.length, dtd.get_path(), null, Xml.ParserOption.DTDVALID | Xml.ParserOption.PEDANTIC); if (doc == null) { - throw new MarkupError.INVALID_CONTENT ("""File "%s" is not valid XML""", - uri); + throw new MarkupError.INVALID_CONTENT ("""Data is not valid XML"""); } else { if (! this.xml_read_doc (doc->get_root_element ())) { warning ("Document loading failed"); @@ -257,6 +252,17 @@ namespace OVCC return true; } + + public bool load (string filename) + throws Error + { + uint8[] data; + + File file = Utils.lookup_resource_path(filename); + debug ("""Loading tiles definitions from "%s"...""", file.get_path()); + file.load_contents (null, out data, null); + return load_from_string ((string)data); + } } } diff --git a/libovcc/src/ovcc-utils.vala b/libovcc/src/ovcc-utils.vala index 9e459b3..c9a66ee 100644 --- a/libovcc/src/ovcc-utils.vala +++ b/libovcc/src/ovcc-utils.vala @@ -93,4 +93,31 @@ namespace OVCC.Utils return (uint)val; } + + /** + * Lookup a filename in common and custom resource prefixes + * + * @param str The filename to look for + * @return a File object + */ + public File lookup_resource_path (string str) + throws FileError + { + List list = new List (); + list.prepend(Config.DATADIR); + list.prepend(Path.build_filename(Environment.get_user_data_dir(), "ovcc")); + list.prepend(Environment.get_variable ("OVCC_DATADIR")); + foreach (var d in list) + { + if (d != null) + { + debug ("Looking up for %s in %s", str, d); + File file = File.new_for_path(Path.build_filename(d, str)); + if (file.query_exists()) + return file; + } + } + + throw new FileError.NOENT ("Resource not found in common and custom paths"); + } } diff --git a/libovccclient/src/ovccclient-server.vala b/libovccclient/src/ovccclient-server.vala index 2cb6828..a32a558 100644 --- a/libovccclient/src/ovccclient-server.vala +++ b/libovccclient/src/ovccclient-server.vala @@ -484,16 +484,16 @@ namespace OVCCClient /* create our game */ try { - tiles.load (File.new_for_path (data.tiles_filename)); + tiles.load_from_string (data.tiles_data); } catch (Error e1) { - throw new ServerError.DATA_UNREACHABLE ("Failed to load tiles data from \"%s\": %s", - data.tiles_filename, e1.message); + throw new ServerError.DATA_UNREACHABLE ("Failed to load tiles data from server: %s", + e1.message); } try { - tileset.load (tiles, File.new_for_path (data.tileset_filename)); + tileset.load_from_string (tiles, data.tileset_data); } catch (Error e2) { - throw new ServerError.DATA_UNREACHABLE ("Failed to load tileset data from \"%s\": %s", - data.tileset_filename, e2.message); + throw new ServerError.DATA_UNREACHABLE ("Failed to load tileset data from server: %s", + e2.message); } var stack = new Stack.from_tile_ids (data.stack_ids, tiles); diff --git a/server/Makefile.am b/server/Makefile.am index 09df440..c91695e 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,3 +1,6 @@ SUBDIRS = src +dist_pkgdata_DATA = data/xml/tiles.xml \ + data/xml/tileset.xml + ACLOCAL_AMFLAGS = -I build/m4 diff --git a/server/configure.ac b/server/configure.ac index 0cb9326..987dedf 100644 --- a/server/configure.ac +++ b/server/configure.ac @@ -11,6 +11,9 @@ AC_CONFIG_HEADERS([config.h]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) +pkgdatadir="${datadir}/ovcc/" +AC_SUBST(pkgdatadir) + # Checks for programs. AC_PROG_CC AM_PROG_VALAC([0.11.6]) diff --git a/libovcc/data/xml/tiles_original.xml b/server/data/xml/tiles.xml similarity index 100% rename from libovcc/data/xml/tiles_original.xml rename to server/data/xml/tiles.xml diff --git a/libovcc/data/xml/tileset_original.xml b/server/data/xml/tileset.xml similarity index 100% rename from libovcc/data/xml/tileset_original.xml rename to server/data/xml/tileset.xml diff --git a/server/src/server.vala b/server/src/server.vala index 3bfbb6b..8f40831 100644 --- a/server/src/server.vala +++ b/server/src/server.vala @@ -32,6 +32,8 @@ public class Server: ThreadedSocketService private List tables = null; private TilesDef tiles = new TilesDef (); private TileSet tileset = new TileSet (); + private string tiles_data; + private string tileset_data; public string name { get; construct; } public uint port { get; construct; default = 0xdead; } @@ -148,7 +150,7 @@ public class Server: ThreadedSocketService debug ("Sending game data"); var data = new GamedataMessage (client.game.get_stack_ids(), client.game.get_player_nicks(), - TILES_FILE, TILESET_FILE); + tiles_data, tileset_data); client.send (data); return true; } @@ -241,10 +243,21 @@ public class Server: ThreadedSocketService uint16 port = 0xdead) throws Error { + uint8[] data1; + uint8[] data2; Object (name: name, port: port); - tiles.load (File.new_for_path (TILES_FILE)); - tileset.load (tiles, File.new_for_path (TILESET_FILE)); + File tiles_file = Utils.lookup_resource_path(TILES_FILE); + File tileset_file = Utils.lookup_resource_path(TILESET_FILE); + + tiles_file.load_contents(null, out data1, null); + tileset_file.load_contents(null, out data2, null); + + tiles_data = (string) data1; + tileset_data = (string) data2; + + tiles.load_from_string (tiles_data); + tileset.load_from_string (tiles, tileset_data); } /* a bit ugly since a direct call to parent method will not trigger the -- GitLab