Use GameHooks for ChatTriggers.

This commit is contained in:
David Anderson 2015-09-06 12:54:12 -07:00
parent 5757b729ac
commit c54b54ded0
2 changed files with 44 additions and 127 deletions

View File

@ -37,27 +37,13 @@
#include "HalfLife2.h"
#include "logic_bridge.h"
#include "sourcemod.h"
#include "provider.h"
#include <amtl/am-string.h>
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif
ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
ChatTriggers::ChatTriggers() : m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
{
m_PubTrigger = "!";
@ -115,70 +101,43 @@ void ChatTriggers::OnSourceModAllInitialized_Post()
void ChatTriggers::OnSourceModGameInitialized()
{
m_pSayCmd = FindCommand("say");
m_pSayTeamCmd = FindCommand("say_team");
ConCommand *say_team = FindCommand("say_team");
if (m_pSayCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
CommandHook::Callback pre_hook = [this] (const ICommandArgs *args) -> bool {
return this->OnSayCommand_Pre(args);
};
CommandHook::Callback post_hook = [this] (const ICommandArgs *args) -> bool {
return this->OnSayCommand_Post(args);
};
if (ConCommand *say = FindCommand("say")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say, post_hook));
}
if (m_pSayTeamCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (ConCommand *say_team = FindCommand("say_team")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say_team, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
}
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
if (m_bIsINS)
{
m_pSay2Cmd = FindCommand("say2");
if (m_pSay2Cmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (m_bIsINS) {
if (ConCommand *say2 = FindCommand("say2")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
}
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
m_pSaySquadCmd = FindCommand("say_squad");
if (m_pSaySquadCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (ConCommand *say_squad = FindCommand("say_squad")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
}
#endif
}
void ChatTriggers::OnSourceModShutdown()
{
if (m_pSayCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
}
if (m_pSayTeamCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
}
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS && m_pSay2Cmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
if (m_pSaySquadCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#endif
hooks_.clear();
forwardsys->ReleaseForward(m_pShouldFloodBlock);
forwardsys->ReleaseForward(m_pDidFloodBlock);
@ -186,32 +145,21 @@ void ChatTriggers::OnSourceModShutdown()
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
bool ChatTriggers::OnSayCommand_Pre(const ICommandArgs *command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
void ChatTriggers::OnSayCommand_Pre()
{
CCommand command;
#endif
int client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
m_bPluginIgnored = true;
const char *args = command.ArgS();
const char *args = command->ArgS();
if (!args)
{
RETURN_META(MRES_IGNORED);
}
return false;
/* Save these off for post hook as the command data returned from the engine in older engine versions
* can be NULL, despite the data still being there and valid. */
m_Arg0Backup = command.Arg(0);
m_Arg0Backup = command->Arg(0);
size_t len = strlen(args);
#if SOURCE_ENGINE == SE_EPISODEONE
@ -224,9 +172,7 @@ void ChatTriggers::OnSayCommand_Pre()
}
if (len == 0)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
}
#endif
@ -244,9 +190,7 @@ void ChatTriggers::OnSayCommand_Pre()
/* The server normally won't display empty say commands, but in this case it does.
* I don't think it's desired so let's block it. */
if (len <= 2)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
args++;
len--;
@ -275,20 +219,16 @@ void ChatTriggers::OnSayCommand_Pre()
if (client == 0)
{
if (CallOnClientSayCommand(client) >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
RETURN_META(MRES_IGNORED);
return false;
}
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
/* We guarantee the client is connected */
if (!pPlayer || !pPlayer->IsConnected())
{
RETURN_META(MRES_IGNORED);
}
return false;
/* Check if we need to block this message from being sent */
if (ClientIsFlooding(client))
@ -305,8 +245,7 @@ void ChatTriggers::OnSayCommand_Pre()
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
m_bWasFloodedMessage = true;
RETURN_META(MRES_SUPERCEDE);
return true;
}
bool is_trigger = false;
@ -339,26 +278,16 @@ void ChatTriggers::OnSayCommand_Pre()
}
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
if (CallOnClientSayCommand(client) >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
/* Otherwise, let the command continue */
RETURN_META(MRES_IGNORED);
return false;
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
#else
void ChatTriggers::OnSayCommand_Post()
#endif
bool ChatTriggers::OnSayCommand_Post(const ICommandArgs *command)
{
int client = g_ConCmds.GetCommandClient();
@ -387,6 +316,7 @@ void ChatTriggers::OnSayCommand_Post()
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
return false;
}
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)

View File

@ -34,6 +34,7 @@
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "GameHooks.h"
#include <IGameHelpers.h>
#include <compat_wrappers.h>
#include <IForwardSys.h>
@ -55,16 +56,8 @@ public: //SMGlobalClass
char *error,
size_t maxlength);
private: //ConCommand
#if SOURCE_ENGINE == SE_DOTA
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void OnSayCommand_Pre(const CCommand &command);
void OnSayCommand_Post(const CCommand &command);
#else
void OnSayCommand_Pre();
void OnSayCommand_Post();
#endif
bool OnSayCommand_Pre(const ICommandArgs *args);
bool OnSayCommand_Post(const ICommandArgs *args);
public:
unsigned int GetReplyTo();
unsigned int SetReplyTo(unsigned int reply);
@ -75,13 +68,7 @@ private:
bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client);
private:
ConCommand *m_pSayCmd;
ConCommand *m_pSayTeamCmd;
#if SOURCE_ENGINE == SE_EPISODEONE
ConCommand *m_pSay2Cmd;
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
ConCommand *m_pSaySquadCmd;
#endif
ke::Vector<ke::Ref<CommandHook>> hooks_;
ke::AString m_PubTrigger;
ke::AString m_PrivTrigger;
bool m_bWillProcessInPost;