example in data store player has data like this:
[“Warning”] = 1,
[“Time”] = 151215102121, – this is os.time()
[“Reason”] = “Walk Speed Hack”
i make script that when you fire remote the script will read datastore if player datastore has warning = 1 script gonna +1 with warning value it gonna be 2 but script cant find data it keep return nil when i fire with another player userid but when i use my userid the script can find my data
local Data = game:GetService("DataStoreService");
local BanDataStore = Data:GetDataStore("Test", "1")
local remote = game.ReplicatedStorage:WaitForChild("BanRemote")
local CurrentTime = os.time()
local OneDays = 86400
local ThreeDays = 259200
local OneWeek = 604800
local OneMonth = 2592000
local Banned = 3110400000
remote.OnServerEvent:Connect(function(plr, arg1, arg2)
if plr.UserId == 1 then -- Check Only This UserId Can Run Script
local Players = game:GetService("Players")
local BanUserId = tonumber(arg1)
local Data = BanDataStore:GetAsync(plr.UserId)
local BanTime = nil
local Warn = nil
if Data == nil or Data.Warning <= 0 then
BanTime = OneDays
elseif Data ~= nil and Data.Warning == 1 then
BanTime = ThreeDays
elseif Data ~= nil and Data.Warning == 2 then
BanTime = OneWeek
elseif Data ~= nil and Data.Warning == 3 then
BanTime = OneMonth
elseif Data ~= nil and Data.Warning == 4 then
BanTime = Banned
elseif Data ~= nil and Data.Warning >= 5 then
BanTime = Banned
end
if Data ~= nil and Data.Warning >= 5 then
Warn = 5
elseif Data ~= nil and Data.Warning < 5 then
Warn = Data.Warning + 1
elseif Data == nil then
Warn = 1
end
local bantable = {
["Warning"] = Warn,
["Time"] = CurrentTime + BanTime,
["Reason"] = arg2
}
BanDataStore:UpdateAsync(BanUserId, function(oldValue)
return bantable
end)
end
end)
The first Parameter passed in OnServerEvent is the Player that fired the remote (In your case plr), when you do :GetAsync you are using the plr.UserId which means you are always getting the ID of the player that fired the remote.
Also, I forgot to mention but pcall returns two things, the first one being a boolean (success in your case) that tells u if the pcall ran successfully and the second one being the error message (Data in your case). If whatever is running in the pcall doesn’t error then the Data will be nil because its the error message.
SetAsync does not take a callback for the second argument (you may be thinking of UpdateAsync).
It should look like this
local success, result = pcall(function()
BanDataStore:SetAsync(plr.UserId, bantable)
end)
if (not success) then
warn("failed to save player", plr, "to the ban datastore. details:", success, result)
end
Also, like @ItzPlanes said, you do not need to send the UserId as an argument for the RemoteEvent, you can just use plr.UserId
Highly DO NOT recommend doing it through a remote as hackers can easily fire remotes. It would make sense if you used it to ban their self on a client sided exploit detection however doing this without even checking the player if they should be banning other players is EXTREMELY exploitable and will be abused as soon as someone sees this.
As well as you have made it define OS.time outside of the event so it will ban them for less time. E.g If The server has been up for 1 hour and I get banned, I will only get a 23h ban as It is using the time from when the server started. Again, this is another major flaw as some servers stay open for days and some people might not even notice they got a ban.
Also you do not need to update the table, setting it would do the exact same but just work better as well as setting/updating is not something you use function like you did, Instead you could so something like this: BanDataStore:SetAsync(BanUserId, bantable) However adding fail safes like @wallythecocatoo did in his answer would be better than the entire script breaking as sometimes ROBLOX datastores go down.