Roblox Admin Commands Guide

Roblox Admin Commands Guide

Roblox admin commands allow players to moderate the game’s experience. Players with admin privileges can kick or ban players that harm the experience for others. We can also set up different types of roles for different types of players. Each role has its own set of abilities.

What you’ll learn

  • Store and manage player privileges
  • How to use the command design pattern
  • Build your own custom commands
  • How to use the HD Admin plugin

Create a custom player role system

Let’s go over how we can build our own player role system to manage access levels and command privileges. If you rather not use someone else’s plugin or script, then you should use your own that is trustworthy.

Different types of player roles

The first type of player role is the administrator. An administrator has nearly full control of the game.

Above all other roles, we have the owner account. The owner account has full unfettered access to all Roblox admin commands and abilities.

A developer is another type of role where they may have some admin privileges or could have full admin rights. The developer role gives a player the abilities they need to build or test game features. You can set up this role system in a private server so developers can only change the game in a test environment instead of using your production environment. 

The moderator role allows a player to take on the responsibility of maintaining a safe and fair environment for all players. Moderators should have the ability to kick, ban, mute players, or place players into a temporary holding area.

A premium player role is used for those players that have a premium Roblox subscription. With this role, we can grant access to exclusive content or give special commands. These commands should make the game more exciting and fun but not give them a major advantage against normal players.

A normal role is any player that joins that does not fit any other role. Player’s with a normal role have limited privileges and access.

What is the command design pattern?

The command design pattern is a behavioral pattern where an object contains all necessary info to perform an action. Such info includes the object to perform an action on or different parameter values to use.

With the command pattern, we can implement several features such as storing a history of actions or changes for player privileges. Having a history log allows you to audit or review changes which are great for the security of your game’s experience. You can set up a logging system by having all commands go through a central server script that validates and runs all commands.

The pattern works by having a common interface for the objects that set up and create commands and objects that will manage and execute these commands. Other objects that run the command only need to use this common interface (a common set of function names) without knowing the actual internal workings of the command.

Organizing player privileges

With each role, we can assign different commands that they have the power to use. We’ll define a few objects to set this up. Commands must get defined within a server script to prevent exploiters from decompiling it as a local script. Local scripts should only send minimal information required to start a command. Server scripts should receive this info to validate and then call the desired function or event.

First, let’s define the command object.

local Command = {}
local function Command:new()
  local o = {
    Name = "",
    SentBy = nil
  }
  self.__index = self
  return metatable(o, self)
end

local function Command:execute()
  -- add command logic  
end

Next, let’s define the player role object.

local PlayerRole = {}
local function PlayerRole:new()
  local o = {
    Name = "",
    Commands = {}
  }
  self.__index = self
  return metatable(o, self)
end

local function PlayerRole:CanUse(command)
  local playerCanUse = false
  for i, command in ipairs(self.Commands) do
    if command.Name == commandName then
      playerCanUse = true
      break
    end
  end
  return playerCanUse
end

Let’s use an enum object to define all command names.

local CommandsEnum = {
  KickPlayer = 1000,
  BanPlayer = 1001,
  AwardGold = 2000,
  WithdrawGold = 2001
}

Here’s an example admin role object.

local AdminPlayerRole = PlayerRole:new()
AdminPlayerRole.Name = "admin"
AdminPlayerRole.Commands = { CommandsEnum.KickPlayer, CommandsEnum.BanPlayer }

We’ll need an object to collect and run our commands. We’ll use a remote event to validate the player’s role can use the command. Once validated, we’ll use a command factory to create the command object and add the command to our runner’s command array.

local CommandRunner = {}
local function CommandRunner:new()
  local o = {}
  o.Commands = {}
  self.__index = self
  return metatable(o, self)
end

local function CommandRunner:Execute()
  for i, command in ipairs(self.Commands) do
    command.Execute()
    self.Command[i] = nil
  end
end

local runner = CommandRunner:new()

-- Receive command event
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlayerCommandEvent = Instance.new("RemoteEvent", ReplicatedStorage)
PlayerCommandEvent.Name = "PlayerCommand"
 
local function onPlayerCommandFired(player, eventData)
  -- validate player’s role can use command
  -- create command using a command factory with eventData.CommandName
  -- add command to runner
  table.insert(runner.Command, newPlayerCommand)
end
PlayerCommandEvent.OnServerEvent:Connect(onPlayerCommandFired)

while true do
  runner:Execute()
end

Here’s an example command to kick a player from the server. 

local KickPlayerCommand = Command:new()
function KickPlayerCommand:new()
  local o = {}
  o.Name = CommandsEnum.KickPlayer
  o.PlayerToKick = nil
  o.Command = "/kick "
  o.KickMessage = ""
  self.__index = self
  setmetatable(o, self)
end

local Player = game:GetService("Players")
function KickPlayerCommand:Execute()
  if self.PlayerToKick
    -- kick player
    self.PlayerToKick:Kick(self.KickMessage)
  end
end

Player role security

All commands should run through a server-side script to limit exploiters from sending unauthorized commands. This goes especially for actions that affect player state and data. Data would include any player progress or in-game currency that they’ve earned.

Server script logic must validate that a player’s command comes from an authorized user. To validate these commands, we can use their role that’s stored in the game’s data store.

Storing player privileges

Depending on the player size of your game, we can use different methods of storing player roles and privileges. 

The simplest method is to have it all done in the script. Though this is limited by how easily we can update the data. With this method, all data will live in server memory. So if a server goes down that will effectively delete this data. 

Using this simplified method, we can have a single owner or admin that can invoke commands to update this data in server memory. 

