Content generated with AI — it may contain mistakes.

Getting started

Installation

Installing the library on a server and depending on it from a plugin.

On the server

Drop ExyliaLib.jar into plugins/. That is the whole installation — plugins that depend on it refuse to load without it, and the library carries what it needs inside its own jar.

PacketEvents goes next to it on every server. The library lists it under depend, so the server refuses to load ExyliaLib — and with it every Exylia plugin — without it. The library's packet features — overlays, dialogs, per-viewer displays — run through it. Download it from Modrinth.

The packet-level sidebar library travels inside the jar, relocated, so there is exactly one copy on the server rather than one per plugin.

Optional plugins

Nothing here is required. Each one unlocks a module or improves one:

PluginWhat it enables
PlaceholderAPIExposing this plugin's placeholders to other plugins, and reading theirs.
FastAsyncWorldEditThe schematic module: saving and pasting boxes of the world.
Vault or PlayerPointsThe economy module.
A clan pluginThe clan module. Eight are detected — see Players.
Lunar (Apollo) or FeatherClient waypoints, cooldowns and teammate markers.
DeluxeCombat or PvPManagerThe combat module's answer to "is this player fighting".
WorldsCreating and deleting worlds, which is the only way to do it on Folia.

A module whose backing plugin is absent does nothing loudly: Schematics.isSupported() and Holograms.isSupported() answer honestly, and the reason is a string you can print.

From a plugin

Declare the dependency so the server loads the library first:

plugin.yml
name: MyPlugin
main: net.example.MyPlugin
api-version: '1.21'
depend:
  - ExyliaLib

Then take the module views you need in onEnable. Almost every module is reached the same way — a static of(plugin) handing back a view that belongs to your plugin:

MyPlugin.java
public final class MyPlugin extends JavaPlugin {
 
    private ConfigFile<Settings> settings;
 
    @Override
    public void onEnable() {
        TaskScheduler tasks = Tasks.of(this);
        PluginMenus menus   = Menus.of(this);
        PluginActions acts  = Actions.of(this);
 
        settings = Configs.define(this, "config", Settings.class).load();
    }
}
Why per plugin

The view is what makes ownership work: your actions live in your namespace, your menus close when your plugin disables, your placeholders unregister with it, and values written onto items are filed under your name rather than the library's.

Cleaning up

You do not have to. The library releases a plugin's tasks, menus, actions, placeholders and inputs when it disables — menus are closed before tasks are released, so a button whose handler comes from a dying classloader cannot answer one last click.

The library's own commands

/exylialib needs exylialib.admin on every subcommand:

CommandWhat it does
/exylialib reloadRefreshes colours, formats and the rest of the shared configuration, and notifies every plugin listening for it.
/exylialib infoVersion, platform and who depends on this library.
/exylialib statsLive counters from every module.
/exylialib updateChecks GitHub now and stages a newer release.
/exylialib export <plugin>Writes that plugin's tables to a dump.
/exylialib import <plugin> <file> [force]Reads one back; force merges, it does not replace.
/exylialib wipe <plugin> <table|*> [code]Empties one table or all of them, after a typed confirmation and an automatic dump.

A plugin listens for that reload with Reloads.onLibraryReload(plugin, runnable) — the palette changing is the usual reason, since every compiled menu is holding the old colours.

Something missing on this page? Tell us on Discord