So, I’m making some admin commands for my game and some commands need to be ran on the client side.
My system currently works by getting a module script and cloning it to replicated storage so the client can access the functions needed.
A problem with this is if anyone is using a program to look into the game files, they could use the cloned module script and gain client sided admin commands for themselves on a silver platter.
A work around for this is to delete the module script on the server once the client has used it,
The downside is that I can’t make custom key binds for certain commands because it deletes itself after the client finishes executing it.
Server
local ReplicatedStorage = game:GetService("ReplicatedStorage").Shared.Managers.CommandManager
local ServerStorage = game:GetService("ServerStorage").Managers.CommandManager
local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
local RBXGeneral: TextChannel = TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXGeneral")
local command_prefix = ";"
local command_arg_splitter = ", "
local adminID = 482222647 -- temporary
RBXGeneral.ShouldDeliverCallback = function(message: TextChatMessageProperties, TextSource: TextSource)
local text = message.Text
local sender = Players:GetPlayerByUserId(TextSource.UserId)
if text:sub(1, 1) == command_prefix and IsAdmin(sender) then
return Execute(sender, text:sub(2, text:len()))
end
return true
end
function Execute(sender: Player, message: string): boolean
local args = message:split(command_arg_splitter)
local command = args[1]:lower()
table.remove(args, 1)
if (ServerStorage.ServerModules:FindFirstChild(command) ~= nil) then
local module = require(ServerStorage.ServerModules:FindFirstChild(command))
module.Execute(sender, args)
return false
end
if (sender ~= nil and ServerStorage.ClientModules:FindFirstChild(command) ~= nil) then
local module: ModuleScript = ServerStorage.ClientModules:FindFirstChild(command):Clone()
module.Parent = ReplicatedStorage.ModuleStorage
local result: boolean = ReplicatedStorage.RequestExecute:InvokeClient(sender, module, args)
module:Destroy()
-- if result == nil or result then this was an attempt to fix it.
-- module:Destroy()
-- else
-- local players: {Player} = Players:GetChildren()
-- table.remove(players, sender)
--
-- end
return false
end
return true
end
function IsAdmin(sender: Player): boolean
return sender.UserId == adminID -- replace with group roles
end
Client
local ReplicatedStorage = game:GetService("ReplicatedStorage").Shared.Managers.CommandManager
local TextChatService = game:GetService("TextChatService")
local NetworkClient = game:GetService("NetworkClient")
local module = {}
function OnClientExecute(moduleScript: ModuleScript, args: {string})
local commandModule = require(moduleScript)
return commandModule.Execute(args)
end
ReplicatedStorage.RequestExecute.OnClientInvoke = OnClientExecute
return module
Example Command Module
local players = game:GetService("Players")
local module = {}
function module.Execute(args: {string})
local highlight = Instance.new("Highlight")
local r = highlight.FillColor.R
local g = highlight.FillColor.G
local b = highlight.FillColor.B
if args[2] ~= nil and tonumber(args[2]) ~= 0 then
r = tonumber(args[2])
end
if args[3] ~= nil and tonumber(args[3]) ~= 0 then
g = tonumber(args[3])
end
if args[4] ~= nil and tonumber(args[4]) ~= 0 then
b = tonumber(args[4])
end
highlight.FillColor = Color3.fromRGB(r,g,b)
local target: Player = players[args[1]]
highlight.Parent = target.Character
return true
end
return module