<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40537 >

Attached patch cleans up the editor related start position handling
code in the server and the client.

The start positions are kept in a hash table in the 'map' structure.
Common accessor functions map_{get,set,clear}_startpos are used by
the client and the server to check and modify start position data.

In the future the interface can be further extended to allow for
multiple nations and/or players per start position, as well as
subsume the role of map.start_positions as used by the generator.


-----------------------------------------------------------------------
耳を噛もうぜ。
 client/packhand.c  |    7 ++--
 client/tilespec.c  |    6 +++-
 common/map.c       |   82 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 common/map.h       |   10 ++++++
 common/packets.def |    2 +-
 common/tile.h      |    1 -
 server/edithand.c  |   20 ++++--------
 server/maphand.c   |    4 ++-
 8 files changed, 111 insertions(+), 21 deletions(-)

diff --git a/client/packhand.c b/client/packhand.c
index 2667885..e5bab25 100644
--- a/client/packhand.c
+++ b/client/packhand.c
@@ -2207,6 +2207,7 @@ void handle_tile_info(struct packet_tile_info *packet)
   struct resource *presource = resource_by_number(packet->resource);
   struct terrain *pterrain = terrain_by_number(packet->terrain);
   struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
+  const struct nation_type *pnation;
 
   if (NULL == ptile) {
     freelog(LOG_ERROR,
@@ -2360,9 +2361,9 @@ void handle_tile_info(struct packet_tile_info *packet)
     }
   }
 
