My Admin Command Script

Is there any way I can improve this Module script? Its fully functional but it looks unorganized in my opinion.

local functionIds = {
	[1] = "getPizza",
	[2] = "kickPlayer",
}

local commands = {
	[1] = "/pizza",
	[2] = "/kick",

}


local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
local DataStoreService = game:GetService("DataStoreService")
local Bans = DataStoreService:GetDataStore("Bans")
local ServerScriptService = game:GetService("ServerScriptService")
local ChatService = require(ServerScriptService:WaitForChild("ChatServiceRunner"):WaitForChild("ChatService"))

local toolId = 22596452 -- Pepperoni pizza slice gear
local prefix = "/"



local function OnPlayerAdded(player)
	

	player.Chatted:Connect(function(message, recipient)
		message = string.lower(message)

		local splitString = message:split(" ")

		local slashCommand = splitString[1]

		local cmd = slashCommand:split(prefix)

		local cmdName = cmd[2]

		if commands[cmdName] then

			local arguments = {}

			for i = 2, #splitString, 1 do
				table.insert(arguments, splitString[i])
			end

			commands[cmdName](player, arguments)

		end
	end)

end


local function findPlayer(name)

	for i, player in pairs(Players:GetPlayers()) do 
		if string.lower(player.Name) == name then
			return player
		end
	end
	return nil
end



local function processPizzaCommand(speakerName, message, channelName)
	if string.sub(message, 1, commands[1]:len()) == commands[1] then
		local model = game:GetService("InsertService"):LoadAsset(toolId)
		local tool = model:GetChildren()[1]
		local speaker = ChatService:GetSpeaker(speakerName)
		local player = speaker:GetPlayer()
		tool.Parent = player.Backpack
		print("Nom nom pizza has been received")
		return true
	end
	return false
end

local function processKickCommand(sender, arguments, channelName)
		if string.sub(arguments, 1, commands[2]:len()) == commands[2] then
			local SplitMessage = arguments:split(" ")
			local playerToKick = SplitMessage[2]
			local reason = SplitMessage[3]
		if playerToKick then
			local plrToKick = Players:FindFirstChild(playerToKick)
				if plrToKick then
					plrToKick:Kick(reason)
					print("Successfully Kicked")
				return true
			end
		end
	end
	return false
end


Players.PlayerAdded:Connect(OnPlayerAdded)

local function runChatModule(ChatService)
	ChatService:RegisterProcessCommandsFunction(functionIds[1], processPizzaCommand)
	ChatService:RegisterProcessCommandsFunction(functionIds[2], processKickCommand)
end


-- Listen for players being added
return runChatModule
4 Likes

There is a better way to do this, I won’t give full script but idea:

How about make the function in the pizza thing, like

local cmdtable = {
pizza = {
allowedrank = 0, -- if you even have this system, this important
func = function(plr,argsetc,anotherargetc)
--ur function
end
},
}

And to call the function

cmdtable[givenstring].func(plr,args,anotherargetc)

Hope this helped, however this only organizes the cmds.

Sorry, but I don’t entirely get it.

I’ll try to simplify what they said.

Basically, currently you’re storing your functions in separate ways. You store the command names in a table whilst you create those function outside the table. This is disorganized:

local cmds = {
        "/kick"
}

local function KickCommand()

end

The following code above is an example of what you’re doing right now. To organize it better, simply make a dictionary where each key is the command’s name and their respective value is the corresponding function like this:

local cmds = {
        kick = function()
            — code here
        end,
}
1 Like

How would I use the ChatService:RegisterProcessCommandsFunction() then?

You don’t. Since you already did your logic of running the functions, that would be useless in this case. Also, those functions shouldn’t exist in this code. They should exist under the ChatModules folder under the Chat service.

I need to or else the commands will appear in chat. With my current code, the commands don’t appear in chat because of the function.

My Module Script already is in the ChatModules Folder under ChatService.
The RegisterProcessCommandsFunction works with my current code.

Is there a way I could organize my code while still being able to use RegisterProcessCommandsFunction?

In that case

This whole code would be unnecessary because the below code already takes responsibility over it

Also, if you have a lot of commands and functions to work on, you don’t have to type like the code you did above, you can simply use a for loop:

local function Run(ChatService)
    for commandName, commandFunc in pairs(cmds) do
        ChatService:RegisterProcessCommandsFunction(commandName, commandFunc)
    end
end

The cmds variable, again, is like the one I mentioned at my previous post:

It may work, but it would be extremely inefficient. When writing a module script, the entire point is to modularize code. Hardcoding in processing for the commands wouldn’t be good in this case.

Do what @ItzMeZeus_IGotHacked said and store the commands and permissions for said command in a table, then call the function via a table["key"] call. For my admin system, I have each command in a separate file and a loop that registers each command in a table in the main script. I did mine that way for better organization and I suggest you do the same.

As an example of what I’m saying:

function main_loader.load()
	local folder = script.Storage.Commands
	for _, child in pairs(folder:GetChildren()) do
		if child:IsA("ModuleScript") then
			main_loader.settings.commands[child.Name] = require(child).run
		end
	end
end

Explanation of Code

Loop through your commands folder’s children, and store the script name, which in this case would be the command.

for _, child in pairs(folder:GetChildren()) do

Make sure it’s a ModuleScript to prevent errors.

if child:IsA("ModuleScript") then

Now here is where we store the command in a table

main_loader.settings.commands[child.Name] = require(child).run

Notice how the function run doesn’t have the two parenthesis at the end, that’s because we aren’t calling it yet, it’ll probably make more sense later.

Now we have all our commands loaded. Great.

Now to understand this code better let’s look at how the commands are structured.

local command = {}

function command.run(ctx, args)
    -- Command code here
end

return command

So we have a module script with the table called command and the function is called run

The two arguments are as follows:

ctx: “Context”, a table that contains information such as who sent the command, their ID and the command name.

args: “Arguments”, a table that contains all the arguments passed through the command

For example:

If we had a ban command and typed :ban player exploiting

It would be broken up like this:

:: The prefix
ban: The command name
player, exploiting: The two arguments passed in.

You can break this up however you want.

Now you can add the player who chatted to a table called context or whatever name you want.

I specifically did this for my context table:

local context = {}
context["author"] = p.Name
context["authorId"] = p.UserId
context["cmd"] = cmdN -- This is a variable that has the command name.

Now you can take your arguments table and context table, call the command from the commands table and pass both those tables as it’s arguments.

Like this:

main_loader.settings.commands["ban"].run(contextTable, argumentsTable)

I hope this more in depth explanation helped you understand more about how these admin systems work. Obviously there’s more complex things like all the command code and such but the base of loading and running the commands is fairly simple.

Best of luck to you, PM me with any other questions!

1 Like