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

Looking at other packet names, changed PLAYER_REMOVE to PLAYER_CONTROL
instead, for consistency.  As planned, this allows a reduction of GAME_INFO
packets merely sent to update game.info.nplayers.  Also, allows copious
error checking.

Completed removal of struct player ->player_no -- a process started in July
with PR#39476 -- now using player_number() and player_index() everywhere.

Moved game.info.nbarbarians into new struct civserver server, matching
struct civclient client.  Use player_count_no_barbarians().

Likewise, moved server_states out of game.h -- should be server-only.




Index: version.in
===================================================================
--- version.in  (revision 14221)
+++ version.in  (working copy)
@@ -1,4 +1,4 @@
-#  Copyright (C) 2004 Freeciv team
+#  Copyright (C) 2004-2008 Freeciv team
 
 # Version definition for Freeciv.
 
@@ -20,7 +20,7 @@
 #   - No new mandatory capabilities can be added to the release branch; doing
 #     so would break network capability of supposedly "compatible" releases.
 #
-#   - Avoid adding a new mandatory capbility to the development branch for
+#   - Avoid adding a new mandatory capability 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.Dec.07"
+NETWORK_CAPSTRING="+Freeciv.Devel.2008.Jan.04"
Index: server/civserver.c
===================================================================
--- server/civserver.c  (revision 14221)
+++ server/civserver.c  (working copy)
@@ -34,6 +34,7 @@
 
 #include "fciconv.h"
 #include "fcintl.h"
+#include "game.h"
 #include "log.h"
 #include "shared.h"
 #include "support.h"
Index: server/srv_main.c
===================================================================
--- server/srv_main.c   (revision 14221)
+++ server/srv_main.c   (working copy)
@@ -116,6 +116,9 @@
 /* command-line arguments to server */
 struct server_arguments srvarg;
 
+/* server aggregate information */
+struct civserver server;
+
 /* server state information */
 static enum server_states civserver_state = S_S_INITIAL;
 bool nocity_send = FALSE;
@@ -1077,6 +1080,14 @@
 }
 
 /**************************************************************************
+...
+**************************************************************************/
+int player_count_no_barbarians(void)
+{
+  return player_count() - server.nbarbarians;
+}
+
+/**************************************************************************
 Returns 0 if connection should be closed (because the clients was
 rejected). Returns 1 else.
 **************************************************************************/
@@ -1558,8 +1569,7 @@
   amount = MIN(amount, game.info.max_players);
 
   while (game.info.nplayers < amount) {
-    const int old_nplayers = game.info.nplayers;
-    struct player *pplayer = player_by_number(old_nplayers);
+    struct player *pplayer = player_by_number(game.info.nplayers);
     char leader_name[ARRAY_SIZE(pplayer->name)];
 
     server_player_init(pplayer, FALSE, TRUE);
@@ -1583,20 +1593,17 @@
                player_name(pplayer),
                ai_level_name(pplayer->ai.skill_level));
 
-    game.info.nplayers++;
-
-    send_game_info(NULL);
+    dlsend_packet_player_control(game.est_connections, ++game.info.nplayers);
     send_player_info(pplayer, NULL);
   }
 
   remove = game.info.nplayers - 1;
   while (game.info.nplayers > amount && remove >= 0) {
-    struct player *pplayer = player_by_number(remove);
+    struct player *pplayer = player_by_number(remove--);
 
     if (!pplayer->is_connected && !pplayer->was_created) {
       server_remove_player(pplayer);
     }
-    remove--;
   }
 }
 
