Player Spamming Datastore

Sometimes someone comes in my game and spams the life out of datastore somehow and overwhelms it.


Specifically they’re spamming GetSortedAsnyc
I’m not sure how they are doing it but I’m guessing they’re spamming the remote events that return the datastore. There are two datastores they could be spamming, one is a list and one is a number. I’ve only ever used datstore2 so I’m not familiar with the intricacies of datastore.

local function returnInventory(player)
	local inventoryStore = DataStore2("Inventory", player)
	return inventoryStore:Get()
end
--and
local function coinValue(player)
	local coinsStore = DataStore2("Coins", player)
	return coinsStore:Get()
end

The thing that I’m confused about is since it’s a connected to a remote event, usually when a player spams a remote event there will be a warning like “player appears to be spamming remote events,” but I don’t see that.

1 Like

This is what I use to kick players when they spam remotes:

Source Code
local TrackRequests = {}

local PLAYER_ERRORS = require(script.Parent.Parent.Admin.PLAYER_ERRORS)

function TrackRequests.new(requestCacheLength : number, maxRequests  : number)
	local self = {
		RequestCacheLength = requestCacheLength or 6,
		MaxRequests = maxRequests or 5,
		_RequestTracker = {},
	}
	setmetatable(self, {__index = TrackRequests})
	return self
end

function TrackRequests:AddToTrack(plr : Player)
	local currentRequestNum = self._RequestTracker[plr.UserId]
	
	local newRequestNum

	if currentRequestNum then
		newRequestNum = currentRequestNum + 1
	else
		newRequestNum = 1
	end

	self._RequestTracker[plr.UserId] = newRequestNum
	
	self:CheckPlayerRequests(plr)

	task.delay(self.RequestCacheLength, function()
		if not self._RequestTracker[plr.UserId] then
			return
		end

		self._RequestTracker[plr.UserId] -= 1

		if self._RequestTracker[plr.UserId] > 0 then
			return
		end

		self._RequestTracker[plr.UserId] = nil
	end)
end

function TrackRequests:CheckPlayerRequests(plr : Player)
	if not self._RequestTracker[plr.UserId] then
		return
	end

	if self._RequestTracker[plr.UserId] < self.MaxRequests then
		return
	end

	plr:Kick(PLAYER_ERRORS.KickReasons[1])
	self._RequestTracker[plr.UserId] = nil
end

return TrackRequests
How To Use
local TrackRequests = require(script.Parent.TrackRequests) -- Whereever your module is located
local TrackRequestHandler = TrackRequests.new(300, 2) -- First parameter is how long you want each paremeter to be tracked for, the second parameter is the request limit b4 the player is kicked

blahblahEvent.OnServerEvent:Connect(function(plr)
	TrackRequestHandler:AddToTrack(plr)

Not anything professional or whatever, and probably not that much of use, but felt like it would help you a little bit.

2 Likes

Also there’s an error something about PLAYER_ERRORS, that’s part of my admin collection, so just replace that with whatever kick reason you want

I don’t think that that is a thing by default. I believe you would need some extra code added in order to achieve that.

If you want to limit the number of times that a player can trigger the remote event, you can do something like this

local counts = {}
local function returnInventory(player)
    counts[player] = (counts[player] + 1) or 1
    if counts[player] > 10 then -- choose a value
         player:Kick("Spamming Remotes")
         return
    end 
    task.delay(1, function() counts[player] -= 1 end

	local inventoryStore = DataStore2("Inventory", player)
	return inventoryStore:Get()
end

This checks that they haven’t sent more than 10 calls to returnInventory in the last second, and if they do then it kicks them

2 Likes

Why are you fetching their data every time they ask? You should just load it once on the server, when they first join, and then return that to the player when they fire the remote.

For the leaderboard, just update it every 5 seconds or so on the server, and save it to a value that’s returned when players ask for it.

2 Likes

I’ll implement this
@Judgy_Oreo
That’s a good point. I still want to update the inventory datastore every time a player selects something new in their inventory, but I can make a table in that script of the inventory that the remote function will reference that updates when the player changes their inventory.

Why you send link to it if you don’t open access to it

I apologize, just opened it now, the source code is still available anyways, but sorry about that.

1 Like