> For the complete documentation index, see [llms.txt](https://buildsystem.eintosti.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://buildsystem.eintosti.de/v4/developer-portal/world-management.md).

# World Management API

Programmatically create, import, and manage worlds using the `WorldService` and fluent builders.

***

## 1. World Creation & Import (Fluent API)

### Generating a Fresh World

To generate a new world, use `WorldService#newWorld(String)` which returns a `WorldBuilder` instance. Chain options and execute `.build()` synchronously:

```java
import de.eintosti.buildsystem.api.BuildSystem;
import de.eintosti.buildsystem.api.BuildSystemProvider;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.WorldService;
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
import org.bukkit.Difficulty;

WorldService worldService = BuildSystemProvider.get().getWorldService();

BuildWorld lobbyWorld = worldService.newWorld("Lobby_01")
    .type(BuildWorldType.NORMAL)
    .difficulty(Difficulty.PEACEFUL)
    .time(6000) // Noon
    .worldBorderSize(5000)
    .privateWorld(false) // false = public (EVERYONE), true = private (ADDED_PLAYERS)
    .build(); // Synchronous. Must run on Bukkit's main thread.
```

### Importing an Existing Directory

To register an existing world folder present in the server container:

```java
import de.eintosti.buildsystem.api.world.creation.WorldImporter;

BuildWorld importedWorld = worldService.importWorld("legacy_lobby")
    .privateWorld(true) // true = private (ADDED_PLAYERS)
    .build(); // Synchronous. Must run on Bukkit's main thread.
```

### Async Operations (Bulk Import, Delete, and Unimport)

Bulk imports, unimports, and deletion tasks operate asynchronously to protect tick timing.

```java
import de.eintosti.buildsystem.api.world.lifecycle.SaveBehavior;

// Bulk-import unregistered world directories (spread across ticks to prevent lag)
worldService.importWorlds().thenAccept(importedCount -> {
    getLogger().info("Successfully imported " + importedCount + " worlds.");
});

// Unimport (unload registry entries without deleting directory files)
worldService.unimportWorld(buildWorld, SaveBehavior.SAVE).thenRun(() -> {
    getLogger().info("Unimported world successfully.");
});

// Delete (unload registry entries and permanently delete directory)
worldService.deleteWorld(buildWorld).thenRun(() -> {
    getLogger().info("Deleted world directory from disk.");
});
```

***

## 2. Accessing & Mutating World Data

`BuildWorld` represents the metadata of a world. You can access the live Bukkit `World` handle (if loaded) or mutate properties directly through the flat `WorldData` interface.

### Resolving the Bukkit World

```java
// Returns Optional.empty() if the world is currently unloaded
Optional<org.bukkit.World> bukkitWorldOpt = buildWorld.getWorld();
if (bukkitWorldOpt.isPresent()) {
    org.bukkit.World world = bukkitWorldOpt.get();
}
```

### World Settings (`WorldData`)

Every world setting is addressed through a typed `WorldDataKey<T>`: read it with `get(key)` and write it with `set(key, value)`. The key carries the value type, so no cast is needed at the call site. The built-in keys (`PERMISSION`, `PROJECT`, `STATUS`, `DIFFICULTY`, `MATERIAL`, `BLOCK_BREAKING`, `VISIBILITY`, …) live on `WorldDataKey`.

```java
import de.eintosti.buildsystem.api.world.data.WorldData;
import de.eintosti.buildsystem.api.world.data.WorldDataKey;
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
import de.eintosti.buildsystem.api.world.data.WorldStatusRegistry;
import com.cryptomorin.xseries.XMaterial;

WorldData data = buildWorld.getData();

// Read settings
boolean physicsEnabled = data.get(WorldDataKey.PHYSICS);
BuildWorldStatus status = data.get(WorldDataKey.STATUS);
boolean canBreak = data.get(WorldDataKey.BLOCK_BREAKING);

// Write settings (persisted with the world)
data.set(WorldDataKey.PHYSICS, false);
data.set(WorldDataKey.MATERIAL, XMaterial.GRASS_BLOCK);
data.set(WorldDataKey.CUSTOM_SPAWN, "0.0;64.0;0.0;90.0;0.0"); // x;y;z;yaw;pitch

// Statuses are interfaces resolved via the registry (returns Optional)
WorldStatusRegistry registry = BuildSystemProvider.get().getStatusRegistry();
registry.getStatus("finished").ifPresent(s -> data.set(WorldDataKey.STATUS, s));
```

The custom spawn has a parsed helper, `data.getCustomSpawnLocation()`, returning a Bukkit `Location` (or `null` when unset/invalid).

***

## 3. Save Behavior Configuration

When unloading or unimporting worlds, specify saving guidelines using the `SaveBehavior` enum:

* `SaveBehavior.SAVE`: Saves modified chunks and database properties to disk before unloading.
* `SaveBehavior.DISCARD`: Discards block changes from memory (rolled back) before unloading the world.

***

## 4. API Enumerations Directory

### `BuildWorldType`

Exposed by `BuildWorld#getType()` and `BuildWorldCreateEvent#getType()`. Defines the dimension or generator layout:

| Enum Constant | Description                                                   |
| ------------- | ------------------------------------------------------------- |
| `NORMAL`      | Standard vanilla terrain generation.                          |
| `FLAT`        | Flatworld grid generation.                                    |
| `NETHER`      | Nether dimension layout.                                      |
| `END`         | End dimension layout.                                         |
| `VOID`        | Void chunk generation (empty space).                          |
| `CUSTOM`      | Chunk generation controlled by third-party generator plugins. |
| `IMPORTED`    | World directory adopted from an existing server folder.       |
| `TEMPLATE`    | World copied from a template source directory.                |
| `PRIVATE`     | World that defaults to creator-only modification access.      |
| `UNKNOWN`     | World type could not be determined or is not recognized.      |

### `BuildWorldStatus`

An interface representing the progress state of a world, resolved and managed via `WorldStatusRegistry` (`BuildSystemProvider.get().getStatusRegistry()`). Two statuses are equal when they share the same id, so compare with `equals()` (or `getId()`), never `==`. The built-in default status IDs are:

| ID                | Description                                                                                                                                                                             |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_started`     | Default status upon world generation.                                                                                                                                                   |
| `in_progress`     | Builder actions are underway.                                                                                                                                                           |
| `almost_finished` | Final detailing is active.                                                                                                                                                              |
| `finished`        | Project completed.                                                                                                                                                                      |
| `archive`         | Disables block modifications (`buildingAllowed = false`). Adventure mode enforcement is a separate config option (`settings.archive.change-gamemode`), not an inherent status property. |
| `hidden`          | Hides the world from default navigator listings.                                                                                                                                        |

### `Visibility`

An enum defining the access restrictions on a world:

* `Visibility.EVERYONE`: Visible to all players (public).
* `Visibility.ADDED_PLAYERS`: Restricted to the creator and added builders (private).

### `NavigatorCategory`

An interface representing navigator tab groupings, resolved and managed via `NavigatorCategoryRegistry` (`BuildSystemProvider.get().getNavigatorCategoryRegistry()`). Built-in defaults include `public`, `private`, and `archive`. Like statuses, categories are equal by id — compare with `equals()`, not `==`.

### `WorldSetting`

Evaluated in custom code via `WorldPermissions#canModify(Player, WorldSetting)` to check permission guards:

* `WorldSetting.BLOCK_BREAKING`: Restricts block breaks.
* `WorldSetting.BLOCK_PLACEMENT`: Restricts block placements.
* `WorldSetting.BLOCK_INTERACTIONS`: Restricts door/trapdoor opening and container interactions.