-  if (ptile->editor.startpos_nation_id
-      != packet->editor_startpos_nation_id) {
-    ptile->editor.startpos_nation_id = packet->editor_startpos_nation_id;
+  pnation = nation_by_number(packet->nation_start);
+  if (map_get_startpos(ptile) != pnation) {
+    map_set_startpos(ptile, pnation);
     tile_changed = TRUE;
   }
 
diff --git a/client/tilespec.c b/client/tilespec.c
index 9f43d41..79631e0 100644
--- a/client/tilespec.c
+++ b/client/tilespec.c
@@ -4507,11 +4507,15 @@ int fill_sprite_array(struct tileset *t,
 
   case LAYER_EDITOR:
     if (ptile && editor_is_active()) {
+      const struct nation_type *pnation;
+
       if (editor_tile_is_selected(ptile)) {
         int color = 2 % tileset_num_city_colors(tileset);
         ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
       }
-      if (ptile->editor.startpos_nation_id != -1) {
+
+      pnation = map_get_startpos(ptile);
+      if (pnation != NULL) {
         ADD_SPRITE_SIMPLE(t->sprites.user.attention);
       }
     }
diff --git a/common/map.c b/common/map.c
index d13df47..52bf27b 100644
--- a/common/map.c
+++ b/common/map.c
@@ -20,6 +20,7 @@
 #include "city.h"
 #include "fcintl.h"
 #include "game.h"
+#include "hash.h"
 #include "log.h"
 #include "mem.h"
 #include "movement.h"
@@ -35,6 +36,12 @@
 /* the very map */
 struct civ_map map;
 
+/* An entry in the start position table. */
+struct startpos_entry {
+  int key;
+  const struct nation_type *nation;
+};
+
 /* these are initialized from the terrain ruleset */
 struct terrain_misc terrain_control;
 
@@ -282,7 +289,6 @@ static void tile_init(struct tile *ptile)
   ptile->worked   = NULL; /* No city working here. */
   ptile->spec_sprite = NULL;
   ptile->editor.need_terrain_fix = FALSE;
-  ptile->editor.startpos_nation_id = -1;
 }
 
 /****************************************************************************
@@ -417,6 +423,12 @@ void map_allocate(void)
 
   generate_city_map_indices();
   generate_map_indices();
+
+  if (map.startpos_table != NULL) {
+    hash_free(map.startpos_table);
+  }
+  map.startpos_table = hash_new_full(hash_fval_int, hash_fcmp_int,
+                                     NULL, free);
 }
 
 /***************************************************************
@@ -433,6 +445,11 @@ void map_free(void)
 
     free(map.tiles);
     map.tiles = NULL;
+
+    if (map.startpos_table) {
+      hash_free(map.startpos_table);
+      map.startpos_table = NULL;
+    }
   }
 }
 
@@ -1206,3 +1223,66 @@ bool is_singular_tile(const struct tile *ptile, int dist)
 		&& (ntl_y < dist || ntl_y >= NATURAL_HEIGHT - dist)));
   } do_in_natural_pos_end;
 }
+
+/****************************************************************************
+  Set a start position at the given tile for the given nation. Clears any
+  existing start position at the tile. The 'pnation' argument may be NULL,
+  in which case this function has the same effect as map_clear_startpos().
+****************************************************************************/
+void map_set_startpos(const struct tile *ptile,
+                      const struct nation_type *pnation)
+{
+  struct startpos_entry *spe;
+
+  if (!map.startpos_table || !ptile) {
+    return;
+  }
+  map_clear_startpos(ptile);
+
+  if (!pnation) {
+    return;
+  }
+
+  spe = fc_calloc(1, sizeof(*spe));
+  spe->key = tile_index(ptile);
+  spe->nation = pnation;
+
+  hash_insert(map.startpos_table, &spe->key, spe);
+}
+
+/****************************************************************************
+  Returns the nation of the start position at the given tile, or NULL if
+  none exists there.
+****************************************************************************/
+const struct nation_type *map_get_startpos(const struct tile *ptile)
+{
+  struct startpos_entry *spe;
+  int key;
+
+  if (!map.startpos_table || !ptile) {
+    return NULL;
+  }
+
+  key = tile_index(ptile);
+  spe = hash_lookup_data(map.startpos_table, &key);
+  if (!spe) {
+    return NULL;
+  }
+
+  return spe->nation;
+}
+
+/****************************************************************************
+  Remove a start position at the given tile.
+****************************************************************************/
+void map_clear_startpos(const struct tile *ptile)
+{
+  int key;
+
+  if (!map.startpos_table || !ptile) {
+    return;
+  }
+
+  key = tile_index(ptile);
+  hash_delete_entry(map.startpos_table, &key);
+}
diff --git a/common/map.h b/common/map.h
index 20b06c9..9bf6e71 100644
--- a/common/map.h
+++ b/common/map.h
@@ -33,6 +33,8 @@ miscellaneous terrain information
 *****************************************************************/
 #define terrain_misc packet_ruleset_terrain_control
 
+struct hash_table;
+
 struct civ_map {
   int topology_id;
   enum direction8 valid_dirs[8], cardinal_dirs[8];
@@ -62,6 +64,8 @@ struct civ_map {
   int num_oceans;               /* not updated at the client */
   struct tile *tiles;
 
+  struct hash_table *startpos_table;
+
   /* Only used by server. */
   struct start_position {
     struct tile *tile;
@@ -103,6 +107,12 @@ bool base_get_direction_for_step(const struct tile *src_tile,
 int get_direction_for_step(const struct tile *src_tile,
 			   const struct tile *dst_tile);
 
+void map_set_startpos(const struct tile *ptile,
+                      const struct nation_type *pnation);
+const struct nation_type *map_get_startpos(const struct tile *ptile);
+void map_clear_startpos(const struct tile *ptile);
+
+
 /* Number of index coordinates (for sanity checks and allocations) */
 #define MAP_INDEX_SIZE (map.xsize * map.ysize)
 
diff --git a/common/packets.def b/common/packets.def
index 49a7433..d1669b4 100644
--- a/common/packets.def
+++ b/common/packets.def
@@ -356,7 +356,7 @@ PACKET_TILE_INFO=14; sc,lsend,is-info
   BOOL special[S_LAST];
   BV_BASES bases;
   STRING spec_sprite[MAX_LEN_NAME];
-  NATION editor_startpos_nation_id;
+  NATION nation_start;
 end
 
 # This packet used to have is_info set but that doesn't work with the
diff --git a/common/tile.h b/common/tile.h
index c818e93..71db75d 100644
--- a/common/tile.h
+++ b/common/tile.h
@@ -48,7 +48,6 @@ struct tile {
   char *spec_sprite;
   struct {
     bool need_terrain_fix; /* Server only. */
-    int startpos_nation_id;
   } editor;
 };
 
diff --git a/server/edithand.c b/server/edithand.c
index b848de6..c2e1a4c 100644
--- a/server/edithand.c
+++ b/server/edithand.c
@@ -20,6 +20,7 @@
 
 #include "events.h"
 #include "fcintl.h"
+#include "hash.h"
 #include "log.h"
 #include "shared.h"
 #include "support.h"
@@ -45,6 +46,7 @@
  * been deferred after their terrains have been edited. */
 static int unfixed_terrain_count;
 
+
 /****************************************************************************
   Do the potentially slow checks required after some tile's terrain changes.
 ****************************************************************************/
@@ -1115,7 +1117,7 @@ void handle_edit_startpos(struct connection *pc, int x, int y,
                           Nation_type_id nation)
 {
   struct tile *ptile;
-  bool changed = FALSE;
+  const struct nation_type *pnation, *old;
 
   if (!can_conn_edit(pc)) {
     notify_conn(pc->self, NULL, E_BAD_COMMAND,
@@ -1131,20 +1133,12 @@ void handle_edit_startpos(struct connection *pc, int x, int y,
     return;
   }
 
-  if (nation == -1) {
-    changed = ptile->editor.startpos_nation_id != -1;
-    ptile->editor.startpos_nation_id = -1;
-  } else {
-    struct nation_type *pnation;
+  old = map_get_startpos(ptile);
 
-    pnation = nation_by_number(nation);
-    if (pnation) {
-      changed = ptile->editor.startpos_nation_id != nation;
-      ptile->editor.startpos_nation_id = nation;
-    }
-  }
+  pnation = nation_by_number(nation);
+  map_set_startpos(ptile, pnation);
 
-  if (changed) {
+  if (old != pnation) {
     send_tile_info(NULL, ptile, FALSE);
   }
 }
diff --git a/server/maphand.c b/server/maphand.c
index bcf5b82..689413e 100644
--- a/server/maphand.c
+++ b/server/maphand.c
@@ -344,6 +344,7 @@ void send_tile_info(struct conn_list *dest, struct tile *ptile,
                     bool send_unknown)
 {
   struct packet_tile_info info;
+  const struct nation_type *pnation;
 
   if (send_tile_suppressed) {
     return;
@@ -362,7 +363,8 @@ void send_tile_info(struct conn_list *dest, struct tile *ptile,
     info.spec_sprite[0] = '\0';
   }
 
-  info.editor_startpos_nation_id = ptile->editor.startpos_nation_id;
+  pnation = map_get_startpos(ptile);
+  info.nation_start = pnation ? nation_number(pnation) : -1;
 
   info.special[S_OLD_FORTRESS] = FALSE;
   info.special[S_OLD_AIRBASE] = FALSE;
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to