@@ -2096,6 +2103,8 @@
 {
   game_init();
 
+  server.nbarbarians = 0;
+
   /* Rulesets are loaded on game initialization, but may be changed later
    * if /load or /rulesetdir is done. */
   load_rulesets();
Index: server/scripting/api.pkg
===================================================================
--- server/scripting/api.pkg    (revision 14221)
+++ server/scripting/api.pkg    (working copy)
@@ -34,8 +34,6 @@
   Nation_Type *nation;
 
   Player_ai ai;
-
-  const int player_no @ id;
 };
 
 struct City {
Index: server/srv_main.h
===================================================================
--- server/srv_main.h   (revision 14221)
+++ server/srv_main.h   (working copy)
@@ -14,10 +14,8 @@
 #define FC__SRV_MAIN_H
 
 #include "fc_types.h"
-#include "game.h"
-#include "packets.h"
 
-struct connection;
+struct conn_list;
 
 struct server_arguments {
   /* metaserver information */
@@ -50,6 +48,22 @@
   bool auth_allow_newusers;     /* defaults to TRUE */
 };
 
+/* used in savegame values */
+enum server_states { 
+  S_S_INITIAL = 0, 
+  S_S_GENERATING_WAITING = 1,
+  S_S_RUNNING = 2,
+  S_S_OVER = 3,
+};
+
+/* Structure for holding global server data.
+ *
+ * TODO: Lots more variables could be added here. */
+extern struct civserver {
+  int nbarbarians;
+} server;
+
+
 void init_game_seed(void);
 void srv_init(void);
 void srv_main(void);
@@ -72,6 +86,7 @@
 void dealloc_id(int id);
 void alloc_id(int id);
 int get_next_id_number(void);
+int player_count_no_barbarians(void);
 void server_game_init(void);
 void server_game_free(void);
 void aifill(int amount);
Index: server/connecthand.c
===================================================================
--- server/connecthand.c        (revision 14221)
+++ server/connecthand.c        (working copy)
@@ -125,18 +125,19 @@
       send_packet_thaw_hint(pconn);
       dsend_packet_start_phase(pconn, game.info.phase);
     } else {
+      send_game_info(dest);
       /* send new player connection to everybody */
-      send_game_info(game.est_connections);
       send_player_info_c(NULL, game.est_connections);
       send_conn_info(game.est_connections, dest);
     }
   } else {
+    send_game_info(dest);
+
     if (S_S_INITIAL == server_state() && game.info.is_new_game) {
       if (attach_connection_to_player(pconn, NULL)) {
         sz_strlcpy(pconn->player->name, pconn->username);
 
         /* send new player connection to everybody */
-        send_game_info(game.est_connections);
         send_player_info_c(NULL, game.est_connections);
       } else {
         notify_conn(dest, NULL, E_CONNECTION,
@@ -144,12 +145,10 @@
         freelog(LOG_VERBOSE, "%s is not attached to a player", 
pconn->username);
 
         /* send old player connections to self */
-        send_game_info(dest);
         send_player_info_c(NULL, dest);
       }
     } else {
       /* send old player connections to self */
-      send_game_info(dest);
       send_player_info_c(NULL, dest);
     }
     send_conn_info(game.est_connections, dest);
@@ -441,8 +440,8 @@
     } else {
       pplayer = &game.players[game.info.nplayers];
       server_player_init(pplayer, FALSE, TRUE);
-      game.info.nplayers++;
-      send_game_info(game.est_connections);
+
+      dlsend_packet_player_control(game.est_connections, ++game.info.nplayers);
     }
   }
 
Index: server/citytools.c
===================================================================
--- server/citytools.c  (revision 14221)
+++ server/citytools.c  (working copy)
@@ -30,6 +30,7 @@
 #include "base.h"
 #include "city.h"
 #include "events.h"
+#include "game.h"
 #include "government.h"
 #include "improvement.h"
 #include "idex.h"
@@ -1251,7 +1252,7 @@
   BV_CLR_ALL(saw_entering);
   players_iterate(pplayer) {
     if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
-      BV_SET(saw_entering, pplayer->player_no);
+      BV_SET(saw_entering, player_index(pplayer));
     }
   } players_iterate_end;
 
