BanTeam command

I want to have a command that bans a player from a team.

Problem is, I have no way where to start. Like, how do I ban the player in the first place?

Any feedback is appreciated!

So I have 2 things I made.

  1. A YouTube tutorial:
    How To Make A BAN SYSTEM | ROBLOX STUDIO - YouTube

  2. A DevForum Tutorial:
    How to make a ban system/command (tutorial)

I get the ban script, but how to I ban the player from the team?

Aha, okay. Do you want this van to save and be Global or just Server-Wide?

Global

30char minimum stuff lol

Alright, so basically let’s say we have teams; Red, White, and Blue. We ban domboss37 from Team Red, lets say I rejoin, I would still be banned from team red correct?

Mhm

30char limit stuff lol hello there mate

Hey there, so I got it working (almost all the way). I have so far made it so that ban’s the player from the team, however, no saving yet, still working on it.

Now, I usually don’t spoon-feed but this is too much to write (so I just explained it through comments)

--// Services
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")

--// Vars
--local admins = {154609412}

--// Connections
Players.PlayerAdded:Connect(function(player)
	
	local bannedTeams = Instance.new("StringValue")
	bannedTeams.Name = "BannedTeams"
	bannedTeams.Value = ""
	bannedTeams.Parent = player
	
	player.Chatted:Connect(function(msg)
		--if not table.find(admins, player.UserId) then return end
		
		local indexOfSlash = msg:find('/') -- Find Start Of Command
		local indexOfSemi = msg:find(';') -- Find End Of Command
		if indexOfSlash == nil or indexOfSemi == nil then return end -- Make sure command has start and end
		local fullCommand = msg:sub(indexOfSlash, indexOfSemi):gsub(';', '') -- Get only the command from the message (this is so you can type anything before and after the command)
		local splitCommand = fullCommand:split(':') -- Get all the data from the command
		
		local command = splitCommand[1] -- Get the command name (such as /ban)
		
		if command == '/ban' then -- Check if its the ban command
			local teamName = splitCommand[2] -- Get Team To Ban Player From's Name
			local playerName = splitCommand[3] -- Get Player To Ban Name
	
			if playerName == nil or teamName == nil then return end -- Make sure both exist
			if not Teams:FindFirstChild(teamName) or not Players:FindFirstChild(playerName) then return end -- Make sure their valid
			
			bannedTeams.Value = bannedTeams.Value..teamName.."," -- Add to player's bannedTeams (this will be for saving)
			
			-- Choose New Team
			local plrsBannedTeams = bannedTeams.Value:split(',') -- Make a table of the bannedTeams
			for _, team in Teams:GetChildren() do -- Iterate through all the teams
				if table.find(plrsBannedTeams, team.Name) then continue end -- Check if its a banned team
				player.Team = team -- Set the player's team to the first non-banned team
				break -- exit loop
			end
		end
		
	end)
end)

-------------------------------
--			Grammar			 --
-------------------------------

--		/ban:team:playerName;

P.S Server Script In ServerScriptService

You should use a dictionary instead, and OP stated he wants this globally so, you should save the data using DataStoreService when the server shuts down.

Example:

-- userid, teams.
local bannedTeams = {
[1] = {"Team1", "Team2"}
}

for userid, teams in pairs(bannedTeams) do
-- save to datastore
end

As I stated in my post, I am currently working on making it save, just wanted to update him.

1 Like

Alright, I have finished. Once again, comments in the code to explain.

ServerScript In ServerScriptService (Called Commands or Whatever you want)

--// Services
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")
local DS = game:GetService("DataStoreService"):GetDataStore("BannedTeamsDataStore2")

--// Vars
--local admins = {154609412}

--// Connections
Players.PlayerAdded:Connect(function(player)
	
	local bannedTeams = Instance.new("StringValue")
	bannedTeams.Name = "BannedTeams"
	bannedTeams.Value = ""
	bannedTeams.Parent = player
	
	player.Chatted:Connect(function(msg)
		--if not table.find(admins, player.UserId) then return end
		
		local indexOfSlash = msg:find('/') -- Find Start Of Command
		local indexOfSemi = msg:find(';') -- Find End Of Command
		if indexOfSlash == nil or indexOfSemi == nil then return end -- Make sure command has start and end
		local fullCommand = msg:sub(indexOfSlash, indexOfSemi):gsub(';', '') -- Get only the command from the message (this is so you can type anything before and after the command)
		local splitCommand = fullCommand:split(':') -- Get all the data from the command
		
		local command = splitCommand[1] -- Get the command name (such as /ban)
		
		if command == '/ban' then -- Check if its the ban command
			local teamName = splitCommand[2] -- Get Team To Ban Player From's Name
			local playerName = splitCommand[3] -- Get Player To Ban Name
	
			if playerName == nil or teamName == nil then return end -- Make sure both exist
			local playerToBan = Players:FindFirstChild(playerName)
			if not Teams:FindFirstChild(teamName) or not playerToBan then return end -- Make sure their valid
			
			bannedTeams.Value = bannedTeams.Value..teamName.."," -- Add to player's bannedTeams (this will be for saving)
			DS:SetAsync("id_"..playerToBan.UserId, bannedTeams.Value)
			
			-- Choose New Team
			local plrsBannedTeams = bannedTeams.Value:split(',') -- Make a table of the bannedTeams
			for _, team in Teams:GetChildren() do -- Iterate through all the teams
				if table.find(plrsBannedTeams, team.Name) then continue end -- Check if its a banned team
				player.Team = team -- Set the player's team to the first non-banned team
				break -- exit loop
			end
		end
		
	end)
end)

