Skip to content

3. Module Architecture ​

3.1 Common module (AppelTools-Common.jar) ​

Pure Java library. No Bukkit or Velocity classes are referenced in common; the platform modules implement adapter interfaces declared here. Provides:

  • Database (HikariCP + MySQL) with a self-migrating schema system.
  • All persistent data classes (POJOs) and DAO interfaces.
  • A configuration framework based on ConfigKey<T> / MessageKey<T> with YAML + ConfigLib.
  • The Permissions constants class.
  • The plugin-update subsystem (PluginUpdater with six providers).
  • Chat filter (RegexFilter) for advertising and curse-word detection.
  • The Embeds factory for Discord MessageEmbeds.
  • A scheduler abstraction and a logger abstraction.
  • A small pub/sub queue (SignedQueue / QueuedData / SignedResult) used to coordinate cross-server chat moderation.

The Gradle task replaceTokens substitutes @version@, @description@, @author@ from Constants.java at compile time.

3.2 Paper module (AppelTools-Paper.jar) ​

A standard paper-plugin.yml plugin with a PluginLoader. The libraries are shaded into the jar and moved under their own namespace, so the descriptor holds no libraries: section. Responsibilities:

  • Gameplay commands (teleport, gamemode, speed, fly, homes, economy, freeze, notes GUI).
  • Per-server economy (Vault hook) and per-server balances.
  • Player session wrapper (ATPPlayer) with auto-save every 5 minutes.
  • Staff mode (vanish + tool kit + invsee + freeze + notes).
  • Plugin-messaging listener for chat/command moderation and staff-mode sync from the proxy.
  • HikariCP-backed DAO access (shared with common).

3.3 Velocity module (AppelTools-Velocity.jar) ​

Standard Velocity @Plugin. Responsibilities:

  • Cross-server moderation: ban/mute/kick, IP-targeted variants, history, undo.
  • Friend system, party system, private messaging.
  • Cross-server chat filter and staff-chat broadcasting.
  • Reports (with Discord embed).
  • Maintenance mode (proxy-wide + per-Paper fan-out).
  • Server restart scheduler with countdown broadcasts.
  • Server registration (/servers register/unregister/list).
  • Discord logging of all significant events.
  • Plugin-messaging bridge: PluginMessageListener is the central dispatcher for all incoming cross-server channels.

3.4 Inter-Module Wiring ​

The Paper and Velocity modules share the same MySQL database but do not share a JVM. They synchronize via Velocity plugin-message channels (see 08-messaging.md).

┌──────────────┐  plugin messages   ┌──────────────────────┐
│   Velocity   │ ─────────────────▶ │   Paper (each node)  │
│   Proxy      │ ◀───────────────── │                      │
└──────┬───────┘                    └──────────┬───────────┘
       │                                      │
       └─────────────► MySQL ◄────────────────┘

3.5 Adapter Pattern ​

The platform-agnostic contract is defined by me.Maussee.AppelTools.common.Adapters.AppelToolsAdapter (interface). It exposes:

java
SchedulerAdapter getScheduler();
AppelLogger getLogger();
ServerType getServerType();        // enum: VELOCITY, PAPER
String getServerName();
Path getDataDirectory();
Path getConfigPath();
LuckPerms getLuckPerms();
Database getDatabase();

AppelSettingsDB     getAppelSettingsDB();
PlayerDataDB        getPlayerDataDB();
PlayerServerDataDB  getPlayerServerDataDB();
PunishmentDB        getPunishmentDB();
UndonePunishmentDB  getUndonePunishmentDB();
ServerDataDB        getServerDataDB();
StaffInventoryDB    getStaffInventoryDB();
FriendRequestDB     getFriendRequestDB();
HomeDB              getHomeDB();

PlayerManager<? extends ATUserAdapter> getPlayerManager();

The platform modules (AppelToolsPaper and AppelToolsVelocity) implement this interface. Player types ATPPlayer (Paper) and ATVPlayer (Velocity) implement ATUserAdapter.

3.6 Package Layout ​

