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

 I don't know if the crash happens only for observer players, but I
were observing by the time it happened. Reason was that
ptile->city->tile is NULL when fill_city_overlays_sprite_array() calls
city_base_to_city_map().

 From handle_tile_info() it seems that tile->city->tile == NULL is
intentional, and legal, state called 'invisible city'.

 Attached patch should fix the crash (I had no way to reproduce it)


 - ML

diff -Nurd -X.diff_ignore freeciv/client/mapview_common.c freeciv/client/mapview_common.c
--- freeciv/client/mapview_common.c	2008-03-08 16:13:03.000000000 +0200
+++ freeciv/client/mapview_common.c	2008-04-27 00:55:12.000000000 +0300
@@ -1807,7 +1807,7 @@
 
 /**************************************************************************
   Find the "best" city/settlers to associate with the selected tile.
-    a.  If a city is working the tile, return that city.
+    a.  If a visible city is working the tile, return that city.
     b.  If another player's city is working the tile, return NULL.
     c.  If any selected cities are within range, return the closest one.
     d.  If any cities are within range, return the closest one.
@@ -1821,14 +1821,16 @@
 					    struct unit **punit)
 {
   struct city *closest_city;
-  struct city *pcity = tile_worked(ptile);
+  struct city *pcity;
   struct unit *closest_settler = NULL, *best_settler = NULL;
 
   if (punit) {
     *punit = NULL;
   }
 
-  if (pcity) {
+  /* Check if there is visible city working that tile */
+  pcity = tile_worked(ptile);
+  if (pcity && pcity->tile) {
     if (NULL == client.conn.playing
         || city_owner(pcity) == client.conn.playing) {
       /* rule a */
diff -Nurd -X.diff_ignore freeciv/client/packhand.c freeciv/client/packhand.c
--- freeciv/client/packhand.c	2008-04-09 16:29:23.000000000 +0300
+++ freeciv/client/packhand.c	2008-04-27 00:18:18.000000000 +0300
@@ -2189,7 +2189,7 @@
   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);
-  
+
   if (NULL == ptile) {
     freelog(LOG_ERROR,
             "handle_tile_info() invalid tile (%d,%d).",
@@ -2279,6 +2279,9 @@
         }
       }
 
+      /* This marks tile worked by invisible city. Other
+       * parts of the code have to handle invisible cities correctly
+       * (ptile->city->tile == NULL) */
       tile_set_worked(ptile, pwork);
     } else {
       tile_set_worked(ptile, NULL);
diff -Nurd -X.diff_ignore freeciv/client/tilespec.c freeciv/client/tilespec.c
--- freeciv/client/tilespec.c	2008-03-08 16:13:03.000000000 +0200
+++ freeciv/client/tilespec.c	2008-04-27 00:26:58.000000000 +0300
@@ -3618,6 +3618,13 @@
     pcity = find_city_or_settler_near_tile(ptile, &psettler);
   }
 
+  /* Below code does not work if pcity is invisible.
+   * Make sure it is not. */
+  assert(pcity == NULL || pcity->tile != NULL);
+  if (pcity && !pcity->tile) {
+    pcity = NULL;
+  }
+
   if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
     /* FIXME: check elsewhere for valid tile (instead of above) */
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to