@@ -1264,7 +1265,7 @@
   if (is_capital(pcity)
       && city_list_size(cplayer->cities) >= game.info.civilwarsize
       && game.info.civilwarsize < GAME_MAX_CIVILWARSIZE
-      && get_num_human_and_ai_players() < MAX_NUM_PLAYERS
+      && player_count_no_barbarians() < MAX_NUM_PLAYERS
       && civil_war_triggered(cplayer)) {
     /* Do a civil war only if there's an available unused nation. */
     nations_iterate(pnation) {
@@ -1364,11 +1365,11 @@
 
   /* After city has been transferred, some players may no longer see inside. */
   players_iterate(pplayer) {
-    if (BV_ISSET(saw_entering, pplayer->player_no)
+    if (BV_ISSET(saw_entering, player_index(pplayer))
         && !can_player_see_unit_at(pplayer, punit, pcity->tile)) {
       /* Player saw unit entering, but now unit is hiding inside city */
       unit_goes_out_of_sight(pplayer, punit);
-    } else if (!BV_ISSET(saw_entering, pplayer->player_no)
+    } else if (!BV_ISSET(saw_entering, player_index(pplayer))
                && can_player_see_unit_at(pplayer, punit, pcity->tile)) {
       /* Player sees inside cities of new owner */
       send_unit_info_to_onlookers(pplayer->connections, punit,
Index: server/barbarian.c
===================================================================
--- server/barbarian.c  (revision 14221)
+++ server/barbarian.c  (working copy)
@@ -82,9 +82,9 @@
 **************************************************************************/
 static struct player *create_barbarian_player(enum barbarian_type type)
 {
-  int newplayer = game.info.nplayers;
   struct player *barbarians;
   struct nation_type *nation;
+  int newplayer = player_count();
 
   players_iterate(barbarians) {
     if ((type == LAND_BARBARIAN && is_land_barbarian(barbarians))
@@ -119,9 +119,9 @@
   player_set_nation(barbarians, nation);
   pick_random_player_name(nation, barbarians->name);
 
-  game.info.nplayers++;
-  game.info.nbarbarians++;
-  game.info.max_players = game.info.nplayers;
+  server.nbarbarians++;
+  dlsend_packet_player_control(game.est_connections,
+                               (game.info.max_players = ++game.info.nplayers));
 
   sz_strlcpy(barbarians->username, ANON_USER_NAME);
   barbarians->is_connected = FALSE;
@@ -156,7 +156,6 @@
                 nation_plural_for_player(barbarians),
                 player_name(barbarians));
 
-  send_game_info(NULL);
   send_player_info(barbarians, NULL);
 
   return barbarians;
Index: server/meta.c
===================================================================
--- server/meta.c       (revision 14221)
+++ server/meta.c       (working copy)
@@ -44,6 +44,7 @@
 #include "connection.h"
 #include "dataio.h"
 #include "fcintl.h"
+#include "game.h"
 #include "log.h"
 #include "mem.h"
 #include "netintf.h"
@@ -271,7 +272,7 @@
     s = end_of_strn(s, &rest);
 
     /* NOTE: send info for ALL players or none at all. */
-    if (get_num_human_and_ai_players() == 0) {
+    if (player_count_no_barbarians() == 0) {
       mystrlcpy(s, "dropplrs=1&", rest);
       s = end_of_strn(s, &rest);
     } else {
Index: server/sernet.c
===================================================================
--- server/sernet.c     (revision 14221)
+++ server/sernet.c     (working copy)
@@ -66,6 +66,7 @@
 #include "dataio.h"
 #include "events.h"
 #include "fcintl.h"
+#include "game.h"
 #include "log.h"
 #include "mem.h"
 #include "netintf.h"
@@ -1181,7 +1182,7 @@
   }
 
    my_snprintf(players, sizeof(players), "%d",
-               get_num_human_and_ai_players());
+               player_count_no_barbarians());
    my_snprintf(port, sizeof(port), "%d",
               srvarg.port );
 
Index: server/sanitycheck.c
===================================================================
--- server/sanitycheck.c        (revision 14221)
+++ server/sanitycheck.c        (working copy)
@@ -32,9 +32,11 @@
 
 #include "citytools.h"
 #include "maphand.h"
-#include "sanitycheck.h"
+#include "srv_main.h"
 #include "unittools.h"
 
+#include "sanitycheck.h"
+
 #ifdef SANITY_CHECKING
 
 #define SANITY_CHECK(x)                                                        
\
@@ -145,7 +147,7 @@
       nbarbs++;
     }
   } players_iterate_end;
-  SANITY_CHECK(nbarbs == game.info.nbarbarians);
+  SANITY_CHECK(nbarbs == server.nbarbarians);
 
   SANITY_CHECK(player_count() <= MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
   SANITY_CHECK(team_count() <= MAX_NUM_TEAMS);
Index: server/stdinhand.c
===================================================================
--- server/stdinhand.c  (revision 14221)
+++ server/stdinhand.c  (working copy)
@@ -901,8 +901,12 @@
   sz_strlcpy(pplayer->username, ANON_USER_NAME);
   pplayer->was_created = TRUE; /* must use /remove explicitly to remove */
 
-  game.info.nplayers++;
+  dlsend_packet_player_control(game.est_connections, ++game.info.nplayers);
 
+  pplayer->ai.control = TRUE;
+  set_ai_level_directer(pplayer, game.info.skill_level);
+  send_player_info_c(pplayer, game.est_connections);
+
   notify_conn(NULL, NULL, E_SETTING,
              _("%s has been added as an AI-controlled player."),
              arg);
@@ -915,11 +919,7 @@
     return FALSE;
   }
 
-  pplayer->ai.control = TRUE;
-  set_ai_level_directer(pplayer, game.info.skill_level);
   aifill(game.info.aifill);
-  send_game_info(NULL);
-  send_player_info(pplayer, NULL);
   reset_all_start_commands();
   (void) send_server_info_to_metaserver(META_INFO);
   return TRUE;
@@ -2850,8 +2850,8 @@
     send_packet_thaw_hint(pconn);
     dsend_packet_start_phase(pconn, game.info.phase);
   } else {
+    send_game_info(pconn->self);
     /* send changed player connection to everybody */
-    send_game_info(game.est_connections);
     send_player_info_c(pplayer, game.est_connections);
     /* we already know existing connections */
   }
@@ -3027,8 +3027,8 @@
     send_packet_thaw_hint(pconn);
     dsend_packet_start_phase(pconn, game.info.phase);
   } else {
+    send_game_info(pconn->self);
     /* send changed player connection to everybody */
-    send_game_info(game.est_connections);
     send_player_info_c(pplayer, game.est_connections);
     /* we already know existing connections */
   }
Index: server/savegame.c
===================================================================
--- server/savegame.c   (revision 14221)
+++ server/savegame.c   (working copy)
@@ -1800,7 +1800,9 @@
 
   plr->ai.barbarian_type = secfile_lookup_int_default(file, 0, 
"player%d.ai.is_barbarian",
                                                     plrno);
-  if (is_barbarian(plr)) game.info.nbarbarians++;
+  if (is_barbarian(plr)) {
+    server.nbarbarians++;
+  }
 
   sz_strlcpy(plr->name, secfile_lookup_str(file, "player%d.name", plrno));
   sz_strlcpy(plr->username,
@@ -3808,7 +3810,7 @@
     game.info.revolution_length
       = secfile_lookup_int_default(file, game.info.revolution_length,
                                   "game.revolen");
-    game.info.nbarbarians = 0; /* counted in player_load for compatibility 
with 
+    server.nbarbarians = 0; /* counted in player_load for compatibility with 
                             1.10.0 */
     game.info.occupychance = secfile_lookup_int_default(file, 
game.info.occupychance,
                                                   "game.occupychance");
Index: server/plrhand.c
===================================================================
--- server/plrhand.c    (revision 14221)
+++ server/plrhand.c    (working copy)
@@ -27,6 +27,7 @@
 
 #include "diptreaty.h"
 #include "events.h"
+#include "game.h"
 #include "government.h"
 #include "movement.h"
 #include "packets.h"
@@ -1113,7 +1114,6 @@
   if (initmap) {
     player_map_allocate(pplayer);
   }
-  pplayer->player_no = pplayer - game.players;
   if (needs_team) {
     team_add_player(pplayer, find_empty_team());
   }
@@ -1138,9 +1138,12 @@
   notify_conn(game.est_connections, NULL, E_CONNECTION,
              _("%s has been removed from the game."),
              player_name(pplayer));
-  
-  dlsend_packet_player_remove(game.est_connections, player_number(pplayer));
 
+  if (is_barbarian(pplayer)) {
+    server.nbarbarians--;
+  }
+  dlsend_packet_player_control(game.est_connections, player_index(pplayer));
+
   /* Note it is ok to remove the _current_ item in a list_iterate. */
   conn_list_iterate(pplayer->connections, pconn) {
     if (!unattach_connection_from_player(pconn)) {
@@ -1478,11 +1481,10 @@
 ***********************************************************************/
 static struct player *split_player(struct player *pplayer)
 {
-  int newplayer = player_count();
-  struct player *cplayer = &game.players[newplayer];
+  struct player_research *new_research, *old_research;
+  struct player *cplayer = &game.players[player_count()];
   struct nation_type **civilwar_nations
     = get_nation_civilwar(nation_of_player(pplayer));
-  struct player_research *new_research, *old_research;
 
   /* make a new player */
   server_player_init(cplayer, TRUE, TRUE);
@@ -1523,11 +1525,11 @@
     if (other_player != pplayer) {
       send_player_info(other_player, other_player);
     }
-  }
-  players_iterate_end;
+  } players_iterate_end;
 
-  game.info.nplayers++;
-  game.info.max_players = game.info.nplayers;
+  /* FIXME: this should be sent before above, so that fields can be verified? 
*/
+  dlsend_packet_player_control(game.est_connections,
+                               (game.info.max_players = ++game.info.nplayers));
 
   /* Split the resources */
   cplayer->economic.gold = pplayer->economic.gold;
@@ -1691,9 +1693,6 @@
 
   cplayer = split_player(pplayer);
 
-  /* So that clients get the correct number of players */
-  send_game_info(NULL);
-  
   /* Before units, cities, so clients know name of new nation
    * (for debugging etc).
    */
Index: common/packets.def
===================================================================
--- common/packets.def  (revision 14221)
+++ common/packets.def  (working copy)
@@ -415,7 +415,6 @@
   BOOL auto_ai_toggle;
   BOOL fogofwar;  
   UINT8 borders;
-  UINT8 nbarbarians;
   BOOL happyborders;
   BOOL slow_invasions;
   UINT8 add_to_size_limit;
@@ -636,8 +635,8 @@
 
 /************** Player packets **********************/
 
-PACKET_PLAYER_REMOVE=38; sc,dsend,lsend
-  PLAYER player_id;
+PACKET_PLAYER_CONTROL=38; sc,dsend,lsend
+  PLAYER playerno;
 end
 
 PACKET_PLAYER_INFO=39; sc
@@ -1344,7 +1343,7 @@
 
 PACKET_GAME_LOAD=111;sc,handle-via-packet,lsend
   BOOL load_successful;
-  UINT8 nplayers;
+  PLAYER nplayers;
   STRING load_filename[MAX_LEN_PACKET];
   STRING name[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
   STRING username[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
Index: common/player.c
===================================================================
--- common/player.c     (revision 14221)
+++ common/player.c     (working copy)
@@ -176,8 +176,6 @@
 {
   int i;
 
-  plr->player_no = plr - game.players;
-
   sz_strlcpy(plr->name, ANON_PLAYER_NAME);
   sz_strlcpy(plr->username, ANON_USER_NAME);
   sz_strlcpy(plr->ranked_username, ANON_USER_NAME);
@@ -267,6 +265,14 @@
   return game.info.nplayers;
 }
 
+/***************************************************************
+  Set the number of players.
+***************************************************************/
+void set_player_count(int count)
+{
+  game.info.nplayers = count;
+}
+
 /**************************************************************************
   Return the player index.
 
@@ -285,7 +291,7 @@
 int player_number(const struct player *pplayer)
 {
   assert(pplayer);
-  return pplayer->player_no;
+  return pplayer - game.players;
 }
 
 /**************************************************************************
@@ -300,7 +306,6 @@
     /* This isn't an error; some callers rely on this behavior. */
     return NULL;
   }
-  assert(game.players[player_id].player_no == player_id);
   return &game.players[player_id];
 }
 
@@ -314,7 +319,6 @@
    || player_id >= ARRAY_SIZE(game.players)) {
     return NULL;
   }
-  assert(game.players[player_id].player_no == player_id);
   return &game.players[player_id];
 }
 
Index: common/player.h
===================================================================
--- common/player.h     (revision 14221)
+++ common/player.h     (working copy)
@@ -154,7 +154,6 @@
 };
 
 struct player {
-  int player_no;
   char name[MAX_LEN_NAME];
   char username[MAX_LEN_NAME];
   char ranked_username[MAX_LEN_NAME]; /* the user who will be ranked */
@@ -205,6 +204,8 @@
 
 /* General player accessor functions. */
 int player_count(void);
+void set_player_count(int count);
+
 int player_index(const struct player *pplayer);
 int player_number(const struct player *pplayer);
 
Index: common/game.c
===================================================================
--- common/game.c       (revision 14221)
+++ common/game.c       (working copy)
@@ -267,7 +267,6 @@
   game.info.fulltradesize = GAME_DEFAULT_FULLTRADESIZE;
   game.info.barbarianrate = GAME_DEFAULT_BARBARIANRATE;
   game.info.onsetbarbarian= GAME_DEFAULT_ONSETBARBARIAN;
-  game.info.nbarbarians   = 0;
   game.info.occupychance  = GAME_DEFAULT_OCCUPYCHANCE;
   game.info.autoattack    = GAME_DEFAULT_AUTOATTACK;
   game.info.revolution_length = GAME_DEFAULT_REVOLUTION_LENGTH;
@@ -389,8 +388,7 @@
     game_remove_player(&game.players[i]);
   }
 
-  game.info.nplayers=0;
-  game.info.nbarbarians=0;
+  set_player_count(0);
 }
 
 /***************************************************************
@@ -544,19 +542,13 @@
 
   /* This comes last because log calls in the above functions may use it. */
   if (pplayer->nation != NULL) {
-    /* There never was nation assigned to this player */
     player_set_nation(pplayer, NULL);
   }
-
-  if (is_barbarian(pplayer)) game.info.nbarbarians--;
 }
 
 /****************************************************************************
-  After calling game_remove_player, you should always call this function to
-  renumber players to fill in the gap left by the empty player.
+  Called after game_remove_player() to fill the empty player gap.
 
-  FIXME: maybe this should be called directly by game_remove_player?
-
   FIXME: this cannot be called once the game is started.  You can't remove
   players of a running game.
 ****************************************************************************/
@@ -565,17 +557,19 @@
   int i;
 
   for (i = plrno; i < game.info.nplayers - 1; i++) {
-    game.players[i]=game.players[i+1];
-    game.players[i].player_no=i;
+    /* structure copy including pointers */
+    game.players[i] = game.players[i+1];
+
     conn_list_iterate(game.players[i].connections, pconn) {
       pconn->player = &game.players[i];
     } conn_list_iterate_end;
+
     if (game.players[i].nation) {
       game.players[i].nation->player = &game.players[i];
     }
 
-    /* We could renumber players in-game if we updated the unit and
-     * city owners.  But for now we just make sure these lists are empty. */
+    /* FiXME: This could renumber players in-game by updating the unit and
+     * city owners.  But for now, just make sure these lists are empty. */
     assert(unit_list_size(game.players[i].units) == 0);
     assert(city_list_size(game.players[i].cities) == 0);
   }
@@ -591,15 +585,6 @@
 }
 
 /**************************************************************************
-This function is used by is_wonder_useful to estimate if it is worthwhile
-to build the great library.
-**************************************************************************/
-int get_num_human_and_ai_players(void)
-{
-  return game.info.nplayers - game.info.nbarbarians;
-}
-
-/**************************************************************************
   Return TRUE if it is this player's phase.
 **************************************************************************/
 bool is_player_phase(const struct player *pplayer, int phase)
