Skip to main content

Versatia

Declare what your Paper plugin has. Versatia takes care of when and how.

A Kotlin framework for Paper 1.21.4 plugins. Dependency injection and lifecycle hooks resolved at compile time, executed by a small runtime, with nothing discovered on the server.

class ShopPlugin : VersatiaPlugin() {

@AutoInvoke(Phase.PLUGIN_RELOAD_OR_START)
private fun start(prices: PriceList) =
logger.info("Loaded ${prices.size} prices")
}

@LocalBean
class PriceList(private val config: ShopConfig) {
val size get() = config.prices.size
}

@LocalBean
class ShopConfig {
@Value("prices")
var prices: Map<String, Int> = emptyMap()
}

How it works

1

Annotate

Mark classes with a bean scope and functions with @AutoInvoke. Constructor parameters are the dependencies.

2

Build

The VersatiaAPI KSP processor validates the graph and generates a descriptor next to your main class. Cycles and ambiguity stop the build.

3

Run

VersatiaCore reads the descriptor when the plugin enables, creates the beans in dependency order and calls your functions.

Dependency injection

Constructor injection with three scopes: @LocalBean, @ExposeSingleton and @ExposePrototype. Beans can be shared between plugins; @Qualifier and @Primary resolve ambiguity.

Learn about beans →

Lifecycle hooks

@AutoInvoke(phase) runs a function at plugin start, reload or stop with its parameters injected. There is nothing to override in the main class.

Auto-invoked functions →

Errors at build time

Dependency cycles, ambiguous injections and beans that cannot be constructed fail the build with a message pointing at the line. Nothing broken reaches a server.

Compile-time checks →

Encapsulation kept

Beans, constructors and functions may be private. Generated code calls visible members directly and falls back to reflection only where it has to.

The descriptor →

Utilities over Paper

Strict configuration getters, deep-merging maps, scheduler and logging shorthands, primary-thread checks and reflection helpers, usable without the runtime.

Utilities →

Extensible core

Annotations are enhancements interpreted by processors, and scopes can be inherited to define your own. The descriptor format is a versioned contract.

Enhancements and processors →