Skip to content

v5 Modules and Shading

Jake Moore edited this page Aug 31, 2026 · 4 revisions

Modules and Shading

Six modules are published, all under com.kamikazejam.kamicommon. All six can be shaded. Which one you want depends on how much of the toolkit you need and how you intend to deploy.

The inheritance chain

shared-utils              the common base: utilities, LoggerService, collections
  ├── shared-jar          + MySQL (HikariCP), Redis (Lettuce), RabbitMQ
  └── standalone-utils    + the YAML configuration system
        ├── standalone-jar    aggregator: standalone-utils + shared-jar
        └── spigot-utils      + Spigot: KamiPlugin, commands, menus, ItemBuilder, spigot-nms

spigot-jar                the KamiCommon plugin: spigot-utils + shared-jar, all shaded

spigot-utils reaches shared-utils through standalone-utils, which is also how it gets snakeyaml and org.json. spigot-jar depends on both spigot-utils and shared-jar, which is why the database and messaging APIs are available in it but not in spigot-utils.

spigot-utils versus spigot-jar

This is the first decision you make. There are three ways to go, and all three are supported.

Shade spigot-utils for a smaller payload

Roughly 400 KB, and the option to reach for when you want the plugin API without the database and messaging layers.

public class YourPlugin extends KamiPlugin {
    @Override
    public void onEnableInner()  { SpigotUtilsSource.onEnable(this); }
    @Override
    public void onDisableInner() { SpigotUtilsSource.onDisable(); }
}

onEnable() and onDisable() are final on KamiPlugin; onEnableInner() and onDisableInner() are the abstract methods you implement.

Its dependencies arrive unrelocated, and relocating them is your job. spigot-utils exports spigot-nms, item-nbt-api, XSeries, gson, commons-text, snakeyaml and org.json as api dependencies, at their real package names. commons-lang3 comes too, transitively through commons-text, and needs relocating just the same. Shipping those unrelocated means colliding with every other plugin that carries a different version of the same library.

A jar built against spigot-utils without shading is unlikely to work on a server, whether or not the KamiCommon plugin is installed.

Depend on spigot-jar when the plugin is already on the server

Install the KamiCommon plugin, scope the dependency provided (Maven) or compileOnly (Gradle), and add depend: [KamiCommon] to your plugin.yml. Nothing is shaded into your jar and your build stays small.

Shade spigot-jar for the whole toolkit

Everything KamiCommon offers, in one dependency, with no second plugin for your users to install and no relocation work for you. This is a supported and well-tested path.

The trade is size and granularity. spigot-jar publishes zero transitive dependencies because everything is already flattened and relocated inside it, so you take all 19 MB and cannot exclude individual libraries. Wire it up the same way as spigot-utils, using PluginSource instead:

public class YourPlugin extends KamiPlugin {
    @Override
    public void onEnableInner()  { PluginSource.onEnable(this); }
    @Override
    public void onDisableInner() { PluginSource.onDisable(); }
}

What is relocated

Only spigot-jar relocates. Developing against spigot-utils means developing against the real package names.

original relocated to
com.cryptomorin.xseries com.kamikazejam.kamicommon.xseries
de.tr7zw.changeme.nbtapi com.kamikazejam.kamicommon.nbtapi
com.zaxxer.hikari com.kamikazejam.kamicommon.hikari
com.mysql com.kamikazejam.kamicommon.mysql
io.lettuce com.kamikazejam.kamicommon.lettuce
redis.clients com.kamikazejam.kamicommon.redisclients
com.rabbitmq com.kamikazejam.kamicommon.rabbitmq
org.slf4j com.kamikazejam.kamicommon.slf4j
io.netty com.kamikazejam.kamicommon.netty
reactor com.kamikazejam.kamicommon.reactor
org.reactivestreams com.kamikazejam.kamicommon.reactivestreams
org.apache.commons.pool2 com.kamikazejam.kamicommon.commons.pool2
org.yaml.snakeyaml com.kamikazejam.kamicommon.snakeyaml
org.json com.kamikazejam.kamicommon.json
com.google.gson com.kamikazejam.kamicommon.gson
com.google.errorprone com.kamikazejam.kamicommon.errorprone
org.apache.commons.text com.kamikazejam.kamicommon.text
org.apache.commons.lang3 com.kamikazejam.kamicommon.lang3
org.apache.hc.client5 com.kamikazejam.kamicommon.hc.client5
org.apache.hc.core5 com.kamikazejam.kamicommon.hc.core5

Every class in the published spigot-jar lives under com/kamikazejam/kamicommon/, with no exceptions, and the build fails if that stops being true.

Two things that must survive your shade configuration

1. internal-libs/adventure.jar must be copied through intact

The published jar contains a nested jar at internal-libs/adventure.jar. It holds a relocated copy of Adventure, used only on servers below 1.18.2 that have no Adventure of their own. It is loaded through a child classloader at runtime, not from the classpath.

A shade configuration that unpacks nested jars, or that excludes internal-libs/**, produces IllegalStateException: internal-libs/adventure.jar is missing from this jar on any pre-1.18.2 server. Shadow copies it through byte-identically by default; you only break this by going out of your way.

Java cannot read a jar nested inside a jar, so on a pre-1.18.2 server the copy is extracted to plugins/<plugin>/internal/adventure.jar and loaded from there. The directory is the data folder of the plugin that owns the KamiCommon copy in use, so a server owner sees one such file per plugin that shades it. Nothing is extracted on 1.18.2 and above.

You cannot import anything inside it. See Adventure and Server Versions.

2. Do not relocate com.kamikazejam.kamicommon.nms.bundle.*

Version-specific implementations are resolved by string name at runtime. If your own relocation rules rewrite com.kamikazejam.kamicommon.nms.bundle.* or com.kamikazejam.kamicommon.nms.text.TextBundleImpl_*, the lookup fails and nothing loads.

KamiCommon's own shading is safe because it relocates only third-party packages. A consumer applying a blanket relocation of com.kamikazejam.** is not.

Removed soft dependencies

As of 5.0.0-alpha.17, KamiCommon no longer soft-depends on Citizens, ItemsAdder or MythicMobs. The integration classes and the onItemsAdderLoaded() / onMythicMobsLoaded() / onCitizensLoaded() subsystem hooks are gone. If you relied on those hooks for load ordering, listen for the plugins' own events instead.

Clone this wiki locally