Mute player's chat feature

This commit is contained in:
Diavolo 2022-01-01 14:08:02 +01:00
parent 6d80943380
commit 57d598617c
No known key found for this signature in database
GPG Key ID: FA77F074E98D98A5
6 changed files with 121 additions and 7 deletions

View File

@ -71,7 +71,7 @@ namespace Components
{ "9", 33554432 }, { "9", 33554432 },
}; };
unsigned int Bots::GetClientNum(Game::client_s* cl) unsigned int Bots::GetClientNum(const Game::client_s* cl)
{ {
unsigned int num; unsigned int num;

View File

@ -7,7 +7,7 @@ namespace Components
public: public:
Bots(); Bots();
~Bots(); ~Bots();
static unsigned int GetClientNum(Game::client_s*); static unsigned int GetClientNum(const Game::client_s*);
static bool IsValidClientNum(unsigned int); static bool IsValidClientNum(unsigned int);
private: private:

View File

@ -8,17 +8,26 @@ namespace Components
bool Chat::SendChat; bool Chat::SendChat;
std::unordered_set<std::uint64_t> Chat::MuteList;
const char* Chat::EvaluateSay(char* text, Game::gentity_t* player) const char* Chat::EvaluateSay(char* text, Game::gentity_t* player)
{ {
SendChat = true; Chat::SendChat = true;
if (text[1] == '/') if (text[1] == '/')
{ {
SendChat = false; Chat::SendChat = false;
text[1] = text[0]; text[1] = text[0];
++text; ++text;
} }
if (Chat::MuteList.find(Game::svs_clients[player->s.number].steamID) != Chat::MuteList.end())
{
Chat::SendChat = false;
Game::SV_GameSendServerCommand(player->s.number, 0,
Utils::String::VA("%c \"You are muted\"", 0x65));
}
TextRenderer::StripMaterialTextIcons(text, text, strlen(text) + 1); TextRenderer::StripMaterialTextIcons(text, text, strlen(text) + 1);
Game::Scr_AddEntity(player); Game::Scr_AddEntity(player);
@ -194,9 +203,94 @@ namespace Components
} }
} }
void Chat::MuteClient(const Game::client_t* client)
{
if (Chat::MuteList.find(client->steamID) == Chat::MuteList.end())
{
Chat::MuteList.insert(client->steamID);
Logger::Print("%s was muted\n", client->name);
Game::SV_GameSendServerCommand(Bots::GetClientNum(client), 0,
Utils::String::VA("%c \"You were muted\"", 0x65));
return;
}
Logger::Print("%s is already muted\n", client->name);
Game::SV_GameSendServerCommand(-1, 0,
Utils::String::VA("%c \"%s is already muted\"", 0x65, client->name));
}
void Chat::UnmuteClient(const Game::client_t* client)
{
Chat::MuteList.erase(client->steamID);
Logger::Print("%s was unmuted\n", client->name);
Game::SV_GameSendServerCommand(Bots::GetClientNum(client), 0,
Utils::String::VA("%c \"You were unmuted\"", 0x65));
}
void Chat::AddChatCommands()
{
Command::AddSV("muteClient", [](Command::Params* params)
{
if (!Dvar::Var("sv_running").get<bool>())
{
Logger::Print("Server is not running.\n");
return;
}
const auto* cmd = params->get(0);
if (params->length() < 2)
{
Logger::Print("Usage: %s <client number> : prevent the player from using the chat\n", cmd);
return;
}
const auto* client = Game::SV_GetPlayerByNum();
if (client != nullptr)
{
Chat::MuteClient(client);
}
});
Command::AddSV("unmute", [](Command::Params* params)
{
if (!Dvar::Var("sv_running").get<bool>())
{
Logger::Print("Server is not running.\n");
return;
}
const auto* cmd = params->get(0);
if (params->length() < 2)
{
Logger::Print("Usage: %s <client number>\n%s all = unmute everyone\n", cmd, cmd);
return;
}
const auto* client = Game::SV_GetPlayerByNum();
if (client == nullptr)
{
if (params->get(1) == "all"s)
{
Logger::Print("All players were unmuted\n");
Chat::MuteList.clear();
}
}
else
{
Chat::UnmuteClient(client);
}
});
}
Chat::Chat() Chat::Chat()
{ {
cg_chatWidth = Dvar::Register<int>("cg_chatWidth", 52, 1, INT_MAX, Game::DVAR_FLAG_SAVED, "The normalized maximum width of a chat message"); Dvar::OnInit([]
{
cg_chatWidth = Dvar::Register<int>("cg_chatWidth", 52, 1, std::numeric_limits<int>::max(), Game::DVAR_FLAG_SAVED, "The normalized maximum width of a chat message");
Chat::AddChatCommands();
});
// Intercept chat sending // Intercept chat sending
Utils::Hook(0x4D000B, PreSayStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4D000B, PreSayStub, HOOK_CALL).install()->quick();
@ -206,4 +300,9 @@ namespace Components
// Change logic that does word splitting with new lines for chat messages to support fonticons // Change logic that does word splitting with new lines for chat messages to support fonticons
Utils::Hook(0x592E10, CG_AddToTeamChat_Stub, HOOK_JUMP).install()->quick(); Utils::Hook(0x592E10, CG_AddToTeamChat_Stub, HOOK_JUMP).install()->quick();
} }
Chat::~Chat()
{
Chat::MuteList.clear();
}
} }

