Compare commits

...

9 Commits

Author SHA1 Message Date
Rainyan
63f329210b
Merge 69988c8b98 into 1819f491b5 2025-11-25 23:21:49 +00:00
dependabot[bot]
1819f491b5
Bump actions/checkout from 5 to 6 (#2378)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 15:55:07 +00:00
Rain
69988c8b98
Use MAX_TARGET_LENGTH
Use MAX_TARGET_LENGTH over defining a new custom length
2023-12-09 11:21:57 +02:00
Rain
3b6f18e3b4
Fix client validity checks
Unify the client validity checks with AddTargetsToMenuByAuthId checks
2023-10-15 22:05:25 +03:00
Rain
9b06d85771
Don't attempt to get auth string for unauthorized clients 2023-10-15 21:29:51 +03:00
Rain
67f5fcdb25
Refactor
In function "PrepareBan", use the global PlayerInfo struct array
members directly, instead of passing them as function parameters.
2023-10-15 20:58:56 +03:00
Rain
5ac6be0497
Use userid to find client when possible
Only fall back to authid lookup if userid no longer resolved to client index
2023-10-15 20:49:37 +03:00
Rain
f9ec38103a
Use auth strings when banning from menu
When an admin initiates a ban from a BaseBans GUI menu, track players by
their AuthId (SteamID) instead of userid, so that the admin is able to
target players who disconnect after that menu was constructed.

If the target player is still connected, use their userid to ban the
same as before this commit.

If the target has disconnected, write a ban using their stored AuthId
value, as with "sm_addban".

This commit also revertss the `(admin==0)` check from PrepareBan that
was mistakenly added by bf7212889b,
because it would prevent banning from server/RCON (client index 0).
2023-10-15 19:56:51 +03:00
Rain
bf7212889b Fix invalid client index in Basebans menu
Fix #1768

The `sm_admin`-triggered Menu flow for banning players is caching client
indices inside the basebans.sp `PlayerInfo` struct, and can then
incorrectly use them in the menu callback without checking for the
related client's UserId validity. This leads to bug #1768 occurring when
the ban target player disconnects from the server before the banning
admin could complete the banmenu UI flow.

Since the related menu callbacks can't rely on the cached client index,
I have removed the basebans.sp `PlayerInfo.banTarget` member entirely,
in favor of the `PlayerInfo.banTarget`, and instead call
`GetClientOfUserId(...)` to get & validate the target client index where
necessary. The `PrepareBan(...)` function has been refactored to take a
ban target UserId (instead of the target client index) accordingly.
2023-05-11 23:56:40 +03:00
7 changed files with 174 additions and 61 deletions

View File

@ -36,7 +36,7 @@ jobs:
MYSQL_VERSION: '5.7'
MMSOURCE_VERSION: '1.12'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive
path: sourcemod

View File

@ -12,20 +12,20 @@ jobs:
mock:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone sourcemod
with:
submodules: recursive
path: sourcemod
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone metamod-source
with:
repository: alliedmodders/metamod-source
submodules: recursive
path: metamod-source
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone hl2sdk-mock
with:
repository: alliedmodders/hl2sdk-mock

View File

@ -25,7 +25,7 @@ jobs:
env:
ARCH: x86,x86_64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive

View File

@ -10,7 +10,7 @@ jobs:
update_translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive

View File

@ -15,7 +15,7 @@ jobs:
check_translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
name: Setup Python 3.10

View File

@ -51,10 +51,10 @@ public Plugin myinfo =
TopMenu hTopMenu;
enum struct PlayerInfo {
int banTarget;
int banTargetUserId;
int banTime;
int isWaitingForChatReason;
char banTargetAuthId[MAX_AUTHID_LENGTH];
}
PlayerInfo playerinfo[MAXPLAYERS+1];
@ -387,7 +387,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
if(playerinfo[client].isWaitingForChatReason && !IsChatTrigger())
{
playerinfo[client].isWaitingForChatReason = false;
PrepareBan(client, playerinfo[client].banTarget, playerinfo[client].banTime, sArgs);
PrepareBan(client, playerinfo[client].banTime, sArgs);
return Plugin_Stop;
}

View File

@ -31,59 +31,71 @@
* Version: $Id$
*/
void PrepareBan(int client, int target, int time, const char[] reason)
void PrepareBan(int adminClient, int time, const char[] reason)
{
int originalTarget = GetClientOfUserId(playerinfo[client].banTargetUserId);
if (originalTarget != target)
{
if (client == 0)
{
PrintToServer("[SM] %t", "Player no longer available");
}
else
{
PrintToChat(client, "[SM] %t", "Player no longer available");
}
return;
}
char name[MAX_NAME_LENGTH];
GetClientName(target, name, sizeof(name));
char name[MAX_TARGET_LENGTH];
GetTargetName(playerinfo[adminClient].banTargetUserId, playerinfo[adminClient].banTargetAuthId, name, sizeof(name));
if (!time)
{
if (reason[0] == '\0')
{
ShowActivity(client, "%t", "Permabanned player", name);
ShowActivity(adminClient, "%t", "Permabanned player", name);
}
else
{
ShowActivity(client, "%t", "Permabanned player reason", name, reason);
ShowActivity(adminClient, "%t", "Permabanned player reason", name, reason);
}
}
else
{
if (reason[0] == '\0')
{
ShowActivity(client, "%t", "Banned player", name, time);
ShowActivity(adminClient, "%t", "Banned player", name, time);
}
else
{
ShowActivity(client, "%t", "Banned player reason", name, time, reason);
ShowActivity(adminClient, "%t", "Banned player reason", name, time, reason);
}
}
LogAction(client, target, "\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")", client, target, time, reason);
int target = (playerinfo[adminClient].banTargetUserId == 0)
? 0 : GetClientOfUserId(playerinfo[adminClient].banTargetUserId);
if (reason[0] == '\0')
if (target == 0)
{
BanClient(target, time, BANFLAG_AUTO, "Banned", "Banned", "sm_ban", client);
target = GetClientOfAuthId(playerinfo[adminClient].banTargetAuthId);
}
// Ban & kick if target is connected, else record the ban with authid
if (target != 0)
{
LogAction(adminClient,
target,
"\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")",
adminClient,
target,
time,
reason);
BanClient(target, time, BANFLAG_AUTO,
(reason[0] == '\0') ? "Banned" : reason,
(reason[0] == '\0') ? "Banned" : reason,
"sm_ban", adminClient);
}
else
{
BanClient(target, time, BANFLAG_AUTO, reason, reason, "sm_ban", client);
LogAction(adminClient,
target,
"\"%L\" added ban (minutes \"%d\") (id \"%s\") (reason \"%s\")",
adminClient,
time,
playerinfo[adminClient].banTargetAuthId,
reason);
BanIdentity(playerinfo[adminClient].banTargetAuthId, time, BANFLAG_AUTHID,
(reason[0] == '\0') ? "Banned" : reason,
"sm_addban", adminClient);
}
}
@ -96,17 +108,20 @@ void DisplayBanTargetMenu(int client)
menu.SetTitle(title);
menu.ExitBackButton = CheckCommandAccess(client, "sm_admin", ADMFLAG_GENERIC, false);
AddTargetsToMenu2(menu, client, COMMAND_FILTER_NO_BOTS|COMMAND_FILTER_CONNECTED);
AddTargetsToMenuByAuthId(menu, client, COMMAND_FILTER_NO_BOTS|COMMAND_FILTER_CONNECTED, AuthId_Steam2);
menu.Display(client, MENU_TIME_FOREVER);
}
void DisplayBanTimeMenu(int client)
{
char targetName[MAX_TARGET_LENGTH];
GetTargetName(playerinfo[client].banTargetUserId, playerinfo[client].banTargetAuthId, targetName, sizeof(targetName));
Menu menu = new Menu(MenuHandler_BanTimeList);
char title[100];
Format(title, sizeof(title), "%T: %N", "Ban player", client, playerinfo[client].banTarget);
Format(title, sizeof(title), "%T: %s", "Ban player", client, targetName);
menu.SetTitle(title);
menu.ExitBackButton = true;
@ -123,10 +138,13 @@ void DisplayBanTimeMenu(int client)
void DisplayBanReasonMenu(int client)
{
char name[MAX_TARGET_LENGTH];
GetTargetName(playerinfo[client].banTargetUserId, playerinfo[client].banTargetAuthId, name, sizeof(name));
Menu menu = new Menu(MenuHandler_BanReasonList);
char title[100];
Format(title, sizeof(title), "%T: %N", "Ban reason", client, playerinfo[client].banTarget);
Format(title, sizeof(title), "%T: %s", "Ban reason", client, name);
menu.SetTitle(title);
menu.ExitBackButton = true;
@ -199,10 +217,10 @@ public int MenuHandler_BanReasonList(Menu menu, MenuAction action, int param1, i
else
{
char info[64];
menu.GetItem(param2, info, sizeof(info));
PrepareBan(param1, playerinfo[param1].banTarget, playerinfo[param1].banTime, info);
PrepareBan(param1, playerinfo[param1].banTime, info);
}
}
@ -224,26 +242,13 @@ public int MenuHandler_BanPlayerList(Menu menu, MenuAction action, int param1, i
}
else if (action == MenuAction_Select)
{
char info[32], name[32];
int userid, target;
char name[32];
menu.GetItem(param2, playerinfo[param1].banTargetAuthId, sizeof(PlayerInfo::banTargetAuthId), _, name, sizeof(name));
menu.GetItem(param2, info, sizeof(info), _, name, sizeof(name));
userid = StringToInt(info);
int target = GetClientOfAuthId(playerinfo[param1].banTargetAuthId);
playerinfo[param1].banTargetUserId = (target == 0) ? 0 : GetClientUserId(target);
if ((target = GetClientOfUserId(userid)) == 0)
{
PrintToChat(param1, "[SM] %t", "Player no longer available");
}
else if (!CanUserTarget(param1, target))
{
PrintToChat(param1, "[SM] %t", "Unable to target");
}
else
{
playerinfo[param1].banTarget = target;
playerinfo[param1].banTargetUserId = userid;
DisplayBanTimeMenu(param1);
}
DisplayBanTimeMenu(param1);
}
return 0;
@ -316,9 +321,117 @@ public Action Command_Ban(int client, int args)
}
playerinfo[client].banTargetUserId = GetClientUserId(target);
GetClientAuthId(target, AuthId_Steam2, playerinfo[client].banTargetAuthId, sizeof(PlayerInfo::banTargetAuthId));
int time = StringToInt(s_time);
PrepareBan(client, target, time, Arguments[len]);
PrepareBan(client, time, Arguments[len]);
return Plugin_Handled;
}
int GetClientOfAuthId(const char[] authid, AuthIdType authIdType=AuthId_Steam2)
{
char compareId[MAX_AUTHID_LENGTH];
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientConnected(client) || IsClientInKickQueue(client) || !IsClientAuthorized(client))
{
continue;
}
if (!GetClientAuthId(client, authIdType, compareId, sizeof(compareId)))
{
continue;
}
if (StrEqual(compareId, authid))
{
return client;
}
}
return 0;
}
void GetTargetName(int userid, const char[] authid, char[] out, int maxlen)
{
int client = GetClientOfUserId(userid);
if (client)
{
Format(out, maxlen, "%N", client);
}
else
{
// if client was not in game, use their authid as the name instead
strcopy(out, maxlen, authid);
}
}
/**
* Adds targets to an admin menu.
*
* Each client is displayed as: name (authid)
* Each item contains the authid as a string for its info.
*
* @param menu Menu Handle.
* @param source_client Source client, or 0 to ignore immunity.
* @param flags COMMAND_FILTER flags from commandfilters.inc.
* @return Number of clients added.
*/
int AddTargetsToMenuByAuthId(Menu menu, int source_client, int flags, AuthIdType authIdType)
{
char authid[MAX_AUTHID_LENGTH];
char name[MAX_NAME_LENGTH];
char display[sizeof(name) + sizeof(authid) + 3];
int num_clients;
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientConnected(i) || IsClientInKickQueue(i))
{
continue;
}
if (!IsClientAuthorized(i))
{
continue;
}
if (((flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS)
&& IsFakeClient(i))
{
continue;
}
if (((flags & COMMAND_FILTER_CONNECTED) != COMMAND_FILTER_CONNECTED)
&& !IsClientInGame(i))
{
continue;
}
if (((flags & COMMAND_FILTER_ALIVE) == COMMAND_FILTER_ALIVE)
&& !IsPlayerAlive(i))
{
continue;
}
if (((flags & COMMAND_FILTER_DEAD) == COMMAND_FILTER_DEAD)
&& IsPlayerAlive(i))
{
continue;
}
if ((source_client && ((flags & COMMAND_FILTER_NO_IMMUNITY) != COMMAND_FILTER_NO_IMMUNITY))
&& !CanUserTarget(source_client, i))
{
continue;
}
GetClientAuthId(i, authIdType, authid, sizeof(authid));
GetClientName(i, name, sizeof(name));
Format(display, sizeof(display), "%s (%s)", name, authid);
menu.AddItem(authid, display);
num_clients++;
}
return num_clients;
}