Added global pre and post forwards for client chat (bug 5394, r=psychonic).
This commit is contained in:
		
							parent
							
								
									696f702204
								
							
						
					
					
						commit
						96a8003448
					
				@ -66,6 +66,10 @@ ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
 | 
			
		||||
	m_PubTriggerSize = 1;
 | 
			
		||||
	m_PrivTriggerSize = 1;
 | 
			
		||||
	m_bIsChatTrigger = false;
 | 
			
		||||
	m_bPluginIgnored = false;
 | 
			
		||||
#if SOURCE_ENGINE == SE_EPISODEONE
 | 
			
		||||
	m_bIsINS = false;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChatTriggers::~ChatTriggers()
 | 
			
		||||
@ -109,6 +113,8 @@ void ChatTriggers::OnSourceModAllInitialized()
 | 
			
		||||
{
 | 
			
		||||
	m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
 | 
			
		||||
	m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
 | 
			
		||||
	m_pOnClientSayCmd = g_Forwards.CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
 | 
			
		||||
	m_pOnClientSayCmd_Post = g_Forwards.CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChatTriggers::OnSourceModAllInitialized_Post()
 | 
			
		||||
@ -131,23 +137,62 @@ void ChatTriggers::OnSourceModGameInitialized()
 | 
			
		||||
		SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
 | 
			
		||||
		SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#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);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChatTriggers::OnSourceModShutdown()
 | 
			
		||||
{
 | 
			
		||||
	if (m_pSayTeamCmd)
 | 
			
		||||
	{
 | 
			
		||||
		SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
 | 
			
		||||
		SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
 | 
			
		||||
	}
 | 
			
		||||
	if (m_pSayCmd)
 | 
			
		||||
	{
 | 
			
		||||
		SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
 | 
			
		||||
		SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, 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
 | 
			
		||||
 | 
			
		||||
	g_Forwards.ReleaseForward(m_pShouldFloodBlock);
 | 
			
		||||
	g_Forwards.ReleaseForward(m_pDidFloodBlock);
 | 
			
		||||
	g_Forwards.ReleaseForward(m_pOnClientSayCmd);
 | 
			
		||||
	g_Forwards.ReleaseForward(m_pOnClientSayCmd_Post);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
 | 
			
		||||
@ -158,21 +203,21 @@ void ChatTriggers::OnSayCommand_Pre()
 | 
			
		||||
{
 | 
			
		||||
	CCommand command;
 | 
			
		||||
#endif
 | 
			
		||||
	int client;
 | 
			
		||||
	CPlayer *pPlayer;
 | 
			
		||||
	
 | 
			
		||||
	client = g_ConCmds.GetCommandClient();
 | 
			
		||||
	int client = g_ConCmds.GetCommandClient();
 | 
			
		||||
	m_bIsChatTrigger = false;
 | 
			
		||||
	m_bWasFloodedMessage = false;
 | 
			
		||||
	m_bPluginIgnored = false;
 | 
			
		||||
 | 
			
		||||
	/* The server console cannot do this */
 | 
			
		||||
	if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
 | 
			
		||||
	if (client == 0)
 | 
			
		||||
	{
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
 | 
			
		||||
 | 
			
		||||
	/* We guarantee the client is connected */
 | 
			
		||||
	if (!pPlayer->IsConnected())
 | 
			
		||||
	if (!pPlayer || !pPlayer->IsConnected())
 | 
			
		||||
	{
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
	}
 | 
			
		||||
@ -211,6 +256,14 @@ void ChatTriggers::OnSayCommand_Pre()
 | 
			
		||||
		is_quoted = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const char * pCommandName = command.Arg(0);
 | 
			
		||||
#if SOURCE_ENGINE == SE_EPISODEONE
 | 
			
		||||
	if (m_bIsINS && strcmp(pCommandName, "say2") == 0 && strlen(args) >= 4)
 | 
			
		||||
	{
 | 
			
		||||
		args += 4;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	bool is_trigger = false;
 | 
			
		||||
	bool is_silent = false;
 | 
			
		||||
 | 
			
		||||
@ -227,38 +280,37 @@ void ChatTriggers::OnSayCommand_Pre()
 | 
			
		||||
		args = &args[m_PrivTriggerSize];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!is_trigger)
 | 
			
		||||
	{
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Test if this is actually a command!
 | 
			
		||||
	 */
 | 
			
		||||
	if (!PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
 | 
			
		||||
	if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
 | 
			
		||||
	{
 | 
			
		||||
		CPlayer *pPlayer;
 | 
			
		||||
		if (is_silent 
 | 
			
		||||
			&& g_bSupressSilentFails 
 | 
			
		||||
			&& client != 0
 | 
			
		||||
			&& (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
 | 
			
		||||
			&& pPlayer->GetAdminId() != INVALID_ADMIN_ID)
 | 
			
		||||
		{
 | 
			
		||||
			RETURN_META(MRES_SUPERCEDE);
 | 
			
		||||
		}
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
		m_bIsChatTrigger = true;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * We'll execute it in post.
 | 
			
		||||
		 */
 | 
			
		||||
		m_bWillProcessInPost = true;
 | 
			
		||||
		m_bTriggerWasSilent = is_silent;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_bIsChatTrigger = true;
 | 
			
		||||
	if (m_pOnClientSayCmd->GetFunctionCount() != 0)
 | 
			
		||||
	{
 | 
			
		||||
		cell_t res = Pl_Continue;
 | 
			
		||||
		m_pOnClientSayCmd->PushCell(client);
 | 
			
		||||
		m_pOnClientSayCmd->PushString(pCommandName);
 | 
			
		||||
		m_pOnClientSayCmd->PushString(command.ArgS());
 | 
			
		||||
		m_pOnClientSayCmd->Execute(&res);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * We'll execute it in post.
 | 
			
		||||
	 */
 | 
			
		||||
	m_bWillProcessInPost = true;
 | 
			
		||||
	m_bTriggerWasSilent = is_silent;
 | 
			
		||||
		if (res >= Pl_Handled)
 | 
			
		||||
		{
 | 
			
		||||
			m_bPluginIgnored = (res >= Pl_Stop);
 | 
			
		||||
			RETURN_META(MRES_SUPERCEDE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If we're silent, block */
 | 
			
		||||
	if (is_silent)
 | 
			
		||||
	if (m_bWillProcessInPost || \
 | 
			
		||||
		(is_silent && g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID))
 | 
			
		||||
	{
 | 
			
		||||
		RETURN_META(MRES_SUPERCEDE);
 | 
			
		||||
	}
 | 
			
		||||
@ -269,23 +321,39 @@ void ChatTriggers::OnSayCommand_Pre()
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
 | 
			
		||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
 | 
			
		||||
{
 | 
			
		||||
#else
 | 
			
		||||
void ChatTriggers::OnSayCommand_Post()
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
	m_bIsChatTrigger = false;
 | 
			
		||||
	m_bWasFloodedMessage = false;
 | 
			
		||||
        CCommand command;
 | 
			
		||||
#endif
 | 
			
		||||
	int client = g_ConCmds.GetCommandClient();
 | 
			
		||||
 | 
			
		||||
	if (m_bWillProcessInPost)
 | 
			
		||||
	{
 | 
			
		||||
		/* Reset this for re-entrancy */
 | 
			
		||||
		m_bWillProcessInPost = false;
 | 
			
		||||
		
 | 
			
		||||
		/* Execute the cached command */
 | 
			
		||||
		int client = g_ConCmds.GetCommandClient();
 | 
			
		||||
		unsigned int old = SetReplyTo(SM_REPLY_CHAT);
 | 
			
		||||
		serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
 | 
			
		||||
		SetReplyTo(old);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (m_bPluginIgnored)
 | 
			
		||||
	{
 | 
			
		||||
		m_bPluginIgnored = false;
 | 
			
		||||
	}
 | 
			
		||||
	else if (!m_bWasFloodedMessage && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
 | 
			
		||||
	{	
 | 
			
		||||
		m_pOnClientSayCmd_Post->PushCell(client);
 | 
			
		||||
		m_pOnClientSayCmd_Post->PushString(command.Arg(0));
 | 
			
		||||
		m_pOnClientSayCmd_Post->PushString(command.ArgS());
 | 
			
		||||
		m_pOnClientSayCmd_Post->Execute(NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_bIsChatTrigger = false;
 | 
			
		||||
	m_bWasFloodedMessage = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,11 @@ private:
 | 
			
		||||
private:
 | 
			
		||||
	ConCommand *m_pSayCmd;
 | 
			
		||||
	ConCommand *m_pSayTeamCmd;
 | 
			
		||||
#if SOURCE_ENGINE == SE_EPISODEONE
 | 
			
		||||
	ConCommand *m_pSay2Cmd;
 | 
			
		||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
 | 
			
		||||
	ConCommand *m_pSaySquadCmd;
 | 
			
		||||
#endif
 | 
			
		||||
	char *m_PubTrigger;
 | 
			
		||||
	size_t m_PubTriggerSize;
 | 
			
		||||
	char *m_PrivTrigger;
 | 
			
		||||
@ -80,10 +85,16 @@ private:
 | 
			
		||||
	bool m_bTriggerWasSilent;
 | 
			
		||||
	bool m_bIsChatTrigger;
 | 
			
		||||
	bool m_bWasFloodedMessage;
 | 
			
		||||
	bool m_bPluginIgnored;
 | 
			
		||||
	unsigned int m_ReplyTo;
 | 
			
		||||
	char m_ToExecute[300];
 | 
			
		||||
	IForward *m_pShouldFloodBlock;
 | 
			
		||||
	IForward *m_pDidFloodBlock;
 | 
			
		||||
	IForward *m_pOnClientSayCmd;
 | 
			
		||||
	IForward *m_pOnClientSayCmd_Post;
 | 
			
		||||
#if SOURCE_ENGINE == SE_EPISODEONE
 | 
			
		||||
	bool m_bIsINS;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern ChatTriggers g_ChatTriggers;
 | 
			
		||||
 | 
			
		||||
@ -81,9 +81,6 @@ public OnPluginStart()
 | 
			
		||||
	g_Cvar_Deadtalk = CreateConVar("sm_deadtalk", "0", "Controls how dead communicate. 0 - Off. 1 - Dead players ignore teams. 2 - Dead players talk to living teammates.", 0, true, 0.0, true, 2.0);
 | 
			
		||||
	g_Cvar_Alltalk = FindConVar("sv_alltalk");
 | 
			
		||||
	
 | 
			
		||||
	AddCommandListener(Command_Say, "say");
 | 
			
		||||
	AddCommandListener(Command_Say, "say_team");
 | 
			
		||||
	
 | 
			
		||||
	RegAdminCmd("sm_mute", Command_Mute, ADMFLAG_CHAT, "sm_mute <player> - Removes a player's ability to use voice.");
 | 
			
		||||
	RegAdminCmd("sm_gag", Command_Gag, ADMFLAG_CHAT, "sm_gag <player> - Removes a player's ability to use chat.");
 | 
			
		||||
	RegAdminCmd("sm_silence", Command_Silence, ADMFLAG_CHAT, "sm_silence <player> - Removes a player's ability to use voice or chat.");
 | 
			
		||||
@ -154,13 +151,13 @@ public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Action:Command_Say(client, const String:command[], args)
 | 
			
		||||
public Action:OnClientSayCommand(client, const String:command[], const String:sArgs[])
 | 
			
		||||
{
 | 
			
		||||
	if (client)
 | 
			
		||||
	{
 | 
			
		||||
		if (g_Gagged[client])
 | 
			
		||||
		{
 | 
			
		||||
			return Plugin_Handled;		
 | 
			
		||||
			return Plugin_Stop;		
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@ -75,10 +75,6 @@ public OnPluginStart()
 | 
			
		||||
	g_Cvar_TimeleftInterval = CreateConVar("sm_timeleft_interval", "0.0", "Display timeleft every x seconds. Default 0.", 0, true, 0.0, true, 1800.0);
 | 
			
		||||
	g_Cvar_FriendlyFire = FindConVar("mp_friendlyfire");
 | 
			
		||||
	
 | 
			
		||||
	AddCommandListener(Command_Say, "say");
 | 
			
		||||
	AddCommandListener(Command_Say, "say2");
 | 
			
		||||
	AddCommandListener(Command_Say, "say_team");
 | 
			
		||||
	
 | 
			
		||||
	RegConsoleCmd("timeleft", Command_Timeleft);
 | 
			
		||||
	RegConsoleCmd("nextmap", Command_Nextmap);
 | 
			
		||||
	RegConsoleCmd("motd", Command_Motd);
 | 
			
		||||
@ -236,22 +232,22 @@ public Action:Command_Motd(client, args)
 | 
			
		||||
	return Plugin_Handled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Action:Command_Say(client, const String:command[], argc)
 | 
			
		||||
public OnClientSayCommand_Post(client, const String:command[], const String:sArgs[])
 | 
			
		||||
{
 | 
			
		||||
	decl String:text[192];
 | 
			
		||||
	new startidx = 0;
 | 
			
		||||
	if (GetCmdArgString(text, sizeof(text)) < 1)
 | 
			
		||||
	
 | 
			
		||||
	if (strcopy(text, sizeof(text), sArgs) < 1)
 | 
			
		||||
	{
 | 
			
		||||
		return Plugin_Continue;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (text[strlen(text)-1] == '"')
 | 
			
		||||
	if (text[0] == '"')
 | 
			
		||||
	{
 | 
			
		||||
		text[strlen(text)-1] = '\0';
 | 
			
		||||
		startidx = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(command, "say2", false) == 0)
 | 
			
		||||
	if ((strcmp(command, "say2", false) == 0) && strlen(sArgs) >= 4)
 | 
			
		||||
		startidx += 4;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(text[startidx], "timeleft", false) == 0)
 | 
			
		||||
@ -342,8 +338,6 @@ public Action:Command_Say(client, const String:command[], argc)
 | 
			
		||||
	{
 | 
			
		||||
		ShowMOTDPanel(client, "Message Of The Day", "motd", MOTDPANEL_TYPE_INDEX);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return Plugin_Continue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShowTimeLeft(client, who)
 | 
			
		||||
 | 
			
		||||
@ -938,3 +938,24 @@ native bool:AddCommandListener(CommandListener:callback, const String:command[]=
 | 
			
		||||
 */
 | 
			
		||||
native RemoveCommandListener(CommandListener:callback, const String:command[]="");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Global listener for the chat commands.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Client index.
 | 
			
		||||
 * @param command		Command name.
 | 
			
		||||
 * @param sArgs			Chat argument string.
 | 
			
		||||
 * 
 | 
			
		||||
 * @return				An Action value. Returning Plugin_Handled bypasses the game function call.
 | 
			
		||||
							Returning Plugin_Stop bypasses the post hook as well as the game function.
 | 
			
		||||
 */
 | 
			
		||||
forward Action:OnClientSayCommand(client, const String:command[], const String:sArgs[]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Global post listener for the chat commands.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Client index.
 | 
			
		||||
 * @param command		Command name.
 | 
			
		||||
 * @param sArgs			Chat argument string.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
forward OnClientSayCommand_Post(client, const String:command[], const String:sArgs[]);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user