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

Attached patch implements a property for viewing and
modifying bases on a tile in the property editor. Thus
also copy/paste mode is made to work for the base tool.
Hence the patch builds on the one in 40569.


Incidentally, just for the sake of putting it out there,
it seems to me that specials and bases are very similar
in how they are handled, at least from the point of view
of the data structures. It might therefore be beneficial
to generalize specials so that they are loaded from the
ruleset sort of like how bases are loaded now. This
would allow consistent handling of these kinds of game
entities (rather than having a separate bitvector for
each of them). Continuing along this line of reasoning,
I don't see why we should not include "resources" in
this group of "meta-specials" as well; a mechanism
similar to unit classes could be used to control whether
more than one is allowed on a single tile. Anyway, that
is just a random idea I had; if anyone cares to comment
or work on it feel free to cut-and-paste this into a new
ticket.


-----------------------------------------------------------------------
オッカムの剃刀の原点をご存知ですか。
 client/editor.c               |   33 +++++++++++++++++++-
 client/gui-gtk-2.0/editprop.c |   66 +++++++++++++++++++++++++++++++++++++++--
 common/packets.def            |    1 +
 server/edithand.c             |   11 +++++++
 4 files changed, 106 insertions(+), 5 deletions(-)

diff --git a/client/editor.c b/client/editor.c
index ac24808..d5b89f8 100644
--- a/client/editor.c
+++ b/client/editor.c
@@ -1486,6 +1486,33 @@ void edit_buffer_copy(struct edit_buffer *ebuf, const struct tile *ptile)
 }
 
 /****************************************************************************
+  Helper function to fill in an edit packet with the tile's current values.
+****************************************************************************/
+static void fill_tile_edit_packet(struct packet_edit_tile *packet,
+                                  const struct tile *ptile)
+{
+  const struct resource *presource;
+  const struct terrain *pterrain;
+  const struct nation_type *pnation;
+
+  if (!packet || !ptile) {
+    return;
+  }
+  packet->id = tile_index(ptile);
+  packet->specials = tile_specials(ptile);
+  packet->bases = tile_bases(ptile);
+
+  presource = tile_resource(ptile);
+  packet->resource = presource ? resource_number(presource) : -1;
+
+  pterrain = tile_terrain(ptile);
+  packet->terrain = pterrain ? terrain_number(pterrain) : -1;
+
+  pnation = map_get_startpos(ptile);
+  packet->startpos_nation = pnation ? nation_number(pnation) : -1;
+}
+
+/****************************************************************************
   Helper function for edit_buffer_paste(). Do a single paste of the stuff set
   in the buffer on the virtual tile to the destination tile 'ptile_dest'.
 ****************************************************************************/
