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

The current game state is very fragile.  It depends on client and server
packets arriving in the correct order, and scattered checks for correct
state.  Rather than a formal finite state machine, the game has an ad hoc
dichotomy between the client and server.

The "client" state values were sent across the network (and actually are
the server state).  The "server" state values are saved in savegames,
although the values are usually replaced and/or ignored upon loading....

This patch stops sending game state as a packet.  Each client derives its
own current state from the packet events independently.

(Amazingly, now that old unused state values can be discarded, the
client_states and server_states have the same values in parallel....)

Also, send_game_state() had special processing to clear the delta values
sent across the network.  (PR#7085 & 7216)  This patch clears the delta
values with send_ruleset_control() instead, because that better matches
client/packhand.c clearing the rulesets for each game!

Because the client_states are no longer in game.h, and game.h is not
needed in civclient.h, fix a significant number of missing game.h and
specialist.h #includes.  They always should have been there!

Index: version.in
===================================================================
--- version.in  (revision 14141)
+++ version.in  (working copy)
@@ -23,4 +23,4 @@
 #   - Avoid adding a new mandatory capbility to the development branch for
 #     as long as possible.  We want to maintain network compatibility with
 #     the stable branch for as long as possible.
-NETWORK_CAPSTRING="+Freeciv.Devel.2007.Nov.01"
+NETWORK_CAPSTRING="+Freeciv.Devel.2007.Dec.07"
Index: server/cityhand.c
===================================================================
--- server/cityhand.c   (revision 14141)
+++ server/cityhand.c   (working copy)
@@ -29,6 +29,7 @@
 #include "map.h"
 #include "player.h"
 #include "rand.h"
+#include "specialist.h"
 #include "support.h"
 #include "unit.h"
 #include "worklist.h"
Index: server/score.c
===================================================================
--- server/score.c      (revision 14141)
+++ server/score.c      (working copy)
@@ -26,6 +26,7 @@
 #include "improvement.h"
 #include "map.h"
 #include "player.h"
+#include "specialist.h"
 #include "unit.h"
 #include "unitlist.h"
 
Index: server/srv_main.c
===================================================================
--- server/srv_main.c   (revision 14141)
+++ server/srv_main.c   (working copy)
@@ -640,7 +640,7 @@
   } phase_players_iterate_end;
   send_player_info(NULL, NULL);
 
-  send_start_phase_to_clients();
+  dlsend_packet_start_phase(game.est_connections, game.info.phase);
 
   if (is_new_phase) {
     /* Unit "end of turn" activities - of course these actually go at
@@ -1921,7 +1921,6 @@
     calc_civ_score(pplayer);
   } players_iterate_end;
 
-  send_game_state(game.est_connections, C_S_OVER);
   report_final_scores();
   show_map_to_all();
   notify_player(NULL, NULL, E_GAME_END, _("The game is over..."));
@@ -2079,8 +2078,6 @@
   if (game.info.is_new_game) {
     init_new_game();
   }
-
-  send_game_state(game.est_connections, C_S_RUNNING);
 }
 
 /**************************************************************************
Index: server/connecthand.c
===================================================================
--- server/connecthand.c        (revision 14141)
+++ server/connecthand.c        (working copy)
@@ -117,7 +117,6 @@
        * See the comment in lost_connection_to_client(). */
       send_packet_freeze_hint(pconn);
       send_all_info(dest);
-      send_game_state(dest, C_S_RUNNING);
       send_player_info(NULL,NULL);
       send_diplomatic_meetings(pconn);
       send_packet_thaw_hint(pconn);
Index: server/citytools.c
===================================================================
--- server/citytools.c  (revision 14141)
+++ server/citytools.c  (working copy)
@@ -37,6 +37,7 @@
 #include "movement.h"
 #include "player.h"
 #include "requirements.h"
+#include "specialist.h"
 #include "tech.h"
 #include "unit.h"
 #include "unitlist.h"
Index: server/report.c
===================================================================
--- server/report.c     (revision 14141)
+++ server/report.c     (working copy)
@@ -31,8 +31,9 @@
 #include "government.h"
 #include "packets.h"
 #include "player.h"
+#include "specialist.h"
+#include "unitlist.h"
 #include "version.h"
-#include "unitlist.h"
 
 #include "citytools.h"
 #include "report.h"
@@ -1074,6 +1075,7 @@
 
 /**************************************************************************
   Inform clients about player scores and statistics when the game ends.
+  Called only from server/srv_main.c srv_scores()
 **************************************************************************/
 void report_final_scores(void)
 {
Index: server/cityturn.c
===================================================================
--- server/cityturn.c   (revision 14141)
+++ server/cityturn.c   (working copy)
@@ -33,6 +33,7 @@
 #include "government.h"
 #include "map.h"
 #include "player.h"
+#include "specialist.h"
 #include "tech.h"
 #include "unit.h"
 #include "unitlist.h"
Index: server/ruleset.c
===================================================================
--- server/ruleset.c    (revision 14141)
+++ server/ruleset.c    (working copy)
@@ -36,6 +36,7 @@
 #include "registry.h"
 #include "requirements.h"
 #include "shared.h"
+#include "specialist.h"
 #include "support.h"
 #include "tech.h"
 #include "unit.h"
Index: server/gamehand.c
===================================================================
--- server/gamehand.c   (revision 14141)
+++ server/gamehand.c   (working copy)
@@ -330,16 +330,6 @@
 }
 
 /**************************************************************************
-  This is called once at the start of each phase to alert the clients to
-  the new phase.  game.info.phase should be incremented before calling it.
-**************************************************************************/
-void send_start_phase_to_clients(void)
-{
-  /* This function is so simple it could probably be dropped... */
-  dlsend_packet_start_phase(game.est_connections, game.info.phase);
-}
-
-/**************************************************************************
   Tell clients the year, and also update turn_done and nturns_idle fields
   for all players.
 **************************************************************************/
@@ -360,18 +350,7 @@
                 textyear(year));
 }
 
