How To: Admin Commands

Getting started.

This page is a tutorial on some basic Chatted commands, or as they are more widely known, admin commands. First off, this is a medium-leveled tutorial, and it is strongly suggested that you read and understand the absolute beginner's guide to scripting before reading this. That's it for disclaimers, let's move on to the good stuff!

What you need to know

So what exactly do you need to know to make an admin command script? Actually, only two things. The Events PlayerAdded and Chatted. The PlayerAdded event tells us when a player enters the game. The Chatted event tells us when a player has chatted, or said something. Here's an example:

function added(player) --Our function's name
     print(player.Name) --Print the name of the person who just entered
end --End our function
game.Players.PlayerAdded:connect(added) --Connecting the event

So in case you didn't understand that last line, here's what it's saying:

When a Player is added to Players, run the function 'added'.

One down, one to go. The Chatted event is our next subject, and here's a quick example:

--Called whenever a player chats
function onChatted(message, player)
    if message == "message" then --If we chatted "message" then...
          print(player.Name) --Print our name
    end
end

--When a player enters the level
game.Players.PlayerAdded:connect(function(player)
    --Attach an event handler that calls onChatted every time they chat
    player.Chatted:connect(function(message) onChatted(message, player) end)
end)

Alrighty. A bit more confusing, but only because we needed both Events to run it. We can't run an event that tells us when someone Chatted without the player, now can we? First we'll dissect out 'onChatted' function.

Our variable 'message' is what the player said, 'player' is the player. If our player says 'message', then print his name in the output.

Simple, right? Well, the next function is just as simple.

Our variable 'player' is the person who entered. When the player who entered talks, run the function 'chat', with 'message' as the message, and 'player' as the player.

So that's that. When someone comes in, we check to see if they say 'message' then, if they do, print their name! Easy! You've just made your first admin command! Yes, it is actually that simple.

Making admins

So you've made your command, but you don't want random people using it. What do you do? You use a table! That's all good, but how do we check if the person is on the list? The easiest way I've found to do this is make your own function that returns true if the name is on the table. Here's the code:

function tableContains(t, value)
    for _, v in pairs(t) do
        if v == value then 
            return true
        end
    end
    return false
end

Fairly simple, and incredibly useful. Now let's edit our code a bit. Let's make it so only a few people can use those commands.

local admins = {"OBF", "ArceusInator", "amanda12895"}

function tableContains(t, value)
    for _, v in pairs(t) do
        if v == value then 
            return true
        end
    end
    return false
end

function onChatted(message, player)
    if message == "reset" and tableContains(admins, player.Name) then
        player.Character:BreakJoints()
    end
end

game.Players.PlayerAdded:connect(function(player)
    player.Chatted:connect(function(message) onChatted(message, player) end)
end)

Kind of long, right? That's why most admin command scripts are 100+ lines long. But on to explaining.

However, there's a better way of writing this. Rather than having the user names as values in the table, you can use them as keys. This makes it much simpler:

local isAdmin = {["OBF"] = true, ["ArceusInator"] = true, ["amanda12895"] = true}

function onChatted(message, player)
    if message == "reset" and isAdmin[player.Name] then
        player.Character:BreakJoints()
    end
end

game.Players.PlayerAdded:connect(function(player)
    player.Chatted:connect(function(message) onChatted(message, player) end)
end)

So in our chat function, instead of just checking whether the player said "reset" or not, we're also checking if the player is on the 'admin' table. If he is, we kill him. 'player.Character' is how we get the player's character, which is what you find in Workspace and what you see everytime you go into a game. :breakJoints() is a method that kills people. Almost done now, bear with me.

Better admin commands

Well, you've made it this far. Hopefully you know more than you last did. You know how to check if someone's on a table, and to get what the person said. You know how to kill people. But you don't know how person299 made kill/OBF. This'll tell you how. String.sub. string:sub(start,end) gets all the letters in a string from the start position to the end position. Example:

local exampleString = "OBF"

local newExampleString = exampleString:sub(1, 2)
print(newExampleString) --> OB

newExampleString = exampleString:sub(2)
print(newExampleString) --> BF

If we don't give it an end number, it'll get every character in the string from the start position to the end. You can read more about string.sub here. But how is this useful in admin commands? Well, suppose someone said kill/OBF. We could check if the first five letters of the string were 'kill/', and if they were, get the rest of the string, find the person in Players, and kill their Character. Easiest way to do that? You guessed it, another function. Here's more or less what the code would look like:

function findPlayer(name)
    for _, player in pairs(game.Players:GetPlayers()) do
        if player.Name:lower() == name:lower() then
            return player
        end
    end
end

GetPlayers() returns a table of all the players in the game. We're simply iterating through that table and finding the player whose name is name. If we find them, we return them. If not, we (implicitly) return nil. By using string.lower, we're checking if the all lowercase name equals the all lowercase variable we gave it. So, in conclusion, here's what the code would look like for the kill/ command.

local isAdmin = {["OBF"] = true, ["ArceusInator"] = true, ["amanda12895"] = true}

function findPlayer(name)
    for _, player in ipairs(game.Players:GetPlayers()) do
        if player.Name:lower() == name:lower() then
            return player
        end
    end
end

function onChatted(message, player)
    if message:sub(1, 5) == "kill/" and isAdmin[player.Name] then
        victim = findPlayer(message:sub(6))
        if victim and victim.Character then
            victim.Character:BreakJoints()
        end
    end
end


game.Players.PlayerAdded:connect(function(player)
    player.Chatted:connect(function(message) onChatted(message, player) end)
end)