me.Maussee.AppelTools
├── common
│   ├── Adapters
│   ├── Config
│   ├── Database
│   │   └── DAO
│   ├── Discord
│   ├── Logger
│   ├── Punishments
│   ├── Queue
│   ├── Scheduler
│   ├── Types
│   │   ├── Data
│   │   └── Query
│   └── Utils
│       ├── Exceptions
│       └── Managers
├── paper
│   ├── Commands
│   │   ├── Economy
│   │   ├── Gamemode
│   │   ├── Helpers
│   │   │   ├── Arguments
│   │   │   ├── Contexts
│   │   │   └── Handler
│   │   ├── Home
│   │   ├── Speed
│   │   └── Teleport
│   │       └── Requests
│   ├── Config
│   ├── Discord
│   │   └── Commands
│   ├── Economy
│   ├── Events
│   │   └── Modifiers
│   ├── Types
│   │   └── Debug
│   └── Utils
│       ├── Managers
│       └── Scheduler
└── velocity
    ├── Commands
    │   ├── Friends
    │   ├── Helpers
    │   │   ├── Arguments
    │   │   ├── Contexts
    │   │   └── Handler
    │   ├── Message
    │   ├── Other
    │   ├── Party
    │   ├── Punishment
    │   ├── Report
    │   └── Staff
    ├── Config
    ├── Discord
    │   └── Commands
    │       └── Helpers
    │           └── Arguments
    ├── Events
    │   └── Modifiers
    ├── Types
    └── Utils
        ├── Managers
        └── Scheduler

3.7 Lifecycles ​

Paper (AppelToolsPaperBootstrap.onEnable → AppelToolsPaper constructor) ​

  1. Set paths and data directory; throw StartupException on failure.
  2. Load config.yml, messages.yml, data.yml via YamlStore.
  3. Set Locale from Config.ServerInfo.LOCALE; set serverName from Config.ServerInfo.NAME.
  4. Generate and persist serverUuid (random) if unset.
  5. Resolve LuckPerms provider; throw if missing.
  6. Register VaultEconomyProvider and resolve it back.
  7. Create player manager, console, baltop calculator.
  8. Create all DAOs.
  9. Setup Database (Hikari pool) and async-load ServerData for the server's port.
  10. Create CommandRegistrar and ModuleManager; load modules and register commands.
  11. Create StaffInventoryManager.
  12. If Modules.Discord.ROOT.isEnabled() and token non-empty, load DiscordBot with commands (filtering Bukkit listeners out).
  13. Run PluginChecker.checkPlugins().
  14. Create PluginUpdaterManager.
  15. playerManager.startAutoSaveTask() (5-minute interval).

onShutdown() stops auto-save, awaits saves, unregisters commands, unloads Discord, disconnects DB.

Velocity (AppelToolsVelocityBootstrap @Plugin → AppelToolsVelocity.onProxyInitialization) ​

  1. Inject Logger, ProxyServer, PluginManager, @DataDirectory Path data.
  2. Construct managers/services.
  3. Register Velocity event listeners (forwarded by bootstrap).
  4. Connect to MySQL via Database.
  5. Build LiteCommands via CommandRegistrar.
  6. Load modules via ModuleManager.
  7. Optionally start DiscordBot, PunishmentManager auto-save, AnnouncementManager.

onProxyShutdown() reverses: stops schedulers, unregisters commands, disconnects DB, unloads Discord.

3.8 Library Relocations (shadowJar) ​

To avoid classpath conflicts when deployed alongside other plugins:

Paper shadowJar relocates:

  • dev.rollczi.litecommands → me.Maussee.AppelTools.libs.litecommands

Velocity shadowJar relocates:

  • com.mysql → me.Maussee.AppelTools.libs.mysql
  • com.zaxxer.hikari → me.Maussee.AppelTools.libs.hikari
  • dev.rollczi.litecommands → me.Maussee.AppelTools.libs.litecommands
  • net.dv8tion.jda → me.Maussee.AppelTools.libs.jda

Built with VitePress.