-
 /**************************************************************************
-  Send specified state; should be a CLIENT_GAME_*_STATE ?
-  (But note client also changes state from other events.)
-**************************************************************************/
-void send_game_state(struct conn_list *dest, int state)
-{
-  dlsend_packet_game_state(dest, state);
-}
-
-
-/**************************************************************************
   Send game_info packet; some server options and various stuff...
   dest==NULL means game.est_connections
 
Index: server/gamehand.h
===================================================================
--- server/gamehand.h   (revision 14141)
+++ server/gamehand.h   (working copy)
@@ -20,8 +20,6 @@
 void init_new_game(void);
 void send_year_to_clients(int year);
 void send_game_info(struct conn_list *dest);
-void send_game_state(struct conn_list *dest, int state);
-void send_start_phase_to_clients(void);
 
 struct unit_type *crole_to_unit_type(char crole,struct player *pplayer);
 
Index: server/sanitycheck.c
===================================================================
--- server/sanitycheck.c        (revision 14141)
+++ server/sanitycheck.c        (working copy)
@@ -25,6 +25,7 @@
 #include "map.h"
 #include "movement.h"
 #include "player.h"
+#include "specialist.h"
 #include "terrain.h"
 #include "unit.h"
 #include "unitlist.h"
Index: server/unithand.c
===================================================================
--- server/unithand.c   (revision 14141)
+++ server/unithand.c   (working copy)
@@ -34,6 +34,7 @@
 #include "movement.h"
 #include "packets.h"
 #include "player.h"
+#include "specialist.h"
 #include "unit.h"
 #include "unitlist.h"
 
Index: server/stdinhand.c
===================================================================
--- server/stdinhand.c  (revision 14141)
+++ server/stdinhand.c  (working copy)
@@ -2842,7 +2842,6 @@
   if (S_S_RUNNING == server_state()) {
     send_packet_freeze_hint(pconn);
     send_all_info(pconn->self);
-    send_game_state(pconn->self, C_S_RUNNING);
     send_player_info(NULL, NULL);
     send_diplomatic_meetings(pconn);
     send_packet_thaw_hint(pconn);
@@ -2945,7 +2944,6 @@
 
   /* if we want to switch players, reset the client if the game is running */
   if (S_S_RUNNING == server_state()) {
-    send_game_state(pconn->self, C_S_PREPARING);
     send_rulesets(pconn->self);
     send_server_settings(pconn->self);
     send_player_info_c(NULL, pconn->self);
@@ -2958,7 +2956,6 @@
     conn_list_iterate(pplayer->connections, aconn) {
       if (!aconn->observer) {
        if (S_S_RUNNING == server_state()) {
-         send_game_state(aconn->self, C_S_PREPARING);
          send_rulesets(aconn->self);
          send_server_settings(aconn->self);
        }
@@ -3011,7 +3008,6 @@
   if (S_S_RUNNING == server_state()) {
     send_packet_freeze_hint(pconn);
     send_all_info(pconn->self);
-    send_game_state(pconn->self, C_S_RUNNING);
     send_player_info(NULL, NULL);
     send_diplomatic_meetings(pconn);
     send_packet_thaw_hint(pconn);
@@ -3099,7 +3095,6 @@
 
   /* if we want to detach while the game is running, reset the client */
   if (S_S_RUNNING == server_state()) {
-    send_game_state(pconn->self, C_S_PREPARING);
     send_rulesets(pconn->self);
     send_server_settings(pconn->self);
     send_game_info(pconn->self);
Index: server/savegame.c
===================================================================
--- server/savegame.c   (revision 14141)
+++ server/savegame.c   (working copy)
@@ -36,6 +36,7 @@
 #include "idex.h"
 #include "map.h"
 #include "movement.h"
+#include "specialist.h"
 #include "unit.h"
 #include "unitlist.h"
 #include "version.h"
Index: common/packets.h
===================================================================
--- common/packets.h    (revision 14141)
+++ common/packets.h    (working copy)
@@ -92,10 +92,10 @@
 void pre_send_packet_player_attribute_chunk(struct connection *pc,
                                            struct packet_player_attribute_chunk
                                            *packet);
-void post_receive_packet_game_state(struct connection *pc,
-                                   struct packet_game_state *packet);
-void post_send_packet_game_state(struct connection *pc,
-                                const struct packet_game_state *packet);
+void post_receive_packet_ruleset_control(struct connection *pc,
+                                        struct packet_ruleset_control *packet);
+void post_send_packet_ruleset_control(struct connection *pc,
+                                     const struct packet_ruleset_control 
*packet);
 
 #define SEND_PACKET_START(type) \
   unsigned char buffer[MAX_LEN_PACKET]; \
Index: common/packets.def
===================================================================
--- common/packets.def  (revision 14141)
+++ common/packets.def  (working copy)
@@ -316,9 +316,7 @@
   BOOL is_ready;
 end
 
-PACKET_GAME_STATE=12;post-send,post-recv,sc,dsend,lsend
-  UINT32 value;
-end
+# 12 removed in 2.2
 
 PACKET_ENDGAME_REPORT=13;sc,lsend
   UINT8 nscores;
@@ -1306,15 +1304,13 @@
   BV_BASE_FLAGS flags;
 end
 
-/*********************************************************
-  Ruleset control values: single values, some of which are
-  needed before sending other ruleset data (eg,
-  num_unit_types, government_count).  This is only sent
-  once at the start of the game, eg unlike game_info which
-  is sent again each turn.  (Terrain ruleset has enough
-  info for its own "control" packet, done separately.)
-*********************************************************/
-PACKET_RULESET_CONTROL=106;sc,lsend
+/**************************************************************************
+  Ruleset control values: single values, all of which are needed before
+  sending other ruleset data.  After sending this packet, resend every
+  other part of the rulesets.  (Terrain ruleset has enough info for its
+  own "control" packet, done separately.)
+**************************************************************************/
+PACKET_RULESET_CONTROL=106; sc, post-send, post-recv, lsend
   UINT8 num_unit_classes;
   UINT8 num_unit_types;
   UINT8 num_impr_types;
Index: common/city.c
===================================================================
--- common/city.c       (revision 14141)
+++ common/city.c       (working copy)
@@ -32,6 +32,7 @@
 #include "mem.h"
 #include "movement.h"
 #include "packets.h"
+#include "specialist.h"
 #include "unit.h"
 
 #include "cm.h"
Index: common/aicore/cm.c
===================================================================
--- common/aicore/cm.c  (revision 14141)
+++ common/aicore/cm.c  (working copy)
@@ -29,6 +29,7 @@
 #include "map.h"
 #include "mem.h"
 #include "shared.h"
+#include "specialist.h"
 #include "support.h"
 #include "timing.h"
 
Index: common/game.c
===================================================================
--- common/game.c       (revision 14141)
+++ common/game.c       (working copy)
@@ -34,6 +34,7 @@
 #include "player.h"
 #include "shared.h"
 #include "spaceship.h"
+#include "specialist.h"
 #include "support.h"
 #include "tech.h"
 #include "unit.h"
Index: common/game.h
===================================================================
--- common/game.h       (revision 14141)
+++ common/game.h       (working copy)
@@ -26,7 +26,6 @@
 #include "fc_types.h"
 #include "player.h"
 #include "packets.h"
-#include "specialist.h"
 
 enum debug_globals {
   DEBUG_FERRIES,
@@ -41,15 +40,6 @@
   S_S_OVER = 3,
 };
 
-/* used in network values */
-enum client_states { 
-  C_S_INITIAL = 0,
-  C_S_PREPARING = 1,
-  C_S_STARTING_UNUSED = 2,
-  C_S_RUNNING = 3,
-  C_S_OVER = 4,
-};
-
 #define CONTAMINATION_POLLUTION 1
 #define CONTAMINATION_FALLOUT   2
 
Index: common/requirements.c
===================================================================
--- common/requirements.c       (revision 14141)
+++ common/requirements.c       (working copy)
@@ -24,6 +24,8 @@
 #include "government.h"
 #include "improvement.h"
 #include "map.h"
+#include "specialist.h"
+
 #include "requirements.h"
 
 /* Names of source types.  These must correspond to enum universals_n in
Index: common/packets.c
===================================================================
--- common/packets.c    (revision 14141)
+++ common/packets.c    (working copy)
@@ -720,8 +720,8 @@
 /**************************************************************************
   ...
 **************************************************************************/
-void post_receive_packet_game_state(struct connection *pc,
-                                   struct packet_game_state *packet)
+void post_receive_packet_ruleset_control(struct connection *pc,
+                                        struct packet_ruleset_control *packet)
 {
   conn_clear_packet_cache(pc);
 }
@@ -729,8 +729,8 @@
 /**************************************************************************
   ...
 **************************************************************************/
-void post_send_packet_game_state(struct connection *pc,
-                                const struct packet_game_state *packet)
+void post_send_packet_ruleset_control(struct connection *pc,
+                                     const struct packet_ruleset_control 
*packet)
 {
   conn_clear_packet_cache(pc);
 }
Index: ai/aicity.c
===================================================================
--- ai/aicity.c (revision 14141)
+++ ai/aicity.c (working copy)
@@ -33,6 +33,7 @@
 #include "player.h"
 #include "rand.h"
 #include "shared.h"
+#include "specialist.h"
 #include "support.h"
 #include "unit.h"
 #include "unitlist.h"
Index: client/agents/cma_core.c
===================================================================
--- client/agents/cma_core.c    (revision 14141)
+++ client/agents/cma_core.c    (working copy)
@@ -25,12 +25,14 @@
 #include "dataio.h"
 #include "events.h"
 #include "fcintl.h"
+#include "game.h"
 #include "government.h"
 #include "hash.h"
 #include "log.h"
 #include "mem.h"
 #include "packets.h"
 #include "shared.h"            /* for MIN() */
+#include "specialist.h"
 #include "support.h"
 #include "timing.h"
 
Index: client/agents/cma_fec.c
===================================================================
--- client/agents/cma_fec.c     (revision 14141)
+++ client/agents/cma_fec.c     (working copy)
@@ -27,6 +27,7 @@
 #include "game.h"
 #include "log.h"
 #include "mem.h"
+#include "specialist.h"
 #include "support.h"
 
 #include "agents.h"
Index: client/citydlg_common.c
===================================================================
--- client/citydlg_common.c     (revision 14141)
+++ client/citydlg_common.c     (working copy)
@@ -22,6 +22,8 @@
 #include "support.h"
 
 #include "city.h"
+#include "game.h"
+#include "specialist.h"
 #include "unitlist.h"
 
 #include "citydlg_g.h"
Index: client/cityrepdata.c
===================================================================
--- client/cityrepdata.c        (revision 14141)
+++ client/cityrepdata.c        (working copy)
@@ -25,6 +25,7 @@
 #include "city.h"
 #include "game.h"
 #include "map.h"
+#include "specialist.h"
 #include "unitlist.h"
 
 #include "cma_fec.h"
Index: client/overview_common.c
===================================================================
--- client/overview_common.c    (revision 14141)
+++ client/overview_common.c    (working copy)
@@ -15,6 +15,7 @@
 #include <config.h>
 #endif
 
+#include "game.h"
 #include "log.h"
 
 #include "civclient.h" /* can_client_change_view() */
Index: client/control.c
===================================================================
--- client/control.c    (revision 14141)
+++ client/control.c    (working copy)
@@ -22,6 +22,7 @@
 #include "mem.h"
 #include "timing.h"
 
+#include "game.h"
 #include "map.h"
 #include "movement.h"
 
Index: client/gui-gtk-2.0/menu.c
===================================================================
--- client/gui-gtk-2.0/menu.c   (revision 14141)
+++ client/gui-gtk-2.0/menu.c   (working copy)
@@ -24,6 +24,8 @@
 #include "astring.h"
 #include "fcintl.h"
 #include "log.h"
+
+#include "game.h"
 #include "government.h"
 #include "map.h"
 #include "mem.h"
Index: client/text.c
===================================================================
--- client/text.c       (revision 14141)
+++ client/text.c       (working copy)
@@ -25,6 +25,7 @@
 #include "support.h"
 
 #include "combat.h"
+#include "game.h"
 #include "government.h"
 #include "map.h"
 #include "unitlist.h"
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 14141)
+++ client/packhand.c   (working copy)
@@ -32,6 +32,7 @@
 #include "packets.h"
 #include "player.h"
 #include "spaceship.h"
+#include "specialist.h"
 #include "support.h"
 #include "unit.h"
 #include "unitlist.h"
@@ -354,10 +355,9 @@
 }
 
 /****************************************************************************
-  Handles a game-state packet from the server.  The server sends these to
-  us regularly to inform the client of state changes.
+  Updates the client_state due to packets from the server.
 ****************************************************************************/
-void handle_game_state(int value)
+static void update_client_state(enum client_states value)
 {
   bool changed = (client_state() != value);
 
@@ -898,6 +898,8 @@
     return;
   }
 
+  update_client_state(C_S_RUNNING);
+
   game.info.phase = phase;
 
   if (game.player_ptr && is_player_phase(game.player_ptr, phase)) {
@@ -937,6 +939,9 @@
 {
   freelog(LOG_DEBUG, "handle_begin_turn()");
 
+  /* probably duplicate insurance */
+  update_client_state(C_S_RUNNING);
+
   /* Possibly replace wait cursor with something else */
   set_server_busy(FALSE);
 }
@@ -2216,6 +2221,8 @@
 {
   int i;
 
+  update_client_state(C_S_PREPARING);
+
   ruleset_data_free();
 
   ruleset_cache_init();
@@ -2884,6 +2891,8 @@
 **************************************************************************/
 void handle_endgame_report(struct packet_endgame_report *packet)
 {
+  update_client_state(C_S_OVER);
+
   popup_endgame_report_dialog(packet);
 }
 
Index: client/helpdata.c
===================================================================
--- client/helpdata.c   (revision 14141)
+++ client/helpdata.c   (working copy)
@@ -38,6 +38,7 @@
 #include "packets.h"
 #include "registry.h"
 #include "requirements.h"
+#include "specialist.h"
 #include "support.h"
 #include "unit.h"
 
Index: client/tilespec.c
===================================================================
--- client/tilespec.c   (revision 14141)
+++ client/tilespec.c   (working copy)
@@ -40,6 +40,7 @@
 #include "player.h"
 #include "registry.h"
 #include "shared.h"
+#include "specialist.h"
 #include "support.h"
 #include "unit.h"
 #include "unitlist.h"
Index: client/mapctrl_common.c
===================================================================
--- client/mapctrl_common.c     (revision 14141)
+++ client/mapctrl_common.c     (working copy)
@@ -23,6 +23,7 @@
 #include "support.h"
 
 #include "combat.h"
+#include "game.h"
 #include "unitlist.h"
 
 #include "agents.h"
Index: client/mapview_common.c
===================================================================
--- client/mapview_common.c     (revision 14141)
+++ client/mapview_common.c     (working copy)
@@ -23,6 +23,7 @@
 #include "support.h"
 #include "timing.h"
 
+#include "game.h"
 #include "map.h"
 #include "unitlist.h"
 
Index: client/civclient.h
===================================================================
--- client/civclient.h  (revision 14141)
+++ client/civclient.h  (working copy)
@@ -15,7 +15,6 @@
 
 #include "shared.h"            /* MAX_LEN_NAME */
 
-#include "game.h"              /* enum client_states */
 #include "packets.h"           /* enum report_type */
 #include "worklist.h"
 
@@ -26,6 +25,14 @@
  */
 #define TIMER_INTERVAL (int)(real_timer_callback() * 1000)
 
+/* independent and parallel to server_states */
+enum client_states { 
+  C_S_INITIAL,
+  C_S_PREPARING,
+  C_S_RUNNING,
+  C_S_OVER,
+};
+
 void handle_packet_input(void *packet, int type);
 
 void send_report_request(enum report_type type);
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to