A Developer’s Guide to Setting up the Adonis Administration System
Written By:
@Expertcoderz, Adonis Maintainer on GitHub
Thanks to @ar_qx for the original guide. This is intended to be a more comprehensive and polished version.
Preface
Adonis is a major open source administration and moderation system for ROBLOX games, distributed under the MIT license.
Some features of Adonis include:
-
Over 400 commands including optional fun commands and utility commands for players
-
Highly configurable and customizable ranks and permissions system
-
Cross-server administration and extensive logging
-
Trello functionality to globally manage and sync configurations and permissions across games
-
Support for loader plugins with access to the rich and modular API for modifying functionality, implementing custom commands etc. (see documentation link below)
-
Support for custom UI themes and creation of your own Adonis-based UIs using the aforementioned API
-
Built with security against exploits, by design; we never simply obfuscate our code
-
[Experimental] WebPanel to manage your game servers remotely
Furthermore, Adonis is updated and maintained regularly by a community of contributors ie. volunteering devs. The original creator and developer is @Davey_Bones aka Sceleratis.
To learn more or to receive quick support, join our official Discord server from the link provided below.
Bug reports or feature requests may be submitted on the Adonis GitHub repository.
Relevant Links:
-
Loader
-
MainModule (source code)
-
GitHub Repository \ API Documentation
-
User Manual
-
Discord server
-
ROBLOX group (Epix Incorporated)
Advisory
It is known that there are many non-official copies of the Adonis admin loader found in the Studio toolbox and library. Many of these models are uploaded by individuals of malicious intent and may open up backdoors/viruses to games using them. Or, they may simply be outdated.
Anyways, just be sure you’re using the official loader taken from the link above,
and you’ll be fine.Edit: In addition to malicious loaders/models, certain Studio plugins may also attempt to hijack your copy of the Adonis loader and modify it such as to redirect to another module. Therefore, always exercise caution when installing plugins from unknown sources.
Installation - Getting Started
-
Grab the Adonis loader.
-
Insert it into your game via the toolbox (Inventory tab).
-
Optionally move it into
ServerScriptService
. It is best not to rename the “Adonis_Loader” model. You can, however, delete “ThumbnailCamera”.
-
Open the Config > Settings module script as highlighted above. In it, you’ll see something like this:
-
Scroll down to the following lines. Change
settings.DataStoreKey
to any random string (random as in"q5'j#1uZrUC-"
or equivalent, just make sure nobody can guess it).
Info - Why is the DataStoreKey important?
Because it specifies where persistent data such as permissions (ranks), warnings and bans assigned in-game, as well as settings/preferences for individual players (ie. player data) are saved by Adonis.
Having a randomized datastore key is a security measure against malicious server side scripts (or admins using the
:s <code>
command) attempting to tamper with the data, since the exact key is needed to access the data.This is what you’ll get in-game if you leave the DataStoreKey as “CHANGE_THIS”:
Configuring Adonis
📑 Accepted Entry Formats for Permission Lists
-
"USERNAME"
-"SomeRandomGuy"
-
"USERNAME:USER_ID"
-"SomeRandomGuy:12345678"
-
"Group:GROUP_ID:GROUP_RANK
-"Group:12345678:40"
Note: place ‘-’ before the group rank to specify users of the rank and any ranks above, eg.Group:12345678:-100
which will give perms to people with rank 100+ in the group of ID 12345678. -
"Item:ASSET_ID"
-"Item:12345678"
-
"GamePass:GAMEPASS_ID"
-"GamePass:12345678"
Hint
User, group, asset and gamepass IDs can be found in their Roblox website URLs. For instance:
Remember: Anything you set under the loader settings is considered permanent and cannot be modified in-game except by people of the Creators permission level. If you wish to assign temporary/provisional permissions, bans etc., do it in-game using commands.
📁 Assigning People to Ranks
To get started, simply edit the tables in settings.Ranks
, as shown below (you may refer to the Accepted Entry Formats):
📁 Customizing the Hierarchy (Ranks) Structure
You can add custom ranks:
You can hide specific ranks from the in-game admin list UI (accessed via the :admins
command):
Note on Renaming
If you wish to rename the existing default ranks, such as “Moderators” to “Mods”, you must first hide the existing rank in question before adding a rank of the same level, otherwise Adonis will still think that it exists as a separate rank. For example:
📁 Configuring Bans, Mutes, Blacklist and Whitelist
settings.Banned - People who are permanently prohibited from joining the game.
settings.Muted - People who are permanently prevented from using the in-game chat.
settings.Blacklist - People who are always disallowed from running Adonis commands.
settings.Whitelist - People who are always allowed to join while server whitelist ie. serverlock is in effect.
(You may refer to the Accepted Entry Formats.)
📁 Customizing Command Permissions
You can modify the rank required to run certain commands with settings.Permissions
(which is especially useful when implementing custom ranks).
- To restrict command CMD to ranks of level LVL and higher:
CMD:LVL
- To restrict command CMD to ranks of exact levels LVL1, LVL2, LVL3… only:
CMD:LVL1,LVL2,LVL3,...
(no spaces after commas) - To allow command CMD to be run by everyone:
CMD:0
Note: You do not have to include command prefixes (the “:” in “:kill all”) when configuring permissions.
📂 Additional Command-Related Settings
Refer to this for a list of possible values for settings.ConsoleKeyCode
.
[boolean] settings.FunCommands - Whether or not entertaining but non-essential commands are enabled.
[boolean] settings.PlayerCommands - Whether or not player utility/informative commands (such as!notepad
) are usable by players.
[boolean] settings.CrossServerCommands - Whether or not commands that affect more than one server (such as:globalvote
) are enabled.
[boolean] settings.ChatCommands - Whether or not commands can be run from the chat. If set tofalse
, the console will have to be used for commands.
[boolean] settings.Console - Whether or not the Adonis command console (an alternative interface to the chat for silently running commands, opened by pressing the key specified insettings.ConsoleKeyCode
) is enabled.
[boolean] settings.Console_AdminsOnly - Whether or not the console can only be used by people with admin permissions.
This is NOT a comprehensive list of settings provided in the configuration module. The rest is up to you to explore.
📂 Conveniently Implementing Custom Commands
Please refer to The Structure of an Adonis command near the bottom of this article for more information on scripting commands.
You can also replace commands here. To get an existing Adonis command’s index for overriding it, you’ll have to look for the command itself in MainModule > Server > Commands.
Using settings.Commands
for adding custom commands is essentially equivalent to having a server plugin module placed in Adonis_Loader > Config > Plugins. (See Plugins section below.) However, plugins will still be needed if you’re looking to specifically modify parts of existing commands (such as Description
, instead of overriding the entire command structure) or completely remove an existing command.
The Help Button
You may have noticed in-game that Adonis comes with a button at the bottom right corner of the screen that opens the userpanel when clicked:
This button is not intended to be a watermark and can be disabled or customized by the following settings:
Donor Perks
Adonis by default includes aesthetic perks for players who have purchased the donation pass/shirt (intended to support development), on the in-game donation panel:
These perks can be disabled if you wish, by configuring the following settings:
Anti-Exploit System
NOTE: This section may be outdated.
Adonis includes an optional and configurable system to counter a few types of exploits.
Note the following:
-
By design, Adonis will always attempt to protect itself from modification or tampering by exploiters/malicious scripts.
-
The additional anti-exploit features Adonis provides is not intended to be comprehensive or fully effective in stopping all known exploits, as Adonis is an administration and not a dedicated anticheat system.
Using the Adonis Global API
Adonis provides an optional _G
API for accessing the system from other scripts, allowing developers to connect it with their games for better integration.
If you require only basic access to functions such as _G.Adonis.CheckAdmin(player)
(NOTE: actual documentation for the functions _G.Adonis
provides has yet to be written; we’re still working on it), leaving settings.G_API = true
will do.
However, for advanced access to the internals of Adonis (you probably don’t need this), settings.G_Access
must be enabled and settings.G_Access_Key
set to something secret/random. You can then expose Adonis core modules in other scripts using _G.Adonis.Access("SomeRandomKey", "Admin/Functions/Variables/Logs/UI etc.")
.
Refer to the API documentation for in-depth usage information.
Plugins
Plugins allow developers to modify Adonis without needing to edit the MainModule. This means that, along with UI themes, they allow for integrations of nearly limitless possibilities, from adding custom commands and modifying/removing existing commands, to altering core functionality and behavior. Plugins run in an environment such that they have full access to the Adonis API.
There are two types of Adonis plugins: client plugins and server plugins. Server plugins are most often used to implement custom commands.
Plugins go under Adonis_Loader > Config > Plugins:
Important: In order for Adonis to determine whether each loader plugin belongs to the client or server, their module names must be prefixed with “Client/Server-” or "Client/Server: ". For example, “
Server-MyCommands
” or “Client: MyRandomPlugin
”.
Making Plugins
Plugin development is explained in the API documentation linked at the top of this page.
Some scripting knowledge may be necessary.
UI Themes
Adonis comes with the following themes by default:
Mobilius
Essentially Default with some non-mobile-friendly elements removed.
Rounded
Simply modifies the default theme to add UICorners to each element. And also includes a different-looking command console.
Legacy Themes (unmaintained)
Some older themes Adonis once included (Steampunk, Hydris, etc.) but got removed for lack of quality/use can be found and downloaded here.
You can specify the game theme from the following loader settings:
Note: By default, individual players are still able to change their own displayed theme in-game under the Client tab of the userpanel:
The “Game Theme” option refers to the theme specified bysettings.Theme
.
Implementing Custom Themes
To add a custom Adonis UI theme that can be used in your game, place the theme folder in Adonis_Loader > Config > Themes:
Remember to edit the loader settings to apply your theme as desired:
Creating Custom Themes
The actual process of making an Adonis theme is rather challenging to describe. Also, it typically requires some capability in scripting/UI design, and, as with plugin development, even more exploration and familiarization with the Adonis internal API and UI framework.
To achieve this and understand how everything works, you’d want to look into the built-in themes themselves which are stored under MainModule > Client > UI:
Some useful explanation is provided in the code modules responsible for each theme’s appearance and behavior.
The official API documentation as linked at the top of this page may also help. Otherwise, feel free to ask for help in the Adonis community server.
Additional Information
A note on forking Adonis (the MainModule)
Some developers have been known to edit the MainModule itself to customize Adonis for their own games. This is actually almost always not necessary, as loader plugins and themes are already capable of changing nearly anything conceivable inside Adonis without making an entire copy of the MainModule. Unless you’re at this level, it is quite unwise to maintain such a thing which means having to manually port updates/patches over from mainstream Adonis or missing out on bug fixes, feature updates and security-related patches otherwise.
Reference: The structure of an Adonis command (read to understand making custom commands)
Here’s how an Adonis command definition table looks like:
ExampleCommand1 = { --// The index & table of the command
Prefix = server.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 command's 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";
Filter = true; --// Should user supplied text passed to this command be filtered automatically? Use this if you plan to display a user-defined message to other players
Fun = false; --// Is this command considered as fun?
Hidden = true; --// Should this command be hidden from the command list?
Disabled = true; --// Should this command be unusable?
NoStudio = false; --// Should this command be blocked from being executed in a Studio environment?
NonChattable = false; --// Should this command be blocked from being executed via chat?
CrossServerDenied = false; --// If true, this command will not be usable via :crossserver
Function = function(plr: Player, args: {string}, data: {}) --// The command's function; This is the actual code of the command which runs when you run the command
--// "plr" is the player running the command
--// "args" is a table containing command arguments supplied by the user
--// "data" is a table containing information related to the command and the player running it, such as data.PlayerData.Level (the player's admin level)
print("This is 'arg1':", args[1])
print("This is 'arg2':", args[2])
print("This is 'etc'(arg 3):", args[3])
error("this is an example error :o !")
end
};
All command definitions are contained with the server.Commands
table.
This is the index and table of the command, a unique internal identifier as in server.Commands.ExampleCommand1
.
Note: In Adonis plugins and custom command code you can use this to refer to specific other commands for doing something with them. Changes to the
server.Commands
dictionary (which ultimately contains all registered commands) are live in the game so it’s possible to make, for instance, a command that disables another command byserver.Commands.ExampleCommand1.Disabled = true
.
This is the prefix used to run the command, eg. the “:” in “:kill someplayer”. Setting this to (server.)Settings.Prefix
will tell Adonis to use the prefix configured in the loader settings. For player-use commands, this should (but need not) be set to (server.)Settings.PlayerPrefix
. The default player prefix used would be “!” as in “!notepad”.
This is an array of names or aliases that can be used to run/refer to the same command. For example, {"removetools", "notools"}
so that running “:notools” in-game is the same as running “:removetools”. This can also be used to implement shorthands such as “m” for the “message” command. The first string in the array will be the name listed the commands list UI (:cmds).
This is an array of the names of arguments the command expects to take during execution. For example, Args = {"player", "tool"}
for a “:give <player> <tool>” command. The first argument “player” tells the command function which player(s) to give to, and the second argument “tool” specifies the name of the tool to give. More about arguments will be explained ahead.
If your command doesn’t require any arguments behind it, such as the “:savemap” or “!notepad” commands, simply leave Args = {}
(empty table). If your command accepts optional arguments, as many do, just include them in Args
and handle them later in the Function
.
This is what you want to tell your players/admins what the command does when run. It will be shown in the in-game command list (:cmds) and command info (:cmdinfo <command>) UIs.
This determines the permission required for people to execute the command. It can be any of the following:
-
A number specifying the minimum admin rank allowed, such as
100
for “Moderators” (by default) -
A string that is the name of the minimum admin rank allowed, such as
"Moderators"
-
A table containing specific allowed levels rather than a minimum level:
{100, 150, "HeadAdmins", etc}
(only the specified ranks will be allowed to run the command)
If this is set to true
, any string arguments a player specifies according to the Args table will be filtered by ROBLOX before being passed to the command’s Function (see below) This is a simple way for filtering message/publicly-visible text input without having to handle it in the Function later.
If set to true
, the command will not be shown on the in-game command list (:cmds) and will not appear in the console autocomplete (by default). This feature is useful for hiding secret commands!
If set to true
, the command will not be usable.
If set to true
, the command will not be usable when playtesting in a Studio environment. This is meant for commands involving API features not supported in Studio, such as TeleportService features.
This is where all the action happens when the command is executed. plr
is the player running the command (or nil
if run by the system) and args
is an array of strings containing the raw string arguments passed in sequence behind the command (delimited by Settings.SplitKey in the loader settings).
For example, Player1 runs “:pm player2 Hello there!”. This will result in
plr = Player1 --(the Player object)
and
args = {[1] = "player2", [2] = "Hello there!"}
being passed to the Function.
Note that the arguments fed to the Function in args
are in strings as what the player typed out. You’ll have to interpret and convert them to the relevant types in the Function code. If the desired argument type is a player/set of target players to be selected for running the command on (such as in “:kill <player(s)>”), use the following code to obtain the desired players from the raw string argument:
for _, v: Player in ipairs(service:GetPlayers(plr, args[1])) do
--// Sample code using the Adonis API (server.Remote)
--// The stuff below runs on the selected players according to the args[1] string (first command argument)
server.Remote.MakeGui(v, "Notification", {
Title = "Hello, "..v.DisplayName;
Message = "You are about to get respawned!";
Time = 10;
})
v:LoadCharacter() --respawn
end
You may have noticed the plr
being supplied in service:GetPlayers(plr, args[1])
. This is to facilitate player selections such as “me” or “others” that depend on the player running the command.
Finally, data
is a table containing information related to the command and the player running it, such as data.PlayerData.Level
(the player’s admin level). For in-depth info on this, please refer to the API documentation.
Adonis catches errors from command Functions and displays them in the form of an error message UI to the player running the command (if any). This can be used with error
or assert
to express errors such as for invalid arguments supplied.
Once again, refer to the API docs for details and useful built-in functions Adonis provides that can be used in your command/plugin code.
End of Guide
Questions? Comments? Suggestions? Criticisms? Reply to this topic or join our community server!