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

Patch implements the "game" object type and one of its
editable properties, 'year', in the property editor system.

There are also two changes outside the editor code; the
first is a call to update_info_label() in handle_game_info
in the client. This is so that the 'year' label is properly
updated when the server sends back the result of modifying
the 'year' property.

The second change is that the minimum and maximum endyear
setting values were changed to -32768 and 32767 respectively.

I think it might be a good idea anyway to change the 'year'
variable to a signed int. That way mod/scenario authors
could for example make a dinosaur scenario in 300,000,000 BC,
or a scenario about the awakening of some "settlers" frozen
in stasis for 2 billion years. :)


----------------------------------------------------------------------
麻薬の使用はどうですか。
 client/editor.h               |    1 +
 client/gui-gtk-2.0/editgui.c  |    3 +-
 client/gui-gtk-2.0/editprop.c |  116 +++++++++++++++++++++++++++++++++++++---
 client/gui-gtk-2.0/editprop.h |    2 +-
 client/packhand.c             |    6 ++
 common/game.h                 |    4 +-
 common/packets.def            |    6 ++-
 server/edithand.c             |   35 ++++++++++++
 8 files changed, 159 insertions(+), 14 deletions(-)

diff --git a/client/editor.h b/client/editor.h
index 7dc520f..43e5201 100644
--- a/client/editor.h
+++ b/client/editor.h
@@ -23,6 +23,7 @@ enum editor_object_type {
   OBJTYPE_UNIT,
   OBJTYPE_CITY,
   OBJTYPE_PLAYER,
+  OBJTYPE_GAME,
   
   NUM_OBJTYPES
 };
diff --git a/client/gui-gtk-2.0/editgui.c b/client/gui-gtk-2.0/editgui.c
index ca1b987..9cf03f6 100644
--- a/client/gui-gtk-2.0/editgui.c
+++ b/client/gui-gtk-2.0/editgui.c
@@ -396,7 +396,8 @@ static void editbar_player_properties_button_clicked(GtkButton *b,
   }
 
   pe = editprop_get_property_editor();
-  property_editor_reload_players(pe);
+  property_editor_reload(pe, OBJTYPE_GAME);
+  property_editor_reload(pe, OBJTYPE_PLAYER);
   property_editor_popup(pe);
 }
 
diff --git a/client/gui-gtk-2.0/editprop.c b/client/gui-gtk-2.0/editprop.c
index bf3c71d..67d6012 100644
--- a/client/gui-gtk-2.0/editprop.c
+++ b/client/gui-gtk-2.0/editprop.c
@@ -78,6 +78,7 @@ union packetdata {
   struct packet_edit_city *city;
   struct packet_edit_unit *unit;
   struct packet_edit_player *player;
+  struct packet_edit_game *game;
 };
 
 
@@ -251,7 +252,9 @@ enum object_property_ids {
   OPID_PLAYER_NAME,
   OPID_PLAYER_NATION,
   OPID_PLAYER_ADDRESS,
-  OPID_PLAYER_INVENTIONS
+  OPID_PLAYER_INVENTIONS,
+
+  OPID_GAME_YEAR
 };
 
 enum object_property_flags {
@@ -524,6 +527,10 @@ static const char *objtype_get_name(int objtype)
     return _("Player");
     break;
 
+  case OBJTYPE_GAME:
+    return Q_("?play:Game");
+    break;
+
   default:
     break;
   }
@@ -565,6 +572,10 @@ static int objtype_get_id_from_object(int objtype, gpointer object)
     id = player_number(pplayer);
     break;
 
+  case OBJTYPE_GAME:
+    id = 1;
+    break;
+
   default:
     break;
   }
@@ -1040,6 +1051,9 @@ static gpointer objbind_get_object(struct objbind *ob)
   case OBJTYPE_PLAYER:
     return valid_player_by_number(id);
     break;
+  case OBJTYPE_GAME:
+    return &game;
+    break;
   default:
     break;
   }
@@ -1255,6 +1269,26 @@ static struct propval *objbind_get_value_from_object(struct objbind *ob,
       goto FAILED;
       break;
     }
+
+  } else if (objtype == OBJTYPE_GAME) {
+    struct civ_game *pgame = objbind_get_object(ob);
+
+    if (pgame == NULL) {
+      goto FAILED;
+    }
+
+    switch (propid) {
+    case OPID_GAME_YEAR:
+      pv->data.v_int = pgame->info.year;
+      break;
+    default:
+      freelog(LOG_ERROR, "Unhandled request for value of property %d "
+              "(%s) from object of type \"%s\" in "
+              "objbind_get_value_from_object().",
+              propid, objprop_get_name(op), objtype_get_name(objtype));
+      goto FAILED;
+      break;
+    }
   } else {
     goto FAILED;
   }
