diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau
index c38d42b7e..150654bf7 100644
--- a/MainModule/Server/Commands/Admins.luau
+++ b/MainModule/Server/Commands/Admins.luau
@@ -1,1719 +1,1598 @@
-server = nil
-service = nil
-Routine = nil
-GetEnv = nil
-origEnv = nil
-logError = nil
-
---// Admin
-return function(Vargs, GetEnv)
- local env = GetEnv(nil, {script = script})
- setfenv(1, env)
-
+--!nocheck
+return function(Vargs, env)
local server = Vargs.Server;
local service = Vargs.Service;
- local Functions, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Settings, Commands
- local AddLog, TrackTask, Defaults
- local CreatorId = game.CreatorType == Enum.CreatorType.User and game.CreatorId or service.GetGroupCreatorId(game.CreatorId)
- local function Init()
- Functions = server.Functions;
- Admin = server.Admin;
- Anti = server.Anti;
- Core = server.Core;
- HTTP = server.HTTP;
- Logs = server.Logs;
- Remote = server.Remote;
- Process = server.Process;
- Variables = server.Variables;
- Settings = server.Settings;
- Commands = server.Commands;
- Defaults = server.Defaults
-
- TrackTask = service.TrackTask
- AddLog = Logs.AddLog;
-
- TrackTask("Thread: ChatServiceHandler", function()
-
- --// Support for modern TextChatService
- if service.TextChatService and service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then
- local function onNewTextchannel(textchannel: TextChannel)
- AddLog("Script", `Connected to TextChannel: {textchannel.Name}`)
-
- if Settings.OverrideChatCallbacks ~= false then --// Default to "on" this for all games
- AddLog("Script", "Overriding ShouldDeliverCallback for " .. textchannel.Name)
- textchannel.ShouldDeliverCallback = function(chatMessage, textSource)
- if
- chatMessage.Status == Enum.TextChatMessageStatus.Success
- or chatMessage.Status == Enum.TextChatMessageStatus.Sending
- then
- local SenderId = chatMessage.TextSource.UserId
- local SenderPlayer = service.Players:GetPlayerByUserId(SenderId)
- local Receiver = service.Players:GetPlayerByUserId(textSource.UserId)
- local slowCache = Admin.SlowCache
-
- local IsOriginalSender = SenderPlayer == Receiver
-
- if not SenderPlayer then
- return true
- elseif Admin.DoHideChatCmd(SenderPlayer, chatMessage.Text) then -- // Hide chat commands?
- return false
- elseif Admin.IsMuted(SenderPlayer) then -- // Mute handler
- if IsOriginalSender then
- server.Remote.Send(SenderPlayer, "Function", "DisplaySystemMessageInTextChat", nil, `[Adonis Chat]: You are muted! Other players cannot see your messages.`)
- end
-
- return false
- elseif Admin.SlowMode and not Admin.CheckAdmin(SenderPlayer) and slowCache[SenderPlayer] and os.time() - slowCache[SenderPlayer] < Admin.SlowMode then
- if IsOriginalSender then --// Only show this for the person sending! Hide for others, however
- --Functions.Notification("You are chatting too fast!", string.format("[Adonis] :: Slow mode enabled! (%g second(s) remaining)", Admin.SlowMode - (os.time() - slowCache[SenderPlayer])), {SenderPlayer}, 10)
-
- server.Remote.Send(SenderPlayer, "Function", "DisplaySystemMessageInTextChat", nil, `[Adonis Chat]: You are sending messages too fast! {string.format("(%g second(s) remaining)", Admin.SlowMode - (os.time() - slowCache[SenderPlayer]))}`)
- end
-
- return false
- end
-
- if Variables.DisguiseBindings[SenderId] then -- // Disguise command handler
- chatMessage.PrefixText = Variables.DisguiseBindings[SenderId].TargetUsername..":"
- end
-
- if Admin.SlowMode and IsOriginalSender then
- slowCache[SenderPlayer] = os.time()
- end
- end
-
- return true
+ local Settings = server.Settings
+ local Functions, Commands, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Deps =
+ server.Functions, server.Commands, server.Admin, server.Anti, server.Core, server.HTTP, server.Logs, server.Remote, server.Process, server.Variables, server.Deps
+
+ if env then setfenv(1, env) end
+
+ local Routine = env.Routine
+
+ return {
+ SetRank = {
+ Prefix = Settings.Prefix;
+ Commands = {"setrank", "permrank", "permsetrank"};
+ Args = {"player/user", "rank"};
+ Description = "Sets the admin rank of the target user(s); THIS SAVES!";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ assert(args[1], "Missing target user (argument #1)")
+ local rankName = assert(args[2], "Missing rank name (argument #2)")
+
+ local newRank = Settings.Ranks[rankName]
+ if not newRank then
+ for thisRankName, thisRank in Settings.Ranks do
+ if thisRankName:lower() == rankName:lower() then
+ rankName = thisRankName
+ newRank = thisRank
+ break
end
+ end
+ end
+ assert(newRank, `No rank named '{rankName}' exists`)
+
+ local newLevel = newRank.Level
+ local senderLevel = data.PlayerData.Level
+
+ assert(newLevel < senderLevel, string.format("Rank level (%s) cannot be equal to or above your own level (%s)", newLevel, senderLevel))
+ local v = Functions.GetPlayers(plr, args[1], {NoFakePlayer = false})
+ for _, p in v do
+ if senderLevel > Admin.GetLevel(p) then
+ Admin.AddAdmin(p, rankName)
+ Functions.LogAdminAction(plr, "Set Rank", p.Name, `New rank: {rankName}, New level: {newLevel}`)
+ Functions.Notification(
+ "Notification",
+ `You are {if string.lower(string.sub(rankName, 1, 3)) == "the" then "" elseif string.match(rankName, "^[AEIOUaeiou]") and string.lower(string.sub(rankName, 1, 3)) ~= "uni" then "an " else "a "}{rankName}. Click to view commands.`,
+ {p}, 10, "MatIcon://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}cmds')`)
+ )
+ Functions.Hint(`{service.FormatPlayer(p, true)} is now rank {rankName} (Permission Level: {newLevel})`, {plr})
else
- AddLog("Script", `Using the 'CanSend' method of handling chat connectivity in channel {textchannel.Name}`)
- server.Variables.TextChatSpeakers = {}
- local function AddUserToTextChatSpeakers(player: Player, speaker: TextSource)
- if not server.Variables.TextChatSpeakers[player] then
- server.Variables.TextChatSpeakers[player] = {}
- end
- table.insert(server.Variables.TextChatSpeakers[player], speaker)
- --// Check if the player is muted or not
- speaker:SetAttribute("OriginalCanSend", speaker.CanSend)
- if server.Admin.IsMuted(player) then
- speaker.CanSend = false
- end
- end
- local function SpeakerAdded(speaker: TextSource)
- if speaker.UserId and speaker.UserId > 0 then
- local Player = service.Players:GetPlayerByUserId(speaker.UserId)
- if Player then
- AddUserToTextChatSpeakers(Player, speaker)
- end
- end
- end
- local function SpeakerRemoved(speaker: TextSource)
- if speaker.UserId and speaker.UserId > 0 then
- local Player = service.Players:GetPlayerByUserId(speaker.UserId)
- local Tab = server.Variables.TextChatSpeakers[Player]
- if Tab then
- local index = table.find(Tab, speaker)
- while index do
- table.remove(Tab, index)
- index = table.find(Tab, speaker)
- end
- task.defer(function()
- if #Tab == 0 then
- server.Variables.TextChatSpeakers[Player] = nil
- end
- end)
- end
- end
- end
-
- textchannel.ChildAdded:Connect(function(textSource)
- if textSource:IsA("TextSource") then
- SpeakerAdded(textSource)
- end
- end)
-
- textchannel.ChildRemoved:Connect(function(textSource)
- if textSource:IsA("TextSource") then
- SpeakerRemoved(textSource)
- end
- end)
-
- for _,inst in textchannel:GetChildren() do
- if inst:IsA("TextSource") then
- SpeakerAdded(inst)
- end
- end
-
+ Functions.Hint(`You do not have permission to set the rank of {service.FormatPlayer(p, true)}`, {plr})
end
end
-
- --// Only set this up once
- --// This is for commands to tell us when a player should be muted
- if not Settings.OverrideChatCallbacks then
- service.Events.PlayerMuted:Connect(function(data)
- local PlayerId = data.Target;
- local ModId = data.Moderator;
-
- local Player = service.Players:GetPlayerByUserId(PlayerId)
- --// Loop through CanSend of a speaker
- for _,speakers : TextSource in if Player then server.Variables.TextChatSpeakers[Player] or {} else {} do
- speakers.CanSend = false
- end
- if Player then
- AddLog("Script", `Muted player {Player.Name}:{Player.UserId} using CanSend method`)
- end
- end)
- service.Events.PlayerUnMuted:Connect(function(data)
- local PlayerId = data.Target;
- local ModId = data.Moderator;
-
- local Player = service.Players:GetPlayerByUserId(PlayerId)
- --// Loop through CanSend of a speaker
- for _,speakers : TextSource in if Player then server.Variables.TextChatSpeakers[Player] or {} else {} do
- local original = speakers:GetAttribute("OriginalCanSend")
- speakers.CanSend = if original ~= nil then original else true
- end
- if Player then
- AddLog("Script", `UnMuted player {Player.Name}:{Player.UserId} via CanSend method`)
+ end;
+ };
+
+ SetTempRank = {
+ Prefix = Settings.Prefix;
+ Commands = {"settemprank", "temprank", "tempsetrank"};
+ Args = {"player", "rank"};
+ Description = `Identical to {Settings.Prefix}setrank, but doesn't save`;
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ assert(args[1], "Missing target player (argument #1)")
+ local rankName = assert(args[2], "Missing rank name (argument #2)")
+
+ local newRank = Settings.Ranks[rankName]
+ if not newRank then
+ for thisRankName, thisRank in Settings.Ranks do
+ if thisRankName:lower() == rankName:lower() then
+ rankName = thisRankName
+ newRank = thisRank
+ break
end
- end)
- service.Events.MutedPlayerChat_UnFiltered:Connect(function(p, ...)
- server.Remote.Send(p, "Function", "DisplaySystemMessageInTextChat", nil, `[Adonis Chat]: You are muted! Other players cannot see your messages.`)
- end)
+ end
end
+ assert(newRank, `No rank named '{rankName}' exists`)
+ local newLevel = newRank.Level
+ local senderLevel = data.PlayerData.Level
- local function onTextChannelsAdded(textChannels)
- textChannels.ChildAdded:Connect(function(child)
- if child:IsA("TextChannel") then
- task.spawn(onNewTextchannel, child)
- end
- end)
+ assert(newLevel < senderLevel, string.format("Rank level (%s) cannot be equal to or above your own level (%s)", newLevel, senderLevel))
- for _, v in textChannels:GetChildren() do
- if v:IsA("TextChannel") then
- task.spawn(onNewTextchannel, v)
- end
+ for _, v in service.GetPlayers(plr, args[1]) do
+ if senderLevel > Admin.GetLevel(v) then
+ Admin.AddAdmin(v, rankName, true)
+ Functions.LogAdminAction(plr, "Set Temporary Rank", v.Name, `Temporary rank set to: {rankName}`)
+ Functions.Notification("Notification", `You are a temp {rankName}. Click to view commands.`, {v}, 10, "MatIcon://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}cmds')`))
+ Functions.Hint(`{service.FormatPlayer(v, true)} is now rank {rankName} (Permission Level: {newLevel})`, {plr})
+ else
+ Functions.Hint(`You do not have permission to set the rank of {service.FormatPlayer(v, true)}`, {plr})
end
end
-
- service.TextChatService.ChildAdded:Connect(function(child)
- if child.Name == "TextChannels" then
- task.spawn(onTextChannelsAdded, child)
+ end;
+ };
+
+ SetLevel = {
+ Prefix = Settings.Prefix;
+ Commands = {"setlevel", "setadminlevel"};
+ Args = {"player", "level"};
+ Description = "Sets the target player(s) permission level for the current server; does not save";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local senderLevel = data.PlayerData.Level
+ local newLevel = assert(tonumber(args[2]), "Level must be a number")
+
+ assert(newLevel < senderLevel, `Level cannot be equal to or above your own permission level ({senderLevel})`);
+
+ for _, v in service.GetPlayers(plr, args[1])do
+ if senderLevel > Admin.GetLevel(v) then
+ Admin.SetLevel(v, newLevel, args[3] == "true")
+ Functions.LogAdminAction(plr, "Set Level", v.Name, `New level: {newLevel}`)
+ Functions.Notification("Notification", `Your admin permission level was set to {newLevel} for this server only. Click to view commands.`, {v}, 10, "MatIcon://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}cmds')`))
+ Functions.Hint(`{service.FormatPlayer(v, true)} is now permission level {newLevel}`, {plr})
+ else
+ Functions.Hint(`You do not have permission to set the permission level of {service.FormatPlayer(v, true)}`, {plr})
end
- end)
-
- if service.TextChatService:FindFirstChild("TextChannels") then
- task.spawn(pcall, onTextChannelsAdded, service.TextChatService:FindFirstChild("TextChannels"))
end
-
- AddLog("Script", "TextChatService Handler Loaded")
- end
-
- --// Support for legacy Lua chat system
- --// ChatService mute handler (credit to Coasterteam)
- AddLog("Script", "Starting loading of legacy chatservice handler")
- local chatService = Functions.GetChatService(300)
- if chatService then
- chatService:RegisterProcessCommandsFunction("ADONIS_CMD", function(speakerName, message)
- local speaker = chatService:GetSpeaker(speakerName)
- local speakerPlayer = speaker and speaker:GetPlayer()
-
- if not speakerPlayer then
- return false
- end
-
- if Admin.DoHideChatCmd(speakerPlayer, message) then
- return true
+ end;
+ };
+
+ UnAdmin = {
+ Prefix = Settings.Prefix;
+ Commands = {"unadmin", "unmod", "unowner", "unpadmin", "unheadadmin", "unrank"};
+ Args = {"player/user / list entry", "temp? (true/false) (default: false)"};
+ Description = "Removes admin/moderator ranks from the target player(s); saves unless is 'true'";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local target = assert(args[1], "Missing target user (argument #1)")
+ local temp = args[2] and args[2]:lower() == "true"
+ local senderLevel = data.PlayerData.Level
+ local userFound = false
+
+ if not string.find(target, ":") then
+ for _, v in service.GetPlayers(plr, target, {
+ UseFakePlayer = true;
+ DontError = true;
+ })
+ do
+ userFound = true
+ local targLevel, targRank = Admin.GetLevel(v)
+ if targLevel > 0 then
+ if senderLevel > targLevel then
+ Admin.RemoveAdmin(v, temp)
+ Functions.LogAdminAction(plr, "Remove Admin", v.Name, `Temporary: {temp}`)
+ Functions.Hint(string.format("Removed %s from rank %s", service.FormatPlayer(v, true), targRank or "[unknown rank]"), {plr})
+ Functions.Notification("Notification", `You are no longer a(n) {targRank or "admin"}`, {v}, 10, "MatIcon://Shield")
+ else
+ Functions.Hint(`You do not have permission to remove {service.FormatPlayer(v, true)}'s rank`, {plr})
+ end
+ else
+ Functions.Hint(`{service.FormatPlayer(v, true)} does not already have any rank to remove`, {plr})
+ end
end
- return false
- end)
-
- chatService:RegisterProcessCommandsFunction("ADONIS_MUTE_SERVER", function(speakerName, _, channelName)
- local slowCache = Admin.SlowCache
-
- local speaker = chatService:GetSpeaker(speakerName)
- local speakerPlayer = speaker and speaker:GetPlayer()
-
- if not speakerPlayer then
- return false
+ if userFound then
+ return
+ else
+ Functions.Hint("User not found in server; searching datastore", {plr})
end
+ end
- if speakerPlayer and Admin.IsMuted(speakerPlayer) then
- speaker:SendSystemMessage("[Adonis] :: You are muted!", channelName)
- return true
- elseif speakerPlayer and Admin.SlowMode and not Admin.CheckAdmin(speakerPlayer) and slowCache[speakerPlayer] and os.time() - slowCache[speakerPlayer] < Admin.SlowMode then
- speaker:SendSystemMessage(string.format("[Adonis] :: Slow mode enabled! (%g second(s) remaining)", Admin.SlowMode - (os.time() - slowCache[speakerPlayer])), channelName)
- return true
+ for rankName, rankData in Settings.Ranks do
+ if senderLevel <= rankData.Level then
+ continue
end
-
- if Admin.SlowMode then
- slowCache[speakerPlayer] = os.time()
+ for i, user in rankData.Users do
+ if not (user:lower() == target:lower() or user:lower():match(`^{target:lower()}:`) or Admin.DoCheck(target, user)) then
+ continue
+ end
+ if
+ Remote.GetGui(plr, "YesNoPrompt", {
+ Question = `Remove '{user}' from '{rankName}'?`;
+ }) == "Yes"
+ then
+ table.remove(rankData.Users, i)
+ if not temp and Settings.SaveAdmins then
+ service.TrackTask("Thread: RemoveAdmin", Core.DoSave, false, {
+ Type = "TableRemove";
+ Table = {"Settings", "Ranks", rankName, "Users"};
+ Value = user;
+ });
+ Functions.Hint(`Removed entry '{user}' from {rankName}`, {plr})
+ Logs:AddLog("Script", `{plr} removed {user} from {rankName}`)
+ end
+ end
+ userFound = true
end
-
- return false
- end)
-
- AddLog("Script", "ChatService Handler Loaded")
- elseif chatService == false then
- AddLog("Script", "Using TextChatService; Handler Loaded")
- else
- warn("Place is missing ChatService; Vanilla Roblox chat related features may not work")
- AddLog("Script", "ChatService Handler Not Found")
- end
- end)
-
- --// Make sure the default ranks are always present for compatability with existing commands
- local Ranks = Settings.Ranks
- for rank, data in Defaults.Settings.Ranks do
- if not Ranks[rank] then
- for r, d in Ranks do
- if d.Level == data.Level then
- data.Hidden = true
- break
+ end
+ assert(userFound, `No table entries matching '{args[1]}' were found`)
+ end
+ };
+
+ TempUnAdmin = {
+ Prefix = Settings.Prefix;
+ Commands = {"tempunadmin", "untempadmin", "tunadmin", "untadmin"};
+ Args = {"player"};
+ Description = "Removes the target players' admin powers for this server; does not save";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local senderLevel = data.PlayerData.Level
+
+ for _, v in service.GetPlayers(plr, assert(args[1], "Missing target player (argument #1)")) do
+ local targetLevel = Admin.GetLevel(v)
+ if targetLevel > 0 then
+ if senderLevel > targetLevel then
+ Admin.RemoveAdmin(v, true)
+ Functions.LogAdminAction(plr, "Temporary Unadmin", v.Name, "Admin powers temporarily removed")
+ Functions.Hint(`Removed {service.FormatPlayer(v)}'s admin powers`, {plr})
+ Functions.Notification("Notification", "Your admin powers have been temporarily removed", {v}, 10, "MatIcons://Remove moderator")
+ else
+ Functions.Hint(`You do not have permission to remove {service.FormatPlayer(v, true)}'s admin powers`, {plr})
+ end
+ else
+ Functions.Hint(`{service.FormatPlayer(v, true)} is not an admin`, {plr})
end
end
- Ranks[rank] = data
end
- end
-
- if Settings.CustomRanks then
- local Ranks = Settings.Ranks
- for name, users in Settings.CustomRanks do
- if not Ranks[name] then
- Ranks[name] = {
- Level = 1;
- Users = users;
- };
+ };
+
+ TempModerator = {
+ Prefix = Settings.Prefix;
+ Commands = {"tempmod", "tmod", "tempmoderator", "tmoderator"};
+ Args = {"player"};
+ Description = "Makes the target player(s) a temporary moderator; does not save";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local senderLevel = data.PlayerData.Level
+
+ for _, v in service.GetPlayers(plr, assert(args[1], "Missing target player (argument #1)")) do
+ if senderLevel > Admin.GetLevel(v) then
+ Admin.AddAdmin(v, "Moderators", true)
+ Functions.LogAdminAction(plr, "Temporary Moderator", v.Name, "N/A")
+ Functions.Notification("Notification", "You are a temp moderator. Click to view commands.", {v}, 10, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}cmds')`))
+ Functions.Hint(`{service.FormatPlayer(v, true)} is now a temp moderator`, {plr})
+ else
+ Functions.Hint(`{service.FormatPlayer(v, true)} is already the same admin level as you or higher`, {plr})
+ end
end
end
- end
+ };
- if Settings.CommandCooldowns then
- for cmdName, cooldownData in Settings.CommandCooldowns do
- local realCmd = Admin.GetCommand(cmdName)
+ Moderator = {
+ Prefix = Settings.Prefix;
+ Commands = {"permmod", "pmod", "mod", "moderator", "pmoderator"};
+ Args = {"player/user"};
+ Description = "Makes the target player(s) a moderator; saves";
+ AdminLevel = "Admins";
+ Dangerous = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local senderLevel = data.PlayerData.Level
- if realCmd then
- if cooldownData.Player then
- realCmd.PlayerCooldown = cooldownData.Player
- end
-
- if cooldownData.Server then
- realCmd.ServerCooldown = cooldownData.Server
- end
-
- if cooldownData.Cross then
- realCmd.CrossCooldown = cooldownData.Cross
+ for _, v in service.GetPlayers(plr, assert(args[1], "Missing target player (argument #1)"), {
+ UseFakePlayer = true;
+ })
+ do
+ if senderLevel > Admin.GetLevel(v) then
+ Admin.AddAdmin(v, "Moderators")
+ Functions.LogAdminAction(plr, "Promoted to Moderator", v.Name, "N/A")
+ Functions.Notification("Notification", "You are a moderator. Click to view commands.", {v}, 10, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}cmds')`))
+ Functions.Hint(`{service.FormatPlayer(v, true)} is now a moderator`, {plr})
+ else
+ Functions.Hint(`{service.FormatPlayer(v, true)} is already the same admin level as you or higher`, {plr})
end
end
end
- end
-
- Admin.Init = nil;
- AddLog("Script", "Admin Module Initialized")
- end;
-
- local function RunAfterPlugins(data)
- --// Backup Map
- if Settings.AutoBackup then
- TrackTask("Thread: Initial Map Backup", Admin.RunCommand, false, `{Settings.Prefix}backupmap`)
- end
-
- --// Run OnStartup Commands
- for i,v in Settings.OnStartup do
- print(`Running startup command {v}`)
- TrackTask(`Thread: Startup_Cmd: {v}`, Admin.RunCommand, false, v)
- AddLog("Script", {
- Text = `Startup: Executed {v}`;
- Desc = `Executed startup command; {v}`;
- })
- end
-
- --// Check if Shutdownlogs is set and if not then set it
- if Core.DataStore and not Core.GetData("ShutdownLogs") then
- Core.SetData("ShutdownLogs", {})
- end
-
- Admin.RunAfterPlugins = nil;
- AddLog("Script", "Admin Module RunAfterPlugins Finished")
- end
-
- service.MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, id, purchased)
- if Variables and player.Parent and table.find(Variables.DonorPass, id) and purchased then
- Variables.CachedDonors[tostring(player.UserId)] = os.time()
- end
- end)
-
- local function stripArgPlaceholders(alias)
- return service.Trim(string.gsub(alias, "<%S+>", ""))
- end
-
- local function FormatAliasArgs(alias, aliasCmd, msg)
- local uniqueArgs = {}
- local argTab = {}
- local numArgs = 0
-
- --// First try to extract args info from the alias
- for arg in string.gmatch(alias, "<(%S+)>") do
- if arg ~= "" and arg ~= " " then
- local arg = `<{arg}>`
- if not uniqueArgs[arg] then
- numArgs += 1
- uniqueArgs[arg] = true
- table.insert(argTab, arg)
- end
- end
- end
-
- --// If no args in alias string, check the command string instead and try to guess args based on order of appearance
- if numArgs == 0 then
- for arg in string.gmatch(aliasCmd, "<(%S+)>") do
- if arg ~= "" and arg ~= " " then
- local arg = `<{arg}>`
- if not uniqueArgs[arg] then --// Get only unique placeholder args, repeats will be matched to the same arg pos
- numArgs += 1
- uniqueArgs[arg] = true --// :cmd
- table.insert(argTab, arg)
+ };
+
+ Broadcast = {
+ Prefix = Settings.Prefix;
+ Commands = {"broadcast", "bc"};
+ Args = {"Message"};
+ Filter = true;
+ Description = "Makes a message in the chat window";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers() do
+ if service.TextChatService and service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then
+ local TextToUse = args[1]
+ if data.Options.Chat ~= true then
+ TextToUse = service.SanitizeXML(args[1] or "Hello world!")
+ end
+ Remote.Send(
+ v, "Function", "DisplaySystemMessageInTextChat", nil, `{
+ string.format(`[%s] %s`, Settings.SystemTitle, service.Filter(TextToUse), plr, v)
+ }`)
+ else
+ Remote.Send(v, "Function", "ChatMessage", string.format("[%s] %s", Settings.SystemTitle, service.Filter(args[1], plr, v)), Color3.fromRGB(255,64,77))
end
end
end
- end
-
- local suppliedArgs = Admin.GetArgs(msg, numArgs) -- User supplied args (when running :alias arg)
- local out = aliasCmd
-
- local SanitizePattern = service.SanitizePattern
- for i,argType in argTab do
- local replaceWith = suppliedArgs[i]
- if replaceWith then
- out = string.gsub(out, SanitizePattern(argType), replaceWith)
- end
- end
-
- return out
- end
+ };
- server.Admin = {
- Init = Init;
- RunAfterPlugins = RunAfterPlugins;
-
- SpecialLevels = {};
- TempAdmins = {};
-
- PrefixCache = {};
- CommandCache = {};
- SlowCache = {};
- UserIdCache = {};
- UsernameCache = {};
- GroupsCache = {};
-
- BlankPrefix = false;
-
- --// How long admin levels will be cached (unless forcibly updated via something like :admin user)
- AdminLevelCacheTimeout = 30;
-
- CheckSlowMode = function(p: Player)
- if Admin.SlowMode and Admin.SlowCache[p] and os.time() - Admin.SlowCache[p] < Admin.SlowMode then
- return true
- else
- return false
+ ShutdownLogs = {
+ Prefix = Settings.Prefix;
+ Commands = {"shutdownlogs", "shutdownlog", "slogs", "shutdowns"};
+ Args = {};
+ Description = "Shows who shutdown or restarted a server and when";
+ AdminLevel = "Admins";
+ ListUpdater = function(plr: Player)
+ local logs = Core.GetData("ShutdownLogs") or {}
+ local tab = {}
+ for i, v in logs do
+ if v.Restart then v.Time ..= " [RESTART]" end
+ tab[i] = {
+ Text = `{v.Time}: {v.User}`;
+ Desc = `Reason: {v.Reason}`;
+ }
+ end
+ return tab
+ end;
+ Function = function(plr: Player, args: {string})
+ Remote.MakeGui(plr, "List", {
+ Title = "Shutdown Logs";
+ Table = Logs.ListUpdaters.ShutdownLogs(plr);
+ Update = "ShutdownLogs";
+ })
end
- end,
-
- DoHideChatCmd = function(p: Player, message: string, data: {[string]: any}?)
- local pData = data or Core.GetPlayer(p)
- if pData.Client.HideChatCommands then
- if Admin.BlankPrefix and
-
- (string.sub(message,1,1) ~= Settings.Prefix or string.sub(message,1,1) ~= Settings.PlayerPrefix or (type(Settings.Prefix) == "table" and not table.find(Settings.Prefix, string.sub(message,1,1)))) then
- local isCMD = Admin.GetCommand(message)
- if isCMD then
- return true
+ };
+
+ ServerLock = {
+ Prefix = Settings.Prefix;
+ Commands = {"slock", "serverlock", "lockserver"};
+ Args = {"on/off"};
+ Description = "Enables/disables server lock";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local arg = args[1] and string.lower(args[1])
+ Functions.LogAdminAction(plr, "Server Lock", "Server is now " .. (if (arg == "on" or arg == "true") then "locked" else "unlocked"), "")
+ if (not arg and Variables.ServerLock ~= true) or arg == "on" or arg == "true" then
+ Variables.ServerLock = true
+ Functions.Hint("Server Locked", service.Players:GetPlayers())
+ elseif Variables.ServerLock == true or arg == "off" or arg == "false" then
+ Variables.ServerLock = false
+ Functions.Hint("Server Unlocked", service.Players:GetPlayers())
+ end
+ end
+ };
+
+ Whitelist = {
+ Prefix = Settings.Prefix;
+ Commands = {"wl", "enablewhitelist", "whitelist"};
+ Args = {"on/off/add/remove/list/clear", "optional player"};
+ Description = "Enables/disables the server whitelist; :wl username to add them to the whitelist";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local sub = string.lower(args[1])
+
+ if sub == "on" or sub == "enable" then
+ Variables.Whitelist.Enabled = true
+ Functions.Hint("Enabled server whitelist", service.Players:GetPlayers())
+ elseif sub == "off" or sub == "disable" then
+ Variables.Whitelist.Enabled = false
+ Functions.Hint("Disabled server whitelist", service.Players:GetPlayers())
+ elseif sub == "add" then
+ if args[2] then
+ local plrs = service.GetPlayers(plr, args[2], {
+ DontError = true;
+ IsServer = false;
+ IsKicking = false;
+ NoFakePlayer = false;
+ })
+ if #plrs>0 then
+ for _, v in plrs do
+ table.insert(Variables.Whitelist.Lists.Settings, `{v.Name}:{v.UserId}`)
+ Functions.Hint(`Added {service.FormatPlayer(v)} to the whitelist`, {plr})
+ end
+ else
+ table.insert(Variables.Whitelist.Lists.Settings, args[2])
+ end
else
- return false
+ error("Missing user argument")
end
- elseif (string.sub(message,1,1) == Settings.Prefix or string.sub(message,1,1) == Settings.PlayerPrefix or (type(Settings.Prefix) == "table" and table.find(Settings.Prefix, string.sub(message,1,1))))
- and string.sub(message,2,2) ~= string.sub(message,1,1) then
- return true;
- end
- end
- end;
-
- GetPlayerGroups = function(p: Player)
- if not p or p.Parent ~= service.Players then
- return {}
- end
- return Admin.GetGroups(p.UserId)
- end;
-
- GetPlayerGroup = function(p, group)
- local groups = Admin.GetPlayerGroups(p)
- local isId = type(group) == "number"
- if groups and #groups > 0 then
- for _, g in groups do
- if (isId and g.Id == group) or (not isId and g.Name == group) then
- return g
+ elseif sub == "remove" then
+ if args[2] then
+ for i, v in Variables.Whitelist.Lists.Settings do
+ if string.sub(string.lower(v), 1,#args[2]) == string.lower(args[2])then
+ table.remove(Variables.Whitelist.Lists.Settings,i)
+ Functions.Hint(`Removed {v} from the whitelist`, {plr})
+ end
+ end
+ else
+ error("Missing user argument")
end
- end
- end
- end;
-
- GetGroups = function(uid, updateCache)
- uid = tonumber(uid)
-
- if type(uid) == "number" then
- local existCache = Admin.GroupsCache[uid]
- local canUpdate = false
-
- if not updateCache then
- --> Feel free to adjust the time to update over or less than 300 seconds (5 minutes).
- --> 300 seconds is recommended in the event of unexpected server breakdowns with Roblox and faster performance.
- if (existCache and (os.time()-existCache.LastUpdated > 300)) or not existCache then
- canUpdate = true
+ elseif sub == "list" then
+ local Tab = {}
+ for Key, List in Variables.Whitelist.Lists do
+ local Prefix = Key == "Settings" and "" or `[{Key}] `
+ for _, User in List do
+ table.insert(Tab, {Text = Prefix .. User, Desc = User})
+ end
end
+ Remote.MakeGui(plr, "List", {Title = "Whitelist List"; Tab = Tab;})
+ elseif sub == "clear" then
+ Variables.Whitelist.Lists.Settings = {}
+ Functions.Hint("Cleared server whitelist", service.Players:GetPlayers())
else
- canUpdate = true
- end
-
- if canUpdate then
- local cacheTab = {
- Groups = (existCache and existCache.Groups) or {};
- LastUpdated = os.time();
- }
- Admin.GroupsCache[uid] = cacheTab
-
- local suc,groups = pcall(function()
- return service.GroupService:GetGroupsAsync(uid) or {}
- end)
-
- if suc and type(groups) == "table" then
- cacheTab.Groups = groups
- return cacheTab.Groups
+ error("Invalid subcommand (on/off/add/remove/list/clear)")
+ end
+ end
+ };
+
+ SystemNotify = {
+ Prefix = Settings.Prefix;
+ Commands = {"sn", "systemnotify", "sysnotif", "sysnotify", "systemsmallmessage", "snmessage", "snmsg", "ssmsg", "ssmessage"};
+ Args = {"message"};
+ Filter = true;
+ Description = "Makes a system small message";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[1], "Missing message")
+ for _, v in service.GetPlayers() do
+ Remote.RemoveGui(v, "Notify")
+ Functions.Notify(Settings.SystemTitle, service.Filter(args[1], plr, v), {v})
+ end
+ end
+ };
+
+ Notif = {
+ Prefix = Settings.Prefix;
+ Commands = {"setmessage", "notif", "setmsg", "permhint"};
+ Args = {"message OR off"};
+ Filter = true;
+ Description = "Sets a small hint message at the top of the screen";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[1], "Missing message (or enter 'off' to disable)")
+
+ if args[1] == "off" or args[1] == "false" then
+ Variables.NotifMessage = nil
+ for _, v in service.GetPlayers() do
+ Remote.RemoveGui(v, "Notif")
end
-
- Admin.GroupsCache[uid] = cacheTab
- return table.clone(cacheTab.Groups)
else
- return table.clone((existCache and existCache.Groups) or {})
- end
- end
- end;
-
- GetGroupLevel = function(uid, groupId)
- groupId = tonumber(groupId)
-
- if groupId then
- local groups = Admin.GetGroups(uid) or {}
-
- for _, group in groups do
- if group.Id == groupId then
- return group.Rank
+ Variables.NotifMessage = args[1]
+ for _, v in service.GetPlayers() do
+ Remote.MakeGui(v, "Notif", {
+ Message = Variables.NotifMessage;
+ })
end
end
end
-
- return 0
- end;
-
- CheckInGroup = function(uid, groupId)
- local groups = Admin.GetGroups(uid) or {}
- groupId = tonumber(groupId)
-
- if groupId then
- for i,group in groups do
- if group.Id == groupId then
- return true
+ };
+
+ SetBanMessage = {
+ Prefix = Settings.Prefix;
+ Commands = {"setbanmessage", "setbmsg"};
+ Args = {"message"};
+ Filter = true;
+ Description = "Sets the ban message banned players see";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ Variables.BanMessage = assert(args[1], "Missing message (argument #1)")
+ end
+ };
+
+ SetLockMessage = {
+ Prefix = Settings.Prefix;
+ Commands = {"setlockmessage", "slockmsg", "setlmsg"};
+ Args = {"message"};
+ Filter = true;
+ Description = "Sets the lock message unwhitelisted players see if :whitelist or :slock is on";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ Variables.LockMessage = assert(args[1], "Missing message (argument #1)")
+ end
+ };
+
+ SystemMessage = {
+ Prefix = Settings.Prefix;
+ Commands = {"sm", "systemmessage", "sysmsg"};
+ Args = {"message"};
+ Filter = true;
+ Description = "Same as message but says SYSTEM MESSAGE instead of your name, or whatever system message title is server to...";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ Functions.Message(Settings.SystemTitle, service.BroadcastFilter(assert(args[1], "Missing message (argument #1)"), plr), service.GetPlayers(), true)
+ end
+ };
+
+ SetCoreGuiEnabled = {
+ Prefix = Settings.Prefix;
+ Commands = {"setcoreguienabled", "setcoreenabled", "showcoregui", "setcoregui", "setcgui", "setcore", "setcge"};
+ Args = {"player", "All/Backpack/Chat/EmotesMenu/Health/PlayerList", "true/false"};
+ Description = "Enables or disables CoreGui elements for the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[3], "Missing state (argument #3)")
+ local enable = if args[3]:lower() == "on" or args[3]:lower() == "true" then true elseif args[3]:lower() == "off" or args[3]:lower() == "false" then false else nil
+ assert(enable ~= nil, `Invalid state '{args[3]}'; please supply 'true' or 'false' (argument #3)`)
+ for _,v in service.GetPlayers(plr, args[1]) do
+ if string.lower(args[3]) == "on" or string.lower(args[3]) == "true" then
+ Remote.Send(v, "Function", "SetCoreGuiEnabled", args[2], true)
+ elseif string.lower(args[3]) == 'off' or string.lower(args[3]) == "false" then
+ Remote.Send(v, "Function", "SetCoreGuiEnabled", args[2], false)
end
end
end
-
- return false
- end,
-
- IsLax = function(str)
- for _, v in {"plr", "user", "player", "brickcolor"} do
- if string.match(string.lower(str), v) then
- return true
- end
- end
-
- return false
- end,
-
- IsMuted = function(player)
- local DoCheck = Admin.DoCheck
- for _, v in Settings.Muted do
- if DoCheck(player, v) then
- return true
- end
- end
-
- for _, v in HTTP.Trello.Mutes do
- if DoCheck(player, v) then
- return true
+ };
+
+ Alert = {
+ Prefix = Settings.Prefix;
+ Commands = {"alert", "alarm", "annoy"};
+ Args = {"player", "message"};
+ Filter = true;
+ Description = "Get someone's attention";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr,string.lower(args[1]))do
+ Remote.MakeGui(v, "Alert", {Message = args[2] and service.Filter(args[2],plr, v) or "Wake up; Your attention is required"})
+ end
+ end
+ };
+
+ LockMap = {
+ Prefix = Settings.Prefix;
+ Commands = {"lockmap"};
+ Args = {};
+ Description = "Locks the map";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, obj in workspace:GetDescendants()do
+ if obj:IsA("BasePart")then
+ obj.Locked = true
+ end
end
end
+ };
- if HTTP.WebPanel.Mutes then
- for _, v in HTTP.WebPanel.Mutes do
- if DoCheck(player, v) then
- return true
+ UnlockMap = {
+ Prefix = Settings.Prefix;
+ Commands = {"unlockmap"};
+ Args = {};
+ Description = "Unlocks the map";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, obj in workspace:GetDescendants()do
+ if obj:IsA("BasePart")then
+ obj.Locked = false
end
end
end
- end;
-
- DoCheck = function(pObj, check, banCheck)
- local pType = typeof(pObj)
- local cType = typeof(check)
-
- local pUnWrapped = service.UnWrap(pObj)
-
- local plr: Player = if pType == "userdata" and pObj:IsA("Player") then pObj
- elseif pType == "number" then service.Players:GetPlayerByUserId(pObj)
- elseif pType == "string" then service.Players:FindFirstChild(pObj)
- elseif typeof(pUnWrapped) == "Instance" and pUnWrapped:IsA("Player") then pUnWrapped
- elseif pType == "userdata" then service.Players:GetPlayerByUserId(pObj.UserId)
- else nil
- if not plr then
- return false
- end
-
- if cType == "number" then
- return plr.UserId == check
- elseif cType == "string" then
- if plr.Name == check then
- return true
- end
-
- local filterName, filterData = string.match(check, "^(.-):(.+)$")
- if filterName then
- filterName = string.lower(filterName)
- else
- return false
- end
- if filterName == "group" then
- local groupId = tonumber((string.match(filterData, "^%d+")))
- if groupId then
- local plrRank = Admin.GetGroupLevel(plr.UserId, groupId)
- local requiredRank,noRank = tonumber((string.match(filterData, "^%d+:(.+)$"))), string.match(filterData,"^%d+$")
- if requiredRank then
- if requiredRank < 0 then
- return plrRank >= math.abs(requiredRank)
- else
- return plrRank == requiredRank
- end
- elseif noRank then
- return plrRank > 0
+ };
+
+ BuildingTools = {
+ Prefix = Settings.Prefix;
+ Commands = {"btools", "f3x", "buildtools", "buildingtools", "buildertools"};
+ Args = {"player"};
+ Description = "Gives the target player(s) F3X building tools.";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local F3X = Deps.Assets:FindFirstChild("F3X Deps") and (function(deps)
+ local F3X = service.New("Tool", {
+ GripPos = Vector3.new(0, 0, 0.4),
+ CanBeDropped = false,
+ ManualActivationOnly = false,
+ ToolTip = "Building Tools by F3X",
+ Name = "Building Tools"
+ }, true)
+ local clonedDeps = deps:Clone()
+
+ for _, obj in clonedDeps:GetDescendants() do
+ if obj:IsA("BaseScript") then
+ obj.Disabled = false
end
end
- return false
- elseif filterName == "item" then
- local itemId = tonumber((string.match(filterData, "^%d+")))
- return itemId and service.CheckAssetOwnership(plr, itemId)
- elseif filterName == "gamepass" then
- local gamepassId = tonumber((string.match(filterData, "^%d+")))
- return gamepassId and service.CheckPassOwnership(plr, gamepassId)
- elseif filterName == "subscription" then
- local subscriptionId = string.match(filterData, "^EXP%-%d+$")
- return subscriptionId and service.CheckSubscriptionStatus(plr, subscriptionId)
- else
- local username, userId = string.match(check, "^(.*):(.*)")
- if username and userId and (plr.UserId == tonumber(userId) or string.lower(plr.Name) == string.lower(username)) then
- return true
+ for _, obj in clonedDeps:GetChildren() do
+ obj.Parent = F3X
end
- if not banCheck and type(check) == "string" and not string.find(check, ":") then
- local cache = Functions.GetUserIdFromNameAsync(check)
- if cache and plr.UserId == cache then
- return true
- end
- end
- end
- elseif cType == "table" then
- local groupId, rank = check.Group, check.Rank
- if groupId and rank then
- local plrGroupInfo = Admin.GetPlayerGroup(plr, groupId)
- if plrGroupInfo then
- local plrRank = plrGroupInfo.Rank
- return plrRank == rank or (rank < 0 and plrRank >= math.abs(rank))
- end
- end
- end
+ clonedDeps:Destroy()
+ return F3X
+ end)(Deps.Assets:FindFirstChild("F3X Deps")) or Variables.F3XCached and Variables.F3XCached:Clone() or require(580330877)()
+ Variables.F3XCached = Variables.F3XCached or F3X:Clone()
+ service.New("StringValue", {
+ Name = `__ADONIS_VARIABLES_{Variables.CodeName}`,
+ Parent = F3X
+ })
- return check == plr
- end;
+ for _, v in service.GetPlayers(plr, args[1]) do
+ local Backpack = v:FindFirstChildOfClass("Backpack")
- LevelToList = function(lvl)
- local lvl = tonumber(lvl)
- if not lvl then return nil end
- local listName = Admin.LevelToListName(lvl)
- if listName then
- local list = Settings.Ranks[listName];
- if list then
- return list.Users, listName, list;
+ if Backpack then
+ F3X:Clone().Parent = Backpack
+ end
end
- end
- end;
- LevelToListName = function(lvl)
- if lvl > 999 then
- return "Place Owner"
- elseif lvl == 0 then
- return "Players"
+ F3X:Destroy()
end
+ };
- --// Check if this is a default rank and if the level matches the default (so stuff like [Trello] Admins doesn't appear in the command list)
- for i,v in server.Defaults.Settings.Ranks do
- local tRank = Settings.Ranks[i];
- if tRank and tRank.Level == v.Level and v.Level == lvl then
- return i
- end
- end
+ Insert = {
+ Prefix = Settings.Prefix;
+ Commands = {"insert", "ins"};
+ Args = {"id"};
+ Description = "Inserts whatever object belongs to the ID you supply, the object must be in the place owner's or Roblox's inventory";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local id = string.lower(args[1])
- for i,v in Settings.Ranks do
- if v.Level == lvl then
- return i
- end
- end
- end;
-
- UpdateCachedLevel = function(p, data)
- local data = data or Core.GetPlayer(p)
- local oLevel, oRank = data.AdminLevel, data.AdminRank
- local level, rank = Admin.GetUpdatedLevel(p, data)
-
- data.AdminLevel = level
- data.AdminRank = rank
- data.LastLevelUpdate = os.time()
-
- AddLog("Script", {
- Text = `Updating cached level for {p.Name}`;
- Desc = `Updating the cached admin level for {p.Name}`;
- Player = p;
- })
-
- if Settings.Console and (oLevel ~= level or oRank ~= rank) then
- if not Settings.Console_AdminsOnly or (Settings.Console_AdminsOnly and level > 0) then
- task.defer(Remote.RefreshGui, p, "Console")
- else
- task.defer(Remote.RemoveGui, p, "Console")
+ for i, v in Variables.InsertList do
+ if id == string.lower(v.Name)then
+ id = v.ID
+ break
+ end
end
- end
-
- return level, rank
- end;
-
- GetLevel = function(p)
- local data = Core.GetPlayer(p)
- local level = data.AdminLevel
- local rank = data.AdminRank
- local lastUpdate = data.LastLevelUpdate or 0
- local clients = Remote.Clients
- local key = tostring(p.UserId)
-
- local currentTime = os.time()
- if (not level or not lastUpdate or currentTime - lastUpdate > Admin.AdminLevelCacheTimeout) or lastUpdate > currentTime then
- local newLevel, newRank = Admin.UpdateCachedLevel(p, data)
-
- if clients[key] and level and newLevel and type(p) == "userdata" and p:IsA("Player") then
- if newLevel < level then
- Functions.Hint(`Your admin level has been reduced to {newLevel} [{newRank or "Unknown"}]`, {p})
- elseif newLevel > level then
- Functions.Hint(`Your admin level has been increased to {newLevel} [{newRank or "Unknown"}]`, {p})
+ for i, v in HTTP.Trello.InsertList do
+ if id == string.lower(v.Name) then
+ id = v.ID
+ break
end
end
- return newLevel, newRank
- end
-
- return level or 0, rank;
- end;
-
- GetUpdatedLevel = function(p, data)
- local checkTable = Admin.CheckTable
- local doCheck = Admin.DoCheck
-
- for _, admin in Admin.SpecialLevels do
- if doCheck(p, admin.Player) then
- return admin.Level, admin.Rank
+ local obj = service.Insert(tonumber(id), true)
+ if obj and plr.Character then
+ table.insert(Variables.InsertedObjects, obj)
+ obj.Parent = workspace
+ pcall(obj.MakeJoints, obj)
+ obj:PivotTo(plr.Character:GetPivot())
+ end
+ end
+ };
+
+ SaveTool = {
+ Prefix = Settings.Prefix;
+ Commands = {"addtool", "savetool", "maketool"};
+ Args = {"optional player", "optional new tool name"};
+ Description = `Saves the equipped tool to the storage so that it can be inserted using {Settings.Prefix}give`;
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ local tool = v.Character and v.Character:FindFirstChildWhichIsA("BackpackItem")
+ if tool then
+ tool = tool:Clone()
+ if args[2] then tool.Name = args[2] end
+ tool.Parent = service.UnWrap(Settings.Storage)
+ Variables.SavedTools[tool] = service.FormatPlayer(plr)
+ Functions.Hint(`Added tool: {tool.Name}`, {plr})
+ elseif not args[1] then
+ error("You must have an equipped tool to add to the storage.")
+ end
end
end
-
- local sortedRanks = {}
- for rank, data in Settings.Ranks do
- table.insert(sortedRanks, {
- Rank = rank;
- Users = data.Users;
- Level = data.Level;
- });
- end
-
- table.sort(sortedRanks, function(t1, t2)
- return t1.Level > t2.Level
- end)
-
- local highestLevel = 0
- local highestRank = nil
-
- for _, data in sortedRanks do
- local level = data.Level
- if level > highestLevel then
- for _, v in data.Users do
- if doCheck(p, v) then
- highestLevel, highestRank = level, data.Rank
- break
+ };
+
+ ClearSavedTools = {
+ Prefix = Settings.Prefix;
+ Commands = {"clraddedtools", "clearaddedtools", "clearsavedtools", "clrsavedtools"};
+ Args = {};
+ Description = `Removes any tools in the storage added using {Settings.Prefix}savetool`;
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local count = 0
+ for tool in Variables.SavedTools do
+ count += 1
+ tool:Destroy()
+ end
+ table.clear(Variables.SavedTools)
+ Functions.Hint(string.format("Cleared %d saved tool%s.", count, count == 1 and "" or "s"), {plr})
+ end
+ };
+
+ NewTeam = {
+ Prefix = Settings.Prefix;
+ Commands = {"newteam", "createteam", "maketeam"};
+ Args = {"name", "BrickColor"};
+ Filter = true;
+ Description = "Make a new team with the specified name and color";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local teamName = assert(args[1], "Missing team name (argument #1)")
+ local teamColor = Functions.ParseBrickColor(args[2])
+
+ if service.Teams:FindFirstChild(teamName) then
+ Functions.Hint(string.format("Team '%s' already exists!", teamName), {plr})
+ return;
+ end
+
+ service.New("Team", {
+ Parent = service.Teams;
+ Name = teamName;
+ TeamColor = teamColor;
+ AutoAssignable = false;
+ })
+ if Settings.CommandFeedback then
+ Functions.Hint(string.format("Created new team '%s' (%s)", teamName, teamColor.Name), {plr})
+ end
+ end
+ };
+
+ RemoveTeam = {
+ Prefix = Settings.Prefix;
+ Commands = {"removeteam", "deleteteam"};
+ Args = {"name"};
+ Description = "Remove the specified team";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.Teams:GetTeams() do
+ if string.sub(string.lower(v.Name), 1, #args[1]) == string.lower(args[1]) then
+ local ans = Remote.GetGui(plr, "YesNoPrompt", { Question = `Remove team: '{v.Name}'?` })
+
+ if ans == "Yes" then
+ v:Destroy()
+ return Functions.Hint(`Removed team {v.Name}`, {plr})
+ else
+ return Functions.Hint("Cancelled team removal operation", {plr})
end
end
end
end
+ };
- if Admin.IsPlaceOwner(p) and highestLevel < 1000 then
- return 1000, "Place Owner"
- end
-
- return highestLevel, highestRank
- end;
+ RestoreMap = {
+ Prefix = Settings.Prefix;
+ Commands = {"restoremap", "maprestore", "rmap"};
+ Args = {};
+ Description = "Restore the map to the the way it was the last time it was backed up";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local plrName = plr and service.FormatPlayer(plr) or ""
- IsPlaceOwner = function(p)
- if type(p) == "userdata" and p:IsA("Player") then
- --// These are my accounts; Lately I've been using my game dev account(698712377) more so I'm adding it so I can debug without having to sign out and back in (it's really a pain)
- --// Disable CreatorPowers in settings if you don't trust me. It's not like I lose or gain anything either way. Just re-enable it BEFORE telling me there's an issue with the script so I can go to your place and test it.
- if Settings.CreatorPowers and table.find(Variables.DeveloperWhitelist, p.UserId) then
- return true
+ if not Variables.MapBackup then
+ error("Cannot restore when there are no backup maps!", 0)
+ return
end
-
- if tonumber(CreatorId) and p.UserId == CreatorId then
- return true
+ if Variables.RestoringMap then
+ error("Map has not been backed up",0)
+ return
end
-
- if p.UserId == -1 and Variables.IsStudio then --// To account for player emulators in multi-client Studio tests
- return true
+ if Variables.BackingupMap then
+ error("Cannot restore map while backing up map is in process!", 0)
+ return
end
- end
- end;
-
- CheckAdmin = function(p)
- return Admin.GetLevel(p) > 0
- end;
- SetLevel = function(p, level, doSave, rankName)
- local current, rank = Admin.GetLevel(p)
+ Variables.RestoringMap = true
+ Functions.Hint("Restoring Map...", service.Players:GetPlayers())
+ workspace.Gravity = Variables.OriginalGravity
- if tonumber(level) then
- if current >= 1000 then
- return false
- else
- Admin.SpecialLevels[tostring(p.UserId)] = {
- Player = p.UserId,
- Level = level,
- Rank = rankName
- }
+ for _, obj in workspace:GetChildren() do
+ if obj.ClassName ~= "Terrain" and not service.Players:GetPlayerFromCharacter(obj) then
+ obj:Destroy()
+ service.RunService.Stepped:Wait()
+ end
end
- elseif level == "Reset" then
- Admin.SpecialLevels[tostring(p.UserId)] = nil
- end
- Admin.UpdateCachedLevel(p)
- end;
-
- IsTempAdmin = function(p)
- local DoCheck = Admin.DoCheck
- for i,v in Admin.TempAdmins do
- if DoCheck(p,v) then
- return true, i
+ local new = Variables.MapBackup:Clone()
+ for _, obj in new:GetChildren() do
+ obj.Parent = workspace
+ if obj:IsA("Model") then
+ obj:MakeJoints()
+ end
end
- end
- end;
+ new:Destroy()
- RemoveAdmin = function(p, temp, override)
- local current, rank = Admin.GetLevel(p)
- local listData = rank and Settings.Ranks[rank]
- local listName = listData and rank
- local list = listData and listData.Users
-
- local isTemp,tempInd = Admin.IsTempAdmin(p)
-
- if isTemp then
- temp = true
- table.remove(Admin.TempAdmins, tempInd)
- end
-
- if override then
- temp = false
- end
-
- if type(p) == "userdata" then
- Admin.SetLevel(p, 0)
- end
-
- if list then
- local DoCheck = Admin.DoCheck
- for ind,check in list do
- if DoCheck(p, check) and not (type(check) == "string" and (string.match(check,"^Group:") or string.match(check,"^Item:"))) then
- table.remove(list, ind)
-
- if not temp and Settings.SaveAdmins then
- TrackTask("Thread: RemoveAdmin", Core.DoSave, false, {
- Type = "TableRemove";
- Table = {"Settings", "Ranks", listName, "Users"};
- Value = check;
- })
- end
- end
+ local Terrain = workspace.Terrain or workspace:FindFirstChildOfClass("Terrain")
+ if Terrain and Variables.TerrainMapBackup then
+ Terrain:Clear()
+ Terrain:PasteRegion(Variables.TerrainMapBackup, Terrain.MaxExtents.Min, true)
end
- end
- Admin.UpdateCachedLevel(p)
- end;
-
- AddAdmin = function(p, level, temp)
- local current, rank = Admin.GetLevel(p)
- local list = rank and Settings.Ranks[rank]
- local levelName, newRank, newList
-
- if type(level) == "string" then
- local newRank = Settings.Ranks[level]
- levelName = newRank and level
- newList = newRank and newRank.Users
- level = (newRank and newRank.Level) or Admin.StringToComLevel(levelName) or level
- else
- local nL, nLN = Admin.LevelToList(level)
- levelName = nLN
- newRank = nLN
- newList = nL
- end
+ task.wait()
- Admin.RemoveAdmin(p, temp)
- Admin.SetLevel(p, level, nil, levelName)
+ Admin.RunCommand(`{Settings.Prefix}fixlighting`)
+ Admin.RunCommand(`{Settings.Prefix}respawn`, "all")
+ Variables.RestoringMap = false
+ Functions.Hint('Map Restore Complete.',service.Players:GetPlayers())
- if temp then
- table.insert(Admin.TempAdmins, p)
+ Logs:AddLog("Script", {
+ Text = "Map Restoration Complete",
+ Desc = `{plrName} has restored the map.`,
+ })
end
-
- if list and type(list) == "table" then
- local index,value
-
- for ind,ent in list do
- if (type(ent)=="number" or type(ent)=="string") and (ent==p.UserId or string.lower(ent)==string.lower(p.Name) or string.lower(ent)==string.lower(`{p.Name}:{p.UserId}`)) then
- index = ind
- value = ent
- end
- end
-
- if index and value then
- table.remove(list, index)
+ };
+
+ ScriptBuilder = {
+ Prefix = Settings.Prefix;
+ Commands = {"scriptbuilder", "scriptb", "sb"};
+ Args = {"create/remove/edit/close/clear/append/run/stop/list", "localscript/script", "scriptName", "data"};
+ Description = "[Deprecated] Script Builder; make a script, then edit it and chat it's code or use :sb append ";
+ AdminLevel = "Admins";
+ Hidden = true;
+ NoFilter = true;
+ CrossServerDenied = true;
+ Function = function(plr: Player, args: {string})
+ assert(Settings.CodeExecution, "CodeExecution must be enabled for this command to work")
+ local sb = Variables.ScriptBuilder[tostring(plr.UserId)]
+ if not sb then
+ sb = {
+ Script = {};
+ LocalScript = {};
+ Events = {};
+ }
+ Variables.ScriptBuilder[tostring(plr.UserId)] = sb
end
- end
- local value = `{p.Name}:{p.UserId}`
+ local action = string.lower(args[1])
+ local class = args[2] or "LocalScript"
+ local name = args[3]
- if newList then
- table.insert(newList, value)
-
- if Settings.SaveAdmins and levelName and not temp then
- TrackTask("Thread: SaveAdmin", Core.DoSave, false, {
- Type = "TableAdd";
- Table = {"Settings", "Ranks", levelName, "Users"};
- Value = value
- })
+ if string.lower(class) == "script" or string.lower(class) == "s" then
+ class = "Script"
+ elseif string.lower(class) == "clientscript" or string.lower(class) == "cs" then
+ class = "ClientScript"
+ --elseif string.lower(class) == "localscript" or string.lower(class) == "ls" then
+ -- class = "LocalScript"
+ else
+ class = "LocalScript"
end
- end
- Admin.UpdateCachedLevel(p)
- end;
-
- CheckDonor = function(p)
- local key = tostring(p.UserId)
- if Variables.CachedDonors[key] then
- return true
- else
- local pGroup = Admin.GetPlayerGroup(p, 886423)
- for _, pass in Variables.DonorPass do
- if p.Parent ~= service.Players then
- return false
- end
-
- local ran, ret
- if type(pass) == "number" then
- ran, ret = pcall(service.MarketPlace.UserOwnsGamePassAsync, service.MarketPlace, p.UserId, pass)
- elseif type(pass) == "string" and tonumber(pass) then
- ran, ret = pcall(service.MarketPlace.PlayerOwnsAsset, service.MarketPlace, p, tonumber(pass))
- end
+ if action == "create" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ local code = args[4] or " "
- if (ran and ret) or (pGroup and pGroup.Rank >= 10) then --// Complimentary donor access is given to Adonis contributors & developers.
- Variables.CachedDonors[key] = os.time()
- return true
+ if sb[class][name] then
+ pcall(function()
+ sb[class][name].Script.Disabled = true
+ sb[class][name].Script:Destroy()
+ end)
+ if sb.ChatEvent then
+ sb.ChatEvent:Disconnect()
+ end
end
- end
- end
- end;
- CheckBan = function(p)
- local doCheck = Admin.DoCheck
- local banCheck = Admin.DoBanCheck
+ local wrapped,scr = Core.NewScript(class,code,false,true)
- for ind, admin in Settings.Banned do
- if (type(admin) == "table" and ((admin.UserId and doCheck(p, admin.UserId, true)) or (admin.Name and not admin.UserId and doCheck(p, admin.Name, true)))) or doCheck(p, admin, true) then
- return true, (type(admin) == "table" and admin.Reason)
- end
- end
+ sb[class][name] = {
+ Wrapped = wrapped;
+ Script = scr;
+ }
- for ind, ban in Core.Variables.TimeBans do
- if p.UserId == ban.UserId then
- if ban.EndTime-os.time() <= 0 then
- table.remove(Core.Variables.TimeBans, ind)
+ if args[4] then
+ Functions.Hint(`Created {class} {name} and appended text`, {plr})
else
- return true, `\n {ban.Reason or "(No reason provided.)"}\n | Banned until {service.FormatTime(ban.EndTime, {WithWrittenDate = true})}`
+ Functions.Hint(`Created {class} {name}`, {plr})
end
- end
- end
-
- for ind, admin in HTTP.Trello.Bans do
- local name = type(admin) == "table" and admin.Name or admin
- if doCheck(p, name) or banCheck(p, name) then
- return true, (type(admin) == "table" and admin.Reason and service.Filter(admin.Reason, p, p))
- end
- end
-
- if HTTP.WebPanel.Bans then
- for ind, admin in HTTP.WebPanel.Bans do
- if doCheck(p, admin) or banCheck(p, admin) then
- return true, (type(admin) == "table" and admin.Reason)
+ elseif action == "edit" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ if sb[class][name] then
+ local scr = sb[class][name].Script
+ local tab = Core.GetScript(scr)
+ if scr and tab then
+ sb[class][name].Event = plr.Chatted:Connect(function(msg)
+ if string.sub(msg, 1,#(`{Settings.Prefix}sb`)) ~= `{Settings.Prefix}sb` then
+ tab.Source ..= `\n{msg}`
+ Functions.Hint(`Appended message to {class} {name}`, {plr})
+ end
+ end)
+ Functions.Hint(`Now editing {class} {name}; Chats will be appended`, {plr})
+ end
+ else
+ error(`{class} {name} not found!`)
end
- end
- end
- end;
-
- AddBan = function(p, reason, doSave, moderator, banType)
- local value = {
- Name = p.Name;
- UserId = p.UserId;
- Reason = reason;
- Moderator = if moderator then service.FormatPlayer(moderator) else "%SYSTEM%";
- BanType = banType
- }
-
- table.insert(Settings.Banned, value)
-
- if doSave then
- Core.DoSave({
- Type = "TableAdd";
- Table = "Banned";
- Value = value;
- })
-
- Core.CrossServer("RemovePlayer", p.Name, Variables.BanMessage, value.Reason or "No reason provided")
- end
-
- if type(p) ~= "table" then
- if not service.Players:FindFirstChild(p.Name) then
- Remote.Send(p,'Function','KillClient')
- else
- if p then pcall(function() p:Kick(`{Variables.BanMessage} | Reason: {value.Reason or "No reason provided"}`) end) end
- end
- end
-
- service.Events.PlayerBanned:Fire(p, reason, doSave, moderator)
- end;
-
- AddTimeBan = function(p : Player | {[string]: any}, duration: number, reason: string, moderator: Player?)
- local value = {
- Name = p.Name;
- UserId = p.UserId;
- EndTime = os.time() + tonumber(duration);
- Reason = reason;
- Moderator = if moderator then service.FormatPlayer(moderator) else "%SYSTEM%";
- }
-
- table.insert(Core.Variables.TimeBans, value)
-
- Core.DoSave({
- Type = "TableAdd";
- Table = {"Core", "Variables", "TimeBans"};
- Value = value;
- })
-
- Core.CrossServer("RemovePlayer", p.Name, Variables.BanMessage, value.Reason or "No reason provided")
-
- if type(p) ~= "table" then
- if not service.Players:FindFirstChild(p.Name) then
- Remote.Send(p, "Function", "KillClient")
- else
- if p then pcall(function() p:Kick(`{Variables.BanMessage} | Reason: {value.Reason or "No reason provided"}`) end) end
- end
- end
-
- service.Events.PlayerBanned:Fire(p, reason, true, moderator)
- end,
-
- DoBanCheck = function(name: string | number | Instance, check: string | {[string]: any})
- local id = type(name) == "number" and name
-
- if type(name) == "userdata" and name:IsA("Player") then
- id = name.UserId
- name = name.Name
- end
-
- if type(check) == "table" then
- if type(name) == "string" and check.Name and string.lower(check.Name) == string.lower(name) then
- return true
- elseif id and check.UserId and check.UserId == id then
- return true
- end
- elseif type(check) == "string" then
- local cName, cId = string.match(check, "(.*):(.*)")
- if not cName and cId then cName = check end
-
- if cName then
- if string.lower(cName) == string.lower(name) then
- return true
- elseif id and cId and id == tonumber(cId) then
- return true
+ elseif action == "close" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ local scr = sb[class][name].Script
+ local tab = Core.GetScript(scr)
+ if sb[class][name] then
+ if sb[class][name].Event then
+ sb[class][name].Event:Disconnect()
+ sb[class][name].Event = nil
+ Functions.Hint(`No longer editing {class} {name}`, {plr})
+ end
+ else
+ error(`{class} {name} not found!`)
end
- else
- return string.lower(tostring(check)) == string.lower(tostring(name))
- end
- end
-
- return false
- end;
-
- RemoveBan = function(name, doSave)
- local ret
- for i,v in Settings.Banned do
- if Admin.DoBanCheck(name, v) then
- ret = table.remove(Settings.Banned, i)
- if doSave then
- Core.DoSave({
- Type = "TableRemove";
- Table = "Banned";
- Value = ret;
- LaxCheck = true;
- })
+ elseif action == "clear" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ local scr = sb[class][name].Script
+ local tab = Core.GetScript(scr)
+ if scr and tab then
+ tab.Source = " "
+ Functions.Hint(`Cleared {class} {name}`, {plr})
+ else
+ error(`{class} {name} not found!`)
end
- end
- end
- return ret
- end;
-
- RemoveTimeBan = function(name : string | number | Instance)
- local ret
- for i,v in Core.Variables.TimeBans do
- if Admin.DoBanCheck(name, v) then
- table.remove(Core.Variables.TimeBans, i)
- ret = v
- Core.DoSave({
- Type = "TableRemove";
- Table = {"Core", "Variables", "TimeBans"};
- Value = v;
- LaxCheck = true;
- })
- end
- end
- return ret
- end,
-
- RunCommand = function(coma: string, ...)
- local _, com = Admin.GetCommand(coma)
- if com then
- local cmdArgs = com.Args or com.Arguments
- local args = Admin.GetArgs(coma, #cmdArgs, ...)
-
- TrackTask(`Command: {coma}`, com.Function, function(err)
- warn(`Encountered an error while running a command: {coma}\n{err}\n{debug.traceback()}`)
- end, false, args)
- end
- end;
-
- RunCommandAsPlayer = function(coma, plr, ...)
- local ind, com = Admin.GetCommand(coma)
- if com then
- local adminLvl = Admin.GetLevel(plr)
-
- local cmdArgs = com.Args or com.Arguments
- local args = Admin.GetArgs(coma, #cmdArgs, ...)
- local ran, error = TrackTask(
- `{plr.Name}: {coma}`,
- com.Function,
- function(err)
- err = string.match(err, ":(.+)$") or "Unknown error"
- Remote.MakeGui(plr, "Output", {
- Title = "Error",
- Message = error,
- Color = Color3.new(1, 0, 0),
- })
- warn(`Encountered an error while running a command: {coma}\n{err}\n{debug.traceback()}`)
- end,
- plr,
- args,
- {
- PlayerData = {
- Player = plr,
- Level = adminLvl,
- isDonor = ((Settings.DonorCommands or com.AllowDonors) and Admin.CheckDonor(plr)) or false,
- },
- }
- )
- end
- end;
-
- RunCommandAsNonAdmin = function(coma, plr, ...)
- local ind, com = Admin.GetCommand(coma)
- if com and com.AdminLevel == 0 then
- local cmdArgs = com.Args or com.Arguments
- local args = Admin.GetArgs(coma, #cmdArgs, ...)
- local _, error = TrackTask(
- `{plr.Name}: {coma}`,
- com.Function,
- function(err)
- err = string.match(err, ":(.+)$") or "Unknown error"
- Remote.MakeGui(plr, "Output", {
- Title = "",
- Message = error,
- Color = Color3.new(1, 0, 0),
- })
- warn(`Encountered an error while running a command: {coma}\n{err}\n{debug.traceback()}`)
- end,
- plr,
- args,
- { PlayerData = {
- Player = plr,
- Level = 0,
- isDonor = false,
- } }
- )
- end
- end;
-
- CacheCommands = function()
- local tempTable = {}
- local tempPrefix = {}
- for ind, data in Commands do
- if type(data) == "table" then
- for i,cmd in data.Commands do
- if type(data.Prefix) ~= "table" and data.Prefix == "" then Admin.BlankPrefix = true end
- if type(data.Prefix) == "table" then
- for _,p in data.Prefix do
- tempPrefix[p] = true
- tempTable[string.lower(p..cmd)] = ind
- end
- else
- tempPrefix[data.Prefix] = true
- tempTable[string.lower(data.Prefix..cmd)] = ind
+ elseif action == "remove" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ if sb[class][name] then
+ pcall(function()
+ sb[class][name].Script.Disabled = true
+ sb[class][name].Script:Destroy()
+ end)
+ if sb.ChatEvent then
+ sb.ChatEvent:Disconnect()
+ sb.ChatEvent = nil
end
+ sb[class][name] = nil
+ else
+ error(`{class} {name} not found!`)
end
- end
- end
-
- Admin.PrefixCache = tempPrefix
- Admin.CommandCache = tempTable
-
- if Variables.ChatCreateRobloxCommands then
- -- // Support for commands to be ran via TextChat
- task.spawn(function()
- local container = service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService and service.TextChatService:WaitForChild("TextChatCommands", 9e9)
-
- if container then
- for _, v in container:GetChildren() do
- if string.sub(v.Name, 1, 7) == "Adonis_" then
- v:Destroy()
- end
+ elseif action == "append" then
+ assert(args[1] and args[2] and args[3] and args[4], "Missing arguments")
+ if sb[class][name] then
+ local scr = sb[class][name].Script
+ local tab = Core.GetScript(scr)
+ if scr and tab then
+ tab.Source ..= `\n{args[4]}`
+ Functions.Hint(`Appended message to {class} {name}`, {plr})
end
-
- local blacklistedCommands = {}
-
- for _, v in container:GetDescendants() do
- if v:IsA("TextChatCommand") then
- blacklistedCommands[v.PrimaryAlias] = true
- blacklistedCommands[v.SecondaryAlias] = true
- end
+ else
+ error(`{class} {name} not found!`)
+ end
+ elseif action == "run" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ if sb[class][name] then
+ if class == "LocalScript" then
+ sb[class][name].Script.Parent = plr:FindFirstChildOfClass("Backpack")
+ else
+ sb[class][name].Script.Parent = service.ServerScriptService
end
+ sb[class][name].Script.Disabled = true
+ task.wait(0.03)
+ sb[class][name].Script.Disabled = false
+ Functions.Hint(`Running {class} {name}`, {plr})
+ else
+ error(`{class} {name} not found!`)
+ end
+ elseif action == "stop" then
+ assert(args[1] and args[2] and args[3], "Missing arguments")
+ if sb[class][name] then
+ sb[class][name].Script.Disabled = true
+ Functions.Hint(`Stopped {class} {name}`, {plr})
+ else
+ error(`{class} {name} not found!`)
+ end
+ elseif action == "list" then
+ local tab = {}
+ for i, v in sb.Script do
+ table.insert(tab, {Text = `Script: {i}`, Desc = `Running: {v.Script.Disabled}`})
+ end
- for name, data in Commands do
- local command1, command2 = nil, nil
+ for i, v in sb.LocalScript do
+ table.insert(tab, {Text = `LocalScript: {i}`, Desc = `Running: {v.Script.Disabled}`})
+ end
- if type(data) ~= "table" or data.Hidden then
- continue
- end
+ Remote.MakeGui(plr, "List", {Title = "SB Scripts", Table = tab})
+ end
+ end
+ };
+
+ MakeScript = {
+ Prefix = Settings.Prefix;
+ Commands = {"s", "ss", "serverscript", "sscript", "script", "makescript"};
+ Args = {"code"};
+ Description = "Executes the given Lua code on the server";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ CrossServerDenied = true;
+ Function = function(plr: Player, args: {string})
+ assert(Settings.CodeExecution, "CodeExecution config must be enabled for this command to work")
+ local bytecode = Core.Bytecode(assert(args[1], "Missing Script code (argument #2)"))
+ assert(string.find(bytecode, "\27Lua"), `Script unable to be created: {string.gsub(bytecode, "Loadstring%.LuaX:%d+:", "")}`)
+
+ local cl = Core.NewScript("Script", args[1], true)
+ cl.Name = "[Adonis] Script"
+ cl.Parent = service.ServerScriptService
+ task.wait()
+ cl.Disabled = false
+ Functions.Hint("Ran Script", {plr})
+ end
+ };
+
+ MakeLocalScript = {
+ Prefix = Settings.Prefix;
+ Commands = {"ls", "localscript", "lscript"};
+ Args = {"code"};
+ Description = "Executes the given code on your client";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ Function = function(plr: Player, args: {string})
+ Commands.LoadLocalScript.Function(plr, {`@{plr.Name}`, args[1]})
+ end
+ };
+
+ LoadLocalScript = {
+ Prefix = Settings.Prefix;
+ Commands = {"cs", "cscript", "clientscript"};
+ Args = {"player", "code"};
+ Description = "Executes the given code on the client of the target player(s)";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ Function = function(plr: Player, args: {string})
+ assert(args[2], "Missing LocalScript code (argument #2)")
+
+ local bytecode = Core.Bytecode(args[2])
+ assert(string.find(bytecode, "\27Lua"), `LocalScript unable to be created: {string.gsub(bytecode, "Loadstring%.LuaX:%d+:", "")}`)
+
+ local new = Core.NewScript("LocalScript", `script.Parent = game:GetService('Players').LocalPlayer.PlayerScripts; {args[2]}`, true)
+ local function cloneScript(targetPlayer)
+ local playerName = if targetPlayer == plr then "your client" else service.FormatPlayer(targetPlayer)
+
+ local backpack = targetPlayer:FindFirstChildOfClass("Backpack")
+ if not backpack then
+ Functions.Hint(`Couldn't run LocalScript on {playerName} (Backpack missing?)`, {plr})
+ return
+ end
- for _, v in data.Commands do
- if type(data.Prefix) == "table" then
- for _, p in data.Prefix do
- if not blacklistedCommands["/"..p..v] then
- if not command1 then
- command1 = "/"..p..v
- else
- command2 = "/"..p..v
- end
- end
- end
- else
- if not blacklistedCommands["/"..data.Prefix..v] then
- if not command1 then
- command1 = "/"..data.Prefix..v
- else
- command2 = "/"..data.Prefix..v
- end
- end
+ local cl = new:Clone()
+ cl.Name = "[Adonis] LocalScript"
+ cl.Disabled = true
+ cl.Parent = targetPlayer:FindFirstChildOfClass("Backpack")
+ task.wait(.1)
+ cl.Disabled = false
+ Functions.Hint(`Ran LocalScript on {playerName}`, {plr})
+ end
+
+ for i, v in service.GetPlayers(plr, args[1]) do
+ task.spawn(cloneScript, v)
+ end
+ end
+ };
+
+ CreateStarterScript = {
+ Prefix = Settings.Prefix;
+ Commands = {"starterscript", "clientstarterscript", "starterclientscript", "createstarterscript"};
+ Args = {"name", "code"};
+ Description = "Executes the given code on everyone's client upon respawn";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ Function = function(plr: Player, args: {string})
+ assert(args[1], "Missing starter script name (argument #1)")
+ assert(args[2], "Missing LocalScript code (argument #2)")
+
+ local bytecode = Core.Bytecode(args[2])
+ assert(string.find(bytecode, "\27Lua"), `LocalScript unable to be created: {string.gsub(bytecode, "Loadstring%.LuaX:%d+:", "")}`)
+
+ local new = Core.NewScript("LocalScript", args[2], true)
+ new.Name = `[Adonis] {args[1]}`
+ new.Parent = service.StarterGui
+ new.Disabled = false
+ Functions.Hint("Created starter script", {plr})
+ end
+ };
+
+
+ StarterScripts = {
+ Prefix = Settings.Prefix;
+ Commands = {"starterscripts", "clientstarterscripts", "starterclientscripts"};
+ Args = {};
+ Description = "Show existing starterscripts";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ Function = function(plr: Player, args: {string})
+ local result = {}
+
+ for _,v : Instance in service.StarterGui:GetChildren() do
+ if v:IsA("LocalScript") and v.Name:find("[Adonis]") then
+ table.insert(result, (v.Name:gsub("%[Adonis%] ", "")))
+ end
+ end
- end
- end
+ Remote.MakeGui(plr,"List",{
+ Title = "Starter Scripts";
+ Tab = result;
+ })
+ end
+ };
- if command1 then
- local command = service.New("TextChatCommand")
- command.Name = "Adonis_"..name
- command.PrimaryAlias = command1
- command.SecondaryAlias = command2 or ""
- command.Archivable = false
- command:SetAttribute("AdminLevel", tonumber(data.AdminLevel) or data.AdminLevel or nil)
- command.Parent = container
- command.Triggered:Connect(function(textSource, text)
- local player = service.Players:GetPlayerByUserId(textSource.UserId)
+ RemoveStarterScript = {
+ Prefix = Settings.Prefix;
+ Commands = {"removestarterscript", "removeclientstarterscripts", "removestarterclientscripts", "unstarterscript"};
+ Args = {"name"};
+ Description = "Remove a starterscript";
+ AdminLevel = "Admins";
+ NoFilter = true;
+ Function = function(plr: Player, args: {string})
+ assert(args[1], "No starterscript name provided!")
- if player then
- Process.Command(player, string.sub(text, 2))
- end
- end)
- end
+ for _,v : Instance in service.StarterGui:GetChildren() do
+ if v:IsA("LocalScript") and v.Name:find("[Adonis]") then
+ if v.Name:gsub("%[Adonis%] ", ""):lower() == args[1]:lower() or args[1]:lower() == "all" then
+ service.Delete(v)
+ Functions.Hint("Removed starter script "..v.Name, {plr})
end
end
- end)
+ end
end
- end;
-
- GetCommand = function(Command)
- if Admin.PrefixCache[string.sub(Command, 1, 1)] or Admin.BlankPrefix then
- local matched
- matched = if string.find(Command, Settings.SplitKey) then
- string.match(Command, `^(%S+){Settings.SplitKey}`)
- else string.match(Command, "^(%S+)")
-
- if matched then
- local found = Admin.CommandCache[string.lower(matched)]
- if found then
- local real = Commands[found]
- if real then
- return found,real,matched
+ };
+
+ Note = {
+ Prefix = Settings.Prefix;
+ Commands = {"note", "writenote", "makenote"};
+ Args = {"player", "note"};
+ Filter = true;
+ Description = "Makes a note on the target player(s) that says ";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[2], "Missing note (argument #2)")
+ for _, v in service.GetPlayers(plr, args[1]) do
+ local PlayerData = Core.GetPlayer(v)
+ if not PlayerData.AdminNotes then PlayerData.AdminNotes = {} end
+ table.insert(PlayerData.AdminNotes, args[2])
+ Functions.Hint(`Added {service.FormatPlayer(v)} Note {args[2]}`, {plr})
+ Core.SavePlayer(v, PlayerData)
+ end
+ end
+ };
+
+ DeleteNote = {
+ Prefix = Settings.Prefix;
+ Commands = {"removenote", "remnote", "deletenote", "clearnote"};
+ Args = {"player", "note (specify 'all' to delete all notes)"};
+ Description = "Removes a note on the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[2], "Missing note (argument #2)")
+ for _, v in service.GetPlayers(plr, args[1]) do
+ local PlayerData = Core.GetPlayer(v)
+ if PlayerData.AdminNotes then
+ if string.lower(args[2]) == "all" then
+ PlayerData.AdminNotes = {}
+ else
+ for k, m in PlayerData.AdminNotes do
+ if string.sub(string.lower(m), 1, #args[2]) == string.lower(args[2]) then
+ Functions.Hint(`Removed {service.FormatPlayer(v)} Note {m}`, {plr})
+ table.remove(PlayerData.AdminNotes, k)
+ end
+ end
end
+ Core.SavePlayer(v, PlayerData)
end
end
end
- end;
-
- FindCommands = function(Command)
- local prefixChar = string.sub(Command, 1, 1)
- local checkPrefix = Admin.PrefixCache[prefixChar] and prefixChar
- local matched
-
- if checkPrefix then
- Command = string.sub(Command, 2)
- end
-
- if string.find(Command, Settings.SplitKey) then
- matched = string.match(Command, `^(%S+){Settings.SplitKey}`)
- else
- matched = string.match(Command, "^(%S+)")
- end
-
- if matched then
- local foundCmds = {}
- matched = string.lower(matched)
-
- for ind,cmd in Commands do
- if type(cmd) == "table" and ((checkPrefix and prefixChar == cmd.Prefix) or not checkPrefix) then
- for _, alias in cmd.Commands do
- if string.lower(alias) == matched then
- foundCmds[ind] = cmd
- break
- end
- end
+ };
+
+ ShowNotes = {
+ Prefix = Settings.Prefix;
+ Commands = {"notes", "viewnotes"};
+ Args = {"player"};
+ Description = "Views notes on the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ local PlayerData = Core.GetPlayer(v)
+ local notes = PlayerData.AdminNotes
+ if not notes then
+ Functions.Hint(`No notes found on {service.FormatPlayer(v)}`, {plr})
+ continue
end
+ Remote.MakeGui(plr, "List", {Title = service.FormatPlayer(v), Table = notes})
+ end
+ end
+ };
+
+ LoopKill = {
+ Prefix = Settings.Prefix;
+ Commands = {"loopkill"};
+ Args = {"player", "num (optional)"};
+ Description = "Repeatedly kills the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local num = tonumber(args[2]) or 9999
+
+ for _, v in service.GetPlayers(plr, args[1]) do
+ service.StopLoop(`{v.UserId}LOOPKILL`)
+ local count = 0
+ Routine(service.StartLoop, `{v.UserId}LOOPKILL`, 3, function()
+ local hum = v.Character and v.Character:FindFirstChildOfClass("Humanoid")
+ if hum and hum.Health > 0 then
+ hum.Health = 0
+ count += 1
+ end
+ if count == num then
+ service.StopLoop(`{v.UserId}LOOPKILL`)
+ end
+ end)
end
-
- return foundCmds
end
- end;
+ };
- SetPermission = function(comString, newLevel)
- local cmds = Admin.FindCommands(comString)
- if cmds then
- for ind, cmd in cmds do
- cmd.AdminLevel = newLevel
+ UnLoopKill = {
+ Prefix = Settings.Prefix;
+ Commands = {"unloopkill"};
+ Args = {"player"};
+ Description = "Un-Loop Kill";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ service.StopLoop(`{v.UserId}LOOPKILL`)
end
end
- end;
+ };
- FormatCommandArguments = function(command)
- local text = table.create(#command.Args)
- for i, arg in command.Args do
- text[i] = `<{arg}>`
- end
- return table.concat(text, Settings.SplitKey)
- end;
-
- FormatCommand = function(command, cmdn)
- return table.concat({
- (if type(command.Prefix) == "table" then command.Prefix[1] else command.Prefix or ""),
- tostring(command.Commands[cmdn or 1]),
- #command.Args > 0 and Settings.SplitKey or "",
- #command.Args > 0 and Admin.FormatCommandArguments(command) or ""
- })
- end;
-
- FormatCommandAdminLevel = function(command)
- local levels = if type(command.AdminLevel) == "table"
- then table.clone(command.AdminLevel)
- else {command.AdminLevel}
- local permissionDesc = table.create(#levels)
-
- for i, lvl in levels do
- if type(lvl) == "number" then
- local list, name, data = Admin.LevelToList(lvl)
- permissionDesc[i] = `{name or "No Rank"}; Level {lvl}`
- elseif type(lvl) == "string" then
- local numLvl = Admin.StringToComLevel(lvl)
- permissionDesc[i] = `{lvl}; Level {numLvl or "Unknown"}`
- else
- permissionDesc[i] = "N/A"
+ Lag = {
+ Prefix = Settings.Prefix;
+ Commands = {"lag", "fpslag"};
+ Args = {"player"};
+ Description = "Makes the target player(s)'s FPS drop";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ if Admin.CheckAuthority(plr, v, "lag") then
+ Remote.Send(v, "Function", "SetFPS", 5.6)
+ end
end
end
+ };
- return table.concat(permissionDesc, ", ")
- end;
-
- CheckTable = function(p, tab)
- local doCheck = Admin.DoCheck
- for i,v in tab do
- if doCheck(p, v) then
- return true
+ UnLag = {
+ Prefix = Settings.Prefix;
+ Commands = {"unlag", "unfpslag"};
+ Args = {"player"};
+ Description = "Un-Lag";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ Remote.Send(v, "Function", "RestoreFPS")
end
end
- end;
-
- --// Make it so you can't accidentally overwrite certain existing commands... resulting in being unable to add/edit/remove aliases (and other stuff)
- CheckAliasBlacklist = function(alias)
- local playerPrefix = Settings.PlayerPrefix;
- local prefix = Settings.Prefix
- local blacklist = {
- [`{playerPrefix}alias`] = true;
- [`{playerPrefix}newalias`] = true;
- [`{playerPrefix}removealias`] = true;
- [`{playerPrefix}client`] = true;
- [`{playerPrefix}userpanel`] = true;
- [":adonissettings"] = true;
- }
- --return Admin.CommandCache[alias:lower()] --// Alternatively, we could make it so you can't overwrite ANY existing commands...
- return blacklist[alias];
- end;
-
- GetArgs = function(msg, num, ...)
- local newArgs = table.pack(...)
- local args = Functions.Split(string.match(msg, `^.-{Settings.SplitKey}(.+)`) or "", Settings.SplitKey, num) or table.create(newArgs.n)
- for i = 1, newArgs.n do
- table.insert(args, newArgs[i])
- end
- return args
- end;
-
- AliasFormat = function(aliases, msg)
- local foundPlayerAlias = false --// Check if there's a player-defined alias first then otherwise check settings aliases
+ };
- local CheckAliasBlacklist, SanitizePattern = Admin.CheckAliasBlacklist, service.SanitizePattern
-
- if aliases then
- for alias, cmd in aliases do
- local tAlias = stripArgPlaceholders(alias)
- if not Admin.CheckAliasBlacklist(tAlias) then
- local escAlias = SanitizePattern(tAlias)
- --// Ignore any "empty" aliases, aka aliases that would basically match any command
- if string.len(Functions.Trim(escAlias)) == 0 then
- continue
- end
- local trimmedMsg = Functions.Trim(msg)
- --// Use Adonis split to better support various characters that string.split can't handle properly
- local aliasCharacters = Functions.Split(trimmedMsg, Settings.SplitKey)
- --// Matching an alias can result in an infinite loop like running !fire with the alias !f, it will infinitely run the !f alias
- --// If you have an alias !f
- if escAlias == aliasCharacters[1] or string.match(trimmedMsg, `%s{escAlias}`) then
- msg = FormatAliasArgs(alias, cmd, msg)
- end
+ Crash = {
+ Prefix = Settings.Prefix;
+ Commands = {"crash"};
+ Args = {"player"};
+ Description = "Crashes the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if Admin.CheckAuthority(plr, v, "crash") then
+ Remote.Send(v, "Function", "Crash")
end
end
end
+ };
- for alias, cmd in Variables.Aliases do
- local tAlias = stripArgPlaceholders(alias)
- if not CheckAliasBlacklist(tAlias) then
- local escAlias = SanitizePattern(tAlias)
- if string.match(msg, `^{escAlias}`) or string.match(msg, `%s{escAlias}`) then
- msg = FormatAliasArgs(alias, cmd, msg)
+ HardCrash = {
+ Prefix = Settings.Prefix;
+ Commands = {"hardcrash"};
+ Args = {"player"};
+ Description = "Hard-crashes the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if Admin.CheckAuthority(plr, v, "hard-crash") then
+ Remote.Send(v, "Function", "HardCrash")
end
end
end
+ };
- return msg
- end;
-
- StringToComLevel = function(str)
- local strType = type(str)
- if strType == "string" and string.lower(str) == "players" then
- return 0
- end
- if strType == "number" then
- return str
- end
-
- local lvl = Settings.Ranks[str]
- return (lvl and lvl.Level) or tonumber(str)
- end;
-
- CheckComLevel = function(plrAdminLevel, comLevel)
- if type(comLevel) == "string" then
- comLevel = Admin.StringToComLevel(comLevel)
- elseif type(comLevel) == "table" then
- for _, level in comLevel do
- if Admin.CheckComLevel(plrAdminLevel, level) then
- return true
+ RAMCrash = {
+ Prefix = Settings.Prefix;
+ Commands = {"ramcrash", "memcrash"};
+ Args = {"player"};
+ Description = "RAM-crashes the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if Admin.CheckAuthority(plr, v, "RAM-crash") then
+ Remote.Send(v, "Function", "RAMCrash")
end
end
- return false
end
+ };
- return type(comLevel) == "number" and plrAdminLevel >= comLevel
- end;
-
- IsBlacklisted = function(p)
- local CheckTable = Admin.CheckTable
- for _, list in Variables.Blacklist.Lists do
- if CheckTable(p, list) then
- return true
+ GPUCrash = {
+ Prefix = Settings.Prefix;
+ Commands = {"gpucrash"};
+ Args = {"player"};
+ Description = "GPU crashes the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if Admin.CheckAuthority(plr, v, "GPU-crash") then
+ Remote.Send(v, "Function", "GPUCrash")
+ end
end
end
- end;
+ };
- CheckPermission = function(pDat, cmd, ignoreCooldown, opts)
- opts = opts or {}
+ CustomKick = {
+ Prefix = Settings.Prefix;
+ Commands = {"ckick", "customkick", "customcrash"};
+ Args = {"player", "title", "message"};
+ Description = "Disconnects (crashes) the target player with a custom Roblox dialog";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[3], "Argument(s) missing or nil")
- local adminLevel = pDat.Level
- local comLevel = cmd.AdminLevel
+ local title = service.BroadcastFilter(args[2], plr)
+ assert(title == args[2], "Title was filtered: "..title)
- if cmd.Disabled then
- return false, "This command has been disabled."
- end
-
- if Variables.IsStudio and cmd.NoStudio then
- return false, "This command cannot be used in Roblox Studio."
- end
+ local msg = service.BroadcastFilter(args[3], plr)
+ assert(msg == args[3], "Message was filtered: "..msg)
- if opts.CrossServer and cmd.CrossServerDenied then -- Ignore when disabled then
- return false, "This command may not be run across servers (cross-server-blacklisted)."
- end
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if not Admin.CheckAuthority(plr, v, "custom-kick") then
+ continue
+ end
- if cmd.CrossServer and not Settings.CrossServerCommands then
- return false, "This command has been disabled due to CrossServerCommands being disabled"
- end
+ local plrgui = v:FindFirstChildOfClass("PlayerGui")
+ if not plrgui then
+ Remote.MakeGui(plr, "Output", {
+ Message = `Failed to custom-kick {service.FormatPlayer(v)} (PlayerGui not found)`;
+ })
+ continue
+ end
- if Admin.IsPlaceOwner(pDat.Player) or adminLevel >= Settings.Ranks.Creators.Level then
- return true, nil
- end
+ local promptGui = Deps.Assets.RobloxPromptGui:Clone()
+ promptGui.promptOverlay.ErrorPrompt.TitleFrame.ErrorTitle.Text = title
+ promptGui.promptOverlay.ErrorPrompt.MessageArea.ErrorFrame.ErrorMessage.Text = msg
+ promptGui.Parent = plrgui
- if Admin.IsBlacklisted(pDat.Player) then
- return false, "You are blacklisted from running commands."
- end
+ Remote.Send(v, "Function", "CustomKick")
+ task.delay(5, function()
+ if v.Parent == service.Players then
+ -- make sure they're really kicked
+ v:Kick("Unexpected Error")
+ end
+ end)
+ Functions.Hint(`Custom-kicking {service.FormatPlayer(v)}`, {plr})
+ end
+ end
+ };
+
+ Shutdown = {
+ Prefix = Settings.Prefix;
+ Commands = {"shutdown"};
+ Args = {"reason"};
+ Description = "Shuts the server down";
+ Filter = true;
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ if Core.DataStore then
+ Core.UpdateData("ShutdownLogs", function(logs)
+ table.insert(logs, 1, {
+ User = plr and plr.Name or "[Server]",
+ Time = os.time(),
+ Reason = args[1] or "N/A"
+ })
- if (comLevel == 0 or comLevel == "Players") and adminLevel <= 0 and not Settings.PlayerCommands then
- return false, "Player commands are disabled in this game."
- end
+ local nlogs = #logs
+ if nlogs > Logs.OldCommandLogsLimit then
+ table.remove(logs, nlogs)
+ end
- if cmd.Fun and not Settings.FunCommands then
- return false, "Fun commands are disabled in this game."
- end
+ return logs
+ end)
+ end
- if opts.Chat and cmd.Chattable == false then
- return false, "This command is not permitted as chat message (non-chattable command)."
+ Functions.Shutdown(args[1])
end
+ };
- local permAllowed = (cmd.Donors and (pDat.isDonor and (Settings.DonorCommands or cmd.AllowDonors))) or (cmd.Agent and HTTP.Trello.CheckAgent) and HTTP.Trello.CheckAgent(pDat.Player)
- or Admin.CheckComLevel(adminLevel, comLevel)
-
- if permAllowed and not ignoreCooldown and type(pDat.Player) == "userdata" then
- local playerCooldown = tonumber(cmd.PlayerCooldown)
- local serverCooldown = tonumber(cmd.ServerCooldown)
- local crossCooldown = tonumber(cmd.CrossCooldown)
-
- local cmdFullName = cmd._fullName or (function()
- local aliases = cmd.Aliases or cmd.Commands or {}
- cmd._fullName = `{cmd.Prefix}{aliases[1] or `{service.HttpService:GenerateGUID(false)}-RANDOM_COMMAND`}`
- return cmd._fullName
- end)()
-
- local pCooldown_Cache = cmd._playerCooldownCache or (function()
- local tab = {}
- cmd._playerCooldownCache = tab
- return tab
- end)()
-
- local sCooldown_Cache = cmd._serverCooldownCache or (function()
- local tab = {}
- cmd._serverCooldownCache = tab
- return tab
- end)()
-
- local crossCooldown_Cache = cmd._crossCooldownCache or (function()
- local tab = {}
- cmd._crossCooldownCache = tab
- return tab
- end)()
-
- local cooldownIndex = tostring(pDat.Player.UserId)
- local pCooldown_playerCache = pCooldown_Cache[cooldownIndex]
- local sCooldown_playerCache = sCooldown_Cache[cooldownIndex]
-
- if playerCooldown and pCooldown_playerCache then
- local secsTillPass = os.clock() - pCooldown_playerCache
- if secsTillPass < playerCooldown then
- return false, string.format("[PlayerCooldown] You must wait %.0f seconds to run the command.", playerCooldown - secsTillPass)
- end
- end
-
- if serverCooldown and sCooldown_playerCache then
- local secsTillPass = os.clock() - sCooldown_playerCache
- if secsTillPass < serverCooldown then
- return false, string.format("[ServerCooldown] You must wait %.0f seconds to run the command.", serverCooldown - secsTillPass)
+ ServerBan = {
+ Prefix = Settings.Prefix;
+ Commands = {"serverban", "ban"};
+ Args = {"player/user", "reason"};
+ Description = "Bans the target player(s) from the server";
+ AdminLevel = "Admins";
+ Filter = true;
+ Function = function(plr: Player, args: {string}, data: {any})
+ local reason = args[2] or "No reason provided"
+ for _, v in service.GetPlayers(plr, args[1], {
+ IsKicking = true;
+ NoFakePlayer = false;
+ })
+ do
+ if Admin.CheckAuthority(plr, v, "server-ban", false) then
+ Admin.AddBan(v, reason, false, plr, "Server")
+ Functions.LogAdminAction(plr, "Server Ban", v.Name, `Reason: {reason}`)
+ Functions.Hint(`Server-banned {service.FormatPlayer(v, true)}`, {plr})
end
end
+ end
+ };
- if crossCooldown then
- local playerData = Core.GetPlayer(pDat.Player) or {}
- local crossCooldown_Cache = playerData._crossCooldownCache or (function()
- local tab = {}
- playerData._crossCooldownCache = tab
- return tab
- end)()
- local crossCooldown_playerCache = crossCooldown_Cache[cmdFullName]
-
- if crossCooldown_playerCache then
- local secsTillPass = os.clock() - crossCooldown_playerCache
- if secsTillPass < crossCooldown then
- return false, string.format("[CrossServerCooldown] You must wait %.0f seconds to run the command.", crossCooldown - secsTillPass)
- end
+ UnBan = {
+ Prefix = Settings.Prefix;
+ Commands = {"unserverban", "unban"};
+ Args = {"user"};
+ Description = "Unbans the target user(s) from the server";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, assert(args[1], "Missing user (argument #1)"), {
+ UseFakePlayer = true;
+ })
+ do
+ if Admin.RemoveBan(v) then
+ Functions.LogAdminAction(plr, "Unban", v.Name, "User has been unbanned.")
+ Functions.Hint(`{service.FormatPlayer(v, true)} has been unbanned`, {plr})
+ else
+ Functions.Hint(`{service.FormatPlayer(v, true)} is not currently banned`, {plr})
end
end
end
-
- return permAllowed, nil
- end;
-
- UpdateCooldown = function(pDat, cmd)
- if pDat.Player == "SYSTEM" then return end
- local playerCooldown = tonumber(cmd.PlayerCooldown)
- local serverCooldown = tonumber(cmd.ServerCooldown)
- local crossCooldown = tonumber(cmd.CrossCooldown)
-
- local cmdFullName = cmd._fullName or (function()
- local aliases = cmd.Aliases or cmd.Commands or {}
- cmd._fullName = `{cmd.Prefix}{aliases[1] or `{service.HttpService:GenerateGUID(false)}-RANDOM_COMMAND`}`
- return cmd._fullName
- end)()
-
- local pCooldown_Cache = cmd._playerCooldownCache or (function()
- local tab = {}
- cmd._playerCooldownCache = tab
- return tab
- end)()
-
- local sCooldown_Cache = cmd._serverCooldownCache or (function()
- local tab = {}
- cmd._serverCooldownCache = tab
- return tab
- end)()
-
- local crossCooldown_Cache = cmd._crossCooldownCache or (function()
- local tab = {}
- cmd._crossCooldownCache = tab
- return tab
- end)()
-
- local cooldownIndex = tostring(pDat.Player.UserId)
- local pCooldown_playerCache = pCooldown_Cache[cooldownIndex]
- local sCooldown_playerCache = sCooldown_Cache[cooldownIndex]
- local lastUsed = os.clock()
-
- if playerCooldown then
- pCooldown_Cache[cooldownIndex] = lastUsed
- end
-
- if serverCooldown then
- sCooldown_Cache[cooldownIndex] = lastUsed
- end
-
- --// Cross cooldown
- do
- local playerData = Core.GetPlayer(pDat.Player)
- local crossCooldown_Cache = playerData._crossCooldownCache or {}
- local crossCooldown_playerCache = crossCooldown_Cache[cmdFullName]
-
- if not crossCooldown and crossCooldown_playerCache then
- crossCooldown_playerCache[cmdFullName] = nil
- elseif crossCooldown then
- crossCooldown_Cache[cmdFullName] = lastUsed
+ };
+
+ BanMenu = {
+ Prefix = Settings.Prefix;
+ Commands = {"banmenu"};
+ Args = {};
+ Description = "Opens the ban menu";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string}, data: {any})
+ Remote.MakeGui(plr,"BanMenu",{
+ AdminLevel = Admin.GetLevel(plr);
+ CanBan = Admin.CheckComLevel(Admin.GetLevel(plr),Commands.ServerBan.AdminLevel);
+ CanTimeBan = Admin.CheckComLevel(Admin.GetLevel(plr),Commands.TimeBan.AdminLevel);
+ CanPermBan = Admin.CheckComLevel(Admin.GetLevel(plr),Commands.PermanentBan.AdminLevel);
+ Prefix = Functions.GetMainPrefix()
+ })
+ end,
+ };
+
+ CustomMessage = {
+ Prefix = Settings.Prefix;
+ Commands = {"cm", "custommessage"};
+ Args = {"Upper message", "message"};
+ Filter = true;
+ Description = "Same as message but says whatever you want upper message to be instead of your name.";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[1], "Missing message title (argument #1)")
+ assert(args[2], "Missing message (argument #2)")
+ for _, v in service.Players:GetPlayers() do
+ Remote.RemoveGui(v, "Message")
+ Remote.MakeGui(v, "Message", {
+ Title = args[1];
+ Message = args[2];
+ Time = (#tostring(args[1]) / 19) + 2.5;
+ --service.Filter(args[1],plr, v);
+ })
end
end
- end;
-
- SearchCommands = function(p, search)
- local checkPerm = Admin.CheckPermission
- local tab = {}
- local pDat = {
- Player = p;
- Level = Admin.GetLevel(p);
- isDonor = Admin.CheckDonor(p);
- }
-
- for ind, cmd in Commands do
- if checkPerm(pDat, cmd, true) then
- tab[ind] = cmd
+ };
+
+ Nil = {
+ Prefix = Settings.Prefix;
+ Commands = {"nil"};
+ Args = {"player"};
+ Hidden = true;
+ Description = `Deletes the player forcefully, causing them to be kicked for "Player has been removed from the DataModel"`;
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ v.Character = nil
+ v.Parent = nil
+ Functions.Hint(`Sent {service.FormatPlayer(v)} to nil`, {plr})
+ end
+ end
+ };
+
+ PromptPremiumPurchase = {
+ Prefix = Settings.Prefix;
+ Commands = {"promptpremiumpurchase", "premiumpurchaseprompt"};
+ Args = {"player"};
+ Description = "Opens the Roblox Premium purchase prompt for the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ service.MarketplaceService:PromptPremiumPurchase(v)
+ end
+ end
+ };
+
+ RobloxNotify = {
+ Prefix = Settings.Prefix;
+ Commands = {"rbxnotify", "robloxnotify", "robloxnotif", "rblxnotify", "rnotif", "rn"};
+ Args = {"player", "duration (seconds)", "text"};
+ Filter = true;
+ Description = "Sends a Roblox-styled notification for the target player(s)";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ for _, v in service.GetPlayers(plr, args[1]) do
+ Remote.Send(v, "Function", "SetCore", "SendNotification", {
+ Title = "Notification";
+ Text = args[3] or "Hello, from Adonis!";
+ Duration = tonumber(args[2]) or 5;
+ })
end
end
+ };
+
+ Disguise = {
+ Prefix = Settings.Prefix;
+ Commands = {"disguise", "masquerade"};
+ Args = {"player", "username"};
+ Description = "Names the player, chars the player, and modifies the player's chat tag";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ assert(args[2], "Argument missing or nil")
+ local userId = Functions.GetUserIdFromNameAsync(args[2])
+ assert(userId, "Invalid username supplied/user not found")
- return tab
- end;
+ local username = select(2, xpcall(function()
+ return service.Players:GetNameFromUserIdAsync(userId)
+ end, function() return args[2] end))
- CheckAuthority = function(p, target, actionName, allowSelf)
- if p == target then
- if allowSelf == false then
- Functions.Hint(`You cannot {actionName} yourself`, {p})
- return false
+ if service.Players:GetPlayerByUserId(userId) then
+ error("You cannot disguise as this player (currently in server)")
end
- return allowSelf or Remote.GetGui(p, "YesNoPrompt", {
- Question = `Are you sure you want to {actionName} yourself?`;
- }) == "Yes"
+ Commands.Char.Function(plr, args)
+ Commands.DisplayName.Function(plr, {args[1], username})
- elseif Admin.GetLevel(p) > Admin.GetLevel(target) then
- return true
- end
+ local ChatService = Functions.GetChatService()
- Functions.Hint(`You don't have permission to {actionName} {service.FormatPlayer(target)}`, {p})
- return false
- end;
+ for _, v in service.GetPlayers(plr, args[1]) do
+ if Variables.DisguiseBindings[v.UserId] then
+ Variables.DisguiseBindings[v.UserId].Rename:Disconnect()
+ Variables.DisguiseBindings[v.UserId].Rename = nil
+ if ChatService then
+ ChatService:RemoveSpeaker(Variables.DisguiseBindings[v.UserId].TargetUsername)
+ ChatService:UnregisterProcessCommandsFunction(`Disguise_{v.Name}`)
+ end
+ end
- GetAliases = function(player)
- local aliases = table.clone(Variables.Aliases)
- local pData = player and Core.GetPlayer(player)
+ Variables.DisguiseBindings[v.UserId] = {
+ TargetUsername = username;
+ Rename = v.CharacterAppearanceLoaded:Connect(function(char)
+ Commands.DisplayName.Function(v, {v.Name, username})
+ end);
+ }
- if pData and pData.Aliases then
- for alias, command in pData.Aliases do
- aliases[alias] = command
+ if ChatService then
+ local disguiseSpeaker = ChatService:AddSpeaker(username)
+ disguiseSpeaker:JoinChannel("All")
+ ChatService:RegisterProcessCommandsFunction(`Disguise_{v.Name}`, function(speaker, message, channelName)
+ if speaker == v.Name then
+ local filteredMessage = select(2, xpcall(function()
+ return service.TextService:FilterStringAsync(message, v.UserId, Enum.TextFilterContext.PrivateChat):GetChatForUserAsync(v.UserId)
+ end, function()
+ Remote.Send(v, "Function", "ChatMessage", "A message filtering error occurred.", Color3.new(1, 64/255, 77/255))
+ return
+ end))
+ if filteredMessage and not server.Admin.DoHideChatCmd(v, message) then
+ disguiseSpeaker:SayMessage(filteredMessage, channelName)
+ if v.Character then
+ service.Chat:Chat(v.Character, filteredMessage, Enum.ChatColor.White)
+ end
+ end
+ return true
+ end
+ return false
+ end)
+ end
end
end
-
- return aliases
- end;
+ };
+
+ UnDisguise = {
+ Prefix = Settings.Prefix;
+ Commands = {"undisguise", "removedisguise", "cleardisguise", "nodisguise"};
+ Args = {"player"};
+ Description = "Removes the player's disguise";
+ AdminLevel = "Admins";
+ Function = function(plr: Player, args: {string})
+ local ChatService = Functions.GetChatService()
+ for _, v in service.GetPlayers(plr, args[1]) do
+ if Variables.DisguiseBindings[v.UserId] then
+ Variables.DisguiseBindings[v.UserId].Rename:Disconnect()
+ Variables.DisguiseBindings[v.UserId].Rename = nil
+ pcall(function()
+ ChatService:RemoveSpeaker(Variables.DisguiseBindings[v.UserId].TargetUsername)
+ ChatService:UnregisterProcessCommandsFunction(`Disguise_{v.Name}`)
+ end)
+ end
+ Variables.DisguiseBindings[v.UserId] = nil
+ end
+ Commands.UnChar.Function(plr, args)
+ Commands.UnDisplayName.Function(plr, args)
+ end
+ };
}
end
diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau
index 551cdbaf8..c38d42b7e 100644
--- a/MainModule/Server/Core/Admin.luau
+++ b/MainModule/Server/Core/Admin.luau
@@ -425,14 +425,15 @@ return function(Vargs, GetEnv)
local pData = data or Core.GetPlayer(p)
if pData.Client.HideChatCommands then
if Admin.BlankPrefix and
- (string.sub(message,1,1) ~= Settings.Prefix or string.sub(message,1,1) ~= Settings.PlayerPrefix) then
+
+ (string.sub(message,1,1) ~= Settings.Prefix or string.sub(message,1,1) ~= Settings.PlayerPrefix or (type(Settings.Prefix) == "table" and not table.find(Settings.Prefix, string.sub(message,1,1)))) then
local isCMD = Admin.GetCommand(message)
if isCMD then
return true
else
return false
end
- elseif (string.sub(message,1,1) == Settings.Prefix or string.sub(message,1,1) == Settings.PlayerPrefix)
+ elseif (string.sub(message,1,1) == Settings.Prefix or string.sub(message,1,1) == Settings.PlayerPrefix or (type(Settings.Prefix) == "table" and table.find(Settings.Prefix, string.sub(message,1,1))))
and string.sub(message,2,2) ~= string.sub(message,1,1) then
return true;
end
@@ -1397,7 +1398,7 @@ return function(Vargs, GetEnv)
--// Make it so you can't accidentally overwrite certain existing commands... resulting in being unable to add/edit/remove aliases (and other stuff)
CheckAliasBlacklist = function(alias)
local playerPrefix = Settings.PlayerPrefix;
- local prefix = Settings.Prefix;
+ local prefix = Settings.Prefix
local blacklist = {
[`{playerPrefix}alias`] = true;
[`{playerPrefix}newalias`] = true;