-------------------------------
--			Grammar			 --
-------------------------------

--		/ban:team:playerName;

ServerScript In ServerScriptService (Called SaveBans, or whatever you want)

--// Services
local DS = game:GetService("DataStoreService"):GetDataStore("BannedTeamsDataStore2")
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")

--// Connections
Players.PlayerAdded:Connect(function(player)
	local plr_key = "id_"..player.UserId -- DS Player Key

	local success, res = pcall(function()
		return DS:GetAsync(plr_key) -- Get Values From DataStore
	end)
	
	if success then -- No Errors
		if res then -- If Theres a result
			local bannedTeams = player:WaitForChild("BannedTeams")
			bannedTeams.Value = res -- Set BannedTeams to the saved value
			
			-- Make Sure Player Is on a non-banned team
			local splitBannedTeams = bannedTeams.Value:split(',')
			if table.find(splitBannedTeams, player.Team.Name) then  -- Make sure player is/is not on a banned team
				for _, team in Teams:GetChildren() do -- Loop through teams
					if table.find(splitBannedTeams, team.Name) then continue end
					player.Team = team -- Set Team
					break
				end
			end
		end
	else
		DS:GetAsync(plr_key, "")
	end
end)

@SouthLondonDeveloper

1 Like

Thank you so much for the script!

And, for the “/unban” command, I would just remove the player from the “BannedTeamsDataStore2” datastore, right?

1 Like
local Game = game
local Players = Game:GetService("Players")
local Teams = Game:GetService("Teams")
local DataStoreService = Game:GetService("DataStoreService")
local BanStore = DataStoreService:GetDataStore("BanStore")

local Admins = { --Admins table (able to use command).
	[1] = true,
}

local Bans = {} --Dictionary that store bans.

local Commands = {"ban", "unban"} --Change this to change each command's 'name' (command should be preceded by any punctuation character).

local function FindPlayer(Name) --Function that finds a single player from an abbreviation of their name.
	local PlayersTable = {}
	for _, Player in ipairs(Players:GetPlayers()) do
		if not string.match(string.lower(Player.Name), "^"..string.lower(Name)) then continue end
		table.insert(PlayersTable, Player)
	end
	if #PlayersTable == 1 then return PlayersTable[1] end --Only return a result if a single match was found.
end

local function FindTeam(Name) --Function that finds a single team from an abbreviation of their name.
	local TeamsTable = {}
	for _, Team in ipairs(Teams:GetTeams()) do
		if not string.match(string.lower(Team.Name), "^"..string.lower(Name)) then continue end
		table.insert(TeamsTable, Team)
	end
	if #TeamsTable == 1 then return TeamsTable[1] end --Only return a result if a single match was found.
end

local function OnPlayerAdded(Player)
	local function OnPlayerChatted(Message)
		if not Admins[Player.UserId] then return end --Check if player issuing command is authorized.
		for _, Command in pairs(Commands) do
			local PlayerNick, TeamNick = string.match(string.lower(Message), "^%p"..Command.."%s(%S+)%s(%S+)")
			if not (PlayerNick and TeamNick) then continue end --If command is missing player and/or team then ignore it.
			local APlayer, ATeam = FindPlayer(PlayerNick), FindTeam(TeamNick)
			if not (APlayer and ATeam) then return end --If specified player and/or team cannot be found then ignore the command.
			if Command == "ban" then
				Bans[ATeam.Name][APlayer.Name] = true --Insert the player into the team's table of the bans table.
			elseif Command == "unban" then
				Bans[ATeam.Name][APlayer.Name] = false --Remove the player from the team's table of the bans table.
			end

			--Perform a save whenever a player is banned/unbanned from a team.
			local Success, Result = pcall(function() return BanStore:UpdateAsync(Game.GameId, Bans) end) --Global key, table is already 'serialized'.
			if not Success then warn(Result) end
		end
	end
	
	Player.Chatted:Connect(OnPlayerChatted)
end

local function OnTeamPlayerAdded(Player)
	if not Bans[Player.Team.Name][Player.Name] then return end
	Player.Team = nil --If a player attempts to join a team they are banned from assign them to the neutral team.
end

local function OnTeamAdded(Team)
	Team.PlayerAdded:Connect(OnTeamPlayerAdded) --Hook function to team's 'player joined' signal.
	Bans[Team.Name] = {} --Setup a table for the team in the bans table.
end

local function OnTeamRemoved(Team)
	Bans[Team.Name] = nil --Team has been removed (destroyed?) so its table inside the bans table is no longer needed.
end

local function OnGameLoaded()
	local Success, Result = pcall(function() return BanStore:GetAsync(Game.GameId) end) --Global key.
	if not Success then warn(Result) return end
	Bans = Result or {} --Update bans table.
end

local function OnGameClosed()
	local Success, Result = pcall(function() return BanStore:UpdateAsync(Game.GameId, Bans) end) --Global key, table is already 'serialized'.
	if not Success then warn(Result) end
end

Players.PlayerAdded:Connect(OnPlayerAdded)
Teams.ChildAdded:Connect(OnTeamAdded)
Teams.ChildRemoved:Connect(OnTeamRemoved)
Game.Loaded:Connect(OnGameLoaded)
Game:BindToClose(OnGameClosed)
for _, Team in ipairs(Teams:GetTeams()) do
	OnTeamAdded(Team)
end