For the complete documentation index, see llms.txt. This page is also available as Markdown.

Migration Guide

Upgrade reference for moving between major versions of BuildSystem.


Upgrading from v3 to v4

4.0.0 is a major release. The plugin migrates its data, config.yml, and messages.yml automatically on the first server start — a working server needs no manual steps. The breaking changes are the runtime requirements (Java and Minecraft versions) and the buildsystem-api surface for dependent plugins.

Read the sections below for the full picture: requirements, automatic conversion, configuration, permissions, commands, language, and API.


1. System Requirements

These are hard requirements — the plugin will not start otherwise.

Requirement
v3
v4

Java

21

25

Minecraft

1.21+

26.1 – 26.2

Server software

Spigot / Paper

Spigot / Paper (game-rule access bridged through XSeries, so both run cleanly)

Upgrade your server's JDK to 25 before dropping in the new jar.


2. Automatic Data & File Conversion

On the first 4.0.0 boot the plugin upgrades each legacy structure in place. Nothing is lost; unrecognized values fall back to a sensible default.

Data Element
Legacy Format (v3)
New Format (v4)
Notes

Storage keying

worlds.yml / folders.yml keyed by world/folder name

Keyed by a stable UUID, with the name stored as a field

A rename is now a field update, not a key move, so renames no longer leave orphaned entries. Folder parent references switch from the parent's name to its UUID.

World status

IN_PROGRESS (uppercase enum)

in_progress (lowercase registry id)

Unrecognized values default to not_started.

World visibility

private: true / false

visibility: ADDED_PLAYERS / EVERYONE

One-to-one mapping.

Folder category

category: PUBLIC (uppercase enum)

category: public (lowercase registry id)

Unrecognized values default to public.

Status display names

status_in_progress: "&6In Progress" in messages.yml

displayName + color in statuses.yml

Seeded on first boot only if statuses.yml does not exist yet. The leading colour code is split into color; the remainder becomes displayName, preserving any rename/translation.

config.yml / messages.yml

Older layouts

Versioned, auto-migrated

Missing keys are appended and some keys are relocated; existing customisations are preserved.

Before re-keying, the plugin writes a one-time backup next to each affected file:

  • plugins/BuildSystem/worlds.yml.v3.bak

  • plugins/BuildSystem/folders.yml.v3.bak

The migration also creates two new files for the now-customizable statuses and categories:

  • plugins/BuildSystem/statuses.yml

  • plugins/BuildSystem/categories.yml

After the first boot, statuses.yml is authoritative. The status_* keys in messages.yml are no longer read and can be removed (see the Language File section below).


3. Configuration File Changes

config.yml is versioned and migrated on load, so custom values survive the upgrade. Two flags are gone and one is new.

Removed Keys

Silently ignored in v4 — safe to delete from config.yml:

  • settings.per-option-permissions — superseded by the always-on buildsystem.setting.<option> nodes.

  • settings.restrict-template-access — superseded by the deny-to-restrict buildsystem.create.template.<name> model.

New Keys

  • settings.world-permission-whitelist (default: []) — restricts the permission strings /worlds setPermission may assign. An empty list allows any value.


4. Permission Changes

Existing command permissions are unchanged. v4 adds the following.

New Static Nodes

Permission
Default
Description

buildsystem.savetemplate

OP

Run /worlds saveTemplate to copy a live world into templates/.

buildsystem.edit.pin

OP

Pin worlds to the top of navigator lists via the Edit GUI.

buildsystem.edit.icon

OP

Set a world's custom icon material or skull texture in the Edit GUI.

New Dynamic Nodes

Resolved at runtime from the id of the status, category, template, or generator:

Permission Pattern
Default
Description

buildsystem.create.<categoryId>

OP

Create a world in a specific category (e.g. buildsystem.create.public). Admins with the create bypass may create in any category.

buildsystem.navigator.<categoryId>

true

Show the category in the navigator and enable its /worlds <category> shortcut. Deny it to hide a category and disable its command together.

buildsystem.setstatus.<statusId>

