mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
PluginSystem: add callback for chatroom receiver
Allow plugins to block chat msg's based on their text.
This commit is contained in:
parent
425f1dc5da
commit
b5616999ab
@ -177,7 +177,7 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
|
|||||||
|
|
||||||
for (auto& callback : !g_PluginSystem.GetConnectClientCallbacks())
|
for (auto& callback : !g_PluginSystem.GetConnectClientCallbacks())
|
||||||
{
|
{
|
||||||
if (!callback(pServer, pClient, pChallenge))
|
if (!callback.Function()(pServer, pClient, pChallenge))
|
||||||
{
|
{
|
||||||
pClient->Disconnect(REP_MARK_BAD, "#Valve_Reject_Banned");
|
pClient->Disconnect(REP_MARK_BAD, "#Valve_Reject_Banned");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "engine/server/server.h"
|
#include "engine/server/server.h"
|
||||||
#include "game/shared/usercmd.h"
|
#include "game/shared/usercmd.h"
|
||||||
#include "game/server/util_server.h"
|
#include "game/server/util_server.h"
|
||||||
|
#include "pluginsystem/pluginsystem.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// This is called when a new game is started. (restart, map)
|
// This is called when a new game is started. (restart, map)
|
||||||
@ -77,8 +78,39 @@ ServerClass* CServerGameDLL::GetAllServerClasses(void)
|
|||||||
return CallVFunc<ServerClass*>(index, this);
|
return CallVFunc<ServerClass*>(index, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConVar chat_debug("chat_debug", "0", FCVAR_RELEASE, "Enables chat-related debug printing.");
|
||||||
|
|
||||||
void __fastcall CServerGameDLL::OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat)
|
void __fastcall CServerGameDLL::OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat)
|
||||||
{
|
{
|
||||||
|
const CGlobalVars* globals = *g_pGlobals;
|
||||||
|
if (senderId > 0)
|
||||||
|
{
|
||||||
|
if (senderId <= globals->m_nMaxPlayers && senderId != 0xFFFF)
|
||||||
|
{
|
||||||
|
CPlayer* player = reinterpret_cast<CPlayer*>(globals->m_pEdicts[senderId + 30728]);
|
||||||
|
|
||||||
|
if (player && player->IsConnected())
|
||||||
|
{
|
||||||
|
for (auto& cb : !g_PluginSystem.GetChatMessageCallbacks())
|
||||||
|
{
|
||||||
|
if (!cb.Function()(player, text, sv_forceChatToTeamOnly->GetBool()))
|
||||||
|
{
|
||||||
|
if (chat_debug.GetBool())
|
||||||
|
{
|
||||||
|
char moduleName[MAX_PATH] = {};
|
||||||
|
|
||||||
|
V_UnicodeToUTF8(V_UnqualifiedFileName(cb.ModuleName()), moduleName, MAX_PATH);
|
||||||
|
|
||||||
|
Msg(eDLL_T::SERVER, "[%s] Plugin blocked chat message from '%s' (%llu): \"%s\"\n", moduleName, player->GetNetName(), player->GetPlatformUserId(), text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set isTeamChat to false so that we can let the convar sv_forceChatToTeamOnly decide whether team chat should be enforced
|
// set isTeamChat to false so that we can let the convar sv_forceChatToTeamOnly decide whether team chat should be enforced
|
||||||
// this isn't a great way of doing it but it works so meh
|
// this isn't a great way of doing it but it works so meh
|
||||||
CServerGameDLL__OnReceivedSayTextMessage(thisptr, senderId, text, false);
|
CServerGameDLL__OnReceivedSayTextMessage(thisptr, senderId, text, false);
|
||||||
|
@ -13,8 +13,12 @@ struct PluginHelpWithAnything_t
|
|||||||
|
|
||||||
enum class ePluginCallback : int16_t
|
enum class ePluginCallback : int16_t
|
||||||
{
|
{
|
||||||
CModAppSystemGroup_Create = 0,
|
// !! - WARNING: if any existing values are changed, you must increment INTERFACEVERSION_PLUGINSYSTEM - !!
|
||||||
CServer_ConnectClient
|
|
||||||
|
CModAppSystemGroup_Create = 0,
|
||||||
|
CServer_ConnectClient = 1,
|
||||||
|
SV_RegisterScriptFunctions = 2,
|
||||||
|
OnReceivedChatMessage = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
ePluginHelp m_nHelpID;
|
ePluginHelp m_nHelpID;
|
||||||
|
@ -131,7 +131,16 @@ CUtlVector<CPluginSystem::PluginInstance_t>& CPluginSystem::GetInstances()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help)
|
void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help)
|
||||||
{
|
{
|
||||||
#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast<fn>(function)
|
#define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast<fn>(function); callback.GetCallbacks().Tail().SetModuleName(moduleName)
|
||||||
|
|
||||||
|
if (!help->m_pFunction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// [rexx]: This fetches the path to the module that contains the requested callback function.
|
||||||
|
// The module name is fetched so that callbacks can be identified by the plugin that they came from.
|
||||||
|
// This must use the wide-char version of this func, as file paths may contain non-ASCII characters and we don't really want those to break.
|
||||||
|
wchar_t moduleName[MAX_PATH] = {};
|
||||||
|
GetMappedFileNameW((HANDLE)-1, help->m_pFunction, moduleName, MAX_PATH);
|
||||||
|
|
||||||
switch (help->m_nCallbackID)
|
switch (help->m_nCallbackID)
|
||||||
{
|
{
|
||||||
@ -145,6 +154,11 @@ void CPluginSystem::AddCallback(PluginHelpWithAnything_t* help)
|
|||||||
ADD_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction);
|
ADD_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PluginHelpWithAnything_t::ePluginCallback::OnReceivedChatMessage:
|
||||||
|
{
|
||||||
|
ADD_PLUGIN_CALLBACK(OnChatMessageFn, GetChatMessageCallbacks(), help->m_pFunction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -160,6 +174,9 @@ void CPluginSystem::RemoveCallback(PluginHelpWithAnything_t* help)
|
|||||||
{
|
{
|
||||||
#define REMOVE_PLUGIN_CALLBACK(fn, callback, function) callback -= reinterpret_cast<fn>(function)
|
#define REMOVE_PLUGIN_CALLBACK(fn, callback, function) callback -= reinterpret_cast<fn>(function)
|
||||||
|
|
||||||
|
if (!help->m_pFunction)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (help->m_nCallbackID)
|
switch (help->m_nCallbackID)
|
||||||
{
|
{
|
||||||
case PluginHelpWithAnything_t::ePluginCallback::CModAppSystemGroup_Create:
|
case PluginHelpWithAnything_t::ePluginCallback::CModAppSystemGroup_Create:
|
||||||
@ -172,6 +189,11 @@ void CPluginSystem::RemoveCallback(PluginHelpWithAnything_t* help)
|
|||||||
REMOVE_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction);
|
REMOVE_PLUGIN_CALLBACK(ConnectClientFn, GetConnectClientCallbacks(), help->m_pFunction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PluginHelpWithAnything_t::ePluginCallback::OnReceivedChatMessage:
|
||||||
|
{
|
||||||
|
REMOVE_PLUGIN_CALLBACK(OnChatMessageFn, GetChatMessageCallbacks(), help->m_pFunction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
class CModAppSystemGroup;
|
class CModAppSystemGroup;
|
||||||
class CServer;
|
class CServer;
|
||||||
class CClient;
|
class CClient;
|
||||||
|
class CPlayer;
|
||||||
struct user_creds_s;
|
struct user_creds_s;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -82,6 +83,32 @@ private:
|
|||||||
CUtlVector<T> m_vCallbacks;
|
CUtlVector<T> m_vCallbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class CPluginCallback
|
||||||
|
{
|
||||||
|
friend class CPluginSystem;
|
||||||
|
public:
|
||||||
|
CPluginCallback(T f) : function(f) {};
|
||||||
|
|
||||||
|
inline const T& Function() { return function; };
|
||||||
|
inline const wchar_t* ModuleName() { return moduleName; };
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline void SetModuleName(wchar_t* name)
|
||||||
|
{
|
||||||
|
wcscpy_s(moduleName, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
T function;
|
||||||
|
wchar_t moduleName[MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
class CPluginSystem : IPluginSystem
|
class CPluginSystem : IPluginSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -120,10 +147,11 @@ public:
|
|||||||
|
|
||||||
virtual void* HelpWithAnything(PluginHelpWithAnything_t* help);
|
virtual void* HelpWithAnything(PluginHelpWithAnything_t* help);
|
||||||
|
|
||||||
#define CREATE_PLUGIN_CALLBACK(typeName, type, funcName, varName) public: using typeName = type; CPluginCallbackList<typeName>& funcName() { return varName; } private: CPluginCallbackList<typeName> varName;
|
#define CREATE_PLUGIN_CALLBACK(typeName, type, funcName, varName) public: using typeName = type; CPluginCallbackList<CPluginCallback<typeName>>& funcName() { return varName; } private: CPluginCallbackList<CPluginCallback<typeName>> varName;
|
||||||
|
|
||||||
CREATE_PLUGIN_CALLBACK(CreateFn, bool(*)(CModAppSystemGroup*), GetCreateCallbacks, createCallbacks);
|
CREATE_PLUGIN_CALLBACK(CreateFn, bool(*)(CModAppSystemGroup*), GetCreateCallbacks, createCallbacks);
|
||||||
CREATE_PLUGIN_CALLBACK(ConnectClientFn, bool(*)(CServer*, CClient*, user_creds_s*), GetConnectClientCallbacks, connectClientCallbacks);
|
CREATE_PLUGIN_CALLBACK(ConnectClientFn, bool(*)(CServer*, CClient*, user_creds_s*), GetConnectClientCallbacks, connectClientCallbacks);
|
||||||
|
CREATE_PLUGIN_CALLBACK(OnChatMessageFn, bool(*)(CPlayer*, const char*, bool), GetChatMessageCallbacks, chatMessageCallbacks);
|
||||||
|
|
||||||
#undef CREATE_PLUGIN_CALLBACK
|
#undef CREATE_PLUGIN_CALLBACK
|
||||||
|
|
||||||
@ -140,4 +168,4 @@ FORCEINLINE CPluginSystem* PluginSystem()
|
|||||||
// Monitor this and performance profile this if fps drops are detected.
|
// Monitor this and performance profile this if fps drops are detected.
|
||||||
#define CALL_PLUGIN_CALLBACKS(callback, ...) \
|
#define CALL_PLUGIN_CALLBACKS(callback, ...) \
|
||||||
for (auto& cb : !callback) \
|
for (auto& cb : !callback) \
|
||||||
cb(__VA_ARGS__)
|
cb.Function()(__VA_ARGS__)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#define INCORRECT_PATH_SEPARATOR_S "/"
|
#define INCORRECT_PATH_SEPARATOR_S "/"
|
||||||
#define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES ":/\\"
|
#define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES ":/\\"
|
||||||
#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
|
#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
|
||||||
|
#define PATHSEPARATORW(c) ((c) == L'\\' || (c) == L'/')
|
||||||
#elif POSIX || defined( _PS3 )
|
#elif POSIX || defined( _PS3 )
|
||||||
#define CORRECT_PATH_SEPARATOR '/'
|
#define CORRECT_PATH_SEPARATOR '/'
|
||||||
#define CORRECT_PATH_SEPARATOR_S "/"
|
#define CORRECT_PATH_SEPARATOR_S "/"
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#define INCORRECT_PATH_SEPARATOR_S "\\"
|
#define INCORRECT_PATH_SEPARATOR_S "\\"
|
||||||
#define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES "/"
|
#define CHARACTERS_WHICH_SEPARATE_DIRECTORY_COMPONENTS_IN_PATHNAMES "/"
|
||||||
#define PATHSEPARATOR(c) ((c) == '/')
|
#define PATHSEPARATOR(c) ((c) == '/')
|
||||||
|
#define PATHSEPARATORW(c) ((c) == L'/')
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COPY_ALL_CHARACTERS -1
|
#define COPY_ALL_CHARACTERS -1
|
||||||
@ -156,6 +158,8 @@ inline void V_MakeAbsolutePath(char* pOut, size_t outLen, const char* pPath, con
|
|||||||
size_t V_StripLastDir(char* dirName, size_t maxLen);
|
size_t V_StripLastDir(char* dirName, size_t maxLen);
|
||||||
// Returns a pointer to the unqualified file name (no path) of a file name
|
// Returns a pointer to the unqualified file name (no path) of a file name
|
||||||
const char* V_UnqualifiedFileName(const char* in);
|
const char* V_UnqualifiedFileName(const char* in);
|
||||||
|
const wchar_t* V_UnqualifiedFileName(const wchar_t* in);
|
||||||
|
|
||||||
// Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary
|
// Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary
|
||||||
void V_ComposeFileName(const char* path, const char* filename, char* dest, size_t destSize);
|
void V_ComposeFileName(const char* path, const char* filename, char* dest, size_t destSize);
|
||||||
|
|
||||||
|
@ -503,8 +503,15 @@ int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes
|
|||||||
cchResult = wcstombs(pUTF8, pUnicode, cubDestSizeInBytes);
|
cchResult = wcstombs(pUTF8, pUnicode, cubDestSizeInBytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cubDestSizeInBytes > 0)
|
if (cchResult <= 0 || cchResult > cubDestSizeInBytes)
|
||||||
pUTF8[cubDestSizeInBytes - 1] = 0;
|
{
|
||||||
|
if (cchResult != cubDestSizeInBytes || pUTF8[cubDestSizeInBytes - 1] != '\0')
|
||||||
|
{
|
||||||
|
*pUTF8 = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pUTF8[cchResult] = '\0';
|
||||||
|
|
||||||
return cchResult;
|
return cchResult;
|
||||||
}
|
}
|
||||||
@ -1248,6 +1255,26 @@ const char* V_UnqualifiedFileName(const char* in)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wchar_t* V_UnqualifiedFileName(const wchar_t* in)
|
||||||
|
{
|
||||||
|
Assert(in);
|
||||||
|
|
||||||
|
const wchar_t* out = in;
|
||||||
|
|
||||||
|
while (*in)
|
||||||
|
{
|
||||||
|
if (PATHSEPARATORW(*in))
|
||||||
|
{
|
||||||
|
// +1 to skip the slash
|
||||||
|
out = in + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Composes a path and filename together, inserting a path separator
|
// Purpose: Composes a path and filename together, inserting a path separator
|
||||||
// if need be
|
// if need be
|
||||||
|
Loading…
x
Reference in New Issue
Block a user