Skip to main content

Plugin resources

Every Versatia plugin extracts the files it ships under a resources directory into its data folder when it starts and at every reload. Nothing has to be declared: put the files there and they appear on the server.

Where the files go​

In the buildIn the JAROn the server
src/main/resources/resources/config.ymlresources/config.ymlplugins/<Name>/config.yml
src/main/resources/resources/lang/en.ymlresources/lang/en.ymlplugins/<Name>/lang/en.yml

The directory layout under resources/ is kept. Only files are copied; an empty directory in the JAR creates nothing.

For plugin developers

Everything under src/main/resources/resources/ is copied into the plugin's data folder, with its layout, and never overwritten once it is there: what you ship are the defaults. Anything else in src/main/resources/, such as plugin.yml, stays inside the JAR.

For server admins

The server admin's side, editing the copies and getting a default back, is in Configuration files of the server admin guide.

Existing files are never overwritten​

A file that already exists in the data folder is left exactly as it is, whatever the JAR contains. Server owners edit the extracted copies, and an update of the plugin does not undo their changes. To get a fresh copy of a file, delete it and run /versatia reload <name> or restart the plugin.

When it happens​

Extraction runs at PLUGIN_RELOAD_OR_START, first: at start before any bean is created, any @Value property is read or any auto-invoked function runs, and again at every reload before the values are read. So a value always finds its file, and a file the administrator deleted comes back with its default at the next reload.

Reading the files is the job of the features built on them. A single value is a @Value property set from the extracted file, so the shipped file is where the defaults live:

@LocalBean
class Shop {
@Value("greeting", file = "messages.yml")
lateinit var greeting: String
}

Texts shown to players belong to Messages, which reads messages/. A file of your own format is read in a PLUGIN_RELOAD_OR_START function, so a reload picks up its changes, with loadYamlOrThrow and the strict getters of the configuration utilities; never in a constructor, which runs once.

Why every plugin has it​

VersatiaPlugin is annotated with @ExtractResources, and an enhancement declared on a base class applies to every plugin extending it, as explained under Enhancements and processors. A main class that extends JavaPlugin directly can carry the annotation itself. The processor behind it is ExtractResourcesEnhancementProcessor (ResourceProcessors.EXTRACT); it reads the files from the plugin's own JAR, never from a dependency.

The classpath directory is fixed to resources (ExtractResources.DIRECTORY). Files placed anywhere else in src/main/resources, such as plugin.yml, stay inside the JAR.

Switching it off​

A plugin that wants to handle its files itself switches the feature off on its main class:

@DisableVersatiaFeatures(extractResources = true)
class MyPlugin : VersatiaPlugin()

The descriptor then carries no extraction element at all; nothing happens at runtime. The annotation is accepted on the main class and on its base classes only, and the nearest declaration wins: a base class may switch the feature off and a subclass may declare @ExtractResources again. Writing @DisableVersatiaFeatures without switching anything on, or next to @ExtractResources on the same class, is a compile error. Every feature a plugin inherits and its switch are listed under Enhancements on a base class.

Corner cases​

  • A link counts as a file. Anything at the destination, a symbolic link included, even one pointing nowhere, keeps the JAR's copy out; a configuration the administrator shares through a link is left alone.
  • A deleted file comes back at the next reload or start, with the content of the JAR the server runs now.
  • Empty directories in the JAR create nothing in the data folder.