inherits buildsystem.setstatus (OP)

Assign a status to a world. Built-in statuses strip underscores for backwards compatibility (in_progress…inprogress); custom statuses use their full id (my_status…my_status).

buildsystem.create.template.<name>

true

Use a specific template. Deny the node to restrict it.

buildsystem.create.generator.<name>

true

Use a specific chunk generator. Deny the node to restrict it.

buildsystem.setting.<option>

true

Toggle a /settings option (e.g. buildsystem.setting.noclip). Deny to restrict.


5. Navigator Command Changes

The fixed /worlds archive, /worlds private, and /worlds public subcommands are replaced by per-category /worlds <category> shortcuts, generated from the navigator layout instead of being hardcoded.

Existing setups keep working: the three built-in categories still answer to archive, private, and public. A real subcommand always wins a name clash, so a custom category named like a command can never shadow it.


6. Language File (messages.yml) Changes

  • Default English: delete messages.yml and restart to regenerate a fresh file with every v4 key.

  • Custom translations: keep the file; the plugin appends new keys on startup. Localize the newly added keys manually.

Obsolete Keys (can be removed)

No longer read — their values were copied into statuses.yml on the first boot:

  • status_not_started, status_in_progress, status_almost_finished, status_finished, status_archive, status_hidden

Changed Keys

  • world_navigator_create_world — default changed to &bCreate a World because clicking the item now opens a category picker.


7. Developer API Changes

Plugins compiling against buildsystem-api must recompile against 4.0.0 and apply the changes below.

Breaking Changes

API Element
Legacy Code (v3)
Upgrade Action (v4)

Event package

de.eintosti.buildsystem.api.event.BuildWorldManipulationEvent

Import from de.eintosti.buildsystem.api.event.world instead.

World creation

WorldService.createWorld(...)

Fluent builder: worldService.newWorld(name)…build().

World importing

WorldService.importWorld(name, ...)

Fluent builder: worldService.importWorld(name)…build().

Properties

Type<T>

Renamed to Property<T>.

Bukkit handle

BuildWorld.getWorld() returned a nullable World

Now returns Optional<org.bukkit.World>.

World status

BuildWorldStatus (enum)

Now an interface resolved via BuildSystem.getStatusRegistry(). Compare by getId() / equals(), never == or switch.

Categories

NavigatorCategory (enum)

Now an interface resolved via BuildSystem.getNavigatorCategoryRegistry(); Folder.getCategory() returns it. Compare by getId() / equals(), never == or switch.

Visibility

isPrivateWorld() / setPrivateWorld(boolean)

Replaced by WorldData.getVisibility() / setVisibility(Visibility) (EVERYONE / ADDED_PLAYERS).

API lookup

BuildSystemProvider.register() / unregister()

No longer public. Resolve via BuildSystemProvider.get() or Bukkit's ServicesManager.

Removed

  • BuildWorld.setLoaded(boolean) — the read-only isLoaded() remains.

  • BuildWorld.asProfileable() — resolve head icons through Displayable.getHeadProfile() / getIconSkullTexture().

  • WorldData.getConfigFormat() and WorldData.getAllData().

  • The public registration entrypoints on BuildSystemProvider (see above).

New (non-breaking)

Available to dependent plugins but not required for an upgrade:

  • World lifecycle events in event.world (BuildWorldCreateEvent, BuildWorldPostCreateEvent, BuildWorldDeleteEvent, BuildWorldPostDeleteEvent, BuildWorldRenameEvent, BuildWorldUnimportEvent, BuildWorldStatusChangeEvent), plus backup and folder events in event.backup and event.folder.

  • WorldService.importWorlds() for bulk import spread across ticks.

  • Direct WorldData accessors (getStatus()/setStatus(), isPhysics()/setPhysics(), …) alongside the property objects.

  • WorldStatusRegistry and NavigatorCategoryRegistry, exposed via BuildSystem.getStatusRegistry() / getNavigatorCategoryRegistry().

  • Displayable.getIconSkullTexture() / getHeadProfile() for custom head icons.

Last updated