I’m trying to make a game that bans you if you die.
I’m banning the player through a remote event:
local rem = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvent")
rem.OnServerEvent:Connect(Ban)
However, I’m not sure how to make a temp ban system. I know I need to use os.time and a dataStore. But I don’t know where to start aside from that. Please help
Depends on how you add the ban. You would check the ban when a player joins and see if it’s been past 30 minutes since the ban was issued, if it has been more than 30 minutes then do nothing. Otherwise, kick.
If you want the ban system to include all servers, then you need to use datastore or memoryservice (I recommand memoryservice) and save the time that they got banned on you can simply use os.time(), and then whenever a player rejoins you can get the time that passed by doing os.time() - SavedOsTime; which will return the number of seconds since they got banned; be sure to convert that to minutes or whatever time units your using
Hello! For a temporary server ban system you don’t need to do any of these. Here is a quick script I have made just now for a temporary ban system, please mark this as the solution and leave a like if it helps!
banned = {}
admins = {}
game.Players.PlayerAdded:Connect(function(Player)
for _,v in pairs(banned) do
if tonumber(v) == Player.UserId then
Player:Kick('You are temporarily banned from this server by an Administrator!')
end
end
for _,v in pairs(admins) do
if v == Player.UserId then
Player.Chatted:Connect(function(message)
local target = game.Players:FindFirstChild(message):
target:kick('get banned bozo')
table.insert(banned, target.UserId)
end)
end
end
end)
Please remember to leave a like and mark this as the solution
First of all, you’re not declaring the variables admins and banned as local. This is general good practice.
Second of all, you don’t have to iterate through the list. You can just use table.find, and check if it is nil or if it exists.
Also, you’re using “pairs” incorrectly. This is unfortunately a common mistake, but if you’re going to use a one-dimensional table that is indexed numerically, then just use ipairs. It is a better practice to use the correct iteration function.
Also, there is a syntax error on the line where you look for the player.
They’re global variables for a reason, localizing variables that are meant to be used for global purposes in a server script in my opinion is bad practice.
function UnbanUsers()
while true do
wait(1800)
for _,v in pairs(banned) do
table.remove(banned, v)
end
end
end
local unbancoro = coroutine.create(UnbanUsers)
coroutine.resume(unbancoro)
I’ll add a patch for all servers later. Sorry for the miss reading of your post.
First of all, server script or local script, the local keyword has the same behavior. local variable read/write usually tends to be a lot faster than for globals, regardless of the use.
Highlighting this part:
Thus, if a local variable is registered top-level, it’s “local” to the whole program.
So, in reality, using global variables when they are not needed is a bad practice, period. Opinions do not factor in this case.
Quoting the lua basics (written by the creator of lua!)
The “sin” variable is being localized and used to access it faster than a global value (math.sin). It is a micro-optimization, but still.
I actually made a system for this yesterday, it bans players from a single server when they die such that they need to rejoin a different server to continue playing.
local Players = game:GetService("Players")
local KickedPlayers = {}
Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Humanoid = Character:WaitForChild("Humanoid")
Humanoid.Died:Connect(function()
table.insert(KickedPlayers, Player.UserId)
Player:Kick("You have died!")
end)
end)
if table.find(KickedPlayers, Player.UserId) then
Player:Kick("You have already died in this server!")
end
end)
Logic should be relatively simple to follow, I used the “UserId” property of the player instance instead of the player instance itself as the latter would change if the player rejoined the same server instance, the former will never change.
Here’s a similar script to the previous one but it incorporates DataStores, such that if a player who has previously died attempts to rejoin any server they will be kicked.
local dataModel = game
local dataStoreService = dataModel:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("DataStore")
local players = dataModel:GetService("Players")
local kickedPlayers = {}
local protectedCall = pcall
local function onPlayerAdded(player)
local function onCharacterAdded(character)
local function onHumanoidDied()
table.insert(kickedPlayers, player.UserId)
local success, result = protectedCall(function()
dataStore:SetAsync(player.UserId, true) --"true" indicates dead.
end)
if success then
print(result)
else
warn(result)
end
player:Kick("You have died!")
end
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(onHumanoidDied)
end
if table.find(kickedPlayers, player.UserId) then
player:Kick("You have already died in this server!")
end
local success, result = protectedCall(function()
return dataStore:GetAsync(player.UserId)
end)
if success then
if result then
player:Kick("You have already died in another server!")
end
else
warn(result)
end
end
players.PlayerAdded:Connect(onPlayerAdded)
local banDataStore = game:GetService("DataStoreService"):GetDataStore("BannedPlayers")
local players = game:GetService("Players")
function GetPlayerIDFromName(playerName : string)
local success, playerID = pcall(function()
return players:GetUserIdFromNameAsync(playerName)
end)
if not success then
print("Failed to get user.")
return
end
return playerID
end
function BanPlayer(playerName : string, time : number)
local playerID = GetPlayerIDFromName(playerName)
if not playerID then return end
local success = pcall(function()
if time > 0 then
banDataStore:SetAsync(playerID, time*60+os.time()) -- timed ban
else
banDataStore:SetAsync(playerID,nil) -- nil means perm ban.
end
end)
if success then
if time > 0 then
print(string.format("%s has been banned for %s minutes.",playerName,time))
else
print(string.format("%s has been banned permanently.",playerName))
end
end
local player = players:FindFirstChild(playerName)
if player and success then
if time > 0 then
player:Kick(string.format("You have been banned for %s minutes.",time))
else
player:Kick(string.format("You have been banned permanently."))
end
end
end
function UnBanPlayer(playerName : string)
local playerID = GetPlayerIDFromName(playerName)
if not playerID then return end
local success = pcall(function()
banDataStore:SetAsync(playerID,0) -- 0 means not banned.
end)
end
function CheckBan(player : Player)
local success, time = pcall(function()
return banDataStore:GetAsync(player.UserId)
end)
if not success then return end
if time > 0 then
player:Kick(string.format("You have been banned. Time Remaining: %s minutes.",math.round((time-os.time())/60)))
elseif time == nil then
player:Kick(string.format("You have been banned permanently."))
end
end
Here you go I have made a simple script it is not the most perfect script but it should satisfy your needs.
I am not going to make the command part for that you should do some research and try to implement it yourself but I will give you some resources which you can get started on.
These 2 should do it. I highly recommend you fiddle around the first try to figure it out. If you manage to make it by yourself great you are on your way to becoming a developer if not that’s also fine getting used to the language may take some time. I will also leave a link to a guide.
Yes, no problem, that’s a relatively quick change.
local dataModel = game
local dataStoreService = dataModel:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("DataStore")
local players = dataModel:GetService("Players")
local kickedPlayers = {}
local protectedCall = pcall
local function onPlayerAdded(player)
local function onCharacterAdded(character)
local function onHumanoidDied()
table.insert(kickedPlayers, player.UserId)
local success, result = protectedCall(function()
dataStore:SetAsync(player.UserId, tick()) --"true" indicates dead.
end)
if success then
print(result)
else
warn(result)
end
player:Kick("You have died!")
end
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(onHumanoidDied)
end
if table.find(kickedPlayers, player.UserId) then
player:Kick("You have already died in this server!")
end
local success, result = protectedCall(function()
return dataStore:GetAsync(player.UserId)
end)
if success then
if result then
if tick() - result <= 86400 then --1 day.
player:Kick("You have already died in another server! Please rejoin in "..(86400)-(tick() - result).." seconds.")
else
local success, result = protectedCall(function()
return dataStore:RemoveAsync(player.UserId)
end)
end
end
else
warn(result)
end
end
players.PlayerAdded:Connect(onPlayerAdded)
Hmm… For some reason this isn’t working. I’ve been looking through the code for a potential cause for it to not be working. However, I can’t find why. The player doesn’t get kicked on death. I also tried it with a remote event and it didn’t work. There’s nothing in the output and Studio Access to API Services is enabled.