@@ -1346,6 +1380,25 @@ static bool objbind_get_allowed_value_span(struct objbind *ob,
       ok = FALSE;
       break;
     }
+
+  } else if (objtype == OBJTYPE_GAME) {
+
+    switch (propid) {
+    case OPID_GAME_YEAR:
+      min = -30000;
+      max = 30000;
+      step = 1;
+      big_step = 25;
+      break;
+    default:
+      freelog(LOG_ERROR, "Unhandled request for value range of "
+              "property %d (%s) from object of type \"%s\" in "
+              "objbind_get_allowed_value_span().",
+              propid, objprop_get_name(op), objtype_get_name(objtype));
+      ok = FALSE;
+      break;
+    }
+
   } else {
     ok = FALSE;
   }
@@ -1620,6 +1673,16 @@ static void objbind_pack_current_values(struct objbind *ob,
     } advance_index_iterate_end;
     /* TODO: Set more packet fields. */
 
+  } else if (objtype == OBJTYPE_GAME) {
+    struct packet_edit_game *packet = pd.game;
+    struct civ_game *pgame = objbind_get_object(ob);
+
+    if (!pgame) {
+      return;
+    }
+
+    packet->year = pgame->info.year;
+    /* TODO: Set more packet fields. */
   }
 }
 
@@ -1744,6 +1807,21 @@ static void objbind_pack_modified_value(struct objbind *ob,
               propid, objprop_get_name(op), objtype_get_name(objtype));
       break;
     }
+
+  } else if (objtype == OBJTYPE_GAME) {
+    struct packet_edit_game *packet = pd.game;
+
+    switch (propid) {
+    case OPID_GAME_YEAR:
+      packet->year = pv->data.v_int;
+      break;
+    default:
+      freelog(LOG_ERROR, "Unhandled request to pack value of "
+              "property %d (%s) from object of type \"%s\" in "
+              "objbind_pack_modified_value().",
+              propid, objprop_get_name(op), objtype_get_name(objtype));
+      break;
+    }
   }
 }
 
@@ -2062,6 +2140,7 @@ static void objprop_setup_widget(struct objprop *op)
     break;
 
   case OPID_CITY_SIZE:
+  case OPID_GAME_YEAR:
     spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
     g_signal_connect(spin, "value-changed",
                      G_CALLBACK(objprop_widget_spin_button_changed), op);
@@ -2224,6 +2303,7 @@ static void objprop_refresh_widget(struct objprop *op,
     break;
 
   case OPID_CITY_SIZE:
+  case OPID_GAME_YEAR:
     spin = objprop_get_child_widget(op, "spin");
     if (pv) {
       disable_widget_callback(spin,
@@ -3030,6 +3110,11 @@ static void property_page_setup_objprops(struct property_page *pp)
             | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INVENTIONS_ARRAY);
     break;
 
+  case OBJTYPE_GAME:
+    ADDPROP(OPID_GAME_YEAR, _("Year"), OPF_IN_LISTVIEW
+            | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
+    break;
+
   default:
     break;
   }
@@ -3842,6 +3927,9 @@ static union packetdata property_page_new_packet(struct property_page *pp)
   case OBJTYPE_PLAYER:
     packet.player = fc_calloc(1, sizeof(*packet.player));
     break;
+  case OBJTYPE_GAME:
+    packet.game = fc_calloc(1, sizeof(*packet.game));
+    break;
   default:
     break;
   }
@@ -3872,6 +3960,9 @@ static void property_page_send_packet(struct property_page *pp,
   case OBJTYPE_PLAYER:
     send_packet_edit_player(&client.conn, packet.player);
     break;
+  case OBJTYPE_GAME:
+    send_packet_edit_game(&client.conn, packet.game);
+    break;
   default:
     break;
   }
@@ -4327,19 +4418,17 @@ void property_editor_clear(struct property_editor *pe)
 }
 
 /****************************************************************************
-  Clear the player property page, load the current game players into it, and
-  make it the current shown notebook page.
+  Clear and load objects into the property page corresponding to the given
+  object type. Also, make it the current shown notebook page.
 ****************************************************************************/