A more robust solution would use Roblox data stores. Instead of relying on just the owner, you can give control to players you trust instead. Within the data store, we’ll have objects that contain which roles each player has. All role logic exists in scripts that rely on this data to control who has access.

Player authorization data store script

We’ll first define the Player authorization service constructor function.

local DataStoreService = game:GetService("DataStoreService")

local PlayerAuthorizationErrors = {
  NOT_ADMIN = 1000
}

local PlayerAuthorizationService = {}
local function PlayerAuthorizationService:new()
  local o = {}
  o.datastore = DataStoreService:GetDataStore("PlayerAuthorization")
  self.__index = self
  return setmetatable(o, self)
end

local function PlayerAuthorizationService:_createPlayerModel()
  return {
    PlayerId = nil,
    Name = "",
    Role = nil
  }
end

local function PlayerAuthorizationSevice:GetPlayerModelById(playerId)
  local model = o.datastore:GetAsync("player_" .. playerId)
  model.Role = RoleFactory:GetRole(model.Role.Name)
  return model
end

local function PlayerAuthorizationService:CreatePlayerModel(player, role)
  local model = self:_createPlayerModel()
  model.PlayerId = player.UserId
  model.Name = player.DisplayName
  model.Role = RoleFactory:GetRole(role)
  return model
end

local function PlayerAuthorizationService:RequestorIs(requestor, role)
  local requestor = o.datastore:GetAsync("player_" .. requestor.UserId)
  return requestor.Role.Name == role
end

-- validate CRUD operations of requestor is an admin
local function PlayerAuthorizationService:ValidateAdminRequestor(requestor)
  return self:RequestorIs(requestor, "admin")
end

The ValidateAdminRequestor function confirms that the player making sensitive data changes such as adding new player records has the admin role. Use the RequestorIs function to restrict functions to other roles.

local function PlayerAuthorizationService:AddPlayer(requestor, player, role)
  if self:ValidateAdminRequestor(requestor) then
    local model = self:CreatePlayerModel(player, role)
    o.datastore:SetAsync("player_" .. player.UserId, model)
    return model
  end

  error({ code = PlayerAuthorizationErrors.NOT_ADMIN, message = "requestor is not authorized" } )
end

The command runner can use the CanUse function to validate that the player has the correct role to use the desired command.

local function PlayerAuthorizationService:CanUse(player, command)
  -- check that player has given command
  local model = self:GetPlayerModelId(player.UserId)
  return model.Role:CanUse(command)
end

We’ll use a separate module script to create a role factory object. The factory pattern simplifies creating role object models that use a common interface.

-- new module script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Roles = ReplicatedStorage:WaitForChild("Roles")

local RoleFactory = {}
local function RoleFactory:new()
  local o = {}
  self.__index = self
  return setmetatable(o, self)
end

local function RoleFactory:GetRole(rolename)
  if rolename == "admin" then
    return Roles.AdminRole
  elseif rolename == "owner" then
    return Roles.OwnerRole
  elseif rolename == "moderator" then
    return Roles.ModeratorRole
  elseif rolename == "developer" then
    return Roles.DeveloperRole
  elseif rolename == "premium_player" then
    return Roles.PremiumPlayerRole
  else rolename == "normal_player" then
    return Roles.NormalPlayerRole
  end
end

return RoleFactory

How to run Roblox admin commands

Using the Roblox chat system is the easiest method to run commands. Another option is to use a Gui.

Use the Roblox chat system to run commands

We’ll use the Player.Chatted event to parse out commands. 

local Player = game:GetService("Players")

local Commands = {
  KickPlayer = "/kick "
}

local function stringMatches(input, shouldMatch)
  return input:sub(1, shouldMatch:len()):lower() == shouldMatch:lower()
end

local function onPlayerChatted(player, message, recipient)
  local command = nil
  if stringMatches(Commands.KickPlayer) then
    command = KickPlayerCommand:new()
    command.PlayerToKick = player
    command.KickMessage = player.Name .. " has been kicked!"
  end

  if command then
    -- validate player can use the command
    local playerCanUseCommand = PlayerAuthorizationService:CanUse(player, command.Name)

    If playerCanUseCommand then
      command:Execute()
    end
  end
end

local function onPlayerAdded(player)
  player.Chatted:Connect(onPlayerChatted)
end

Player.PlayerAdded:Connect(onPlayerAdded)

Use a Gui to run commands

Now that we have a player command authorization service, we can create any type of front end or GUI interface to interact with it. 

The first option could include a /admin command to display the admin console. It’s important to note that the authorization service acts as the main gatekeeper when running any commands

Any admin UI must exist as a local script, making it accessible to exploiters if not built correctly. So instead of thinking of it as “the player wants to run this command”, think of it as “can this player use this command?”.

Using Roblox HD Admin

HD Admin gives you a lot out of the box. You can easily set up player roles, create custom commands, custom events, and change the appearance of players.

How to add HD Admin to your Roblox game

  1. To add HD admin to your game, add it to your inventory
  2. In a new or existing game, open up the explorer
  3. Select the inventory tab
  4. Once you’ve found HD Admin in your inventory, add it to your game’s workspace
  5. Now you can load up your game, set up different player roles, and commands

Check out their tutorials for more information.

What’s Next

You now understand how to organize and provide the tools to different types of players so all players have a great experience in your game. Remember to code defensively when giving other players control of powerful Roblox admin commands and abilities.

Please consider joining my email newsletter for future updates and content!

Thank you for reading and stay curious!

Leave a Reply