Chat commands

Chat commands are special messages that are typed in the chat window in order to control the game, such as /kill Shedletsky or /reset. Another name for these are admin commands These are not built into roblox, but are a feature shared by many games.

This page is a tutorial on adding some basic chat commands to your own game. It is strongly suggested that you read and understand the absolute beginner's guide to scripting before reading this.

Contents

[edit] Running code when a player chats

If you want to run code when a particular player chats, you can use the Chatted event:

-- find a played somehow
local player = ...
-- listen for their chatting
player.Chatted:connect(function(message)
    -- and each time they chat, do stuff with `message` 
end)

But how do we know which player to listen to? When the game starts up, there are no players! We need to start listening to each player when they enter the game - we do this with the PlayerAdded event:

-- listen for new players being added
game.Players.PlayerAdded:connect(function(player)
    -- when `player` joins the game, start listening for their chatting
    player.Chatted:connect(function(message)
        -- and each time they chat, do stuff with `player` and `message`
        processCommand(player, message)
    end)
end

That's it! Now the function processCommand will be called whenever a player chats, with both the speaker and the message. Leaving this at the bottom of our script, we can start writing some commands.

[edit] Simple commands

We can now define the function processCommand. It gets two pieces of information: who was speaking - speaker, and what they said - message. Here's a simple command that prints the names of players

function processCommand(speaker, message)
    -- if someone chatted "whoami"
    if message == "whoami" then
        -- print out their name
        print(speaker.Name)
    end
end


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.

[edit] 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.

[edit] 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)