Exemple #1
0
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &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();

	if (!args)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* 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);
	size_t len = strlen(args);

#if SOURCE_ENGINE == SE_EPISODEONE
	if (m_bIsINS)
	{
		if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
		{
			args += 4;
			len -= 4;
		}

		if (len == 0)
		{
			RETURN_META(MRES_SUPERCEDE);
		}
	}
#endif

	/* The first pair of quotes are stripped from client say commands, but not console ones.
	 * We do not want the forwards to differ from what is displayed.
	 * So only strip the first pair of quotes from client say commands. */
	bool is_quoted = false;

	if (
#if SOURCE_ENGINE == SE_EPISODEONE
		!m_bIsINS && 
#endif
		client != 0 && args[0] == '"' && args[len-1] == '"')
	{
		/* 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);
		}

		args++;
		len--;
		is_quoted = true;
	}

	/* Some? engines strip the last quote when printing the string to chat.
	 * This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
	 * but losing the last quote in the OnClientSayCommand_Post ("message) forward.
	 * To compensate this, we copy the args into our own buffer where the engine won't mess with
	 * and strip the quotes. */
	delete [] m_ArgSBackup;
	m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
	memcpy(m_ArgSBackup, args, len+1);

	/* Strip the quotes from the argument */
	if (is_quoted)
	{
		if (m_ArgSBackup[len-1] == '"')
		{
			m_ArgSBackup[--len] = '\0';
		}
	}

	/* The server console cannot do this */
	if (client == 0)
	{
		if (CallOnClientSayCommand(client) >= Pl_Handled)
		{
			RETURN_META(MRES_SUPERCEDE);
		}

		RETURN_META(MRES_IGNORED);
	}

	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);

	/* We guarantee the client is connected */
	if (!pPlayer || !pPlayer->IsConnected())
	{
		RETURN_META(MRES_IGNORED);
	}

	/* Check if we need to block this message from being sent */
	if (ClientIsFlooding(client))
	{
		char buffer[128];

		if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
			UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");

		/* :TODO: we should probably kick people who spam too much. */

		char fullbuffer[192];
		UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
		g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);

		m_bWasFloodedMessage = true;

		RETURN_META(MRES_SUPERCEDE);
	}

	bool is_trigger = false;
	bool is_silent = false;

	/* Check for either trigger */
	if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0)
	{
		is_trigger = true;
		args = &m_ArgSBackup[m_PubTriggerSize];
	} 
	else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0) 
	{
		is_trigger = true;
		is_silent = true;
		args = &m_ArgSBackup[m_PrivTriggerSize];
	}

	/**
	 * Test if this is actually a command!
	 */
	if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args))
	{
		m_bIsChatTrigger = true;

		/**
		 * We'll execute it in post.
		 */
		m_bWillProcessInPost = true;
	}

	if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	if (CallOnClientSayCommand(client) >= Pl_Handled)
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	/* Otherwise, let the command continue */
	RETURN_META(MRES_IGNORED);
}
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
void ChatTriggers::OnSayCommand_Pre()
{
	CCommand command;
#endif
	int client;
	CPlayer *pPlayer;
	
	client = g_ConCmds.GetCommandClient();
	m_bIsChatTrigger = false;
	m_bWasFloodedMessage = false;

	/* The server console cannot do this */
	if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* We guarantee the client is connected */
	if (!pPlayer->IsConnected())
	{
		RETURN_META(MRES_IGNORED);
	}

	const char *args = command.ArgS();
	
	if (!args)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* Check if we need to block this message from being sent */
	if (ClientIsFlooding(client))
	{
		char buffer[128];

		/* :TODO: log an error? */
		if (g_Translator.CoreTransEx(g_pFloodPhrases, 
			client, 
			buffer, 
			sizeof(buffer),
			"Flooding the server",
			NULL,
			NULL)
			!= Trans_Okay)
		{
			UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
		}

		/* :TODO: we should probably kick people who spam too much. */

		char fullbuffer[192];
		UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
		g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);

		m_bWasFloodedMessage = true;

		RETURN_META(MRES_SUPERCEDE);
	}

	/* Handle quoted string sets */
	bool is_quoted = false;
	if (args[0] == '"')
	{
		args++;
		is_quoted = true;
	}

	bool is_trigger = false;
	bool is_silent = false;

	/* Check for either trigger */
	if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
	{
		is_trigger = true;
		args = &args[m_PubTriggerSize];
	} 
	else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0) 
	{
		is_trigger = true;
		is_silent = true;
		args = &args[m_PrivTriggerSize];
	}

	if (!is_trigger)
	{
		RETURN_META(MRES_IGNORED);
	}

	/**
	 * Test if this is actually a command!
	 */
	if (!PreProcessTrigger(engine->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;

	/* If we're silent, block */
	if (is_silent)
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	/* Otherwise, let the command continue */
	RETURN_META(MRES_IGNORED);
}