Skip to content

Commit eae47fe

Browse files
authored
Add ability to limit client triggered events (via triggerServerEvent) (#3251)
1 parent abec07a commit eae47fe

File tree

8 files changed

+83
-8
lines changed

8 files changed

+83
-8
lines changed

Server/mods/deathmatch/logic/CGame.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,9 @@ void CGame::DoPulse()
551551
PrintLogOutputFromNetModule();
552552
m_pScriptDebugging->UpdateLogOutput();
553553

554+
if (GetTickCount64_() + m_iClientTriggeredEventsIntervalMs > m_lClientTriggeredEventsLastCheck)
555+
ProcessClientTriggeredEventSpam();
556+
554557
// Unlock the critical section again
555558
Unlock();
556559
}
@@ -1585,6 +1588,7 @@ void CGame::AddBuiltInEvents()
15851588
m_Events.AddEvent("onPlayerResourceStart", "resource", NULL, false);
15861589
m_Events.AddEvent("onPlayerProjectileCreation", "weaponType, posX, posY, posZ, force, target, rotX, rotY, rotZ, velX, velY, velZ", nullptr, false);
15871590
m_Events.AddEvent("onPlayerDetonateSatchels", "", nullptr, false);
1591+
m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false);
15881592

15891593
// Ped events
15901594
m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false);
@@ -2568,6 +2572,8 @@ void CGame::Packet_LuaEvent(CLuaEventPacket& Packet)
25682572
}
25692573
else
25702574
m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not added serverside", pCaller->GetNick(), szName);
2575+
2576+
RegisterClientTriggeredEventUsage(pCaller);
25712577
}
25722578
}
25732579

@@ -4699,3 +4705,28 @@ void CGame::HandleCrashDumpEncryption()
46994705
}
47004706
#endif
47014707
}
4708+
4709+
void CGame::RegisterClientTriggeredEventUsage(CPlayer* pPlayer)
4710+
{
4711+
if (!pPlayer)
4712+
return;
4713+
4714+
auto iter = m_mapClientTriggeredEvents.find(pPlayer);
4715+
4716+
if (iter == m_mapClientTriggeredEvents.end())
4717+
m_mapClientTriggeredEvents.insert({pPlayer, 0});
4718+
4719+
m_mapClientTriggeredEvents[pPlayer]++;
4720+
}
4721+
4722+
void CGame::ProcessClientTriggeredEventSpam()
4723+
{
4724+
for (const auto& [player, count]: m_mapClientTriggeredEvents)
4725+
{
4726+
if (player && player->IsPlayer() && !player->IsBeingDeleted() && count > m_iMaxClientTriggeredEventsPerInterval)
4727+
player->CallEvent("onPlayerTriggerEventThreshold", {});
4728+
}
4729+
4730+
m_mapClientTriggeredEvents.clear();
4731+
m_lClientTriggeredEventsLastCheck = GetTickCount64_();
4732+
}

Server/mods/deathmatch/logic/CGame.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ class CGame
457457
bool IsBelowMinimumClient(const CMtaVersion& strVersion);
458458
bool IsBelowRecommendedClient(const CMtaVersion& strVersion);
459459
void ApplyAseSetting();
460+
void ApplyPlayerTriggeredEventIntervalChange();
460461
bool IsUsingMtaServerConf() { return m_bUsingMtaServerConf; }
461462

462463
void SetDevelopmentMode(bool enabled) { m_DevelopmentModeEnabled = enabled; }
@@ -508,6 +509,9 @@ class CGame
508509

509510
static void PlayerCompleteConnect(CPlayer* pPlayer);
510511

512+
void ProcessClientTriggeredEventSpam();
513+
void RegisterClientTriggeredEventUsage(CPlayer* pPlayer);
514+
511515
// Technically, this could be put somewhere else. It's a callback function
512516
// which the voice server library will call to send out data.
513517

@@ -658,4 +662,10 @@ class CGame
658662

659663
bool m_DevelopmentModeEnabled;
660664
bool m_showClientTransferBox = true;
665+
666+
int m_iMaxClientTriggeredEventsPerInterval = 100;
667+
int m_iClientTriggeredEventsIntervalMs = 1000;
668+
long long m_lClientTriggeredEventsLastCheck = 0;
669+
670+
std::map<CPlayer*, int> m_mapClientTriggeredEvents;
661671
};

Server/mods/deathmatch/logic/CMainConfig.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,7 @@ bool CMainConfig::AddMissingSettings()
847847
if (!g_pGame->IsUsingMtaServerConf())
848848
return false;
849849

850-
// Load template
851-
const char* szTemplateText =
852-
#include MTA_SERVER_CONF_TEMPLATE
853-
;
854-
SString strTemplateFilename = PathJoin(g_pServerInterface->GetServerModPath(), "resource-cache", "conf.template");
855-
FileSave(strTemplateFilename, szTemplateText);
850+
SString strTemplateFilename = PathJoin(g_pServerInterface->GetServerModPath(), "mtaserver.conf.template");
856851
CXMLFile* pFileTemplate = g_pServerInterface->GetXML()->CreateXML(strTemplateFilename);
857852
CXMLNode* pRootNodeTemplate = pFileTemplate && pFileTemplate->Parse() ? pFileTemplate->GetRootNode() : nullptr;
858853
if (!pRootNodeTemplate)
@@ -1463,6 +1458,8 @@ const std::vector<SIntSetting>& CMainConfig::GetIntSettingList()
14631458
{true, true, 0, 1, 1, "filter_duplicate_log_lines", &m_bFilterDuplicateLogLinesEnabled, NULL},
14641459
{false, false, 0, 1, 1, "database_credentials_protection", &m_bDatabaseCredentialsProtectionEnabled, NULL},
14651460
{false, false, 0, 0, 1, "fakelag", &m_bFakeLagCommandEnabled, NULL},
1461+
{true, true, 50, 1000, 5000, "player_triggered_event_interval", &m_iPlayerTriggeredEventIntervalMs, &CMainConfig::OnPlayerTriggeredEventIntervalChange},
1462+
{true, true, 1, 100, 1000, "max_player_triggered_events_per_interval", &m_iMaxPlayerTriggeredEventsPerInterval, &CMainConfig::OnPlayerTriggeredEventIntervalChange},
14661463
};
14671464

