Skip to content
Select theme
  • Auto
  • Dark
  • Light

Commands and configuration

This page covers three services. CommandApi tracks Plex commands and runs commands for a named staff member. ConfigurationApi reads the Plex configuration files. ModuleConfigApi creates configuration files for your module.

Get each service from the Plex API. In your module class and in a command that extends SimplePlexCommand, call api(). In other classes, keep a reference to your module and call module.api(). See the API overview.

CommandApi commands = api().commands();
ConfigurationApi configuration = api().configuration();
ModuleConfigApi moduleConfigs = api().moduleConfigs();

To write a command, see Commands. To add a config.yml or messages.yml to your module, see Configuration and messages.

Javadoc: CommandApi

Method What it does
register(PlexCommand command) Registers a command with Plex.
unregister(PlexCommand command) Removes a command from Plex and removes its labels from Paper.
registeredCommands() Returns a copy of the list of commands that Plex tracks. The list has the Plex commands and the commands of every module.
requiresLifecycleReload() Returns true if commands changed after Paper built its command list. Paper must then rebuild the list.
dispatchAsConsole(UUID identityId, String identityName, String command, Consumer<? super Component> feedback) Runs a command line as the console and names the given player as the actor. Returns true if Paper accepted the command.

In a module, call registerCommand and unregisterCommand on your module, not register and unregister on CommandApi. The module methods record the command, so Plex removes it when your module unloads. Register commands in load(). Paper builds its command list after that.

If commands change later, requiresLifecycleReload() returns true. When Plex reloads modules on Paper, Plex reloads the datapacks to rebuild the list. Folia needs a server restart.

import dev.plex.command.PlexCommand;
public List<String> commandsFor(CommandSender sender)
{
List<String> names = new ArrayList<>();
for (PlexCommand command : api().commands().registeredCommands())
{
String permission = command.getPermission();
if (permission.isEmpty() || sender.hasPermission(permission))
{
names.add(command.getName());
}
}
return names;
}

An empty permission means that everyone can use the command.

Use dispatchAsConsole when a staff member runs a command from outside the game, for example from a web panel. Plex runs the command line as the console. A Plex command then uses identityName and identityId as the sender name and UUID in its messages and records. Write the command line without a leading slash.

Plex sends the command output to feedback. The method returns false when Paper does not accept the command, for example when the command does not exist.

Call dispatchAsConsole on the global region thread.

public void runForStaff(UUID staffId, String staffName, String commandLine, Consumer<Component> reply)
{
ownTask(Bukkit.getGlobalRegionScheduler().run(plugin(), task ->
{
boolean accepted = api().commands().dispatchAsConsole(staffId, staffName, commandLine, reply);
if (!accepted)
{
reply.accept(Component.text("Unknown command."));
}
}));
}

Javadoc: CommandExecutionIdentity

CommandExecutionIdentity holds the actor name and UUID while dispatchAsConsole runs a command. Plex reads it when a Plex command starts. It is an internal class. Use dispatchAsConsole instead of calling it.

Method What it does
call(UUID uniqueId, String name, Supplier<T> action) Runs action on the current thread with the given actor.
currentName(String fallback) Returns the current actor name, or fallback when no name is set.
currentUniqueId() Returns the current actor UUID, or null.

Javadoc: ConfigurationApi

ConfigurationApi gives read access to the shared Plex files in plugins/Plex.

Method What it does
mainConfig() Returns config.yml.
messages() Returns messages.yml.
indefiniteBans() Returns indefbans.yml.
toggles() Returns toggles.yml.

Each method returns a PlexConfiguration. You cannot change the file through it. Each read gives the value that is loaded now. After a server owner runs /plex reload, the same object returns the new values. To keep a value that you use often, read it in load() or enable().

The keys are described on the config.yml, messages.yml, and indefbans.yml pages.

Javadoc: PlexConfiguration

Method What it does
getString(String path) Returns the string at path, or null if the path does not exist.
getString(String path, String fallback) Returns the string at path, or fallback if the path does not exist.
getBoolean(String path) Returns the boolean at path, or false if the path does not exist.
getBoolean(String path, boolean fallback) Returns the boolean at path, or fallback if the path does not exist.
getInt(String path) Returns the integer at path, or 0 if the path does not exist.
getInt(String path, int fallback) Returns the integer at path, or fallback if the path does not exist.
getStringList(String path) Returns the string list at path, or an empty list if the path does not exist.
getStringList(String path, List<String> fallback) Returns the string list at path, or fallback if the path does not exist.

The lists that these methods return cannot be changed.

PlexConfiguration plexConfig = api().configuration().mainConfig();
ZoneId zone = ZoneId.of(plexConfig.getString("server.timezone", "Etc/UTC"));
boolean chatEnabled = plexConfig.getBoolean("chat.enabled", true);
List<String> blockedWhileMuted = plexConfig.getStringList("block_on_mute");
boolean pvp = api().configuration().toggles().getBoolean("pvp", true);

Javadoc: ModuleConfigApi

Method What it does
create(PlexModule module, String fileName) Returns a ModuleConfiguration for one file of your module. It does not read the file.

fileName is two paths at the same time. It is the path of the default file in your module JAR, and the path of the file in your module data folder, plugins/Plex/modules/<module name>/. You can use a folder, such as data/homes.yml. The path must be relative and must stay inside the data folder. If it does not, create throws an IllegalArgumentException.

Javadoc: ModuleConfiguration

ModuleConfiguration extends the Bukkit YamlConfiguration. You read and change values with the usual Bukkit methods, such as getString, getInt, and set.

Method What it does
load() Reads the file from disk. If the file does not exist, Plex first copies the default file from your JAR.
save() Writes the current values to the file.

When you call load(), Plex also compares the file with the default file in your JAR. Plex adds each key that is only in the default file to the file on disk, and logs the keys that it added. Keys that the server owner set stay as they are.

load() throws an IllegalStateException if your JAR has no default file at that path, or if Plex cannot read the file. save() throws an IllegalStateException if Plex cannot write the file.

Both methods read or write a file on disk. Call them in load(), enable(), or disable(), or on your own executor. Do not call them on a player or region thread during play.

private ModuleConfiguration config;
private ModuleConfiguration homes;
@Override
public void load()
{
config = api().moduleConfigs().create(this, "config.yml");
config.load();
homes = api().moduleConfigs().create(this, "data/homes.yml");
homes.load();
}
public void setHome(UUID owner, String location)
{
homes.set("homes." + owner, location);
}
@Override
public void disable()
{
try
{
homes.save();
}
catch (IllegalStateException ex)
{
getLogger().error("Could not save data/homes.yml", ex);
}
}

For this example, your JAR must contain src/main/resources/config.yml and src/main/resources/data/homes.yml.