View File

@ -7,6 +7,7 @@ namespace Components
static constexpr auto FONT_ICON_CHAT_WIDTH_CALCULATION_MULTIPLIER = 2.0f; static constexpr auto FONT_ICON_CHAT_WIDTH_CALCULATION_MULTIPLIER = 2.0f;
public: public:
Chat(); Chat();
~Chat();
private: private:
static Game::dvar_t** cg_chatHeight; static Game::dvar_t** cg_chatHeight;
@ -15,6 +16,8 @@ namespace Components
static bool SendChat; static bool SendChat;
static std::unordered_set<std::uint64_t> MuteList;
static const char* EvaluateSay(char* text, Game::gentity_t* player); static const char* EvaluateSay(char* text, Game::gentity_t* player);
static void PreSayStub(); static void PreSayStub();
@ -23,5 +26,9 @@ namespace Components
static void CheckChatLineEnd(const char*& inputBuffer, char*& lineBuffer, float& len, int chatHeight, float chatWidth, char*& lastSpacePos, char*& lastFontIconPos, int lastColor); static void CheckChatLineEnd(const char*& inputBuffer, char*& lineBuffer, float& len, int chatHeight, float chatWidth, char*& lastSpacePos, char*& lastFontIconPos, int lastColor);
static void CG_AddToTeamChat(const char* text); static void CG_AddToTeamChat(const char* text);
static void CG_AddToTeamChat_Stub(); static void CG_AddToTeamChat_Stub();
static void MuteClient(const Game::client_t* client);
static void UnmuteClient(const Game::client_t* client);
static void AddChatCommands();
}; };
} }

View File

@ -322,6 +322,8 @@ namespace Game
SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0); SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0);
SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0); SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0);
SV_ClientThink_t SV_ClientThink = SV_ClientThink_t(0x44ADD0); SV_ClientThink_t SV_ClientThink = SV_ClientThink_t(0x44ADD0);
SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0);
SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390);
Sys_Error_t Sys_Error = Sys_Error_t(0x4E0200); Sys_Error_t Sys_Error = Sys_Error_t(0x4E0200);
Sys_FreeFileList_t Sys_FreeFileList = Sys_FreeFileList_t(0x4D8580); Sys_FreeFileList_t Sys_FreeFileList = Sys_FreeFileList_t(0x4D8580);

View File

@ -759,7 +759,7 @@ namespace Game
typedef void(__cdecl * SV_Cmd_EndTokenizedString_t)(); typedef void(__cdecl * SV_Cmd_EndTokenizedString_t)();
extern SV_Cmd_EndTokenizedString_t SV_Cmd_EndTokenizedString; extern SV_Cmd_EndTokenizedString_t SV_Cmd_EndTokenizedString;
typedef void(__cdecl* SV_Cmd_ArgvBuffer_t)(int arg, char* buf, int size); typedef void(__cdecl * SV_Cmd_ArgvBuffer_t)(int arg, char* buf, int size);
extern SV_Cmd_ArgvBuffer_t SV_Cmd_ArgvBuffer; extern SV_Cmd_ArgvBuffer_t SV_Cmd_ArgvBuffer;
typedef void(__cdecl * SV_SetConfigstring_t)(int index, const char* string); typedef void(__cdecl * SV_SetConfigstring_t)(int index, const char* string);
@ -771,9 +771,15 @@ namespace Game
typedef bool(__cdecl * SV_Loaded_t)(); typedef bool(__cdecl * SV_Loaded_t)();
extern SV_Loaded_t SV_Loaded; extern SV_Loaded_t SV_Loaded;
typedef void(__cdecl* SV_ClientThink_t)(client_s*, usercmd_s*); typedef void(__cdecl * SV_ClientThink_t)(client_s*, usercmd_s*);
extern SV_ClientThink_t SV_ClientThink; extern SV_ClientThink_t SV_ClientThink;
typedef client_t*(__cdecl * SV_GetPlayerByName_t)();
extern SV_GetPlayerByName_t SV_GetPlayerByName;
typedef client_t*(__cdecl * SV_GetPlayerByNum_t)();
extern SV_GetPlayerByNum_t SV_GetPlayerByNum;
typedef int(__cdecl * Sys_Error_t)(int, char *, ...); typedef int(__cdecl * Sys_Error_t)(int, char *, ...);
extern Sys_Error_t Sys_Error; extern Sys_Error_t Sys_Error;