14681465
static std::vector<SIntSetting> settingsList;
@@ -1506,3 +1503,14 @@ void CGame::ApplyAseSetting()
15061503
m_pLanBroadcast = m_pASE->InitLan();
15071504
}
15081505
}
1506+
1507+
void CMainConfig::OnPlayerTriggeredEventIntervalChange()
1508+
{
1509+
g_pGame->ApplyPlayerTriggeredEventIntervalChange();
1510+
}
1511+
1512+
void CGame::ApplyPlayerTriggeredEventIntervalChange()
1513+
{
1514+
m_iClientTriggeredEventsIntervalMs = m_pMainConfig->GetPlayerTriggeredEventInterval();
1515+
m_iMaxClientTriggeredEventsPerInterval = m_pMainConfig->GetMaxPlayerTriggeredEventsPerInterval();
1516+
}

Server/mods/deathmatch/logic/CMainConfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ class CMainConfig : public CXMLConfig
142142
const std::vector<SIntSetting>& GetIntSettingList();
143143
void OnTickRateChange();
144144
void OnAseSettingChange();
145+
void OnPlayerTriggeredEventIntervalChange();
146+
147+
int GetPlayerTriggeredEventInterval() const { return m_iPlayerTriggeredEventIntervalMs; }
148+
int GetMaxPlayerTriggeredEventsPerInterval() const { return m_iMaxPlayerTriggeredEventsPerInterval; }
145149

146150
private:
147151
void RegisterCommand(const char* szName, FCommandHandler* pFunction, bool bRestricted, const char* szConsoleHelpText);
@@ -221,4 +225,6 @@ class CMainConfig : public CXMLConfig
221225
int m_bFilterDuplicateLogLinesEnabled;
222226
int m_bDatabaseCredentialsProtectionEnabled;
223227
int m_bFakeLagCommandEnabled;
228+
int m_iPlayerTriggeredEventIntervalMs;
229+
int m_iMaxPlayerTriggeredEventsPerInterval;
224230
};

Server/mods/deathmatch/mtaserver.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@
264264
Values: 0 - Off, 1 - Enabled. Default - 1 -->
265265
<database_credentials_protection>1</database_credentials_protection>
266266

267+
<!-- These parameters specify the maximum amount of events that can be triggered by the client (via triggerServerEvent) within the given interval.
268+
Note: The interval is given in milliseconds
269+
Interval range: 50 to 5000. Default: 1000
270+
Max events per interval range: 1 to 1000. Default: 100 -->
271+
<player_triggered_event_interval>1000</player_triggered_event_interval>
272+
<max_player_triggered_events_per_interval>100</max_player_triggered_events_per_interval>
273+
267274
<!-- Specifies the module(s) which are loaded with the server. To load several modules, add more <module>
268275
parameter(s). Optional parameter. -->
269276
<!-- <module src="sample_win32.dll"/> -->

Server/mods/deathmatch/mtaserver.conf.template

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
R"=====(
21
<!-- This file is compiled into the server binary.
32
It is used for inserting missing settings into mtaserver.conf at server startup -->
43
<config>
@@ -265,5 +264,11 @@ R"=====(
265264
*NOTE* This only protects resources which use dbConnect with mysql
266265
Values: 0 - Off, 1 - Enabled. Default - 1 -->
267266
<database_credentials_protection>1</database_credentials_protection>
267+
268+
<!-- These parameters specify the maximum amount of events that can be triggered by the client (via triggerServerEvent) within the given interval.
269+
Note: The interval is given in milliseconds
270+
Interval range: 50 to 5000. Default: 1000
271+
Max events per interval range: 1 to 1000. Default: 100 -->
272+
<player_triggered_event_interval>1000</player_triggered_event_interval>
273+
<max_player_triggered_events_per_interval>100</max_player_triggered_events_per_interval>
268274
</config>
269-
)====="

utils/buildactions/compose_files.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ newaction {
2525

2626
-- Copy configs
2727
os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "*.conf")
28+
os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "mtaserver.conf.template")
2829
os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "*.xml")
2930

3031
-- Copy compiled binaries

utils/buildactions/install_data.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ newaction {
4949
return
5050
end
5151

52+
local success, message = os.copydir("Server/mods/deathmatch", BIN_DIR.."/server/mods/deathmatch", "mtaserver.conf.template", false, true)
53+
if not success then
54+
errormsg("ERROR: Couldn't copy server config files", "\n"..message)
55+
os.exit(1)
56+
return
57+
end
58+
5259
local success, message = os.copydir("Server/mods/deathmatch", BIN_DIR.."/server/mods/deathmatch", "*.xml", false, true)
5360
if not success then
5461
errormsg("ERROR: Couldn't copy server xml files", "\n"..message)

0 commit comments

Comments
 (0)