Need help with ban function

I’m working on making an admin panel currently and I’m trying to incorporate a ban, unban, give admin, and remove admin functions. I have tried scripting and rescripted multiple times and keep failing. I’m going to ask for help here. I have buttons and a reason button which i have scripted, however it’s the server script to manage everything that I am failing in. I’d like to use datastores to check for bans, and if the player is an admin or not, etc. I want the player to be banned by displaying the reason included in the reason box (Main.Reason.Text).

Button Local Scripts:
Ban:
script.Parent.Ban.MouseButton1Click:Connect(function()
if game.Players:FindFirstChild(Main.Player.Text) and Main.Player.Text ~= “H34E7R” then
game.ReplicatedStorage.AdminEvents.Ban:FireServer(Main.Player.Text, Main.Reason.Text)
else
game.ReplicatedStorage.AdminEvents.Ban:FireServer(Main.Player.Text, Main.Reason.Text)
end
end)
Unban:
script.Parent.Unban.MouseButton1Click:Connect(function()
game.ReplicatedStorage.AdminEvents.Unban:FireServer(Main.Player.Text, Main.Reason.Text)
end)
Give Admin:
script.Parent.GiveAdmin.MouseButton1Click:Connect(function()
if game.Players.LocalPlayer.Name == “H34E7R” then
game.ReplicatedStorage.AdminEvents.GiveAdmin:FireServer(Main.Player.Text)
end
end)
Remove Admin:
script.Parent.RemoveAdmin.MouseButton1Click:Connect(function()
if game.Players.LocalPlayer.Name == “H34E7R” then
game.ReplicatedStorage.AdminEvents.RemoveAdmin:FireServer(Main.Player.Text)
end
end)

Thank you in advance!
-H34E7R

Do you have anything you’ve gotten so far for the server script or is it just the logic of doing it that you’re having difficulty with?

local DDS = game:GetService(“DataStoreService”)
local AdminData = DDS:GetDataStore(“Admins”)
local BanData = DDS:GetDataStore(“Bans1”)

As of now that’s what I have, and I’ve been experimenting with setting async and getting async in datastores to try to achieve what I’ve been wanting. I also want to be able to ban, unban, give admin, and remove admin from players who are not ingame, so I know that will involve :GetUserIdFromAsync() as well. It’s also the logic as well.

Here is a topic I found that should help you with what you are asking about:

If you have any questions do not hesitate to ask.

I did try using that but it still didn’t work for me.

Did you actually add anything to the bans datastore…? Are there any errors?

I tried adding reason and I get some sort of error when I edit it to use :GetUserIdFromAsync().

ServerScript:
if not BanData:GetAsync(game.Players:FindFirstChild(playerToBan):GetUserIdFromAsync()) then
BanData:SetAsync(game.Players[playerToBan:GetUserIdFromAsync()]:GetUserIdFromAsync(), reason)
if playerToBan then
playerToBan:Kick(“\nYou are currently banned for:\n” … reason … “\nPlease appeal your ban in discord.”)
end
end

CheckBan Function:
local function CheckBan(player, playerToBan, reason)
if BanData:GetAsync(playerToBan, reason) then
return true
end
return false
end

OnPlayerAdded Check:
game.Players.PlayerAdded:Connect(function(player, playerToBan, reason)
if CheckBan(playerToBan) then
player:Kick(“\nYou are currently banned for:\n” … reason … “\nPlease appeal your ban in discord.”)
end
end)

Error:
‘GetUserIdFromAsync is not a valid member of Player’ on the first line of the serverscript

You should use Player.UserId, not Player:GetUserIdFromAsync() (this function doesn’t exist) to retrieve the player’s UserId.

1 Like

I need to get the player’s ID so that way I can ban player’s who aren’t in-game.

That’s pretty simple actually you could make a GetId function. Which would allow you to get the Player’s Id.

local Players = game:GetService("Players")
local function GetId(PlayerName)
	-- pcall as a failsafe if the player doesn't exist
	local Success, Error = pcall(Players.GetNameFromUserIdAsync, Players, PlayerName) -- uses . because you need parenthesis to call a colon function, and the service is the self argument
	return (Success and Success, PlayerName or Success, Error) -- Ternary statement in lua, a one line if statement.
end

And then you can use the banned userId to set a datastore.

local DataStoreService = game:GetService("DataStoreService")
local BanStore = DataStoreService:GetDataStore("Bans")

-- function for banning offline players
local function BanOfflinePlayer(PlayerName)
	-- Using other function
	local Successful, PlayerId = GetId(PlayerName)
	
	-- pcall check in this function
	if Successful then
		BanStore:SetAsync(tostring(PlayerId), true) -- Convert it to a string, because it is a interger.
		print("Successfully banned player")
	else
		warn(PlayerId) -- PlayerId is also the warning error
	end
end

local function PlayerAdded(Player)
	local UserId = Player.UserId

	-- checks if an entry for the player's userid exists in the datastore, if it does then the player is banned.
	if BanStore:GetAsync(tostring(UserId)) then
		Player:Kick("You have been banned.") -- obviously kick the player
	end
	-- a chatted event just for testing purposes, you can do this any way you want.
	local function OnChatted(Message, Recipient)
		if string.sub("ban", 1, 3) and not Recipient then -- command is "ban PlayerName"
			if string.sub(5) then -- Get Player name argument of the command
				BanOfflinePlayer(string.sub(5)) -- ban them, finally.
			end
		end
	end
	
	-- connect to the event
	Player.Chatted:Connect(OnChatted)
end

-- using the players variable defined in the other code snippet.
Players.PlayerAdded:Connect(PlayerAdded)

-- i hear this is good practice, not sure why but it is.
-- all i'm aware of this being useful is if your script is disabled and enabled.
for _, Player in pairs(Players:GetPlayers()) do
	PlayerAdded(Player)
end

And, that’s it!
If my code has any issues feel free to tell me. :slight_smile:

PS: I’m on mobile right now so I can’t test my code.

Also, you should check to see if the player is an admin on the server. When firing the remote events you should incorperate all checks on the server when possible.

1 Like

Regarding your bottom comment about having the function listen to Players.PlayerAdded and then running it over each existing player: this is because PlayerAdded can fire before your function has a chance to hook onto PlayerAdded, therefore it will not run for those players.

To run through what that code is responsible for, you connect it to PlayerAdded first so the function gets called for each new player and then you call it for all existing players who may not have had the function get called on them when they joined.

It’s always a good idea to add net functions like this, especially when you might be doing something that might yield at the beginning of a script.

2 Likes