Stop Exploiters from Spamming Your RemoteEvents ( Module_Queue )

> Marketplace link < {V.1}


This module can prevent Event spamming & much more.

  • RemoteEvent
  • RemoteFunction
  • BindableEvent
  • Webhook Throttling
  • And much more!

Open source, distribution while attaining compensation in any sort of currency is disallowed. (no selling this, credit me if you want to).

NOTE : THIS COMES WITH AN AUTOMATIC INTERNAL CLEANER. REMOVES DATA ON LEAVE AUTOMATICALLY, SAVES SERVER MEMORY.

Ability / Functions avaliable


  • function Module_Queue:set_Event_Limit(Event_Name, number_CooldownInSeconds)
    This function must be called if you use Module_Queue:return_DidPlayerExceedLimit(), it initializes the Event limit.
    LIMIT : You may set cooldowns as low as 0.001 seconds so the server saves memory.
EXAMPLE
Module_Queue:set_Event_Limit(RemoteEvent_Test.Name, 1.5)

  • Module_Queue:return_DidPlayerExceedLimit(Player.UserId, Event.Name)
    This function checks if the player exceeded the limit. If so, true else false.
EXAMPLES

MICROSCOPIC EXAMPLE

local bool_IsTheRequestTooQuick = Module_Queue:return_DidPlayerExceedLimit(Player_Local.UserId, RemoteEvent_Test.Name)

print(bool_IsTheRequestTooQuick)

if bool_IsTheRequestTooQuick == true then return end --Do not go forward in the function! Too quick!

CODE - BLOCK EXAMPLE

--[[	EVENT	]]

RemoteEvent_Test.OnServerEvent:Connect(function(Player_Local)
	
	
	if Module_Queue:return_DidPlayerExceedLimit(Player_Local.UserId, RemoteEvent_Test.Name) == false then
		
		return --CLOSES FUNCTION IF LIMIT EXCEEDED
			
	end
	
	--Script will continue to run if limit is not exceeded.
	
end)

  • Module_Queue:enable_Kick_Offender(Event_Name, number_Maximum_Offences)
    Optional, this will not run by default. Use if you want to kick the Player if they go past the maximum offenses, use this. Do not use this if you have no cooldown for firing events on the Player’s (local / client) scripts.
EXAMPLE
Module_Queue:enable_Kick_Offender(RemoteEvent_Test.Name, 3) -- THIS IS ENTIRELY OPTIONAL, KICKS PLAYERS THAT GO ABOVE THE COOLDOWN!

! SOURCE CODE !


script that calls Module_Queue Source Code
--[[	EXTERNAL DEPENDENCIES	]]
local Module_Queue			=	require(script:WaitForChild("Module_Queue"))


local RemoteEvent_Test		=	game.ReplicatedStorage.Folder_Replicated.RemoteEvent_Request_Wear_Garment


--[[	QUEUE SETTINGS	]]

Module_Queue:set_Event_Limit(RemoteEvent_Test.Name, 1.5)

--Module_Queue:enable_Kick_Offender(RemoteEvent_Test.Name, 3) -- THIS IS ENTIRELY OPTIONAL, KICKS PLAYERS THAT GO ABOVE THE COOLDOWN!


--[[	EVENT	]]

RemoteEvent_Test.OnServerEvent:Connect(function(Player_Local)
	
	
	if Module_Queue:return_DidPlayerExceedLimit(Player_Local.UserId, RemoteEvent_Test.Name) == false then
		
		return 
			
	end --CLOSES FUNCTION IF LIMIT EXCEEDED
	
	--Script will continue to run if limit is not exceeded.
	
end)

Module_Queue Source Code
local Module_Queue			=	{}


Module_Queue.table_Limit			=	{}
Module_Queue.table_Queue			=	{}
Module_Queue.table_Offender			=	{}


function Module_Queue:return_DidPlayerExceedLimit(Player_Local_UserId,Event_Name)

	if self.table_Queue[Event_Name][Player_Local_UserId] then
		
		
		if math.floor(os.clock()*1000)/1000 - self.table_Queue[Event_Name][Player_Local_UserId] >= self.table_Limit[Event_Name] then

			self.table_Queue[Event_Name][Player_Local_UserId]	=	math.floor(os.clock()*1000)/1000

			return true

		else
			
			if self.table_Queue[Event_Name].Kick_Offender	~= false then

				if self.table_Offender[Player_Local_UserId] then
					
					self.table_Offender[Player_Local_UserId] += 1
					
					if self.table_Offender[Player_Local_UserId] > self.table_Queue[Event_Name].Kick_Offender then
						
						local bool_Success, string_ErrorMessage	=	pcall(function()
							
							if game.Players:GetPlayerByUserId(Player_Local_UserId) ~= nil then
								
								game.Players:GetPlayerByUserId(Player_Local_UserId):Kick("You have exceeded the Limit.")
								
							end
							
						end)
						
						if string_ErrorMessage then print(string_ErrorMessage) end
						
					else
						

						
					end
					
				else

					self.table_Offender[Player_Local_UserId]	=	0
					
				end
				
			end
			
			return false

		end

	else

		self.table_Queue[Event_Name][Player_Local_UserId]	=	math.floor(os.clock()*1000)/1000

		return true

	end

