Ensure bot names set by Lua's K_SetNameForBot are good

This commit is contained in:
JugadorXEI 2025-10-03 21:00:01 +02:00
parent 494f4c1641
commit 9921d0b427
4 changed files with 63 additions and 44 deletions

View file

@ -618,7 +618,23 @@ static boolean AllowedPlayerNameChar(char ch)
return true; return true;
} }
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) boolean IsPlayerNameUnique(const char *name, INT32 playernum)
{
// Check if a player is currently using the name, case-insensitively.
for (INT32 ix = 0; ix < MAXPLAYERS; ix++)
{
if (ix == playernum) // Don't compare with themself.
continue;
if (playeringame[ix] == false) // This player is not ingame.
continue;
if (strcasecmp(name, player_names[ix]) == 0) // Are usernames equal?
return false;
}
return true;
}
boolean IsPlayerNameGood(char *name)
{ {
size_t ix, len = strlen(name); size_t ix, len = strlen(name);
@ -651,35 +667,42 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
if (!AllowedPlayerNameChar(name[ix])) if (!AllowedPlayerNameChar(name[ix]))
return false; return false;
// Check if a player is currently using the name, case-insensitively. return true;
for (ix = 0; ix < MAXPLAYERS; ix++) }
{
if (ix != (size_t)playernum && playeringame[ix]
&& strcasecmp(name, player_names[ix]) == 0)
{
// We shouldn't kick people out just because
// they joined the game with the same name
// as someone else -- modify the name instead.
// Recursion! boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
// Slowly strip characters off the end of the {
// name until we no longer have a duplicate. size_t len = strlen(name);
if (len > 1)
{ // Check if a player is using a valid name.
name[len-1] = '\0'; if (!IsPlayerNameGood(name))
if (!EnsurePlayerNameIsGood (name, playernum)) return false;
return false;
} // Check if another player is currently using the name, case-insensitively.
else if (len == 1) // Agh! if (!IsPlayerNameUnique(name, playernum))
{ {
// Last ditch effort... // We shouldn't kick people out just because
sprintf(name, "%d", 'A' + M_RandomKey(26)); // they joined the game with the same name
if (!EnsurePlayerNameIsGood (name, playernum)) // as someone else -- modify the name instead.
return false;
} // Recursion!
else // Slowly strip characters off the end of the
// name until we no longer have a duplicate.
if (len > 1)
{
name[len-1] = '\0';
if (!EnsurePlayerNameIsGood (name, playernum))
return false; return false;
} }
else if (len == 1) // Agh!
{
// Last ditch effort...
sprintf(name, "%d", 'A' + M_RandomKey(26));
if (!EnsurePlayerNameIsGood (name, playernum))
return false;
}
else
return false;
} }
return true; return true;

View file

@ -200,6 +200,8 @@ extern const char *netxcmdnames[MAXNETXCMD - 1];
void D_RegisterServerCommands(void); void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void); void D_RegisterClientCommands(void);
void CleanupPlayerName(INT32 playernum, const char *newname); void CleanupPlayerName(INT32 playernum, const char *newname);
boolean IsPlayerNameUnique(const char *name, INT32 playernum);
boolean IsPlayerNameGood(char *name);
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); boolean EnsurePlayerNameIsGood(char *name, INT32 playernum);
void D_FillPlayerSkinAndColor(const UINT8 n, const player_t *player, player_config_t *config); void D_FillPlayerSkinAndColor(const UINT8 n, const player_t *player, player_config_t *config);
void D_PlayerChangeSkinAndColor(player_t *player, UINT16 skin, UINT16 color, INT16 follower, UINT16 followercolor); void D_PlayerChangeSkinAndColor(player_t *player, UINT16 skin, UINT16 color, INT16 follower, UINT16 followercolor);

View file

@ -55,30 +55,16 @@ extern "C" consvar_t cv_forcebots;
--------------------------------------------------*/ --------------------------------------------------*/
void K_SetNameForBot(UINT8 newplayernum, const char *realname) void K_SetNameForBot(UINT8 newplayernum, const char *realname)
{ {
UINT8 ix = MAXPLAYERS;
// These names are generally sourced from skins. // These names are generally sourced from skins.
I_Assert(MAXPLAYERNAME >= SKINNAMESIZE+2); I_Assert(MAXPLAYERNAME >= SKINNAMESIZE+2);
boolean canApplyNameChange = true;
if (netgame == true) if (netgame == true)
{ {
// Check if a player is currently using the name, case-insensitively. canApplyNameChange = IsPlayerNameUnique(realname, newplayernum);
// We only do this if online, because it doesn't matter if there are multiple Eggrobo *off*line.
// See also EnsurePlayerNameIsGood
for (ix = 0; ix < MAXPLAYERS; ix++)
{
if (ix == newplayernum)
continue;
if (playeringame[ix] == false)
continue;
if (strcasecmp(realname, player_names[ix]) != 0)
continue;
break;
}
} }
if (ix == MAXPLAYERS) if (canApplyNameChange)
{ {
// No conflict detected! // No conflict detected!
sprintf(player_names[newplayernum], "%s", realname); sprintf(player_names[newplayernum], "%s", realname);

View file

@ -5986,7 +5986,15 @@ static int lib_kSetNameForBot(lua_State *L)
if (!player->bot) if (!player->bot)
return luaL_error(L, "You may only change bot names."); return luaL_error(L, "You may only change bot names.");
K_SetNameForBot(player-players, realname); // Doing this to avoid a discarded const warning:
char modifiedname[MAXPLAYERNAME+1] = "";
strcpy(modifiedname, realname);
if (!IsPlayerNameGood(modifiedname))
return luaL_error(L, "Invalid bot name - it must be between %d and %d characters of length, "
"not start with a space, @ or ~ characters, and it must be composed of valid ASCII characters.", 1, MAXPLAYERNAME);
K_SetNameForBot(player-players, modifiedname);
return 0; return 0;
} }