-void property_editor_reload_players(struct property_editor *pe)
+void property_editor_reload(struct property_editor *pe, int objtype)
 {
-  int objtype;
   struct property_page *pp;
 
   if (!pe) {
     return;
   }
 
-  objtype = OBJTYPE_PLAYER;
   pp = pe->property_pages[objtype];
   if (!pp) {
     return;
@@ -4347,9 +4436,18 @@ void property_editor_reload_players(struct property_editor *pe)
 
   property_page_clear_objbinds(pp);
 
-  players_iterate(pplayer) {
-    property_page_add_objbind(pp, pplayer);
-  } players_iterate_end;
+  switch (objtype) {
+  case OBJTYPE_PLAYER:
+    players_iterate(pplayer) {
+      property_page_add_objbind(pp, pplayer);
+    } players_iterate_end;
+    break;
+  case OBJTYPE_GAME:
+    property_page_add_objbind(pp, &game);
+    break;
+  default:
+    break;
+  }
 
   property_page_fill_widgets(pp);
   gtk_notebook_set_current_page(GTK_NOTEBOOK(pe->notebook), objtype);
diff --git a/client/gui-gtk-2.0/editprop.h b/client/gui-gtk-2.0/editprop.h
index 5910c8a..4a50721 100644
--- a/client/gui-gtk-2.0/editprop.h
+++ b/client/gui-gtk-2.0/editprop.h
@@ -21,7 +21,7 @@ struct property_editor;
 void property_editor_clear(struct property_editor *pe);
 void property_editor_load_tiles(struct property_editor *pe,
                                 const struct tile_list *tiles);
-void property_editor_reload_players(struct property_editor *pe);
+void property_editor_reload(struct property_editor *pe, int objtype);
 void property_editor_popup(struct property_editor *pe);
 void property_editor_popdown(struct property_editor *pe);
 void property_editor_handle_object_changed(struct property_editor *pe,
diff --git a/client/packhand.c b/client/packhand.c
index 9b24389..b5a180d 100644
--- a/client/packhand.c
+++ b/client/packhand.c
@@ -1613,6 +1613,12 @@ void handle_game_info(struct packet_game_info *pinfo)
   if (update_aifill_button) {
     update_start_page();
   }
+  
+  if (can_client_change_view()) {
+    update_info_label();
+  }
+
+  editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
 }
 
 /**************************************************************************
diff --git a/common/game.h b/common/game.h
index ba18102..d05ae96 100644
--- a/common/game.h
+++ b/common/game.h
@@ -168,8 +168,8 @@ bool setting_class_is_changeable(enum sset_class class);
 #define GAME_DEFAULT_ANGRYCITIZEN TRUE
 
 #define GAME_DEFAULT_END_YEAR    5000
-#define GAME_MIN_END_YEAR        GAME_START_YEAR
-#define GAME_MAX_END_YEAR        5000
+#define GAME_MIN_END_YEAR        -32768
+#define GAME_MAX_END_YEAR        32767
 
 #define GAME_DEFAULT_MIN_PLAYERS     1
 #define GAME_MIN_MIN_PLAYERS         0
diff --git a/common/packets.def b/common/packets.def
index 8cdbe0e..a0e0f45 100644
--- a/common/packets.def
+++ b/common/packets.def
@@ -1593,10 +1593,14 @@ PACKET_EDIT_PLAYER=168;cs,handle-per-conn,lsend
   BOOL ai;
 end
 
+PACKET_EDIT_GAME=169;cs,handle-per-conn,handle-via-packet
+  YEAR year;
+end
+
 /* Always keep this as the last edit type packet,
  * so that the test in server/srv_main.c +1203
  * is easy to write. */
-PACKET_EDIT_PLAYER_VISION=169;cs,handle-per-conn,dsend
+PACKET_EDIT_PLAYER_VISION=170;cs,handle-per-conn,dsend
   PLAYER player;
   COORD x, y;
   BOOL known;
diff --git a/server/edithand.c b/server/edithand.c
index e6f7e6f..f87772e 100644
--- a/server/edithand.c
+++ b/server/edithand.c
@@ -1111,3 +1111,38 @@ void handle_edit_startpos(struct connection *pc, int x, int y,
     send_tile_info(NULL, ptile, FALSE);
   }
 }
+
+/****************************************************************************
+  Handle edit requests to the main game data structure.
+****************************************************************************/
+void handle_edit_game(struct connection *pc,
+                      struct packet_edit_game *packet)
+{
+  bool changed = FALSE;
+
+  if (!can_conn_edit(pc)) {
+    notify_conn(pc->self, NULL, E_BAD_COMMAND,
+                _("You are not allowed to edit."));
+    return;
+  }
+
+  if (packet->year != game.info.year) {
+
+    /* 'year' is stored in a signed short. */
+    const short min_year = -30000, max_year = 30000;
+
+    if (!(min_year <= packet->year && packet->year <= max_year)) {
+      notify_conn(pc->self, NULL, E_BAD_COMMAND,
+                  _("Cannot set invalid game year %d. Valid year range "
+                    "is from %d to %d."),
+                  packet->year, min_year, max_year);
+    } else {
+      game.info.year = packet->year;
+      changed = TRUE;
+    }
+  }
+
+  if (changed) {
+    send_game_info(NULL);
+  }
+}
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to