end


function Module_Queue:set_Event_Limit(Event_Name,number_CooldownInSeconds)
	
	self.table_Queue[Event_Name]				=	{}
	self.table_Limit[Event_Name]				=	number_CooldownInSeconds
	self.table_Queue[Event_Name].Kick_Offender	=	false
	
end


function Module_Queue:enable_Kick_Offender(Event_Name, number_Maximum_Offences)
	
	self.table_Queue[Event_Name].Kick_Offender	=	number_Maximum_Offences
	
end


game.Players.PlayerRemoving:Connect(function(Player_Local)

	for Name_RemoteEvent, table_RemoteEvent in pairs(Module_Queue.table_Queue) do

		if table_RemoteEvent[Player_Local.UserId] then table_RemoteEvent[Player_Local.UserId] = nil end

	end

end)


return Module_Queue

Have a nice day’, feel free to request featues or suggestions.

9 Likes

Sorry but this isn’t necessary as Roblox already does this for you (spam any remote 1000 times without a wait and you’ll see what I mean). With that in mind, you just wrote and released bloatware…

1 Like

You may have read the post incorrectly. This Module additionally allows action to be taken against the offender. I’ll probably be adding features like queueing (on fail retry) so this beauty can fulfil more use cases, when people start wishing for more.

Undefined behaviour, why not achieve defined.

If you have suggestions on how to not make this “bloatware”, I’d take them. Regardless, I’ve seen your post.

Most games have a few remotes that are performance heavy and spamming those can result in server lag and sometimes it can even result in crashing the server. It is always recommended to use (or write your own) a module that allows you to limit the number of times a remote can be called by a specific player within a specific time frame.

1 Like

Never kick a player just because it inquired too many requests to the server! Natural ping spikes can backup remote calls and force them to be fired all at once so the server can catch up.

As for ratelimiting, don’t be too overzealous with this. If your client absolutely has to inquire the server to run an expensive calculation, just use RemoteFunctions and apply a simple debounce like so:

local Cooldown: number = 2
local Debounce: boolean = false

function RemoteFunction.OnServerInvoke(Player: Player)
	if Debounce then return false end
	Debounce = true
	task.delay(Cooldown, function() Debounce = false end)
	
	print("Yay!")
	return true
end

-- Or if you want, set debounces for specific players

local DebouncedPlayers: {[number]: boolean} = {}

function RemoteFunction.OnServerInvoke(Player: Player)
	if DebouncedPlayers[Player.UserId] then return false end
	DebouncedPlayers[Player.UserId] = true
	task.delay(Cooldown, function() DebouncedPlayers[Player.UserId] = nil end)
	
	print("Yay!")
	return true
end

Again, this isn’t something you should be doing for every single remote. An exploiter abusing a simple getter function isn’t going to bring your server to its knees, and even then Roblox already internally ratelimits remotes to prevent enough damage anyways. It’s just more work for a non-issue.

7 Likes

Magma, I do believe there are operations that could slow or break the game, thus the Module.

RemoteFunctions are vulnerable on the Server - Client - Server so make sure none of you rely on that.

You’re literally using the same method the Module already provides. You’re being quite ignorant.

Current Benefits

  • Speed of module : 0.000010599847882986069 seconds
  • Under 50 lines of code (most of it is conditional statements)
  • Automatic Memory Cleanup on leave
  • Organized, Structurized, Modular

You’re recreating what I made, making it messier, loose untracked memory & manual. Kicking down innovative tools isn’t how one should go.

Here is a stress test I made that invokes the server to create a part at a random position at the start of every RenderStepped. As you can see, natural network lag and internal ratelimiting already takes care of the entire overhead and the server is able to continue producing parts way past 10000 invokes quite gracefully.


RemoteFunction StressTest - Roblox

(Do note I removed any physical aspects to the part creation to prevent Physics Throttling from biasing the results. The only overhead here is replication and rendering.)

You’re right about modularity, but in the grand scheme of things carrying around a dependency just to mimic a 3-liner is absolutely ridiculous and extremely inconvenient from a producer standpoint. If you seriously think we need better ratelimit technology, make a feature request instead!

2 Likes

I do not see any suggestions in your post. My point stands, anyone who wishes to use it, may.