Index: common/game.h
===================================================================
--- common/game.h       (revision 14221)
+++ common/game.h       (working copy)
@@ -32,14 +32,6 @@
   DEBUG_LAST
 };
 
-/* used in savegame values */
-enum server_states { 
-  S_S_INITIAL = 0, 
-  S_S_GENERATING_WAITING = 1,
-  S_S_RUNNING = 2,
-  S_S_OVER = 3,
-};
-
 #define CONTAMINATION_POLLUTION 1
 #define CONTAMINATION_FALLOUT   2
 
@@ -141,7 +133,6 @@
 void game_remove_city(struct city *pcity);
 void initialize_globals(void);
 
-int get_num_human_and_ai_players(void);
 bool is_player_phase(const struct player *pplayer, int phase);
 
 const char *population_to_text(int thousand_citizen);
Index: ai/aicity.c
===================================================================
--- ai/aicity.c (revision 14221)
+++ ai/aicity.c (working copy)
@@ -47,6 +47,7 @@
 #include "gotohand.h"
 #include "plrhand.h"
 #include "settlers.h"
+#include "srv_main.h"
 #include "unithand.h"
 #include "unittools.h"
 
@@ -787,7 +788,7 @@
 {
   int v = 0;
   int cities[REQ_RANGE_LAST];
-  int nplayers = game.info.nplayers - game.info.nbarbarians;
+  int nplayers = player_count_no_barbarians();
   struct ai_data *ai = ai_data_get(pplayer);
   bool capital = is_capital(pcity);
   bool can_build = TRUE;
Index: ai/ailog.c
===================================================================
--- ai/ailog.c  (revision 14221)
+++ ai/ailog.c  (working copy)
@@ -19,6 +19,7 @@
 
 #include "astring.h"
 #include "city.h"
+#include "game.h"
 #include "log.h"
 #include "shared.h"
 #include "support.h"
Index: client/gui-gtk-2.0/pages.c
===================================================================
--- client/gui-gtk-2.0/pages.c  (revision 14221)
+++ client/gui-gtk-2.0/pages.c  (working copy)
@@ -1998,7 +1998,7 @@
 {
   int i;
 
-  game.info.nplayers = packet->nplayers;
+  set_player_count(packet->nplayers);
 
   gtk_list_store_clear(nation_store);
 
Index: client/gui-win32/connectdlg.c
===================================================================
--- client/gui-win32/connectdlg.c       (revision 14221)
+++ client/gui-win32/connectdlg.c       (working copy)
@@ -182,7 +182,7 @@
   ShowWindow(start_dlg, SW_HIDE);
   ShowWindow(players_dlg, SW_SHOWNORMAL);
 
-  game.info.nplayers = packet->nplayers;
+  set_player_count(packet->nplayers);
   ListView_DeleteAllItems(players_listview);
 
   for (i = 0; i < packet->nplayers; i++) {
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 14221)
+++ client/packhand.c   (working copy)
@@ -892,9 +892,10 @@
 void handle_start_phase(int phase)
 {
 
-  if (phase < 0 || phase >= game.info.nplayers) {
-    /* Illegal phase */
-    freelog(LOG_ERROR, "Illegal phase %d received from server!", phase);
+  if (phase < 0 || phase >= player_count()) {
+    freelog(LOG_ERROR,
+            "handle_start_phase() illegal phase %d.",
+            phase);
     return;
   }
 
@@ -2204,11 +2205,29 @@
 }
 
 /**************************************************************************
-...
+  Decrease or increase the player_count(), removing by player_index(),
+  or setting the new value.
 **************************************************************************/
-void handle_player_remove(int player_id)
+void handle_player_control(int playerno)
 {
-  client_remove_player(player_id);
+  if (0 > playerno) {
+    freelog(LOG_ERROR,
+            "handle_player_control() invalid player index %d.",
+            playerno);
+    return;
+  } else if (player_count() > playerno) {
+    client_remove_player(playerno);
+  } else if (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS >= playerno) {
+    if (game.info.max_players < playerno) {
+      game.info.max_players = playerno;
+    }
+    set_player_count(playerno);
+  } else {
+    freelog(LOG_ERROR,
+            "handle_player_control() invalid player index %d.",
+            playerno);
+    return;
+  }
   update_conn_list_dialog();
 }
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to