@@ -1522,12 +1549,14 @@ static void paste_tile(struct edit_buffer *ebuf,
       dsend_packet_edit_tile_resource(my_conn, x, y, value, 1);
       break;
     case EBT_SPECIAL:
-      tile_packet.id = tile_index(ptile_dest);
+      fill_tile_edit_packet(&tile_packet, ptile_dest);
       tile_packet.specials = tile_specials(vtile);
       send_packet_edit_tile(my_conn, &tile_packet);
       break;
     case EBT_BASE:
-      /* FIXME: Implement as property and send like specials. */
+      fill_tile_edit_packet(&tile_packet, ptile_dest);
+      tile_packet.bases = tile_bases(vtile);
+      send_packet_edit_tile(my_conn, &tile_packet);
       break;
     case EBT_UNIT:
       unit_list_iterate(vtile->units, vunit) {
diff --git a/client/gui-gtk-2.0/editprop.c b/client/gui-gtk-2.0/editprop.c
index 79a7dd3..b38eb2e 100644
--- a/client/gui-gtk-2.0/editprop.c
+++ b/client/gui-gtk-2.0/editprop.c
@@ -184,6 +184,7 @@ enum value_types {
   VALTYPE_BUILT_ARRAY,        /* struct built_status[B_LAST] */
   VALTYPE_INVENTIONS_ARRAY,   /* bool[A_LAST] */
   VALTYPE_BV_SPECIAL,
+  VALTYPE_BV_BASES,
   VALTYPE_NATION,
   VALTYPE_TILE_VISION_DATA    /* struct tile_vision_data */
 };
@@ -207,6 +208,7 @@ union propval_data {
   GdkPixbuf *v_pixbuf;
   struct built_status *v_built;
   bv_special v_bv_special;
+  bv_bases v_bv_bases;
   struct nation_type *v_nation;
   bool *v_inventions;
   struct tile_vision_data *v_tile_vision;
@@ -281,6 +283,7 @@ enum object_property_ids {
   OPID_TILE_XY,
   OPID_TILE_RESOURCE,
   OPID_TILE_SPECIALS,
+  OPID_TILE_BASES,
   OPID_TILE_VISION, /* tile_known and tile_seen */
 
   OPID_UNIT_IMAGE,
@@ -760,6 +763,9 @@ static const char *valtype_get_name(int valtype)
   case VALTYPE_BV_SPECIAL:
     return "bv_special";
     break;
+  case VALTYPE_BV_BASES:
+    return "bv_bases";
+    break;
   case VALTYPE_NATION:
     return "nation";
     break;
@@ -863,9 +869,6 @@ static int propval_as_string(struct propval *pv, char *buf, int buflen)
 
   case VALTYPE_BV_SPECIAL:
     tile_special_type_iterate(spe) {
-      if (!(0 <= spe && spe < buflen - 1)) {
-        continue;
-      }
       if (BV_ISSET(pv->data.v_bv_special, spe)) {
         count++;
       }
@@ -875,6 +878,15 @@ static int propval_as_string(struct propval *pv, char *buf, int buflen)
     ret = my_snprintf(buf, buflen, _("%d present"), count);
     break;
 
+  case VALTYPE_BV_BASES:
+    base_type_iterate(pbase) {
+      if (BV_ISSET(pv->data.v_bv_bases, base_number(pbase))) {
+        count++;
+      }
+    } base_type_iterate_end;
+    ret = my_snprintf(buf, buflen, _("%d present"), count);
+    break;
+
   default:
     buf[0] = '\0';
     break;
@@ -1095,6 +1107,9 @@ static bool propval_equal(struct propval *pva,
   case VALTYPE_BV_SPECIAL:
     return BV_ARE_EQUAL(pva->data.v_bv_special, pvb->data.v_bv_special);
     break;
+  case VALTYPE_BV_BASES:
+    return BV_ARE_EQUAL(pva->data.v_bv_bases, pvb->data.v_bv_bases);
+    break;
   case VALTYPE_TILE_VISION_DATA:
     if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_known,
                       pvb->data.v_tile_vision->tile_known)) {
@@ -1366,6 +1381,9 @@ static struct propval *objbind_get_value_from_object(struct objbind *ob,
     case OPID_TILE_SPECIALS:
       pv->data.v_bv_special = tile_specials(ptile);
       break;
+    case OPID_TILE_BASES:
+      pv->data.v_bv_bases = tile_bases(ptile);
+      break;
     case OPID_TILE_VISION:
       size = sizeof(struct tile_vision_data);
       pv->data.v_tile_vision = fc_malloc(size);
@@ -1877,6 +1895,7 @@ static void objbind_pack_current_values(struct objbind *ob,
 
     packet->id = tile_index(ptile);
     packet->specials = tile_specials(ptile);
+    packet->bases = tile_bases(ptile);
     /* TODO: Set more packet fields. */
 
   } else if (objtype == OBJTYPE_UNIT) {
@@ -1981,6 +2000,9 @@ static void objbind_pack_modified_value(struct objbind *ob,
     case OPID_TILE_SPECIALS:
       packet->specials = pv->data.v_bv_special;
       break;
+    case OPID_TILE_BASES:
+      packet->bases = pv->data.v_bv_bases;
+      break;
     default:
       freelog(LOG_ERROR, "Unhandled request to pack value of "
               "property %d (%s) from object of type \"%s\" in "
@@ -2141,6 +2163,7 @@ static GType objprop_get_gtype(const struct objprop *op)
   case VALTYPE_BUILT_ARRAY:
   case VALTYPE_INVENTIONS_ARRAY:
   case VALTYPE_BV_SPECIAL:
+  case VALTYPE_BV_BASES:
     return G_TYPE_STRING;
     break;
   case VALTYPE_PIXBUF:
@@ -2453,6 +2476,7 @@ static void objprop_setup_widget(struct objprop *op)
     break;
 
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
   case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_NATION:
@@ -2640,6 +2664,7 @@ static void objprop_refresh_widget(struct objprop *op,
     break;
 
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
   case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_NATION:
@@ -2838,6 +2863,7 @@ static struct extviewer *extviewer_new(struct objprop *op)
 
   switch (propid) {
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_INVENTIONS:
     hbox = gtk_hbox_new(FALSE, 4);
@@ -2898,6 +2924,7 @@ static struct extviewer *extviewer_new(struct objprop *op)
 
   switch (propid) {
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
   case OPID_PLAYER_INVENTIONS:
     store = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_INT,
                                G_TYPE_STRING);
@@ -2964,6 +2991,7 @@ static struct extviewer *extviewer_new(struct objprop *op)
   switch (propid) {
 
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
     /* TRANS: As in "this tile special is present". */
     add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
                G_CALLBACK(extviewer_view_cell_toggled), ev);
@@ -3120,6 +3148,19 @@ static void extviewer_refresh_widgets(struct extviewer *ev,
     gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
     break;
 
+  case OPID_TILE_BASES:
+    gtk_list_store_clear(store);
+    base_type_iterate(pbase) {
+      id = base_number(pbase);
+      name = base_name_translation(pbase);
+      present = BV_ISSET(pv->data.v_bv_bases, id);
+      gtk_list_store_append(store, &iter);
+      gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
+    } base_type_iterate_end;
+    propval_as_string(pv, buf, sizeof(buf));
+    gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
+    break;
+
   case OPID_TILE_VISION:
     gtk_list_store_clear(store);
     player_slots_iterate(pslot) {
@@ -3232,6 +3273,7 @@ static void extviewer_clear_widgets(struct extviewer *ev)
 
   switch (propid) {
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_BASES:
   case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_INVENTIONS:
@@ -3332,6 +3374,21 @@ static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell,
     gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
     break;
 
+  case OPID_TILE_BASES:
+    gtk_tree_model_get(model, &iter, 1, &id, -1);
+    if (!(0 <= id && id < base_count())) {
+      return;
+    }
+    if (present) {
+      BV_SET(pv->data.v_bv_bases, id);
+    } else {
+      BV_CLR(pv->data.v_bv_bases, id);
+    }
+    gtk_list_store_set(ev->store, &iter, 0, present, -1);
+    propval_as_string(pv, buf, sizeof(buf));
+    gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
+    break;
+
   case OPID_CITY_BUILDINGS:
     gtk_tree_model_get(model, &iter, 1, &id, -1);
     if (!(0 <= id && id < B_LAST)) {
@@ -3424,6 +3481,8 @@ static void property_page_setup_objprops(struct property_page *pp)
             OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
     ADDPROP(OPID_TILE_SPECIALS, _("Specials"), OPF_IN_LISTVIEW
             | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BV_SPECIAL);
+    ADDPROP(OPID_TILE_BASES, _("Bases"), OPF_IN_LISTVIEW
+            | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BV_BASES);
     ADDPROP(OPID_TILE_ADDRESS, _("Address"),
             OPF_HAS_WIDGET, VALTYPE_STRING);
     ADDPROP(OPID_TILE_VISION, _("Vision"),
@@ -4077,6 +4136,7 @@ static bool property_page_set_store_value(struct property_page *pp,
   case VALTYPE_BUILT_ARRAY:
   case VALTYPE_INVENTIONS_ARRAY:
   case VALTYPE_BV_SPECIAL:
+  case VALTYPE_BV_BASES:
     propval_as_string(pv, buf, sizeof(buf));
     gtk_list_store_set(pp->object_store, iter, col_id, buf, -1);
     break;
diff --git a/common/packets.def b/common/packets.def
index fdbfea1..9ae94da 100644
--- a/common/packets.def
+++ b/common/packets.def
@@ -1484,6 +1484,7 @@ end
 PACKET_EDIT_TILE=160;cs,handle-per-conn,handle-via-packet
   UNIT id; key
   BV_SPECIAL specials;
+  BV_BASES bases;
   RESOURCE resource;
   TERRAIN terrain;
   NATION startpos_nation;
diff --git a/server/edithand.c b/server/edithand.c
index 7508342..e040b58 100644
--- a/server/edithand.c
+++ b/server/edithand.c
@@ -387,6 +387,17 @@ void handle_edit_tile(struct connection *pc,
     changed = TRUE;
   }
 
+  /* Handle changes in bases. */
+  if (!(BV_ARE_EQUAL(packet->bases, ptile->bases))) {
+    base_type_iterate(pbase) {
+      if (BV_ISSET(packet->bases, base_number(pbase))) {
+        tile_add_base(ptile, pbase);
+      } else {
+        tile_remove_base(ptile, pbase);
+      }
+    } base_type_iterate_end;
+    changed = TRUE;
+  }
 
   /* TODO: Handle more property edits. */
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to