From c917e5a857ddffa3a03e7bc8ae27115cd77b25b4 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Thu, 25 Jun 2026 09:02:20 +0200 Subject: [PATCH 1/4] feat(core): Release 2.1.0 - Fixed forced name not changing after renaming / when connecting - Fixed forced names list menu not opening when it was empty - Minor optimization + translations addition - Added ire. name since he made the original forced name plugin - Minor refactoring - Add `GetClientForcedName`, `GetForcedNameByAuthId`, `GetSteam2Variant` --- addons/sourcemod/scripting/NameFilter.sp | 127 +++++++++++++++--- .../translations/namefilter.phrases.txt | 22 +-- 2 files changed, 122 insertions(+), 27 deletions(-) diff --git a/addons/sourcemod/scripting/NameFilter.sp b/addons/sourcemod/scripting/NameFilter.sp index 2f1bb33..1882130 100644 --- a/addons/sourcemod/scripting/NameFilter.sp +++ b/addons/sourcemod/scripting/NameFilter.sp @@ -6,27 +6,33 @@ #pragma semicolon 1 #pragma newdecls required -KeyValues g_Kv; -StringMap g_SMsteamID; +bool g_bLateLoaded = false; +bool g_bNFDebug = false; -char g_sFilePath[PLATFORM_MAX_PATH], g_sSteamID[32], g_sForcedName[64], g_sOriginalName[64], g_sAdminName[64], g_sTime[32]; +int g_iBlockNameChangeEvents[MAXPLAYERS + 1] = {0, ...}; -Regex g_FilterExpr; +char g_sAdminName[64]; +char g_sFilePath[PLATFORM_MAX_PATH]; +char g_sForcedName[64]; +char g_sOriginalName[64]; +char g_sSteamID[32]; +char g_sTime[32]; char g_sFilterChar[2] = ""; + +ConVar g_hNFDebug; +Regex g_FilterExpr; ArrayList g_BannedExprs; ArrayList g_ReplacementNames; -int g_iBlockNameChangeEvents[MAXPLAYERS + 1] = {0, ...}; -ConVar g_hNFDebug; -bool g_bNFDebug = false; -bool g_bLateLoaded = false; +KeyValues g_Kv; +StringMap g_SMsteamID; public Plugin myinfo = { name = "NameFilter", - author = "BotoX, .Rushaway", + author = "BotoX, .Rushaway, ire.", description = "Filters player names + Force names", url = "https://github.com/srcdslab/sm-plugin-NameFilter", - version = "2.0.7" + version = "2.1.0" } public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) @@ -98,15 +104,29 @@ public void OnClientConnected(int client) RequestFrame(OnFrameRequested, pack); } - if (!IsValidClient(client)) - CreateTimer(2.0, CheckClientName, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); + if (IsValidClient(client)) + CreateTimer(3.0, CheckClientName, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); +} + +public void OnClientAuthorized(int client, const char[] auth) +{ + if (IsFakeClient(client)) + return; + + if (GetForcedNameByAuthId(auth, g_sForcedName, sizeof(g_sForcedName))) + { + DataPack pack = new DataPack(); + pack.WriteCell(client); + pack.WriteString(g_sForcedName); + RequestFrame(OnFrameRequested, pack); + } } public Action CheckClientName(Handle timer, int userid) { int client = GetClientOfUserId(userid); - if (client && GetClientAuthId(client, AuthId_Steam2, g_sSteamID, sizeof(g_sSteamID)) && g_SMsteamID.GetString(g_sSteamID, g_sForcedName, sizeof(g_sForcedName))) + if (client && GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) { DataPack pack = new DataPack(); pack.WriteCell(client); @@ -128,6 +148,7 @@ stock void OnFrameRequested(DataPack pack) return; SetClientName(client, sName); + CPrintToChat(client, "%t", "ForcedName_ChatInfo"); } public void OnClientPutInServer(int client) @@ -155,14 +176,17 @@ public Action Event_ChangeName(Event event, const char[] name, bool dontBroadcas return Plugin_Handled; } - if (!IsValidClient(client)) + if (IsValidClient(client)) { char NewName[64]; event.GetString("newname", NewName, sizeof(NewName)); - if (GetClientAuthId(client, AuthId_Steam2, g_sSteamID, sizeof(g_sSteamID)) && g_SMsteamID.GetString(g_sSteamID, g_sForcedName, sizeof(g_sForcedName))) + if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) { if (!StrEqual(NewName, g_sForcedName, false)) + { SetClientName(client, g_sForcedName); + CPrintToChat(client, "%t", "ForcedName_ChatInfo"); + } } } @@ -209,7 +233,7 @@ public Action Command_ForceName(int client, int args) g_Kv.JumpToKey(g_sSteamID, true); g_Kv.SetString("OriginalName", TargetName); g_Kv.SetString("ForcedName", Arg2); - g_SMsteamID.SetString(g_sSteamID, Arg2); + CacheForcedName(g_sSteamID, Arg2); g_Kv.SetString("AdminName", g_sAdminName); FormatTime(g_sTime, sizeof(g_sTime), "%d.%m.%Y %R", GetTime()); g_Kv.SetString("Date", g_sTime); @@ -229,6 +253,8 @@ public Action Command_ForcedNames(int client, int args) Format(MenuBuffer, sizeof(MenuBuffer), "%T", "MenuTitle", client); MainMenu.SetTitle(MenuBuffer); + bool bEmpty = true; + SetUpKeyValues(); if (!g_Kv.GotoFirstSubKey()) { @@ -242,6 +268,8 @@ public Action Command_ForcedNames(int client, int args) // Check if g_sForcedName is empty, if yes then skip this entry if (g_sForcedName[0] == '\0') continue; + + bEmpty = false; Format(MenuBuffer3, sizeof(MenuBuffer3), "%T", "MenuContent", client, g_sForcedName); MainMenu.AddItem(g_sSteamID, MenuBuffer3); } @@ -249,6 +277,12 @@ public Action Command_ForcedNames(int client, int args) } delete g_Kv; + if (bEmpty) + { + Format(MenuBuffer2, sizeof(MenuBuffer2), "%T", "MenuEmpty", client); + MainMenu.AddItem("", MenuBuffer2, ITEMDRAW_DISABLED); + } + MainMenu.ExitButton = true; MainMenu.Display(client, MENU_TIME_FOREVER); @@ -315,6 +349,11 @@ int SubMenuHandle(Menu menu, MenuAction action, int param1, int param2) g_Kv.ExportToFile(g_sFilePath); delete g_Kv; g_SMsteamID.Remove(MenuChoice); + + char sSteamIDVariant[32]; + if (GetSteam2Variant(MenuChoice, sSteamIDVariant, sizeof(sSteamIDVariant))) + g_SMsteamID.Remove(sSteamIDVariant); + CReplyToCommand(param1, "%t", "NameDeleted"); Command_ForcedNames(param1, param2); } @@ -340,13 +379,65 @@ void GetNamesFromCfg() do { g_Kv.GetSectionName(g_sSteamID, sizeof(g_sSteamID)); + + // Skip "banned" and "names" etc. sectionnames because they aren't steamids + if (strncmp(g_sSteamID, "STEAM_", 6, true) != 0) + continue; + g_Kv.GetString("ForcedName", g_sForcedName, sizeof(g_sForcedName)); - g_SMsteamID.SetString(g_sSteamID, g_sForcedName); + CacheForcedName(g_sSteamID, g_sForcedName); } while(g_Kv.GotoNextKey()); delete g_Kv; } +stock void CacheForcedName(const char[] authId, const char[] forcedName) +{ + g_SMsteamID.SetString(authId, forcedName); + + char authVariant[32]; + if (GetSteam2Variant(authId, authVariant, sizeof(authVariant))) + g_SMsteamID.SetString(authVariant, forcedName); +} + +stock bool GetClientForcedName(int client, char[] forcedName, int forcedNameLen) +{ + char authId[32]; + + if (GetClientAuthId(client, AuthId_Steam2, authId, sizeof(authId)) && GetForcedNameByAuthId(authId, forcedName, forcedNameLen)) + return true; + + if (GetClientAuthId(client, AuthId_Steam3, authId, sizeof(authId)) && GetForcedNameByAuthId(authId, forcedName, forcedNameLen)) + return true; + + return false; +} + +stock bool GetForcedNameByAuthId(const char[] authId, char[] forcedName, int forcedNameLen) +{ + if (g_SMsteamID.GetString(authId, forcedName, forcedNameLen)) + return true; + + char authVariant[32]; + if (GetSteam2Variant(authId, authVariant, sizeof(authVariant)) && g_SMsteamID.GetString(authVariant, forcedName, forcedNameLen)) + return true; + + return false; +} + +stock bool GetSteam2Variant(const char[] authId, char[] authVariant, int authVariantLen) +{ + if (strncmp(authId, "STEAM_0:", 8, false) == 0 || strncmp(authId, "STEAM_1:", 8, false) == 0) + { + strcopy(authVariant, authVariantLen, authId); + authVariant[6] = (authId[6] == '0') ? '1' : '0'; + return true; + } + + authVariant[0] = '\0'; + return false; +} + void SetUpKeyValues() { delete g_Kv; @@ -723,4 +814,4 @@ stock bool IsNameOnlyWhitespace(const char[] name) return false; // found a non-whitespace code unit/sequence } return any; // true only if at least one whitespace and no other chars -} +} \ No newline at end of file diff --git a/addons/sourcemod/translations/namefilter.phrases.txt b/addons/sourcemod/translations/namefilter.phrases.txt index 6ba99a4..aff7503 100644 --- a/addons/sourcemod/translations/namefilter.phrases.txt +++ b/addons/sourcemod/translations/namefilter.phrases.txt @@ -1,29 +1,33 @@ "Phrases" { + "ForcedName_ChatInfo" + { + "en" "{green}[NameFilter] {white}Your name has been changed because it violates server rules. To request a name change, please contact an administrator." + } "Usage" { - "en" "{green}[SM] {white}Usage: sm_forcename " + "en" "{green}[NameFilter] {white}Usage: sm_forcename " } "InvalidSteamID" { - "en" "{green}[SM] {white}This command can't be used on a player without a SteamID." + "en" "{green}[NameFilter] {red}Error: {white}This player does not have a valid SteamID." } "ForcedName" { "#format" "{1:s},{2:s},{3:s}" - "en" "{green}[SM] {white}Forced name {1} on player {2} ({3})" + "en" "{green}[NameFilter] {white}Name of {olive}{2} {white}({3}) has been set to {olive}{1}{white}." } "NameDeleted" { - "en" "{green}[SM] {white}Name has been deleted!" + "en" "{green}[NameFilter] {white}Forced name entry has been removed successfully." } "MenuTitle" { - "en" "Forced names:" + "en" "Forced Names" } "MenuEmpty" { - "en" "There are no forced names!" + "en" "No forced names are currently active." } "MenuContent" { @@ -32,15 +36,15 @@ } "SubMenuTitle" { - "en" "Details about this forced name:" + "en" "Forced Name Details" } "SubMenuContent" { "#format" "{1:s},{2:s},{3:s},{4:s}" - "en" "\nForced name: {1}\nOriginal name: {2}\nAdmin name: {3}\nTime: {4}" + "en" "\nForced Name: {1}\nOriginal Name: {2}\nSet by Admin: {3}\nDate/Time: {4}" } "SubMenuDeleteName" { - "en" "Choose to delete the name." + "en" "Remove this forced name" } } \ No newline at end of file From 52e5e0d31300891c7833499d9389e16d598ea285 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Thu, 25 Jun 2026 09:23:00 +0200 Subject: [PATCH 2/4] Simplify logic --- addons/sourcemod/scripting/NameFilter.sp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/addons/sourcemod/scripting/NameFilter.sp b/addons/sourcemod/scripting/NameFilter.sp index 1882130..d47b40b 100644 --- a/addons/sourcemod/scripting/NameFilter.sp +++ b/addons/sourcemod/scripting/NameFilter.sp @@ -104,24 +104,10 @@ public void OnClientConnected(int client) RequestFrame(OnFrameRequested, pack); } - if (IsValidClient(client)) + if (IsClientConnected(client)) CreateTimer(3.0, CheckClientName, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); } -public void OnClientAuthorized(int client, const char[] auth) -{ - if (IsFakeClient(client)) - return; - - if (GetForcedNameByAuthId(auth, g_sForcedName, sizeof(g_sForcedName))) - { - DataPack pack = new DataPack(); - pack.WriteCell(client); - pack.WriteString(g_sForcedName); - RequestFrame(OnFrameRequested, pack); - } -} - public Action CheckClientName(Handle timer, int userid) { int client = GetClientOfUserId(userid); @@ -164,11 +150,18 @@ public void OnClientPutInServer(int client) g_iBlockNameChangeEvents[client] = 2; SetClientName(client, sName); } + else if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) + { + g_iBlockNameChangeEvents[client] = 2; + SetClientName(client, g_sForcedName); + CPrintToChat(client, "%t", "ForcedName_ChatInfo"); + } } public Action Event_ChangeName(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); + if (g_iBlockNameChangeEvents[client]) { g_iBlockNameChangeEvents[client]--; From 802f4721a5f91d6741bf4d449a095c370e2931f3 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Thu, 25 Jun 2026 09:58:47 +0200 Subject: [PATCH 3/4] Make the logic more robust against map change --- addons/sourcemod/scripting/NameFilter.sp | 35 +++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/addons/sourcemod/scripting/NameFilter.sp b/addons/sourcemod/scripting/NameFilter.sp index d47b40b..7c6dfab 100644 --- a/addons/sourcemod/scripting/NameFilter.sp +++ b/addons/sourcemod/scripting/NameFilter.sp @@ -93,19 +93,26 @@ public void OnClientConnected(int client) if (IsFakeClient(client)) return; + if (!IsValidClient(client)) + { + CreateTimer(3.0, CheckClientName, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); + return; + } + char sName[MAX_NAME_LENGTH]; GetClientName(client, sName, sizeof(sName)); if (FilterName(client, sName)) { - DataPack pack = new DataPack(); - pack.WriteCell(client); - pack.WriteString(sName); - RequestFrame(OnFrameRequested, pack); + g_iBlockNameChangeEvents[client] = 2; + SetClientName(client, sName); + } + else if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) + { + g_iBlockNameChangeEvents[client] = 2; + SetClientName(client, g_sForcedName); + CPrintToChat(client, "%t", "ForcedName_ChatInfo"); } - - if (IsClientConnected(client)) - CreateTimer(3.0, CheckClientName, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); } public Action CheckClientName(Handle timer, int userid) @@ -139,6 +146,9 @@ stock void OnFrameRequested(DataPack pack) public void OnClientPutInServer(int client) { + if (!IsValidClient(client)) + return; + if (IsFakeClient(client)) return; @@ -152,9 +162,14 @@ public void OnClientPutInServer(int client) } else if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) { - g_iBlockNameChangeEvents[client] = 2; - SetClientName(client, g_sForcedName); - CPrintToChat(client, "%t", "ForcedName_ChatInfo"); + + + if (!StrEqual(sName, g_sForcedName, false)) + { + g_iBlockNameChangeEvents[client] = 2; + SetClientName(client, g_sForcedName); + CPrintToChat(client, "%t", "ForcedName_ChatInfo"); + } } } From 16ba083e1416929784a6dfec80fd4ce96a7ebfaf Mon Sep 17 00:00:00 2001 From: Rushaway Date: Thu, 25 Jun 2026 16:41:32 +0200 Subject: [PATCH 4/4] Copilot review --- addons/sourcemod/scripting/NameFilter.sp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/NameFilter.sp b/addons/sourcemod/scripting/NameFilter.sp index 7c6dfab..56e2089 100644 --- a/addons/sourcemod/scripting/NameFilter.sp +++ b/addons/sourcemod/scripting/NameFilter.sp @@ -107,7 +107,7 @@ public void OnClientConnected(int client) g_iBlockNameChangeEvents[client] = 2; SetClientName(client, sName); } - else if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName))) + else if (GetClientForcedName(client, g_sForcedName, sizeof(g_sForcedName)) && !StrEqual(sName, g_sForcedName, false)) { g_iBlockNameChangeEvents[client] = 2; SetClientName(client, g_sForcedName); @@ -192,6 +192,8 @@ public Action Event_ChangeName(Event event, const char[] name, bool dontBroadcas { if (!StrEqual(NewName, g_sForcedName, false)) { + g_iBlockNameChangeEvents[client] = 2; + SetEventBroadcast(event, true); SetClientName(client, g_sForcedName); CPrintToChat(client, "%t", "ForcedName_ChatInfo"); } @@ -254,7 +256,7 @@ public Action Command_ForceName(int client, int args) public Action Command_ForcedNames(int client, int args) { - char MenuBuffer[128], MenuBuffer2[32], MenuBuffer3[128]; + char MenuBuffer[128], MenuBuffer2[128], MenuBuffer3[128]; Menu MainMenu = new Menu(MenuHandle);