Repository navigation
Architecture
Pavel Erokhin edited this page Nov 9, 2026
·
8 revisions
Mo’Bosses is a Paper plugin in Kotlin, and Fabric and NeoForge mods are on their way. The code lives in five Gradle modules, one package per concern under ru.mairwunnx.mobosses. This page maps the modules and the packages and lists the rules that keep the plugin working.
| Module | What it holds |
|---|---|
core/ |
What doesn’t touch a game platform: Log, algebra/, config/ but Ids, lang/ but PlayerLanguages and Texts, progress/Store and Tables, combat/Shares, boss/Codec, and every file the plugin copies (the configs, lang/, bundled.sha256). No Bukkit and no Minecraft |
paper/ |
The plugin: everything that calls Bukkit or Paper, and paper-plugin.yml. Its jar is mobosses-paper-X.Y.Z.jar
|
modcore/ |
What both mods share, the game without a loader, compiled against NeoForm: one package per Paper package under ru.mairwunnx.mobosses.modcore, each file the twin of Paper’s, the mixins and Hooks where they land, MoBosses for one server, the messages between a player’s game and the server (net/), and the settings screen and loot pages (client/). Its game tests run on both loaders |
fabric/, neoforge/
|
The mods, thin adapters around modcore, for dedicated servers and singleplayer and LAN worlds: the entries, the loader’s events, permissions, and channel, the client entries, and the test mods |
The packages stay the same in every module, so a class moves between core and paper without a change to its imports. A class goes to core once nothing in it, and nothing it uses, needs Bukkit.
| Where | What it does |
|---|---|
MoBossesPlugin.kt |
Startup, reload(), and shutdown. Reload reads every file again and keeps the plugin, its command, and its bosses running |
MoBossesCommand.kt |
/mobosses and its subcommands, with suggestions |
config/ |
One model per file (Settings, AbilitySettings, Classes, BossSpec, MinionSettings, RewardSettings, LootTable), read by Configs through kaml, not strict. Yamls.decode drops a value that doesn’t fit, with a warning, so it takes its default. Ids resolves game ids against the registries, 1.x enum names included |
algebra/ |
The math, pure: Curves (the shared growth curve), Stats (health, damage, armor, vanilla experience), Leveling (player levels, boss levels, relevance), Rolls (minions, cooldowns, weighted picks) |
boss/ |
Catalog (configs with ids resolved), Bosses (live bosses: make, adopt, forget), BossFactory and Equipment (stats and gear), Boss (the fight state, kept on the entity through Keys and Codec), Minions, NameTags, BossBars, Visuals, Decoys, Despawns
|
spawn/ |
SpawnListener (events), NaturalSpawns (the roll and the level), SpawnLimiter (cooldowns per player, the cap on bosses nearby), FullMoon, SurvivalBonus
|
combat/ |
DamageListener (shares, bars, abilities on hit), DeathListener (experience, kills, loot, rewards, the kill message), Shares, Loot, Rewards, GroupHealth, SpawnerFatigue
|
ability/ |
Ability and its context Cast. Abilities picks one on a hit. kinds/ holds one object per shared ability and signature/ one per boss type’s own. Targets decides who may be hit and where the ground is. Arrows shoots for the arrow abilities |
achievement/ |
The advancements tab: Achievement lists them, Achievements loads and grants them |
menu/ |
Stats (cards, the board, boss counts, from the database off the server thread), Menu, Bestiary, BossList, LanguagePage, MenuListener
|
progress/ |
Players’ levels and boss statistics: Progression (a cache filled at login), Store (Exposed over SQLite, MySQL/MariaDB, or PostgreSQL) on a thread of its own, Tables, DeathPenalty
|
lang/ |
Message, Languages, LanguageFiles, LocaleResolver, GeoIp, PlayerLanguages, LanguageChoices, Texts (rendering, boss names, classes, minions) |
protect/ |
Guard and Guards, the GriefPrevention and WorldGuard adapters and flags, BlockLog and CoreProtectLog, and BlockChanges with TemporaryBlocks, the only way abilities touch blocks |
hooks/ |
PlaceholderAPI (Expansion, Placeholders), MiniPlaceholders (MiniPlaceholderTags), Plan (PlanData), WorldAPI (BossesExpansion, through WorldAPI’s expansion API 2, com.mairwunnx:worldapi-expansion, and WorldApiLink, which the rest of the plugin calls and which loads without WorldAPI), and Allay (AllayBosses, through Allay’s expansion API 2, chat.allay:allay-expansion, and AllayLink, the same way) |
- Threads. Bukkit calls stay on the server thread. The database and GeoIP downloads run off it. PlaceholderAPI, Plan, and MiniPlaceholders may ask from any thread, so they read only the progress cache and counts the server thread keeps.
-
What a boss is. Any entity that carries
mobosses:type,mobosses:class, andmobosses:level. Fight state that must outlive a restart (damage shares, cooldowns, enrage) lives on the boss. Cooldowns that must outlive a relog (rewards, spawns) live on the player. Never keep it only in memory, and never force-load chunks for a boss. -
Names. Names over mobs are
TextDisplaypassengers, not saved, invisible by default, and shown per player byNameTags. -
Ability entities, like meteors and arrows, are
isPersistent = false, so a restart never brings one back. -
Blocks. Abilities change blocks only through
BlockChanges.setorsetFor. That asks the guards, logs to CoreProtect before the change, in the same tick, and restores temporary blocks on shutdown. -
Targets. Abilities hit players through
Targets, which checks the game mode andGuard.canHurt, and the pets and golems that hit the boss in the last 15 seconds. Nothing else. -
Never weaker than vanilla.
BossFactorykeeps every stat at least the mob’s own, andEquipmentputs on only stronger pieces of the same kind. -
Core stays platform-free. Nothing in
coreimportsorg.bukkit,io.papermc, ornet.minecraft, so the mods can share it. -
Optional plugins are
compileOnlyandjoin-classpathinpaper-plugin.yml. Their classes are touched only after checking the plugin is enabled. WorldGuard flags register inonLoad, the only time WorldGuard takes them. -
Game ids stay strings in the config models and resolve in
Catalog. A bad one logs a warning and drops out, never failing the file. -
Player text goes into messages through
Placeholder.unparsed. PlaceholderAPI goes through the<papi:…>tag only. -
The database. The table
player_progresskeeps 1.x’s name, columns, and index. Progress changes go throughStore.add, which reads and writes in one transaction.
-
A new ability. An object in
ability/kinds/, listed inAbilities.PICKED, with its keys in a section of its own inAbilitySettingsandabilities.yml(asobelisk,chain,doubles, andphase_twodo), a threshold inAbilityThresholdsandclasses.yml, and a message in every language. -
A new message. A
Messageentry and a line in every file incore/src/main/resources/lang/. A new boss type, minion, class, or lootidneeds its name in every language too. -
A new config key. The same default in its model as in the bundled file. 1.x files must keep loading (
core/src/test/resources/v1/).
ResourcesTest fails when any of these is missing.
Next: Development