diff --git a/.github/alerts.deploy.project.json b/.github/alerts.deploy.project.json new file mode 100644 index 0000000000..c15a3de83d --- /dev/null +++ b/.github/alerts.deploy.project.json @@ -0,0 +1,6 @@ +{ + "name": "MainModule", + "tree": { + "$path": "../MainModule/Server/Dependencies/__URGENT_MESSAGES.luau" + } +} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d91694631e..71780ea74e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -67,11 +67,14 @@ jobs: path: ${{ steps.naming.outputs.output_name }}.rbxm - name: Build Loader - run: rojo build -o loader.rbxm .github/loader.deploy.project.json + run: rojo build -o Adonis_Loader.rbxm .github/loader.deploy.project.json - name: Build MainModule - run: rojo build -o module.rbxm .github/module.deploy.project.json - + run: rojo build -o Adonis_MainModule.rbxm .github/module.deploy.project.json + + - name: Build Alerts Module + run: rojo build -o Adonis_AlertsModule.rbxm .github/alerts.deploy.project.json + - name: Send Standalone Release to Discord channel uses: tsickert/discord-webhook@v6.0.0 with: @@ -84,7 +87,7 @@ jobs: url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.LOADER_ID }}" method: "POST" contentType: "multipart/form-data" - files: '{ "file": "loader.rbxm" }' + files: '{ "file": "Adonis_Loader.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 @@ -94,6 +97,16 @@ jobs: url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.MODULE_ID }}" method: "POST" contentType: "multipart/form-data" - files: '{ "file": "module.rbxm" }' + files: '{ "file": "Adonis_MainModule.rbxm" }' + customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' + timeout: 10000 + + - name: Publish Alerts Module + uses: fjogeleit/http-request-action@v1.16.1 + with: + url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.ALERTS_MODULE_ID }}" + method: "POST" + contentType: "multipart/form-data" + files: '{ "file": "Adonis_AlertsModule.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 47fcb6e03c..7ecfb7e259 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ There is a very clear/obvious difference between unavoidably complex code and in ## Q: Is there a style guide for writing code? -**A:** Not really, but we would normally try to follow the format of the other existing code in the module we are editing, as well as the [Roblox Lua Style Guide](https://roblox.github.io/lua-style-guide/) where applicable. Also, be sure to use US English spellings for both code variable names and user-facing text. +**A:** Not really, but we would normally try to follow the format of the other existing code in the module we are editing, as well as the [Roblox Luau Style Guide](https://roblox.github.io/lua-style-guide/) where applicable. Also, be sure to use US English spellings for both code variable names and user-facing text. ## Q: What are some things I should watch out for when submitting my changes? diff --git a/LICENSE.luau b/LICENSE.luau index 1c2b089369..a81c1f3dbe 100644 --- a/LICENSE.luau +++ b/LICENSE.luau @@ -2,7 +2,7 @@ MIT License - Copyright (c) 2016-2024 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. + Copyright (c) 2016-2025 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE.md b/LICENSE.md index cca960237f..f35d57aa81 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2024 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. +Copyright (c) 2016-2025 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Loader/Config/API.luau b/Loader/Config/API.luau index a7e9137eaf..bf01639289 100644 --- a/Loader/Config/API.luau +++ b/Loader/Config/API.luau @@ -1,6 +1,6 @@ --[[ If you're learning how to create in Adonis, the wiki may be of help. - The wiki contains informationa about the Adonis API and how to use it; + The wiki contains information about the Adonis API and how to use it; as well as information about settings and how to use Adonis. It can be viewed here: diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index 04a748438c..cda345f7e6 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -36,7 +36,7 @@ local descs = {}; --// Contains settings descriptions Numbers do not use quotes. setting = 56 - This green block of text you are reading is called a comment. It's like a message + This block of text you are reading is called a comment. It's like a message from the programmer to anyone who reads their stuff. Anything in a comment will not be seen by Luau when the script is run. @@ -75,7 +75,7 @@ local descs = {}; --// Contains settings descriptions settings.HeadAdmins = {"Group:181:121"} See? Not so hard is it? - If I wanted to add group 181 and all ranks in it to the :slock whitelist I would do; + If I wanted to add group 181 and all ranks in it to the ;slock whitelist I would do; settings.Whitelist = {"Group:181";} I can do the above if I wanted to give everyone in a group admin for any of the other admin tables @@ -85,11 +85,11 @@ local descs = {}; --// Contains settings descriptions --// Command Permissions You can set the permission level for specific commands using setting.Permissions - If I wanted to make it so only HeadAdmins+ can use :ff player then I would do: + If I wanted to make it so only HeadAdmins+ can use ;ff player then I would do: settings.Permissions = {"ff:HeadAdmins"} - ff is the Command ":ff scel" and HeadAdmins is the NewLevel + ff is the Command ";ff scel" and HeadAdmins is the NewLevel Built-In Permissions Levels: Players - 0 @@ -99,7 +99,7 @@ local descs = {}; --// Contains settings descriptions Creators - 900 Note that when changing command permissions you MUST include the prefix; - So if you change the prefix to $ you would need to do $ff instead of :ff + So if you change the prefix to $ you would need to do $ff instead of ;ff --// Trello @@ -115,12 +115,12 @@ local descs = {}; --// Contains settings descriptions 6. Congrats! The board is ready to be used; 7. Create a list and add cards to it; - - You can view lists in-game using :viewlist ListNameHere + - You can view lists in-game using ;viewlist ListNameHere Lists: Moderators - Card Format: Same as settings.Moderators Admins - Card Format: Same as settings.Admins - HeadAdmins - Card Format: Same as settings.HeadAdmins + HeadAdmins - Card Format: Same as settings.HeadAdmins Creators - Card Format: Same as settings.Creators Banlist - Card Format: Same as settings.Banned Mutelist - Card Format: Same as settings.Muted @@ -128,7 +128,7 @@ local descs = {}; --// Contains settings descriptions Whitelist - Card Format: Same as settings.Whitelist Permissions - Card Format: Same as settings.Permissions Music - Card Format: SongName:AudioID - Commands - Card Format: Command (eg. :ff bob) + Commands - Card Format: Command (eg. ;ff bob) Card format refers to how card names should look @@ -140,14 +140,13 @@ settings.HideScript = true -- When the game starts the Adonis_Loader model settings.DataStore = "Adonis_1" -- DataStore the script will use for saving data; Changing this will lose any saved data settings.DataStoreKey = "CHANGE_THIS" -- CHANGE THIS TO ANYTHING RANDOM! Key used to encrypt all datastore entries; Changing this will lose any saved data settings.DataStoreEnabled = true -- Disable if you don't want to load settings and admins from the datastore; PlayerData will still save -settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers +settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers -settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored -settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the :give command (useful if your tools are organized into multiple folders) +settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored +settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders) settings.Theme = "Default" -- UI theme; settings.MobileTheme = "Mobilius" -- Theme to use on mobile devices; Some UI elements are disabled - --[[ **HOW TO ADD ADMINISTRATORS:** Below are the administrator permission levels/ranks (Mods, Admins, HeadAdmins, Creators, StuffYouAdd, etc) @@ -157,7 +156,7 @@ settings.MobileTheme = "Mobilius" -- Theme to use on mobile devices; Some UI el settings.Ranks = { ["Moderators"] = { Level = 100; - Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID"; "Subscription:SubscriptionId";} + Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} } } @@ -199,49 +198,60 @@ settings.Ranks = { --// Use the below table to set command permissions; Commented commands are included for example purposes settings.Permissions = { - -- "ff:HeadAdmins"; --// Changes :ff to HeadAdmins and higher (HeadAdmins = Level 300 by default) - -- "kill:300"; --// Changes :kill to level 300 and higher (Level 300 = HeadAdmins by default) - -- "ban:200,300" --// Makes it so :ban is only usable by levels 200 and 300 specifically (nothing higher or lower or in between) + -- "ff:HeadAdmins"; --// Changes ;ff to HeadAdmins and higher (HeadAdmins = Level 300 by default) + -- "kill:300"; --// Changes ;kill to level 300 and higher (Level 300 = HeadAdmins by default) + -- "ban:200,300" --// Makes it so ;ban is only usable by levels 200 and 300 specifically (nothing higher or lower or in between) }; -- Format: {"Command:NewLevel"; "Command:Customrank1,Customrank2,Customrank3";} --// Use the below table to define "pre-set" command aliases ---// Command aliases; Format: {[":alias ..."] = ":command ..."} +--// Command aliases; Format: {[";alias ..."] = ";command ..."} settings.Aliases = { - [":examplealias "] = ":ff | :fling | :fire " --// Order arguments appear in alias string determines their required order in the command message when ran later + [";examplealias "] = ";ff | ;fling | ;fire " --// Order arguments appear in alias string determines their required order in the command message when ran later }; +--// Use the below table to define pre-set cameras +settings.Cameras = { +--[[ + "Camera Name" would be the name of your camera + { + Name = "Camera Name"; + Position = Vector3.new(0, 0, 0) + } +]] +} + settings.Banned = {} -- List of people banned from the game Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Muted = {} -- List of people muted (cannot send chat messages) Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Blacklist = {} -- List of people banned from running commands Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Whitelist = {} -- People who can join if whitelist enabled Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} -settings.MusicList = {} -- List of songs to appear in the :musiclist Format: {{Name = "somesong", ID = 1234567}, {Name = "anotherone", ID = 1243562}} +settings.MusicList = {} -- List of songs to appear in the ;musiclist Format: {{Name = "somesong", ID = 1234567}, {Name = "anotherone", ID = 1243562}} settings.CapeList = {} -- List of capes Format: {{Name = "somecape", Material = "Fabric", Color = "Bright yellow", ID = 12345567, Reflectance = 1}; {etc more stuff here}} -settings.InsertList = {} -- List of models to appear in the :insertlist and can be inserted using ':insert ' Format: {{Name = "somemodel", ID = 1234567}; {Name = "anotherone", ID = 1243562}} -settings.Waypoints = {} -- List of waypoints you can teleport via ':to wp-WAYPOINTNAME' or ':teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} +settings.InsertList = {} -- List of models to appear in the ;insertlist and can be inserted using ';insert ' Format: {{Name = "somemodel", ID = 1234567}; {Name = "anotherone", ID = 1243562}} +settings.Waypoints = {} -- List of waypoints you can teleport via ';to wp-WAYPOINTNAME' or ';teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} -settings.OnStartup = {} -- List of commands ran at server start Format: {":notif TestNotif"} -settings.OnJoin = {} -- List of commands ran as player on join (ignores adminlevel) Format: {":cmds"} -settings.OnSpawn = {} -- List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",":ff me"} +settings.OnStartup = {} -- List of commands ran at server start Format: {";notif TestNotif"} +settings.OnJoin = {} -- List of commands ran as player on join (ignores adminlevel) Format: {";cmds"} +settings.OnSpawn = {} -- List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",";ff me"} -settings.SaveAdmins = true -- If true anyone you :admin or :headadmin in-game will save +settings.SaveAdmins = true -- If true anyone you ;admin or ;headadmin in-game will save settings.LoadAdminsFromDS = true -- If false, any admins saved in your DataStores will not load settings.WhitelistEnabled = false -- If true enables the whitelist/server lock; Only lets admins & whitelisted users join -settings.Prefix = ":" -- The : in :kill me +settings.Prefix = {";", ":"} -- A list of prefixes for commands, the ; in ;kill me settings.PlayerPrefix = "!" -- The ! in !donate; Mainly used for commands that any player can run; Do not make it the same as settings.Prefix -settings.SpecialPrefix = "" -- Used for things like "all", "me" and "others" (If changed to ! you would do :kill !me) -settings.SplitKey = " " -- The space in :kill me (eg if you change it to / :kill me would be :kill/me) -settings.BatchKey = "|" -- :kill me | :ff bob | :explode scel +settings.SpecialPrefix = "" -- Used for things like "all", "me" and "others" (If changed to ! you would do ;kill !me) +settings.SplitKey = " " -- The space in ;kill me (eg if you change it to / ;kill me would be ;kill/me) +settings.BatchKey = "|" -- ;kill me | ;ff bob | ;explode scel settings.ConsoleKeyCode = "Quote" -- Keybind to open the console; Rebindable per player in userpanel; KeyCodes: https://developer.roblox.com/en-us/api-reference/enum/KeyCode --// Easily add new custom commands below (without needing to create a plugin module) --// You can also use this to overwrite existing commands if you know the command's index (found in the command's respective module within the Adonis MainModule) settings.Commands = { ExampleCommand1 = { --// The index & table of the command - Prefix = Settings.Prefix; --// The prefix the command will use, this is the ':' in ':ff me' - Commands = {"examplecommand1", "examplealias1", "examplealias2"}; --// A table containing the command strings (the things you chat in-game to run the command, the 'ff' in ':ff me') - Args = {"arg1", "arg2", "etc"}; --// Command arguments, these will be available in order as args[1], args[2], args[3], etc; This is the 'me' in ':ff me' + Prefix = Settings.Prefix; --// The prefix the command will use, this is the ';' in ';ff me' + Commands = {"examplecommand1", "examplealias1", "examplealias2"}; --// A table containing the command strings (the things you chat in-game to run the command, the 'ff' in ';ff me') + Args = {"arg1", "arg2", "etc"}; --// Command arguments, these will be available in order as args[1], args[2], args[3], etc; This is the 'me' in ';ff me' Description = "Example command";--// The description of the command AdminLevel = 100; -- Moderators --// The commands minimum admin level; This can also be a table containing specific levels rather than a minimum level: {124, 152, "HeadAdmins", etc}; -- Alternative option: AdminLevel = "Moderators" @@ -263,7 +273,7 @@ settings.Commands = { settings.CommandCooldowns = { --[[ REFERENCE: - command_full_name: The name of a command (e.g. :cmds) + command_full_name: The name of a command (e.g. ;cmds) [command_full_name] = { Player = 0; @@ -281,25 +291,25 @@ settings.CommandFeedback = false -- Should players be notified when commands wi settings.CrossServerCommands = true -- Are commands which affect more than one server enabled? settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script -settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as :s) and a few other commands require this +settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as ;s) and a few other commands require this settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command -settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. +settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. settings.BanMessage = "Banned" -- Message shown to banned users upon kick -settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is :slocked -settings.SystemTitle = "System Message" -- Title to display in :sm and :bc +settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is ;slocked +settings.SystemTitle = "System Message" -- Title to display in ;sm and ;bc settings.MaxLogs = 5000 -- Maximum logs to save before deleting the oldest settings.SaveCommandLogs = true -- If command logs are saved to the datastores settings.Notification = true -- Whether or not to show the "You're an admin" and "Updated" notifications -settings.SongHint = true -- Display a hint with the current song name and ID when a song is played via :music +settings.SongHint = true -- Display a hint with the current song name and ID when a song is played via ;music settings.TopBarShift = false -- By default hints and notifications will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. settings.DefaultTheme = "Default" -- Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. settings.HiddenThemes = {} -- Hide themes from the theme selector tab inside the userpanel. Each theme name must be the specific name such as "Mobilius" settings.Messages = {} -- A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level settings.AutoClean = false -- Will auto clean workspace of things like hats and tools settings.AutoCleanDelay = 60 -- Time between auto cleans -settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap +settings.AutoBackup = false -- Run ;backupmap automatically when the server starts. To restore the map, run ;restoremap settings.ReJail = false -- If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed settings.Console = true -- Whether the command console is enabled @@ -329,7 +339,7 @@ settings.Trello_Primary = "" -- Primary Trello board settings.Trello_Secondary = {} -- Secondary Trello boards (read-only) Format: {"BoardID";"BoardID2","etc"} settings.Trello_AppKey = "" -- Your Trello AppKey settings.Trello_Token = "" -- Trello token (DON'T SHARE WITH ANYONE!) Get API key: /1/connect?name=Trello_API_Module&response_type=token&expires=never&scope=read,write&key=YOUR_APP_KEY_HERE -settings.Trello_HideRanks = false -- If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via :admins) +settings.Trello_HideRanks = false -- If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via ;admins) --------------------- @@ -393,7 +403,7 @@ descs.DataStoreEnabled = [[ Disable if you don't want settings and admins to be descs.LocalDatastore = [[ If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers ]] descs.Storage = [[ Where things like tools are stored ]] -descs.RecursiveTools = [[ Whether tools that are included in sub-containers within settings.Storage will be available via the :give command (useful if your tools are organized into multiple folders) ]] +descs.RecursiveTools = [[ Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders) ]] descs.Theme = [[ UI theme; ]] descs.MobileTheme = [[ Theme to use on mobile devices; Mobile themes are optimized for smaller screens; Some GUIs are disabled ]] @@ -405,7 +415,8 @@ descs.HeadAdmins = [[ Head Admins; Format: {"Username"; "Username:UserId"; UserI descs.Creators = [[ Anyone to be identified as a place owner; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] descs.Permissions = [[ Command permissions; Format: {"Command:NewLevel";} ]] -descs.Aliases = [[ Command aliases; Format: {[":alias ..."] = ":command ..."} ]] +descs.Aliases = [[ Command aliases; Format: {[";alias ..."] = ";command ..."} ]] +descs.Cameras = [[ Cameras; Format: {Name = "CamName", Position = Vector3.new(X, Y, Z)} ]] descs.Commands = [[ Custom commands ]] descs.Banned = [[ List of people banned from the game; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] @@ -415,22 +426,22 @@ descs.Whitelist = [[ People who can join if whitelist enabled; Format: {"Usernam descs.MusicList = [[ List of songs to appear in the script; Format: {{Name = "somesong",ID = 1234567},{Name = "anotherone",ID = 1243562}} ]] descs.CapeList = [[ List of capes; Format: {{Name = "somecape",Material = "Fabric",Color = "Bright yellow",ID = 12345567,Reflectance = 1},{etc more stuff here}} ]] descs.InsertList = [[ List of models to appear in the script; Format: {{Name = "somemodel",ID = 1234567},{Name = "anotherone",ID = 1243562}} ]] -descs.Waypoints = [[ List of waypoints you can teleport via ':to wp-WAYPOINTNAME' or ':teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} ]] +descs.Waypoints = [[ List of waypoints you can teleport via ';to wp-WAYPOINTNAME' or ';teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} ]] descs.CustomRanks = [[ List of custom AdminLevel ranks Format: {RankName = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";};} ]] -descs.OnStartup = [[ List of commands ran at server start Format: {":notif TestNotif"} ]] -descs.OnJoin = [[ List of commands ran as player on join (ignores adminlevel) Format: {":cmds"} ]] -descs.OnSpawn = [[ List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",":ff me"} ]] +descs.OnStartup = [[ List of commands ran at server start Format: {";notif TestNotif"} ]] +descs.OnJoin = [[ List of commands ran as player on join (ignores adminlevel) Format: {";cmds"} ]] +descs.OnSpawn = [[ List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",";ff me"} ]] -descs.SaveAdmins = [[ If true anyone you :mod, :admin, or :headadmin in-game will save]] +descs.SaveAdmins = [[ If true anyone you ;mod, ;admin, or ;headadmin in-game will save]] descs.LoadAdminsFromDS = [[ If false, any admins saved in your DataStores will not load ]] descs.WhitelistEnabled = [[ If true enables the whitelist/server lock; Only lets admins & whitelisted users join ]] -descs.Prefix = [[ The : in :kill me ]] +descs.Prefix = [[ The ; in ;kill me ]] descs.PlayerPrefix = [[ The ! in !donate; Mainly used for commands that any player can run ]] -descs.SpecialPrefix = [[ Used for things like "all", "me" and "others" (If changed to ! you would do :kill !me) ]] -descs.SplitKey = [[ The space in :kill me (eg if you change it to / :kill me would be :kill/me) ]] -descs.BatchKey = [[ :kill me | :ff bob | :explode scel ]] +descs.SpecialPrefix = [[ Used for things like "all", "me" and "others" (If changed to ! you would do ;kill !me) ]] +descs.SplitKey = [[ The space in ;kill me (eg if you change it to / ;kill me would be ;kill/me) ]] +descs.BatchKey = [[ ;kill me | ;ff bob | ;explode scel ]] descs.ConsoleKeyCode = [[ Keybind to open the console ]] descs.HttpWait = [[ How long things that use the HttpService will wait before updating again ]] @@ -439,7 +450,7 @@ descs.Trello_Primary = [[ Primary Trello board ]] descs.Trello_Secondary = [[ Secondary Trello boards; Format: {"BoardID";"BoardID2","etc"} ]] descs.Trello_AppKey = [[ Your Trello AppKey; ]] descs.Trello_Token = [[ Trello token (DON'T SHARE WITH ANYONE!) ]] -descs.Trello_HideRanks = [[ If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via :admins) ]] +descs.Trello_HideRanks = [[ If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via ;admins) ]] descs.G_API = [[ If true, allows other server scripts to access certain functions described in the API module through _G.Adonis ]] descs.G_Access = [[ If enabled, allows other scripts to access Adonis using _G.Adonis.Access; Scripts will still be able to do things like _G.Adonis.CheckAdmin(player) ]] @@ -458,15 +469,15 @@ descs.SilentCommandDenials = [[ If true, there will be no differences between th descs.OverrideChatCallbacks = [[ If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for muting ]] descs.BanMessage = [[ Message shown to banned users ]] -descs.LockMessage = [[ Message shown to people when they are kicked while the game is :slocked ]] -descs.SystemTitle = [[ Title to display in :sm ]] +descs.LockMessage = [[ Message shown to people when they are kicked while the game is ;slocked ]] +descs.SystemTitle = [[ Title to display in ;sm ]] descs.CreatorPowers = [[ Gives me creator-level admin; This is strictly used for debugging; I can't debug without access to the script and specific owner commands ]] descs.MaxLogs = [[ Maximum logs to save before deleting the oldest; Too high can lag the game ]] descs.SaveCommandLogs = [[ If command logs are saved to the datastores ]] descs.Notification = [[ Whether or not to show the "You're an admin" and "Updated" notifications ]] descs.CodeExecution = [[ Enables the use of code execution in Adonis; Scripting related and a few other commands require this ]] -descs.SongHint = [[ Display a hint with the current song name and ID when a song is played via :music ]] +descs.SongHint = [[ Display a hint with the current song name and ID when a song is played via ;music ]] descs.TopBarShift = [[ By default hints and notifs will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. ]] descs.DefaultTheme = [[ Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] @@ -474,7 +485,7 @@ descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. descs.Messages = [[ A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level ]] descs.AutoClean = [[ Will auto clean workspace of things like hats and tools ]] -descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run :restoremap ]] +descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run ;restoremap ]] descs.AutoCleanDelay = [[ Time between auto cleans ]] descs.PlayerList = [[ Custom playerlist ]] @@ -523,6 +534,7 @@ order = { " "; "Permissions"; "Aliases"; + "Cameras"; " "; "Commands"; "Banned"; @@ -592,7 +604,6 @@ order = { "AutoBackup"; " "; "PlayerList"; - " "; "Console"; "Console_AdminsOnly"; " "; diff --git a/Loader/Version.model.json b/Loader/Version.model.json index 50b0f991a1..6cde8b08e1 100644 --- a/Loader/Version.model.json +++ b/Loader/Version.model.json @@ -1,6 +1,6 @@ { "ClassName": "NumberValue", "Properties": { - "Value": 261 + "Value": 263 } } diff --git a/MainModule/Client/Client.luau b/MainModule/Client/Client.luau index 4d6133487c..9b59dfc27a 100644 --- a/MainModule/Client/Client.luau +++ b/MainModule/Client/Client.luau @@ -218,7 +218,7 @@ do task.wait(1) service.Player:Kick(info) end) - + if not isStudio then spawn(pcall, function() task.wait(5) @@ -575,7 +575,7 @@ return service.NewProxy({ for i, line in ipairs(client.Changelog) do client.FormattedChangelog[i] = applyColour(line) end - + --// Setup MatIcons do local MaterialIcons = oldReq(service_UnWrap(client.Shared.MatIcons)) @@ -752,7 +752,9 @@ return service.NewProxy({ continue end - LoadModule(module, false, { script = module, cPcall = client.cPcall }) --noenv + task.defer(LoadModule, module, false, { --noenv + script = module, cPcall = client.cPcall + }) end --// We need to do some stuff *after* plugins are loaded (in case we need to be able to account for stuff they may have changed before doing something, such as determining the max length of remote commands) diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index 540a1ccb13..0b868b7ed2 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -169,7 +169,7 @@ return function(Vargs, GetEnv) end local textbox = service.UserInputService:GetFocusedTextBox() - if textbox then + if textbox and service.CheckProperty(textbox, "ReleaseFocus") then textbox:ReleaseFocus() end @@ -179,7 +179,7 @@ return function(Vargs, GetEnv) HandleTextChatCommands = function() local data = Remote.Get("PlayerData") local adminLevel, isDonor = data.AdminLevel, data.isDonor - + if service.TextChatService and service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then local function onCommandAdded(command) if not command:IsA("TextChatCommand") then diff --git a/MainModule/Client/UI/BasicAdmin/Message.rbxmx b/MainModule/Client/UI/BasicAdmin/Message.rbxmx index 3b9996452a..bd3c02a3d3 100644 --- a/MainModule/Client/UI/BasicAdmin/Message.rbxmx +++ b/MainModule/Client/UI/BasicAdmin/Message.rbxmx @@ -6,7 +6,7 @@ false - 0 + 0dgxzhjgfhjfhgjhdjgfzjdhg true false 0 diff --git a/MainModule/Client/UI/Default/Music/Slider.luau b/MainModule/Client/UI/Default/Music/Slider.luau index f24cc2065b..6dcd7d7722 100644 --- a/MainModule/Client/UI/Default/Music/Slider.luau +++ b/MainModule/Client/UI/Default/Music/Slider.luau @@ -1,3 +1,4 @@ +--!native -------------------------------------------------------------------------------------------- -------------------------------------- Slider Module --------------------------------------- -- [Adonis Maintainer]: P3tray diff --git a/MainModule/Client/UI/Default/Music/Visualizer.luau b/MainModule/Client/UI/Default/Music/Visualizer.luau index 6772f56c24..7c089564cf 100644 --- a/MainModule/Client/UI/Default/Music/Visualizer.luau +++ b/MainModule/Client/UI/Default/Music/Visualizer.luau @@ -1,3 +1,5 @@ +--!native +--!optimize 2 local RunService = game:GetService("RunService") local module = {} diff --git a/MainModule/Client/UI/Default/Music/init.luau b/MainModule/Client/UI/Default/Music/init.luau index 3725aba090..5bbd19740a 100644 --- a/MainModule/Client/UI/Default/Music/init.luau +++ b/MainModule/Client/UI/Default/Music/init.luau @@ -205,7 +205,14 @@ return function(data, env) Position = UDim2.new(0, 10, 1, -410); OnClose = function() doOnClose() - end + end, + OnMinimized = function(opened) + if opened and not visualiser.Sound then + visualiser:LinkToSound(audioLib:GetSound()) + elseif not opened and visualiser.Sound then + visualiser:UnlinkFromSound() + end + end, }) -- The controls frame at the bottom of the window diff --git a/MainModule/Client/UI/Default/PrivateChat.luau b/MainModule/Client/UI/Default/PrivateChat.luau index a60b8db2bd..f4312fe6fc 100644 --- a/MainModule/Client/UI/Default/PrivateChat.luau +++ b/MainModule/Client/UI/Default/PrivateChat.luau @@ -321,7 +321,7 @@ return function(data, env) Parent = chatlog; FillDirection = "Vertical"; HorizontalAlignment = "Left"; - VerticalAlignment = "Bottom"; + VerticalAlignment = "Top"; SortOrder = "LayoutOrder"; }) @@ -358,7 +358,6 @@ return function(data, env) local p = vargs[1] local message = vargs[2] if newMessage then - print('sdf') newMessage({ PlayerName = p.Name; PlayerDisplayName = p.DisplayName; diff --git a/MainModule/Client/UI/Default/Profile.luau b/MainModule/Client/UI/Default/Profile.luau index b1105632bf..1abefa1804 100644 --- a/MainModule/Client/UI/Default/Profile.luau +++ b/MainModule/Client/UI/Default/Profile.luau @@ -162,29 +162,40 @@ return function(data, env) window:Ready() do --// Friends Tab + local function pagesToTable(pages) + local items = {} + while true do + table.insert(items, pages:GetCurrentPage()) + if pages.IsFinished then + break + end + pages:AdvanceToNextPageAsync() + end + return items + end local function iterPageItems(pages) + local contents = pagesToTable(pages) + local pagenum = 1 + local lastpagenum = #contents return coroutine.wrap(function() local pagenum = 1 - while true do - for _, item in ipairs(pages:GetCurrentPage()) do + while pagenum <= lastpagenum do + for _, item in ipairs(contents[pagenum]) do coroutine.yield(item, pagenum) end - if pages.IsFinished then - break - end - pages:AdvanceToNextPageAsync() + pagenum += 1 end end) end - local LOCATION_TYPE = {"Mobile Website", "Mobile InGame", "Webpage", "Studio", "InGame", "Xbox", "Team Create"} + local LOCATION_TYPE = {"Mobile Website", "Mobile In-Game", "Webpage", "Studio", "In-Game", "Xbox", "Team Create"} local ACTIVITY_COLOR_CODES = { ["Mobile Website"] = Color3.fromRGB(50, 140, 231); - ["Mobile InGame"] = Color3.fromRGB(55, 200, 55); + ["Mobile In-Game"] = Color3.fromRGB(55, 200, 55); ["Webpage"] = Color3.fromRGB(50, 140, 231); ["Studio"] = Color3.fromRGB(231, 112, 0); - ["InGame"] = Color3.fromRGB(55, 200, 55); + ["In-Game"] = Color3.fromRGB(55, 200, 55); ["Xbox"] = Color3.fromRGB(127, 0, 127); ["Team Create"] = Color3.fromRGB(231, 112, 0); } @@ -210,7 +221,7 @@ return function(data, env) Routine(function() for item, pageNo in iterPageItems(friendPages) do table.insert(sortedFriends, item.Username) - local userId = item.id + local userId = item.Id local activity = onlineFriends[userId] friendInfoRef[item.Username] = { id = userId; @@ -467,4 +478,4 @@ return function(data, env) else gametab:Disable() end -end +end \ No newline at end of file diff --git a/MainModule/Client/UI/Default/Teams.luau b/MainModule/Client/UI/Default/Teams.luau index 957c721914..000b102175 100644 --- a/MainModule/Client/UI/Default/Teams.luau +++ b/MainModule/Client/UI/Default/Teams.luau @@ -85,7 +85,7 @@ return function(data, env) self.Active = false self.AutoButtonColor = false self.Text = "..." - client.Remote.Send("ProcessCommand", string.format("%snewteam%s%s%s%s", data.CmdPrefix, data.CmdSplitKey, teamName.Text, data.CmdSplitKey, teamColor.Text)); + client.Remote.Send("ProcessCommand", string.format("%snewteam%s%s%s%s", data.CmdPrefix, data.CmdSplitKey, `"{teamName.Text}"`, data.CmdSplitKey, teamColor.Text)); teamName.Text = "" teamColor.Text = "" wait(1.2) @@ -98,9 +98,6 @@ return function(data, env) end; }) - teamName:GetPropertyChangedSignal("Text"):Connect(function() - teamName.Text = string.gsub(teamName.Text, data.CmdSplitKey, "") - end) teamColor:GetPropertyChangedSignal("Text"):Connect(function() teamColor.TextColor3 = BrickColor.new(teamColor.Text).Color --teamColor.TextColor3 = `{BrickColor.new(teamColor.Text:sub(1, 1):upper()}{teamColor.Text:sub(2):lower()).Color}` -- unfortunately we have BrickColors with names like "New Yeller" diff --git a/MainModule/Client/UI/Default/UserPanel.luau b/MainModule/Client/UI/Default/UserPanel.luau index 7d50c7f385..363fcfbdd8 100644 --- a/MainModule/Client/UI/Default/UserPanel.luau +++ b/MainModule/Client/UI/Default/UserPanel.luau @@ -497,7 +497,8 @@ return function(data, env) chatMod = Remote.Get("Setting",{"Prefix","SpecialPrefix","BatchKey","AnyPrefix","DonorCommands","DonorCapes"}) settingsData = Remote.Get("AllSettings") Variables.Aliases = playerData.Aliases or {} - commandPrefix = chatMod.Prefix + commandPrefix = if type(chatMod.Prefix) == "table" then chatMod.Prefix[1] else chatMod.Prefix + for _, v in loadingIcons do v:Destroy() diff --git a/MainModule/Client/UI/Windows XP/Window.rbxmx b/MainModule/Client/UI/Windows XP/Window.rbxmx index cd162b580f..3439b8f3b3 100644 --- a/MainModule/Client/UI/Windows XP/Window.rbxmx +++ b/MainModule/Client/UI/Windows XP/Window.rbxmx @@ -2,7 +2,7 @@ true null nil - + false @@ -25,7 +25,7 @@ 0 - + false @@ -69,6 +69,7 @@ null null null + 0 0 @@ -118,7 +119,7 @@ false 2 - + true @@ -164,6 +165,7 @@ null null null + 0.699999988 0.699999988 @@ -222,7 +224,7 @@ 2 - + 0 @@ -234,7 +236,7 @@ - + false @@ -297,7 +299,7 @@ false 2 - + 0 @@ -308,7 +310,7 @@ 0 - + false @@ -372,7 +374,7 @@ 2 - + false @@ -469,7 +471,7 @@ 2 - + false @@ -567,7 +569,7 @@ - + false @@ -630,7 +632,7 @@ false 999999 - + false @@ -674,6 +676,7 @@ null null null + 0 5 @@ -725,7 +728,7 @@ - + false @@ -788,7 +791,7 @@ false 1 - + true @@ -834,6 +837,7 @@ null null null + 0 0 @@ -886,7 +890,7 @@ 1 - + true @@ -989,7 +993,7 @@ 1 - + false @@ -1054,7 +1058,7 @@ - + 0 @@ -1063,7 +1067,7 @@ -1 - + 0 @@ -1074,14 +1078,14 @@ true - + 0 false Code.OLD - {0506ffb7-ad3b-489a-9bef-cfd7dbff8f3e} + {31a3c2a2-a077-40a7-9010-52f827d566fa} - + 0 @@ -2713,14 +2717,14 @@ end]]> true - + 0 false NoEnv-Modifier - {9840b665-71ba-4ed0-acd6-04d535842c43} + {396ac619-0995-414c-a5c6-7c78f71f014a} - + false @@ -2879,6 +2887,7 @@ end]]> null null null + 0 0 @@ -2928,7 +2937,7 @@ end]]> false 2 - + true @@ -2974,6 +2983,7 @@ end]]> null null null + 1 -50 @@ -3026,7 +3036,7 @@ end]]> 2 - + 0 @@ -3038,7 +3048,7 @@ end]]> - + false @@ -3082,6 +3092,7 @@ end]]> null null null + 0 0 @@ -3131,7 +3142,7 @@ end]]> false 2 - + true @@ -3177,6 +3188,7 @@ end]]> null null null + 1 -100 @@ -3229,7 +3241,7 @@ end]]> 2 - + 0 @@ -3241,7 +3253,7 @@ end]]> - + true @@ -3273,7 +3285,7 @@ end]]> rbxasset://fonts/families/LegacyArial.json 400 - rbxasset://fonts/arial.ttf + rbxasset://fonts/Arimo-Regular.ttf true 0 @@ -3287,6 +3299,7 @@ end]]> null null null + 0 400 @@ -3338,7 +3351,7 @@ end]]> true 1 - + true @@ -3441,7 +3454,7 @@ end]]> 2 - + false @@ -3485,6 +3498,7 @@ end]]> null null null + 0 34 @@ -3535,7 +3549,7 @@ end]]> 9 - + false @@ -3631,7 +3645,7 @@ end]]> true 1 - + true @@ -3702,7 +3716,7 @@ end]]> 0 0 0 - false + true null 0 @@ -3721,7 +3735,7 @@ end]]> 1 - + false @@ -3824,7 +3838,7 @@ end]]> 1 - + false @@ -3927,7 +3941,7 @@ end]]> 1 - + false @@ -4030,7 +4044,7 @@ end]]> 1 - + false @@ -4133,7 +4147,7 @@ end]]> 1 - + false @@ -4236,7 +4250,7 @@ end]]> 1 - + false @@ -4339,7 +4353,7 @@ end]]> 1 - + false @@ -4442,7 +4456,7 @@ end]]> 1 - + false @@ -4545,7 +4559,7 @@ end]]> 1 - + false @@ -4642,7 +4656,7 @@ end]]> 1 - + false @@ -4740,7 +4754,7 @@ end]]> - + true @@ -4786,6 +4800,7 @@ end]]> null null null + 1 -52 @@ -4837,7 +4852,7 @@ end]]> true 2 - + true @@ -4941,7 +4956,7 @@ end]]> - + true @@ -4987,6 +5002,7 @@ end]]> null null null + 1 -76 @@ -5038,7 +5054,7 @@ end]]> true 2 - + true @@ -5141,7 +5157,7 @@ end]]> 1 - + false @@ -5239,7 +5255,7 @@ end]]> - + true @@ -5285,6 +5301,7 @@ end]]> null null null + 1 -28 @@ -5336,7 +5353,7 @@ end]]> true 2 - + false @@ -5380,6 +5397,7 @@ end]]> null null null + 0.5 0 @@ -5430,7 +5448,7 @@ end]]> 10 - + true @@ -5534,7 +5552,7 @@ end]]> - + false @@ -5632,7 +5650,7 @@ end]]> - + 0 @@ -5643,7 +5661,7 @@ end]]> true - + false @@ -5706,7 +5724,7 @@ end]]> false 1 - + false @@ -5777,7 +5795,7 @@ end]]> 0 0 0 - false + true null 0 @@ -5796,7 +5814,7 @@ end]]> 1 - + false @@ -5861,7 +5879,7 @@ end]]> - + false @@ -5905,6 +5923,7 @@ end]]> null null null + 0 0 @@ -5954,7 +5973,7 @@ end]]> false 2 - + true @@ -6000,6 +6019,7 @@ end]]> null null null + 1 -100 @@ -6052,7 +6072,7 @@ end]]> 2 - + 0 @@ -6064,7 +6084,7 @@ end]]> - + false @@ -6127,7 +6147,7 @@ end]]> false 2 - + 0 @@ -6138,7 +6158,7 @@ end]]> TestDesc - + false @@ -6182,6 +6202,7 @@ end]]> null null null + 0 5 @@ -6232,7 +6253,7 @@ end]]> 2 - + false @@ -6276,6 +6297,7 @@ end]]> null null null + 1 -10 @@ -6327,7 +6349,7 @@ end]]> - + true @@ -6373,6 +6395,7 @@ end]]> null null null + 1 -100 @@ -6426,4 +6449,4 @@ end]]> - + \ No newline at end of file diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index dd10d2f70d..e69de29bb2 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -1,1592 +0,0 @@ ---!nocheck -return function(Vargs, env) - local server = Vargs.Server; - local service = Vargs.Service; - - 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 - Functions.Hint(`You do not have permission to set the rank of {service.FormatPlayer(p, true)}`, {plr}) - end - end - 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 - 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)) - - 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 - 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 - 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 - - if userFound then - return - else - Functions.Hint("User not found in server; searching datastore", {plr}) - end - end - - for rankName, rankData in Settings.Ranks do - if senderLevel <= rankData.Level then - continue - end - 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 - 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 - end - }; - - 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 - }; - - 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 - - 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 - }; - - 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 - }; - - 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 - }; - - 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 - error("Missing user argument") - end - 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 - 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 - 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 - else - Variables.NotifMessage = args[1] - for _, v in service.GetPlayers() do - Remote.MakeGui(v, "Notif", { - Message = Variables.NotifMessage; - }) - end - end - end - }; - - 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 - }; - - 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 - }; - - 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 - }; - - 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 - for _, obj in clonedDeps:GetChildren() do - obj.Parent = F3X - 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 - }) - - for _, v in service.GetPlayers(plr, args[1]) do - local Backpack = v:FindFirstChildOfClass("Backpack") - - if Backpack then - F3X:Clone().Parent = Backpack - end - end - - F3X:Destroy() - 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 Variables.InsertList do - if id == string.lower(v.Name)then - id = v.ID - break - end - end - - for i, v in HTTP.Trello.InsertList do - if id == string.lower(v.Name) then - id = v.ID - break - end - end - - 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 - }; - - 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]) - 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 - }; - - 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 "" - - if not Variables.MapBackup then - error("Cannot restore when there are no backup maps!", 0) - return - end - if Variables.RestoringMap then - error("Map has not been backed up",0) - return - end - if Variables.BackingupMap then - error("Cannot restore map while backing up map is in process!", 0) - return - end - - Variables.RestoringMap = true - Functions.Hint("Restoring Map...", service.Players:GetPlayers()) - workspace.Gravity = Variables.OriginalGravity - - 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 - - local new = Variables.MapBackup:Clone() - for _, obj in new:GetChildren() do - obj.Parent = workspace - if obj:IsA("Model") then - obj:MakeJoints() - end - end - new:Destroy() - - 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 - - task.wait() - - Admin.RunCommand(`{Settings.Prefix}fixlighting`) - Admin.RunCommand(`{Settings.Prefix}respawn`, "all") - Variables.RestoringMap = false - Functions.Hint('Map Restore Complete.',service.Players:GetPlayers()) - - Logs:AddLog("Script", { - Text = "Map Restoration Complete", - Desc = `{plrName} has restored the map.`, - }) - end - }; - - 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 - - local action = string.lower(args[1]) - local class = args[2] or "LocalScript" - local name = args[3] - - 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 - - if action == "create" then - assert(args[1] and args[2] and args[3], "Missing arguments") - local code = args[4] or " " - - 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 - - local wrapped,scr = Core.NewScript(class,code,false,true) - - sb[class][name] = { - Wrapped = wrapped; - Script = scr; - } - - if args[4] then - Functions.Hint(`Created {class} {name} and appended text`, {plr}) - else - Functions.Hint(`Created {class} {name}`, {plr}) - end - 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 - 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 - 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 - 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 - 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 - 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 i, v in sb.LocalScript do - table.insert(tab, {Text = `LocalScript: {i}`, Desc = `Running: {v.Script.Disabled}`}) - 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 - - 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 - - - Remote.MakeGui(plr,"List",{ - Title = "Starter Scripts"; - Tab = result; - }) - end - }; - - - 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!") - - 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 - }; - - 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 - }; - - 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 - end - }; - - 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 - }; - - 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 - }; - - 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 - }; - - 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 - }; - - 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 - }; - - 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 - end - }; - - 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 - }; - - 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 title = service.BroadcastFilter(args[2], plr) - assert(title == args[2], "Title was filtered: "..title) - - local msg = service.BroadcastFilter(args[3], plr) - assert(msg == args[3], "Message was filtered: "..msg) - - for _, v in service.GetPlayers(plr, args[1], { - IsKicking = true; - NoFakePlayer = false; - }) - do - if not Admin.CheckAuthority(plr, v, "custom-kick") then - continue - 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 - - local promptGui = Deps.Assets.RobloxPromptGui:Clone() - promptGui.promptOverlay.ErrorPrompt.TitleFrame.ErrorTitle.Text = title - promptGui.promptOverlay.ErrorPrompt.MessageArea.ErrorFrame.ErrorMessage.Text = msg - promptGui.Parent = plrgui - - 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" - }) - - local nlogs = #logs - if nlogs > Logs.OldCommandLogsLimit then - table.remove(logs, nlogs) - end - - return logs - end) - end - - Functions.Shutdown(args[1]) - end - }; - - 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 - }; - - 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.Name) 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 - }; - - 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 = Settings.Prefix; - }) - 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 - }; - - 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") - - local username = select(2, xpcall(function() - return service.Players:GetNameFromUserIdAsync(userId) - end, function() return args[2] end)) - - if service.Players:GetPlayerByUserId(userId) then - error("You cannot disguise as this player (currently in server)") - end - - Commands.Char.Function(plr, args) - Commands.DisplayName.Function(plr, {args[1], username}) - - 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 - if ChatService then - ChatService:RemoveSpeaker(Variables.DisguiseBindings[v.UserId].TargetUsername) - ChatService:UnregisterProcessCommandsFunction(`Disguise_{v.Name}`) - end - end - - Variables.DisguiseBindings[v.UserId] = { - TargetUsername = username; - Rename = v.CharacterAppearanceLoaded:Connect(function(char) - Commands.DisplayName.Function(v, {v.Name, username}) - end); - } - - 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 - }; - - 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/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index 3343588c6e..93715fec68 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -154,7 +154,7 @@ return function(Vargs, env) --// Apparently Rojo doesn't handle mesh parts very well, so I'm loading this remotely (using require to bypass insertservice restrictions) --// The model is free to take so feel free to that 👍 --// Here's the URL https://www.roblox.com/library/7679952474/Adonis-Assets-Module - if not gerald then -- TODO: Add gerald to deps and remove require, I think the Rojo plugin (up to date) now supports loading + if not gerald then -- TODO: Add gerald to deps and remove require, I think the Rojo plugin (up to date) now supports loading warn("Requiring Assets Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/7679952474/Adonis-Assets-Module"}) gerald = require(7679952474).Gerald --// This apparently caches, so don't delete anything else future usage breaks end @@ -429,7 +429,9 @@ return function(Vargs, env) AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local size = tonumber(args[2]) or 19 + assert(size >= 10, "Pixel size too small (< 10)") local dist = tonumber(args[3]) or 100 + assert(dist <= 10_000, "Render distance too large (> 10,000)") for i, v in service.GetPlayers(plr, args[1]) do Remote.MakeGui(v, "Effect", { Mode = "Pixelize"; @@ -626,7 +628,7 @@ return function(Vargs, env) TorsoColor = BrickColor.new("Artichoke").Color, Face = math.random(1, 3) == 3 and 173789114 or 133360789, } - + local ActionProperties = { Speed = args[2] or nil, Health = args[3] or nil, @@ -644,7 +646,7 @@ return function(Vargs, env) end task.defer(humanoid.ApplyDescription, humanoid, description, Enum.AssetTypeVerification.Always) - + if ActionProperties.Speed then humanoid.WalkSpeed = ActionProperties.Speed end if ActionProperties.Jumppower then humanoid.JumpPower = ActionProperties.Jumppower end if ActionProperties.Health then humanoid.MaxHealth = ActionProperties.Health; humanoid.Health = ActionProperties.Health end @@ -2707,7 +2709,56 @@ return function(Vargs, env) end end elseif human.RigType == Enum.HumanoidRigType.R15 then - Remote.MakeGui(plr, "Output", {Title = "Nonfunctional"; Message = `This command does not yet support R15.`; Color = Color3.new(1,1,1)}) + if plr.Character:FindFirstChild("Shirt") then + plr.Character.Shirt.Parent = plr.Character.HumanoidRootPart + end + if plr.Character:FindFirstChild("Pants") then + plr.Character.Pants.Parent = plr.Character.HumanoidRootPart + end + local char, uppertorso, lowertorso, ca1, ca2 = plr.Character, plr.Character:FindFirstChild("UpperTorso"), plr.Character:FindFirstChild("LowerTorso"), CFrame.Angles(0, 0, 0), CFrame.Angles(0, 0, 0) + local head = char:FindFirstChild("Head") + + uppertorso.Transparency = 1 + lowertorso.Transparency = 1 + + for _, v in uppertorso:GetChildren() do + if v:IsA("Motor6D") then + local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) + end + end + + for _, v in lowertorso:GetChildren() do + if v:IsA("Motor6D") then + local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) + end + end + + head.Neck.C0 = CFrame.new(0, -.5, -2) * CFrame.Angles(0, 0, 0) + + char.RightUpperArm["RightShoulder"].C0 = CFrame.new(.5, -1, -1.5) * ca1 + char.LeftUpperArm["LeftShoulder"].C0 = CFrame.new(-.5, -1, -1.5) * ca2 + char.RightUpperLeg["RightHip"].C0 = CFrame.new(1, -0.3, 1.5) * ca1 + char.LeftUpperLeg["LeftHip"].C0 = CFrame.new(-1, -0.3, 1.5) * ca2 + local st = service.New("Seat", { + Name = "Adonis_Torso", + TopSurface = 0, + BottomSurface = 0, + Size = Vector3.new(3, 1, 4), + }) + + local attachment = service.New("Attachment", {Parent = st}) + local bf = service.New("VectorForce", {Force = Vector3.new(0, 2e3, 0), Parent = st, Attachment0 = attachment}) + + st.CFrame = uppertorso.CFrame + st.Parent = char + + Functions.MakeWeld(uppertorso, st, CFrame.new(), CFrame.new(0, .5, 0)) + + for _, v in char:GetDescendants() do + if v:IsA("BasePart") then + v.BrickColor = BrickColor.new("Brown") + end + end end end end @@ -3326,29 +3377,29 @@ return function(Vargs, env) torso.Anchored = true torso.BottomSurface = 0 torso.TopSurface = 0 - + for _, v in char:GetChildren() do if v:IsA("BasePart") then v.Anchored = true end end - + local function size(part) for _, v in part:GetChildren() do if (v:IsA("Weld") or v:IsA("Motor") or v:IsA("Motor6D")) and v.Part1 and v.Part1:IsA("Part") then local p1 = v.Part1 local c0 = {v.C0:components()} local c1 = {v.C1:components()} - + c0[3] = c0[3]*num c1[3] = c1[3]*num - + p1.Anchored = true v.Part1 = nil - + v.C0 = CFrame.new(unpack(c0)) v.C1 = CFrame.new(unpack(c1)) - + if p1.Name ~= "Head" and p1.Name ~= "Torso" then p1.Size = Vector3.new(p1.Size.X, p1.Size.Y, num) elseif p1.Name ~= "Torso" then @@ -3359,9 +3410,9 @@ return function(Vargs, env) m.Part1.Anchored = true end end - + p1.Size = Vector3.new(p1.Size.X, p1.Size.Y, num) - + for _, m in p1:GetChildren() do if m:IsA("Weld") then m.Part0 = p1 @@ -3369,15 +3420,15 @@ return function(Vargs, env) end end end - + if v.Parent == torso then p1.BottomSurface = 0 p1.TopSurface = 0 end - + p1.Anchored = false v.Part1 = p1 - + if v.Part0 == torso then table.insert(welds, v) p1.Anchored = true @@ -3389,24 +3440,24 @@ return function(Vargs, env) size(v) end end - + size(char) - + torso.Size = Vector3.new(torso.Size.X, torso.Size.Y, num) - + for i, v in welds do v.Part0 = torso v.Part1.Anchored = false end - + for i, v in char:GetChildren() do if v:IsA("BasePart") then v.Anchored = false end end - + Functions.MakeWeld(root, torso, CFrame.new(), CFrame.new()) - + local cape = char:FindFirstChild("ADONIS_CAPE") if cape then cape.Size = cape.Size*num @@ -4733,7 +4784,7 @@ return function(Vargs, env) AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) for i, v in service.GetPlayers(plr, args[1]) do - Admin.RunCommand(`{Settings.Prefix}char`, v.Name, "userid-51310503") + Admin.RunCommand(`{Settings.Prefix}char`, v.Name, "id-51310503") end end }; @@ -5029,7 +5080,7 @@ return function(Vargs, env) local humanoid = character:FindFirstChildOfClass("Humanoid") local isR15 = humanoid and humanoid.RigType == Enum.HumanoidRigType.R15 or false local relativeSize = head.Size / (isR15 and Vector3.new(1.2, 1.2, 1.2) or Vector3.new(2, 1, 1)) - local partsColor = ({head.Color:ToHSV()})[3] < 0.26 and BrickColor.new("Lily White") or BrickColor.new("Black") + local partsColor = ({head.Color:ToHSV()})[3] < 0.26 and BrickColor.new("Lily white") or BrickColor.new("Black") local sound = head:FindFirstChild("ADONIS_SOUND") or Instance.new("Sound") sound.SoundId = `rbxassetid://{id}` diff --git a/MainModule/Server/Commands/HeadAdmins.luau b/MainModule/Server/Commands/HeadAdmins.luau index acddf436f0..b1dea981cf 100644 --- a/MainModule/Server/Commands/HeadAdmins.luau +++ b/MainModule/Server/Commands/HeadAdmins.luau @@ -102,7 +102,7 @@ return function(Vargs, env) do Functions.LogAdminAction(plr, "Un-Time Ban", v.Name, "Removed from timeban list") Functions.Hint( - if Admin.RemoveTimeBan(v.Name) + if Admin.RemoveTimeBan(v) then `{service.FormatPlayer(v, true)} has been un-time-banned` else `{service.FormatPlayer(v, true)} is not currently time-banned`, {plr} @@ -153,7 +153,7 @@ return function(Vargs, env) do Functions.LogAdminAction(plr, "Unbanned", v.Name, "N/A") Functions.Hint( - if Admin.RemoveBan(v.Name, true) + if Admin.RemoveBan(v, true) then `{service.FormatPlayer(v, true)} has been unbanned from the game` else `{service.FormatPlayer(v, true)} is not currently banned`, {plr} diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index 28ac795b70..6e5391f464 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -292,7 +292,7 @@ return function(Vargs, env) Commands = {"cn", "customsmallmessage", "cnmessage"}; Args = {"title", "message"}; Filter = true; - Description = `Same as {Settings.Prefix}n but says whatever you want the title to be instead of your name.`; + Description = `Same as {Functions.GetMainPrefix()}n but says whatever you want the title to be instead of your name.`; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) Functions.Notify(service.BroadcastFilter(assert(args[1], "Missing title"), plr), service.BroadcastFilter(assert(args[2], "Missing message") , plr), service.GetPlayers()) @@ -377,7 +377,7 @@ return function(Vargs, env) Remote.RemoveGui(v, "Notify") Functions.Notify(`Warning from {service.FormatPlayer(plr)}`, reason, {v}) - Functions.Notification("Notification", `Warned {service.FormatPlayer(v)}`, {plr}, 5, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}warnings {v.Name}')`)) + Functions.Notification("Notification", `Warned {service.FormatPlayer(v)}`, {plr}, 5, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Functions.GetMainPrefix()}warnings {v.Name}')`)) end end end @@ -416,7 +416,7 @@ return function(Vargs, env) Core.CrossServer("RemovePlayer", v.Name, `Warning from {service.FormatPlayer(plr)}`, reason) end - Functions.Notification("Notification", `Kick-warned {service.FormatPlayer(v)}`, {plr}, 5, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}warnings {v.Name}')`)) + Functions.Notification("Notification", `Kick-warned {service.FormatPlayer(v)}`, {plr}, 5, "MatIcons://Shield", Core.Bytecode(`client.Remote.Send('ProcessCommand','{Functions.GetMainPrefix()}warnings {v.Name}')`)) end end end @@ -725,7 +725,7 @@ return function(Vargs, env) for k, t in v.Backpack:GetChildren() do t.Parent = tools end - Admin.RunCommand(`{Settings.Prefix}name`, v.Name, `-AFK-_{service.FormatPlayer(v)}_-AFK-`) + Admin.RunCommand(`{Functions.GetMainPrefix()}name`, v.Name, `-AFK-_{service.FormatPlayer(v)}_-AFK-`) local torso = v.Character.HumanoidRootPart local pos = torso.CFrame local running=true @@ -738,7 +738,7 @@ return function(Vargs, env) for k, t in tools:GetChildren() do t.Parent = v.Backpack end - Admin.RunCommand(`{Settings.Prefix}unname`, v.Name) + Admin.RunCommand(`{Functions.GetMainPrefix()}unname`, v.Name) event:Disconnect() end) repeat torso.CFrame = pos wait() until not v or not v.Character or not torso or not running or not torso.Parent @@ -811,7 +811,7 @@ return function(Vargs, env) Prefix = Settings.Prefix; Commands = {"fullgod", "totalgod"}; Args = {"player"}; - Description = `Same as {server.Settings.Prefix}god, but also provides blast protection`; + Description = `Same as {Functions.GetMainPrefix()}god, but also provides blast protection`; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) for _, v in service.GetPlayers(plr, args[1]) do @@ -1243,7 +1243,7 @@ return function(Vargs, env) TitleButtons = { { Text = ""; - OnClick = Core.Bytecode(`client.Remote.Send('ProcessCommand','{Settings.Prefix}tools')`); + OnClick = Core.Bytecode(`client.Remote.Send('ProcessCommand','{Functions.GetMainPrefix()}tools')`); Children = { { Class = "ImageLabel"; @@ -1445,7 +1445,7 @@ return function(Vargs, env) Prefix = Settings.Prefix; Commands = {"viewcam", "viewc", "camview", "watchcam", "cam"}; Args = {"camera"}; - Description = "Makes you view the target player"; + Description = "Makes you view the target camera"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) for i, v in Variables.Cameras do @@ -1594,7 +1594,7 @@ return function(Vargs, env) local command = args[3] local name = string.lower(plr.Name) assert(command, "Missing command name to repeat") - if string.lower(string.sub(command, 1, #Settings.Prefix+string.len("repeat"))) == string.lower(`{Settings.Prefix}repeat`) or string.sub(command, 1, #Settings.Prefix+string.len("loop")) == string.lower(`{Settings.Prefix}loop`) or string.find(command, `^{Settings.Prefix}loop`) or string.find(command, `^{Settings.Prefix}repeat`) then + if string.lower(string.sub(command, 1, #Functions.GetMainPrefix()+string.len("repeat"))) == string.lower(`{Settings.Prefix}repeat`) or string.sub(command, 1, #Functions.GetMainPrefix()+string.len("loop")) == string.lower(`{Settings.Prefix}loop`) or string.find(command, `^{Settings.Prefix}loop`) or string.find(command, `^{Settings.Prefix}repeat`) then error("Cannot repeat the loop command in a loop command") return end @@ -1891,7 +1891,7 @@ return function(Vargs, env) local reason = "No reason provided" local moderator = "%UNKNOWN%" - local banType = if typeof(v) == 'table' and v.BanType == "Server" then + local banType = if typeof(v) == 'table' and v. == "Server" then "SERVER" else "GLOBAL"; @@ -2116,7 +2116,7 @@ return function(Vargs, env) local data = { Tools = {}; SavedTools = {}; - Prefix = Settings.Prefix; + Prefix = Functions.GetMainPrefix(); SplitKey = Settings.SplitKey; SpecialPrefix = Settings.SpecialPrefix; } @@ -4468,7 +4468,7 @@ return function(Vargs, env) AdminLevel = "Moderators"; Function = function(plr: Player, args: {[number]:string}) Remote.MakeGui(plr, "Teams", { - CmdPrefix = Settings.Prefix; CmdPlayerPrefix = Settings.PlayerPrefix; CmdSpecialPrefix = Settings.SpecialPrefix; CmdSplitKey = Settings.SplitKey; + CmdPrefix = Functions.GetMainPrefix(); CmdPlayerPrefix = Settings.PlayerPrefix; CmdSpecialPrefix = Settings.SpecialPrefix; CmdSplitKey = Settings.SplitKey; }) end }; @@ -5414,7 +5414,8 @@ return function(Vargs, env) assert(success and productInfo, "Invalid item ID") local AssetTypeNameDescriptionOverides = { - DynamicHead = "Head" + DynamicHead = "Head"; + TShirt = "GraphicTShirt" } --local typeEnum = Enum.AvatarAssetType:FromValue(productInfo.AssetTypeId) local typeId = productInfo.AssetTypeId diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 33b54e3335..ee7ac02dbd 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -23,14 +23,25 @@ return function(Vargs, env) local cmdCount = 0 for _, cmd in Admin.SearchCommands(plr, "all") do + local cmdAliases = table.create(#cmd.Commands) + if cmd.Hidden or cmd.Disabled then continue end + for _,alias in cmd.Commands do + if #cmdAliases >= 4 and (#cmd.Commands - #cmdAliases) ~= 0 then + table.insert(cmdAliases, `and {#cmd.Commands - #cmdAliases} more...`) + break + end + end + + table.remove(cmdAliases, 1) + local permissionDesc = Admin.FormatCommandAdminLevel(cmd) table.insert(tab, { Text = Admin.FormatCommand(cmd), - Desc = `[{permissionDesc}] {cmd.Description or "(No description provided)"}`, + Desc = `[{permissionDesc}] {if #cmdAliases >= 1 then `\nAliases: {table.concat(cmdAliases, ", ")}` else ""} \n\n{cmd.Description or "(No description provided)"}`, Filter = permissionDesc }) cmdCount += 1 @@ -72,7 +83,7 @@ return function(Vargs, env) local cmd, ind for i, v in Admin.SearchCommands(plr, "all") do for _, p in v.Commands do - if (v.Prefix or "")..string.lower(p) == string.lower(args[1]) then + if (if type(v.Prefix) == "table" then v.Prefix[1] else v.Prefix or "")..string.lower(p) == string.lower(args[1]) then cmd, ind = v, i break end @@ -96,7 +107,7 @@ return function(Vargs, env) Title = "Command Info"; Icon = server.MatIcons.Info; Table = { - {Text = `Prefix: {cmd.Prefix}`, Desc = "Prefix used to run the command"}, + {Text = `Prefix: {if type(cmd.Prefix) =="table" then table.concat(cmd.Prefix, ", ") else cmd.Prefix}`, Desc = "Prefix used to run the command"}, {Text = `Commands: {SanitizeXML(table.concat(cmd.Commands, ", "))}`, Desc = "Valid default aliases for the command"}, {Text = `Arguments: {if cmdArgs == "" then "-" else SanitizeXML(cmdArgs)}`, Desc = "Parameters taken by the command"}, {Text = `Admin Level: {Admin.FormatCommandAdminLevel(cmd)}`, Desc = "Rank required to run the command"}, @@ -139,7 +150,7 @@ return function(Vargs, env) Description = "Shows you the command prefix using the :cmds command"; AdminLevel = "Players"; Function = function(plr: Player, args: {string}) - Functions.Hint(`{Settings.Prefix}cmds`, {plr}) + Functions.Hint(`{if type(Settings.Prefix) == "table" then Settings.Prefix[1] else Settings.Prefix}cmds`, {plr}) end }; @@ -556,46 +567,47 @@ return function(Vargs, env) Description = "Shows you how to use some syntax related things"; AdminLevel = "Players"; Function = function(plr: Player, args: {string}) + local Prefix = if type(Settings.Prefix) == "table" then Settings.Prefix[1] else Settings.Prefix local usage = { ""; "Mouse over things in lists to expand them"; "You can also resize windows by dragging the edges"; ""; - `Put /e in front to silence commands in chat (/e {Settings.Prefix}kill scel) or enable chat command hiding in client settings`; + `Put /e in front to silence commands in chat (/e {Prefix}kill scel) or enable chat command hiding in client settings`; `Player commands can be used by anyone, these commands have {Settings.PlayerPrefix} infront, such as {Settings.PlayerPrefix}info and {Settings.PlayerPrefix}rejoin`; ""; `――――― Player Selectors ―――――`; - `Usage example: {Settings.Prefix}kill {Settings.SpecialPrefix}all (where {Settings.SpecialPrefix}all is the selector)`; + `Usage example: {Prefix}kill {Settings.SpecialPrefix}all (where {Settings.SpecialPrefix}all is the selector)`; `{Settings.SpecialPrefix}me - Yourself`; `{Settings.SpecialPrefix}all - Everyone in the server`; `{Settings.SpecialPrefix}admins - All admins in the server`; `{Settings.SpecialPrefix}nonadmins - Non-admins (normal players) in the server`; `{Settings.SpecialPrefix}others - Everyone except yourself`; `{Settings.SpecialPrefix}random - A random person in the server excluding those removed with -SELECTION`; - `@USERNAME - Targets a specific player with that exact username Ex: {Settings.Prefix}god @Sceleratis would give a player with the username 'Sceleratis' god powers`; - `#NUM - NUM random players in the server {Settings.Prefix}ff #5 will ff 5 random players excluding those removed with -SELECTION.`; + `@USERNAME - Targets a specific player with that exact username Ex: {Prefix}god @Sceleratis would give a player with the username 'Sceleratis' god powers`; + `#NUM - NUM random players in the server {Prefix}ff #5 will ff 5 random players excluding those removed with -SELECTION.`; `{Settings.SpecialPrefix}friends - Your friends who are in the server`; - `%TEAMNAME - Members of the team TEAMNAME Ex: {Settings.Prefix}kill %raiders`; + `%TEAMNAME - Members of the team TEAMNAME Ex: {Prefix}kill %raiders`; `$GROUPID - Members of the group with ID GROUPID (number in the Roblox group webpage URL)`; - `-SELECTION - Inverts the selection, ie. will remove SELECTION from list of players to run command on. {Settings.Prefix}kill all,-%TEAM will kill everyone except players on TEAM`; - `+SELECTION - Readds the selection, ie. will readd SELECTION from list of players to run command on. {Settings.Prefix}kill all,-%TEAM,+Lethalitics will kill everyone except players on TEAM but also Lethalitics`; - `radius-NUM -- Anyone within a NUM-stud radius of you. {Settings.Prefix}ff radius-5 will ff anyone within a 5-stud radius of you.`; + `-SELECTION - Inverts the selection, ie. will remove SELECTION from list of players to run command on. {Prefix}kill all,-%TEAM will kill everyone except players on TEAM`; + `+SELECTION - Readds the selection, ie. will readd SELECTION from list of players to run command on. {Prefix}kill all,-%TEAM,+Lethalitics will kill everyone except players on TEAM but also Lethalitics`; + `radius-NUM -- Anyone within a NUM-stud radius of you. {Prefix}ff radius-5 will ff anyone within a 5-stud radius of you.`; ""; `――――― Repetition ―――――`; - `Multiple player selections - {Settings.Prefix}kill me,noob1,noob2,{Settings.SpecialPrefix}random,%raiders,$123456,{Settings.SpecialPrefix}nonadmins,-scel`; - `Multiple Commands at a time - {Settings.Prefix}ff me {Settings.BatchKey} {Settings.Prefix}sparkles me {Settings.BatchKey} {Settings.Prefix}rocket jim`; - `You can add a delay if you want; {Settings.Prefix}ff me {Settings.BatchKey} !wait 10 {Settings.BatchKey} {Settings.Prefix}m hi we waited 10 seconds`; - `{Settings.Prefix}repeat 10(how many times to run the cmd) 1(how long in between runs) {Settings.Prefix}respawn jim`; + `Multiple player selections - {Prefix}kill me,noob1,noob2,{Settings.SpecialPrefix}random,%raiders,$123456,{Settings.SpecialPrefix}nonadmins,-scel`; + `Multiple Commands at a time - {Prefix}ff me {Settings.BatchKey} {Prefix}sparkles me {Settings.BatchKey} {Prefix}rocket jim`; + `You can add a delay if you want; {Prefix}ff me {Settings.BatchKey} !wait 10 {Settings.BatchKey} {Prefix}m hi we waited 10 seconds`; + `{Prefix}repeat 10(how many times to run the cmd) 1(how long in between runs) {Prefix}respawn jim`; ""; `――――― Reference Info ―――――`; - `{Settings.Prefix}cmds for a list of available commands`; - `{Settings.Prefix}cmdinfo <command> for detailed info about a specific command`; + `{Prefix}cmds for a list of available commands`; + `{Prefix}cmdinfo <command> for detailed info about a specific command`; `{Settings.PlayerPrefix}brickcolors for a list of BrickColors`; `{Settings.PlayerPrefix}materials for a list of materials`; ""; - `{Settings.Prefix}capes for a list of preset admin capes`; - `{Settings.Prefix}musiclist for a list of preset audios`; - `{Settings.Prefix}insertlist for a list of insertable assets using {Settings.Prefix}insert`; + `{Prefix}capes for a list of preset admin capes`; + `{Prefix}musiclist for a list of preset audios`; + `{Prefix}insertlist for a list of insertable assets using {Prefix}insert`; } Remote.MakeGui(plr, "List", { Title = "Usage"; @@ -926,7 +938,7 @@ return function(Vargs, env) IsDonor = Admin.CheckDonor(v); GameData = gameData; IsServerOwner = v.UserId == game.PrivateServerOwnerId; - CmdPrefix = Settings.Prefix; + CmdPrefix = Functions.GetMainPrefix(); CmdSplitKey = Settings.SplitKey; OnlineFriends = Remote.Get(v, "Function", "GetFriendsOnline"); }) @@ -1007,7 +1019,7 @@ return function(Vargs, env) ServerAge = service.FormatTime(os.time() - server.ServerStartTime); ServerInternetInfo = serverInfo; Refreshables = Logs.ListUpdaters.ServerDetails(plr); - CmdPrefix = Settings.Prefix; + CmdPrefix = if type(Settings.Prefix) == "table" then Settings.Prefix[1] else Settings.Prefix, CmdPlayerPrefix = Settings.PlayerPrefix; SplitKey = Settings.SplitKey; }) diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 0ad9ff97ae..551cdbaf8f 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -1193,9 +1193,16 @@ return function(Vargs, GetEnv) for ind, data in Commands do if type(data) == "table" then for i,cmd in data.Commands do - if data.Prefix == "" then Admin.BlankPrefix = true end - tempPrefix[data.Prefix] = true - tempTable[string.lower(data.Prefix..cmd)] = ind + 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 + end end end end @@ -1232,13 +1239,27 @@ return function(Vargs, GetEnv) end for _, v in data.Commands do - if not blacklistedCommands["/"..data.Prefix..v] then - if not command1 then - command1 = "/"..data.Prefix..v - else - command2 = "/"..data.Prefix..v + 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 + end + end if command1 then @@ -1336,7 +1357,7 @@ return function(Vargs, GetEnv) FormatCommand = function(command, cmdn) return table.concat({ - (command.Prefix or ""), + (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 "" diff --git a/MainModule/Server/Core/Anti.luau b/MainModule/Server/Core/Anti.luau index accd3a746d..fbdb70ebd4 100644 --- a/MainModule/Server/Core/Anti.luau +++ b/MainModule/Server/Core/Anti.luau @@ -187,7 +187,7 @@ return function(Vargs, GetEnv) if Settings.AENotifs == true or Settings.ExploitNotifications == true then -- AENotifs for old loaders local debounceIndex = `{action}{player}{info}` - if os.clock() < antiNotificationResetTick then + if os.clock() > antiNotificationResetTick then antiNotificationDebounce = {} antiNotificationResetTick = os.clock() + 60 end @@ -201,6 +201,8 @@ return function(Vargs, GetEnv) return end + antiNotificationDebounce[debounceIndex] += 1 + for _, plr in service.Players:GetPlayers() do if Admin.GetLevel(plr) >= Settings.Ranks.Moderators.Level then Functions.Notification("Notification", string.format( diff --git a/MainModule/Server/Core/Commands.luau b/MainModule/Server/Core/Commands.luau index c8edb07110..e9b9ad82b8 100644 --- a/MainModule/Server/Core/Commands.luau +++ b/MainModule/Server/Core/Commands.luau @@ -34,7 +34,7 @@ return function(Vargs, GetEnv) t = server.Typechecker; local ValidateCommandDefinition = t.interface({ - Prefix = t.string, + Prefix = t.union(t.string, t.array(t.string)), Commands = t.array(t.string), Description = t.string, AdminLevel = t.union(t.string, t.number, t.nan, t.array(t.union(t.string, t.number, t.nan))), @@ -99,7 +99,13 @@ return function(Vargs, GetEnv) Admin.PrefixCache[cmd.Prefix] = true for _, v in cmd.Commands do - Admin.CommandCache[string.lower(cmd.Prefix..v)] = ind + if type(cmd.Prefix) == "table" then + for _,p in cmd.Prefix do + Admin.CommandCache[string.lower(p..v)] = ind + end + else + Admin.CommandCache[string.lower(cmd.Prefix..v)] = ind + end end cmd.Args = cmd.Args or cmd.Arguments or {} diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index f8b8fcdd38..5f191d1429 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1289,9 +1289,11 @@ return function(Vargs, GetEnv) local data = GetData(tData.TableKey) if data then --// TODO: Possibly find a better way to "batch" TableUpdates to prevent script exhaustion + local isStudio = service.RunService:IsStudio() -- Studio lag workaround for loading larger data such as BannedList + local isHugeTable = #data > 1000 for i = 1, #data do LoadData("TableUpdate", data[i]) - if i % 250 == 0 then + if (isStudio and isHugeTable and i % 25 == 0) or i % 250 == 0 then task.wait() end end diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 3cfb23da83..f137444a85 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -355,7 +355,7 @@ return function(Vargs, GetEnv) return; end - for i = 1,num do + for i = 1, math.min(num, #service.Players:GetPlayers()) do Functions.PlayerFinders.random.Function(msg, plr, ...) end end @@ -1337,7 +1337,7 @@ return function(Vargs, GetEnv) table.insert(tab,result) end end - + return tab end; @@ -1405,7 +1405,11 @@ return function(Vargs, GetEnv) return AllGrabbedPlayers end; - GetUserIdFromNameAsync = function(name) + GetUserIdFromNameAsync = function(name: string | Player) + if type(name) == "userdata" and name:IsA("Player") then + return name.UserId + end + local cache = Admin.UserIdCache[name] if not cache then local success, UserId = pcall(service.Players.GetUserIdFromNameAsync, service.Players, name) @@ -1419,7 +1423,11 @@ return function(Vargs, GetEnv) return cache end; - GetNameFromUserIdAsync = function(id) + GetNameFromUserIdAsync = function(id: number | Player) + if type(id) == "userdata" and id:IsA("Player") then + return id.Name + end + local cache = Admin.UsernameCache[id] if not cache then local success, Username = pcall(service.Players.GetNameFromUserIdAsync, service.Players, id) @@ -1656,5 +1664,11 @@ return function(Vargs, GetEnv) end return if allowNil then nil else BrickColor.random() end; - }; + + GetMainPrefix = function() + if type(Settings.Prefix) == "table" then return Settings.Prefix[1] else return Settings.Prefix end + end; + } + + end diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 311492d0c2..8d36db06a3 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -88,16 +88,18 @@ return function(Vargs, GetEnv) log.Time = os.time() end - if tab.__meta == "DLL" then - tab:AddToStartAndRemoveEndIfEnd(log, Logs.MaxLogs) - else - table.insert(tab, 1, log) - if #tab > tonumber(Logs.MaxLogs) then - table.remove(tab, #tab) + if tab then + if tab.__meta == "DLL" then + tab:AddToStartAndRemoveEndIfEnd(log, Logs.MaxLogs) + else + table.insert(tab, 1, log) + if #tab > tonumber(Logs.MaxLogs) then + table.remove(tab, #tab) + end end + + service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end - - service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end; -- // Preliminary support for oldlog encryption diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index f7243ea007..dc5132804d 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -32,6 +32,21 @@ return function(Vargs, GetEnv) Variables.ChatCreateRobloxCommands = Settings.ChatCreateRobloxCommands == nil and Variables.ChatCreateRobloxCommands or Settings.ChatCreateRobloxCommands Variables.DisableRejoinAtMaxPlayers = Settings.DisableRejoinAtMaxPlayers or Variables.DisableRejoinAtMaxPlayers + for _, v in Settings.Cameras or {} do + local cam = service.New("Part", { + Parent = workspace; + Name = `Camera: {v.Name}`; + Position = v.Position; + Anchored = true; + CanCollide = false; + Locked = true; + Size = Vector3.new(1, 1, 1); + Transparency = 1; + }) + + table.insert(Variables.Cameras, {Brick = cam, Name = v.Name}) + end + for _, v in Settings.MusicList or {} do table.insert(Variables.MusicList, v) end for _, v in Settings.InsertList or {} do table.insert(Variables.InsertList, v) end for _, v in Settings.CapeList or {} do table.insert(Variables.Capes, v) end diff --git a/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json b/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json new file mode 100644 index 0000000000..4c86de4ed5 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "BindableEvent" +} diff --git a/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json b/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/BotBrain.rbxmx b/MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua similarity index 80% rename from MainModule/Server/Dependencies/Assets/BotBrain.rbxmx rename to MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua index 0db12f9a55..ad580461d6 100644 --- a/MainModule/Server/Dependencies/Assets/BotBrain.rbxmx +++ b/MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua @@ -1,18 +1,4 @@ - - true - null - nil - - - - 0 - false - true - - BotBrain - 1 - {57C75EF3-A7BD-4721-AC2E-EF182347E0A6} - - -1 - - - - - - 0 - false - Event - -1 - - - - - \ No newline at end of file +end) diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua similarity index 60% rename from MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx rename to MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua index a1602fc675..6c2fb848b4 100644 --- a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua @@ -1,15 +1,4 @@ - - true - null - nil - - - - true - - ClickTeleport - {BDAA343E-7C81-459C-A2DB-06B5F4C8C90A} - - -1 - - - - - - Mode - -1 - - - - - - - - Target - -1 - - - - - - +humanoid.Died:Connect(function() tool:Destroy() end) diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx b/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx deleted file mode 100644 index af0d4db9a1..0000000000 --- a/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx +++ /dev/null @@ -1,60 +0,0 @@ - - true - null - nil - - - - true - - Glitcher - {53875408-B9EB-48D7-AF56-6C82B2C7F77E} - - -1 - - - - - - Num - -1 - - 3214.431999999999789 - - - - - - Type - -1 - - - - - - diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json b/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json new file mode 100644 index 0000000000..9381de9457 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "NumberValue", + "Properties": { + "Value": 3214.431999999999789 + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json b/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua b/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua new file mode 100644 index 0000000000..58f18b99b9 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua @@ -0,0 +1,26 @@ +task.wait() +local torso = script.Parent +local posed = false +local type = script:WaitForChild("Type").Value +local int = tonumber(script:WaitForChild("Num").Value) or 50 + +game:GetService("RunService").RenderStepped:Connect(function() + if type == "ghost" then + torso.CFrame += Vector3.new(tonumber(int) * (posed and 4 or -2), 0, 0) + elseif type == "trippy" then + torso.CFrame *= CFrame.new(tonumber(int) * (posed and 4 or -2), 0, 0) + elseif type == "vibrate" then + local num = math.random(1,4) + + if num == 1 then + torso.CFrame *= CFrame.new(tonumber(int) * 2, 0, 0) + elseif num == 2 then + torso.CFrame *= CFrame.new(-tonumber(int) * 2, 0, 0) + elseif num == 3 then + torso.CFrame *= CFrame.new(0, 0, -tonumber(int) * 2) + elseif num == 4 then + torso.CFrame *= CFrame.new(0 ,0, tonumber(int) * 2) + end + end + posed = not posed +end) diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json b/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx deleted file mode 100644 index c37215ed6a..0000000000 --- a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx +++ /dev/null @@ -1,44 +0,0 @@ - - true - null - nil - - - - true - - Sfling - {61F447BE-6192-4214-8938-59EF4489FA89} - - -1 - - - - - - Strength - -1 - - 0 - - - - diff --git a/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json b/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json new file mode 100644 index 0000000000..e21ad5d0af --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "NumberValue", + "Properties": { + "Value": 0 + } +} diff --git a/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua b/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua new file mode 100644 index 0000000000..49ed248e3b --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua @@ -0,0 +1,19 @@ +task.wait() +local cam = workspace.CurrentCamera +local torso = script.Parent +local humanoid = torso.Parent:FindFirstChildOfClass("Humanoid") +local strength = script:WaitForChild("Strength").Value + +for i = 1, 100 do + task.wait(0.1) + humanoid.Sit = true + local ex = Instance.new("Explosion") + ex.Position = torso.Position + Vector3.new(math.random(-5, 5), -10, math.random(-5, 5)) + ex.BlastRadius = 35 + ex.BlastPressure = strength + ex.ExplosionType = Enum.ExplosionType.NoCraters--Enum.ExplosionType.Craters + ex.DestroyJointRadiusPercent = 0 + ex.Archivable = false + ex.Parent = cam +end +script:Destroy() diff --git a/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json b/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index c19cbef1d6..d3eceb87d0 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -36,7 +36,7 @@ local descs = {}; --// Contains settings descriptions Numbers do not use quotes. setting = 56 - This green block of text you are reading is called a comment. It's like a message + This block of text you are reading is called a comment. It's like a message from the programmer to anyone who reads their stuff. Anything in a comment will not be seen by Luau when the script is run. @@ -75,7 +75,7 @@ local descs = {}; --// Contains settings descriptions settings.HeadAdmins = {"Group:181:121"} See? Not so hard is it? - If I wanted to add group 181 and all ranks in it to the :slock whitelist I would do; + If I wanted to add group 181 and all ranks in it to the ;slock whitelist I would do; settings.Whitelist = {"Group:181";} I can do the above if I wanted to give everyone in a group admin for any of the other admin tables @@ -85,11 +85,11 @@ local descs = {}; --// Contains settings descriptions --// Command Permissions You can set the permission level for specific commands using setting.Permissions - If I wanted to make it so only HeadAdmins+ can use :ff player then I would do: + If I wanted to make it so only HeadAdmins+ can use ;ff player then I would do: settings.Permissions = {"ff:HeadAdmins"} - ff is the Command ":ff scel" and HeadAdmins is the NewLevel + ff is the Command ";ff scel" and HeadAdmins is the NewLevel Built-In Permissions Levels: Players - 0 @@ -99,7 +99,7 @@ local descs = {}; --// Contains settings descriptions Creators - 900 Note that when changing command permissions you MUST include the prefix; - So if you change the prefix to $ you would need to do $ff instead of :ff + So if you change the prefix to $ you would need to do $ff instead of ;ff --// Trello @@ -115,12 +115,12 @@ local descs = {}; --// Contains settings descriptions 6. Congrats! The board is ready to be used; 7. Create a list and add cards to it; - - You can view lists in-game using :viewlist ListNameHere + - You can view lists in-game using ;viewlist ListNameHere Lists: Moderators - Card Format: Same as settings.Moderators Admins - Card Format: Same as settings.Admins - HeadAdmins - Card Format: Same as settings.HeadAdmins + HeadAdmins - Card Format: Same as settings.HeadAdmins Creators - Card Format: Same as settings.Creators Banlist - Card Format: Same as settings.Banned Mutelist - Card Format: Same as settings.Muted @@ -128,7 +128,7 @@ local descs = {}; --// Contains settings descriptions Whitelist - Card Format: Same as settings.Whitelist Permissions - Card Format: Same as settings.Permissions Music - Card Format: SongName:AudioID - Commands - Card Format: Command (eg. :ff bob) + Commands - Card Format: Command (eg. ;ff bob) Card format refers to how card names should look @@ -140,14 +140,13 @@ settings.HideScript = true -- When the game starts the Adonis_Loader model settings.DataStore = "Adonis_1" -- DataStore the script will use for saving data; Changing this will lose any saved data settings.DataStoreKey = "CHANGE_THIS" -- CHANGE THIS TO ANYTHING RANDOM! Key used to encrypt all datastore entries; Changing this will lose any saved data settings.DataStoreEnabled = true -- Disable if you don't want to load settings and admins from the datastore; PlayerData will still save -settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers +settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers -settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored -settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the :give command (useful if your tools are organized into multiple folders) +settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored +settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders) settings.Theme = "Default" -- UI theme; settings.MobileTheme = "Mobilius" -- Theme to use on mobile devices; Some UI elements are disabled -settings.DefaultTheme = "Default" -- Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. --[[ **HOW TO ADD ADMINISTRATORS:** @@ -158,7 +157,7 @@ settings.DefaultTheme = "Default" -- Theme to be used as a replacement for "Defa settings.Ranks = { ["Moderators"] = { Level = 100; - Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} + Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID"; "Subscription:SubscriptionId";} } } @@ -200,49 +199,59 @@ settings.Ranks = { --// Use the below table to set command permissions; Commented commands are included for example purposes settings.Permissions = { - -- "ff:HeadAdmins"; --// Changes :ff to HeadAdmins and higher (HeadAdmins = Level 300 by default) - -- "kill:300"; --// Changes :kill to level 300 and higher (Level 300 = HeadAdmins by default) - -- "ban:200,300" --// Makes it so :ban is only usable by levels 200 and 300 specifically (nothing higher or lower or in between) + -- "ff:HeadAdmins"; --// Changes ;ff to HeadAdmins and higher (HeadAdmins = Level 300 by default) + -- "kill:300"; --// Changes ;kill to level 300 and higher (Level 300 = HeadAdmins by default) + -- "ban:200,300" --// Makes it so ;ban is only usable by levels 200 and 300 specifically (nothing higher or lower or in between) }; -- Format: {"Command:NewLevel"; "Command:Customrank1,Customrank2,Customrank3";} --// Use the below table to define "pre-set" command aliases ---// Command aliases; Format: {[":alias ..."] = ":command ..."} +--// Command aliases; Format: {[";alias ..."] = ";command ..."} settings.Aliases = { - [":examplealias "] = ":ff | :fling | :fire " --// Order arguments appear in alias string determines their required order in the command message when ran later + [";examplealias "] = ";ff | ;fling | ;fire " --// Order arguments appear in alias string determines their required order in the command message when ran later }; +settings.Cameras = { +--[[ + "Camera Name" would be the name of your camera + { + Name = "Camera Name"; + Position = Vector3.new(0, 0, 0) + } +]] +} + settings.Banned = {} -- List of people banned from the game Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Muted = {} -- List of people muted (cannot send chat messages) Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Blacklist = {} -- List of people banned from running commands Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Whitelist = {} -- People who can join if whitelist enabled Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} -settings.MusicList = {} -- List of songs to appear in the :musiclist Format: {{Name = "somesong", ID = 1234567}, {Name = "anotherone", ID = 1243562}} +settings.MusicList = {} -- List of songs to appear in the ;musiclist Format: {{Name = "somesong", ID = 1234567}, {Name = "anotherone", ID = 1243562}} settings.CapeList = {} -- List of capes Format: {{Name = "somecape", Material = "Fabric", Color = "Bright yellow", ID = 12345567, Reflectance = 1}; {etc more stuff here}} -settings.InsertList = {} -- List of models to appear in the :insertlist and can be inserted using ':insert ' Format: {{Name = "somemodel", ID = 1234567}; {Name = "anotherone", ID = 1243562}} -settings.Waypoints = {} -- List of waypoints you can teleport via ':to wp-WAYPOINTNAME' or ':teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} +settings.InsertList = {} -- List of models to appear in the ;insertlist and can be inserted using ';insert ' Format: {{Name = "somemodel", ID = 1234567}; {Name = "anotherone", ID = 1243562}} +settings.Waypoints = {} -- List of waypoints you can teleport via ';to wp-WAYPOINTNAME' or ';teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} -settings.OnStartup = {} -- List of commands ran at server start Format: {":notif TestNotif"} -settings.OnJoin = {} -- List of commands ran as player on join (ignores adminlevel) Format: {":cmds"} -settings.OnSpawn = {} -- List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",":ff me"} +settings.OnStartup = {} -- List of commands ran at server start Format: {";notif TestNotif"} +settings.OnJoin = {} -- List of commands ran as player on join (ignores adminlevel) Format: {";cmds"} +settings.OnSpawn = {} -- List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",";ff me"} -settings.SaveAdmins = true -- If true anyone you :admin or :headadmin in-game will save +settings.SaveAdmins = true -- If true anyone you ;admin or ;headadmin in-game will save settings.LoadAdminsFromDS = true -- If false, any admins saved in your DataStores will not load settings.WhitelistEnabled = false -- If true enables the whitelist/server lock; Only lets admins & whitelisted users join -settings.Prefix = ":" -- The : in :kill me +settings.Prefix = {";", ":"} -- A list of prefixes for commands, the ; in ;kill me settings.PlayerPrefix = "!" -- The ! in !donate; Mainly used for commands that any player can run; Do not make it the same as settings.Prefix -settings.SpecialPrefix = "" -- Used for things like "all", "me" and "others" (If changed to ! you would do :kill !me) -settings.SplitKey = " " -- The space in :kill me (eg if you change it to / :kill me would be :kill/me) -settings.BatchKey = "|" -- :kill me | :ff bob | :explode scel +settings.SpecialPrefix = "" -- Used for things like "all", "me" and "others" (If changed to ! you would do ;kill !me) +settings.SplitKey = " " -- The space in ;kill me (eg if you change it to / ;kill me would be ;kill/me) +settings.BatchKey = "|" -- ;kill me | ;ff bob | ;explode scel settings.ConsoleKeyCode = "Quote" -- Keybind to open the console; Rebindable per player in userpanel; KeyCodes: https://developer.roblox.com/en-us/api-reference/enum/KeyCode --// Easily add new custom commands below (without needing to create a plugin module) --// You can also use this to overwrite existing commands if you know the command's index (found in the command's respective module within the Adonis MainModule) settings.Commands = { ExampleCommand1 = { --// The index & table of the command - Prefix = Settings.Prefix; --// The prefix the command will use, this is the ':' in ':ff me' - Commands = {"examplecommand1", "examplealias1", "examplealias2"}; --// A table containing the command strings (the things you chat in-game to run the command, the 'ff' in ':ff me') - Args = {"arg1", "arg2", "etc"}; --// Command arguments, these will be available in order as args[1], args[2], args[3], etc; This is the 'me' in ':ff me' + Prefix = Settings.Prefix; --// The prefix the command will use, this is the ';' in ';ff me' + Commands = {"examplecommand1", "examplealias1", "examplealias2"}; --// A table containing the command strings (the things you chat in-game to run the command, the 'ff' in ';ff me') + Args = {"arg1", "arg2", "etc"}; --// Command arguments, these will be available in order as args[1], args[2], args[3], etc; This is the 'me' in ';ff me' Description = "Example command";--// The description of the command AdminLevel = 100; -- Moderators --// The commands minimum admin level; This can also be a table containing specific levels rather than a minimum level: {124, 152, "HeadAdmins", etc}; -- Alternative option: AdminLevel = "Moderators" @@ -264,7 +273,7 @@ settings.Commands = { settings.CommandCooldowns = { --[[ REFERENCE: - command_full_name: The name of a command (e.g. :cmds) + command_full_name: The name of a command (e.g. ;cmds) [command_full_name] = { Player = 0; @@ -282,24 +291,25 @@ settings.CommandFeedback = false -- Should players be notified when commands wi settings.CrossServerCommands = true -- Are commands which affect more than one server enabled? settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script -settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as :s) and a few other commands require this +settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as ;s) and a few other commands require this settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command -settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. +settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. settings.BanMessage = "Banned" -- Message shown to banned users upon kick -settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is :slocked -settings.SystemTitle = "System Message" -- Title to display in :sm and :bc +settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is ;slocked +settings.SystemTitle = "System Message" -- Title to display in ;sm and ;bc settings.MaxLogs = 5000 -- Maximum logs to save before deleting the oldest settings.SaveCommandLogs = true -- If command logs are saved to the datastores settings.Notification = true -- Whether or not to show the "You're an admin" and "Updated" notifications -settings.SongHint = true -- Display a hint with the current song name and ID when a song is played via :music +settings.SongHint = true -- Display a hint with the current song name and ID when a song is played via ;music settings.TopBarShift = false -- By default hints and notifications will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. +settings.DefaultTheme = "Default" -- Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. settings.HiddenThemes = {} -- Hide themes from the theme selector tab inside the userpanel. Each theme name must be the specific name such as "Mobilius" settings.Messages = {} -- A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level settings.AutoClean = false -- Will auto clean workspace of things like hats and tools settings.AutoCleanDelay = 60 -- Time between auto cleans -settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap +settings.AutoBackup = false -- Run ;backupmap automatically when the server starts. To restore the map, run ;restoremap settings.ReJail = false -- If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed settings.Console = true -- Whether the command console is enabled @@ -329,7 +339,7 @@ settings.Trello_Primary = "" -- Primary Trello board settings.Trello_Secondary = {} -- Secondary Trello boards (read-only) Format: {"BoardID";"BoardID2","etc"} settings.Trello_AppKey = "" -- Your Trello AppKey settings.Trello_Token = "" -- Trello token (DON'T SHARE WITH ANYONE!) Get API key: /1/connect?name=Trello_API_Module&response_type=token&expires=never&scope=read,write&key=YOUR_APP_KEY_HERE -settings.Trello_HideRanks = false -- If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via :admins) +settings.Trello_HideRanks = false -- If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via ;admins) --------------------- @@ -393,11 +403,10 @@ descs.DataStoreEnabled = [[ Disable if you don't want settings and admins to be descs.LocalDatastore = [[ If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers ]] descs.Storage = [[ Where things like tools are stored ]] -descs.RecursiveTools = [[ Whether tools that are included in sub-containers within settings.Storage will be available via the :give command (useful if your tools are organized into multiple folders) ]] +descs.RecursiveTools = [[ Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders) ]] descs.Theme = [[ UI theme; ]] descs.MobileTheme = [[ Theme to use on mobile devices; Mobile themes are optimized for smaller screens; Some GUIs are disabled ]] -descs.DefaultTheme = [[ Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. ]] descs.Ranks = [[ All admin permission level ranks; ]]; descs.Moderators = [[ Mods; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] @@ -406,7 +415,8 @@ descs.HeadAdmins = [[ Head Admins; Format: {"Username"; "Username:UserId"; UserI descs.Creators = [[ Anyone to be identified as a place owner; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] descs.Permissions = [[ Command permissions; Format: {"Command:NewLevel";} ]] -descs.Aliases = [[ Command aliases; Format: {[":alias ..."] = ":command ..."} ]] +descs.Aliases = [[ Command aliases; Format: {[";alias ..."] = ";command ..."} ]] +descs.Cameras = [[ Cameras; Format: {Name = "CamName", Position = Vector3.new(X, Y, Z)} ]] descs.Commands = [[ Custom commands ]] descs.Banned = [[ List of people banned from the game; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] @@ -416,22 +426,22 @@ descs.Whitelist = [[ People who can join if whitelist enabled; Format: {"Usernam descs.MusicList = [[ List of songs to appear in the script; Format: {{Name = "somesong",ID = 1234567},{Name = "anotherone",ID = 1243562}} ]] descs.CapeList = [[ List of capes; Format: {{Name = "somecape",Material = "Fabric",Color = "Bright yellow",ID = 12345567,Reflectance = 1},{etc more stuff here}} ]] descs.InsertList = [[ List of models to appear in the script; Format: {{Name = "somemodel",ID = 1234567},{Name = "anotherone",ID = 1243562}} ]] -descs.Waypoints = [[ List of waypoints you can teleport via ':to wp-WAYPOINTNAME' or ':teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} ]] +descs.Waypoints = [[ List of waypoints you can teleport via ';to wp-WAYPOINTNAME' or ';teleport PLAYER tp.WAYPOINTNAME' Format {YOURNAME1 = Vector3.new(1,2,3), YOURNAME2 = Vector(231,666,999)} ]] descs.CustomRanks = [[ List of custom AdminLevel ranks Format: {RankName = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";};} ]] -descs.OnStartup = [[ List of commands ran at server start Format: {":notif TestNotif"} ]] -descs.OnJoin = [[ List of commands ran as player on join (ignores adminlevel) Format: {":cmds"} ]] -descs.OnSpawn = [[ List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",":ff me"} ]] +descs.OnStartup = [[ List of commands ran at server start Format: {";notif TestNotif"} ]] +descs.OnJoin = [[ List of commands ran as player on join (ignores adminlevel) Format: {";cmds"} ]] +descs.OnSpawn = [[ List off commands ran as player on spawn (ignores adminlevel) Format: {"!fire Really red",";ff me"} ]] -descs.SaveAdmins = [[ If true anyone you :mod, :admin, or :headadmin in-game will save]] +descs.SaveAdmins = [[ If true anyone you ;mod, ;admin, or ;headadmin in-game will save]] descs.LoadAdminsFromDS = [[ If false, any admins saved in your DataStores will not load ]] descs.WhitelistEnabled = [[ If true enables the whitelist/server lock; Only lets admins & whitelisted users join ]] -descs.Prefix = [[ The : in :kill me ]] +descs.Prefix = [[ The ; in ;kill me ]] descs.PlayerPrefix = [[ The ! in !donate; Mainly used for commands that any player can run ]] -descs.SpecialPrefix = [[ Used for things like "all", "me" and "others" (If changed to ! you would do :kill !me) ]] -descs.SplitKey = [[ The space in :kill me (eg if you change it to / :kill me would be :kill/me) ]] -descs.BatchKey = [[ :kill me | :ff bob | :explode scel ]] +descs.SpecialPrefix = [[ Used for things like "all", "me" and "others" (If changed to ! you would do ;kill !me) ]] +descs.SplitKey = [[ The space in ;kill me (eg if you change it to / ;kill me would be ;kill/me) ]] +descs.BatchKey = [[ ;kill me | ;ff bob | ;explode scel ]] descs.ConsoleKeyCode = [[ Keybind to open the console ]] descs.HttpWait = [[ How long things that use the HttpService will wait before updating again ]] @@ -440,7 +450,7 @@ descs.Trello_Primary = [[ Primary Trello board ]] descs.Trello_Secondary = [[ Secondary Trello boards; Format: {"BoardID";"BoardID2","etc"} ]] descs.Trello_AppKey = [[ Your Trello AppKey; ]] descs.Trello_Token = [[ Trello token (DON'T SHARE WITH ANYONE!) ]] -descs.Trello_HideRanks = [[ If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via :admins) ]] +descs.Trello_HideRanks = [[ If true, Trello-assigned ranks won't be shown in the admins list UI (accessed via ;admins) ]] descs.G_API = [[ If true, allows other server scripts to access certain functions described in the API module through _G.Adonis ]] descs.G_Access = [[ If enabled, allows other scripts to access Adonis using _G.Adonis.Access; Scripts will still be able to do things like _G.Adonis.CheckAdmin(player) ]] @@ -459,22 +469,23 @@ descs.SilentCommandDenials = [[ If true, there will be no differences between th descs.OverrideChatCallbacks = [[ If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for muting ]] descs.BanMessage = [[ Message shown to banned users ]] -descs.LockMessage = [[ Message shown to people when they are kicked while the game is :slocked ]] -descs.SystemTitle = [[ Title to display in :sm ]] +descs.LockMessage = [[ Message shown to people when they are kicked while the game is ;slocked ]] +descs.SystemTitle = [[ Title to display in ;sm ]] descs.CreatorPowers = [[ Gives me creator-level admin; This is strictly used for debugging; I can't debug without access to the script and specific owner commands ]] descs.MaxLogs = [[ Maximum logs to save before deleting the oldest; Too high can lag the game ]] descs.SaveCommandLogs = [[ If command logs are saved to the datastores ]] descs.Notification = [[ Whether or not to show the "You're an admin" and "Updated" notifications ]] descs.CodeExecution = [[ Enables the use of code execution in Adonis; Scripting related and a few other commands require this ]] -descs.SongHint = [[ Display a hint with the current song name and ID when a song is played via :music ]] +descs.SongHint = [[ Display a hint with the current song name and ID when a song is played via ;music ]] descs.TopBarShift = [[ By default hints and notifs will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. ]] +descs.DefaultTheme = [[ Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] descs.Messages = [[ A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level ]] descs.AutoClean = [[ Will auto clean workspace of things like hats and tools ]] -descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run :restoremap ]] +descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run ;restoremap ]] descs.AutoCleanDelay = [[ Time between auto cleans ]] descs.PlayerList = [[ Custom playerlist ]] @@ -518,12 +529,12 @@ order = { " "; "Theme"; "MobileTheme"; - "DefaultTheme"; " "; "Ranks"; " "; "Permissions"; "Aliases"; + "Cameras"; " "; "Commands"; "Banned"; @@ -585,6 +596,7 @@ order = { "Notification"; "SongHint"; "TopBarShift"; + "DefaultTheme"; "ReJail"; ""; "AutoClean"; @@ -592,6 +604,7 @@ order = { "AutoBackup"; " "; "PlayerList"; + " "; "Console"; "Console_AdminsOnly"; " "; diff --git a/MainModule/Server/Dependencies/RebootHandler.rbxmx b/MainModule/Server/Dependencies/RebootHandler.rbxmx deleted file mode 100644 index 02ee5ff485..0000000000 --- a/MainModule/Server/Dependencies/RebootHandler.rbxmx +++ /dev/null @@ -1,113 +0,0 @@ - - true - null - nil - - - - true - - RebootHandler - {62D59941-4C6D-45EB-9E45-D4A6587DB801} - - -1 - - - - - - Mode - -1 - - - - - - - - Model - -1 - - null - - - - - - mParent - -1 - - null - - - - - - Runner - -1 - - null - - - - diff --git a/MainModule/Server/Dependencies/RebootHandler/Mode.model.json b/MainModule/Server/Dependencies/RebootHandler/Mode.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Mode.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/RebootHandler/Model.model.json b/MainModule/Server/Dependencies/RebootHandler/Model.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Model.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} diff --git a/MainModule/Server/Dependencies/RebootHandler/Runner.model.json b/MainModule/Server/Dependencies/RebootHandler/Runner.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Runner.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} diff --git a/MainModule/Server/Dependencies/RebootHandler/init.meta.json b/MainModule/Server/Dependencies/RebootHandler/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/RebootHandler/init.server.lua b/MainModule/Server/Dependencies/RebootHandler/init.server.lua new file mode 100644 index 0000000000..fa02ab72a8 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/init.server.lua @@ -0,0 +1,62 @@ +--# selene: allow(incorrect_standard_library_use) +if script.Parent then + local dTargetVal = script:WaitForChild("Runner") + local parentVal = script:WaitForChild("mParent") + local modelVal = script:WaitForChild("Model") + local modeVal = script:WaitForChild("Mode") + + warn("Reloading in 5 seconds...") + task.wait(5) + script.Parent = nil + + local dTarget = dTargetVal.Value + local tParent = parentVal.Value + local model = modelVal.Value + local mode = modeVal.Value + + local function CleanUp() + warn("TARGET DISABLED") + dTarget.Disabled = true + pcall(function() dTarget.Parent = game:GetService("ServerScriptService") end) + task.wait() + pcall(function() dTarget:Destroy() end) + + warn("TARGET DESTROYED") + task.wait() + + warn("CLEANING") + + if not table.isfrozen(_G) then + rawset(_G, "Adonis", nil) + rawset(_G, "__Adonis_MODULE_MUTEX", nil) + rawset(_G, "__Adonis_MUTEX", nil) + end + + warn("_G VARIABLES CLEARED") + + warn("MOVING MODEL") + model.Parent = tParent + end + + if mode == "REBOOT" then + warn("ATTEMPTING TO RELOAD ADONIS") + CleanUp() + task.wait() + + warn("MOVING") + model.Parent = tParent + + task.wait() + + dTarget.Disabled = false + warn("RUNNING") + elseif mode == "STOP" then + warn("ATTEMPTING TO STOP ADONIS") + CleanUp() + end + + warn("COMPLETE") + + warn("Destroying reboot handler...") + script:Destroy() +end diff --git a/MainModule/Server/Dependencies/RebootHandler/mParent.model.json b/MainModule/Server/Dependencies/RebootHandler/mParent.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/mParent.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} diff --git a/MainModule/Server/Dependencies/TrelloAPI.luau b/MainModule/Server/Dependencies/TrelloAPI.luau index 7d9721993d..e00b2101ba 100644 --- a/MainModule/Server/Dependencies/TrelloAPI.luau +++ b/MainModule/Server/Dependencies/TrelloAPI.luau @@ -10,8 +10,8 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------- local print = function(...) warn("[Adonis TrelloAPI]: INFO:", ...) end +local error = function(...) warn("[Adonis TrelloAPI]: ERROR:", ...) end local warn = function(...) warn("[Adonis TrelloAPI]: WARN:", ...) end -local error = function(message, level) warn("[Adonis TrelloAPI]: ERROR:", message) return error("[Adonis TrelloAPI]: ERROR:"..message, level == 0 and 0 or 1 + (level or 1)) end local HttpService = game:GetService("HttpService") local Weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} diff --git a/MainModule/Server/Plugins/Anti_Cheat.luau b/MainModule/Server/Plugins/Anti_Cheat.luau index 8b7b40d60c..fe74aedf5c 100644 --- a/MainModule/Server/Plugins/Anti_Cheat.luau +++ b/MainModule/Server/Plugins/Anti_Cheat.luau @@ -1,4 +1,3 @@ - --// Anti-Exploit return function(Vargs, GetEnv) local server = Vargs.Server; @@ -27,7 +26,7 @@ return function(Vargs, GetEnv) player.CharacterAdded:Wait() end - if Admin.GetLevel(player) < Settings.Ranks.Moderators.Level or Core.DebugMode then + if Admin.GetLevel(player) < Settings.Ranks.Moderators.Level or server.Data.NightlyMode then Anti.CharacterCheck(player) end end diff --git a/MainModule/Server/Plugins/Server-SoftShutdown.luau b/MainModule/Server/Plugins/Server-SoftShutdown.luau index 4c5cc16f3d..2e6b95f180 100644 --- a/MainModule/Server/Plugins/Server-SoftShutdown.luau +++ b/MainModule/Server/Plugins/Server-SoftShutdown.luau @@ -30,7 +30,7 @@ return function(Vargs, GetEnv) TeleportService:Teleport(game.PlaceId, player, {[PARAMETER_2_NAME] = true}) else Logs:AddLog("Script", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} due to {result.Name}. Details: {message}`) - Logs:AddLog("Error", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} to {result.Name}. Details: {message}`) + Logs:AddLog("Errors", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} to {result.Name}. Details: {message}`) Functions.Notification("Teleport failed", `SoftShutdown failed to teleport {isReservedServer and "back to the main game" or "to a temporary softshutdown server"}. Details {message}`, {player}, 35, "MatIcon://Error") end end diff --git a/MainModule/Server/Plugins/ServerNewDex.rbxmx b/MainModule/Server/Plugins/ServerNewDex.rbxmx index a6ff9ffaad..5f9e16528b 100644 --- a/MainModule/Server/Plugins/ServerNewDex.rbxmx +++ b/MainModule/Server/Plugins/ServerNewDex.rbxmx @@ -61,7 +61,7 @@ Logs:AddLog("Script", "Successfully loaded reflection metadata to Dex") else Logs:AddLog("Script", "Access to HttpService is not enabled! Dex api dump could not be fetched!") - Logs:AddLog("Error", "Access to HttpService is not enabled! Dex api dump could not be fetched!") + Logs:AddLog("Errors", "Access to HttpService is not enabled! Dex api dump could not be fetched!") --logError("Access to HttpService is not enabled! Dex api dump could not be fetched!") end end) diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 75245fb231..3294a0e6e6 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -597,6 +597,23 @@ return service.NewProxy({ end end + --// Attempts to patch Settings.Prefix to fix issues + if type(server.Settings.Prefix) == "table" then + setmetatable(server.Settings.Prefix, { + __concat = function(self, value) + return `{self[1]}{value}` + end, + __tostring = function(self) + return self[1] + end, + + }) + end + + + + + --// Bind cleanup service.DataModel:BindToClose(function(...) server.CleanUp(...) @@ -632,7 +649,7 @@ return service.NewProxy({ server.FormattedChangelog[i] = applyColour(line) end - --// Setup MaterialIcons + --// Setup MaterialIcons do local MaterialIcons = require(server.Shared.MatIcons) server.MatIcons = setmetatable({}, { @@ -712,7 +729,7 @@ return service.NewProxy({ end for _, module in ipairs(data.ServerPlugins or {}) do - xpcall(LoadModule, function(reason) + task.defer(xpcall, LoadModule, function(reason) warn(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) logError(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) table.insert(server.messages, { diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 7493692ffc..ad2f09c540 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,43 @@ return { - "Version: 261.2"; + "Version: 263"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[v263 2025-01-22 11:29 UTC] @Dimenpsyonal"; + "Load plugins asynchronously"; + "Clamp #num selector to max players"; + "(Git/ccuser44) Disable visualiser when window is minimised (#1832)"; + "(Git/WalkerOfBacon) Show command aliases in :commands (#1833)"; + "(Git/Z3phrz) Update :watchcam description (#1835)"; + "(Git/WalkerOfBacon) Prevent creating a team with the same name (#1836)"; + ""; + "[v262 2025-01-12 11:16 UTC] @Dimenpsyonal"; + "*First update of 2025 (!!!)"; + "Set argument range limits on :lowres"; + "(Git/fxeP1) Attempt to fix unbanning on changed player names (#1819)"; + "(Git/WalkerOfBacon) Add a way to define cameras in settings (#1777)"; + "(Git/WalkerOfBacon) Allow team names with spaced to be created via :teams (#1778)"; + "(Git/WalkerOfBacon) Add R15 support for :dog (#1781)"; + "(Git/ccuser44) Convert test case to nightly mode (#1669)"; + "(Git/ccuser44) Update urgent messages module on publish (#1697)"; + "(Git/ccuser44) Update Roblox StandardLib before lint (#1764)"; + "(Git/ccuser44) Use JIT for Visualizer and Slider (#1774)"; + "(Git/wilsontulus) Fix for loading large data in Studio (#1803)"; + "(Git/GalacticInspired) New 'clear' sub-command on :whitelist (#1805)"; + "(Git/WalkerOfBacon) Fix :oddliest (#1775)"; + "(Git/kaiserandaxl) Add override for TShirt Asset Type (#1799)"; + "(Git/kaiserandaxl) Fix indexing nil tab (#1800)"; + "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; + "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; + "(Git/NoobBucket) Fix ServerNewDex not logging correctly (#1814)"; + "(Git/convxors) Fixed friends tab on the !profile command (#1821)"; + "(Git/WalkerOfBacon) Fix :pchat glitching (#1809)"; + "(Git/ImFirstPlace) Update TextField PlaceholderColor3 (#1806)"; + "(Git/Speeder323) Fix debounce for antiexploit notifications (#1783)"; + ""; + "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; + "Fix trello erroring instead of warning (#1805)"; + ""; "[Patch v261.2 2024-12-21 20:23 UTC] @Dimenpsyonal"; "ACTUALLY fix argument handling"; ""; @@ -20,9 +55,9 @@ return { "(Git/Mars7383) Fix typo in Loadstring dependency affecting :ss (#1587)"; "(Git/PurpleCreativity) Remove ;cut command (#1590)"; "(Git/EasternBloxxer) Make dex fetch api dump on server start (#1591)"; - "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; + "(Git/convxors) Fix TopBarShift for :setmessage (#1593)"; "(Git/jun022222222) Replace Coords.luau (#1595)"; - "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; + "(Git/convxors) Add Text Selections to the :players Command (#1597)"; "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Make mats & colors list selectable (#1599)"; "(Git/24rr) Add a search player bar for :privatechat (#1594)"; @@ -497,7 +532,7 @@ return { "(Git/DaRealGandhi20) [Add Text Selectable + New Text Format] :selectplayers/:count (#1132)"; "Git/Dimenpsyonal) Add atmosphere support (#1139)"; "(Git/Deniernal354) Add myself to credits (#1144)"; - "Git/wilsontultus) Update Moderators.lua - :invisible and :visible command... (#1146)"; + "(Git/wilsontultus) Update Moderators.lua - :invisible and :visible command... (#1146)"; "(Git/wilsontulus) Update !playerinfo command - Mail & Phone/ID Verified Status (#1147)"; "(Git/Dimenpsyonal) Add age restriction settings (#1149)"; "(Git/Dimenpsyonal) Remove GitHub link (#1150)"; @@ -1225,7 +1260,7 @@ return { "*Dex updated and moved to its own module; Also added server-side action support"; "*Fixed :countdown"; "*Fixed :slowmode"; - "(Git/happyman090) Fix for sp00ky and k1tty on MeshPart head places"; + "(Git/btt-t) Fix for sp00ky and k1tty on MeshPart head places"; "(Git/Expertcoderz) Mistake fixing + Aero theme"; "(Git/Expertcoderz) Add :transparency command"; "(Git/Expertcoderz) Command-related additions #379"; @@ -1288,7 +1323,7 @@ return { "(Git/ccuser44) Made print and warn work properly. Also fixed some indentation."; "(Git/ccuser44) Removed unnecessary references to filtering enabled."; "(Git/ccuser44) Fixed incorrect string literals"; - "(Git/happyman090) Refresh command update"; + "(Git/btt-t) Refresh command update"; ""; "[v217 5.9.2021 19:15 EST]"; "* Random bug fixes & changes"; @@ -1300,8 +1335,8 @@ return { "(Git/imskyyc) Updated TrelloAPI"; "(Git/ccuser44) Added unprotected metatable detection with tamper protection"; "(Git/LolloDev5123) :admins now correctly shows \"Head Admin\" instead of \"Supervisor\""; - "(Git/happyman090) Character animations for clones"; - "(Git/happyman090) Modified behaviour of kill command"; + "(Git/btt-t) Character animations for clones"; + "(Git/btt-t) Modified behaviour of kill command"; "(Git/p3tray & pbstFusion) Added :pban and :unpban as aliases for :gameban and :ungameban"; "(Git/p3tray) Added _G.Adonis.RunCommandAsNonAdmin(command, playerToRunCommandAs)"; "(Git/Expertcoderz) Revamped server details UI"; @@ -1324,7 +1359,7 @@ return { "*Removed some debug prints and debug/old code"; "*Fixed some typos"; "*Minor bug/security changes"; - "(Git/happyman090) Fixed donor neon command"; + "(Git/btt-t) Fixed donor neon command"; "(Git/Expertcoderz) Removed 'besties' from !usage"; "(Git/fxeP1) Updated ServerInfo command, HTTP.CheckHttp, and RunCommandAsPlayer"; "(Git/Expercoderz) Added :promptpremiumpurchase "; diff --git a/MainModule/Server/Shared/Credits.luau b/MainModule/Server/Shared/Credits.luau index e38134a0e3..2fe59fe052 100644 --- a/MainModule/Server/Shared/Credits.luau +++ b/MainModule/Server/Shared/Credits.luau @@ -39,7 +39,7 @@ return { {Text = "@NeoInversion", Desc = "Open Source Contributor"}; {Text = "@imskyyc", Desc = "Open Source Contributor"}; {Text = "@LolloDev5123", Desc = "Open Source Contributor"}; - {Text = "@happyman090", Desc = "Open Source Contributor"}; + {Text = "@btt-t", Desc = "Open Source Contributor"}; {Text = "@GalacticInspired",Desc = "Open Source Contributor"}; {Text = "@flgx16", Desc = "Open Source Contributor"}; {Text = "@DrewBokman", Desc = "Open Source Contributor"}; @@ -96,7 +96,7 @@ return { {Text = "@Hedreon", Desc = "Open Source Contributor"}; {Text = "@Mars7383", Desc = "Open Source Contributor"}; {Text = "@PurpleCreativity",Desc = "Open Source Contributor"}; - {Text = "@ScriptedConnor", Desc = "Open Source Contributor"}; + {Text = "@convxors", Desc = "Open Source Contributor"}; {Text = "@omwot", Desc = "Open Source Contributor"}; }; diff --git a/SECURITY.md b/SECURITY.md index c51c053726..a4ebe97558 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,7 +11,7 @@ Only the *live* (release) version of Adonis is officially supported and given se ## Reporting a Vulnerability in Adonis -👉 **If the vulnerability is *severe* or highly damaging**, join the [Epix Incorporated Discord server](https://discord.gg/H5RvTP3) and DM an *Adonis Maintainer*. +👉 **If the vulnerability is *severe* or highly damaging**, join the [Epix Incorporated Discord server](https://discord.gg/H5RvTP3) and DM an *Moderator*, *Developer, or *Maintainer*. 👉 **If the vulnerability is relatively minor and can be safely discussed in public**, create a bug report [on GitHub](https://github.com/Epix-Incorporated/Adonis/issues/new/choose) or in our Discord server. diff --git a/build.bat b/build.bat index a1023dba8c..1d299b378f 100644 --- a/build.bat +++ b/build.bat @@ -15,10 +15,13 @@ IF %ERRORLEVEL% NEQ 0 ( SET ROJO_COMMAND=rojo ) +echo Updating Roblox standard library with %SELENE_COMMAND% +%SELENE_COMMAND% generate-roblox-std + echo Checking for lint errors with %SELENE_COMMAND% from ./Loader and ./MainModule %SELENE_COMMAND% ./MainModule ./Loader -echo Running %ROJO_COMMAND% build -o Adonis.rbxm -%ROJO_COMMAND% build -o Adonis.rbxm +echo Running %ROJO_COMMAND% build -o Adonis.rbxl +%ROJO_COMMAND% build -o Adonis.rbxl ENDLOCAL diff --git a/build.sh b/build.sh index c6733cbc4e..5da0cb392a 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,10 @@ #!/bin/bash +printf "Updating Roblox standard library" +selene generate-roblox-std + printf "Checking for lint errors from ./Loader and ./MainModule" selene ./Loader ./MainModule -printf "Running rojo build -o Adonis.rbxm" -rojo build -o Adonis.rbxm +printf "Running rojo build -o Adonis.rbxl" +rojo build -o Adonis.rbxl