Initial commit
Build main / build (21) (push) Failing after 13m38s

This commit is contained in:
Laura
2026-08-09 15:17:12 +02:00
commit 6bf2a93935
285 changed files with 32332 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
applyCommonConfiguration()
plugins {
id("java")
id("maven-publish")
id("signing")
}
project.description = "API"
dependencies {
compileOnly(libs.spigot)
compileOnly(libs.xseries)
compileOnly(libs.annotations)
compileOnly(libs.jspecify)
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
pom {
name.set("BuildSystem API")
description.set("API for the BuildSystem Minecraft plugin.")
url.set("https://github.com/thomasmny/BuildSystem")
licenses {
license {
name.set("GNU General Public License, Version 3")
url.set("https://www.gnu.org/licenses/gpl-3.0.txt")
distribution.set("repo")
}
}
developers {
developer {
id.set("thomasmny")
name.set("Thomas Meaney")
email.set("thomas.meaney@icloud.com")
}
}
scm {
connection.set("scm:git:git://github.com/thomasmny/BuildSystem.git")
developerConnection.set("scm:git:ssh://github.com:thomasmny/BuildSystem.git")
url.set("https://github.com/thomasmny/BuildSystem")
tag.set(project.version.toString())
}
issueManagement {
system.set("GitHub")
url.set("https://github.com/thomasmny/BuildSystem/issues")
}
}
}
}
}
signing {
val signingKeyId: String? by project
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
isRequired = true
sign(publishing.publications["mavenJava"])
}
+11
View File
@@ -0,0 +1,11 @@
<body>
<p>
BuildSystem is a utility plugin targeted towards build-teams.
It allows worlds to be easily managed and also provides handy tools to assist with building.
</p>
<h1>Useful Links</h1>
<ul>
<li><a target="_top" href="https://buildsystem.eintosti.de">Project Website</a></li>
<li><a target="_top" href="https://github.com/thomasmny/BuildSystem">Source Code</a></li>
</ul>
</body>
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api;
import de.eintosti.buildsystem.api.player.BuildPlayer;
import de.eintosti.buildsystem.api.player.PlayerService;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.WorldService;
import org.jspecify.annotations.NullMarked;
/**
* The BuildSystem API.
*
* @since 3.0.0
*/
@NullMarked
public interface BuildSystem {
/**
* Gets the {@link WorldService}, responsible for managing {@link BuildWorld} instances.
*
* @return The world manager
*/
WorldService getWorldService();
/**
* Gets the {@link PlayerService}, responsible for managing {@link BuildPlayer} instances.
*
* @return The player manager
*/
PlayerService getPlayerService();
}
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NullMarked;
/**
* Provides static access to the {@link BuildSystem} API.
*
* @since 3.0.0
*/
@NullMarked
public class BuildSystemProvider {
@Nullable
private static BuildSystem instance = null;
/**
* Sole private constructor to prevent instantiation.
*
* @throws AssertionError Always, as this class is not meant to be instantiated
*/
@ApiStatus.Internal
private BuildSystemProvider() {
throw new AssertionError("This class is not meant to be instantiated");
}
/**
* Gets an instance of the {@link BuildSystem} API.
*
* @return An instance of the BuildSystem API
* @throws IllegalStateException if the API is not loaded yet
*/
public static BuildSystem get() {
BuildSystem instance = BuildSystemProvider.instance;
if (instance == null) {
throw new IllegalStateException("BuildSystem has not loaded yet!");
}
return instance;
}
@ApiStatus.Internal
static void register(BuildSystem instance) {
BuildSystemProvider.instance = instance;
}
@ApiStatus.Internal
static void unregister() {
BuildSystemProvider.instance = null;
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.data;
import org.jspecify.annotations.NullMarked;
/**
* A {@link Capability} that marks a {@link Type} as being bypassable with a specific permission.
*
* @param permission The permission node required to bypass this type
* @since 3.0.1
*/
@NullMarked
public record Bypassable(String permission) implements Capability {
}
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.data;
/**
* A marker interface for a "capability" or "attachment" that can be added to a {@link Type}.
*
* @since 3.0.1
*/
public interface Capability {
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.data;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* A {@link Capability} that marks a {@link Type} as being overridable by an external source.
*
* @param <T> The type of the value being overridden
* @param isEnabled A supplier that returns {@code true} if the override is active
* @param provider A supplier that returns the override value or {@code null} if no override is set
* @since 3.0.1
*/
@NullMarked
public record Overridable<T>(
BooleanSupplier isEnabled,
Supplier<@Nullable T> provider
) implements Capability {
}
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.data;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
/**
* A generic interface representing a configurable data type.
*
* @param <T> The type of the value held by this data point
*/
@NullMarked
public interface Type<T> {
/**
* An immutable implementation of the {@link Type} interface using a Java Record. This class holds a final, read-only value.
*
* @param <T> The type of the value held
* @param value The immutable value
*/
record ImmutableType<T>(T value) implements Type<T> {
/**
* Gets the immutable value.
*
* @return The value
*/
@Override
public T get() {
return value;
}
/**
* Throws {@link UnsupportedOperationException} as this type is immutable.
*
* @param value The value to set (which is ignored)
* @throws UnsupportedOperationException Always, as this type cannot be modified
*/
@Contract("_ -> fail")
@Override
public void set(T value) {
throw new UnsupportedOperationException("This Type is immutable and cannot be modified.");
}
/**
* Gets the immutable value formatted for storage.
*
* @return The immutable value
*/
@Override
public Object getConfigFormat() {
return value;
}
}
/**
* An immutable {@link Type} representing the boolean value {@code true}.
*/
Type<Boolean> TRUE = new ImmutableType<>(true);
/**
* Gets the current value of this data point.
*
* @return The current value
*/
T get();
/**
* Sets the value of this data point.
*
* @param value The new value to set
*/
void set(T value);
/**
* Gets the value of this data point formatted for storage in a configuration file.
* This might involve converting complex objects into simpler types (e.g., enums to strings).
*
* @return The value formatted for a config file
*/
Object getConfigFormat();
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces for events related to the BuildSystem API. These events allow external plugins to hook into and react to various actions within the BuildSystem.
*/
package de.eintosti.buildsystem.api.event;
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Represents a {@link BuildWorld} related event.
*
* @since 3.0.0
*/
@NullMarked
public class BuildWorldEvent extends Event {
private static final HandlerList HANDLER_LIST = new HandlerList();
private final BuildWorld buildWorld;
/**
* Constructs a new {@link BuildWorldEvent}.
*
* @param buildWorld The {@link BuildWorld} involved in this event
*/
@Internal
public BuildWorldEvent(BuildWorld buildWorld) {
this.buildWorld = buildWorld;
}
/**
* Gets the {@link BuildWorld} involved in this event
*
* @return The world involved in this event
*/
public BuildWorld getBuildWorld() {
return buildWorld;
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
/**
* Gets the handler list for this event.
*
* @return The handler list
*/
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Called when a {@link BuildWorld} is loaded.
*
* @since 3.0.0
*/
@NullMarked
public class BuildWorldLoadEvent extends BuildWorldEvent implements Cancellable {
private boolean cancelled = false;
/**
* Constructs a new {@link BuildWorldLoadEvent}.
*
* @param buildWorld The {@link BuildWorld} that is about to be loaded
*/
@Internal
public BuildWorldLoadEvent(BuildWorld buildWorld) {
super(buildWorld);
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Called after a {@link BuildWorld} has loaded.
*
* @since 3.0.0
*/
@NullMarked
public class BuildWorldPostLoadEvent extends BuildWorldEvent {
/**
* Constructs a new {@link BuildWorldPostLoadEvent}.
*
* @param buildWorld The {@link BuildWorld} that has been loaded
*/
@Internal
public BuildWorldPostLoadEvent(BuildWorld buildWorld) {
super(buildWorld);
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Called after a {@link BuildWorld} has unloaded.
*
* @since 3.0.0
*/
@NullMarked
public class BuildWorldPostUnloadEvent extends BuildWorldEvent {
/**
* Constructs a new {@link BuildWorldPostUnloadEvent}.
*
* @param buildWorld The {@link BuildWorld} that has been unloaded
*/
@Internal
public BuildWorldPostUnloadEvent(BuildWorld buildWorld) {
super(buildWorld);
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Called when a {@link BuildWorld} is unloaded.
*
* @since 3.0.0
*/
@NullMarked
public class BuildWorldUnloadEvent extends BuildWorldEvent implements Cancellable {
private boolean cancelled = false;
/**
* Constructs a new {@link BuildWorldUnloadEvent}.
*
* @param buildWorld The {@link BuildWorld} that is about to be unloaded
*/
@Internal
public BuildWorldUnloadEvent(BuildWorld buildWorld) {
super(buildWorld);
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.event.world;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jspecify.annotations.NullMarked;
/**
* Called when a player's build mode is toggled. This event can be triggered by the player themselves or by another plugin/player.
*/
@NullMarked
public class PlayerBuildModeToggleEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
private final boolean buildMode;
private final Player causer;
private boolean cancelled;
/**
* Constructs a new {@link PlayerBuildModeToggleEvent}.
*
* @param who The player whose build mode is being toggled
* @param buildMode The new build mode status ({@code true} for enabled, {@code false} for disabled)
* @param causer The player who caused the build mode to be toggled
*/
public PlayerBuildModeToggleEvent(Player who, boolean buildMode, Player causer) {
super(who);
this.buildMode = buildMode;
this.causer = causer;
this.cancelled = false;
}
/**
* Gets the new build mode status.
*
* @return {@code true} if build mode is being enabled, {@code false} otherwise
*/
public boolean isBuildMode() {
return this.buildMode;
}
/**
* Gets the player who caused the build mode to be toggled.
* <p>
* This will return the player themselves if they toggled their own build mode.
*
* @return The player who caused the action, or null.
*/
public Player getCauser() {
return this.causer;
}
/**
* Gets the cancellation state of this event. A cancelled event will not be executed in the server, but will still pass to other plugins
*
* @return true if this event is cancelled
*/
@Override
public boolean isCancelled() {
return this.cancelled;
}
/**
* Sets the cancellation state of this event. A cancelled event will not be executed in the server, but will still pass to other plugins.
*
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
/**
* Gets the handler list for this event.
*
* @return The handler list
*/
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Events relating to a {@link de.eintosti.buildsystem.api.world.BuildWorld}.
*/
package de.eintosti.buildsystem.api.event.world;
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.exception;
/**
* Thrown when an error occurs during the deletion of a world.
*
* @since 3.0.0
*/
public class WorldDeletionException extends WorldException {
/**
* Constructs a new {@link WorldDeletionException} with the specified message and cause.
*
* @param message The detail message
* @param cause The cause of the exception
*/
public WorldDeletionException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.exception;
/**
* Thrown when a world's directory is not found at the expected path.
*
* @since 3.0.0
*/
public class WorldDirectoryNotFoundException extends WorldException {
/**
* Constructs a new {@link WorldDirectoryNotFoundException} with the specified world name and path.
*
* @param worldName The name of the world
* @param path The path to the expected world directory
*/
public WorldDirectoryNotFoundException(String worldName, String path) {
super("World directory for '" + worldName + "' not found at: " + path);
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.exception;
/**
* The base exception for all world-related errors in the BuildSystem API.
*
* @since 3.0.0
*/
public class WorldException extends RuntimeException {
/**
* Constructs a new {@link WorldException} with the specified detail message.
*
* @param message The detail message
*/
public WorldException(String message) {
super(message);
}
/**
* Constructs a new {@link WorldException} with the specified detail message and cause.
*
* @param message The detail message
* @param cause The cause of the exception
*/
public WorldException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.exception;
/**
* Thrown when a requested world cannot be found.
*
* @since 3.0.0
*/
public class WorldNotFoundException extends WorldException {
/**
* Constructs a new {@link WorldNotFoundException} with the specified world name.
*
* @param worldName The name of the world that was not found
*/
public WorldNotFoundException(String worldName) {
super("World '" + worldName + "' does not exist.");
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces for events related to the BuildSystem API. These events allow external plugins to hook into and react to various actions within the BuildSystem.
*/
package de.eintosti.buildsystem.api;
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player;
import de.eintosti.buildsystem.api.player.settings.Settings;
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a player managed by the BuildSystem. This interface provides access to player-specific data and settings within the BuildSystem.
*/
@NullMarked
public interface BuildPlayer {
/**
* Gets the unique-id of the player.
* <p>
* Should match the wrapped {@link Player}'s UUID.
*
* @return The player's UUID
* @see Player#getUniqueId()
*/
UUID getUniqueId();
/**
* Gets the player's custom settings.
*
* @return The player's settings
*/
Settings getSettings();
/**
* Gets values that are supposed to be cached for a short amount of time.
*
* @return The player's cached values
*/
@Internal
CachedValues getCachedValues();
/**
* Gets the location where the player was last before logging off.
*
* @return The location
*/
@Internal
@Nullable
LogoutLocation getLogoutLocation();
/**
* Sets the location where the player was last before logging off.
*
* @param logoutLocation The logout location
*/
@Internal
void setLogoutLocation(@Nullable LogoutLocation logoutLocation);
/**
* Gets the location the player was last at.
* <p>
* Usually this is the last location before teleportation.
*
* @return The player's previous location
*/
@Internal
@Nullable
Location getPreviousLocation();
/**
* Sets the location the player was last at.
* <p>
* Usually this is the last location before teleportation.
*
* @param location The location
*/
@Internal
void setPreviousLocation(@Nullable Location location);
/**
* Gets the {@link NavigatorCategory} the player last looked at.
*
* @return The last looked navigator inventory type
*/
@Internal
@Nullable
NavigatorCategory getLastLookedAt();
/**
* Sets the {@link NavigatorCategory} the player last looked at.
*
* @param type The last looked navigator inventory type
*/
@Internal
void setLastLookedAt(@Nullable NavigatorCategory type);
}
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
/**
* Interface for managing cached values of a player.
*
* @since 3.0.0
*/
@Internal
@NullMarked
public interface CachedValues {
/**
* Saves the given {@link GameMode} to be restored later.
*
* @param gameMode The game mode to save
*/
void saveGameMode(GameMode gameMode);
/**
* Resets the player's game mode to the previously saved one, if present.
*
* @param player The player whose game mode is to be reset
*/
void resetGameModeIfPresent(Player player);
/**
* Saves the given inventory contents to be restored later.
*
* @param inventory The inventory contents to save
*/
void saveInventory(ItemStack[] inventory);
/**
* Resets the player's inventory to the previously saved one, if present.
*
* @param player The player whose inventory is to be reset
*/
void resetInventoryIfPresent(Player player);
/**
* Saves the given walk speed to be restored later.
*
* @param walkSpeed The walk speed to save
*/
void saveWalkSpeed(float walkSpeed);
/**
* Resets the player's walk speed to the previously saved one, if present.
*
* @param player The player whose walk speed is to be reset
*/
void resetWalkSpeedIfPresent(Player player);
/**
* Saves the given fly speed to be restored later.
*
* @param flySpeed The fly speed to save
*/
void saveFlySpeed(float flySpeed);
/**
* Resets the player's fly speed to the previously saved one, if present.
*
* @param player The player whose fly speed is to be reset
*/
void resetFlySpeedIfPresent(Player player);
/**
* Resets all cached values for the given player.
*
* @param player The player whose cached values are to be reset
*/
void resetCachedValues(Player player);
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player;
import org.bukkit.Location;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a player's logout location, which includes the world name and the location coordinates.
*
* @since 3.0.0
*/
@Internal
@NullMarked
public interface LogoutLocation {
/**
* Gets the name of the world the player logged out from.
*
* @return The world name
*/
String worldName();
/**
* Gets the exact {@link Location} the player logged out from.
*
* @return The logout location
*/
@Nullable
Location location();
}
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player;
import de.eintosti.buildsystem.api.storage.PlayerStorage;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.data.Visibility;
import java.util.Set;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NullMarked;
/**
* Service for managing {@link BuildPlayer}.
*
* @since 3.0.0
*/
@NullMarked
public interface PlayerService {
/**
* Gets the {@link PlayerStorage} implementation for managing {@link BuildPlayer} persistence.
*
* @return The {@link PlayerStorage} implementation
*/
PlayerStorage getPlayerStorage();
/**
* Gets a set of all players currently in "build mode".
*
* @return A set of all players in "build mode".
* @see #isInBuildMode(Player)
*/
Set<UUID> getBuildModePlayers();
/**
* Gets whether a player is currently in "build mode".
*
* @param player The player
* @return {@code true} if the player is in "build mode", otherwise {@code false}
*/
boolean isInBuildMode(Player player);
/**
* Gets whether the given player is allowed to create a new {@link BuildWorld}.<br> This depends on the following factors:
* <ul>
* <li>Is the maximum number of worlds set by the config lower than the number of existing worlds?</li>
* <li>Is the maximum number of worlds created by the player less than the number of worlds said player is allowed to create?</li>
* </ul>
*
* @param player The player trying to create a world
* @param visibility The visibility of the world trying to be created
* @return {@code true} if the player is allowed to create a world, otherwise {@code false}
*/
boolean canCreateWorld(Player player, Visibility visibility);
/**
* Returns the maximum amount of {@link BuildWorld}s a player can create.
* <p>
* If the player has the permission {@code buildsystem.admin}, unlimited worlds can be created. Otherwise, there are two different permissions to set said amount:
* <p>
* To set the maximum of...
* <ul>
* <li>...public worlds, use {@code buildsystem.create.public.%amount%}.
* <li>...private worlds, use {@code buildsystem.create.private.%amount%}.
* </ul>
*
* @param player The player object
* @param visibility The visibility of the worlds to check the maximum of. Possible values: {@link Visibility#PUBLIC} or {@link Visibility#PRIVATE}
* @return If set, the maximum number of worlds a player can create, otherwise -1
*/
int getMaxWorlds(Player player, Visibility visibility);
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and classes related to {@link de.eintosti.buildsystem.api.player.BuildPlayer} management within the BuildSystem API. This includes player-specific data,
* settings, and cached values.
*/
package de.eintosti.buildsystem.api.player;
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player.settings;
import org.jspecify.annotations.NullMarked;
/**
* A {@link DesignColor} is the color which glass panes are tinted to in different menus.
*
* @since 3.0.0
*/
@NullMarked
public enum DesignColor {
/**
* The color red.
*/
RED,
/**
* The color orange.
*/
ORANGE,
/**
* The color yellow.
*/
YELLOW,
/**
* The color pink.
*/
PINK,
/**
* The color magenta.
*/
MAGENTA,
/**
* The color purple.
*/
PURPLE,
/**
* The color brown.
*/
BROWN,
/**
* The color lime.
*/
LIME,
/**
* The color green.
*/
GREEN,
/**
* The color blue.
*/
BLUE,
/**
* The color cyan.
*/
CYAN,
/**
* The color light blue.
*/
LIGHT_BLUE,
/**
* The color white.
*/
WHITE,
/**
* The color gray.
*/
GRAY,
/**
* The color light gray.
*/
LIGHT_GRAY,
/**
* The color black.
*/
BLACK;
/**
* Gets the {@link DesignColor} from a string.
*
* @param colorName The name of the color
* @return The {@link DesignColor} or {@link DesignColor#BLACK} if the color does not exist
*/
public static DesignColor matchColor(String colorName) {
try {
return valueOf(colorName);
} catch (IllegalArgumentException e) {
return DesignColor.BLACK;
}
}
}
@@ -0,0 +1,259 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.player.settings;
import de.eintosti.buildsystem.api.player.BuildPlayer;
import de.eintosti.buildsystem.api.world.navigator.settings.NavigatorType;
import de.eintosti.buildsystem.api.world.navigator.settings.WorldDisplay;
import org.bukkit.GameMode;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus.Internal;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Different settings a {@link BuildPlayer} can modify for themselves.
*
* @since 3.0.0
*/
@NullMarked
public interface Settings {
/**
* Gets the mode the navigator is set to.
*
* @return The navigator type
*/
NavigatorType getNavigatorType();
/**
* Sets the navigator type.
* <p>
* The {@link NavigatorType#OLD} is the classic chest menu, whereas {@link NavigatorType#NEW} is a new 3D selector.
*
* @param navigatorType The navigator type
*/
void setNavigatorType(NavigatorType navigatorType);
/**
* Gets the design color used in menus.
*
* @return The design color
*/
DesignColor getDesignColor();
/**
* Sets the design color used in menus.
*
* @param designColor The design color
*/
void setDesignColor(DesignColor designColor);
/**
* Gets the set of rules by which worlds are displayed in the navigator.
*
* @return The world display rules
*/
WorldDisplay getWorldDisplay();
/**
* Gets whether the player's inventory is to be cleared when joining the server.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isClearInventory();
/**
* Sets whether the player's inventory is to be cleared when joining the server.
*
* @param clearInventory If the inventory is to be cleared
*/
void setClearInventory(boolean clearInventory);
/**
* Gets whether the interaction with blocks is disabled.
*
* @return {@code true} if disabled, otherwise {@code false}
*/
boolean isDisableInteract();
/**
* Sets whether the interaction with blocks should be disabled.
*
* @param disableInteract If the interaction with blocks is to be disabled
*/
void setDisableInteract(boolean disableInteract);
/**
* Gets whether all online players are to be hidden.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isHidePlayers();
/**
* Sets whether all online players are to be hidden.
*
* @param hidePlayers If the players are to be hidden
*/
void setHidePlayers(boolean hidePlayers);
/**
* Gets whether signs should be placed without opening the text input.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isInstantPlaceSigns();
/**
* Sets whether signs should be placed without opening the text input.
*
* @param instantPlaceSigns If signs are to be placed instantly
*/
void setInstantPlaceSigns(boolean instantPlaceSigns);
/**
* Gets whether the navigator is kept in the player's inventory after a clear.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isKeepNavigator();
/**
* Sets whether the navigator is kept in the player's inventory after a clear.
*
* @param keepNavigator If the navigator is to kept
*/
void setKeepNavigator(boolean keepNavigator);
/**
* Gets whether the player has permanent {@link PotionEffectType#NIGHT_VISION}.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isNightVision();
/**
* Sets whether the player has permanent {@link PotionEffectType#NIGHT_VISION}.
*
* @param nightVision If the night vision is to be enabled
*/
void setNightVision(boolean nightVision);
/**
* Gets whether fling against a wall puts the player in {@link GameMode#SPECTATOR}.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isNoClip();
/**
* Sets whether fling against a wall puts the player in {@link GameMode#SPECTATOR}.
*
* @param noClip If no-clip is to be enabled
*/
void setNoClip(boolean noClip);
/**
* Gets whether plants can be placed anywhere.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isPlacePlants();
/**
* Sets whether plants can be placed anywhere.
*
* @param placePlants If plants are to be placed anywhere
*/
void setPlacePlants(boolean placePlants);
/**
* Gets whether the scoreboard is enabled.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isScoreboard();
/**
* Sets whether the scoreboard is enabled.
*
* @param scoreboard If the scoreboard is to be enabled
*/
void setScoreboard(boolean scoreboard);
/**
* Gets whether only one half of a slab will be broken when breaking double slabs.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isSlabBreaking();
/**
* Sets whether only one half of a slab will be broken when breaking double slabs.
*
* @param slabBreaking If precise slab breaking is to be enabled
*/
void setSlabBreaking(boolean slabBreaking);
/**
* Gets whether the player will be teleported to the spawn, if set, when joining the server.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isSpawnTeleport();
/**
* Sets whether the player will be teleported to the spawn, if set, when joining the server.
*
* @param spawnTeleport If the player is to be teleported to the spawn
*/
void setSpawnTeleport(boolean spawnTeleport);
/**
* Gets whether right-clicking iron (trap-)doors will be open/close them.
*
* @return {@code true} if enabled, otherwise {@code false}
*/
boolean isOpenTrapDoors();
/**
* Sets whether right-clicking iron (trap-)doors will be open/close them.
*
* @param openTrapDoors If the iron (trap-)doors are to be opened/closed via right-click
*/
void setOpenTrapDoors(boolean openTrapDoors);
/**
* Gets the {@link BukkitTask} responsible for updating the player's scoreboard.
*
* @return The scoreboard task
*/
@Nullable
@Internal
BukkitTask getScoreboardTask();
/**
* Sets the {@link BukkitTask} responsible for updating the player's scoreboard.
*
* @param scoreboardTask The scoreboard task
*/
@Internal
void setScoreboardTask(@Nullable BukkitTask scoreboardTask);
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and enumerations for player-specific settings within the BuildSystem API. This includes customizable options like design colors and various gameplay
* preferences.
*/
package de.eintosti.buildsystem.api.player.settings;
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.storage;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.builder.Builder;
import de.eintosti.buildsystem.api.world.display.Folder;
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
import java.util.Collection;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Interface for managing the storage of {@link Folder} objects.
*
* @since 3.0.0
*/
@NullMarked
public interface FolderStorage extends Storage<Folder> {
/**
* Gets a list of all {@link Folder}s.
*
* @return An unmodifiable list of all folders
*/
@Unmodifiable
Collection<Folder> getFolders();
/**
* Gets a {@link Folder} by its name (case-insensitive).
*
* @param name The name of the folder to retrieve
* @return The folder if it exists, or {@code null} if it does not
*/
@Nullable
Folder getFolder(String name);
/**
* Checks if a {@link Folder} with the given name (case-insensitive) exists.
*
* @param name The name of the folder to check
* @return {@code true} if the folder exists, {@code false} otherwise
*/
boolean folderExists(String name);
/**
* Creates a new {@link Folder} with the given name.
*
* @param name The name folder to create
* @param category The category in which the folder should be displayed
* @param creator The builder who created the folder
* @return The newly created folder
*/
Folder createFolder(String name, NavigatorCategory category, Builder creator);
/**
* Creates a new nested {@link Folder} with the given name.
*
* @param name The name folder to create
* @param category The category in which the folder should be displayed
* @param parent The parent folder, or {@code null} if this is a top-level folder
* @param creator The builder who created the folder
* @return The newly created folder
*/
Folder createFolder(String name, NavigatorCategory category, @Nullable Folder parent, Builder creator);
/**
* Removes the {@link Folder} with the given name.
* <p>
* This operation cascades:
* <ul>
* <li>All subfolders within the specified folder will also be removed.</li>
* <li>Any {@link BuildWorld} instances associated with this folder will have their folder reference unset.</li>
* </ul>
*
* @param name The name of the folder to remove
* @see #removeFolder(Folder)
*/
void removeFolder(String name);
/**
* Removes the given {@link Folder}.
* <p>
* This operation cascades:
* <ul>
* <li>All subfolders within the specified folder will also be removed.</li>
* <li>Any {@link BuildWorld} instances associated with this folder will have their folder reference unset.</li>
* </ul>
*
* @param folder The folder to remove
* @see #removeFolder(String)
*/
void removeFolder(Folder folder);
}
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.storage;
import de.eintosti.buildsystem.api.player.BuildPlayer;
import java.util.Collection;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Interface for managing the storage of {@link BuildPlayer} objects.
*
* @since 3.0.0
*/
@NullMarked
public interface PlayerStorage extends Storage<BuildPlayer> {
/**
* Creates a new {@link BuildPlayer} with the given uuid and settings.
*
* @param uuid The uuid of the player
* @return The created build-player
*/
BuildPlayer createBuildPlayer(UUID uuid);
/**
* Creates a new {@link BuildPlayer} with the given player.
*
* @param player The player
* @return The created build-player
*/
BuildPlayer createBuildPlayer(Player player);
/**
* Gets the {@link BuildPlayer} whose unique-id matches the given uuid.
*
* @param uuid The uuid of the player
* @return The player, if found, otherwise {@code null}
*/
@Nullable
BuildPlayer getBuildPlayer(UUID uuid);
/**
* Gets the {@link BuildPlayer} which wraps the given player.
* <p>
* If the player is not found, a new {@link BuildPlayer} will be created using {@link #createBuildPlayer(Player)}.
*
* @param player The wrapped player
* @return The player
* @see #createBuildPlayer(Player)
*/
BuildPlayer getBuildPlayer(Player player);
/**
* Gets a collection of all {@link BuildPlayer}s.
*
* @return A collection of all build-players.
*/
@Unmodifiable
Collection<BuildPlayer> getBuildPlayers();
}
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.storage;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import org.jspecify.annotations.NullMarked;
/**
* A generic interface for storage operations.
*
* @param <T> The type of objects to be stored
* @since 3.0.0
*/
@NullMarked
public interface Storage<T> {
/**
* Saves the given object to the storage.
*
* @param object The object to save
* @return A {@link CompletableFuture} that completes when the save operation is done
*/
CompletableFuture<Void> save(T object);
/**
* Saves all the given objects to the storage.
*
* @param objects The objects to save
* @return A {@link CompletableFuture} that completes when the save operation is done
*/
CompletableFuture<Void> save(Collection<T> objects);
/**
* Loads all objects from the storage.
*
* @return A {@link CompletableFuture} that completes with a collection of loaded objects
*/
CompletableFuture<Collection<T>> load();
/**
* Deletes the given object from the storage.
*
* @param object The object to delete
* @return A {@link CompletableFuture} that completes when the deletion finishes
*/
CompletableFuture<Void> delete(T object);
/**
* Deletes the object with the given key from the storage.
*
* @param key The key of the object to delete
* @return A {@link CompletableFuture} that completes when the deletion finishes
*/
CompletableFuture<Void> delete(String key);
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.storage;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.data.Visibility;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Interface for managing the storage of {@link BuildWorld} objects.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldStorage extends Storage<BuildWorld> {
/**
* Gets the {@link BuildWorld} by the given name.
*
* @param name The name of the world
* @return The world object if one was found, {@code null} otherwise
*/
@Nullable
BuildWorld getBuildWorld(String name);
/**
* Gets the {@link BuildWorld} by the given {@link World}.
*
* @param world The bukkit world object
* @return The world object if one was found, {@code null} otherwise
*/
@Nullable
BuildWorld getBuildWorld(World world);
/**
* Gets the {@link BuildWorld} by the given {@link UUID}.
*
* @param uuid The build world's unique identifier
* @return The world object if one was found, {@code null} otherwise
*/
@Nullable
BuildWorld getBuildWorld(UUID uuid);
/**
* Gets a list of all {@link BuildWorld}s.
*
* @return An unmodifiable list of all worlds
*/
@Unmodifiable
Collection<BuildWorld> getBuildWorlds();
/**
* Gets a list of {@link BuildWorld}s created by the given player.
*
* @param player The player who created the worlds
* @return A list of worlds created by the player
*/
@Unmodifiable
List<BuildWorld> getBuildWorldsCreatedByPlayer(Player player);
/**
* Gets a list of {@link BuildWorld}s created by the given player with the given visibility.
*
* @param player The player who created the worlds
* @param visibility The visibility of the worlds
* @return A list of worlds created by the player with the given visibility
*/
@Unmodifiable
List<BuildWorld> getBuildWorldsCreatedByPlayer(Player player, Visibility visibility);
/**
* Checks if a {@link BuildWorld} with the given name (case-insensitive) exists.
*
* @param worldName The name of the world to check
* @return {@code true} if the world exists, {@code false} otherwise
*/
boolean worldExists(String worldName);
/**
* Checks if a {@link BuildWorld} exists and if the world folder exists on disk.
*
* @param worldName The name of the world to check
* @return {@code true} if the world exists in the map or on disk, {@code false} otherwise
*/
boolean worldAndFolderExist(String worldName);
}
@@ -0,0 +1,188 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world;
import com.cryptomorin.xseries.profiles.objects.Profileable;
import de.eintosti.buildsystem.api.world.builder.Builders;
import de.eintosti.buildsystem.api.world.creation.generator.CustomGenerator;
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
import de.eintosti.buildsystem.api.world.data.WorldData;
import de.eintosti.buildsystem.api.world.display.Displayable;
import de.eintosti.buildsystem.api.world.display.Folder;
import de.eintosti.buildsystem.api.world.util.WorldLoader;
import de.eintosti.buildsystem.api.world.util.WorldPermissions;
import de.eintosti.buildsystem.api.world.util.WorldTeleporter;
import de.eintosti.buildsystem.api.world.util.WorldUnloader;
import java.util.UUID;
import org.bukkit.Difficulty;
import org.bukkit.Material;
import org.bukkit.World;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a world managed by the BuildSystem plugin, extending the {@link Displayable} interface. This interface provides comprehensive access to world-specific properties,
* data, and utility methods.
*
* @since 3.0.0
*/
@NullMarked
public interface BuildWorld extends Displayable {
/**
* Gets the Bukkit {@link World} associated with this {@link BuildWorld}.
*
* @return The Bukkit world, or {@code null} if not loaded
*/
@Nullable
World getWorld();
/**
* Gets the unique identifier of this world.
* <p>
* Not equivalent to {@link World#getUID()}.
*
* @return The uuid of this world
*/
UUID getUniqueId();
/**
* Sets the name of this world.
*
* @param name The name of the world
*/
void setName(String name);
/**
* Gets the {@link Profileable} representation of this build world which is applied when {@link WorldData#material()} is set to {@link Material#PLAYER_HEAD}.
*
* @return The {@link Profileable} representation of this build world
*/
Profileable asProfilable();
/**
* Gets this world's {@link BuildWorldType}.
*
* @return The type of this world
*/
BuildWorldType getType();
/**
* Gets this world's {@link WorldData}.
*
* @return The data of the world
*/
WorldData getData();
/**
* Gets the custom chunk generator used to generate this world.
* <p>
* Only set when the world type is {@link BuildWorldType#CUSTOM} or {@link BuildWorldType#IMPORTED}.
*
* @return The custom chunk generator used to generate this world, or {@code null} if not set
*/
@Nullable
CustomGenerator getCustomGenerator();
/**
* Cycles to the next {@link Difficulty} for this world.
* <p>
* The cycle order is: {@link Difficulty#PEACEFUL} -> {@link Difficulty#EASY} -> {@link Difficulty#NORMAL} -> {@link Difficulty#HARD} -> {@link Difficulty#PEACEFUL}.
*
* @return The new difficulty after cycling
*/
Difficulty cycleDifficulty();
/**
* Gets the {@link Builders} object, which manages all players allowed to modify this world.
*
* @return The {@link Builders} instance for this world
*/
Builders getBuilders();
/**
* Gets the time of day in the {@link World} linked to this build world as a formatted string.
*
* @return This world time as a string (e.g., "Day", "Night")
*/
String getWorldTime();
/**
* Gets whether this world is currently loaded into server memory, allowing players to enter it.
*
* @return {@code true} if this world is loaded, otherwise {@code false}
*/
boolean isLoaded();
/**
* Sets whether this world is currently loaded into server memory.
*
* @param loaded {@code true} if this world is to be loaded, {@code false} if it should be unloaded
*/
void setLoaded(boolean loaded);
/**
* Gets the {@link WorldLoader} utility used to manage loading operations for this world.
*
* @return The {@link WorldLoader} instance
*/
WorldLoader getLoader();
/**
* Gets the {@link WorldUnloader} utility used to manage unloading operations for this world.
*
* @return The {@link WorldUnloader} instance
*/
WorldUnloader getUnloader();
/**
* Gets the {@link WorldTeleporter} utility used to manage teleportation of players to this world.
*
* @return The {@link WorldTeleporter} instance
*/
WorldTeleporter getTeleporter();
/**
* Gets the {@link WorldPermissions} associated with this world, which define access and modification rules.
*
* @return The {@link WorldPermissions} instance for this world
*/
WorldPermissions getPermissions();
/**
* Gets the {@link Folder} this world is assigned to.
*
* @return The folder this world is assigned to, or {@code null} if not assigned
*/
@Nullable
Folder getFolder();
/**
* Checks whether this world is assigned to a {@link Folder}.
*
* @return {@code true} if this world is in any folder, {@code false} otherwise
*/
boolean isAssignedToFolder();
/**
* Sets the {@link Folder} this world is assigned to.
*
* @param folder The folder to assign this world to, or {@code null} to remove the assignment
*/
void setFolder(@Nullable Folder folder);
}
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world;
import de.eintosti.buildsystem.api.storage.FolderStorage;
import de.eintosti.buildsystem.api.storage.WorldStorage;
import de.eintosti.buildsystem.api.world.creation.BuildWorldCreator;
import de.eintosti.buildsystem.api.world.display.Folder;
import java.util.concurrent.CompletableFuture;
import org.jspecify.annotations.NullMarked;
/**
* Provides a service for managing world-related operations and data. This interface offers methods to access and interact with world storage and folder management.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldService {
/**
* Gets the {@link FolderStorage} implementation for managing {@link Folder} persistence.
*
* @return The folder storage instance
*/
FolderStorage getFolderStorage();
/**
* Gets the {@link WorldStorage} implementation for managing {@link BuildWorld} persistence.
*
* @return The world storage instance
*/
WorldStorage getWorldStorage();
/**
* Creates a new {@link BuildWorldCreator} for the given name.
*
* @param name The name of the world to create
* @return A new {@link BuildWorldCreator} instance for the specified world name
*/
BuildWorldCreator createWorld(String name);
/**
* Unimport an existing {@link BuildWorld}. In comparison to {@link #deleteWorld(BuildWorld)}, unimporting a world does not delete the world's directory.
*
* @param buildWorld The world to unimport
* @param save Whether to save the world before unloading
* @return A future that completes when the unimport operation is finished
*/
CompletableFuture<Void> unimportWorld(BuildWorld buildWorld, boolean save);
/**
* Delete an existing {@link BuildWorld}. In comparison to {@link #unimportWorld(BuildWorld, boolean)}, deleting a world deletes the world's directory.
*
* @param buildWorld The world to be deleted
* @return A future that completes when the delete operation is finished
*/
CompletableFuture<Void> deleteWorld(BuildWorld buildWorld);
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.backup;
import org.jspecify.annotations.NullMarked;
/**
* Represents a single backup of a {@link de.eintosti.buildsystem.api.world.BuildWorld}.
*/
@NullMarked
public interface Backup {
/**
* Returns the {@link BackupProfile} that owns this backup.
*
* @return The owner of the backup.
*/
BackupProfile owner();
/**
* Returns the timestamp when this backup was created.
*
* @return The creation time in milliseconds since the Unix epoch.
*/
long creationTime();
/**
* Returns a unique key or identifier for this backup.
*
* @return The key of the backup.
*/
String key();
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2023-2025, Thomas Meaney
* All rights reserved.
*
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
*/
package de.eintosti.buildsystem.api.world.backup;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NullMarked;
/**
* Represents a profile for managing backups of a specific {@link BuildWorld}. This interface defines operations related to listing, creating, restoring, and destroying backups.
*/
@NullMarked
public interface BackupProfile {
/**
* Asynchronously populates a list of available {@link Backup}s under this profile.
*
* @return Future that will be completed with available backups
*/
CompletableFuture<List<Backup>> listBackups();
/**
* Creates a backup of the {@link BuildWorld}. If the profile is at the maximum backup capacity, the oldest backup will be deleted.
*
* @return Future that completes with the created backup.
*/
CompletableFuture<Backup> createBackup();
/**
* Restores a {@link Backup}.
*
* @param backup Backup to restore
* @param player The player restoring the backup
*/
void restoreBackup(Backup backup, Player player);
}
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.backup;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.io.File;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.jspecify.annotations.NullMarked;
/**
* Represents a storage mechanism for managing world backups.
*/
@NullMarked
public interface BackupStorage {
/**
* Generates a unique backup name based on a given timestamp.
*
* @param timestamp The timestamp to use for the backup name.
* @return A string representing the backup name (e.g., "1678886400000.zip").
*/
default String getBackupName(long timestamp) {
return timestamp + ".zip";
}
/**
* Lists all available {@link Backup}s for a specific {@link BuildWorld}.
*
* @param buildWorld The world for which to list backups
* @return A future with a list of backup objects associated with the specified world
*/
CompletableFuture<List<Backup>> listBackups(BuildWorld buildWorld);
/**
* Creates and stores a new {@link Backup} for a given {@link BuildWorld}. The result of the operation is communicated via the provided {@link CompletableFuture}.
* <p>
* In comparison to {@link BackupProfile#createBackup()}, a backup will always be created and no older backups will be deleted. This method is intended for immediate backup
* creation and storage, rather than profile management.
*
* @param buildWorld The world to be backed up
* @return A future that will be completed with the backup object upon successful storage, or exceptionally if an error occurs
*/
CompletableFuture<Backup> storeBackup(BuildWorld buildWorld);
/**
* Downloads a specific {@link Backup} file asynchronously.
*
* @param backup The backup object representing the backup to be downloaded
* @return A future that will complete with a {@link File} object pointing to the downloaded backup once the download operation is finished
*/
CompletableFuture<File> downloadBackup(Backup backup);
/**
* Deletes a specific {@link Backup}.
*
* @param backup The backup object representing the backup to be deleted
* @return A future that will complete after the deletion
*/
CompletableFuture<Void> deleteBackup(Backup backup);
/**
* Closes the backup storage, releasing any resources.
*/
void close();
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and classes for managing world backups.
*/
package de.eintosti.buildsystem.api.world.backup;
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.builder;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* A {@link Builder} represents a player allowed to build in a {@link BuildWorld}.
*
* @since 3.0.0
*/
@NullMarked
public sealed interface Builder permits BuilderImpl {
/**
* Creates a new {@link Builder} instance with the given uuid and name.
*
* @param uuid The uuid
* @param name The name
* @return The builder
*/
@Contract("_, _ -> new")
static Builder of(UUID uuid, String name) {
return new BuilderImpl(uuid, name);
}
/**
* Creates a new {@link Builder} instance using the given player.
*
* @param player The player
* @return The builder
*/
@Contract("_ -> new")
static Builder of(Player player) {
return of(player.getUniqueId(), player.getName());
}
/**
* Creates a new {@link Builder} instance using a serialized string.
* <p>
* The format of the string must be {@code <uuid>,<name>}.
*
* @param serialized The serialized builder
* @return The builder if all the input is valid, otherwise {@code null}
*/
@Nullable
static Builder deserialize(@Nullable String serialized) {
if (serialized == null || serialized.equals("-")) {
return null;
}
String[] parts = serialized.split(BuilderImpl.SEPARATOR);
if (parts.length != 2) {
return null;
}
return of(UUID.fromString(parts[0]), parts[1]);
}
/**
* Returns a unique and persistent id for the builder.
* <p>
* Should be equal to the corresponding {@link Player}'s unique id.
*
* @return The uuid
* @see Player#getUniqueId()
*/
UUID getUniqueId();
/**
* Gets the name of the builder.
*
* @return The builder name
*/
String getName();
/**
* Sets the name of the builder.
*
* @param name The name to change to
*/
void setName(String name);
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.builder;
import java.util.UUID;
import org.jspecify.annotations.NullMarked;
/**
* Concrete implementation of the {@link Builder} interface.
*
* @since 3.0.0
*/
@NullMarked
final class BuilderImpl implements Builder {
static final String SEPARATOR = ",";
private final UUID uuid;
private String name;
/**
* Constructs a new {@link BuilderImpl} with the given unique ID and name.
*
* @param uuid The unique ID of the builder
* @param name The name of the builder
*/
BuilderImpl(UUID uuid, String name) {
this.uuid = uuid;
this.name = name;
}
@Override
public UUID getUniqueId() {
return uuid;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return this.uuid + SEPARATOR + this.name;
}
}
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.builder;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Interface for managing builders in a {@link BuildWorld}.
*
* @since 3.0.0
*/
@NullMarked
public interface Builders {
/**
* Checks if the world has a creator.
*
* @return {@code true} if the world has a creator, {@code false} otherwise
*/
boolean hasCreator();
/**
* Gets the creator of the world.
*
* @return The creator of the world, or {@code null} if there is none
*/
@Nullable
Builder getCreator();
/**
* Sets the creator of the world.
*
* @param creator The new creator
*/
void setCreator(@Nullable Builder creator);
/**
* Checks if the given player is the creator of the world.
*
* @param player The player to check
* @return {@code true} if the player is the creator, {@code false} otherwise
*/
boolean isCreator(Player player);
/**
* Gets an unmodifiable list of all builders.
*
* @return List of builders
*/
Collection<Builder> getAllBuilders();
/**
* Gets a builder by their UUID.
*
* @param uuid The UUID to search for
* @return The builder if found, {@code null} otherwise
*/
@Nullable
Builder getBuilder(UUID uuid);
/**
* Get an unmodifiable list of all {@link Builder} names
*
* @return A list of all builder names
*/
@Unmodifiable
List<String> getBuilderNames();
/**
* Checks if a player is a builder.
*
* @param player The player to check
* @return {@code true} if the player is a builder, {@code false} otherwise
*/
boolean isBuilder(Player player);
/**
* Checks if a UUID belongs to a builder.
*
* @param uuid The UUID to check
* @return {@code true} if the given UUID belongs to a builder, {@code false} otherwise
*/
boolean isBuilder(UUID uuid);
/**
* Adds a builder to the world.
*
* @param builder The builder to add
*/
void addBuilder(Builder builder);
/**
* Removes a builder from the world.
*
* @param builder The builder to remove
*/
void removeBuilder(Builder builder);
/**
* Removes a builder by their UUID.
*
* @param uuid The UUID of the builder to remove
*/
void removeBuilder(UUID uuid);
/**
* Formats the list of builders for the {@code %builder%} placeholder.
*
* @param player The player to display the placeholders to
* @return The list of builders which have been added to the given world as a string
*/
String asPlaceholder(Player player);
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and classes for managing world builders and their associated permissions.
*/
package de.eintosti.buildsystem.api.world.builder;
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.creation;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.builder.Builder;
import de.eintosti.buildsystem.api.world.creation.generator.CustomGenerator;
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
import de.eintosti.buildsystem.api.world.display.Folder;
import org.bukkit.Difficulty;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a creator for a {@link BuildWorld}.
*
* @since 3.0.0
*/
@NullMarked
public interface BuildWorldCreator {
/**
* Sets the name of the world.
*
* @param name The world name
* @return The world creator object
*/
BuildWorldCreator setName(String name);
/**
* Sets the creator of the world.
*
* @param creator The creator, may be {@code null}
* @return The world creator object
*/
BuildWorldCreator setCreator(@Nullable Builder creator);
/**
* Sets the template which the world should be copied from.
* <p>
* Only used if the world type is {@link BuildWorldType#TEMPLATE}
*
* @param template The template name, may be {@code null} if no template is used
* @return The creator object
*/
BuildWorldCreator setTemplate(@Nullable String template);
/**
* Sets the type of the world.
*
* @param type The world type
* @return The world creator object
*/
BuildWorldCreator setType(BuildWorldType type);
/**
* Sets the custom {@link ChunkGenerator} of the world.
*
* @param customGenerator The custom chunk generator
* @return The world creator object
*/
BuildWorldCreator setCustomGenerator(CustomGenerator customGenerator);
/**
* Sets the folder in which the world should be created.
*
* @param folder The folder where the world should be created, may be {@code null} if not to be added to a folder
* @return The world creator object
*/
BuildWorldCreator setFolder(@Nullable Folder folder);
/**
* Sets whether the world should be private or not.
*
* @param privateWorld Whether the world should be private
* @return The world creator object
*/
BuildWorldCreator setPrivate(boolean privateWorld);
/**
* Sets the difficulty of the world.
*
* @param difficulty The difficulty
* @return The world creator object
*/
BuildWorldCreator setDifficulty(Difficulty difficulty);
/**
* Sets the creation date of the world.
*
* @param creationDate The creation date in milliseconds since epoch
* @return The world creator object
*/
BuildWorldCreator setCreationDate(long creationDate);
/**
* Creates and generates a new {@link BuildWorld} using the settings configured in this builder.
* <p>
* This process includes creating the world files, registering the world with the plugin, and notifying the player of the progress.
*
* @param player The player who is creating the world
*/
void createWorld(Player player);
/**
* Imports an existing world directory as a new {@link BuildWorld}.
*
* @param player The player who is importing the world
* @param teleport If true, the player will be teleported to the world after the import is finished
*/
void importWorld(Player player, boolean teleport);
/**
* Generates the underlying Bukkit {@link World} and applies post-generation settings. Only generates the world if the world was not created in a newer Minecraft version that
* the server is running.
* <p>
* Important: This method should only be called after the world has been created and registered with the plugin.
*
* @return The generated {@link World}, or {@code null} if generation failed
*/
@Nullable
default World generateBukkitWorld() {
return generateBukkitWorld(true);
}
/**
* Generates the underlying Bukkit {@link World} and applies post-generation settings.
* <p>
* Important: This method should only be called after the world has been created and registered with the plugin.
*
* @param checkVersion If true, verify that the world's data version is compatible
* @return The generated {@link World}, or {@code null} if generation failed
*/
@Nullable
World generateBukkitWorld(boolean checkVersion);
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.creation.generator;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a custom chunk generator for a {@link World} which is provided by an external plugin.
*
* @since 3.0.0
*/
@NullMarked
public interface CustomGenerator {
/**
* Gets the name plugin providing the chunk generator.
*
* @return The name of the plugin
*/
String pluginName();
/**
* Gets the name of the chunk generator.
*
* @return The name of the chunk generator
*/
String chunkGeneratorName();
/**
* Gets the Bukkit {@link ChunkGenerator} within the providing plugin ({@link #pluginName()}:{@link #chunkGeneratorName()}).
*
* @return The chunk generator instance, or {@code null} if it could not be loaded or has not been not set
*/
@Nullable
ChunkGenerator chunkGenerator();
}
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.creation.generator;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jspecify.annotations.NullMarked;
/**
* Different kinds of world generators that can be used for a {@link BuildWorld}.
*
* @since 3.0.0
*/
@NullMarked
public enum Generator {
/**
* A normal world
*/
NORMAL,
/**
* A flat world
*/
FLAT,
/**
* A void world
*/
VOID,
/**
* A custom world
*/
CUSTOM
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Classes relevant to world generation.
*/
package de.eintosti.buildsystem.api.world.creation.generator;
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Classes relevant to world generation.
*/
package de.eintosti.buildsystem.api.world.creation;
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.data;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.Locale;
import org.jspecify.annotations.NullMarked;
/**
* Represents the various building statuses a {@link BuildWorld} can have. These statuses indicate the progression and accessibility of a world.
*
* @since 3.0.0
*/
@NullMarked
public enum BuildWorldStatus {
/**
* Represents a {@link BuildWorld} that has not yet been started or modified. This is typically the initial state for newly created worlds.
*/
NOT_STARTED(1),
/**
* Represents a {@link BuildWorld} that is currently under construction. This status is automatically assigned when a block is placed or broken in the world.
*/
IN_PROGRESS(2),
/**
* Represents a {@link BuildWorld} that is nearing completion.
*/
ALMOST_FINISHED(3),
/**
* Represents a {@link BuildWorld} whose building phase has been completed.
*/
FINISHED(4),
/**
* Represents an older {@link BuildWorld} that has been completed and is now archived. Blocks typically cannot be placed or broken in archived worlds.
*/
ARCHIVE(5),
/**
* Represents a {@link BuildWorld} that is hidden from public view in the navigator.
*/
HIDDEN(6);
private final int stage;
BuildWorldStatus(int stage) {
this.stage = stage;
}
/**
* Gets the permission required to change a world to this status.
*
* @return The permission string (e.g., "buildsystem.setstatus.notstarted")
*/
public String getPermission() {
return "buildsystem.setstatus." + name().toLowerCase(Locale.ROOT).replace("_", "");
}
/**
* Gets the development stage of the {@link BuildWorld}. A higher numerical value indicates a further developed or completed world.
*
* @return The integer representing the stage of development
*/
public int getStage() {
return stage;
}
}
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.data;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.World.Environment;
import org.bukkit.generator.ChunkGenerator;
import org.jspecify.annotations.NullMarked;
/**
* Represents the different types of {@link BuildWorld}s that can be created or managed by the BuildSystem plugin. Each type specifies unique characteristics for world generation
* and behavior.
*
* @since 3.0.0
*/
@NullMarked
public enum BuildWorldType {
/**
* A standard world type, equivalent to a default Minecraft overworld with {@link Environment#NORMAL}.
*/
NORMAL,
/**
* A super-flat world, ideal for creative building without terrain obstacles.
*/
FLAT,
/**
* A world type representing the Nether dimension, with {@link Environment#NETHER}.
*/
NETHER,
/**
* A world type representing the End dimension, with {@link Environment#THE_END}.
*/
END,
/**
* An empty world, containing no blocks except for a single platform at spawn.
*/
VOID,
/**
* A world created as an identical copy of an existing template world.
*/
TEMPLATE,
/**
* A world that, by default, can only be modified by its creator.
*/
PRIVATE,
/**
* A world that was not originally created by the BuildSystem plugin but has been imported for management.
*/
IMPORTED,
/**
* A world generated using a custom {@link ChunkGenerator}.
*/
CUSTOM,
/**
* A world whose type could not be determined or is not recognized by the BuildSystem.
*/
UNKNOWN
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.data;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jspecify.annotations.NullMarked;
/**
* Defines the visibility settings for a {@link BuildWorld} within the BuildSystem. These settings determine how worlds are displayed and accessed in the world navigator.
*
* @since 3.0.0
*/
@NullMarked
public enum Visibility {
/**
* Indicates that a world is publicly accessible and displayed in the main world navigator.
*/
PUBLIC,
/**
* Indicates that a world is private, typically only visible and accessible to its creator and designated builders. Private worlds are usually displayed in a separate,
* dedicated menu.
*/
PRIVATE,
/**
* A special state indicating that the visibility setting of a world should be disregarded. This is useful for internal operations or specific contexts where visibility rules
* do not apply.
*/
IGNORE;
/**
* Returns the appropriate {@link Visibility} enum based on whether a world is private.
*
* @param isPrivateWorld A boolean indicating if the world is private
* @return {@link #PRIVATE} if {@link WorldData#privateWorld()} is true, otherwise {@link #PUBLIC}
*/
public static Visibility matchVisibility(boolean isPrivateWorld) {
return isPrivateWorld ? PRIVATE : PUBLIC;
}
}
@@ -0,0 +1,180 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.data;
import com.cryptomorin.xseries.XMaterial;
import de.eintosti.buildsystem.api.data.Type;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.backup.Backup;
import java.util.Map;
import org.bukkit.Difficulty;
import org.bukkit.Location;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Manages and provides access to various data points and settings for a {@link BuildWorld}. This interface allows for reading and modifying world-specific configurations.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldData {
/**
* Retrieves a {@link Type} object representing the custom spawn location of the {@link BuildWorld}. The value is stored as a string in the format {@code x;y;z;yaw;pitch}.
*
* @return A {@link Type} containing the custom spawn string
* @see #getCustomSpawnLocation()
*/
Type<String> customSpawn();
/**
* Gets the {@link BuildWorld}'s custom spawn as a {@link Location} object.
*
* @return The custom spawn as a location, or {@code null} if not set or invalid
*/
@Nullable
Location getCustomSpawnLocation();
/**
* Retrieves a {@link Type} object representing the permission required to enter the {@link BuildWorld}. Returns "-" if no specific permission is required.
*
* @return A {@link Type} containing the permission string
*/
Type<String> permission();
/**
* Retrieves a {@link Type} object representing the project description of the {@link BuildWorld}. This typically provides a brief overview or purpose of the world.
*
* @return A {@link Type} containing the project description string
*/
Type<String> project();
/**
* Retrieves a {@link Type} object representing the {@link Difficulty} of the {@link BuildWorld}.
*
* @return A {@link Type} containing the world's difficulty setting
*/
Type<Difficulty> difficulty();
/**
* Retrieves a {@link Type} object representing the {@link XMaterial} used to display the {@link BuildWorld} in the navigator menus.
*
* @return A {@link Type} containing the material used for display
*/
Type<XMaterial> material();
/**
* Retrieves a {@link Type} object representing the current {@link BuildWorldStatus} of the world. This indicates the building progression or state of the world.
*
* @return A {@link Type} containing the current build status
*/
Type<BuildWorldStatus> status();
/**
* Retrieves a {@link Type} object indicating whether block breaking is allowed in the {@link BuildWorld}.
*
* @return A {@link Type} containing a boolean: {@code true} if allowed, otherwise {@code false}
*/
Type<Boolean> blockBreaking();
/**
* Retrieves a {@link Type} object indicating whether block interactions (e.g., opening doors, chests) are enabled in the {@link BuildWorld}.
*
* @return A {@link Type} containing a boolean: {@code true} if enabled, otherwise {@code false}
*/
Type<Boolean> blockInteractions();
/**
* Retrieves a {@link Type} object indicating whether block placement is allowed in the {@link BuildWorld}.
*
* @return A {@link Type} containing a boolean: {@code true} if allowed, otherwise {@code false}
*/
Type<Boolean> blockPlacement();
/**
* Retrieves a {@link Type} object indicating whether the "builders feature" is enabled in the {@link BuildWorld}. When enabled, only designated builders can modify the world.
*
* @return A {@link Type} containing a boolean: {@code true} if enabled, otherwise {@code false}
*/
Type<Boolean> buildersEnabled();
/**
* Retrieves a {@link Type} object indicating whether explosions are enabled in the {@link BuildWorld}.
*
* @return A {@link Type} containing a boolean: {@code true} if enabled, otherwise {@code false}
*/
Type<Boolean> explosions();
/**
* Retrieves a {@link Type} object indicating whether entities in the {@link BuildWorld} have artificial intelligence.
*
* @return A {@link Type} containing a boolean: {@code true} if enabled, otherwise {@code false}
*/
Type<Boolean> mobAi();
/**
* Retrieves a {@link Type} object indicating whether physics (e.g., gravity, fluid flow) is applied to blocks in the {@link BuildWorld}.
*
* @return A {@link Type} containing a boolean: {@code true} if enabled, otherwise {@code false}
*/
Type<Boolean> physics();
/**
* Retrieves a {@link Type} object indicating whether the {@link BuildWorld} is set to private visibility. A private world is typically only accessible to its creator and
* designated builders.
*
* @return A {@link Type} containing a boolean: {@code true} if private, otherwise {@code false}
*/
Type<Boolean> privateWorld();
/**
* Gets the number of seconds that have passed since that last {@link Backup} of the {@link BuildWorld} was created.
*
* @return The number of seconds since the last backup
*/
Type<Integer> timeSinceBackup();
/**
* Retrieves a {@link Type} object representing the timestamp (in milliseconds since epoch) of the last time the {@link BuildWorld} was edited.
*
* @return A {@link Type} containing the last edited timestamp
*/
Type<Long> lastEdited();
/**
* Retrieves a {@link Type} object representing the timestamp (in milliseconds since epoch) of the last time the {@link BuildWorld} was loaded.
*
* @return A {@link Type} containing the last loaded timestamp
*/
Type<Long> lastLoaded();
/**
* Retrieves a {@link Type} object representing the timestamp (in milliseconds since epoch) of the last time the {@link BuildWorld} was unloaded.
*
* @return A {@link Type} containing the last unloaded timestamp
*/
Type<Long> lastUnloaded();
/**
* Gets a map of all configurable data points for the {@link BuildWorld}.
*
* @return An unmodifiable map where keys are data point names and values are their corresponding {@link Type} objects
*/
Map<String, Type<?>> getAllData();
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces for data structures and enumerations related to {@link de.eintosti.buildsystem.api.world.BuildWorld} properties. This includes world status, type,
* visibility, and other configurable data points.
*/
package de.eintosti.buildsystem.api.world.data;
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.display;
import com.cryptomorin.xseries.XMaterial;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.List;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.java.JavaPlugin;
import org.jspecify.annotations.NullMarked;
/**
* Represents an object that can be displayed in an inventory.
*
* @since 3.0.0
*/
@NullMarked
public interface Displayable {
/**
* Gets the unique name of this displayable item.
*
* @return The name
*/
String getName();
/**
* Gets the name used to display this item in an inventory.
*
* @param player The player viewing the item
* @return The display name
*/
String getDisplayName(Player player);
/**
* Gets the creation timestamp of the displayable.
*
* @return The number of milliseconds that have passed since {@code January 1, 1970 UTC}, until the displayable was created.
*/
long getCreation();
/**
* Gets the material to display this item with.
*
* @return The material
*/
XMaterial getIcon();
/**
* Sets the icon for this displayable item.
*
* @param material The material to set as the icon
*/
void setIcon(XMaterial material);
/**
* Gets the lore of this displayable item.
*
* @param player The player viewing the item
* @return The lore
*/
List<String> getLore(Player player);
/**
* Converts this displayable to an {@link ItemStack} for display.
*
* @param player The player viewing the inventory
* @return The ItemStack representation
*/
default ItemStack asItemStack(Player player) {
ItemStack itemStack = getIcon().parseItem();
if (itemStack == null) {
throw new IllegalStateException("Icon material " + getIcon() + " could not be parsed into an ItemStack.");
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
throw new IllegalStateException("ItemMeta for " + getIcon() + " is null. This should not happen.");
}
itemMeta.setDisplayName(getDisplayName(player));
itemMeta.setLore(getLore(player));
itemMeta.addItemFlags(ItemFlag.values());
DisplayableType type = switch (this) {
case BuildWorld ignored -> DisplayableType.BUILD_WORLD;
case Folder ignored -> DisplayableType.FOLDER;
default -> throw new IllegalStateException("Unknown displayable type: " + this.getClass().getSimpleName());
};
JavaPlugin plugin = JavaPlugin.getProvidingPlugin(getClass());
PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
pdc.set(new NamespacedKey(plugin, "displayable_type"), PersistentDataType.STRING, type.name());
pdc.set(new NamespacedKey(plugin, "displayable_name"), PersistentDataType.STRING, getName());
itemStack.setItemMeta(itemMeta);
return itemStack;
}
/**
* Adds this displayable to an {@link Inventory} at the given slot.
*
* @param inventory The inventory to add the item to
* @param slot The slot in the inventory to add the item
* @param player The player viewing the inventory
*/
default void addToInventory(Inventory inventory, int slot, Player player) {
inventory.setItem(slot, asItemStack(player));
}
/**
* Represents the distinct types of items that can be displayed in an inventory within the BuildSystem.
*/
enum DisplayableType {
/**
* Indicates that the displayable item is a {@link BuildWorld}.
*/
BUILD_WORLD,
/**
* Indicates that the displayable item is a {@link Folder}.
*/
FOLDER
}
}
@@ -0,0 +1,176 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.display;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.builder.Builder;
import java.util.List;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents a folder within the BuildSystem's world navigation structure. Folders can contain {@link BuildWorld}s and other nested folders, organizing them for easier access.
*
* @since 3.0.0
*/
@NullMarked
public interface Folder extends Displayable {
/**
* Gets the {@link Builder} who originally created this folder.
*
* @return The {@link Builder} instance representing the folder's creator
*/
Builder getCreator();
/**
* Gets the {@link NavigatorCategory} in which this folder is displayed.
*
* @return The {@link NavigatorCategory} of the folder
*/
NavigatorCategory getCategory();
/**
* Gets the parent {@link Folder} of this folder, if it is nested.
*
* @return The parent {@link Folder}, or {@code null} if this is a top-level folder
*/
@Nullable
Folder getParent();
/**
* Sets the parent {@link Folder} for this folder. Setting it to {@code null} will make this a top-level folder.
* <p>
* The parent folder must belong to the same {@link NavigatorCategory} as this folder. If the categories differ, an {@link IllegalArgumentException} is thrown.
*
* @param parent The new parent {@link Folder}, or {@code null} to remove the current parent
* @throws IllegalArgumentException if the parent has a different {@link NavigatorCategory}
*/
void setParent(@Nullable Folder parent);
/**
* Checks if this folder has a parent {@link Folder}.
*
* @return {@code true} if this folder is nested under another, {@code false} otherwise
*/
boolean hasParent();
/**
* Gets an unmodifiable list of UUIDs for all {@link BuildWorld}s contained directly within this folder.
*
* @return An {@link Unmodifiable} {@link List} of {@link BuildWorld} UUIDs
*/
@Unmodifiable
List<UUID> getWorldUUIDs();
/**
* Checks if this folder contains the specified {@link BuildWorld}.
*
* @param buildWorld The {@link BuildWorld} to check for
* @return {@code true} if the folder contains the world, {@code false} otherwise
*/
boolean containsWorld(BuildWorld buildWorld);
/**
* Checks if this folder contains the {@link BuildWorld} with the specified UUID.
*
* @param uuid The unique identifier of the {@link BuildWorld} to check for
* @return {@code true} if the folder contains the world, {@code false} otherwise
*/
boolean containsWorld(UUID uuid);
/**
* Adds a {@link BuildWorld} to this folder.
*
* @param buildWorld The {@link BuildWorld} to add
*/
void addWorld(BuildWorld buildWorld);
/**
* Removes a {@link BuildWorld} from this folder.
*
* @param buildWorld The {@link BuildWorld} to remove
*/
void removeWorld(BuildWorld buildWorld);
/**
* Removes a {@link BuildWorld} with the specified UUID from this folder.
*
* @param uuid The unique identifier of the {@link BuildWorld} to remove
*/
void removeWorld(UUID uuid);
/**
* Returns an unmodifiable list of all immediate subfolders contained within this folder.
* <p>
* This includes only direct children—folders whose {@link #getParent()} is exactly this folder. Nested subfolders (i.e., deeper levels of the folder hierarchy) are not
* included.
*
* @return A list of immediate subfolders
*/
@Unmodifiable
List<Folder> getSubFolders();
/**
* Gets the total number of {@link BuildWorld}s contained in this folder and all of its subfolders.
* <p>
* This includes both the worlds directly assigned to this folder and those assigned to any nested subfolders.
*
* @return The total number of worlds in this folder and its subfolders
*/
int getWorldCount();
/**
* Gets the permission string required for players to access or view this folder. Returns "-" if no specific permission is required.
*
* @return The permission string, or "-" if none is set
*/
String getPermission();
/**
* Sets the permission string required for players to access or view this folder. Setting to "-" will remove any permission requirement.
*
* @param permission The permission string to set, or "-" to remove
*/
void setPermission(String permission);
/**
* Gets the project name associated with this {@link Folder}. This can be used for categorization or informational purposes.
*
* @return The project name as a string
*/
String getProject();
/**
* Sets the project name for this {@link Folder}.
*
* @param project The new project name to set
*/
void setProject(String project);
/**
* Checks if the given {@link Player} has permission to view this folder in the navigator.
*
* @param player The {@link Player} to check
* @return {@code true} if the player can view the folder, {@code false} otherwise
*/
boolean canView(Player player);
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.display;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.builder.Builder;
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
import de.eintosti.buildsystem.api.world.data.WorldData;
import org.jspecify.annotations.NullMarked;
/**
* Represents the different categories used to organize and display {@link BuildWorld}s in the navigator menus. Each category corresponds to a distinct filter or access level for
* worlds.
*
* @since 3.0.0
*/
@NullMarked
public enum NavigatorCategory {
/**
* Represents the category for public worlds. This navigator inventory contains all {@link BuildWorld}s that are still being built or are generally accessible.
*/
PUBLIC,
/**
* Represents the category for archived worlds. This navigator inventory contains {@link BuildWorld}s that have been marked with {@link BuildWorldStatus#ARCHIVE}. These worlds
* are typically read-only and no longer actively built upon.
*
* @see BuildWorldStatus#ARCHIVE
*/
ARCHIVE,
/**
* Represents the category for private worlds. This navigator inventory contains {@link BuildWorld}s that are set as private. These worlds can typically only be modified by
* their creator and explicitly added {@link Builder}s.
*
* @see WorldData#privateWorld()
*/
PRIVATE;
/**
* Determines the appropriate {@link NavigatorCategory} for a given {@link BuildWorld} based on its properties.
* <p>
* First checks if the world is private ({@link #PRIVATE}), then if it's archived ({@link #ARCHIVE}), otherwise it defaults to {@link #PUBLIC}.
*
* @param buildWorld The {@link BuildWorld} for which to determine the category
* @return The corresponding category
*/
public static NavigatorCategory of(BuildWorld buildWorld) {
WorldData worldData = buildWorld.getData();
if (worldData.privateWorld().get()) {
return PRIVATE;
} else if (worldData.status().get() == BuildWorldStatus.ARCHIVE) {
return ARCHIVE;
} else {
return PUBLIC;
}
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and classes for managing world display and rendering.
*/
package de.eintosti.buildsystem.api.world.display;
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.navigator.settings;
import org.bukkit.entity.ArmorStand;
import org.bukkit.inventory.Inventory;
/**
* Represents the type of the navigator.
*
* @since 3.0.0
*/
public enum NavigatorType {
/**
* The old, {@link Inventory}-based navigator.
*/
OLD,
/**
* The new, {@link ArmorStand}-based navigator.
*/
NEW
}
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.navigator.settings;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jspecify.annotations.NullMarked;
/**
* Interface for managing the display settings of worlds in the navigator.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldDisplay {
/**
* Gets the order in which the {@link BuildWorld}s are sorted.
*
* @return The world sort order
*/
WorldSort getWorldSort();
/**
* Sets the order in which the {@link BuildWorld}s are sorted.
*
* @param worldSort The world sort order
*/
void setWorldSort(WorldSort worldSort);
/**
* Gets the filter which removed non-matching {@link BuildWorld}s from the navigator
*
* @return The world filter
*/
WorldFilter getWorldFilter();
}
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.navigator.settings;
import de.eintosti.buildsystem.api.world.BuildWorld;
import java.util.function.Predicate;
import org.jspecify.annotations.NullMarked;
/**
* Interface for a world filter that restricts which {@link BuildWorld}s are shown to a user in the navigator.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldFilter {
/**
* Gets the current mode.
*
* @return The mode
*/
Mode getMode();
/**
* Sets the current mode.
*
* @param mode The mode
*/
void setMode(Mode mode);
/**
* Gets the text which the filter is applied to.
*
* @return The text the filter is applied to
*/
String getText();
/**
* Sets the text which the filter is applied to.
*
* @param text The text
*/
void setText(String text);
/**
* Applies the current filter to a {@link BuildWorld} to determine if it should be shown.
*
* @return A {@link Predicate} that tests if a {@link BuildWorld} matches the filter criteria
*/
Predicate<BuildWorld> apply();
/**
* Represents the different modes of filtering worlds in the navigator.
*/
@NullMarked
enum Mode {
/**
* No filtering is applied.
*/
NONE,
/**
* Worlds that name starts with the filter text.
*
* @see #getText()
*/
STARTS_WITH,
/**
* Worlds that name contains the filter text.
*
* @see #getText()
*/
CONTAINS,
/**
* Worlds that name matches the filter text.
*
* @see #getText()
*/
MATCHES;
/**
* Gets the next filtering mode in the sequence.
*
* @return The next {@link Mode} in the enumeration
*/
public Mode getNext() {
return switch (this) {
case NONE -> STARTS_WITH;
case STARTS_WITH -> CONTAINS;
case CONTAINS -> MATCHES;
case MATCHES -> NONE;
};
}
}
}
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.navigator.settings;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
import de.eintosti.buildsystem.api.world.display.Displayable;
import de.eintosti.buildsystem.api.world.display.Folder;
import java.util.Comparator;
import java.util.Locale;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents the sorting options for worlds in the navigator.
*
* @since 3.0.0
*/
@NullMarked
public enum WorldSort {
/**
* Sort worlds by name in ascending order.
*/
NAME_A_TO_Z(Comparator.comparing(WorldSort::getNameSortKey)),
/**
* Sort worlds by name in descending order.
*/
NAME_Z_TO_A(NAME_A_TO_Z.getComparator().reversed()),
/**
* Sort worlds by project in ascending order.
*/
PROJECT_A_TO_Z(Comparator.comparing(WorldSort::getProjectSortKey)),
/**
* Sort worlds by project in descending order.
*/
PROJECT_Z_TO_A(PROJECT_A_TO_Z.getComparator().reversed()),
/**
* Sort worlds by status ({@link BuildWorldStatus#NOT_STARTED} -> {@link BuildWorldStatus#FINISHED}).
*/
STATUS_NOT_STARTED(Comparator.comparingInt(WorldSort::getStatusSortKey)),
/**
* Sort worlds by status ({@link BuildWorldStatus#FINISHED} -> {@link BuildWorldStatus#NOT_STARTED}).
*/
STATUS_FINISHED(STATUS_NOT_STARTED.getComparator().reversed()),
/**
* Sort worlds by creation date in ascending order (oldest first).
*/
OLDEST_FIRST(Comparator.comparingLong(Displayable::getCreation)),
/**
* Sort worlds by creation date in descending order (newest first).
*/
NEWEST_FIRST(OLDEST_FIRST.getComparator().reversed());
private final Comparator<Displayable> comparator;
WorldSort(Comparator<Displayable> comparator) {
this.comparator = comparator;
}
/**
* Retrieves the name of a {@link Displayable} in lowercase for sorting purposes.
*
* @param displayable The {@link Displayable} item (e.g., {@link BuildWorld} or {@link Folder})
* @return The lowercase name of the displayable
*/
private static String getNameSortKey(Displayable displayable) {
return displayable.getName().toLowerCase(Locale.ROOT);
}
/**
* Retrieves the project name of a {@link Displayable} in lowercase for sorting purposes. If the displayable is a {@link BuildWorld}, its project name is returned. If it is a
* {@link Folder}, its project is returned.
*
* @param displayable The {@link Displayable} item (e.g., {@link BuildWorld} or {@link Folder})
* @return The lowercase project name, or an empty string if not applicable
*/
private static String getProjectSortKey(Displayable displayable) {
return switch (displayable) {
case BuildWorld world -> world.getData().project().get().toLowerCase(Locale.ROOT);
case Folder folder -> folder.getProject().toLowerCase(Locale.ROOT);
default -> "";
};
}
/**
* Retrieves the status stage of a {@link Displayable} for sorting purposes. If the displayable is a {@link BuildWorld}, its status stage is returned. Otherwise,
* {@link BuildWorldStatus#FINISHED} stage is returned.
*
* @param displayable The {@link Displayable} item (e.g., {@link BuildWorld} or {@link Folder})
* @return The status stage integer
*/
private static int getStatusSortKey(Displayable displayable) {
if (displayable instanceof BuildWorld buildWorld) {
return buildWorld.getData().status().get().getStage();
}
return BuildWorldStatus.FINISHED.getStage();
}
/**
* Matches a string to a {@link WorldSort} enum constant.
*
* @param type The string to match
* @return The matched {@link WorldSort} constant, or {@link WorldSort#NAME_A_TO_Z} if no match is found
*/
public static WorldSort matchWorldSort(@Nullable String type) {
if (type == null) {
return NAME_A_TO_Z;
}
for (WorldSort value : values()) {
if (value.toString().equalsIgnoreCase(type)) {
return value;
}
}
return NAME_A_TO_Z;
}
/**
* Gets the pre-configured comparator for this sort order.
*
* @return The comparator used to sort {@link Displayable} items
*/
public Comparator<Displayable> getComparator() {
return this.comparator;
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and enumerations for navigator-specific settings within the BuildSystem API. This includes options for how worlds are displayed, filtered, and sorted in the
* in-game navigator menus.
*/
package de.eintosti.buildsystem.api.world.navigator.settings;
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides interfaces and classes for managing world backups.
*/
package de.eintosti.buildsystem.api.world;
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.util;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NullMarked;
/**
* Provides utilities for loading and managing {@link BuildWorld}s. This interface handles the process of making a world accessible on the server.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldLoader {
/**
* Loads the world associated with this loader for a specific player. This typically involves teleporting the player to the world after it's loaded.
*
* @param player The {@link Player} for whom the world should be loaded and who will be teleported into it
*/
void loadForPlayer(Player player);
/**
* Loads the world associated with this loader without teleporting any specific player. This is useful for background world loading or server-side operations.
*/
void load();
}
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.util;
import de.eintosti.buildsystem.api.data.Type;
import de.eintosti.buildsystem.api.world.BuildWorld;
import de.eintosti.buildsystem.api.world.builder.Builder;
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Manages and checks permissions related to {@link BuildWorld}s within the BuildSystem. This interface handles permissions for actions such as entering, modifying, and executing
* commands in worlds.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldPermissions {
/**
* Checks if the given {@link Player} is allowed to enter the world associated with these permissions.
* <p>
* A player can enter if any of the following conditions are met:
* <ul>
* <li>They have the administrative permission ({@link #hasAdminPermission(Player)}).</li>
* <li>They can bypass the view permission ({@link #canBypassViewPermission(Player)}).</li>
* <li>They are either the world's creator or an assigned builder.</li>
* <li>The world is public (its permission is set to "{@code -}").</li>
* <li>They possess the specific permission defined in the world's data.</li>
* </ul>
*
* @param player The {@link Player} to check
* @return {@code true} if the player can enter the world, {@code false} otherwise
*/
boolean canEnter(Player player);
/**
* Checks if a {@link Player} is allowed to perform a specific modification in the {@link BuildWorld}.
* <p>
* Modifications might be disallowed due to:
* <ul>
* <li>The world having its {@link BuildWorldStatus} set to {@link BuildWorldStatus#ARCHIVE}.</li>
* <li>A world setting is enabled that specifically prohibits certain events (e.g., block placement/breaking).</li>
* <li>The world is configured to only allow designated {@link Builder}s, and the player is neither a builder nor the world's creator.</li>
* </ul>
* <p>
* However, a player can bypass these restrictions if:
* <ul>
* <li>They have the administrative permission ({@link #hasAdminPermission(Player)}).</li>
* <li>They are in a "build mode" that allows them to bypass building restrictions ({@link #canBypassBuildRestriction(Player)}).</li>
* <li>They have the bypass permission for the check</li>
* </ul>
*
* @param player The player attempting to modify the world
* @param check The specific data type representing the modification to be checked
* @return {@code true} if the player is allowed to modify the world, {@code false} otherwise
*/
boolean canModify(Player player, Type<Boolean> check);
/**
* Checks if the given {@link Player} is permitted to execute a specific command within the context of the current world.
* <p>
* Permissions are handled as follows:
* <ul>
* <li>The world's creator can run the command if they have the base permission, optionally ending with {@code .self}.</li>
* <li>All other players require the permission {@code <permission>.other} to execute the command.</li>
* </ul>
*
* @param player The {@link Player} attempting to run the command
* @param permission The base permission string required for the command (e.g., "buildsystem.command.mycommand")
* @return {@code true} if the player is authorized to run the command, {@code false} otherwise
*/
boolean canPerformCommand(Player player, @Nullable String permission);
/**
* Checks if the given {@link Player} possesses the administrative permission, typically "{@code buildsystem.admin}". Players with this permission can bypass many
* world-specific restrictions.
*
* @param player The {@link Player} to check
* @return {@code true} if the player has the administrative permission, {@code false} otherwise
*/
boolean hasAdminPermission(Player player);
/**
* Checks if the player can bypass the permission required to view a private world in the navigator. This is separate from the `canEnter` permission and relates specifically to
* listing the world.
*
* @param player The {@link Player} to check
* @return {@code true} if the player can bypass the view permission, {@code false} otherwise
*/
boolean canBypassViewPermission(Player player);
/**
* Checks if the given {@link Player} can bypass standard building restrictions due to being in a special "build mode" or having a bypass permission. This allows players to
* modify worlds even if general building is disabled.
*
* @param player The {@link Player} to check
* @return {@code true} if the player can bypass build restrictions, {@code false} otherwise
*/
boolean canBypassBuildRestriction(Player player);
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.util;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NullMarked;
/**
* Provides utilities for teleporting {@link Player}s to specific locations within a {@link BuildWorld}. This interface ensures safe and controlled player movement.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldTeleporter {
/**
* Teleports the given {@link Player} to the designated spawn location of the world associated with this teleporter. If a custom spawn is not set, the player will be teleported
* to the world's default spawn.
*
* @param player The {@link Player} to teleport
*/
void teleport(Player player);
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.eintosti.buildsystem.api.world.util;
import de.eintosti.buildsystem.api.world.BuildWorld;
import org.jspecify.annotations.NullMarked;
/**
* Provides utilities for managing the unloading process of a {@link BuildWorld}. This interface handles tasks such as initiating and cancelling unload procedures.
*
* @since 3.0.0
*/
@NullMarked
public interface WorldUnloader {
/**
* Manages the {@link BuildWorld}'s unload state.
* <p>
* If world unloading is enabled in the config, the unload task is started.
*/
void manageUnload();
/**
* Starts a delayed task to unload the world, if world unloading is enabled in the config.
*/
void startUnloadTask();
/**
* Resets the world unload task.
*/
void resetUnloadTask();
/**
* Attempt to unload the world.
* <p>
* If the world contains any players, is blacklisted for unloading or is the spawn world, the unload will be canceled.
*/
void unload();
/**
* Forces the unloading of the world, bypassing any checks or grace periods.
*
* @param save Whether the world should be saved before unloading
*/
void forceUnload(boolean save);
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018-2025, Thomas Meaney
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Provides utility classes and interfaces for managing world-related operations.
*/
package de.eintosti.buildsystem.api.world.util;