<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40195 >
2008/4/7 Marko Lindqvist:
>
> If modpack has less than MAX_PLAYERS playable nations, server can run
> out of nations to assign to players and crash. Attached patch prevents
> several such cases.
- Allow starting game when num players == num nations
- Also for S2_1
Ready for commit. (If civilwar player creation needs similar fix,
I'll make separate ticket)
- ML
diff -Nurd -X.diff_ignore freeciv/server/connecthand.c freeciv/server/connecthand.c
--- freeciv/server/connecthand.c 2008-04-08 15:32:21.000000000 +0300
+++ freeciv/server/connecthand.c 2008-05-04 19:19:01.000000000 +0300
@@ -475,7 +475,8 @@
if (NULL == pplayer) {
/* no uncontrolled player found */
- if (game.info.nplayers >= game.info.max_players) {
+ if (game.info.nplayers >= game.info.max_players
+ || game.info.nplayers - server.nbarbarians >= server.playable_nations) {
return FALSE;
}
assert(game.info.nplayers < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
diff -Nurd -X.diff_ignore freeciv/server/ruleset.c freeciv/server/ruleset.c
--- freeciv/server/ruleset.c 2008-04-09 18:54:09.000000000 +0300
+++ freeciv/server/ruleset.c 2008-05-04 19:19:01.000000000 +0300
@@ -2490,7 +2490,9 @@
pl->is_playable = secfile_lookup_bool_default(file, TRUE,
"%s.is_playable", sec[i]);
-
+ if (pl->is_playable) {
+ server.playable_nations++;
+ }
/* Check barbarian type. Default is "None" meaning not a barbarian */
barb_type = secfile_lookup_str_default(file, "None",
@@ -3554,6 +3556,7 @@
ruleset_data_free();
reset_player_nations();
+ server.playable_nations = 0;
openload_ruleset_file(&techfile, "techs");
load_tech_names(&techfile);
@@ -3611,6 +3614,10 @@
/* Build AI unit class cache corresponding to loaded rulesets */
unit_class_ai_init();
+
+ /* We may need to adjust number of AI players if number of available
+ * nations changed */
+ aifill(game.info.aifill);
}
/**************************************************************************
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c 2008-04-17 10:49:41.000000000 +0300
+++ freeciv/server/srv_main.c 2008-05-04 19:19:01.000000000 +0300
@@ -1591,6 +1591,9 @@
{
int limit = MIN(amount, game.info.max_players);
+ /* Limit to nations provided by ruleset */
+ limit = MIN(limit, server.playable_nations);
+
if (!game.info.is_new_game || S_S_INITIAL != server_state()) {
return;
}
@@ -2144,6 +2147,7 @@
void server_game_init(void)
{
/* was redundantly in game_load() */
+ server.playable_nations = 0;
server.nbarbarians = 0;
server.identity_number = IDENTITY_NUMBER_SKIP;
diff -Nurd -X.diff_ignore freeciv/server/srv_main.h freeciv/server/srv_main.h
--- freeciv/server/srv_main.h 2008-03-10 19:54:21.000000000 +0200
+++ freeciv/server/srv_main.h 2008-05-04 19:19:01.000000000 +0300
@@ -60,6 +60,7 @@
*
* TODO: Lots more variables could be added here. */
extern struct civserver {
+ int playable_nations;
int nbarbarians;
/* this counter creates all the city and unit numbers used.
diff -Nurd -X.diff_ignore freeciv/server/stdinhand.c freeciv/server/stdinhand.c
--- freeciv/server/stdinhand.c 2008-04-17 10:49:41.000000000 +0300
+++ freeciv/server/stdinhand.c 2008-05-04 19:19:42.000000000 +0300
@@ -817,13 +817,13 @@
}
/**************************************************************************
-...
+ Creates named AI player
**************************************************************************/
static bool create_ai_player(struct connection *caller, char *arg, bool check)
{
PlayerNameStatus PNameStatus;
struct player *pplayer = NULL;
-
+
if (S_S_INITIAL != server_state())
{
cmd_reply(CMD_CREATE, caller, C_SYNTAX,
@@ -839,14 +839,19 @@
}
} players_iterate_end;
- /* game.info.max_players is a limit on the number of non-observer players.
- * MAX_NUM_PLAYERS is a limit on all players. */
- if (game.info.nplayers >= MAX_NUM_PLAYERS) {
- if (NULL == pplayer) {
+ if (NULL == pplayer) {
+ /* Check that we are not going over max players setting */
+ if (game.info.nplayers >= game.info.max_players) {
cmd_reply(CMD_CREATE, caller, C_FAIL,
_("Can't add more players, server is full."));
return FALSE;
}
+ /* Check that we have nations available */
+ if (game.info.nplayers - server.nbarbarians >= server.playable_nations) {
+ cmd_reply(CMD_CREATE, caller, C_FAIL,
+ _("Can't add more players, not enough nations."));
+ return FALSE;
+ }
}
if ((PNameStatus = test_player_name(arg)) == PNameEmpty)
@@ -2965,12 +2970,13 @@
* they first release. */
if (!pplayer && !pconn->playing
&& (game.info.nplayers >= game.info.max_players
- || game.info.nplayers >= MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS)) {
+ || game.info.nplayers - server.nbarbarians >= server.playable_nations)) {
cmd_reply(CMD_TAKE, caller, C_FAIL,
_("There is no free player slot for %s"),
pconn->username);
goto end;
}
+ assert(game.info.nplayers < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
res = TRUE;
if (check) {
@@ -3808,6 +3814,10 @@
start_cmd_reply(caller, notify,
_("Not enough players, game will not start."));
return FALSE;
+ } else if (game.info.nplayers - server.nbarbarians > server.playable_nations) {
+ cmd_reply(CMD_START_GAME, caller, C_FAIL,
+ _("Not enough nations for all players, game will not start."));
+ return FALSE;
} else if (check) {
return TRUE;
} else if (!caller) {
diff -Nurd -X.diff_ignore freeciv/common/game.c freeciv/common/game.c
--- freeciv/common/game.c 2008-01-22 03:47:26.000000000 +0200
+++ freeciv/common/game.c 2008-05-04 18:49:37.000000000 +0300
@@ -254,6 +254,7 @@
game.info.government_when_anarchy_id = G_MAGIC; /* flag */
game.info.is_new_game = TRUE;
+ game.playable_nations = 0;
game.fogofwar_old = game.info.fogofwar;
game.simultaneous_phases_stored = GAME_DEFAULT_SIMULTANEOUS_PHASES;
game.timeoutint = GAME_DEFAULT_TIMEOUTINT;
diff -Nurd -X.diff_ignore freeciv/common/game.h freeciv/common/game.h
--- freeciv/common/game.h 2008-01-15 04:04:30.000000000 +0200
+++ freeciv/common/game.h 2008-05-04 18:50:31.000000000 +0300
@@ -85,6 +85,7 @@
bool scorelog;
int scoreturn; /* next make_history_report() */
int seed;
+ int playable_nations;
bool fogofwar_old; /* as the fog_of_war bit get changed by setting
the server we need to remember the old setting */
int ai_goal_government; /* kludge */
diff -Nurd -X.diff_ignore freeciv/server/connecthand.c freeciv/server/connecthand.c
--- freeciv/server/connecthand.c 2008-04-02 22:48:51.000000000 +0300
+++ freeciv/server/connecthand.c 2008-05-04 18:56:28.000000000 +0300
@@ -457,7 +457,8 @@
{
/* if pplayer is NULL, attach to first non-connected player slot */
if (!pplayer) {
- if (game.info.nplayers >= game.info.max_players
+ if (game.info.nplayers >= game.info.max_players
+ || game.info.nplayers - game.info.nbarbarians >= game.playable_nations
|| game.info.nplayers >= MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS) {
return FALSE;
} else {
diff -Nurd -X.diff_ignore freeciv/server/ruleset.c freeciv/server/ruleset.c
--- freeciv/server/ruleset.c 2008-04-01 22:16:20.000000000 +0300
+++ freeciv/server/ruleset.c 2008-05-04 18:57:27.000000000 +0300
@@ -2172,6 +2172,9 @@
pl->is_playable = secfile_lookup_bool_default(file, TRUE,
"%s.is_playable", sec[i]);
+ if (pl->is_playable) {
+ game.playable_nations++;
+ }
pl->is_barbarian = secfile_lookup_bool_default(file, FALSE,
"%s.is_barbarian", sec[i]);
@@ -3156,6 +3159,7 @@
ruleset_data_free();
reset_player_nations();
+ game.playable_nations = 0;
openload_ruleset_file(&techfile, "techs");
load_tech_names(&techfile);
@@ -3201,6 +3205,10 @@
script_init();
openload_script_file("script");
+
+ /* We may need to adjust number of AI players if number of available
+ * nations changed */
+ aifill(game.info.aifill);
}
/**************************************************************************
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c 2008-04-23 03:13:19.000000000 +0300
+++ freeciv/server/srv_main.c 2008-05-04 18:59:17.000000000 +0300
@@ -1556,6 +1556,9 @@
amount = MIN(amount, game.info.max_players);
+ /* Limit to nations provided by ruleset */
+ amount = MIN(amount, game.playable_nations);
+
while (game.info.nplayers < amount) {
const int old_nplayers = game.info.nplayers;
struct player *pplayer = player_by_number(old_nplayers);
diff -Nurd -X.diff_ignore freeciv/server/stdinhand.c freeciv/server/stdinhand.c
--- freeciv/server/stdinhand.c 2008-04-23 03:13:19.000000000 +0300
+++ freeciv/server/stdinhand.c 2008-05-04 19:13:57.000000000 +0300
@@ -833,14 +833,14 @@
}
/**************************************************************************
-...
+ Creates named AI player
**************************************************************************/
static bool create_ai_player(struct connection *caller, char *arg, bool check)
{
struct player *pplayer;
PlayerNameStatus PNameStatus;
bool ai_player_should_be_removed = FALSE;
-
+
if (S_S_INITIAL != server_state())
{
cmd_reply(CMD_CREATE, caller, C_SYNTAX,
@@ -850,7 +850,8 @@
/* game.info.max_players is a limit on the number of non-observer players.
* MAX_NUM_PLAYERS is a limit on all players. */
- if (game.info.nplayers >= MAX_NUM_PLAYERS) {
+ if (game.info.nplayers >= MAX_NUM_PLAYERS
+ || game.info.nplayers - game.info.nbarbarians >= game.playable_nations) {
/* Try emptying a slot if there is an ai player
* created through the /aifill command */
players_iterate(eplayer) {
@@ -860,7 +861,7 @@
ai_player_should_be_removed = TRUE;
break;
} players_iterate_end;
-
+
if (!ai_player_should_be_removed) {
cmd_reply(CMD_CREATE, caller, C_FAIL,
_("Can't add more players, server is full."));
@@ -2957,12 +2958,13 @@
* they first release. */
if (!pplayer && !pconn->player
&& (game.info.nplayers >= game.info.max_players
- || game.info.nplayers >= MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS)) {
+ || game.info.nplayers - game.info.nbarbarians >= game.playable_nations)) {
cmd_reply(CMD_TAKE, caller, C_FAIL,
_("There is no free player slot for %s"),
pconn->username);
goto end;
}
+ assert(game.info.nplayers < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
res = TRUE;
if (check) {
@@ -3800,6 +3802,10 @@
start_cmd_reply(caller, notify,
_("Not enough players, game will not start."));
return FALSE;
+ } else if (game.info.nplayers - game.info.nbarbarians > game.playable_nations) {
+ cmd_reply(CMD_START_GAME, caller, C_FAIL,
+ _("Not enough nations for all players, game will not start."));
+ return FALSE;
} else if (check) {
return TRUE;
} else if (!caller) {
_______________________________________________
Freeciv-dev mailing list
[email protected]
https://mail.gna.org/listinfo/freeciv-dev