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

> [book - Tue Oct 14 02:25:33 2008]:
> 
> If a detached or observer connection does "/take -" when the
> game is running and there are no free players to attach to,
> instead of an error message the client receives invalid utf8
> causing the chatline to display a completely blank line and
> a gtk warning:
> 
> (civclient:4943): Gtk-CRITICAL **: gtk_text_buffer_emit_insert: 
> assertion `g_utf8_validate (text, len, NULL)' failed

Attached patch fixes the is_allowed_to_take() function
to always set the reason string when it returns FALSE
so that the above sending of an uninitialized string
does not occur.

Also, a few other little things found during testing
are fixed:
- attach_connection_to_player() sets the player name
  to the connection username for a completely new player
  created in pregame (avoids "noname" in take command
  message).
- Added NB warning to is_allowed_to_take() comment
  header.
- Added fairly detailed reason strings for the auto-
  taking case in is_allowed_to_take().
- Added periods to the ends of a few take command
  messages.



-----------------------------------------------------------------------
「なりたくない」と返事してもいいですか。
diff --git a/server/connecthand.c b/server/connecthand.c
index b6072cd..13d1407 100644
--- a/server/connecthand.c
+++ b/server/connecthand.c
@@ -486,12 +486,21 @@ bool attach_connection_to_player(struct connection *pconn,
     pplayer->user_turns = 0; /* reset for a new user */
     pplayer->is_connected = TRUE;
 
-    /* If we are attached to a player in pregame from
-     * find_uncontrolled_player above, then that player
-     * will be an AI created by aifill. So turn off AI
-     * mode if it is still on. */
-    if (server_state() == S_S_INITIAL && pplayer->ai.control) {
-      pplayer->ai.control = FALSE;
+    if (server_state() == S_S_INITIAL) {
+      /* If we are attached to a player in pregame from
+       * find_uncontrolled_player above, then that player
+       * will be an AI created by aifill. So turn off AI
+       * mode if it is still on. */
+      if (pplayer->ai.control) {
+        pplayer->ai.control = FALSE;
+      }
+      /* If we are attached to a completely new player in
+       * pregame, set its name to the connection's user
+       * name so that the take command message will not
+       * display "noname". */
+      if (0 == strcmp(player_name(pplayer), ANON_PLAYER_NAME)) {
+        sz_strlcpy(pplayer->name, pconn->username);
+      }
     }
   }
 
diff --git a/server/stdinhand.c b/server/stdinhand.c
index d9d92d9..d568ae4 100644
--- a/server/stdinhand.c
+++ b/server/stdinhand.c
@@ -2633,7 +2633,10 @@ static bool set_command(struct connection *caller, char *str, bool check)
 }
 
 /**************************************************************************
- check game.allow_take for permission to take or observe a player
+  Check game.allow_take for permission to take or observe a player.
+
+  NB: If this function returns FALSE, then callers expect that 'msg' will
+  be filled in with a NULL-terminated string containing the reason.
 **************************************************************************/
 static bool is_allowed_to_take(struct player *pplayer, bool will_obs, 
                                char *msg)
@@ -2655,7 +2658,36 @@ static bool is_allowed_to_take(struct player *pplayer, bool will_obs,
     }
   } else if (!pplayer && !will_obs) {
     /* Auto-taking a new player */
-    return game.info.is_new_game && (S_S_INITIAL == server_state());
+
+    if (!game.info.is_new_game || server_state() != S_S_INITIAL) {
+      mystrlcpy(msg, _("You cannot take a new player at this time."),
+                MAX_LEN_MSG);
+      return FALSE;
+    }
+
+    if (player_count() >= game.info.max_players) {
+      my_snprintf(msg, MAX_LEN_MSG,
+                  /* TRANS: Do not translate "maxplayers". */
+                  PL_("You cannot take a new player because "
+                      "the maximum of %d player has already "
+                      "been reached (maxplayers setting).",
+                      "You cannot take a new player because "
+                      "the maximum of %d players has already "
+                      "been reached (maxplayers setting).",
+                      game.info.max_players),
+                  game.info.max_players);
+      return FALSE;
+    }
+
+    if (player_count() >= player_slot_count()) {
+      mystrlcpy(msg, _("You cannot take a new player because there "
+                       "are no free player slots."),
+                MAX_LEN_MSG);
+      return FALSE;
+    }
+
+    return TRUE;
+
   } else if (is_barbarian(pplayer)) {
     if (!(allow = strchr(game.allow_take, 'b'))) {
       if (will_obs) {
@@ -2969,7 +3001,7 @@ static bool take_command(struct connection *caller, char *str, bool check)
   /* taking your own player makes no sense. */
   if ((NULL != pplayer && !pconn->observer && pplayer == pconn->playing)
    || (NULL == pplayer && !pconn->observer && NULL != pconn->playing)) {
-    cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s already controls %s"),
+    cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s already controls %s."),
               pconn->username,
               player_name(pconn->playing));
     goto end;
@@ -2983,7 +3015,7 @@ static bool take_command(struct connection *caller, char *str, bool check)
       && (player_count() >= game.info.max_players
           || player_count() - server.nbarbarians >= server.playable_nations)) {
     cmd_reply(CMD_TAKE, caller, C_FAIL,
-              _("There is no free player slot for %s"),
+              _("There is no free player slot for %s."),
               pconn->username);
     goto end;
   }
@@ -3074,7 +3106,7 @@ static bool take_command(struct connection *caller, char *str, bool check)
     }
 
     /* inform about the status before changes */
-    cmd_reply(CMD_TAKE, caller, C_OK, _("%s now controls %s (%s, %s)"),
+    cmd_reply(CMD_TAKE, caller, C_OK, _("%s now controls %s (%s, %s)."),
               pconn->username,
               player_name(pplayer),
               is_barbarian(pplayer)
@@ -3096,7 +3128,7 @@ static bool take_command(struct connection *caller, char *str, bool check)
       toggle_ai_player_direct(NULL, pplayer);
     }
   } else {
-    cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s failed to attach to any player"),
+    cmd_reply(CMD_TAKE, caller, C_FAIL, _("%s failed to attach to any player."),
               pconn->username);
   }
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to