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)
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.
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
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.
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.
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.