@@ -0,0 +1,233 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
|
||||
|
||||
applyCoreConfiguration()
|
||||
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("com.gradleup.shadow") version "9.2.2"
|
||||
id("de.eldoria.plugin-yml.bukkit") version "0.8.0"
|
||||
}
|
||||
|
||||
project.description = "Core"
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "AuthLib"
|
||||
url = uri("https://libraries.minecraft.net/")
|
||||
}
|
||||
maven {
|
||||
name = "EngineHub"
|
||||
url = uri("https://maven.enginehub.org/repo/")
|
||||
}
|
||||
maven {
|
||||
name = "PlaceholderAPI"
|
||||
url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||
}
|
||||
maven {
|
||||
name = "Modrinth"
|
||||
url = uri("https://api.modrinth.com/maven")
|
||||
}
|
||||
modrinthMavenWorkaround(
|
||||
"axiom-paper-plugin",
|
||||
"4.0.1-1.21.1",
|
||||
"AxiomPaper-4.0.1-for-MC1.21.1.jar"
|
||||
)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":buildsystem-api"))
|
||||
|
||||
compileOnlyApi(libs.annotations)
|
||||
compileOnlyApi(libs.jspecify)
|
||||
|
||||
compileOnly(libs.spigot)
|
||||
compileOnly(libs.authlib)
|
||||
compileOnly(libs.luckperms)
|
||||
compileOnly(libs.placeholderapi)
|
||||
compileOnly(libs.worldedit)
|
||||
compileOnly(libs.axiompaper)
|
||||
|
||||
implementation(libs.paperlib)
|
||||
implementation(libs.xseries)
|
||||
implementation(libs.fastboard)
|
||||
implementation(libs.nbt) { isTransitive = false }
|
||||
implementation(libs.bstats)
|
||||
implementation(libs.aws.core) // Unable to find the dependency at runtime, so we add it here
|
||||
|
||||
library(libs.bundles.aws)
|
||||
library(libs.bouncycastle)
|
||||
library(libs.sftp)
|
||||
library(libs.zip4j)
|
||||
}
|
||||
|
||||
tasks.named("assemble") {
|
||||
dependsOn(tasks.named("shadowJar"))
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
minimize()
|
||||
archiveFileName.set("${rootProject.name}-${project.version}.jar")
|
||||
|
||||
val shadePath = "de.eintosti.buildsystem.util.external"
|
||||
relocate("io.papermc.lib", "$shadePath.paperlib")
|
||||
relocate("com.cryptomorin.xseries", "$shadePath.xseries")
|
||||
relocate("fr.mrmicky.fastboard", "$shadePath.fastboard")
|
||||
relocate("dev.dewy.nbt", "$shadePath.nbt")
|
||||
relocate("org.bstats", "$shadePath.bstats")
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
val props = mapOf("version" to project.version)
|
||||
filesMatching("plugin.yml") {
|
||||
expand(props)
|
||||
}
|
||||
}
|
||||
|
||||
bukkit {
|
||||
name = "BuildSystem"
|
||||
version = "${project.version}"
|
||||
description = "Powerful, easy to use system for builders"
|
||||
author = "einTosti"
|
||||
website = "https://buildsystem.eintosti.de"
|
||||
|
||||
main = "de.eintosti.buildsystem.BuildSystemPlugin"
|
||||
apiVersion = "1.13"
|
||||
softDepend = listOf("LuckPerms", "PlaceholderAPI", "WorldEdit", "AxiomPaper")
|
||||
|
||||
commands {
|
||||
register("back") {
|
||||
description = "Teleports you to your previous location."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("blocks") {
|
||||
description = "Opens a menu with secret blocks."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("build") {
|
||||
description = "Bypass build restrictions."
|
||||
usage = "/<command> [player]"
|
||||
}
|
||||
register("buildsystem") {
|
||||
description = "Overview of all plugin commands."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("config") {
|
||||
description = "Reload the config."
|
||||
usage = "/<command> reload"
|
||||
}
|
||||
register("day") {
|
||||
description = "Set a world's time to daytime."
|
||||
usage = "/<command> [world]"
|
||||
}
|
||||
register("explosions") {
|
||||
description = "Toggle explosions within a world."
|
||||
usage = "/<command> [world]"
|
||||
}
|
||||
register("gamemode") {
|
||||
description = "Change your gamemode."
|
||||
aliases = listOf("gm")
|
||||
usage = "/<command> <mode> [player]"
|
||||
}
|
||||
register("night") {
|
||||
description = "Set a world's time to nighttime."
|
||||
usage = "/<command> [world]"
|
||||
}
|
||||
register("noai") {
|
||||
description = "Disable all the entity AIs in a world."
|
||||
usage = "/<command> [world]"
|
||||
}
|
||||
register("physics") {
|
||||
description = "Toggle block physics."
|
||||
usage = "/<command> [world]"
|
||||
}
|
||||
register("settings") {
|
||||
description = "Manage user settings."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("setup") {
|
||||
description = "Change the default items in used in the navigator."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("skull") {
|
||||
description = "Receive a player's skull."
|
||||
usage = "/<command> [name]"
|
||||
}
|
||||
register("spawn") {
|
||||
description = "Teleport to the spawn."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("speed") {
|
||||
description = "Change your flying/walking speed."
|
||||
aliases = listOf("s")
|
||||
usage = "/<command> [1-5]"
|
||||
}
|
||||
register("top") {
|
||||
description = "Teleports you to the highest location."
|
||||
usage = "/<command>"
|
||||
}
|
||||
register("worlds") {
|
||||
description = "Open the world menu."
|
||||
aliases = listOf("w")
|
||||
usage = "/<command>"
|
||||
}
|
||||
}
|
||||
permissions {
|
||||
register("buildsystem.help") {
|
||||
children = listOf("buildsystem.help.buildsystem", "buildsystem.help.worlds")
|
||||
description = "Permission for help commands."
|
||||
default = BukkitPluginDescription.Permission.Default.TRUE
|
||||
}
|
||||
register("buildsystem.navigator") {
|
||||
description = "Open the worlds navigator."
|
||||
default = BukkitPluginDescription.Permission.Default.TRUE
|
||||
}
|
||||
register("buildsystem.navigator.item") {
|
||||
description = "Receive and use the navigator."
|
||||
default = BukkitPluginDescription.Permission.Default.TRUE
|
||||
}
|
||||
register("buildsystem.create") {
|
||||
children = listOf(
|
||||
"buildsystem.create.private",
|
||||
"buildsystem.create.type.normal",
|
||||
"buildsystem.create.type.flat",
|
||||
"buildsystem.create.type.nether",
|
||||
"buildsystem.create.type.end",
|
||||
"buildsystem.create.type.void"
|
||||
)
|
||||
description = "Permission for creating world types."
|
||||
default = BukkitPluginDescription.Permission.Default.TRUE
|
||||
}
|
||||
register("buildsystem.setstatus") {
|
||||
children = listOf(
|
||||
"buildsystem.setstatus.hidden",
|
||||
"buildsystem.setstatus.archive",
|
||||
"buildsystem.setstatus.finished",
|
||||
"buildsystem.setstatus.almostfinished",
|
||||
"buildsystem.setstatus.inprogress",
|
||||
"buildsystem.setstatus.notstarted"
|
||||
)
|
||||
description = "Permission for setting world status."
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
}
|
||||
register("buildsystem.gamemode") {
|
||||
children = listOf("buildsystem.gamemode.survival", "buildsystem.gamemode.creative", "buildsystem.gamemode.adventure", "buildsystem.gamemode.spectator")
|
||||
description = "Permission for changing own gamemode."
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
}
|
||||
register("buildsystem.gamemode.other") {
|
||||
children =
|
||||
listOf("buildsystem.gamemode.survival.other", "buildsystem.gamemode.creative.other", "buildsystem.gamemode.adventure.other", "buildsystem.gamemode.spectator.other")
|
||||
description = "Permission for changing other player's gamemode."
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
}
|
||||
register("buildsystem.physics.message") {
|
||||
description = "Receive the message that physics are disabled in a world."
|
||||
default = BukkitPluginDescription.Permission.Default.TRUE
|
||||
}
|
||||
register("buildsystem.updates") {
|
||||
description = "Receive update messages."
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import de.eintosti.buildsystem.api.BuildSystem;
|
||||
import de.eintosti.buildsystem.api.BuildSystemApi;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.world.navigator.settings.NavigatorType;
|
||||
import de.eintosti.buildsystem.command.BackCommand;
|
||||
import de.eintosti.buildsystem.command.BlocksCommand;
|
||||
import de.eintosti.buildsystem.command.BuildCommand;
|
||||
import de.eintosti.buildsystem.command.BuildSystemCommand;
|
||||
import de.eintosti.buildsystem.command.ConfigCommand;
|
||||
import de.eintosti.buildsystem.command.ExplosionsCommand;
|
||||
import de.eintosti.buildsystem.command.GamemodeCommand;
|
||||
import de.eintosti.buildsystem.command.NoAICommand;
|
||||
import de.eintosti.buildsystem.command.PhysicsCommand;
|
||||
import de.eintosti.buildsystem.command.SettingsCommand;
|
||||
import de.eintosti.buildsystem.command.SetupCommand;
|
||||
import de.eintosti.buildsystem.command.SkullCommand;
|
||||
import de.eintosti.buildsystem.command.SpawnCommand;
|
||||
import de.eintosti.buildsystem.command.SpeedCommand;
|
||||
import de.eintosti.buildsystem.command.TimeCommand;
|
||||
import de.eintosti.buildsystem.command.TopCommand;
|
||||
import de.eintosti.buildsystem.command.WorldsCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.BuildTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.ConfigTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.EmptyTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.GamemodeTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.PhysicsTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.SpawnTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.SpeedTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.TimeTabCompleter;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import de.eintosti.buildsystem.config.Config.Folder;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Archive;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Builder;
|
||||
import de.eintosti.buildsystem.config.Config.World;
|
||||
import de.eintosti.buildsystem.config.Config.World.Unload;
|
||||
import de.eintosti.buildsystem.config.migration.ConfigMigrationManager;
|
||||
import de.eintosti.buildsystem.expansion.luckperms.LuckPermsExpansion;
|
||||
import de.eintosti.buildsystem.expansion.placeholderapi.PlaceholderApiExpansion;
|
||||
import de.eintosti.buildsystem.listener.AsyncPlayerChatListener;
|
||||
import de.eintosti.buildsystem.listener.AsyncPlayerPreLoginListener;
|
||||
import de.eintosti.buildsystem.listener.BlockPhysicsListener;
|
||||
import de.eintosti.buildsystem.listener.BuildModePreventationListener;
|
||||
import de.eintosti.buildsystem.listener.BuildWorldResetUnloadListener;
|
||||
import de.eintosti.buildsystem.listener.EditSessionListener;
|
||||
import de.eintosti.buildsystem.listener.EntityDamageListener;
|
||||
import de.eintosti.buildsystem.listener.EntitySpawnListener;
|
||||
import de.eintosti.buildsystem.listener.FoodLevelChangeListener;
|
||||
import de.eintosti.buildsystem.listener.InventoryCreativeListener;
|
||||
import de.eintosti.buildsystem.listener.InventoryListener;
|
||||
import de.eintosti.buildsystem.listener.NavigatorListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerChangedWorldListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerCommandPreprocessListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerInventoryClearListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerJoinListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerMoveListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerQuitListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerRespawnListener;
|
||||
import de.eintosti.buildsystem.listener.PlayerTeleportListener;
|
||||
import de.eintosti.buildsystem.listener.SettingsInteractListener;
|
||||
import de.eintosti.buildsystem.listener.SignChangeListener;
|
||||
import de.eintosti.buildsystem.listener.WeatherChangeListener;
|
||||
import de.eintosti.buildsystem.listener.WorldManipulateByAxiomListener;
|
||||
import de.eintosti.buildsystem.listener.WorldManipulateListener;
|
||||
import de.eintosti.buildsystem.player.LogoutLocationImpl;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.customblock.CustomBlockManager;
|
||||
import de.eintosti.buildsystem.player.settings.NoClipManager;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.util.UpdateChecker;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryManager;
|
||||
import de.eintosti.buildsystem.world.SpawnManager;
|
||||
import de.eintosti.buildsystem.world.WorldServiceImpl;
|
||||
import de.eintosti.buildsystem.world.backup.BackupService;
|
||||
import de.eintosti.buildsystem.world.display.CustomizableIcons;
|
||||
import de.eintosti.buildsystem.world.navigator.ArmorStandManager;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.AdvancedPie;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class BuildSystemPlugin extends JavaPlugin {
|
||||
|
||||
public static final int SPIGOT_ID = 60441;
|
||||
public static final int METRICS_ID = 7427;
|
||||
public static final String ADMIN_PERMISSION = "buildsystem.admin";
|
||||
|
||||
private static BuildSystemPlugin instance;
|
||||
|
||||
private ArmorStandManager armorStandManager;
|
||||
private CustomBlockManager customBlockManager;
|
||||
private InventoryManager inventoryManager;
|
||||
private PlayerServiceImpl playerService;
|
||||
private NoClipManager noClipManager;
|
||||
private SettingsManager settingsManager;
|
||||
private SpawnManager spawnManager;
|
||||
private WorldServiceImpl worldService;
|
||||
private BackupService backupService;
|
||||
private CustomizableIcons customizableIcons;
|
||||
|
||||
private LuckPermsExpansion luckPermsExpansion;
|
||||
private PlaceholderApiExpansion placeholderApiExpansion;
|
||||
|
||||
private BuildSystemApi api;
|
||||
|
||||
private BukkitTask configSaveTask;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
instance = this;
|
||||
|
||||
new ConfigMigrationManager(this).migrate();
|
||||
this.getConfig().options().copyDefaults(true);
|
||||
this.saveConfig();
|
||||
Config.load();
|
||||
|
||||
Messages.createMessageFile();
|
||||
createTemplateFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
initClasses();
|
||||
|
||||
registerCommands();
|
||||
registerTabCompleters();
|
||||
registerListeners();
|
||||
registerExpansions();
|
||||
|
||||
performUpdateCheck();
|
||||
|
||||
this.api = new BuildSystemApi(this);
|
||||
this.api.register();
|
||||
getServer().getServicesManager().register(BuildSystem.class, api, this, ServicePriority.Normal);
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> {
|
||||
BuildPlayer buildPlayer = playerService.getPlayerStorage().createBuildPlayer(pl);
|
||||
Settings settings = buildPlayer.getSettings();
|
||||
noClipManager.startNoClip(pl, settings);
|
||||
settingsManager.displayScoreboard(pl);
|
||||
});
|
||||
|
||||
registerStats();
|
||||
|
||||
this.configSaveTask = Bukkit.getScheduler().runTaskTimer(this, this::saveBuildConfig, 6000L, 6000L);
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage(
|
||||
"%sBuildSystem » Plugin %senabled%s!".formatted(ChatColor.RESET, ChatColor.GREEN, ChatColor.RESET)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> {
|
||||
BuildPlayer buildPlayer = playerService.getPlayerStorage().getBuildPlayer(pl);
|
||||
buildPlayer.getCachedValues().resetCachedValues(pl);
|
||||
buildPlayer.setLogoutLocation(new LogoutLocationImpl(pl.getWorld().getName(), pl.getLocation()));
|
||||
|
||||
settingsManager.hideScoreboard(pl);
|
||||
noClipManager.stopNoClip(pl.getUniqueId());
|
||||
playerService.closeNewNavigator(pl);
|
||||
});
|
||||
|
||||
this.backupService.getStorage().close();
|
||||
|
||||
reloadConfigData(false);
|
||||
saveConfig();
|
||||
saveBuildConfig();
|
||||
|
||||
if (this.configSaveTask != null) {
|
||||
this.configSaveTask.cancel();
|
||||
}
|
||||
|
||||
unregisterExpansions();
|
||||
this.api.unregister();
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage(
|
||||
"%sBuildSystem » Plugin %sdisabled%s!".formatted(ChatColor.RESET, ChatColor.RED, ChatColor.RESET)
|
||||
);
|
||||
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public static BuildSystemPlugin get() {
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException("BuildSystemPlugin instance is not initialized. Make sure the plugin is enabled.");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void initClasses() {
|
||||
this.customizableIcons = new CustomizableIcons(this);
|
||||
|
||||
this.inventoryManager = new InventoryManager();
|
||||
this.armorStandManager = new ArmorStandManager();
|
||||
this.customBlockManager = new CustomBlockManager(this);
|
||||
(this.playerService = new PlayerServiceImpl(this)).init();
|
||||
this.noClipManager = new NoClipManager(this);
|
||||
(this.worldService = new WorldServiceImpl(this)).init();
|
||||
this.backupService = new BackupService(this);
|
||||
this.settingsManager = new SettingsManager(this);
|
||||
this.spawnManager = new SpawnManager(this);
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
new BackCommand(this);
|
||||
new BlocksCommand(this);
|
||||
new BuildCommand(this);
|
||||
new BuildSystemCommand(this);
|
||||
new ConfigCommand(this);
|
||||
new ExplosionsCommand(this);
|
||||
new GamemodeCommand(this);
|
||||
new NoAICommand(this);
|
||||
new PhysicsCommand(this);
|
||||
new SettingsCommand(this);
|
||||
new SetupCommand(this);
|
||||
new SkullCommand(this);
|
||||
new SpawnCommand(this);
|
||||
new SpeedCommand(this);
|
||||
new TimeCommand(this);
|
||||
new TopCommand(this);
|
||||
new WorldsCommand(this);
|
||||
}
|
||||
|
||||
private void registerTabCompleters() {
|
||||
new BuildTabCompleter(this);
|
||||
new ConfigTabCompleter(this);
|
||||
new EmptyTabCompleter(this);
|
||||
new GamemodeTabCompleter(this);
|
||||
new PhysicsTabCompleter(this);
|
||||
new SpawnTabCompleter(this);
|
||||
new SpeedTabCompleter(this);
|
||||
new TimeTabCompleter(this);
|
||||
new WorldsTabCompleter(this);
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
new AsyncPlayerChatListener(this);
|
||||
new AsyncPlayerPreLoginListener(this);
|
||||
new BlockPhysicsListener(this);
|
||||
new CustomBlockManager(this);
|
||||
new BuildModePreventationListener(this);
|
||||
new BuildWorldResetUnloadListener(this);
|
||||
new EntitySpawnListener(this);
|
||||
new FoodLevelChangeListener(this);
|
||||
new InventoryCreativeListener(this);
|
||||
new InventoryListener(this);
|
||||
new NavigatorListener(this);
|
||||
new PlayerChangedWorldListener(this);
|
||||
new EntityDamageListener(this);
|
||||
new PlayerCommandPreprocessListener(this);
|
||||
new PlayerInventoryClearListener(this);
|
||||
new PlayerJoinListener(this);
|
||||
new PlayerMoveListener(this);
|
||||
new PlayerQuitListener(this);
|
||||
new PlayerRespawnListener(this);
|
||||
new PlayerTeleportListener(this);
|
||||
new SettingsInteractListener(this);
|
||||
new SignChangeListener(this);
|
||||
new WeatherChangeListener(this);
|
||||
new WorldManipulateListener(this);
|
||||
}
|
||||
|
||||
private void registerStats() {
|
||||
Metrics metrics = new Metrics(this, METRICS_ID);
|
||||
metrics.addCustomChart(new SimplePie("archive_vanish", () -> String.valueOf(Archive.vanish)));
|
||||
metrics.addCustomChart(new SimplePie("block_world_edit", () -> String.valueOf(Builder.blockWorldEditNonBuilder)));
|
||||
metrics.addCustomChart(new SimplePie("join_quit_messages", () -> String.valueOf(Config.Messages.joinQuitMessages)));
|
||||
metrics.addCustomChart(new SimplePie("lock_weather", () -> String.valueOf(World.lockWeather)));
|
||||
metrics.addCustomChart(new SimplePie("scoreboard", () -> String.valueOf(Config.Settings.scoreboard)));
|
||||
metrics.addCustomChart(new SimplePie("update_checker", () -> String.valueOf(Config.Settings.updateChecker)));
|
||||
metrics.addCustomChart(new SimplePie("unload_worlds", () -> String.valueOf(Unload.enabled)));
|
||||
metrics.addCustomChart(new AdvancedPie("navigator_type", new Callable<>() {
|
||||
@Override
|
||||
public Map<String, Integer> call() {
|
||||
Map<String, Integer> valueMap = new HashMap<>();
|
||||
valueMap.put("Old", getPlayersWithNavigator(NavigatorType.OLD));
|
||||
valueMap.put("New", getPlayersWithNavigator(NavigatorType.NEW));
|
||||
return valueMap;
|
||||
}
|
||||
|
||||
private int getPlayersWithNavigator(NavigatorType navigatorType) {
|
||||
return (int) playerService.getPlayerStorage().getBuildPlayers().stream()
|
||||
.filter(buildPlayer -> buildPlayer.getSettings().getNavigatorType() == navigatorType)
|
||||
.count();
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new SimplePie("folder_override_permissions", () -> String.valueOf(Folder.overridePermissions)));
|
||||
metrics.addCustomChart(new SimplePie("folder_override_projects", () -> String.valueOf(Folder.overrideProjects)));
|
||||
}
|
||||
|
||||
private void registerExpansions() {
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
|
||||
if (pluginManager.getPlugin("PlaceholderAPI") != null) {
|
||||
this.placeholderApiExpansion = new PlaceholderApiExpansion(this);
|
||||
this.placeholderApiExpansion.register();
|
||||
}
|
||||
|
||||
if (pluginManager.getPlugin("LuckPerms") != null) {
|
||||
this.luckPermsExpansion = new LuckPermsExpansion(this);
|
||||
this.luckPermsExpansion.registerAll();
|
||||
}
|
||||
|
||||
if (pluginManager.getPlugin("AxiomPaper") != null) {
|
||||
new WorldManipulateByAxiomListener(this);
|
||||
}
|
||||
|
||||
boolean isWorldEdit = pluginManager.getPlugin("WorldEdit") != null
|
||||
|| pluginManager.getPlugin("FastAsyncWorldEdit") != null;
|
||||
if (isWorldEdit && Builder.blockWorldEditNonBuilder) {
|
||||
new EditSessionListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterExpansions() {
|
||||
if (this.placeholderApiExpansion != null) {
|
||||
this.placeholderApiExpansion.unregister();
|
||||
}
|
||||
|
||||
if (this.luckPermsExpansion != null) {
|
||||
this.luckPermsExpansion.unregisterAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void performUpdateCheck() {
|
||||
if (!Config.Settings.updateChecker) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateChecker.init(this, SPIGOT_ID).requestUpdateCheck().whenComplete((result, e) -> {
|
||||
if (result.requiresUpdate()) {
|
||||
Bukkit.getConsoleSender().sendMessage(
|
||||
ChatColor.YELLOW + "[BuildSystem] Great! a new update is available: "
|
||||
+ ChatColor.GREEN + "v" + result.getNewestVersion()
|
||||
);
|
||||
Bukkit.getConsoleSender().sendMessage(
|
||||
ChatColor.YELLOW + " ➥ Your current version: " +
|
||||
ChatColor.RED + this.getDescription().getVersion()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateChecker.UpdateReason reason = result.getReason();
|
||||
switch (reason) {
|
||||
case COULD_NOT_CONNECT, INVALID_JSON, UNAUTHORIZED_QUERY, UNKNOWN_ERROR, UNSUPPORTED_VERSION_SCHEME -> Bukkit.getConsoleSender().sendMessage(
|
||||
ChatColor.RED + "[BuildSystem] Could not check for a new version of BuildSystem. Reason: " + reason
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void createTemplateFolder() {
|
||||
File templateFolder = new File(getDataFolder() + File.separator + "templates");
|
||||
if (templateFolder.mkdirs()) {
|
||||
getLogger().info("Created \"templates\" folder");
|
||||
}
|
||||
}
|
||||
|
||||
private void saveBuildConfig() {
|
||||
worldService.save();
|
||||
playerService.save();
|
||||
spawnManager.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the config and config data.
|
||||
*
|
||||
* @param init Whether the plugin should reinitialize classes
|
||||
*/
|
||||
public void reloadConfigData(boolean init) {
|
||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
||||
getSettingsManager().hideScoreboard(pl);
|
||||
}
|
||||
|
||||
reloadConfig();
|
||||
Config.load();
|
||||
|
||||
if (init) {
|
||||
worldService.getWorldStorage().getBuildWorlds().forEach(buildWorld -> buildWorld.getUnloader().manageUnload());
|
||||
|
||||
if (Config.Settings.scoreboard) {
|
||||
getSettingsManager().displayScoreboard();
|
||||
} else {
|
||||
getSettingsManager().hideScoreboards();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArmorStandManager getArmorStandManager() {
|
||||
return armorStandManager;
|
||||
}
|
||||
|
||||
public CustomBlockManager getCustomBlockManager() {
|
||||
return customBlockManager;
|
||||
}
|
||||
|
||||
public InventoryManager getInventoryManager() {
|
||||
return inventoryManager;
|
||||
}
|
||||
|
||||
public PlayerServiceImpl getPlayerService() {
|
||||
return playerService;
|
||||
}
|
||||
|
||||
public NoClipManager getNoClipManager() {
|
||||
return noClipManager;
|
||||
}
|
||||
|
||||
public SettingsManager getSettingsManager() {
|
||||
return settingsManager;
|
||||
}
|
||||
|
||||
public SpawnManager getSpawnManager() {
|
||||
return spawnManager;
|
||||
}
|
||||
|
||||
public WorldServiceImpl getWorldService() {
|
||||
return worldService;
|
||||
}
|
||||
|
||||
public BackupService getBackupService() {
|
||||
return backupService;
|
||||
}
|
||||
|
||||
public CustomizableIcons getCustomizableIcons() {
|
||||
return customizableIcons;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.PlayerService;
|
||||
import de.eintosti.buildsystem.api.world.WorldService;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildSystemApi implements BuildSystem {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public BuildSystemApi(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldService getWorldService() {
|
||||
return plugin.getWorldService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerService getPlayerService() {
|
||||
return plugin.getPlayerService();
|
||||
}
|
||||
|
||||
public void register() {
|
||||
BuildSystemProvider.register(this);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
BuildSystemProvider.unregister();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.storage.PlayerStorage;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BackCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerStorage playerStorage;
|
||||
|
||||
public BackCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerStorage = plugin.getPlayerService().getPlayerStorage();
|
||||
plugin.getCommand("back").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.back")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
teleportBack(player);
|
||||
} else {
|
||||
Messages.sendMessage(player, "back_usage");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void teleportBack(Player player) {
|
||||
BuildPlayer buildPlayer = playerStorage.getBuildPlayer(player);
|
||||
Location previousLocation = buildPlayer.getPreviousLocation();
|
||||
if (previousLocation == null) {
|
||||
Messages.sendMessage(player, "back_failed");
|
||||
return;
|
||||
}
|
||||
|
||||
PaperLib.teleportAsync(player, previousLocation)
|
||||
.whenComplete((completed, throwable) -> {
|
||||
if (!completed) {
|
||||
return;
|
||||
}
|
||||
XSound.ENTITY_ZOMBIE_INFECT.play(player);
|
||||
Messages.sendMessage(player, "back_teleported");
|
||||
buildPlayer.setPreviousLocation(null);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.player.customblock.CustomBlockInventory;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BlocksCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public BlocksCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("blocks").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.blocks")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
new CustomBlockInventory(plugin).openInventory(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.event.world.PlayerBuildModeToggleEvent;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.player.PlayerService;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerService playerService;
|
||||
|
||||
public BuildCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerService = plugin.getPlayerService();
|
||||
plugin.getCommand("build").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.build")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> {
|
||||
toggleBuildMode(player, player);
|
||||
}
|
||||
|
||||
case 1 -> {
|
||||
if (!player.hasPermission("buildsystem.build.other")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[0]);
|
||||
if (target == null) {
|
||||
Messages.sendMessage(player, "build_player_not_found");
|
||||
return true;
|
||||
}
|
||||
|
||||
toggleBuildMode(target, player);
|
||||
}
|
||||
|
||||
default -> {
|
||||
Messages.sendMessage(player, "build_usage");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the build mode for a target player.
|
||||
*
|
||||
* @param target The player whose build mode is being changed
|
||||
* @param sender The player who initiated the action, may be the target player themselves
|
||||
*/
|
||||
private void toggleBuildMode(Player target, Player sender) {
|
||||
UUID targetUuid = target.getUniqueId();
|
||||
boolean isEnteringBuildMode = !playerService.getBuildModePlayers().contains(targetUuid);
|
||||
|
||||
PlayerBuildModeToggleEvent toggleEvent = new PlayerBuildModeToggleEvent(target, isEnteringBuildMode, sender);
|
||||
Bukkit.getServer().getPluginManager().callEvent(toggleEvent);
|
||||
if (toggleEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildPlayer buildPlayer = playerService.getPlayerStorage().getBuildPlayer(target);
|
||||
CachedValues cachedValues = buildPlayer.getCachedValues();
|
||||
|
||||
if (isEnteringBuildMode) {
|
||||
playerService.getBuildModePlayers().add(targetUuid);
|
||||
cachedValues.saveGameMode(target.getGameMode());
|
||||
cachedValues.saveInventory(target.getInventory().getContents());
|
||||
target.setGameMode(GameMode.CREATIVE);
|
||||
|
||||
XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(target);
|
||||
if (sender.equals(target)) {
|
||||
Messages.sendMessage(target, "build_activated_self");
|
||||
} else {
|
||||
XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(sender);
|
||||
Messages.sendMessage(sender, "build_activated_other_sender", Map.entry("%target%", target.getName()));
|
||||
Messages.sendMessage(target, "build_activated_other_target", Map.entry("%sender%", sender.getName()));
|
||||
}
|
||||
} else {
|
||||
if (!playerService.getBuildModePlayers().remove(targetUuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cachedValues.resetGameModeIfPresent(target);
|
||||
cachedValues.resetInventoryIfPresent(target);
|
||||
|
||||
XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(target);
|
||||
if (sender.equals(target)) {
|
||||
Messages.sendMessage(target, "build_deactivated_self");
|
||||
} else {
|
||||
XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(sender);
|
||||
Messages.sendMessage(sender, "build_deactivated_other_sender", Map.entry("%target%", target.getName()));
|
||||
Messages.sendMessage(target, "build_deactivated_other_target", Map.entry("%sender%", sender.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildSystemCommand extends PagedCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public BuildSystemCommand(BuildSystemPlugin plugin) {
|
||||
super("buildsystem_title_with_page", "buildsystem_permission");
|
||||
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("buildsystem").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.help.buildsystem")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sendMessage(player, 1);
|
||||
} else if (args.length == 1) {
|
||||
try {
|
||||
int page = Integer.parseInt(args[0]);
|
||||
sendMessage(player, page);
|
||||
} catch (NumberFormatException e) {
|
||||
Messages.sendMessage(player, "buildsystem_invalid_page");
|
||||
}
|
||||
} else {
|
||||
Messages.sendMessage(player, "buildsystem_usage");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<TextComponent> getCommands(Player player) {
|
||||
List<TextComponent> commands = Lists.newArrayList(
|
||||
createComponent(player, "/back", "buildsystem_back", "/back", "buildsystem.back"),
|
||||
createComponent(player, "/blocks", "buildsystem_blocks", "/blocks", "buildsystem.blocks"),
|
||||
createComponent(player, "/build [player]", "buildsystem_build", "/build", "buildsystem.build"),
|
||||
createComponent(player, "/config reload", "buildsystem_config", "/config reload", "buildsystem.config"),
|
||||
createComponent(player, "/day [world]", "buildsystem_day", "/day", "buildsystem.day"),
|
||||
createComponent(player, "/explosions [world]", "buildsystem_explosions", "/explosions", "buildsystem.explosions"),
|
||||
createComponent(player, "/gm <gamemode> [player]", "buildsystem_gamemode", "/gm ", "buildsystem.gamemode"),
|
||||
createComponent(player, "/night [world]", "buildsystem_night", "/night", "buildsystem.night"),
|
||||
createComponent(player, "/noai [world]", "buildsystem_noai", "/noai", "buildsystem.noai"),
|
||||
createComponent(player, "/physics [world]", "buildsystem_physics", "/physics", "buildsystem.physics"),
|
||||
createComponent(player, "/settings", "buildsystem_settings", "/settings", "buildsystem.settings"),
|
||||
createComponent(player, "/setup", "buildsystem_setup", "/setup", "buildsystem.setup"),
|
||||
createComponent(player, "/skull [player/id]", "buildsystem_skull", "/skull", "buildsystem.skull"),
|
||||
createComponent(player, "/spawn", "buildsystem_spawn", "/spawn", "-"),
|
||||
createComponent(player, "/speed <1-5>", "buildsystem_speed", "/speed ", "buildsystem.speed"),
|
||||
createComponent(player, "/top", "buildsystem_top", "/top", "buildsystem.top"),
|
||||
createComponent(player, "/worlds help", "buildsystem_worlds", "/worlds help", "-")
|
||||
);
|
||||
commands.removeIf(textComponent -> textComponent.getText().isEmpty());
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import java.util.Locale;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ConfigCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public ConfigCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("config").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!sender.hasPermission("buildsystem.config")) {
|
||||
Messages.sendPermissionError(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
Messages.sendMessage(sender, "config_usage");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "rl":
|
||||
case "reload":
|
||||
Messages.reloadMessages();
|
||||
plugin.reloadConfigData(true);
|
||||
Messages.sendMessage(sender, "config_reloaded");
|
||||
break;
|
||||
default:
|
||||
Messages.sendMessage(sender, "config_usage");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class ExplosionsCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public ExplosionsCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("explosions").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.explosions")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> toggleExplosions(player, player.getWorld());
|
||||
case 1 -> toggleExplosions(player, Bukkit.getWorld(args[0]));
|
||||
default -> Messages.sendMessage(player, "explosions_usage");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void toggleExplosions(Player player, @Nullable World world) {
|
||||
if (world == null) {
|
||||
Messages.sendMessage(player, "explosions_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(world);
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "explosions_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
WorldData worldData = buildWorld.getData();
|
||||
if (!worldData.explosions().get()) {
|
||||
worldData.explosions().set(true);
|
||||
Messages.sendMessage(player, "explosions_activated", Map.entry("%world%", buildWorld.getName()));
|
||||
} else {
|
||||
worldData.explosions().set(false);
|
||||
Messages.sendMessage(player, "explosions_deactivated", Map.entry("%world%", buildWorld.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class GamemodeCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public GamemodeCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("gamemode").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sendUsageMessage(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "survival":
|
||||
case "s":
|
||||
case "0":
|
||||
setGamemode(player, args, GameMode.SURVIVAL, Messages.getString("gamemode_survival", player));
|
||||
break;
|
||||
case "creative":
|
||||
case "c":
|
||||
case "1":
|
||||
setGamemode(player, args, GameMode.CREATIVE, Messages.getString("gamemode_creative", player));
|
||||
break;
|
||||
case "adventure":
|
||||
case "a":
|
||||
case "2":
|
||||
setGamemode(player, args, GameMode.ADVENTURE, Messages.getString("gamemode_adventure", player));
|
||||
break;
|
||||
case "spectator":
|
||||
case "sp":
|
||||
case "3":
|
||||
setGamemode(player, args, GameMode.SPECTATOR, Messages.getString("gamemode_spectator", player));
|
||||
break;
|
||||
default:
|
||||
sendUsageMessage(player);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setGamemode(Player player, String[] args, GameMode gameMode, String gameModeName) {
|
||||
switch (args.length) {
|
||||
case 1 -> this.setPlayerGamemode(player, gameMode, gameModeName);
|
||||
case 2 -> this.setTargetGamemode(player, args, gameMode, gameModeName);
|
||||
default -> this.sendUsageMessage(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUsageMessage(Player player) {
|
||||
Messages.sendMessage(player, "gamemode_usage");
|
||||
}
|
||||
|
||||
private void setPlayerGamemode(Player player, GameMode gameMode, String gameModeName) {
|
||||
if (!player.hasPermission("buildsystem.gamemode.%s".formatted(gameMode.name().toLowerCase(Locale.ROOT)))) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
player.setGameMode(gameMode);
|
||||
Messages.sendMessage(player, "gamemode_set_self", Map.entry("%gamemode%", gameModeName));
|
||||
}
|
||||
|
||||
private void setTargetGamemode(Player player, String[] args, GameMode gameMode, String gameModeName) {
|
||||
if (!player.hasPermission("buildsystem.gamemode.%s.other".formatted(gameMode.name().toLowerCase(Locale.ROOT)))) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[1]);
|
||||
if (target == null) {
|
||||
Messages.sendMessage(player, "gamemode_player_not_found");
|
||||
return;
|
||||
}
|
||||
|
||||
target.setGameMode(gameMode);
|
||||
Messages.sendMessage(target, "gamemode_set_self", Map.entry("%gamemode%", gameModeName));
|
||||
Messages.sendMessage(player, "gamemode_set_other",
|
||||
Map.entry("%target%", target.getName()),
|
||||
Map.entry("%gamemode%", gameModeName)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class NoAICommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public NoAICommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("noai").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.noai")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> toggleAI(player, player.getWorld());
|
||||
case 1 -> toggleAI(player, Bukkit.getWorld(args[0]));
|
||||
default -> Messages.sendMessage(player, "noai_usage");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void toggleAI(Player player, @Nullable World world) {
|
||||
if (world == null) {
|
||||
Messages.sendMessage(player, "noai_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(world);
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "noai_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
WorldData worldData = buildWorld.getData();
|
||||
if (worldData.mobAi().get()) {
|
||||
worldData.mobAi().set(false);
|
||||
Messages.sendMessage(player, "noai_activated", Map.entry("%world%", buildWorld.getName()));
|
||||
} else {
|
||||
worldData.mobAi().set(true);
|
||||
Messages.sendMessage(player, "noai_deactivated", Map.entry("%world%", buildWorld.getName()));
|
||||
}
|
||||
|
||||
boolean hasAi = worldData.mobAi().get();
|
||||
world.getLivingEntities().forEach(entity -> entity.setAI(hasAi));
|
||||
}
|
||||
}
|
||||
@@ -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.command;
|
||||
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public abstract class PagedCommand {
|
||||
|
||||
private static final int MAX_COMMANDS_PER_PAGE = 7;
|
||||
|
||||
private final String title, permissionTemplate;
|
||||
|
||||
public PagedCommand(String title, String permissionTemplate) {
|
||||
this.title = title;
|
||||
this.permissionTemplate = permissionTemplate;
|
||||
}
|
||||
|
||||
protected void sendMessage(Player player, int pageNum) {
|
||||
List<TextComponent> commands = getCommands(player);
|
||||
int numPages = (int) Math.ceil((double) commands.size() / MAX_COMMANDS_PER_PAGE);
|
||||
|
||||
List<TextComponent> page = createPage(commands, numPages, pageNum);
|
||||
page.add(0, new TextComponent("§7§m----------------------------------------------------"));
|
||||
page.add(1, new TextComponent(Messages.getString(this.title, player)
|
||||
.replace("%page%", String.valueOf(pageNum))
|
||||
.replace("%max%", String.valueOf(numPages))
|
||||
.concat("\n"))
|
||||
);
|
||||
page.add(new TextComponent("§7§m----------------------------------------------------"));
|
||||
page.forEach(line -> player.spigot().sendMessage(line));
|
||||
}
|
||||
|
||||
private List<TextComponent> createPage(List<TextComponent> commands, int numPages, int page) {
|
||||
List<List<TextComponent>> pages = new ArrayList<>(numPages);
|
||||
IntStream.range(0, numPages).forEach(i -> pages.add(new ArrayList<>()));
|
||||
|
||||
int currentPage = 0;
|
||||
int commandsInPage = 0;
|
||||
for (TextComponent command : commands) {
|
||||
pages.get(currentPage).add(command);
|
||||
commandsInPage++;
|
||||
|
||||
if (commandsInPage >= MAX_COMMANDS_PER_PAGE) {
|
||||
currentPage++;
|
||||
commandsInPage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pages.get(page - 1);
|
||||
}
|
||||
|
||||
protected abstract List<TextComponent> getCommands(Player player);
|
||||
|
||||
@Contract("_, _, _, _, _-> new")
|
||||
protected TextComponent createComponent(Player player, String command, String commandDescriptionKey, String suggest, String permission) {
|
||||
if (command.isEmpty()) {
|
||||
return new TextComponent();
|
||||
}
|
||||
|
||||
TextComponent commandComponent = new TextComponent("§b" + command);
|
||||
TextComponent textComponent = new TextComponent(" §8» " + Messages.getString(commandDescriptionKey, player));
|
||||
|
||||
commandComponent.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, suggest));
|
||||
commandComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new Text(Messages.getString(this.permissionTemplate, player, Map.entry("%permission%", permission)))
|
||||
));
|
||||
commandComponent.addExtra(textComponent);
|
||||
return commandComponent;
|
||||
}
|
||||
}
|
||||
@@ -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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class PhysicsCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public PhysicsCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("physics").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.physics")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> {
|
||||
togglePhysics(player, player.getWorld());
|
||||
}
|
||||
case 1 -> {
|
||||
// TODO: Check each world for permission individually?
|
||||
if (args[0].equalsIgnoreCase("all") && !worldStorage.worldExists("all")) {
|
||||
worldStorage.getBuildWorlds().forEach(world -> world.getData().physics().set(true));
|
||||
Messages.sendMessage(player, "physics_activated_all");
|
||||
} else {
|
||||
togglePhysics(player, Bukkit.getWorld(args[0]));
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
Messages.sendMessage(player, "physics_usage");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void togglePhysics(Player player, @Nullable World world) {
|
||||
if (world == null) {
|
||||
Messages.sendMessage(player, "physics_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(world.getName());
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "physics_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
WorldData worldData = buildWorld.getData();
|
||||
if (!worldData.physics().get()) {
|
||||
worldData.physics().set(true);
|
||||
Messages.sendMessage(player, "physics_activated", Map.entry("%world%", buildWorld.getName()));
|
||||
} else {
|
||||
worldData.physics().set(false);
|
||||
Messages.sendMessage(player, "physics_deactivated", Map.entry("%world%", buildWorld.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsInventory;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SettingsCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public SettingsCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("settings").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.settings")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
new SettingsInventory(plugin).openInventory(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.world.modification.SetupInventory;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SetupCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public SetupCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("setup").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.setup")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
new SetupInventory(plugin).openInventory(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.profiles.objects.Profileable;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import java.util.Map;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SkullCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public SkullCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("skull").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.skull")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> {
|
||||
addSkull(player, "§b" + player.getName(), Profileable.of(player));
|
||||
Messages.sendMessage(player, "skull_player_received", Map.entry("%player%", player.getName()));
|
||||
}
|
||||
case 1 -> {
|
||||
String identifier = args[0];
|
||||
if (identifier.length() > 16) {
|
||||
addSkull(player, Messages.getString("custom_skull_item", player), Profileable.detect(identifier));
|
||||
Messages.sendMessage(player, "skull_custom_received");
|
||||
} else {
|
||||
addSkull(player, "§b" + identifier, Profileable.detect(identifier));
|
||||
Messages.sendMessage(player, "skull_player_received", Map.entry("%player%", identifier));
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
Messages.sendMessage(player, "skull_usage");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addSkull(Player player, String displayName, Profileable profileable) {
|
||||
player.getInventory().addItem(InventoryUtils.createSkull(displayName, profileable));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.SpawnManager;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SpawnCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final SpawnManager spawnManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public SpawnCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.spawnManager = plugin.getSpawnManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("spawn").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0 -> {
|
||||
if (!spawnManager.teleport(player)) {
|
||||
Messages.sendMessage(player, "spawn_unavailable");
|
||||
} else if (Config.Messages.spawnTeleportMessage) {
|
||||
Messages.sendMessage(player, "spawn_teleported");
|
||||
}
|
||||
}
|
||||
|
||||
case 1 -> {
|
||||
if (!player.hasPermission("buildsystem.spawn")) {
|
||||
Messages.sendMessage(player, "spawn_usage");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "set" -> {
|
||||
Location playerLocation = player.getLocation();
|
||||
World bukkitWorld = playerLocation.getWorld();
|
||||
if (bukkitWorld == null) {
|
||||
Messages.sendMessage(player, "spawn_world_not_imported");
|
||||
return true;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(bukkitWorld);
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "spawn_world_not_imported");
|
||||
return true;
|
||||
}
|
||||
|
||||
spawnManager.set(playerLocation, buildWorld.getName());
|
||||
Messages.sendMessage(player, "spawn_set",
|
||||
Map.entry("%x%", round(playerLocation.getX())),
|
||||
Map.entry("%y%", round(playerLocation.getY())),
|
||||
Map.entry("%z%", round(playerLocation.getZ())),
|
||||
Map.entry("%world%", playerLocation.getWorld().getName())
|
||||
);
|
||||
}
|
||||
case "remove" -> {
|
||||
spawnManager.remove();
|
||||
Messages.sendMessage(player, "spawn_remove");
|
||||
}
|
||||
default -> {
|
||||
Messages.sendMessage(player, "spawn_admin");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default -> {
|
||||
String key = player.hasPermission("buildsystem.spawn") ? "spawn_admin" : "spawn_usage";
|
||||
Messages.sendMessage(player, key);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String round(double value) {
|
||||
int scale = (int) Math.pow(10, 2);
|
||||
return String.valueOf((double) Math.round(value * scale) / scale);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.player.settings.SpeedInventory;
|
||||
import java.util.Map;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SpeedCommand implements CommandExecutor {
|
||||
|
||||
private static final float INVALID_SPEED = -1.0f;
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public SpeedCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("speed").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.speed")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
new SpeedInventory(plugin).openInventory(player);
|
||||
break;
|
||||
case 1:
|
||||
String speedString = args[0];
|
||||
float speed = switch (speedString) {
|
||||
case "1" -> 0.2f;
|
||||
case "2" -> 0.4f;
|
||||
case "3" -> 0.6f;
|
||||
case "4" -> 0.8f;
|
||||
case "5" -> 1.0f;
|
||||
default -> INVALID_SPEED;
|
||||
};
|
||||
|
||||
if (speed == INVALID_SPEED) {
|
||||
Messages.sendMessage(player, "speed_usage");
|
||||
return true;
|
||||
}
|
||||
|
||||
setSpeed(player, speed, speedString);
|
||||
break;
|
||||
default:
|
||||
Messages.sendMessage(player, "speed_usage");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setSpeed(Player player, float speed, String speedString) {
|
||||
if (player.isFlying()) {
|
||||
player.setFlySpeed(speed - 0.1f);
|
||||
Messages.sendMessage(player, "speed_set_flying", Map.entry("%speed%", speedString));
|
||||
} else {
|
||||
player.setWalkSpeed(speed);
|
||||
Messages.sendMessage(player, "speed_set_walking", Map.entry("%speed%", speedString));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.util.WorldPermissions;
|
||||
import de.eintosti.buildsystem.config.Config.World.Default.Time;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class TimeCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public TimeCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("day").setExecutor(this);
|
||||
plugin.getCommand("night").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
Messages.sendMessage(player, "day_unknown_world");
|
||||
return true;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(world);
|
||||
WorldPermissions permissions = WorldPermissionsImpl.of(buildWorld);
|
||||
|
||||
switch (label.toLowerCase(Locale.ROOT)) {
|
||||
case "day" -> {
|
||||
if (!permissions.canPerformCommand(player, "buildsystem.day")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0, 1 -> {
|
||||
world.setTime(Time.noon);
|
||||
Messages.sendMessage(player, "day_set", Map.entry("%world%", world.getName()));
|
||||
}
|
||||
default -> Messages.sendMessage(player, "day_usage");
|
||||
}
|
||||
}
|
||||
|
||||
case "night" -> {
|
||||
if (!permissions.canPerformCommand(player, "buildsystem.night")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 0, 1 -> {
|
||||
world.setTime(Time.night);
|
||||
Messages.sendMessage(player, "night_set", Map.entry("%world%", world.getName()));
|
||||
}
|
||||
default -> {
|
||||
Messages.sendMessage(player, "night_usage");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.world.util.WorldTeleporterImpl;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class TopCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public TopCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("top").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.top")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 0) {
|
||||
Messages.sendMessage(player, "top_usage");
|
||||
return true;
|
||||
}
|
||||
|
||||
sendToTop(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendToTop(Player player) {
|
||||
Location playerLocation = player.getLocation();
|
||||
Location blockLocation = player.getWorld()
|
||||
.getHighestBlockAt(playerLocation.getBlockX(), playerLocation.getBlockZ())
|
||||
.getLocation();
|
||||
|
||||
boolean failed = !WorldTeleporterImpl.isSafeLocation(blockLocation) || blockLocation.getBlock().getY() < playerLocation.getBlock().getY();
|
||||
if (failed) {
|
||||
Messages.sendMessage(player, "top_failed");
|
||||
return;
|
||||
}
|
||||
|
||||
PaperLib.teleportAsync(player, blockLocation.add(0.5, 1, 0.5))
|
||||
.whenComplete((completed, throwable) -> {
|
||||
if (!completed) {
|
||||
return;
|
||||
}
|
||||
XSound.ENTITY_ZOMBIE_INFECT.play(player);
|
||||
Messages.sendMessage(player, "top_teleported");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.AddBuilderSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.ArchiveSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.BackupsSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.BuildersSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.DeleteSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.EditSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.FolderSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.HelpSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.ImportAllSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.ImportSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.InfoSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.ItemSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.PrivateSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.PublicSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.RemoveBuilderSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.RemoveSpawnSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.RenameSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetCreatorSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetItemSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetPermissionSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetProjectSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetSpawnSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.SetStatusSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.TeleportSubCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.worlds.UnimportSubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.NavigatorInventory;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class WorldsCommand implements CommandExecutor {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public WorldsCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getCommand("worlds").setExecutor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
plugin.getLogger().warning(Messages.getString("sender_not_player", sender));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
if (!player.hasPermission("buildsystem.navigator")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
new NavigatorInventory(plugin).openInventory(player);
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldsTabCompleter.WorldsArgument argument = WorldsTabCompleter.WorldsArgument.matchArgument(args[0]);
|
||||
if (argument == null) {
|
||||
Messages.sendMessage(player, "worlds_unknown_command");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Most commands use the structure /worlds <argument> <world> <...> which is why we assume that args[1] is the world name
|
||||
// Make sure to change if this is not the case for any specific command
|
||||
String worldName = args.length >= 2 ? args[1] : player.getWorld().getName();
|
||||
|
||||
SubCommand subCommand = switch (argument) {
|
||||
case ARCHIVE -> new ArchiveSubCommand(plugin);
|
||||
case ADD_BUILDER -> new AddBuilderSubCommand(plugin, player.getWorld().getName());
|
||||
case BACKUP -> new BackupsSubCommand(plugin);
|
||||
case BUILDERS -> new BuildersSubCommand(plugin, worldName);
|
||||
case DELETE -> new DeleteSubCommand(plugin, worldName);
|
||||
case EDIT -> new EditSubCommand(plugin, worldName);
|
||||
case FOLDER -> new FolderSubCommand(plugin);
|
||||
case HELP -> new HelpSubCommand();
|
||||
case IMPORT_ALL -> new ImportAllSubCommand(plugin);
|
||||
case IMPORT -> new ImportSubCommand(plugin, worldName);
|
||||
case INFO -> new InfoSubCommand(plugin, worldName);
|
||||
case ITEM -> new ItemSubCommand();
|
||||
case PRIVATE -> new PrivateSubCommand(plugin);
|
||||
case PUBLIC -> new PublicSubCommand(plugin);
|
||||
case REMOVE_BUILDER -> new RemoveBuilderSubCommand(plugin, player.getWorld().getName());
|
||||
case REMOVE_SPAWN -> new RemoveSpawnSubCommand(plugin);
|
||||
case RENAME -> new RenameSubCommand(plugin, worldName);
|
||||
case SET_CREATOR -> new SetCreatorSubCommand(plugin, worldName);
|
||||
case SET_ITEM -> new SetItemSubCommand(plugin, worldName);
|
||||
case SET_PERMISSION -> new SetPermissionSubCommand(plugin, worldName);
|
||||
case SET_PROJECT -> new SetProjectSubCommand(plugin, worldName);
|
||||
case SET_SPAWN -> new SetSpawnSubCommand(plugin);
|
||||
case SET_STATUS -> new SetStatusSubCommand(plugin, worldName);
|
||||
case TP -> new TeleportSubCommand(plugin);
|
||||
case UNIMPORT -> new UnimportSubCommand(plugin, worldName);
|
||||
};
|
||||
subCommand.execute(player, args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.command.subcommand;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public interface Argument {
|
||||
|
||||
/**
|
||||
* The name of the command argument.
|
||||
*
|
||||
* @return The command argument name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* The permission required to run the command.
|
||||
*
|
||||
* @return The permission required to run the command
|
||||
*/
|
||||
@Nullable
|
||||
String getPermission();
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.command.subcommand;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface SubCommand {
|
||||
|
||||
void execute(Player player, String[] args);
|
||||
|
||||
Argument getArgument();
|
||||
|
||||
default boolean hasPermission(Player player) {
|
||||
String permission = getArgument().getPermission();
|
||||
return permission == null || player.hasPermission(permission);
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.util.WorldPermissions;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.world.builder.BuilderInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class AddBuilderSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
private final WorldPermissions permissions;
|
||||
|
||||
public AddBuilderSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
this.permissions = WorldPermissionsImpl.of(buildWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!permissions.canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_addbuilder_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 1 -> getAddBuilderInput(player, buildWorld, true);
|
||||
case 2 -> addBuilder(player, buildWorld, args[1], true);
|
||||
default -> Messages.sendMessage(player, "worlds_addbuilder_usage");
|
||||
}
|
||||
}
|
||||
|
||||
private void addBuilder(Player player, BuildWorld buildWorld, String builderName, boolean closeInventory) {
|
||||
Player builderPlayer = Bukkit.getPlayerExact(builderName);
|
||||
Builder builder;
|
||||
UUID builderId;
|
||||
|
||||
if (builderPlayer == null) {
|
||||
builderId = UUIDFetcher.getUUID(builderName);
|
||||
if (builderId == null) {
|
||||
Messages.sendMessage(player, "worlds_addbuilder_player_not_found");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
builder = Builder.of(builderId, builderName);
|
||||
} else {
|
||||
builder = Builder.of(builderPlayer);
|
||||
builderId = builderPlayer.getUniqueId();
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builderId.equals(player.getUniqueId()) && builders.isCreator(player)) {
|
||||
Messages.sendMessage(player, "worlds_addbuilder_already_creator");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (builders.isBuilder(builderId)) {
|
||||
Messages.sendMessage(player, "worlds_addbuilder_already_added");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
builders.addBuilder(builder);
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_addbuilder_added",
|
||||
Map.entry("%builder%", builderName)
|
||||
);
|
||||
|
||||
if (closeInventory) {
|
||||
player.closeInventory();
|
||||
} else {
|
||||
new BuilderInventory(plugin).openInventory(buildWorld, player);
|
||||
}
|
||||
}
|
||||
|
||||
public void getAddBuilderInput(Player player, BuildWorld buildWorld, boolean closeInventory) {
|
||||
new PlayerChatInput(plugin, player, "enter_player_name", input -> {
|
||||
String builderName = input.trim();
|
||||
addBuilder(player, buildWorld, builderName, closeInventory);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.ADD_BUILDER;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.ArchivedWorldsInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ArchiveSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public ArchiveSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
new ArchivedWorldsInventory(plugin, player).openInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.ARCHIVE;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.backup.BackupsInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BackupsSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public BackupsSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(player.getWorld().getName());
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_backup_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 1 -> {
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
new BackupsInventory(plugin).openBackupsInventory(player, buildWorld);
|
||||
}
|
||||
case 2 -> {
|
||||
if (args[1].equalsIgnoreCase("create")) {
|
||||
if (!player.hasPermission(getArgument().getPermission() + ".create")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
Entry<String, Object> worldNamePlaceholder = Map.entry("%world%", buildWorld.getName());
|
||||
plugin.getBackupService().backup(buildWorld,
|
||||
() -> Messages.sendMessage(player, "worlds_backup_created", worldNamePlaceholder),
|
||||
() -> Messages.sendMessage(player, "worlds_backup_failed", worldNamePlaceholder)
|
||||
);
|
||||
} else {
|
||||
Messages.sendMessage(player, "worlds_backup_usage");
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
Messages.sendMessage(player, "worlds_backup_usage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.BACKUP;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.builder.BuilderInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class BuildersSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public BuildersSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_builders_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_builders_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
new BuilderInventory(plugin).openInventory(buildWorld, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.BUILDERS;
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.config.Config.World;
|
||||
import de.eintosti.buildsystem.world.modification.DeleteInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class DeleteSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public DeleteSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_delete_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_delete_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
if (World.deletionBlacklist.contains(buildWorld.getName().toLowerCase())) {
|
||||
Messages.sendMessage(player, "worlds_delete_forbidden");
|
||||
return;
|
||||
}
|
||||
|
||||
new DeleteInventory(plugin).openInventory(player, buildWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.DELETE;
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.modification.EditInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class EditSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public EditSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_edit_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_edit_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld.isLoaded()) {
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
new EditInventory(plugin).openInventory(player, buildWorld);
|
||||
} else {
|
||||
XSound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR.play(player);
|
||||
player.sendTitle(" ", Messages.getString("world_not_loaded", player), 5, 70, 20);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.EDIT;
|
||||
}
|
||||
}
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.storage.FolderStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.display.Folder;
|
||||
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.world.WorldServiceImpl;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class FolderSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final WorldServiceImpl worldService;
|
||||
private final FolderStorage folderStorage;
|
||||
|
||||
public FolderSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.worldService = plugin.getWorldService();
|
||||
this.folderStorage = worldService.getFolderStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (args.length < 2) {
|
||||
Messages.sendMessage(player, "worlds_folder_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
String folderName = args[1];
|
||||
String operation = args.length > 2 ? args[2].toLowerCase(Locale.ROOT) : "";
|
||||
|
||||
Folder folder = this.folderStorage.getFolder(folderName);
|
||||
if (folder == null) {
|
||||
Messages.sendMessage(player, "worlds_folder_unknown_folder");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case "add":
|
||||
case "remove": {
|
||||
if (args.length != 4) {
|
||||
Messages.sendMessage(player, "worlds_folder_usage");
|
||||
return;
|
||||
}
|
||||
handleWorldFolderOperation(player, folder, operation, args[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
case "setpermission": {
|
||||
handlePermissionInput(player, folder);
|
||||
break;
|
||||
}
|
||||
|
||||
case "setproject": {
|
||||
handleProjectInput(player, folder);
|
||||
break;
|
||||
}
|
||||
|
||||
case "setitem": {
|
||||
handleIconChange(player, folder);
|
||||
break;
|
||||
}
|
||||
|
||||
case "delete": {
|
||||
handleDeletion(player, folder);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
Messages.sendMessage(player, "worlds_folder_usage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWorldFolderOperation(Player player, Folder folder, String operation, String worldName) {
|
||||
BuildWorld buildWorld = worldService.getWorldStorage().getBuildWorld(worldName);
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_folder_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
Entry<String, Object> folderPlaceholder = Map.entry("%folder%", folder.getName());
|
||||
Entry<String, Object> worldPlaceholder = Map.entry("%world%", buildWorld.getName());
|
||||
|
||||
switch (operation) {
|
||||
case "add":
|
||||
if (!player.hasPermission("buildsystem.folder.add")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (folder.containsWorld(buildWorld)) {
|
||||
Messages.sendMessage(player, "worlds_folder_world_already_in_folder", folderPlaceholder, worldPlaceholder);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld.isAssignedToFolder()) {
|
||||
Messages.sendMessage(player, "worlds_folder_world_already_in_another_folder", worldPlaceholder);
|
||||
return;
|
||||
}
|
||||
|
||||
if (folder.getCategory() != NavigatorCategory.of(buildWorld)) {
|
||||
Messages.sendMessage(player, "worlds_folder_world_category_mismatch",
|
||||
Map.entry("%folder_category%", folder.getCategory().name()),
|
||||
Map.entry("%world_category%", NavigatorCategory.of(buildWorld).name())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
folder.addWorld(buildWorld);
|
||||
Messages.sendMessage(player, "worlds_folder_world_added_to_folder", folderPlaceholder, worldPlaceholder);
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
if (!player.hasPermission("buildsystem.folder.remove")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!folder.containsWorld(buildWorld)) {
|
||||
Messages.sendMessage(player, "worlds_folder_world_not_in_folder", folderPlaceholder, worldPlaceholder);
|
||||
return;
|
||||
}
|
||||
|
||||
folder.removeWorld(buildWorld);
|
||||
Messages.sendMessage(player, "worlds_folder_world_removed_from_folder", folderPlaceholder, worldPlaceholder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePermissionInput(Player player, Folder folder) {
|
||||
if (!player.hasPermission("buildsystem.folder.setpermission")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
new PlayerChatInput(this.plugin, player, "enter_world_permission", input -> {
|
||||
folder.setPermission(input.trim());
|
||||
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_folder_permission_set",
|
||||
Map.entry("%folder%", folder.getName())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void handleProjectInput(Player player, Folder folder) {
|
||||
if (!player.hasPermission("buildsystem.folder.setproject")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
new PlayerChatInput(this.plugin, player, "enter_world_project", input -> {
|
||||
folder.setProject(input.trim());
|
||||
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_folder_project_set",
|
||||
Map.entry("%folder%", folder.getName())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIconChange(Player player, Folder folder) {
|
||||
if (!player.hasPermission("buildsystem.folder.setitem")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = player.getInventory().getItemInMainHand();
|
||||
if (itemStack.getType() == Material.AIR) {
|
||||
Messages.sendMessage(player, "worlds_setitem_hand_empty");
|
||||
return;
|
||||
}
|
||||
|
||||
folder.setIcon(XMaterial.matchXMaterial(itemStack));
|
||||
Messages.sendMessage(player, "worlds_folder_item_set",
|
||||
Map.entry("%folder%", folder.getName())
|
||||
);
|
||||
}
|
||||
|
||||
private void handleDeletion(Player player, Folder folder) {
|
||||
if (!player.hasPermission("buildsystem.folder.delete")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasWorlds = folder.getWorldCount() > 0;
|
||||
boolean hasSubFolders = this.folderStorage.getFolders().stream().anyMatch(f -> Objects.equals(f.getParent(), folder));
|
||||
if (hasWorlds || hasSubFolders) {
|
||||
Messages.sendMessage(player, "worlds_folder_not_empty",
|
||||
Map.entry("%folder%", folder.getName())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.folderStorage.removeFolder(folder);
|
||||
Messages.sendMessage(player, "worlds_folder_deleted",
|
||||
Map.entry("%folder%", folder.getName())
|
||||
);
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.FOLDER;
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.PagedCommand;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class HelpSubCommand extends PagedCommand implements SubCommand {
|
||||
|
||||
public HelpSubCommand() {
|
||||
super("worlds_help_title_with_page", "worlds_help_permission");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
sendMessage(player, 1);
|
||||
} else if (args.length == 2) {
|
||||
try {
|
||||
int page = Integer.parseInt(args[1]);
|
||||
sendMessage(player, page);
|
||||
} catch (NumberFormatException e) {
|
||||
Messages.sendMessage(player, "worlds_help_invalid_page");
|
||||
}
|
||||
} else {
|
||||
Messages.sendMessage(player, "worlds_help_usage");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<TextComponent> getCommands(Player player) {
|
||||
List<TextComponent> commands = Lists.newArrayList(
|
||||
createComponent(player, "/worlds help <page>", "worlds_help_help", "/worlds help", "-"),
|
||||
createComponent(player, "/worlds info", "worlds_help_info", "/worlds info", "buildsystem.info"),
|
||||
createComponent(player, "/worlds item", "worlds_help_item", "/worlds item", "buildsystem.navigator.item"),
|
||||
createComponent(player, "/worlds tp <world>", "worlds_help_tp", "/worlds tp ", "buildsystem.worldtp"),
|
||||
createComponent(player, "/worlds edit <world>", "worlds_help_edit", "/worlds edit ", "buildsystem.edit"),
|
||||
createComponent(player, "/worlds addBuilder <world>", "worlds_help_addbuilder", "/worlds addBuilder ", "buildsystem.addbuilder"),
|
||||
createComponent(player, "/worlds removeBuilder <world>", "worlds_help_removebuilder", "/worlds removeBuilder ", "buildsystem.removebuilder"),
|
||||
createComponent(player, "/worlds builders <world>", "worlds_help_builders", "/worlds builders ", "buildsystem.builders"),
|
||||
createComponent(player, "/worlds rename <world>", "worlds_help_rename", "/worlds rename ", "buildsystem.rename"),
|
||||
createComponent(player, "/worlds setItem <world>", "worlds_help_setitem", "/worlds setItem ", "buildsystem.setitem"),
|
||||
createComponent(player, "/worlds setCreator <world>", "worlds_help_setcreator", "/worlds setCreator ", "buildsystem.setcreator"),
|
||||
createComponent(player, "/worlds setProject <world>", "worlds_help_setproject", "/worlds setProject ", "buildsystem.setproject"),
|
||||
createComponent(player, "/worlds setPermission <world>", "worlds_help_setpermission", "/worlds setPermission ", "buildsystem.setpermission"),
|
||||
createComponent(player, "/worlds setStatus <world>", "worlds_help_setstatus", "/worlds setStatus ", "buildsystem.setstatus"),
|
||||
createComponent(player, "/worlds setSpawn", "worlds_help_setspawn", "/worlds setSpawn", "buildsystem.setspawn"),
|
||||
createComponent(player, "/worlds removeSpawn", "worlds_help_removespawn", "/worlds removeSpawn", "buildsystem.removespawn"),
|
||||
createComponent(player, "/worlds delete <world>", "worlds_help_delete", "/worlds delete ", "buildsystem.delete"),
|
||||
createComponent(player, "/worlds import <world>", "worlds_help_import", "/worlds import ", "buildsystem.import"),
|
||||
createComponent(player, "/worlds importAll", "worlds_help_importall", "/worlds importAll", "buildsystem.import.all"),
|
||||
createComponent(player, "/worlds unimport", "worlds_help_unimport", "/worlds unimport", "buildsystem.unimport")
|
||||
);
|
||||
commands.removeIf(textComponent -> textComponent.getText().isEmpty());
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.HELP;
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.api.world.creation.generator.Generator;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.ArgumentParser;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.world.WorldServiceImpl;
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ImportAllSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public ImportAllSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
Messages.sendMessage(player, "worlds_importall_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
WorldServiceImpl worldService = plugin.getWorldService();
|
||||
if (worldService.isImportingAllWorlds()) {
|
||||
Messages.sendMessage(player, "worlds_importall_already_started");
|
||||
return;
|
||||
}
|
||||
|
||||
File worldContainer = Bukkit.getWorldContainer();
|
||||
String[] directories = worldContainer.list((dir, name) -> {
|
||||
File worldFolder = new File(dir, name);
|
||||
if (!worldFolder.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new File(worldFolder, "level.dat").exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !worldService.getWorldStorage().worldExists(name);
|
||||
});
|
||||
|
||||
if (directories == null || directories.length == 0) {
|
||||
Messages.sendMessage(player, "worlds_importall_no_worlds");
|
||||
return;
|
||||
}
|
||||
|
||||
ArgumentParser parser = new ArgumentParser(args);
|
||||
Generator generator = Generator.VOID;
|
||||
Builder creator = null;
|
||||
|
||||
if (parser.isArgument("g")) {
|
||||
String generatorArg = parser.getValue("g");
|
||||
if (generatorArg == null) {
|
||||
Messages.sendMessage(player, "worlds_importall_usage");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
generator = Generator.valueOf(generatorArg.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (parser.isArgument("c")) {
|
||||
String creatorArg = parser.getValue("c");
|
||||
if (creatorArg == null) {
|
||||
Messages.sendMessage(player, "worlds_importall_usage");
|
||||
return;
|
||||
}
|
||||
UUID creatorId = UUIDFetcher.getUUID(creatorArg);
|
||||
if (creatorId == null) {
|
||||
Messages.sendMessage(player, "worlds_importall_player_not_found");
|
||||
return;
|
||||
}
|
||||
creator = Builder.of(creatorId, creatorArg);
|
||||
}
|
||||
|
||||
worldService.importWorlds(player, directories, generator, creator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.IMPORT_ALL;
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.api.world.creation.generator.Generator;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.ArgumentParser;
|
||||
import de.eintosti.buildsystem.util.StringCleaner;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.world.WorldServiceImpl;
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ImportSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final String worldName;
|
||||
|
||||
public ImportSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
Messages.sendMessage(player, "worlds_import_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
WorldServiceImpl worldService = plugin.getWorldService();
|
||||
if (worldService.getWorldStorage().worldExists(worldName)) {
|
||||
Messages.sendMessage(player, "worlds_import_world_is_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
File worldFolder = new File(Bukkit.getWorldContainer(), args[1]);
|
||||
File levelFile = new File(worldFolder, "level.dat");
|
||||
if (!worldFolder.isDirectory() || !levelFile.exists()) {
|
||||
Messages.sendMessage(player, "worlds_import_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
String invalidChar = StringCleaner.firstInvalidChar(worldName);
|
||||
if (invalidChar != null) {
|
||||
Messages.sendMessage(player, "worlds_import_invalid_character",
|
||||
Map.entry("%world%", worldName),
|
||||
Map.entry("%char%", invalidChar)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Builder creator = null;
|
||||
Generator generator = Generator.VOID;
|
||||
String generatorName = generator.name();
|
||||
BuildWorldType worldType = BuildWorldType.IMPORTED;
|
||||
|
||||
if (args.length != 2) {
|
||||
ArgumentParser parser = new ArgumentParser(args);
|
||||
|
||||
if (parser.isArgument("g")) {
|
||||
String generatorArg = parser.getValue("g");
|
||||
if (generatorArg == null) {
|
||||
Messages.sendMessage(player, "worlds_import_usage");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
generator = Generator.valueOf(generatorArg.toUpperCase(Locale.ROOT));
|
||||
generatorName = generator.name();
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
generator = Generator.CUSTOM;
|
||||
generatorName = generatorArg;
|
||||
}
|
||||
}
|
||||
|
||||
if (parser.isArgument("c")) {
|
||||
String creatorArg = parser.getValue("c");
|
||||
if (creatorArg == null) {
|
||||
Messages.sendMessage(player, "worlds_import_usage");
|
||||
return;
|
||||
}
|
||||
UUID creatorId = UUIDFetcher.getUUID(creatorArg);
|
||||
if (creatorId == null) {
|
||||
Messages.sendMessage(player, "worlds_import_player_not_found");
|
||||
return;
|
||||
}
|
||||
creator = Builder.of(creatorId, creatorArg);
|
||||
}
|
||||
|
||||
if (parser.isArgument("t")) {
|
||||
String worldTypeArg = parser.getValue("t");
|
||||
if (worldTypeArg == null) {
|
||||
Messages.sendMessage(player, "worlds_import_usage");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
worldType = BuildWorldType.valueOf(worldTypeArg.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Messages.sendMessage(player, "worlds_import_started",
|
||||
Map.entry("%world%", worldName)
|
||||
);
|
||||
if (worldService.importWorld(player, worldName, creator, worldType, generator, generatorName, true)) {
|
||||
Messages.sendMessage(player, "worlds_import_finished");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.IMPORT;
|
||||
}
|
||||
}
|
||||
+118
@@ -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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class InfoSubCommand implements SubCommand {
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public InfoSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_info_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_info_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Print information about the custom generator?
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
WorldData worldData = buildWorld.getData();
|
||||
Messages.sendMessage(player, "world_info",
|
||||
Map.entry("%world%", buildWorld.getName()),
|
||||
Map.entry("%uuid%", buildWorld.getUniqueId().toString()),
|
||||
Map.entry("%creator%", getCreator(builders)),
|
||||
Map.entry("%item%", worldData.material().get().name()),
|
||||
Map.entry("%type%", Messages.getString(Messages.getMessageKey(buildWorld.getType()), player)),
|
||||
Map.entry("%private%", worldData.privateWorld().get()),
|
||||
Map.entry("%builders_enabled%", worldData.buildersEnabled().get()),
|
||||
Map.entry("%builders%", builders.asPlaceholder(player)),
|
||||
Map.entry("%block_breaking%", worldData.blockBreaking().get()),
|
||||
Map.entry("%block_placement%", worldData.blockPlacement().get()),
|
||||
Map.entry("%status%", Messages.getString(Messages.getMessageKey(worldData.status().get()), player)),
|
||||
Map.entry("%project%", worldData.project().get()),
|
||||
Map.entry("%permission%", worldData.permission().get()),
|
||||
Map.entry("%time%", buildWorld.getWorldTime()),
|
||||
Map.entry("%creation%", Messages.formatDate(buildWorld.getCreation())),
|
||||
Map.entry("%physics%", worldData.physics().get()),
|
||||
Map.entry("%explosions%", worldData.explosions().get()),
|
||||
Map.entry("%mobai%", worldData.mobAi().get()),
|
||||
Map.entry("%custom_spawn%", getCustomSpawn(buildWorld)),
|
||||
Map.entry("%lastedited%", Messages.formatDate(worldData.lastEdited().get())),
|
||||
Map.entry("%lastloaded%", Messages.formatDate(worldData.lastLoaded().get())),
|
||||
Map.entry("%lastunloaded%", Messages.formatDate(worldData.lastUnloaded().get()))
|
||||
);
|
||||
}
|
||||
|
||||
private String getCreator(Builders builders) {
|
||||
Builder creator = builders.getCreator();
|
||||
if (creator == null) {
|
||||
return "-";
|
||||
}
|
||||
return creator.getName();
|
||||
}
|
||||
|
||||
private String getCustomSpawn(BuildWorld buildWorld) {
|
||||
WorldData worldData = buildWorld.getData();
|
||||
Location spawn = worldData.getCustomSpawnLocation();
|
||||
if (spawn == null) {
|
||||
return "-";
|
||||
}
|
||||
return "XYZ: " + round(spawn.getX()) + " / " + round(spawn.getY()) + " / " + round(spawn.getZ());
|
||||
}
|
||||
|
||||
private double round(double value) {
|
||||
int scale = (int) Math.pow(10, 2);
|
||||
return (double) Math.round(value * scale) / scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.INFO;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ItemSubCommand implements SubCommand {
|
||||
|
||||
public ItemSubCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
player.getInventory().addItem(InventoryUtils.createNavigatorItem(player));
|
||||
Messages.sendMessage(player, "worlds_item_receive");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.ITEM;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.PrivateWorldsInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PrivateSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public PrivateSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
new PrivateWorldsInventory(plugin, player).openInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.PRIVATE;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.PublicWorldsInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PublicSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public PublicSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
new PublicWorldsInventory(plugin, player).openInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.PUBLIC;
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.util.WorldPermissions;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class RemoveBuilderSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
private final WorldPermissions permissions;
|
||||
|
||||
public RemoveBuilderSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
this.permissions = WorldPermissionsImpl.of(buildWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!permissions.canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_removebuilder_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 1 -> getRemoveBuilderInput(player, buildWorld);
|
||||
case 2 -> removeBuilder(player, buildWorld, args[1]);
|
||||
default -> Messages.sendMessage(player, "worlds_removebuilder_usage");
|
||||
}
|
||||
}
|
||||
|
||||
private void removeBuilder(Player player, BuildWorld buildWorld, String builderName) {
|
||||
Player builderPlayer = Bukkit.getPlayerExact(builderName);
|
||||
UUID builderId;
|
||||
|
||||
if (builderPlayer == null) {
|
||||
builderId = UUIDFetcher.getUUID(builderName);
|
||||
if (builderId == null) {
|
||||
Messages.sendMessage(player, "worlds_removebuilder_player_not_found");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
builderId = builderPlayer.getUniqueId();
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builderId.equals(player.getUniqueId()) && builders.isCreator(player)) {
|
||||
Messages.sendMessage(player, "worlds_removebuilder_not_yourself");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!builders.isBuilder(builderId)) {
|
||||
Messages.sendMessage(player, "worlds_removebuilder_not_builder");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
builders.removeBuilder(builderId);
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_removebuilder_removed", Map.entry("%builder%", builderName));
|
||||
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
private void getRemoveBuilderInput(Player player, BuildWorld buildWorld) {
|
||||
new PlayerChatInput(plugin, player, "enter_player_name", input -> {
|
||||
String builderName = input.trim();
|
||||
removeBuilder(player, buildWorld, builderName);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.REMOVE_BUILDER;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class RemoveSpawnSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public RemoveSpawnSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(player.getWorld());
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_removespawn_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
buildWorld.getData().customSpawn().set("");
|
||||
Messages.sendMessage(player, "worlds_removespawn_world_spawn_removed",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.REMOVE_SPAWN;
|
||||
}
|
||||
}
|
||||
+74
@@ -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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class RenameSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public RenameSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_rename_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_rename_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
new PlayerChatInput(plugin, player, "enter_world_name", input -> {
|
||||
player.closeInventory();
|
||||
plugin.getWorldService().renameWorld(player, buildWorld, input.trim());
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.RENAME;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class SetCreatorSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public SetCreatorSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_setcreator_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setcreator_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
new PlayerChatInput(plugin, player, "enter_world_creator", input -> {
|
||||
String creatorName = input.trim();
|
||||
Builder creator = null;
|
||||
if (!creatorName.equalsIgnoreCase("-")) {
|
||||
creator = Builder.of(UUIDFetcher.getUUID(creatorName), creatorName);
|
||||
}
|
||||
buildWorld.getBuilders().setCreator(creator);
|
||||
|
||||
plugin.getPlayerService().forceUpdateSidebar(buildWorld);
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_setcreator_set",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
player.closeInventory();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_CREATOR;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class SetItemSubCommand implements SubCommand {
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public SetItemSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_setitem_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setitem_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = player.getInventory().getItemInMainHand();
|
||||
if (itemStack.getType() == Material.AIR) {
|
||||
Messages.sendMessage(player, "worlds_setitem_hand_empty");
|
||||
return;
|
||||
}
|
||||
|
||||
buildWorld.getData().material().set(XMaterial.matchXMaterial(itemStack));
|
||||
Messages.sendMessage(player, "worlds_setitem_set",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_ITEM;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.world.modification.EditInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class SetPermissionSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public SetPermissionSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_setpermission_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setpermission_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
getPermissionInput(player, buildWorld, true);
|
||||
}
|
||||
|
||||
public void getPermissionInput(Player player, BuildWorld buildWorld, boolean closeInventory) {
|
||||
new PlayerChatInput(plugin, player, "enter_world_permission", input -> {
|
||||
buildWorld.getData().permission().set(input.trim());
|
||||
plugin.getPlayerService().forceUpdateSidebar(buildWorld);
|
||||
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_setpermission_set",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
|
||||
if (closeInventory) {
|
||||
player.closeInventory();
|
||||
} else {
|
||||
new EditInventory(plugin).openInventory(player, buildWorld);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_PERMISSION;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.util.PlayerChatInput;
|
||||
import de.eintosti.buildsystem.world.modification.EditInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class SetProjectSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public SetProjectSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_setproject_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setproject_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
getProjectInput(player, buildWorld, true);
|
||||
}
|
||||
|
||||
public void getProjectInput(Player player, BuildWorld buildWorld, boolean closeInventory) {
|
||||
new PlayerChatInput(plugin, player, "enter_world_project", input -> {
|
||||
buildWorld.getData().project().set(input.trim());
|
||||
plugin.getPlayerService().forceUpdateSidebar(buildWorld);
|
||||
|
||||
XSound.ENTITY_PLAYER_LEVELUP.play(player);
|
||||
Messages.sendMessage(player, "worlds_setproject_set",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
|
||||
if (closeInventory) {
|
||||
player.closeInventory();
|
||||
} else {
|
||||
new EditInventory(plugin).openInventory(player, buildWorld);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_PROJECT;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SetSpawnSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public SetSpawnSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(player.getWorld());
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setspawn_world_not_imported");
|
||||
return;
|
||||
}
|
||||
|
||||
Location playerLocation = player.getLocation();
|
||||
buildWorld.getData().customSpawn().set("%s;%s;%s;%s;%s".formatted(
|
||||
playerLocation.getX(), playerLocation.getY(), playerLocation.getZ(), playerLocation.getYaw(), playerLocation.getPitch()
|
||||
));
|
||||
Messages.sendMessage(player, "worlds_setspawn_world_spawn_set",
|
||||
Map.entry("%world%", buildWorld.getName())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_SPAWN;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.data.StatusInventory;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class SetStatusSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public SetStatusSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_setstatus_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_setstatus_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
new StatusInventory(plugin).openInventory(player, buildWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.SET_STATUS;
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class TeleportSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public TeleportSubCommand(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!hasPermission(player)) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length != 2) {
|
||||
Messages.sendMessage(player, "worlds_tp_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(args[1]);
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_tp_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
World bukkitWorld = Bukkit.getServer().getWorld(args[1]);
|
||||
if (buildWorld.isLoaded() && bukkitWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_tp_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buildWorld.getPermissions().canEnter(player)) {
|
||||
Messages.sendMessage(player, "worlds_tp_entry_forbidden");
|
||||
return;
|
||||
}
|
||||
|
||||
buildWorld.getTeleporter().teleport(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.TP;
|
||||
}
|
||||
}
|
||||
+71
@@ -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.command.subcommand.worlds;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.command.subcommand.SubCommand;
|
||||
import de.eintosti.buildsystem.command.tabcomplete.WorldsTabCompleter.WorldsArgument;
|
||||
import de.eintosti.buildsystem.world.util.WorldPermissionsImpl;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class UnimportSubCommand implements SubCommand {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
@Nullable
|
||||
private final BuildWorld buildWorld;
|
||||
|
||||
public UnimportSubCommand(BuildSystemPlugin plugin, String worldName) {
|
||||
this.plugin = plugin;
|
||||
this.buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, String[] args) {
|
||||
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, getArgument().getPermission())) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
Messages.sendMessage(player, "worlds_unimport_usage");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld == null) {
|
||||
Messages.sendMessage(player, "worlds_unimport_unknown_world");
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getWorldService()
|
||||
.unimportWorld(buildWorld, true)
|
||||
.thenRun(() -> Messages.sendMessage(player, "worlds_unimport_finished", Map.entry("%world%", buildWorld.getName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Argument getArgument() {
|
||||
return WorldsArgument.UNIMPORT;
|
||||
}
|
||||
}
|
||||
+31
@@ -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.command.tabcomplete;
|
||||
|
||||
import java.util.List;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
abstract class ArgumentSorter {
|
||||
|
||||
public void addArgument(String input, String argument, List<String> arrayList) {
|
||||
if (input.isEmpty() || argument.toLowerCase().startsWith(input.toLowerCase())) {
|
||||
arrayList.add(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
public BuildTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("build").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("buildsystem.build")) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
if (args.length == 1 && !player.hasPermission("buildsystem.build.other")) {
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> addArgument(args[0], pl.getName(), arrayList));
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+45
@@ -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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class ConfigTabCompleter implements TabCompleter {
|
||||
|
||||
public ConfigTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("config").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
|
||||
if (sender.hasPermission("buildsystem.config")) {
|
||||
arrayList.add("reload");
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class EmptyTabCompleter implements TabCompleter {
|
||||
|
||||
public EmptyTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("back").setTabCompleter(this);
|
||||
plugin.getCommand("blocks").setTabCompleter(this);
|
||||
plugin.getCommand("buildsystem").setTabCompleter(this);
|
||||
plugin.getCommand("settings").setTabCompleter(this);
|
||||
plugin.getCommand("setup").setTabCompleter(this);
|
||||
plugin.getCommand("top").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Contract("_, _, _, _ -> new")
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
+68
@@ -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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class GamemodeTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
public GamemodeTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("gamemode").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
Arrays.stream(GameMode.values())
|
||||
.map(gameMode -> gameMode.name().toLowerCase(Locale.ROOT))
|
||||
.filter(gameModeName -> player.hasPermission("buildsystem.gamemode.%s".formatted(gameModeName)))
|
||||
.forEach(gameModeName -> addArgument(args[0], gameModeName, arrayList));
|
||||
} else if (args.length == 2) {
|
||||
String gameModeName = switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "survival", "s", "0" -> GameMode.SURVIVAL.name().toLowerCase(Locale.ROOT);
|
||||
case "creative", "c", "1" -> GameMode.CREATIVE.name().toLowerCase(Locale.ROOT);
|
||||
case "adventure", "a", "2" -> GameMode.ADVENTURE.name().toLowerCase(Locale.ROOT);
|
||||
case "spectator", "sp", "3" -> GameMode.SPECTATOR.name().toLowerCase(Locale.ROOT);
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if (gameModeName != null && player.hasPermission("buildsystem.gamemode.%s.other".formatted(gameModeName))) {
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> addArgument(args[1], pl.getName(), arrayList));
|
||||
}
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PhysicsTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
private final WorldStorage worldStorage;
|
||||
|
||||
public PhysicsTabCompleter(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("physics").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
worldStorage.getBuildWorlds().stream()
|
||||
.filter(world -> world.getPermissions().canPerformCommand(player, "buildsystem.physics"))
|
||||
.forEach(world -> addArgument(args[0], world.getName(), arrayList));
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SpawnTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
public SpawnTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("spawn").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
if (player.hasPermission("buildsystem.spawn")) {
|
||||
for (Argument argument : Argument.values()) {
|
||||
String argumentName = argument.name();
|
||||
addArgument(args[0], argumentName, arrayList);
|
||||
}
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
private enum Argument {
|
||||
set, remove
|
||||
}
|
||||
}
|
||||
+43
@@ -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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SpeedTabCompleter implements TabCompleter {
|
||||
|
||||
public SpeedTabCompleter(BuildSystemPlugin plugin) {
|
||||
plugin.getCommand("speed").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
arrayList.add(String.valueOf(i));
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+61
@@ -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.command.tabcomplete;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class TimeTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
private final WorldStorage worldStorage;
|
||||
|
||||
public TimeTabCompleter(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getCommand("day").setTabCompleter(this);
|
||||
plugin.getCommand("night").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
String labelLowerCase = label.toLowerCase(Locale.ROOT);
|
||||
switch (labelLowerCase) {
|
||||
case "day":
|
||||
case "night":
|
||||
worldStorage.getBuildWorlds().stream()
|
||||
.filter(world -> world.getPermissions().canPerformCommand(player, "buildsystem." + labelLowerCase))
|
||||
.forEach(world -> addArgument(args[0], world.getName(), arrayList));
|
||||
break;
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* 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.command.tabcomplete;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.storage.FolderStorage;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.WorldService;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.creation.generator.Generator;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
|
||||
import de.eintosti.buildsystem.api.world.display.Displayable;
|
||||
import de.eintosti.buildsystem.api.world.display.Folder;
|
||||
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
|
||||
import de.eintosti.buildsystem.command.subcommand.Argument;
|
||||
import de.eintosti.buildsystem.util.StringCleaner;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class WorldsTabCompleter extends ArgumentSorter implements TabCompleter {
|
||||
|
||||
private final WorldStorage worldStorage;
|
||||
private final FolderStorage folderStorage;
|
||||
|
||||
public WorldsTabCompleter(BuildSystemPlugin plugin) {
|
||||
WorldService worldService = plugin.getWorldService();
|
||||
this.worldStorage = worldService.getWorldStorage();
|
||||
this.folderStorage = worldService.getFolderStorage();
|
||||
plugin.getCommand("worlds").setTabCompleter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ArrayList<String> arrayList = new ArrayList<>();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
switch (args.length) {
|
||||
case 1: {
|
||||
for (WorldsArgument argument : WorldsArgument.values()) {
|
||||
String command = argument.getName();
|
||||
String permission = argument.getPermission();
|
||||
if (player.hasPermission(permission)) {
|
||||
addArgument(args[0], command, arrayList);
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "builders":
|
||||
case "edit":
|
||||
case "info":
|
||||
case "rename":
|
||||
case "setcreator":
|
||||
case "setitem":
|
||||
case "setpermission":
|
||||
case "setproject":
|
||||
case "setstatus":
|
||||
case "tp":
|
||||
case "unimport": {
|
||||
worldStorage.getBuildWorlds().stream()
|
||||
.filter(world -> {
|
||||
String permission = world.getData().permission().get();
|
||||
return player.hasPermission(permission) || permission.equalsIgnoreCase("-");
|
||||
})
|
||||
.filter(world -> world.getPermissions().canPerformCommand(player, "buildsystem." + args[0].toLowerCase(Locale.ROOT)))
|
||||
.forEach(world -> addArgument(args[1], world.getName(), arrayList));
|
||||
break;
|
||||
}
|
||||
|
||||
case "backup": {
|
||||
if (player.hasPermission(WorldsArgument.BACKUP.getPermission() + ".create")) {
|
||||
addArgument(args[1], "create", arrayList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "delete": {
|
||||
worldStorage.getBuildWorlds().stream()
|
||||
.filter(world -> world.getPermissions().canPerformCommand(player, "buildsystem." + args[0].toLowerCase(Locale.ROOT)))
|
||||
.forEach(world -> addArgument(args[1], world.getName(), arrayList));
|
||||
break;
|
||||
}
|
||||
|
||||
case "addbuilder": {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld().getName());
|
||||
if (buildWorld == null) {
|
||||
break;
|
||||
}
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(pl -> !builders.isBuilder(pl) && !builders.isCreator(pl))
|
||||
.forEach(pl -> addArgument(args[1], pl.getName(), arrayList));
|
||||
break;
|
||||
}
|
||||
|
||||
case "removebuilder": {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld().getName());
|
||||
if (buildWorld == null) {
|
||||
break;
|
||||
}
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builders.isCreator(player)) {
|
||||
builders.getBuilderNames().forEach(builderName -> addArgument(args[1], builderName, arrayList));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "import": {
|
||||
String[] directories = Bukkit.getWorldContainer().list((dir, name) -> {
|
||||
if (StringCleaner.hasInvalidNameCharacters(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File worldFolder = new File(dir, name);
|
||||
if (!worldFolder.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new File(worldFolder, "level.dat").exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !worldStorage.worldExists(name);
|
||||
});
|
||||
|
||||
if (directories == null || directories.length == 0) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
for (String projectName : directories) {
|
||||
addArgument(args[1], projectName, arrayList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "folder": {
|
||||
folderStorage.getFolders().stream()
|
||||
.map(Displayable::getName)
|
||||
.forEach(folderName -> addArgument(args[1], folderName, arrayList));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
default:
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
case "import": {
|
||||
Map<String, List<String>> arguments = Map.of(
|
||||
"-g", Arrays.stream(Generator.values()).filter(generator -> generator != Generator.CUSTOM).map(Enum::name).toList(),
|
||||
"-c", List.of(),
|
||||
"-t", Arrays.stream(BuildWorldType.values()).map(Enum::name).toList()
|
||||
);
|
||||
|
||||
if (args.length % 2 == 1) {
|
||||
arguments.keySet().stream()
|
||||
.filter(key -> !Lists.newArrayList(args).contains(key))
|
||||
.forEach(argument -> addArgument(args[args.length - 1], argument, arrayList));
|
||||
} else {
|
||||
List<String> values = arguments.get(args[args.length - 2]);
|
||||
if (values != null) {
|
||||
for (String argument : values) {
|
||||
addArgument(args[args.length - 1], argument, arrayList);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "folder": {
|
||||
switch (args.length) {
|
||||
case 3:
|
||||
Map<String, String> subCommands = Map.of(
|
||||
"add", "buildsystem.folder.add",
|
||||
"remove", "buildsystem.folder.remove",
|
||||
"delete", "buildsystem.folder.delete",
|
||||
"setPermission", "buildsystem.folder.setpermission",
|
||||
"setProject", "buildsystem.folder.setproject",
|
||||
"setItem", "buildsystem.folder.setitem"
|
||||
);
|
||||
subCommands.entrySet().stream()
|
||||
.filter(entry -> player.hasPermission(entry.getKey()))
|
||||
.forEach(entry -> addArgument(args[2], entry.getKey(), arrayList));
|
||||
break;
|
||||
case 4:
|
||||
if (!args[2].equalsIgnoreCase("add") && !args[2].equalsIgnoreCase("remove")) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
Folder folder = folderStorage.getFolder(args[1]);
|
||||
if (folder == null) {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
worldStorage.getBuildWorlds().stream()
|
||||
.filter(buildWorld -> NavigatorCategory.of(buildWorld) == folder.getCategory())
|
||||
.filter(buildWorld -> {
|
||||
if (args[2].equalsIgnoreCase("add")) {
|
||||
return !buildWorld.isAssignedToFolder();
|
||||
} else if (args[2].equalsIgnoreCase("remove")) {
|
||||
return folder.containsWorld(buildWorld);
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.forEach(world -> addArgument(args[3], world.getName(), arrayList));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
}
|
||||
|
||||
@NullMarked
|
||||
public enum WorldsArgument implements Argument {
|
||||
ARCHIVE("archive", "buildsystem.navigator"),
|
||||
ADD_BUILDER("addBuilder", "buildsystem.addbuilder"),
|
||||
BACKUP("backup", "buildsystem.backup"),
|
||||
BUILDERS("builders", "buildsystem.builders"),
|
||||
DELETE("delete", "buildsystem.delete"),
|
||||
EDIT("edit", "buildsystem.edit"),
|
||||
FOLDER("folder", "buildsystem.folder"),
|
||||
HELP("help", "buildsystem.help.worlds"),
|
||||
IMPORT("import", "buildsystem.import"),
|
||||
IMPORT_ALL("importAll", "buildsystem.import.all"),
|
||||
INFO("info", "buildsystem.info"),
|
||||
ITEM("item", "buildsystem.navigator.item"),
|
||||
PRIVATE("private", "buildsystem.navigator"),
|
||||
PUBLIC("public", "buildsystem.navigator"),
|
||||
REMOVE_BUILDER("removeBuilder", "buildsystem.removebuilder"),
|
||||
RENAME("rename", "buildsystem.rename"),
|
||||
SET_CREATOR("setCreator", "buildsystem.setcreator"),
|
||||
SET_ITEM("setItem", "buildsystem.setitem"),
|
||||
SET_PERMISSION("setPermission", "buildsystem.setpermission"),
|
||||
SET_PROJECT("setProject", "buildsystem.setproject"),
|
||||
SET_STATUS("setStatus", "buildsystem.setstatus"),
|
||||
SET_SPAWN("setSpawn", "buildsystem.setspawn"),
|
||||
REMOVE_SPAWN("removeSpawn", "buildsystem.removespawn"),
|
||||
TP("tp", "buildsystem.worldtp"),
|
||||
UNIMPORT("unimport", "buildsystem.unimport");
|
||||
|
||||
private final String command;
|
||||
private final String permission;
|
||||
|
||||
WorldsArgument(String command, String permission) {
|
||||
this.command = command;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static WorldsArgument matchArgument(String input) {
|
||||
return Arrays.stream(values())
|
||||
.filter(argument -> argument.getName().equalsIgnoreCase(input))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.backup.BackupStorage;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Archive;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.BuildMode;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Builder;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.DisabledPhysics;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Navigator;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.SaveFromDeath;
|
||||
import de.eintosti.buildsystem.config.Config.World.Backup;
|
||||
import de.eintosti.buildsystem.config.Config.World.Backup.AutoBackup;
|
||||
import de.eintosti.buildsystem.config.Config.World.Default;
|
||||
import de.eintosti.buildsystem.config.Config.World.Default.Permission;
|
||||
import de.eintosti.buildsystem.config.Config.World.Default.Settings.BuildersEnabled;
|
||||
import de.eintosti.buildsystem.config.Config.World.Default.Time;
|
||||
import de.eintosti.buildsystem.config.Config.World.Limits;
|
||||
import de.eintosti.buildsystem.config.Config.World.Unload;
|
||||
import de.eintosti.buildsystem.config.migration.ConfigMigrationManager;
|
||||
import de.eintosti.buildsystem.world.backup.storage.LocalBackupStorage;
|
||||
import de.eintosti.buildsystem.world.backup.storage.S3BackupStorage;
|
||||
import de.eintosti.buildsystem.world.backup.storage.SftpBackupStorage;
|
||||
import de.eintosti.buildsystem.world.modification.GameRuleEntry;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Manages the plugin's configuration, loading and providing access to various settings.
|
||||
*/
|
||||
@NullMarked
|
||||
public class Config {
|
||||
|
||||
private static final BuildSystemPlugin PLUGIN = BuildSystemPlugin.get();
|
||||
private static final FileConfiguration CONFIG = PLUGIN.getConfig();
|
||||
|
||||
/**
|
||||
* Gets the plugin's configuration.
|
||||
*
|
||||
* @return The plugin's configuration
|
||||
*/
|
||||
public static FileConfiguration getConfig() {
|
||||
return CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current version of the plugin's configuration.
|
||||
*
|
||||
* @return The version number of the configuration
|
||||
* @see ConfigMigrationManager#LATEST_VERSION
|
||||
*/
|
||||
public static int getVersion() {
|
||||
return CONFIG.getInt("version", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the plugin's configuration.
|
||||
*
|
||||
* @param version The version number to set
|
||||
*/
|
||||
public static void setVersion(int version) {
|
||||
CONFIG.set("version", version);
|
||||
CONFIG.setComments("version", List.of("Internal, do not change manually!"));
|
||||
PLUGIN.saveConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores messages related configurations.
|
||||
*/
|
||||
public static class Messages {
|
||||
|
||||
/**
|
||||
* Whether a message should be sent to the player when teleporting to a world's spawn.
|
||||
*/
|
||||
public static boolean spawnTeleportMessage = false;
|
||||
/**
|
||||
* Whether join and quit messages should be enabled.
|
||||
*/
|
||||
public static boolean joinQuitMessages = true;
|
||||
/**
|
||||
* The date format used for various date displays.
|
||||
*/
|
||||
public static String dateFormat = "dd/MM/yyyy";
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores general settings for the plugin.
|
||||
*/
|
||||
public static class Settings {
|
||||
|
||||
/**
|
||||
* Whether the update checker should be enabled.
|
||||
*/
|
||||
public static boolean updateChecker = true;
|
||||
/**
|
||||
* Whether the scoreboard should be enabled.
|
||||
*/
|
||||
public static boolean scoreboard = true;
|
||||
|
||||
/**
|
||||
* Stores archive-related settings.
|
||||
*/
|
||||
public static class Archive {
|
||||
|
||||
/**
|
||||
* Whether players should be vanished when entering an archived world.
|
||||
*/
|
||||
public static boolean vanish = true;
|
||||
/**
|
||||
* Whether the gamemode should be changed when entering an archived world.
|
||||
*/
|
||||
public static boolean changeGamemode = true;
|
||||
/**
|
||||
* The gamemode players are set to when entering an archived world.
|
||||
*/
|
||||
public static GameMode worldGameMode = GameMode.ADVENTURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores settings related to worlds with disabled physics.
|
||||
*/
|
||||
public static class DisabledPhysics {
|
||||
|
||||
/**
|
||||
* Whether connections should be prevented in worlds with disabled physics.
|
||||
*/
|
||||
public static boolean preventConnections = true;
|
||||
/**
|
||||
* Whether fluid flow should be prevented in worlds with disabled physics.
|
||||
*/
|
||||
public static boolean preventFluidFlow = true;
|
||||
/**
|
||||
* Whether falling blocks should be prevented in worlds with disabled physics.
|
||||
*/
|
||||
public static boolean preventFallingBlocks = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores settings related to saving players from death.
|
||||
*/
|
||||
public static class SaveFromDeath {
|
||||
|
||||
/**
|
||||
* Whether saving players from death should be enabled.
|
||||
*/
|
||||
public static boolean enabled = true;
|
||||
/**
|
||||
* Whether players should be teleported to the map spawn after being saved from death.
|
||||
*/
|
||||
public static boolean teleportToMapSpawn = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores build mode related settings.
|
||||
*/
|
||||
public static class BuildMode {
|
||||
|
||||
/**
|
||||
* Whether items should be dropped when a player dies in build mode.
|
||||
*/
|
||||
public static boolean dropItems = true;
|
||||
/**
|
||||
* Whether players can move items in their inventory in build mode.
|
||||
*/
|
||||
public static boolean moveItems = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores builder-related settings.
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* Whether WorldEdit usage should be blocked for non-builders.
|
||||
*/
|
||||
public static boolean blockWorldEditNonBuilder = true;
|
||||
/**
|
||||
* The {@link XMaterial} of the WorldEdit wand.
|
||||
*/
|
||||
public static XMaterial worldEditWand = XMaterial.WOODEN_AXE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores navigator-related settings.
|
||||
*/
|
||||
public static class Navigator {
|
||||
|
||||
/**
|
||||
* The {@link XMaterial} of the navigator item.
|
||||
*/
|
||||
public static XMaterial item = XMaterial.CLOCK;
|
||||
/**
|
||||
* Whether the navigator item should be given to players on join.
|
||||
*/
|
||||
public static boolean giveItemOnJoin = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores world-related configurations.
|
||||
*/
|
||||
public static class World {
|
||||
|
||||
/**
|
||||
* Whether the weather should be locked in worlds.
|
||||
*/
|
||||
public static boolean lockWeather = true;
|
||||
/**
|
||||
* A regex string of invalid characters for world names.
|
||||
*/
|
||||
public static String invalidCharacters = "^\b$";
|
||||
/**
|
||||
* The delay in seconds for the /build import all command.
|
||||
*/
|
||||
public static int importAllDelay = 30;
|
||||
/**
|
||||
* A blacklist of worlds that cannot be deleted. This is used to prevent deletion of important worlds.
|
||||
*/
|
||||
public static Set<String> deletionBlacklist = Set.of("world", "world_nether", "worth_the_end");
|
||||
;
|
||||
|
||||
/**
|
||||
* Stores default world settings.
|
||||
*/
|
||||
public static class Default {
|
||||
|
||||
/**
|
||||
* The default world border size.
|
||||
*/
|
||||
public static int worldBoarderSize = 6000000;
|
||||
/**
|
||||
* The default difficulty for new worlds.
|
||||
*/
|
||||
public static Difficulty difficulty = Difficulty.PEACEFUL;
|
||||
/**
|
||||
* Default game rules for new worlds.
|
||||
*/
|
||||
public static List<GameRuleEntry<?>> gameRules = List.of(
|
||||
new GameRuleEntry<>(GameRule.DO_DAYLIGHT_CYCLE, false),
|
||||
new GameRuleEntry<>(GameRule.DO_MOB_SPAWNING, false),
|
||||
new GameRuleEntry<>(GameRule.DO_FIRE_TICK, false)
|
||||
);
|
||||
|
||||
/**
|
||||
* Stores permission-related settings for default worlds.
|
||||
*/
|
||||
public static class Permission {
|
||||
|
||||
/**
|
||||
* The permission required to access public worlds by default.
|
||||
*/
|
||||
public static String publicPermission = "-";
|
||||
/**
|
||||
* The permission required to access private worlds by default. The `%world%` placeholder will be replaced with the world name.
|
||||
*/
|
||||
public static String privatePermission = "worlds.%world%";
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores time-related settings for default worlds.
|
||||
*/
|
||||
public static class Time {
|
||||
|
||||
/**
|
||||
* The time of sunrise in ticks.
|
||||
*/
|
||||
public static int sunrise = 0;
|
||||
/**
|
||||
* The time of noon in ticks.
|
||||
*/
|
||||
public static int noon = 6000;
|
||||
/**
|
||||
* The time of night in ticks.
|
||||
*/
|
||||
public static int night = 18000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores various settings for default worlds.
|
||||
*/
|
||||
public static class Settings {
|
||||
|
||||
/**
|
||||
* Whether physics should be enabled by default.
|
||||
*/
|
||||
public static boolean physics = true;
|
||||
/**
|
||||
* Whether explosions should be enabled by default.
|
||||
*/
|
||||
public static boolean explosions = true;
|
||||
/**
|
||||
* Whether mob AI should be enabled by default.
|
||||
*/
|
||||
public static boolean mobAi = true;
|
||||
/**
|
||||
* Whether block breaking should be enabled by default.
|
||||
*/
|
||||
public static boolean blockBreaking = true;
|
||||
/**
|
||||
* Whether block placement should be enabled by default.
|
||||
*/
|
||||
public static boolean blockPlacement = true;
|
||||
/**
|
||||
* Whether block interactions should be enabled by default.
|
||||
*/
|
||||
public static boolean blockInteractions = true;
|
||||
|
||||
/**
|
||||
* Stores settings for builders being enabled by default.
|
||||
*/
|
||||
public static class BuildersEnabled {
|
||||
|
||||
/**
|
||||
* Whether builders are enabled by default for public worlds.
|
||||
*/
|
||||
public static boolean publicBuilders = false;
|
||||
/**
|
||||
* Whether builders are enabled by default for private worlds.
|
||||
*/
|
||||
public static boolean privateBuilders = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores world limit settings.
|
||||
*/
|
||||
public static class Limits {
|
||||
|
||||
/**
|
||||
* The maximum number of public worlds a player can have. -1 for unlimited.
|
||||
*/
|
||||
public static int publicWorlds = -1;
|
||||
/**
|
||||
* The maximum number of private worlds a player can have. -1 for unlimited.
|
||||
*/
|
||||
public static int privateWorlds = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores world unload settings.
|
||||
*/
|
||||
public static class Unload {
|
||||
|
||||
/**
|
||||
* Whether world unloading is enabled.
|
||||
*/
|
||||
public static boolean enabled = true;
|
||||
/**
|
||||
* The time until a world is unloaded after all players have left (HH:mm:ss).
|
||||
*/
|
||||
public static String timeUntilUnload = "01:00:00";
|
||||
/**
|
||||
* A set of worlds that should not be unloaded.
|
||||
*/
|
||||
public static Set<String> blacklistedWorlds = Set.of("world", "world_nether", "worth_the_end");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores backup-related settings.
|
||||
*/
|
||||
public static class Backup {
|
||||
|
||||
/**
|
||||
* The maximum number of backups to keep per world.
|
||||
*/
|
||||
public static int maxBackupsPerWorld = 5;
|
||||
/**
|
||||
* The storage for backups.
|
||||
*/
|
||||
public static BackupStorage storage = createBackupStorage();
|
||||
|
||||
public static class AutoBackup {
|
||||
|
||||
/**
|
||||
* Whether automatic backups are enabled.
|
||||
*/
|
||||
public static boolean enabled = true;
|
||||
/**
|
||||
* Whether only active worlds should be backed up.
|
||||
*/
|
||||
public static boolean onlyActiveWorlds;
|
||||
/**
|
||||
* The interval in seconds between automatic backups.
|
||||
*/
|
||||
public static int interval = 900;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores folder-related settings.
|
||||
*/
|
||||
public static class Folder {
|
||||
|
||||
/**
|
||||
* Whether permissions should be overridden for folders.
|
||||
*/
|
||||
public static boolean overridePermissions = true;
|
||||
/**
|
||||
* Whether projects should be overridden for folders.
|
||||
*/
|
||||
public static boolean overrideProjects = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configuration values from the plugin's config.yml into the static fields.
|
||||
*/
|
||||
public static void load() {
|
||||
final Logger logger = PLUGIN.getLogger();
|
||||
|
||||
// Messages
|
||||
Messages.spawnTeleportMessage = CONFIG.getBoolean("messages.spawn-teleport-message", false);
|
||||
Messages.joinQuitMessages = CONFIG.getBoolean("messages.join-quit-messages", true);
|
||||
Messages.dateFormat = CONFIG.getString("messages.date-format", "dd/MM/yyyy");
|
||||
|
||||
// Settings
|
||||
Settings.updateChecker = CONFIG.getBoolean("settings.update-checker", true);
|
||||
Settings.scoreboard = CONFIG.getBoolean("settings.scoreboard", true);
|
||||
// Settings - Archive
|
||||
Archive.vanish = CONFIG.getBoolean("settings.archive.vanish", true);
|
||||
Archive.changeGamemode = CONFIG.getBoolean("settings.archive.change-gamemode", true);
|
||||
Archive.worldGameMode = parseGameMode(CONFIG.getString("settings.archive.world-gamemode"));
|
||||
// Settings - Disabled physics
|
||||
DisabledPhysics.preventConnections = CONFIG.getBoolean("settings.disabled-physics.prevent-connections", true);
|
||||
DisabledPhysics.preventFluidFlow = CONFIG.getBoolean("settings.disabled-physics.prevent-fluid-flow", true);
|
||||
DisabledPhysics.preventFallingBlocks = CONFIG.getBoolean("settings.disabled-physics.prevent-falling-blocks", true);
|
||||
// Settings - Save from death
|
||||
SaveFromDeath.enabled = CONFIG.getBoolean("settings.save-from-death.enabled", true);
|
||||
SaveFromDeath.teleportToMapSpawn = CONFIG.getBoolean("settings.save-from-death.teleport-to-map-spawn", true);
|
||||
// Settings - Build mode
|
||||
BuildMode.dropItems = CONFIG.getBoolean("settings.build-mode.drop-items", true);
|
||||
BuildMode.moveItems = CONFIG.getBoolean("settings.build-mode.move-items", true);
|
||||
// Settings - Builder
|
||||
Builder.blockWorldEditNonBuilder = CONFIG.getBoolean("settings.builder.block-worldedit-non-builder", true);
|
||||
Builder.worldEditWand = parseWorldEditWand();
|
||||
// Settings - Navigator
|
||||
Navigator.item = XMaterial.valueOf(CONFIG.getString("settings.navigator.item", "CLOCK"));
|
||||
Navigator.giveItemOnJoin = CONFIG.getBoolean("settings.navigator.give-item-on-join", true);
|
||||
|
||||
// World
|
||||
World.lockWeather = CONFIG.getBoolean("world.lock-weather", true);
|
||||
World.invalidCharacters = CONFIG.getString("world.invalid-characters", "^\b$");
|
||||
World.importAllDelay = CONFIG.getInt("world.import-all.delay", 30);
|
||||
World.deletionBlacklist = CONFIG.getStringList("world.deletion-blacklist").stream().map(String::toLowerCase).collect(Collectors.toSet());
|
||||
// World - Default
|
||||
Default.worldBoarderSize = CONFIG.getInt("world.default.worldborder.size", 6000000);
|
||||
Default.difficulty = Difficulty.valueOf(CONFIG.getString("world.default.difficulty", "PEACEFUL").toUpperCase(Locale.ROOT));
|
||||
Default.gameRules = CONFIG.getConfigurationSection("world.default.gamerules")
|
||||
.getValues(true)
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(entry -> {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
GameRule<?> rule = GameRule.getByName(key);
|
||||
if (rule == null || value == null) {
|
||||
logger.warning("Could not parse game rule '%s' with value '%s'".formatted(key, value));
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (value) {
|
||||
case Boolean booleanValue -> {
|
||||
if (rule.getType() != Boolean.class) {
|
||||
PLUGIN.getLogger().warning("Game rule '%s' is not a boolean type, but a boolean value was provided".formatted(key));
|
||||
yield null;
|
||||
}
|
||||
yield (GameRuleEntry<?>) new GameRuleEntry<>((GameRule<Boolean>) rule, booleanValue);
|
||||
}
|
||||
case Integer integerValue -> {
|
||||
if (rule.getType() != Integer.class) {
|
||||
logger.warning("Game rule '%s' is not an integer type, but an integer value was provided".formatted(key));
|
||||
yield null;
|
||||
}
|
||||
yield (GameRuleEntry<?>) new GameRuleEntry<>((GameRule<Integer>) rule, integerValue);
|
||||
}
|
||||
default -> {
|
||||
logger.warning("Invalid game rule value type. Must be of type Boolean or Integer. Found %s".formatted(value.getClass().getName()));
|
||||
yield null;
|
||||
}
|
||||
};
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
// World - Default - Permission
|
||||
Permission.publicPermission = CONFIG.getString("world.default.permission.public", "-");
|
||||
Permission.privatePermission = CONFIG.getString("world.default.permission.private", "-");
|
||||
// World - Default - Time
|
||||
Time.sunrise = CONFIG.getInt("world.default.time.sunrise", 0);
|
||||
Time.noon = CONFIG.getInt("world.default.time.noon", 6000);
|
||||
Time.night = CONFIG.getInt("world.default.time.night", 18000);
|
||||
// World - Default - Settings
|
||||
Default.Settings.physics = CONFIG.getBoolean("world.default.settings.physics", true);
|
||||
Default.Settings.explosions = CONFIG.getBoolean("world.default.settings.explosions", true);
|
||||
Default.Settings.mobAi = CONFIG.getBoolean("world.default.settings.mob-ai", true);
|
||||
Default.Settings.blockBreaking = CONFIG.getBoolean("world.default.settings.block-breaking", true);
|
||||
Default.Settings.blockPlacement = CONFIG.getBoolean("world.default.settings.block-placement", true);
|
||||
Default.Settings.blockInteractions = CONFIG.getBoolean("world.default.settings.block-interactions", true);
|
||||
// World - Default - Settings - Builders Enabled
|
||||
BuildersEnabled.publicBuilders = CONFIG.getBoolean("world.default.settings.builders-enabled.public", false);
|
||||
BuildersEnabled.privateBuilders = CONFIG.getBoolean("world.default.settings.builders-enabled.private", true);
|
||||
// World - Limits
|
||||
Limits.publicWorlds = CONFIG.getInt("world.default.settings.public-worlds", -1);
|
||||
Limits.privateWorlds = CONFIG.getInt("world.default.settings.private-worlds", -1);
|
||||
// World - Unload
|
||||
Unload.enabled = CONFIG.getBoolean("world.unload.enabled", false);
|
||||
Unload.timeUntilUnload = CONFIG.getString("world.unload.time-until-unload", "01:00:00");
|
||||
Unload.blacklistedWorlds = new HashSet<>(CONFIG.getStringList("world.unload.blacklisted-worlds"));
|
||||
// World - Backup
|
||||
Backup.maxBackupsPerWorld = Math.min(CONFIG.getInt("world.backup.max-backups-per-world", 5), 18);
|
||||
Backup.storage = createBackupStorage();
|
||||
// World - Backup - AutoBackup
|
||||
AutoBackup.enabled = CONFIG.getBoolean("world.backup.auto-backup.enabled", true);
|
||||
AutoBackup.interval = CONFIG.getInt("world.backup.auto-backup.interval", 900);
|
||||
AutoBackup.onlyActiveWorlds = CONFIG.getBoolean("world.backup.auto-backup.only-active-worlds", true);
|
||||
|
||||
// Folder
|
||||
Folder.overridePermissions = CONFIG.getBoolean("folder.override-permissions", true);
|
||||
Folder.overrideProjects = CONFIG.getBoolean("folder.override-projects", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsing the {@link GameMode} from a string. Defaulting to {@link GameMode#ADVENTURE} if the string is not a valid {@link GameMode}.
|
||||
*
|
||||
* @param gameModeName The name of the {@link GameMode} to parse.
|
||||
* @return The parsed {@link GameMode}.
|
||||
*/
|
||||
private static GameMode parseGameMode(@Nullable String gameModeName) {
|
||||
if (gameModeName == null) {
|
||||
return GameMode.ADVENTURE;
|
||||
}
|
||||
|
||||
return Arrays.stream(GameMode.values())
|
||||
.filter(gameMode -> gameMode.name().equalsIgnoreCase(gameModeName))
|
||||
.findAny()
|
||||
.orElse(GameMode.ADVENTURE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the WorldEdit wand from the plugin's configuration.
|
||||
*
|
||||
* @return The parsed {@link XMaterial} for the WorldEdit wand.
|
||||
*/
|
||||
private static XMaterial parseWorldEditWand() {
|
||||
File pluginDir = PLUGIN.getDataFolder().getParentFile();
|
||||
File configFile = null;
|
||||
|
||||
File weConfig = new File(pluginDir + File.separator + "WorldEdit", "config.yml");
|
||||
if (weConfig.exists()) {
|
||||
configFile = weConfig;
|
||||
}
|
||||
|
||||
File faweConfig = new File(pluginDir + File.separator + "FastAsyncWorldEdit", "worldedit-config.yml");
|
||||
if (faweConfig.exists()) {
|
||||
configFile = faweConfig;
|
||||
}
|
||||
|
||||
XMaterial defaultWand = XMaterial.WOODEN_AXE;
|
||||
if (configFile == null) {
|
||||
return defaultWand;
|
||||
}
|
||||
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
String wand = config.getString("wand-item");
|
||||
if (wand == null) {
|
||||
return defaultWand;
|
||||
}
|
||||
|
||||
String namespace = "minecraft:";
|
||||
if (wand.toLowerCase(Locale.ROOT).startsWith(namespace)) {
|
||||
wand = wand.substring(namespace.length());
|
||||
}
|
||||
|
||||
return XMaterial.matchXMaterial(wand).orElse(defaultWand);
|
||||
}
|
||||
|
||||
@Contract("-> new")
|
||||
private static BackupStorage createBackupStorage() {
|
||||
String type = CONFIG.getString("world.backup.storage.type", "local").toLowerCase();
|
||||
|
||||
switch (type) {
|
||||
case "s3" -> {
|
||||
ConfigurationSection s3 = CONFIG.getConfigurationSection("world.backup.storage.s3");
|
||||
return new S3BackupStorage(
|
||||
PLUGIN,
|
||||
s3.getString("url"),
|
||||
s3.getString("access-key"),
|
||||
s3.getString("secret-key"),
|
||||
s3.getString("region"),
|
||||
s3.getString("bucket"),
|
||||
s3.getString("path")
|
||||
);
|
||||
}
|
||||
case "sftp" -> {
|
||||
ConfigurationSection sftp = CONFIG.getConfigurationSection("world.backup.storage.sftp");
|
||||
return new SftpBackupStorage(
|
||||
PLUGIN,
|
||||
sftp.getString("host"),
|
||||
sftp.getInt("port"),
|
||||
sftp.getString("username"),
|
||||
sftp.getString("password"),
|
||||
sftp.getString("path")
|
||||
);
|
||||
}
|
||||
default -> {
|
||||
if (!type.equals("local")) {
|
||||
PLUGIN.getLogger().warning("Unknown backup storage type '" + type + "', defaulting to local storage.");
|
||||
}
|
||||
return new LocalBackupStorage(PLUGIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.config.migration;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Manages the migration of configurations. It holds a registry of available migration steps and applies them sequentially.
|
||||
*/
|
||||
@NullMarked
|
||||
public class ConfigMigrationManager {
|
||||
|
||||
public static final int LATEST_VERSION = 2;
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final Map<Integer, Migration> migrations;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ConfigMigrationManager} instance.
|
||||
*
|
||||
* @param plugin The BuildSystemPlugin instance
|
||||
*/
|
||||
public ConfigMigrationManager(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.migrations = new HashMap<>();
|
||||
|
||||
registerMigration(1, new MigrationV1ToV2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link Migration} step.
|
||||
*
|
||||
* @param fromVersion The version from which this migration applies. For example, {@link MigrationV1ToV2} is registered with {@code fromVersion = 1}
|
||||
* @param migration The migration instance
|
||||
*/
|
||||
public void registerMigration(int fromVersion, Migration migration) {
|
||||
this.migrations.put(fromVersion, migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates the given configuration to the latest version.
|
||||
*
|
||||
* @throws IllegalStateException If a required migration step is missing.
|
||||
*/
|
||||
public void migrate() {
|
||||
Logger logger = plugin.getLogger();
|
||||
|
||||
while (Config.getVersion() < LATEST_VERSION) {
|
||||
int currentVersion = Config.getVersion();
|
||||
Migration migration = migrations.get(currentVersion);
|
||||
if (migration == null) {
|
||||
throw new IllegalStateException("Missing migration from version " + currentVersion + " to " + (currentVersion + 1));
|
||||
}
|
||||
|
||||
logger.info("Migrating from version " + currentVersion + " to " + (currentVersion + 1) + "...");
|
||||
migration.migrate(Config.getConfig());
|
||||
Config.setVersion(currentVersion + 1);
|
||||
}
|
||||
|
||||
logger.info("Config is at the latest version: " + Config.getVersion());
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.config.migration;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Interface for a single configuration migration step. Each implementation should know how to migrate a configuration from a specific source version to the next version.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface Migration {
|
||||
|
||||
/**
|
||||
* Applies the migration logic to the given configuration.
|
||||
* <p>
|
||||
* The implementation is responsible for modifying the config's internal data and potentially its version, though the manager will handle version incrementing.
|
||||
*
|
||||
* @param config The configuration to migrate
|
||||
*/
|
||||
void migrate(FileConfiguration config);
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.config.migration;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class MigrationV1ToV2 implements Migration {
|
||||
|
||||
@Override
|
||||
public void migrate(FileConfiguration config) {
|
||||
if (config.contains("settings.archive-vanish")) {
|
||||
config.set("settings.archive.vanish", config.getBoolean("settings.archive-vanish"));
|
||||
config.set("settings.archive-vanish", null);
|
||||
}
|
||||
|
||||
if (config.contains("settings.archive-should-change-gamemode")) {
|
||||
config.set("settings.archive.change-gamemode", config.getBoolean("settings.archive-should-change-gamemode"));
|
||||
config.set("settings.archive-should-change-gamemode", null);
|
||||
}
|
||||
|
||||
if (config.contains("settings.archive-world-game-mode")) {
|
||||
config.set("settings.archive.world-gamemode", config.getString("settings.archive-world-game-mode"));
|
||||
config.setComments("settings.archive.world-gamemode", List.of("Options: SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR"));
|
||||
config.set("settings.archive-world-game-mode", null);
|
||||
}
|
||||
|
||||
if (config.contains("settings.teleport-after-creation")) {
|
||||
config.set("settings.teleport-after-creation", null);
|
||||
}
|
||||
|
||||
if (config.contains("world.void-block")) {
|
||||
config.set("world.void-block", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.event;
|
||||
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.event.world.BuildWorldManipulationEvent;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Manages the dispatching of custom events related to build world manipulations.
|
||||
*/
|
||||
@NullMarked
|
||||
public class EventDispatcher {
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EventDispatcher} instance.
|
||||
*
|
||||
* @param worldStorage The world storage used to retrieve {@link BuildWorld} information
|
||||
*/
|
||||
public EventDispatcher(WorldStorageImpl worldStorage) {
|
||||
this.worldStorage = worldStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Dispatches a build world manipulation event if the player is in a build world
|
||||
* and the parent event has not been canceled.</p>
|
||||
*
|
||||
* <p>This method checks if:</p>
|
||||
* <ol>
|
||||
* <li>The parent event is not yet canceled</li>
|
||||
* <li>The player is in a valid build world</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* If both conditions are met, it triggers a {@link BuildWorldManipulationEvent}
|
||||
* to allow further processing of the player's action.
|
||||
*
|
||||
* @param player The player who performed the manipulation
|
||||
* @param parentEvent The original event that triggered this potential manipulation
|
||||
*/
|
||||
public void dispatchManipulationEventIfPlayerInBuildWorld(Player player, Cancellable parentEvent) {
|
||||
if (parentEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Bukkit.getPluginManager().callEvent(new BuildWorldManipulationEvent(parentEvent, player, buildWorld));
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.event.player;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when a player's inventory is cleared.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerInventoryClearEvent extends PlayerEvent {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final List<Integer> navigatorSlots;
|
||||
|
||||
public PlayerInventoryClearEvent(Player player, List<Integer> navigatorSlots) {
|
||||
super(player);
|
||||
this.navigatorSlots = navigatorSlots;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all slots containing a navigator item in a player's inventory.
|
||||
*
|
||||
* @return A list of slot numbers containing navigator items
|
||||
*/
|
||||
public List<Integer> getNavigatorSlots() {
|
||||
return navigatorSlots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.event.world;
|
||||
|
||||
import de.eintosti.buildsystem.api.event.world.BuildWorldEvent;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.listener.WorldManipulateListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* This event reduces duplicated code.
|
||||
* <p>
|
||||
* It will be called when:
|
||||
* <ul>
|
||||
* <li>Breaking Blocks</li>
|
||||
* <li>Placing Blocks</li>
|
||||
* <li>Other modification-related stuff</li>
|
||||
* </ul>
|
||||
* Cancelling this event will affect the parent-Event, which has caused the ManipulationEvent to fire.
|
||||
* <p>Expect the manipulation event to be canceled at {@link org.bukkit.event.EventPriority#LOW} if the player is not allowed to interact with the world.</p>
|
||||
*
|
||||
* @see WorldManipulateListener
|
||||
*/
|
||||
@NullMarked
|
||||
public class BuildWorldManipulationEvent extends BuildWorldEvent implements Cancellable {
|
||||
|
||||
private final Cancellable parentEvent;
|
||||
private final Player player;
|
||||
|
||||
public BuildWorldManipulationEvent(Cancellable parentEvent, Player player, BuildWorld buildWorld) {
|
||||
super(buildWorld);
|
||||
this.parentEvent = parentEvent;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return parentEvent.isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
parentEvent.setCancelled(cancelled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the event which has caused the manipulation event to fire.
|
||||
*/
|
||||
public Cancellable getParentEvent() {
|
||||
return parentEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player manipulating the {@link BuildWorld}.
|
||||
*
|
||||
* @return The player manipulating the world
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.expansion.luckperms;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.expansion.luckperms.calculators.BuildModeCalculator;
|
||||
import de.eintosti.buildsystem.expansion.luckperms.calculators.RoleCalculator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.context.ContextCalculator;
|
||||
import net.luckperms.api.context.ContextManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class LuckPermsExpansion {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final ContextManager contextManager;
|
||||
private final List<ContextCalculator<Player>> registeredCalculators;
|
||||
|
||||
public LuckPermsExpansion(BuildSystemPlugin plugin) {
|
||||
LuckPerms luckPerms = plugin.getServer().getServicesManager().load(LuckPerms.class);
|
||||
if (luckPerms == null) {
|
||||
throw new IllegalStateException("LuckPerms API not loaded.");
|
||||
}
|
||||
|
||||
this.plugin = plugin;
|
||||
this.contextManager = luckPerms.getContextManager();
|
||||
this.registeredCalculators = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void registerAll() {
|
||||
register("build-mode", () -> new BuildModeCalculator(plugin));
|
||||
register("role", () -> new RoleCalculator(plugin));
|
||||
plugin.getLogger().info("LuckPerms expansion initialized");
|
||||
}
|
||||
|
||||
private void register(String option, Supplier<ContextCalculator<Player>> calculatorSupplier) {
|
||||
plugin.getLogger().info("Registering '" + option + "' calculator");
|
||||
ContextCalculator<Player> calculator = calculatorSupplier.get();
|
||||
this.contextManager.registerCalculator(calculator);
|
||||
this.registeredCalculators.add(calculator);
|
||||
}
|
||||
|
||||
public void unregisterAll() {
|
||||
this.registeredCalculators.forEach(this.contextManager::unregisterCalculator);
|
||||
this.registeredCalculators.clear();
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.expansion.luckperms.calculators;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import net.luckperms.api.context.ContextCalculator;
|
||||
import net.luckperms.api.context.ContextConsumer;
|
||||
import net.luckperms.api.context.ContextSet;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildModeCalculator implements ContextCalculator<Player> {
|
||||
|
||||
private static final String KEY = "buildsystem:build-mode";
|
||||
|
||||
private final PlayerServiceImpl playerManager;
|
||||
|
||||
public BuildModeCalculator(BuildSystemPlugin plugin) {
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(Player player, ContextConsumer contextConsumer) {
|
||||
boolean isInBuildMode = playerManager.isInBuildMode(player);
|
||||
contextConsumer.accept(KEY, String.valueOf(isInBuildMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet estimatePotentialContexts() {
|
||||
return ImmutableContextSet.builder()
|
||||
.add(KEY, "true")
|
||||
.add(KEY, "false")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+98
@@ -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.expansion.luckperms.calculators;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import java.util.Locale;
|
||||
import net.luckperms.api.context.ContextCalculator;
|
||||
import net.luckperms.api.context.ContextConsumer;
|
||||
import net.luckperms.api.context.ContextSet;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class RoleCalculator implements ContextCalculator<Player> {
|
||||
|
||||
private static final String KEY = "buildsystem:role";
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public RoleCalculator(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(@NonNull Player player, @NonNull ContextConsumer contextConsumer) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
contextConsumer.accept(KEY, Role.matchRole(player, buildWorld).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet estimatePotentialContexts() {
|
||||
ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
|
||||
for (Role role : Role.values()) {
|
||||
builder.add(KEY, role.toString());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@NullMarked
|
||||
private enum Role {
|
||||
|
||||
/**
|
||||
* The creator of a {@link BuildWorld}.
|
||||
*/
|
||||
CREATOR,
|
||||
|
||||
/**
|
||||
* A player which has been added to the list of trusted players and is therefore allowed to build in a {@link BuildWorld}.
|
||||
*/
|
||||
BUILDER,
|
||||
|
||||
/**
|
||||
* A player which is neither the {@link #CREATOR} nor a {@link #BUILDER} in a {@link BuildWorld}.
|
||||
*/
|
||||
GUEST;
|
||||
|
||||
public static Role matchRole(Player player, @Nullable BuildWorld buildWorld) {
|
||||
if (buildWorld == null) {
|
||||
return GUEST;
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builders.isCreator(player)) {
|
||||
return CREATOR;
|
||||
} else if (builders.isBuilder(player.getUniqueId())) {
|
||||
return BUILDER;
|
||||
} else {
|
||||
return GUEST;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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.expansion.placeholderapi;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import java.util.Locale;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class PlaceholderApiExpansion extends PlaceholderExpansion {
|
||||
|
||||
private static final String SETTINGS_KEY = "settings";
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final SettingsManager settingsManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public PlaceholderApiExpansion(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getLogger().info("PlaceholderAPI expansion initialized");
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this is an internal class, you must override this method to let PlaceholderAPI know to not unregister your expansion class when PlaceholderAPI is reloaded
|
||||
*
|
||||
* @return true to persist through reloads
|
||||
*/
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this is an internal class, this check is not needed, and we can simply return {@code true}
|
||||
*
|
||||
* @return Always true since it's an internal class.
|
||||
*/
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the person who created this expansion should go here. For convenience do we return the author from the plugin.yml
|
||||
*
|
||||
* @return The name of the author as a String.
|
||||
*/
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return plugin.getDescription().getAuthors().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The placeholder identifier should go here. This is what tells PlaceholderAPI to call our onRequest method to get a value if a placeholder starts with our identifier. This
|
||||
* must be unique and cannot contain % or _
|
||||
*
|
||||
* @return The identifier in {@code %<identifier>_<value>%} as String.
|
||||
*/
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "buildsystem";
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the version of the expansion. You don't have to use numbers since it is set as a String.
|
||||
* <p>
|
||||
* For convenience do we return the version from the plugin.yml
|
||||
*
|
||||
* @return The version as a string.
|
||||
*/
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method called when a placeholder with our identifier is found and needs a value. We specify the value identifier in this method.
|
||||
*
|
||||
* @param player The player for which the placeholder is requested.
|
||||
* @param identifier The identifier of the placeholder
|
||||
* @return The value of the placeholder as a string, or {@code null} if the identifier is not recognized.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String onPlaceholderRequest(@Nullable Player player, String identifier) {
|
||||
if (player == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (identifier.matches(".*_.*") && identifier.split("_")[0].equalsIgnoreCase(SETTINGS_KEY)) {
|
||||
return parseSettingsPlaceholder(player, identifier);
|
||||
} else {
|
||||
return parseBuildWorldPlaceholder(player, identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method called when a placeholder with the identifier {@code %buildsystem_settings_<setting>%} is found.
|
||||
*
|
||||
* @param player The player for which the placeholder is requested
|
||||
* @param identifier The identifier
|
||||
* @return The requested setting as a string, or {@code null} if the setting is not recognized
|
||||
*/
|
||||
@Nullable
|
||||
private String parseSettingsPlaceholder(Player player, String identifier) {
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
String settingIdentifier = identifier.split("_")[1];
|
||||
|
||||
return switch (settingIdentifier.toLowerCase(Locale.ROOT)) {
|
||||
case "navigatortype" -> settings.getNavigatorType().toString();
|
||||
case "glasscolor" -> settings.getDesignColor().toString();
|
||||
case "worldsort" -> settings.getWorldDisplay().getWorldSort().toString();
|
||||
case "clearinventory" -> String.valueOf(settings.isClearInventory());
|
||||
case "disableinteract" -> String.valueOf(settings.isDisableInteract());
|
||||
case "hideplayers" -> String.valueOf(settings.isHidePlayers());
|
||||
case "instantplacesigns" -> String.valueOf(settings.isInstantPlaceSigns());
|
||||
case "keepnavigator" -> String.valueOf(settings.isKeepNavigator());
|
||||
case "nightvision" -> String.valueOf(settings.isNightVision());
|
||||
case "noclip" -> String.valueOf(settings.isNoClip());
|
||||
case "placeplants" -> String.valueOf(settings.isPlacePlants());
|
||||
case "scoreboard" -> String.valueOf(settings.isScoreboard());
|
||||
case "slabbreaking" -> String.valueOf(settings.isSlabBreaking());
|
||||
case "spawnteleport" -> String.valueOf(settings.isSpawnTeleport());
|
||||
case "opentrapdoors" -> String.valueOf(settings.isOpenTrapDoors());
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method called when a placeholder with the identifier needed for {@link PlaceholderApiExpansion#parseSettingsPlaceholder(Player, String)} is not found.
|
||||
* <p>
|
||||
* The default layout for a world placeholder is {@code %buildsystem_<value>%}. If a world is not specified by using the format {@code %buildsystem_<value>_<world>%} then the
|
||||
* world the player is currently in will be used.
|
||||
*
|
||||
* @param player The player for which the placeholder is requested
|
||||
* @param identifier The identifier
|
||||
* @return The requested value as a string, or {@code null} if the identifier is not recognized or the world does not exist
|
||||
*/
|
||||
@Nullable
|
||||
private String parseBuildWorldPlaceholder(Player player, String identifier) {
|
||||
String worldName = player.getWorld().getName();
|
||||
if (identifier.matches(".*_.*")) {
|
||||
String[] splitString = identifier.split("_");
|
||||
worldName = splitString[1];
|
||||
identifier = splitString[0];
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (buildWorld == null) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
WorldData worldData = buildWorld.getData();
|
||||
return switch (identifier.toLowerCase(Locale.ROOT)) {
|
||||
case "blockbreaking" -> String.valueOf(worldData.blockBreaking().get());
|
||||
case "blockplacement" -> String.valueOf(worldData.blockPlacement().get());
|
||||
case "builders" -> builders.asPlaceholder(player);
|
||||
case "buildersenabled" -> String.valueOf(worldData.buildersEnabled().get());
|
||||
case "creation" -> Messages.formatDate(buildWorld.getCreation());
|
||||
case "creator" -> builders.hasCreator() ? builders.getCreator().getName() : "-";
|
||||
case "creatorid" -> builders.hasCreator() ? String.valueOf(builders.getCreator().getUniqueId()) : "-";
|
||||
case "explosions" -> String.valueOf(worldData.explosions().get());
|
||||
case "lastedited" -> Messages.formatDate(worldData.lastEdited().get());
|
||||
case "lastloaded" -> Messages.formatDate(worldData.lastLoaded().get());
|
||||
case "lastunloaded" -> Messages.formatDate(worldData.lastUnloaded().get());
|
||||
case "loaded" -> String.valueOf(buildWorld.isLoaded());
|
||||
case "material" -> worldData.material().get().name();
|
||||
case "mobai" -> String.valueOf(worldData.mobAi().get());
|
||||
case "permission" -> worldData.permission().get();
|
||||
case "private" -> String.valueOf(worldData.privateWorld().get());
|
||||
case "project" -> worldData.project().get();
|
||||
case "physics" -> String.valueOf(worldData.physics().get());
|
||||
case "spawn" -> worldData.customSpawn().get();
|
||||
case "status" -> Messages.getString(Messages.getMessageKey(worldData.status().get()), player);
|
||||
case "time" -> buildWorld.getWorldTime();
|
||||
case "type" -> Messages.getString(Messages.getMessageKey(buildWorld.getType()), player);
|
||||
case "world" -> buildWorld.getName();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.util.color.ColorAPI;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class AsyncPlayerChatListener implements Listener {
|
||||
|
||||
public AsyncPlayerChatListener(BuildSystemPlugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!player.hasPermission("buildsystem.color.chat")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String coloredMessage = ChatColor.translateAlternateColorCodes('&', ColorAPI.process(event.getMessage()));
|
||||
event.setMessage(coloredMessage);
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.LogoutLocation;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.storage.PlayerStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.SpawnManager;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class AsyncPlayerPreLoginListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerStorage playerStorage;
|
||||
private final SpawnManager spawnManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public AsyncPlayerPreLoginListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerStorage = plugin.getPlayerService().getPlayerStorage();
|
||||
this.spawnManager = plugin.getSpawnManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
|
||||
UUID uuid = event.getUniqueId();
|
||||
BuildPlayer buildPlayer = playerStorage.getBuildPlayer(uuid);
|
||||
if (buildPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = buildPlayer.getSettings();
|
||||
if (settings.isSpawnTeleport() && spawnManager.spawnExists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogoutLocation logoutLocation = buildPlayer.getLogoutLocation();
|
||||
if (logoutLocation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(logoutLocation.worldName());
|
||||
if (buildWorld == null) {
|
||||
buildPlayer.setLogoutLocation(null);
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> buildWorld.getLoader().load());
|
||||
}
|
||||
}
|
||||
}
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.DisabledPhysics;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.util.DirectionUtil;
|
||||
import java.util.List;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.type.Fence;
|
||||
import org.bukkit.block.data.type.Gate;
|
||||
import org.bukkit.block.data.type.GlassPane;
|
||||
import org.bukkit.block.data.type.Stairs;
|
||||
import org.bukkit.block.data.type.Wall;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.BlockFadeEvent;
|
||||
import org.bukkit.event.block.BlockFormEvent;
|
||||
import org.bukkit.event.block.BlockFromToEvent;
|
||||
import org.bukkit.event.block.BlockGrowEvent;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||
import org.bukkit.event.block.BlockSpreadEvent;
|
||||
import org.bukkit.event.block.LeavesDecayEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BlockPhysicsListener implements Listener {
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public BlockPhysicsListener(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPhysics(BlockPhysicsEvent event) {
|
||||
Block block = event.getBlock();
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(block.getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DisabledPhysics.preventConnections) {
|
||||
boolean canConnect = switch (block.getBlockData()) {
|
||||
case Fence fence -> true;
|
||||
case Gate gate -> true;
|
||||
case GlassPane glassPane -> true;
|
||||
case Stairs stairs -> true;
|
||||
case Wall wall -> true;
|
||||
default -> false;
|
||||
};
|
||||
if (canConnect) {
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (XMaterial.matchXMaterial(block.getType())) {
|
||||
case REDSTONE_BLOCK -> {
|
||||
for (BlockFace blockFace : DirectionUtil.BLOCK_SIDES) {
|
||||
if (isCustomRedstoneLamp(block.getRelative(blockFace))) {
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
case REDSTONE_LAMP -> {
|
||||
for (BlockFace blockFace : DirectionUtil.BLOCK_SIDES) {
|
||||
if (block.getRelative(blockFace).getType() == XMaterial.REDSTONE_BLOCK.get()) {
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLeavesDecay(LeavesDecayEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockFade(BlockFadeEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockForm(BlockFormEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockFromTo(BlockFromToEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getBlock().isLiquid() && !DisabledPhysics.preventFluidFlow) {
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockGrow(BlockGrowEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockSpread(BlockSpreadEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getEntityType() == EntityType.FALLING_BLOCK && DisabledPhysics.preventFallingBlocks) {
|
||||
event.setCancelled(true);
|
||||
event.getBlock().getState().update(false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onBlockRedstone(BlockRedstoneEvent event) {
|
||||
Block block = event.getBlock();
|
||||
if (isCustomRedstoneLamp(block)) {
|
||||
event.setNewCurrent(15);
|
||||
}
|
||||
|
||||
XMaterial xMaterial = XMaterial.matchXMaterial(block.getType());
|
||||
if (xMaterial != XMaterial.REDSTONE_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (BlockFace blockFace : DirectionUtil.BLOCK_SIDES) {
|
||||
if (isCustomRedstoneLamp(block.getRelative(blockFace))) {
|
||||
event.setNewCurrent(15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockExplode(BlockExplodeEvent event) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityExplode(EntityExplodeEvent event) {
|
||||
World world = event.getLocation().getWorld();
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(world);
|
||||
if (buildWorld == null || buildWorld.getData().physics().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
private boolean isCustomRedstoneLamp(Block block) {
|
||||
List<MetadataValue> metadataValues = block.getMetadata("CustomRedstoneLamp");
|
||||
for (MetadataValue value : metadataValues) {
|
||||
if (value.asBoolean()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return block.getType().name().equals("REDSTONE_LAMP_ON");
|
||||
}
|
||||
}
|
||||
+81
@@ -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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.inventory.XInventoryView;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.BuildMode;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildModePreventationListener implements Listener {
|
||||
|
||||
private final PlayerServiceImpl playerManager;
|
||||
|
||||
public BuildModePreventationListener(BuildSystemPlugin plugin) {
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a player from dropping items when in build-mode.
|
||||
*
|
||||
* @param event The drop item event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||
if (BuildMode.dropItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerManager.isInBuildMode(event.getPlayer())) {
|
||||
event.getItemDrop().remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a player from moving items into another inventory when in build-mode.
|
||||
*
|
||||
* @param event The inventory click event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (BuildMode.moveItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerManager.isInBuildMode(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (XInventoryView.of(event.getView()).getTopInventory().getType() != InventoryType.CRAFTING) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class BuildWorldResetUnloadListener implements Listener {
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public BuildWorldResetUnloadListener(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
||||
resetUnloadTask(event.getFrom());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
resetUnloadTask(event.getPlayer().getWorld());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the unload task for the given world.
|
||||
*
|
||||
* @param world The world for which the unload task should be reset
|
||||
*/
|
||||
private void resetUnloadTask(World world) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(world.getName());
|
||||
if (buildWorld != null) {
|
||||
buildWorld.getUnloader().resetUnloadTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.NullExtent;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class EditSessionListener implements Listener {
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public EditSessionListener(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
WorldEdit.getInstance().getEventBus().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEditSession(EditSessionEvent event) {
|
||||
Actor actor = event.getActor();
|
||||
if (actor == null || !actor.isPlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = Bukkit.getPlayer(actor.getName());
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getStage() != EditSession.Stage.BEFORE_CHANGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasAdminPermission = buildWorld.getPermissions().hasAdminPermission(player);
|
||||
if (hasAdminPermission || (!disableArchivedWorlds(buildWorld, player, event) && !disableNonBuilders(buildWorld, player, event))) {
|
||||
buildWorld.getData().lastEdited().set(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the editing of archived worlds for players without the necessary permission.
|
||||
*
|
||||
* @param buildWorld The build world
|
||||
* @param player The player
|
||||
* @param event The EditSessionEvent
|
||||
* @return {@code true} if the edit was canceled, otherwise {@code false}
|
||||
*/
|
||||
private boolean disableArchivedWorlds(BuildWorld buildWorld, Player player, EditSessionEvent event) {
|
||||
if (buildWorld.getPermissions().canBypassBuildRestriction(player) || player.hasPermission("buildsystem.bypass.archive")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buildWorld.getData().status().get() == BuildWorldStatus.ARCHIVE) {
|
||||
event.setExtent(new NullExtent());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the editing of worlds in which a player is not a builder.
|
||||
*
|
||||
* @param buildWorld The build world
|
||||
* @param player The player
|
||||
* @param event The EditSessionEvent
|
||||
* @return {@code true} if the edit was canceled, otherwise {@code false}
|
||||
*/
|
||||
private boolean disableNonBuilders(BuildWorld buildWorld, Player player, EditSessionEvent event) {
|
||||
if (buildWorld.getPermissions().canBypassBuildRestriction(player) || player.hasPermission("buildsystem.bypass.builders")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builders.isCreator(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buildWorld.getData().buildersEnabled().get() && !builders.isBuilder(player)) {
|
||||
event.setExtent(new NullExtent());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.SaveFromDeath;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class EntityDamageListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public EntityDamageListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if (event.getEntityType() != EntityType.PLAYER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Teleport player up if void damage is taken
|
||||
if (event.getCause() != EntityDamageEvent.DamageCause.VOID || !SaveFromDeath.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) event.getEntity();
|
||||
Location teleportLoc = player.getLocation().clone().add(0, 200, 0);
|
||||
|
||||
if (SaveFromDeath.teleportToMapSpawn) {
|
||||
BuildWorld buildWorld = plugin.getWorldService().getWorldStorage().getBuildWorld(player.getWorld());
|
||||
if (buildWorld != null) {
|
||||
Location spawn = buildWorld.getData().getCustomSpawnLocation();
|
||||
if (spawn != null) {
|
||||
teleportLoc = spawn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
player.setFallDistance(0);
|
||||
PaperLib.teleportAsync(player, teleportLoc)
|
||||
.whenComplete((completed, throwable) -> {
|
||||
if (!completed) {
|
||||
return;
|
||||
}
|
||||
XSound.ENTITY_ZOMBIE_INFECT.play(player);
|
||||
});
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class EntitySpawnListener implements Listener {
|
||||
|
||||
private final WorldStorage worldStorage;
|
||||
|
||||
public EntitySpawnListener(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntitySpawn(EntitySpawnEvent event) {
|
||||
World bukkitWorld = event.getLocation().getWorld();
|
||||
if (bukkitWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(bukkitWorld.getName());
|
||||
if (buildWorld == null || buildWorld.getData().mobAi().get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getEntity() instanceof LivingEntity livingEntity) {
|
||||
livingEntity.setAI(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class FoodLevelChangeListener implements Listener {
|
||||
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public FoodLevelChangeListener(BuildSystemPlugin plugin) {
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld != null && buildWorld.getData().status().get() == BuildWorldStatus.ARCHIVE) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.event.player.PlayerInventoryClearEvent;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryCreativeEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class InventoryCreativeListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
|
||||
public InventoryCreativeListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClearInventory(InventoryCreativeEvent event) {
|
||||
if (event.getClick() != ClickType.CREATIVE
|
||||
|| event.getSlotType() != InventoryType.SlotType.QUICKBAR
|
||||
|| event.getAction() != InventoryAction.PLACE_ALL
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
List<Integer> navigatorSlots = InventoryUtils.getNavigatorSlots(player);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
PlayerInventoryClearEvent playerInventoryClearEvent = new PlayerInventoryClearEvent(player, navigatorSlots);
|
||||
Bukkit.getServer().getPluginManager().callEvent(playerInventoryClearEvent);
|
||||
}, 2L);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class InventoryListener implements Listener {
|
||||
|
||||
private final InventoryManager inventoryManager;
|
||||
|
||||
public InventoryListener(BuildSystemPlugin plugin) {
|
||||
this.inventoryManager = plugin.getInventoryManager();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||
this.inventoryManager.handleOpen(event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
this.inventoryManager.handleClick(event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
this.inventoryManager.handleClose(event);
|
||||
}
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import com.cryptomorin.xseries.XPotion;
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import com.cryptomorin.xseries.inventory.XInventoryView;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
|
||||
import de.eintosti.buildsystem.api.world.navigator.settings.NavigatorType;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Navigator;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import de.eintosti.buildsystem.world.navigator.ArmorStandManager;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.ArchivedWorldsInventory;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.DisplayablesInventory;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.NavigatorInventory;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.PrivateWorldsInventory;
|
||||
import de.eintosti.buildsystem.world.navigator.inventory.PublicWorldsInventory;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class NavigatorListener implements Listener {
|
||||
|
||||
private static final double MAX_HEIGHT = 2.074631929397583;
|
||||
private static final double MIN_HEIGHT = 1.4409877061843872;
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final ArmorStandManager armorStandManager;
|
||||
private final PlayerServiceImpl playerService;
|
||||
private final SettingsManager settingsManager;
|
||||
private final WorldStorage worldStorage;
|
||||
|
||||
public NavigatorListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.armorStandManager = plugin.getArmorStandManager();
|
||||
this.playerService = plugin.getPlayerService();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the player interacts with the navigator item.
|
||||
*
|
||||
* @param event The event which calls this method
|
||||
*/
|
||||
@EventHandler
|
||||
public void manageNavigatorItemInteraction(PlayerInteractEvent event) {
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (XInventoryView.of(player.getOpenInventory()).getTopInventory().getType() != InventoryType.CRAFTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InventoryUtils.isNavigator(itemStack)) {
|
||||
event.setCancelled(true);
|
||||
if (!player.hasPermission("buildsystem.navigator.item")) {
|
||||
Messages.sendPermissionError(player);
|
||||
return;
|
||||
}
|
||||
openNavigator(player);
|
||||
} else if (isCloseNavigatorItem(player, itemStack)) {
|
||||
event.setCancelled(true);
|
||||
playerService.closeNewNavigator(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void openNavigator(Player player) {
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
switch (settings.getNavigatorType()) {
|
||||
case OLD -> {
|
||||
new NavigatorInventory(plugin).openInventory(player);
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
}
|
||||
case NEW -> {
|
||||
if (playerService.getOpenNavigator().contains(player)) {
|
||||
Messages.sendMessage(player, "worlds_navigator_open");
|
||||
return;
|
||||
}
|
||||
|
||||
summonNewNavigator(player);
|
||||
String findItemName = Messages.getString("navigator_item", player);
|
||||
ItemStack replaceItem = InventoryUtils.createItem(XMaterial.BARRIER, Messages.getString("barrier_item", player));
|
||||
InventoryUtils.replaceItem(player, findItemName, Navigator.item, replaceItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void summonNewNavigator(Player player) {
|
||||
CachedValues cachedValues = playerService.getPlayerStorage().getBuildPlayer(player).getCachedValues();
|
||||
cachedValues.saveWalkSpeed(player.getWalkSpeed());
|
||||
cachedValues.saveFlySpeed(player.getFlySpeed());
|
||||
|
||||
// Cancel movement and disable flying
|
||||
player.setSprinting(false);
|
||||
player.setWalkSpeed(0.0f);
|
||||
player.setFlySpeed(0.0f);
|
||||
player.setVelocity(new Vector(0, 0, 0));
|
||||
player.teleport(player.getLocation());
|
||||
player.addPotionEffect(new PotionEffect(XPotion.BLINDNESS.get(), PotionEffect.INFINITE_DURATION, 0, false, false));
|
||||
player.addPotionEffect(new PotionEffect(XPotion.JUMP_BOOST.get(), PotionEffect.INFINITE_DURATION, 250, false, false));
|
||||
|
||||
armorStandManager.spawnArmorStands(player);
|
||||
playerService.getOpenNavigator().add(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages a player's interaction with the {@link NavigatorType#NEW} navigator.
|
||||
*
|
||||
* @param event The event which calls this method
|
||||
*/
|
||||
@EventHandler
|
||||
public void manageNewNavigatorInteraction(PlayerInteractAtEntityEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Entity entity = event.getRightClicked();
|
||||
|
||||
// Disable interaction entities in archived worlds
|
||||
disableArchivedWorlds(player, event);
|
||||
|
||||
if (!playerService.getOpenNavigator().contains(player) || !(entity instanceof ArmorStand armorStand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCloseNavigatorItem(player, player.getInventory().getItemInMainHand())) {
|
||||
event.setCancelled(true);
|
||||
playerService.closeNewNavigator(player);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector clickedPosition = event.getClickedPosition();
|
||||
if (clickedPosition.getY() > MIN_HEIGHT && clickedPosition.getY() < MAX_HEIGHT) {
|
||||
NavigatorCategory category = ArmorStandManager.matchNavigatorCategory(armorStand);
|
||||
if (category == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID ownerUUID = ArmorStandManager.getOwner(armorStand);
|
||||
if (!Objects.equals(ownerUUID, player.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayablesInventory inventory = switch (category) {
|
||||
case PUBLIC -> new PublicWorldsInventory(plugin, player);
|
||||
case ARCHIVE -> new ArchivedWorldsInventory(plugin, player);
|
||||
case PRIVATE -> new PrivateWorldsInventory(plugin, player);
|
||||
};
|
||||
|
||||
XSound.BLOCK_CHEST_OPEN.play(player);
|
||||
inventory.openInventory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels an event if the player is in an archived world.
|
||||
*
|
||||
* @param player The player object
|
||||
* @param cancellable The event to cancel
|
||||
*/
|
||||
private void disableArchivedWorlds(Player player, Cancellable cancellable) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null || buildWorld.getData().status().get() != BuildWorldStatus.ARCHIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerService.isInBuildMode(player)) {
|
||||
cancellable.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables players from manipulating with armor stands which make up the {@link NavigatorType#NEW} navigator.
|
||||
*
|
||||
* @param event The event which calls this method
|
||||
*/
|
||||
@EventHandler
|
||||
public void preventNewNavigatorManipulation(PlayerArmorStandManipulateEvent event) {
|
||||
ArmorStand armorStand = event.getRightClicked();
|
||||
if (ArmorStandManager.matchNavigatorCategory(armorStand) == null || ArmorStandManager.getOwner(armorStand) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents players from dropping the item which is used to close the {@link NavigatorType#NEW} navigator.
|
||||
*
|
||||
* @param event The event which calls this method
|
||||
*/
|
||||
@EventHandler
|
||||
public void preventBarrierDrop(PlayerDropItemEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!playerService.getOpenNavigator().contains(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCloseNavigatorItem(player, event.getItemDrop().getItemStack())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given item is the item that is used to close the {@link NavigatorType#NEW} navigator.
|
||||
*
|
||||
* @param player The player used to get the item name
|
||||
* @param itemStack The item stack to check
|
||||
* @return {@code true} if the item is the navigator close item, {@code false} otherwise
|
||||
*/
|
||||
private boolean isCloseNavigatorItem(Player player, @Nullable ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
if (itemMeta == null || !itemMeta.hasDisplayName()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (XMaterial.matchXMaterial(itemStack) != XMaterial.BARRIER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return itemMeta.getDisplayName().equals(Messages.getString("barrier_item", player));
|
||||
}
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XPotion;
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldType;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Archive;
|
||||
import de.eintosti.buildsystem.config.Config.World.Unload;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.world.navigator.ArmorStandManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerChangedWorldListener implements Listener {
|
||||
|
||||
private final ArmorStandManager armorStandManager;
|
||||
private final PlayerServiceImpl playerManager;
|
||||
private final SettingsManager settingsManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
private final Map<UUID, GameMode> playerGamemode;
|
||||
private final Map<UUID, ItemStack[]> playerInventory;
|
||||
private final Map<UUID, ItemStack[]> playerArmor;
|
||||
|
||||
public PlayerChangedWorldListener(BuildSystemPlugin plugin) {
|
||||
this.armorStandManager = plugin.getArmorStandManager();
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
|
||||
this.playerGamemode = new HashMap<>();
|
||||
this.playerInventory = new HashMap<>();
|
||||
this.playerArmor = new HashMap<>();
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String worldName = player.getWorld().getName();
|
||||
|
||||
event.getPlayer().setAllowFlight(true);
|
||||
|
||||
BuildWorld oldWorld = worldStorage.getBuildWorld(event.getFrom());
|
||||
if (oldWorld != null && Unload.enabled) {
|
||||
oldWorld.getUnloader().resetUnloadTask();
|
||||
}
|
||||
|
||||
BuildWorld newWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (newWorld != null && !newWorld.getData().physics().get() && player.hasPermission("buildsystem.physics.message")) {
|
||||
Messages.sendMessage(player, "physics_deactivated_in_world", Map.entry("%world%", newWorld.getName()));
|
||||
}
|
||||
|
||||
removeOldNavigator(player);
|
||||
removeBuildMode(player);
|
||||
setGoldBlock(newWorld);
|
||||
checkWorldStatus(player);
|
||||
|
||||
if (settingsManager.getSettings(player).isScoreboard()) {
|
||||
playerManager.forceUpdateSidebar(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeOldNavigator(Player player) {
|
||||
armorStandManager.removeArmorStands(player);
|
||||
player.removePotionEffect(XPotion.BLINDNESS.get());
|
||||
}
|
||||
|
||||
private void removeBuildMode(Player player) {
|
||||
if (!playerManager.getBuildModePlayers().remove(player.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
CachedValues cachedValues = playerManager.getPlayerStorage().getBuildPlayer(player).getCachedValues();
|
||||
cachedValues.resetGameModeIfPresent(player);
|
||||
cachedValues.resetInventoryIfPresent(player);
|
||||
XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(player);
|
||||
Messages.sendMessage(player, "build_deactivated_self");
|
||||
}
|
||||
|
||||
private void setGoldBlock(@Nullable BuildWorld buildWorld) {
|
||||
if (buildWorld == null || buildWorld.getType() != BuildWorldType.VOID
|
||||
|| buildWorld.getData().status().get() != BuildWorldStatus.NOT_STARTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
World bukkitWorld = Bukkit.getWorld(buildWorld.getName());
|
||||
if (bukkitWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitWorld.getBlockAt(0, 64, 0).setType(Material.GOLD_BLOCK);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void checkWorldStatus(Player player) {
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
|
||||
if (this.playerGamemode.containsKey(playerUUID)) {
|
||||
player.setGameMode(this.playerGamemode.get(playerUUID));
|
||||
this.playerGamemode.remove(playerUUID);
|
||||
}
|
||||
|
||||
if (this.playerInventory.containsKey(playerUUID)) {
|
||||
playerInventory.clear();
|
||||
playerInventory.setContents(this.playerInventory.get(playerUUID));
|
||||
this.playerInventory.remove(playerUUID);
|
||||
}
|
||||
|
||||
if (this.playerArmor.containsKey(playerUUID)) {
|
||||
removeArmorContent(player);
|
||||
playerInventory.setArmorContents(this.playerArmor.get(playerUUID));
|
||||
this.playerArmor.remove(playerUUID);
|
||||
}
|
||||
|
||||
if (buildWorld.getData().status().get() == BuildWorldStatus.ARCHIVE) {
|
||||
this.playerGamemode.put(playerUUID, player.getGameMode());
|
||||
this.playerInventory.put(playerUUID, playerInventory.getContents());
|
||||
this.playerArmor.put(playerUUID, playerInventory.getArmorContents());
|
||||
|
||||
removeArmorContent(player);
|
||||
playerInventory.clear();
|
||||
setSpectatorMode(player);
|
||||
|
||||
if (Archive.vanish) {
|
||||
player.addPotionEffect(new PotionEffect(XPotion.INVISIBILITY.get(), PotionEffect.INFINITE_DURATION, 0, false, false), false);
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> pl.hidePlayer(player));
|
||||
}
|
||||
} else {
|
||||
player.removePotionEffect(XPotion.INVISIBILITY.get());
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> pl.showPlayer(player));
|
||||
}
|
||||
|
||||
playerManager.giveNavigator(player);
|
||||
}
|
||||
|
||||
private void setSpectatorMode(Player player) {
|
||||
// Checking if the game mode should be set to adventure mode on archive worlds
|
||||
if (Archive.changeGamemode) {
|
||||
player.setGameMode(Archive.worldGameMode);
|
||||
}
|
||||
player.setSaturation(20);
|
||||
player.setHealth(20);
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
}
|
||||
|
||||
private void removeArmorContent(Player player) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
playerInventory.setHelmet(null);
|
||||
playerInventory.setChestplate(null);
|
||||
playerInventory.setLeggings(null);
|
||||
playerInventory.setBoots(null);
|
||||
}
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Builder;
|
||||
import de.eintosti.buildsystem.event.player.PlayerInventoryClearEvent;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerCommandPreprocessListener implements Listener {
|
||||
|
||||
private static final Set<String> DISABLED_COMMANDS = Sets.newHashSet(
|
||||
"/worldedit",
|
||||
"/we",
|
||||
|
||||
// History Control
|
||||
"//undo",
|
||||
"//redo",
|
||||
"/clearhistory",
|
||||
|
||||
// Region Selection
|
||||
"//wand",
|
||||
"/toggleeditwand",
|
||||
"//sel",
|
||||
"//desel",
|
||||
"//pos1",
|
||||
"//pos2",
|
||||
"//0",
|
||||
"//1",
|
||||
"//2",
|
||||
"//hpos1",
|
||||
"//hpos2",
|
||||
"//chunk",
|
||||
"//expand",
|
||||
"//contract",
|
||||
"//outset",
|
||||
"//inset",
|
||||
"//count",
|
||||
"//distr",
|
||||
|
||||
// Region Operation
|
||||
"//set",
|
||||
"//replace",
|
||||
"//repl",
|
||||
"//overlay",
|
||||
"//walls",
|
||||
"//outline",
|
||||
"//center",
|
||||
"//smooth",
|
||||
"//deform",
|
||||
"//regen",
|
||||
"//hollow",
|
||||
"//move",
|
||||
"//stack",
|
||||
"//naturalize",
|
||||
"//line",
|
||||
"//curve",
|
||||
"//forest",
|
||||
"//flora",
|
||||
"//air",
|
||||
|
||||
// Clipboards and Schematics
|
||||
"//copy",
|
||||
"//cut",
|
||||
"//paste",
|
||||
"//rotate",
|
||||
"//flip",
|
||||
"//schematic",
|
||||
"//schem",
|
||||
"/clearclipboard",
|
||||
|
||||
// Generation
|
||||
"//generate",
|
||||
"//generatebiome",
|
||||
"//hcyl",
|
||||
"//cyl",
|
||||
"//sphere",
|
||||
"//hsphere",
|
||||
"//pyramid",
|
||||
"/forestgen",
|
||||
"/pumpkins",
|
||||
|
||||
// Utilities
|
||||
"/toggleplace",
|
||||
"//fill",
|
||||
"//fillr",
|
||||
"//drain",
|
||||
"//fixwater",
|
||||
"//fixlava",
|
||||
"/removeabove",
|
||||
"/removebelow",
|
||||
"/replacenear",
|
||||
"/removenear",
|
||||
"/snow",
|
||||
"/thaw",
|
||||
"/ex",
|
||||
"/butcher",
|
||||
"/remove",
|
||||
"/green",
|
||||
"//calc",
|
||||
|
||||
// Chunk Tools
|
||||
"/chunkinfo",
|
||||
"/listchunks",
|
||||
"/delchunks",
|
||||
|
||||
// Superpickaxe Tools
|
||||
"//",
|
||||
"/sp single",
|
||||
"/sp area",
|
||||
"/sp recur",
|
||||
|
||||
// General Tools
|
||||
"/tool",
|
||||
"/none",
|
||||
"/farwand",
|
||||
"/lrbuild",
|
||||
"/tree",
|
||||
"/deltree",
|
||||
"/repl",
|
||||
"/cycler",
|
||||
"/flood",
|
||||
|
||||
// Brushes
|
||||
"//brush",
|
||||
"//br",
|
||||
"/brush",
|
||||
"/br",
|
||||
"/size",
|
||||
"/mat",
|
||||
"/range",
|
||||
"/mask",
|
||||
"//gmask",
|
||||
|
||||
// Quick-Travel
|
||||
"/unstuck",
|
||||
"/ascend",
|
||||
"/asc",
|
||||
"/descend",
|
||||
"/desc",
|
||||
"/thru",
|
||||
"/jumpto",
|
||||
"/up",
|
||||
|
||||
// Snapshots
|
||||
"//restore",
|
||||
"/snapshot",
|
||||
|
||||
// Java Scriptings
|
||||
"//cs",
|
||||
"/.s",
|
||||
|
||||
// Biomes
|
||||
"/biomelist",
|
||||
"/biomels",
|
||||
"/biomeinfo",
|
||||
"//setbiome",
|
||||
|
||||
// Voxel Sniper
|
||||
"/vs",
|
||||
"/voxel",
|
||||
"/voxel_chunk",
|
||||
"/voxel_height",
|
||||
"/voxel_ink",
|
||||
"/voxel_ink_replace",
|
||||
"/voxel_list",
|
||||
"/voxel_replace",
|
||||
"/voxel_sniper",
|
||||
"/b",
|
||||
"/brush",
|
||||
"/brush_toolkit",
|
||||
"/d",
|
||||
"/default",
|
||||
"/goto",
|
||||
"/p",
|
||||
"/paint",
|
||||
"/perf",
|
||||
"/performer",
|
||||
"/v",
|
||||
"/vc",
|
||||
"/vchunk",
|
||||
"/vh",
|
||||
"/vi",
|
||||
"/vir",
|
||||
"/vl",
|
||||
"/vr--"
|
||||
);
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final SettingsManager settingsManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public PlayerCommandPreprocessListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String command = event.getMessage().split(" ")[0];
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (command.equalsIgnoreCase("/clear")) {
|
||||
ItemStack navigatorItem = InventoryUtils.createNavigatorItem(player);
|
||||
if (!player.getInventory().contains(navigatorItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingsManager.getSettings(player).isKeepNavigator()) {
|
||||
List<Integer> navigatorSlots = InventoryUtils.getNavigatorSlots(player);
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
PlayerInventoryClearEvent playerInventoryClearEvent = new PlayerInventoryClearEvent(player, navigatorSlots);
|
||||
Bukkit.getServer().getPluginManager().callEvent(playerInventoryClearEvent);
|
||||
}, 2L);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Builder.blockWorldEditNonBuilder) {
|
||||
if (!DISABLED_COMMANDS.contains(command)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
if (disableArchivedWorlds(buildWorld, player, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkBuilders(buildWorld, player, event);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean disableArchivedWorlds(BuildWorld buildWorld, Player player, PlayerCommandPreprocessEvent event) {
|
||||
if (buildWorld.getPermissions().canBypassBuildRestriction(player) || player.hasPermission("buildsystem.bypass.archive")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buildWorld.getData().status().get() == BuildWorldStatus.ARCHIVE) {
|
||||
event.setCancelled(true);
|
||||
Messages.sendMessage(player, "command_archive_world");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkBuilders(BuildWorld buildWorld, Player player, PlayerCommandPreprocessEvent event) {
|
||||
if (buildWorld.getPermissions().canBypassBuildRestriction(player) || player.hasPermission("buildsystem.bypass.builders")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (builders.isCreator(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildWorld.getData().buildersEnabled().get() && !builders.isBuilder(player)) {
|
||||
event.setCancelled(true);
|
||||
Messages.sendMessage(player, "command_not_builder");
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.event.player.PlayerInventoryClearEvent;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerInventoryClearListener implements Listener {
|
||||
|
||||
private final SettingsManager settingsManager;
|
||||
|
||||
public PlayerInventoryClearListener(BuildSystemPlugin plugin) {
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInventoryClear(PlayerInventoryClearEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.isKeepNavigator() || !player.hasPermission("buildsystem.navigator.item")) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack navigatorItem = InventoryUtils.createNavigatorItem(player);
|
||||
event.getNavigatorSlots().forEach(slot -> playerInventory.setItem(slot, navigatorItem));
|
||||
}
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XPotion;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.LogoutLocation;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Archive;
|
||||
import de.eintosti.buildsystem.player.LogoutLocationImpl;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.util.UUIDFetcher;
|
||||
import de.eintosti.buildsystem.util.UpdateChecker;
|
||||
import de.eintosti.buildsystem.world.SpawnManager;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerJoinListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerServiceImpl playerManager;
|
||||
private final SettingsManager settingsManager;
|
||||
private final SpawnManager spawnManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
public PlayerJoinListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.spawnManager = plugin.getSpawnManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void sendPlayerJoinMessage(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String message = Config.Messages.joinQuitMessages
|
||||
? Messages.getString("player_join", player, Map.entry("%player%", player.getName()))
|
||||
: null;
|
||||
event.setJoinMessage(message);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@SuppressWarnings("deprecation")
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
UUIDFetcher.cacheUser(player.getUniqueId(), player.getName());
|
||||
|
||||
BuildPlayer buildPlayer = playerManager.getPlayerStorage().createBuildPlayer(player);
|
||||
manageHidePlayer(player, buildPlayer);
|
||||
manageSettings(player, buildPlayer.getSettings());
|
||||
teleportToCorrectLocation(player, buildPlayer);
|
||||
playerManager.giveNavigator(player);
|
||||
|
||||
String worldName = player.getWorld().getName();
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
|
||||
if (buildWorld != null) {
|
||||
WorldData worldData = buildWorld.getData();
|
||||
if (!worldData.physics().get() && player.hasPermission("buildsystem.physics.message")) {
|
||||
Messages.sendMessage(player, "physics_deactivated_in_world", Map.entry("%world%", worldName));
|
||||
}
|
||||
|
||||
if (Archive.vanish && worldData.status().get() == BuildWorldStatus.ARCHIVE) {
|
||||
player.addPotionEffect(new PotionEffect(XPotion.INVISIBILITY.get(), PotionEffect.INFINITE_DURATION, 0, false, false), false);
|
||||
Bukkit.getOnlinePlayers().forEach(pl -> pl.hidePlayer(player));
|
||||
}
|
||||
}
|
||||
|
||||
if (player.hasPermission("buildsystem.updates")) {
|
||||
performUpdateCheck(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Teleports the player to the correct location.
|
||||
* <ul>
|
||||
* <li>If the spawn exists and {@link SettingsImpl#isSpawnTeleport()} is enabled for the player, the player will be teleported to the spawn</li>
|
||||
* <li>If the player has a {@link LogoutLocationImpl}, teleport to that location</li>
|
||||
* <li>Otherwise, do nothing</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param player The player to teleport
|
||||
* @param buildPlayer The build-player for the given player
|
||||
*/
|
||||
private void teleportToCorrectLocation(Player player, BuildPlayer buildPlayer) {
|
||||
if (buildPlayer.getSettings().isSpawnTeleport() && spawnManager.spawnExists()) {
|
||||
spawnManager.teleport(player);
|
||||
return;
|
||||
}
|
||||
|
||||
LogoutLocation logoutLocation = buildPlayer.getLogoutLocation();
|
||||
if (logoutLocation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(logoutLocation.worldName());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int delay = buildWorld.isLoaded() ? 0 : 20;
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
Location location = logoutLocation.location();
|
||||
if (location != null) {
|
||||
PaperLib.teleportAsync(player, location);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void manageHidePlayer(Player player, BuildPlayer buildPlayer) {
|
||||
// Hide all players to player
|
||||
if (buildPlayer.getSettings().isHidePlayers()) {
|
||||
Bukkit.getOnlinePlayers().forEach(player::hidePlayer);
|
||||
}
|
||||
|
||||
// Hide player from all players who have hidePlayers enabled
|
||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
||||
if (!settingsManager.getSettings(pl).isHidePlayers()) {
|
||||
continue;
|
||||
}
|
||||
pl.hidePlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates features for the player according to their {@link SettingsImpl}.
|
||||
*
|
||||
* @param player The player to activate the features for
|
||||
* @param settings The player's settings
|
||||
*/
|
||||
private void manageSettings(Player player, Settings settings) {
|
||||
if (settings.isNoClip()) {
|
||||
plugin.getNoClipManager().startNoClip(player);
|
||||
}
|
||||
|
||||
if (settings.isScoreboard()) {
|
||||
settingsManager.displayScoreboard(player);
|
||||
plugin.getPlayerService().forceUpdateSidebar(player);
|
||||
}
|
||||
|
||||
if (settings.isClearInventory()) {
|
||||
player.getInventory().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void performUpdateCheck(Player player) {
|
||||
if (!Config.Settings.updateChecker) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateChecker.init(plugin, BuildSystemPlugin.SPIGOT_ID)
|
||||
.requestUpdateCheck()
|
||||
.whenComplete((result, e) -> {
|
||||
if (result.requiresUpdate()) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Messages.getStringList("update_available", player).forEach(line ->
|
||||
stringBuilder.append(line
|
||||
.replace("%new_version%", result.getNewestVersion())
|
||||
.replace("%current_version%", plugin.getDescription().getVersion()))
|
||||
.append("\n"));
|
||||
player.sendMessage(stringBuilder.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.world.navigator.settings.NavigatorType;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerMoveListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerServiceImpl playerManager;
|
||||
private final SettingsManager settingsManager;
|
||||
|
||||
public PlayerMoveListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!playerManager.getOpenNavigator().contains(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.getNavigatorType().equals(NavigatorType.NEW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location to = event.getTo();
|
||||
if (to == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location from = event.getFrom();
|
||||
if (from.getBlockX() != to.getBlockX() || from.getBlockZ() != to.getBlockZ()) {
|
||||
Bukkit.getServer().getScheduler().runTaskLater(plugin, () -> playerManager.closeNewNavigator(player), 5L);
|
||||
}
|
||||
}
|
||||
}
|
||||
+108
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import de.eintosti.buildsystem.player.LogoutLocationImpl;
|
||||
import de.eintosti.buildsystem.player.PlayerServiceImpl;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerQuitListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerServiceImpl playerManager;
|
||||
private final SettingsManager settingsManager;
|
||||
|
||||
public PlayerQuitListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerManager = plugin.getPlayerService();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void sendPlayerQuitMessage(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String message = Config.Messages.joinQuitMessages
|
||||
? Messages.getString("player_quit", player, Map.entry("%player%", player.getName()))
|
||||
: null;
|
||||
event.setQuitMessage(message);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
playerManager.closeNewNavigator(player);
|
||||
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (settings.isNoClip()) {
|
||||
plugin.getNoClipManager().stopNoClip(player.getUniqueId());
|
||||
}
|
||||
|
||||
if (settings.isScoreboard()) {
|
||||
settingsManager.hideScoreboard(player);
|
||||
}
|
||||
|
||||
if (settings.isClearInventory()) {
|
||||
player.getInventory().clear();
|
||||
}
|
||||
|
||||
BuildPlayer buildPlayer = playerManager.getPlayerStorage().getBuildPlayer(player);
|
||||
buildPlayer.setLogoutLocation(new LogoutLocationImpl(
|
||||
player.getWorld().getName(),
|
||||
player.getLocation()
|
||||
));
|
||||
|
||||
CachedValues cachedValues = buildPlayer.getCachedValues();
|
||||
cachedValues.resetGameModeIfPresent(player);
|
||||
cachedValues.resetInventoryIfPresent(player);
|
||||
playerManager.getBuildModePlayers().remove(player.getUniqueId());
|
||||
|
||||
manageHidePlayer(player);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void manageHidePlayer(Player player) {
|
||||
// Show all hidden players to player
|
||||
if (settingsManager.getSettings(player).isHidePlayers()) {
|
||||
Bukkit.getOnlinePlayers().forEach(player::showPlayer);
|
||||
}
|
||||
|
||||
// Show player to all players who had him/her hidden
|
||||
for (Player pl : Bukkit.getOnlinePlayers()) {
|
||||
if (!settingsManager.getSettings(pl).isHidePlayers()) {
|
||||
continue;
|
||||
}
|
||||
pl.showPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.world.SpawnManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerRespawnListener implements Listener {
|
||||
|
||||
private final SettingsManager settingsManager;
|
||||
private final SpawnManager spawnManager;
|
||||
|
||||
public PlayerRespawnListener(BuildSystemPlugin plugin) {
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.spawnManager = plugin.getSpawnManager();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
|
||||
if (settings.isSpawnTeleport() && spawnManager.spawnExists()) {
|
||||
event.setRespawnLocation(spawnManager.getSpawn());
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.storage.PlayerStorage;
|
||||
import de.eintosti.buildsystem.api.storage.WorldStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerTeleportListener implements Listener {
|
||||
|
||||
private final PlayerStorage playerStorage;
|
||||
private final WorldStorage worldStorage;
|
||||
|
||||
public PlayerTeleportListener(BuildSystemPlugin plugin) {
|
||||
this.playerStorage = plugin.getPlayerService().getPlayerStorage();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (event.getCause() != PlayerTeleportEvent.TeleportCause.UNKNOWN) {
|
||||
playerStorage.getBuildPlayer(player).setPreviousLocation(event.getFrom());
|
||||
}
|
||||
|
||||
Location to = event.getTo();
|
||||
if (to == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
World toWorld = to.getWorld();
|
||||
if (toWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(toWorld);
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Users can always teleport to the main server world
|
||||
if (Bukkit.getWorlds().getFirst().equals(toWorld)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buildWorld.getPermissions().canEnter(player)) {
|
||||
Messages.sendMessage(player, "worlds_tp_entry_forbidden");
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+425
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XBlock;
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import com.cryptomorin.xseries.XTag;
|
||||
import com.google.common.collect.Sets;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.player.settings.Settings;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builder;
|
||||
import de.eintosti.buildsystem.api.world.builder.Builders;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.config.Config;
|
||||
import de.eintosti.buildsystem.player.customblock.CustomBlockManager;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.util.DirectionUtil;
|
||||
import de.eintosti.buildsystem.util.inventory.MaterialUtils;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.MultipleFacing;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.block.data.type.Slab;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SettingsInteractListener implements Listener {
|
||||
|
||||
private static final EnumSet<XMaterial> OTHER_PLANTS = Sets.newEnumSet(Sets.newHashSet(
|
||||
XMaterial.TORCHFLOWER, XMaterial.PITCHER_PLANT, XMaterial.LILY_PAD, XMaterial.PINK_PETALS,
|
||||
XMaterial.BROWN_MUSHROOM, XMaterial.RED_MUSHROOM, XMaterial.CRIMSON_FUNGUS, XMaterial.WARPED_FUNGUS,
|
||||
XMaterial.SHORT_GRASS, XMaterial.FERN, XMaterial.DEAD_BUSH, XMaterial.LARGE_FERN, XMaterial.TALL_GRASS,
|
||||
XMaterial.NETHER_SPROUTS, XMaterial.WARPED_ROOTS, XMaterial.CRIMSON_ROOTS, XMaterial.SUGAR_CANE, XMaterial.BAMBOO,
|
||||
XMaterial.BIG_DRIPLEAF, XMaterial.SMALL_DRIPLEAF, XMaterial.SEAGRASS, XMaterial.SWEET_BERRIES
|
||||
), XMaterial.class);
|
||||
|
||||
private final CustomBlockManager customBlockManager;
|
||||
private final SettingsManager settingsManager;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
|
||||
private final Set<UUID> cachePlayers;
|
||||
|
||||
public SettingsInteractListener(BuildSystemPlugin plugin) {
|
||||
this.customBlockManager = plugin.getCustomBlockManager();
|
||||
this.settingsManager = plugin.getSettingsManager();
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
|
||||
this.cachePlayers = new HashSet<>();
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void manageIronDoorSetting(PlayerInteractEvent event) {
|
||||
if (!isValid(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getHand() != EquipmentSlot.HAND) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (player.isSneaking() || event.getAction() != Action.RIGHT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.isOpenTrapDoors()) {
|
||||
return;
|
||||
}
|
||||
|
||||
XMaterial material = XMaterial.matchXMaterial(block.getType());
|
||||
if (material != XMaterial.IRON_DOOR && material != XMaterial.IRON_TRAPDOOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
Openable openable = (Openable) block.getBlockData();
|
||||
openable.setOpen(!openable.isOpen());
|
||||
block.setBlockData(openable);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void manageSlabSetting(PlayerInteractEvent event) {
|
||||
if (!isValid(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Action action = event.getAction();
|
||||
if (action != Action.LEFT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.isSlabBreaking()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null || !(block.getBlockData() instanceof Slab slab) || slab.getType() != Slab.Type.DOUBLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
if (isTopHalf(player)) {
|
||||
slab.setType(Slab.Type.BOTTOM);
|
||||
} else {
|
||||
slab.setType(Slab.Type.TOP);
|
||||
}
|
||||
|
||||
block.setBlockData(slab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the player's ray trace hit position is on the top half of a block.
|
||||
*
|
||||
* @param player The {@link Player} to check.
|
||||
* @return {@code true} if the player's hit position is on the top half of a block, {@code false} otherwise.
|
||||
*/
|
||||
public boolean isTopHalf(Player player) {
|
||||
RayTraceResult result = player.rayTraceBlocks(6);
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
return Math.abs(result.getHitPosition().getY() % 1) < 0.5;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void managePlacePlantsSetting(PlayerInteractEvent event) {
|
||||
if (!isValid(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null || event.getAction() != Action.RIGHT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = settingsManager.getSettings(event.getPlayer());
|
||||
if (!settings.isPlacePlants()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
XMaterial xMaterial = XMaterial.matchXMaterial(itemStack.getType());
|
||||
if (!XTag.FLOWERS.isTagged(xMaterial)
|
||||
&& !XTag.REPLACEABLE_PLANTS.isTagged(xMaterial)
|
||||
&& !XTag.ALIVE_CORAL_PLANTS.isTagged(xMaterial)
|
||||
&& !XTag.DEAD_CORAL_PLANTS.isTagged(xMaterial)
|
||||
&& !XTag.SAPLINGS.isTagged(xMaterial)
|
||||
&& !OTHER_PLANTS.contains(xMaterial)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
Block adjacent = block.getRelative(event.getBlockFace());
|
||||
|
||||
switch (xMaterial) {
|
||||
case SWEET_BERRIES:
|
||||
adjacent.setType(XMaterial.SWEET_BERRY_BUSH.get());
|
||||
break;
|
||||
case VINE:
|
||||
BlockFace toPlace = event.getBlockFace().getOppositeFace();
|
||||
if (toPlace == BlockFace.DOWN) { // Cannot place vines facing down
|
||||
break;
|
||||
}
|
||||
adjacent.setType(xMaterial.get());
|
||||
MultipleFacing multipleFacing = (MultipleFacing) adjacent.getBlockData();
|
||||
Arrays.stream(DirectionUtil.BLOCK_SIDES).forEach(blockFace -> multipleFacing.setFace(blockFace, blockFace == toPlace));
|
||||
adjacent.setBlockData(multipleFacing);
|
||||
break;
|
||||
default:
|
||||
adjacent.setType(xMaterial.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void manageInstantPlaceSignsSetting(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || !isValid(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.isInstantPlaceSigns()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material material = itemStack.getType();
|
||||
XMaterial xMaterial = XMaterial.matchXMaterial(itemStack);
|
||||
if (!XTag.SIGNS.isTagged(xMaterial) && !XTag.HANGING_SIGNS.isTagged(xMaterial)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block clickedBlock = event.getClickedBlock();
|
||||
BlockFace blockFace = event.getBlockFace();
|
||||
if (clickedBlock == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block adjacent = clickedBlock.getRelative(blockFace);
|
||||
if (adjacent.getType() != XMaterial.AIR.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
event.setCancelled(true);
|
||||
|
||||
boolean isHangingSign = XTag.HANGING_SIGNS.isTagged(xMaterial);
|
||||
|
||||
switch (blockFace) {
|
||||
case UP -> {
|
||||
if (isHangingSign) {
|
||||
return;
|
||||
}
|
||||
adjacent.setType(material);
|
||||
customBlockManager.rotateBlock(adjacent, DirectionUtil.getPlayerDirection(player).getOppositeFace());
|
||||
}
|
||||
case DOWN -> {
|
||||
if (!isHangingSign) {
|
||||
return;
|
||||
}
|
||||
adjacent.setType(material);
|
||||
customBlockManager.rotateBlock(adjacent, getHangingSignDirection(event));
|
||||
}
|
||||
case NORTH, EAST, SOUTH, WEST -> {
|
||||
String woodType = xMaterial.name()
|
||||
.replace("_HANGING", "") // Replace hanging if present
|
||||
.replace("_SIGN", ""); // Get wood type
|
||||
String block = isHangingSign ? "_WALL_HANGING_SIGN" : "_WALL_SIGN";
|
||||
BlockFace facing = isHangingSign ? getHangingSignDirection(event) : blockFace;
|
||||
XMaterial.matchXMaterial(woodType + block).ifPresent(value -> adjacent.setType(value.get()));
|
||||
customBlockManager.rotateBlock(adjacent, facing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BlockFace getHangingSignDirection(PlayerInteractEvent event) {
|
||||
BlockFace clickedFace = event.getBlockFace();
|
||||
BlockFace playerFacing = DirectionUtil.getCardinalDirection(event.getPlayer()).getOppositeFace();
|
||||
if (clickedFace != playerFacing && clickedFace != playerFacing.getOppositeFace()) {
|
||||
return playerFacing;
|
||||
}
|
||||
return (clickedFace == BlockFace.NORTH || clickedFace == BlockFace.SOUTH) ? BlockFace.EAST : BlockFace.SOUTH;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void manageDisabledInteractSetting(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || !isValid(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings = settingsManager.getSettings(player);
|
||||
if (!settings.isDisableInteract()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null || !MaterialUtils.isInteractable(XMaterial.matchXMaterial(block.getType()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material material = itemStack.getType();
|
||||
XMaterial xMaterial = XMaterial.matchXMaterial(material);
|
||||
if (xMaterial == Config.Settings.Builder.worldEditWand) {
|
||||
return;
|
||||
}
|
||||
|
||||
cachePlayers.add(player.getUniqueId());
|
||||
event.setCancelled(true);
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
event.setUseInteractedBlock(Event.Result.DENY);
|
||||
|
||||
if (XTag.SIGNS.isTagged(xMaterial) && event.getBlockFace() != BlockFace.UP) {
|
||||
String[] splitMaterial = material.toString().split("_");
|
||||
material = Material.valueOf(splitMaterial[0] + "_WALL_SIGN");
|
||||
}
|
||||
|
||||
if (!material.isBlock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block adjacent = block.getRelative(event.getBlockFace());
|
||||
adjacent.setType(material);
|
||||
XBlock.setColor(adjacent, DyeColor.getByWoolData((byte) itemStack.getDurability()));
|
||||
|
||||
customBlockManager.rotateBlock(adjacent, DirectionUtil.getBlockDirection(player, false));
|
||||
|
||||
EquipmentSlot hand = event.getHand();
|
||||
if (hand == null) {
|
||||
hand = EquipmentSlot.HAND;
|
||||
}
|
||||
|
||||
BlockPlaceEvent blockPlaceEvent = new BlockPlaceEvent(adjacent, adjacent.getState(), block, itemStack, player, true, hand);
|
||||
Bukkit.getServer().getPluginManager().callEvent(blockPlaceEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not every player can always interact with the {@link BuildWorld} they are in.
|
||||
* <p>
|
||||
* Reasons an interaction could be canceled:
|
||||
* <ul>
|
||||
* <li>The world has its {@link BuildWorldStatus} set to archive</li>
|
||||
* <li>The world has a setting enabled which disallows certain events</li>
|
||||
* <li>The world only allows {@link Builder}s to build and the player is not such a builder</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* However, a player can override these reasons if:
|
||||
* <ul>
|
||||
* <li>The player has the permission <b>buildsystem.admin</b></li>
|
||||
* <li>The player has the permission <b>buildsystem.bypass.archive</b></li>
|
||||
* <li>The player has used <b>/build</b> to enter build-mode</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param event the event which was called by the world manipulation
|
||||
* @return if the interaction with the world is valid
|
||||
*/
|
||||
private boolean isValid(PlayerInteractEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld().getName());
|
||||
if (buildWorld == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buildWorld.getPermissions().canBypassBuildRestriction(player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldData worldData = buildWorld.getData();
|
||||
if (worldData.status().get() == BuildWorldStatus.ARCHIVE && !player.hasPermission("buildsystem.bypass.archive")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!worldData.blockPlacement().get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Builders builders = buildWorld.getBuilders();
|
||||
if (buildWorld.getData().buildersEnabled().get()
|
||||
&& !builders.isBuilder(player)
|
||||
&& !player.hasPermission("buildsystem.bypass.builders")) {
|
||||
return builders.isCreator(player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop {@link Player} from opening {@link Inventory} because the event should be canceled as it was fired due to an interaction caused in
|
||||
* {@link SettingsInteractListener#manageDisabledInteractSetting}
|
||||
*/
|
||||
@EventHandler
|
||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||
if (cachePlayers.remove(event.getPlayer().getUniqueId())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.util.color.ColorAPI;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class SignChangeListener implements Listener {
|
||||
|
||||
public SignChangeListener(BuildSystemPlugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSignChange(SignChangeEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!player.hasPermission("buildsystem.color.sign")) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < event.getLines().length; i++) {
|
||||
String line = event.getLine(i);
|
||||
if (line == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String coloredLine = ChatColor.translateAlternateColorCodes('&', ColorAPI.process(line));
|
||||
event.setLine(i, coloredLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -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.listener;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.config.Config.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.weather.ThunderChangeEvent;
|
||||
import org.bukkit.event.weather.WeatherChangeEvent;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class WeatherChangeListener implements Listener {
|
||||
|
||||
public WeatherChangeListener(BuildSystemPlugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onWeatherChange(WeatherChangeEvent event) {
|
||||
if (!World.lockWeather) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.toWeatherState()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onThunderChange(ThunderChangeEvent event) {
|
||||
if (!World.lockWeather) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.toThunderState()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.event.EventDispatcher;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Only register if axiom is available
|
||||
*/
|
||||
@NullMarked
|
||||
public class WorldManipulateByAxiomListener implements Listener {
|
||||
|
||||
private final EventDispatcher dispatcher;
|
||||
|
||||
/**
|
||||
* Creates a new {@link WorldManipulateByAxiomListener} instance.
|
||||
*
|
||||
* @param plugin plugin to register.
|
||||
*/
|
||||
public WorldManipulateByAxiomListener(BuildSystemPlugin plugin) {
|
||||
this.dispatcher = new EventDispatcher(plugin.getWorldService().getWorldStorage());
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
plugin.getLogger().info("Axiom build-world manipulation prevention has been enabled.");
|
||||
}
|
||||
|
||||
@EventHandler()
|
||||
public void onWorldModification(AxiomModifyWorldEvent event) {
|
||||
// I don't know if it is possible. Just to be safe.
|
||||
if (!event.getPlayer().getWorld().equals(event.getWorld())) {
|
||||
event.setCancelled(true);
|
||||
throw new IllegalStateException("Player modifies a world in which he is not present! The event got cancelled for safety reasons.");
|
||||
}
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(event.getPlayer(), event);
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.api.data.Type;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.BuildWorldStatus;
|
||||
import de.eintosti.buildsystem.api.world.data.WorldData;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Builder;
|
||||
import de.eintosti.buildsystem.event.EventDispatcher;
|
||||
import de.eintosti.buildsystem.event.world.BuildWorldManipulationEvent;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class WorldManipulateListener implements Listener {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final WorldStorageImpl worldStorage;
|
||||
private final EventDispatcher dispatcher;
|
||||
|
||||
public WorldManipulateListener(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
this.dispatcher = new EventDispatcher(worldStorage);
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(event.getPlayer(), event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(event.getPlayer(), event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Player player) || !(event.getEntity() instanceof ArmorStand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(player, event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerArmorStandManipulate(PlayerArmorStandManipulateEvent event) {
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(event.getPlayer(), event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (itemStack != null && itemStack.getType() == Builder.worldEditWand.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
BuildWorld buildWorld = worldStorage.getBuildWorld(player.getWorld());
|
||||
if (buildWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.dispatchManipulationEventIfPlayerInBuildWorld(player, event);
|
||||
|
||||
if (!buildWorld.getData().physics().get() && event.getClickedBlock() != null) {
|
||||
if (event.getAction() == Action.PHYSICAL && event.getClickedBlock().getType() == XMaterial.FARMLAND.get()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onWorldManipulation(BuildWorldManipulationEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
BuildWorld buildWorld = event.getBuildWorld();
|
||||
WorldData worldData = buildWorld.getData();
|
||||
|
||||
Cancellable parentEvent = event.getParentEvent();
|
||||
boolean canModify = buildWorld.getPermissions().canModify(player, getRelatedWorldSetting(parentEvent, worldData));
|
||||
if (!canModify) {
|
||||
parentEvent.setCancelled(true);
|
||||
denyPlayerInteraction(event);
|
||||
return;
|
||||
}
|
||||
|
||||
worldData.lastEdited().set(System.currentTimeMillis());
|
||||
updateStatus(worldData, player);
|
||||
}
|
||||
|
||||
private Type<Boolean> getRelatedWorldSetting(Cancellable event, WorldData data) {
|
||||
return switch (event) {
|
||||
case BlockBreakEvent ignored -> data.blockBreaking();
|
||||
case BlockPlaceEvent ignored -> data.blockPlacement();
|
||||
case PlayerInteractEvent ignored -> data.blockInteractions();
|
||||
default -> throw new IllegalStateException("Unexpected event type: " + event.getClass().getName());
|
||||
};
|
||||
}
|
||||
|
||||
private void denyPlayerInteraction(Event event) {
|
||||
if (event instanceof PlayerInteractEvent interactEvent) {
|
||||
interactEvent.setUseItemInHand(Event.Result.DENY);
|
||||
interactEvent.setUseInteractedBlock(Event.Result.DENY);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatus(WorldData worldData, Player player) {
|
||||
if (worldData.status().get() == BuildWorldStatus.NOT_STARTED) {
|
||||
worldData.status().set(BuildWorldStatus.IN_PROGRESS);
|
||||
plugin.getPlayerService().forceUpdateSidebar(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.player;
|
||||
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.player.LogoutLocation;
|
||||
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.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class BuildPlayerImpl implements BuildPlayer {
|
||||
|
||||
private final UUID uuid;
|
||||
private final Settings settings;
|
||||
private final CachedValues cachedValues;
|
||||
|
||||
@Nullable
|
||||
private LogoutLocation logoutLocation;
|
||||
@Nullable
|
||||
private Location previousLocation;
|
||||
@Nullable
|
||||
private NavigatorCategory lastLookedAt;
|
||||
|
||||
public BuildPlayerImpl(UUID uuid, Settings settings) {
|
||||
this.uuid = uuid;
|
||||
this.settings = settings;
|
||||
this.cachedValues = new CachedValuesImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedValues getCachedValues() {
|
||||
return cachedValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public LogoutLocation getLogoutLocation() {
|
||||
return logoutLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogoutLocation(@Nullable LogoutLocation logoutLocation) {
|
||||
this.logoutLocation = logoutLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Location getPreviousLocation() {
|
||||
return previousLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreviousLocation(@Nullable Location location) {
|
||||
this.previousLocation = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public NavigatorCategory getLastLookedAt() {
|
||||
return lastLookedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastLookedAt(@Nullable NavigatorCategory type) {
|
||||
this.lastLookedAt = type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.player;
|
||||
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import java.util.List;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class CachedValuesImpl implements CachedValues {
|
||||
|
||||
@Nullable
|
||||
private GameMode gameMode;
|
||||
@Nullable
|
||||
private List<ItemStack> inventory;
|
||||
@Nullable
|
||||
private Float walkSpeed;
|
||||
@Nullable
|
||||
private Float flySpeed;
|
||||
|
||||
@Override
|
||||
public void saveGameMode(GameMode gameMode) {
|
||||
this.gameMode = gameMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetGameModeIfPresent(Player player) {
|
||||
if (this.gameMode == null) {
|
||||
return;
|
||||
}
|
||||
player.setGameMode(gameMode);
|
||||
this.gameMode = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveInventory(ItemStack[] inventory) {
|
||||
this.inventory = List.of(inventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetInventoryIfPresent(Player player) {
|
||||
if (this.inventory == null) {
|
||||
return;
|
||||
}
|
||||
player.getInventory().clear();
|
||||
player.getInventory().setContents(this.inventory.toArray(new ItemStack[0]));
|
||||
this.inventory = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWalkSpeed(float walkSpeed) {
|
||||
this.walkSpeed = walkSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetWalkSpeedIfPresent(Player player) {
|
||||
if (this.walkSpeed == null) {
|
||||
return;
|
||||
}
|
||||
player.setWalkSpeed(walkSpeed);
|
||||
this.walkSpeed = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFlySpeed(float flySpeed) {
|
||||
this.flySpeed = flySpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetFlySpeedIfPresent(Player player) {
|
||||
if (this.flySpeed == null) {
|
||||
return;
|
||||
}
|
||||
player.setFlySpeed(flySpeed);
|
||||
this.flySpeed = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCachedValues(Player player) {
|
||||
resetGameModeIfPresent(player);
|
||||
resetInventoryIfPresent(player);
|
||||
resetWalkSpeedIfPresent(player);
|
||||
resetFlySpeedIfPresent(player);
|
||||
}
|
||||
}
|
||||
@@ -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.player;
|
||||
|
||||
import de.eintosti.buildsystem.api.player.LogoutLocation;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class LogoutLocationImpl implements LogoutLocation {
|
||||
|
||||
private final String worldName;
|
||||
private final double x, y, z;
|
||||
private final float yaw, pitch;
|
||||
|
||||
public LogoutLocationImpl(String worldName, Location location) {
|
||||
this.worldName = worldName;
|
||||
this.x = location.getX();
|
||||
this.y = location.getY();
|
||||
this.z = location.getZ();
|
||||
this.yaw = location.getYaw();
|
||||
this.pitch = location.getPitch();
|
||||
}
|
||||
|
||||
public LogoutLocationImpl(String worldName, double x, double y, double z, float yaw, float pitch) {
|
||||
this.worldName = worldName;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String worldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Location location() {
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return worldName + ":" + x + ":" + y + ":" + z + ":" + yaw + ":" + pitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* 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.player;
|
||||
|
||||
import com.cryptomorin.xseries.XMaterial;
|
||||
import com.cryptomorin.xseries.XPotion;
|
||||
import com.cryptomorin.xseries.XSound;
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import de.eintosti.buildsystem.Messages;
|
||||
import de.eintosti.buildsystem.api.player.BuildPlayer;
|
||||
import de.eintosti.buildsystem.api.player.CachedValues;
|
||||
import de.eintosti.buildsystem.api.player.PlayerService;
|
||||
import de.eintosti.buildsystem.api.storage.PlayerStorage;
|
||||
import de.eintosti.buildsystem.api.world.BuildWorld;
|
||||
import de.eintosti.buildsystem.api.world.data.Visibility;
|
||||
import de.eintosti.buildsystem.api.world.display.NavigatorCategory;
|
||||
import de.eintosti.buildsystem.config.Config.Settings;
|
||||
import de.eintosti.buildsystem.config.Config.Settings.Navigator;
|
||||
import de.eintosti.buildsystem.config.Config.World.Limits;
|
||||
import de.eintosti.buildsystem.player.settings.SettingsManager;
|
||||
import de.eintosti.buildsystem.storage.PlayerStorageImpl;
|
||||
import de.eintosti.buildsystem.storage.WorldStorageImpl;
|
||||
import de.eintosti.buildsystem.storage.factory.PlayerStorageFactory;
|
||||
import de.eintosti.buildsystem.util.inventory.InventoryUtils;
|
||||
import de.eintosti.buildsystem.world.navigator.ArmorStandManager;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.logging.Level;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerServiceImpl implements PlayerService {
|
||||
|
||||
private final BuildSystemPlugin plugin;
|
||||
private final PlayerStorageImpl playerStorage;
|
||||
|
||||
private final Set<Player> openNavigator;
|
||||
private final Set<UUID> buildModePlayers;
|
||||
|
||||
public PlayerServiceImpl(BuildSystemPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerStorage = new PlayerStorageFactory(plugin).createStorage();
|
||||
|
||||
this.openNavigator = new HashSet<>();
|
||||
this.buildModePlayers = new HashSet<>();
|
||||
|
||||
initEntityChecker();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.playerStorage.loadPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerStorage getPlayerStorage() {
|
||||
return playerStorage;
|
||||
}
|
||||
|
||||
public Set<Player> getOpenNavigator() {
|
||||
return openNavigator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getBuildModePlayers() {
|
||||
return buildModePlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInBuildMode(Player player) {
|
||||
return buildModePlayers.contains(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreateWorld(Player player, Visibility visibility) {
|
||||
boolean showPrivateWorlds = visibility == Visibility.PRIVATE;
|
||||
WorldStorageImpl worldStorage = plugin.getWorldService().getWorldStorage();
|
||||
|
||||
int maxWorldAmountConfig = showPrivateWorlds
|
||||
? Limits.privateWorlds
|
||||
: Limits.publicWorlds;
|
||||
if (maxWorldAmountConfig >= 0 && worldStorage.getBuildWorlds().size() >= maxWorldAmountConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int maxWorldAmountPlayer = getMaxWorlds(player, showPrivateWorlds ? Visibility.PRIVATE : Visibility.PUBLIC);
|
||||
return maxWorldAmountPlayer < 0 || worldStorage.getBuildWorldsCreatedByPlayer(player, visibility).size() < maxWorldAmountPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWorlds(Player player, Visibility visibility) {
|
||||
int max = -1;
|
||||
if (player.hasPermission(BuildSystemPlugin.ADMIN_PERMISSION)) {
|
||||
return max;
|
||||
}
|
||||
|
||||
for (PermissionAttachmentInfo permission : player.getEffectivePermissions()) {
|
||||
String permissionString = permission.getPermission();
|
||||
String[] splitPermission = permissionString.split("\\.");
|
||||
|
||||
if (splitPermission.length != 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!splitPermission[1].equalsIgnoreCase("create")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!splitPermission[2].equalsIgnoreCase(visibility.name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String amountString = splitPermission[3];
|
||||
if (amountString.equals("*")) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
int amount = Integer.parseInt(amountString);
|
||||
if (amount > max) {
|
||||
max = amount;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "Invalid max. world amount (must be int)", e);
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an update of the sidebar for all players in the given {@link BuildWorld}.
|
||||
*
|
||||
* @param buildWorld The world for which the sidebar should be updated
|
||||
*/
|
||||
public void forceUpdateSidebar(BuildWorld buildWorld) {
|
||||
if (!Settings.scoreboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
World bukkitWorld = Bukkit.getWorld(buildWorld.getName());
|
||||
if (bukkitWorld == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitWorld.getPlayers().forEach(this::forceUpdateSidebar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an update of the sidebar for a specific player.
|
||||
*
|
||||
* @param player The player for whom the sidebar should be updated
|
||||
*/
|
||||
public void forceUpdateSidebar(Player player) {
|
||||
SettingsManager settingsManager = plugin.getSettingsManager();
|
||||
if (!Settings.scoreboard || !settingsManager.getSettings(player).isScoreboard()) {
|
||||
return;
|
||||
}
|
||||
settingsManager.updateScoreboard(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the navigator item to the player if they have the permission and do not already have it in their inventory.
|
||||
*
|
||||
* @param player The player to whom the navigator item should be given
|
||||
*/
|
||||
public void giveNavigator(Player player) {
|
||||
if (!Navigator.giveItemOnJoin || !player.hasPermission("buildsystem.navigator.item") || InventoryUtils.hasNavigator(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack navigatorItem = InventoryUtils.createNavigatorItem(player);
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack slot8 = playerInventory.getItem(8);
|
||||
|
||||
if (slot8 == null || slot8.getType() == XMaterial.AIR.get()) {
|
||||
playerInventory.setItem(8, navigatorItem);
|
||||
} else {
|
||||
playerInventory.addItem(navigatorItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the entity checker that periodically checks if players with open navigators are looking at armor stands representing navigator categories.
|
||||
*/
|
||||
private void initEntityChecker() {
|
||||
Bukkit.getScheduler().runTaskTimer(plugin, this::checkForAmorStandNavigator, 0L, 2L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if players with open navigators are looking at armor stands that represent a {@link NavigatorCategory} and updates their UI accordingly.
|
||||
* <p>
|
||||
* This method iterates through all players who have the navigator open and determines if they are looking at an armor stand within the valid look height range. When a player
|
||||
* looks at a different navigator category or stops looking at one entirely, appropriate UI updates are sent.
|
||||
*/
|
||||
private void checkForAmorStandNavigator() {
|
||||
for (Player player : openNavigator) {
|
||||
if (!(getTargetEntity(player) instanceof ArmorStand armorStand)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BuildPlayer buildPlayer = playerStorage.getBuildPlayer(player);
|
||||
if (isLookingAtArmorStandHead(player, armorStand)) {
|
||||
NavigatorCategory category = ArmorStandManager.matchNavigatorCategory(armorStand);
|
||||
sendTypeInfo(player, category);
|
||||
} else {
|
||||
sendTypeInfo(player, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is looking at the head of an armor stand within a 3-block radius.
|
||||
*
|
||||
* @param player The player to check
|
||||
* @param armorStand The armor stand to check against
|
||||
* @return {@code true} if the player is looking at the armor stand's head, {@code false} otherwise
|
||||
*/
|
||||
private boolean isLookingAtArmorStandHead(Player player, ArmorStand armorStand) {
|
||||
Location eyeLocation = player.getEyeLocation();
|
||||
Vector direction = eyeLocation.getDirection().normalize();
|
||||
|
||||
Location standEyeLocation = armorStand.getEyeLocation().clone();
|
||||
double boxHalfSize = 0.3;
|
||||
|
||||
double minX = standEyeLocation.getX() - boxHalfSize;
|
||||
double maxX = standEyeLocation.getX() + boxHalfSize;
|
||||
double minY = standEyeLocation.getY() - boxHalfSize;
|
||||
double maxY = standEyeLocation.getY() + boxHalfSize;
|
||||
double minZ = standEyeLocation.getZ() - boxHalfSize;
|
||||
double maxZ = standEyeLocation.getZ() + boxHalfSize;
|
||||
|
||||
for (double distance = 0; distance <= 3; distance += 0.05) {
|
||||
Vector point = eyeLocation.toVector().add(direction.clone().multiply(distance));
|
||||
|
||||
if (point.getX() >= minX && point.getX() <= maxX
|
||||
&& point.getY() >= minY && point.getY() <= maxY
|
||||
&& point.getZ() >= minZ && point.getZ() <= maxZ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the closest target entity that the player is looking at within a 3-block radius.
|
||||
*
|
||||
* @param entity The entity from which to find the target
|
||||
* @return The closest target entity that the given entity is looking at, or {@code null} if no suitable target is found
|
||||
*/
|
||||
@Nullable
|
||||
private Entity getTargetEntity(Entity entity) {
|
||||
return getTarget(entity, entity.getNearbyEntities(3, 3, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the closest target entity from a given entity collection within a specified threshold.
|
||||
*
|
||||
* @param entity The entity from which to find the target
|
||||
* @param entities The collection of entities to search through
|
||||
* @param <T> The type of entity to search for, which must extend {@link Entity}
|
||||
* @return The closest target entity that the given entity is looking at, or {@code null} if no suitable target is found
|
||||
*/
|
||||
@Nullable
|
||||
@Contract("null, _ -> null")
|
||||
private <T extends Entity> T getTarget(@Nullable Entity entity, Iterable<T> entities) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
T target = null;
|
||||
final Location entityLocation = entity.getLocation();
|
||||
final double threshold = 0.5;
|
||||
|
||||
for (T other : entities) {
|
||||
final Location otherLocation = other.getLocation();
|
||||
final Vector vector = otherLocation.toVector().subtract(entityLocation.toVector());
|
||||
|
||||
if (entityLocation.getDirection().normalize().crossProduct(vector).lengthSquared() < threshold
|
||||
&& vector.normalize().dot(entityLocation.getDirection().normalize()) >= 0) {
|
||||
if (target == null
|
||||
|| target.getLocation().distanceSquared(entityLocation) > otherLocation.distanceSquared(entityLocation)) {
|
||||
target = other;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends type information to the player based on the {@link NavigatorCategory} they are looking at in the navigator.
|
||||
*
|
||||
* @param player The player to whom the type information should be sent
|
||||
* @param category The {@link NavigatorCategory} that the player is looking at, or {@code null} if they are not looking at any category
|
||||
*/
|
||||
private void sendTypeInfo(Player player, @Nullable NavigatorCategory category) {
|
||||
BuildPlayer buildPlayer = playerStorage.getBuildPlayer(player);
|
||||
if (category == null) {
|
||||
buildPlayer.setLastLookedAt(null);
|
||||
displayActionBarMessage(player, "§0");
|
||||
return;
|
||||
}
|
||||
|
||||
NavigatorCategory lastLookedAt = buildPlayer.getLastLookedAt();
|
||||
if (lastLookedAt == null || lastLookedAt != category) {
|
||||
buildPlayer.setLastLookedAt(category);
|
||||
XSound.ENTITY_CHICKEN_EGG.play(player);
|
||||
}
|
||||
|
||||
String message = switch (category) {
|
||||
case PUBLIC -> "new_navigator_world_navigator";
|
||||
case ARCHIVE -> "new_navigator_world_archive";
|
||||
case PRIVATE -> "new_navigator_private_worlds";
|
||||
};
|
||||
displayActionBarMessage(player, Messages.getString(message, player));
|
||||
}
|
||||
|
||||
private void displayActionBarMessage(Player player, String message) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the new navigator for the given player.
|
||||
* <p>
|
||||
* This method removes the armor stands, resets the player's cached values, and updates the player's inventory. It also plays a sound effect and clears the action bar message.
|
||||
*
|
||||
* @param player The player whose navigator should be closed
|
||||
*/
|
||||
public void closeNewNavigator(Player player) {
|
||||
if (!openNavigator.contains(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildPlayer buildPlayer = playerStorage.getBuildPlayer(player);
|
||||
buildPlayer.setLastLookedAt(null);
|
||||
plugin.getArmorStandManager().removeArmorStands(player);
|
||||
|
||||
XSound.ENTITY_ITEM_BREAK.play(player);
|
||||
displayActionBarMessage(player, "");
|
||||
InventoryUtils.replaceItem(player, Messages.getString("barrier_item", player), XMaterial.BARRIER, InventoryUtils.createNavigatorItem(player));
|
||||
|
||||
CachedValues cachedValues = buildPlayer.getCachedValues();
|
||||
cachedValues.resetWalkSpeedIfPresent(player);
|
||||
cachedValues.resetFlySpeedIfPresent(player);
|
||||
player.removePotionEffect(XPotion.JUMP_BOOST.get());
|
||||
player.removePotionEffect(XPotion.BLINDNESS.get());
|
||||
|
||||
openNavigator.remove(player);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
this.playerStorage
|
||||
.save(this.playerStorage.getBuildPlayers())
|
||||
.exceptionally(e -> {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to save player data", e);
|
||||
throw new CompletionException("Failed to save player data", e);
|
||||
});
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.player.customblock;
|
||||
|
||||
import de.eintosti.buildsystem.BuildSystemPlugin;
|
||||
import java.util.Locale;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public enum CustomBlock {
|
||||
|
||||
BARRIER("blocks_barrier", "3ed1aba73f639f4bc42bd48196c715197be2712c3b962c97ebf9e9ed8efa025"),
|
||||
BROWN_MUSHROOM("blocks_brown_mushroom", "fa49eca0369d1e158e539d78149acb1572949b88ba921d9ee694fea4c726b3"),
|
||||
BURNING_FURNACE("blocks_burning_furnace", "d17b8b43f8c4b5cfeb919c9f8fe93f26ceb6d2b133c2ab1eb339bd6621fd309c"),
|
||||
COMMAND_BLOCK("blocks_command_block", "8514d225b262d847c7e557b474327dcef758c2c5882e41ee6d8c5e9cd3bc914"),
|
||||
DOUBLE_STONE_SLAB("blocks_double_stone_slab", "151e70169ea00f04a9439221cf33770844159dd775fc8830e311fd9b5ccd2969"),
|
||||
DRAGON_EGG("blocks_dragon_egg", "3c151fb54b21fe5769ffb4825b5bc92da73657f214380e5d0301e45b6c13f7d"),
|
||||
END_PORTAL("blocks_end_portal", "7840b87d52271d2a755dedc82877e0ed3df67dcc42ea479ec146176b02779a5"),
|
||||
FULL_ACACIA_BARCH("blocks_full_acacia_barch", "96a3bba2b7a2b4fa46945b1471777abe4599695545229e782259aed41d6"),
|
||||
FULL_BIRCH_BARCH("blocks_full_birch_barch", "a221f813dacee0fef8c59f76894dbb26415478d9ddfc44c2e708a6d3b7549b"),
|
||||
FULL_DARK_OAK_BARCH("blocks_full_dark_oak_barch", "cde9d4e4c343afdb3ed68038450fc6a67cd208b2efc99fb622c718d24aac"),
|
||||
FULL_JUNGLE_BARCH("blocks_full_jungle_barch", "1cefc19380683015e47c666e5926b15ee57ab33192f6a7e429244cdffcc262"),
|
||||
FULL_MUSHROOM_STEM("blocks_full_mushroom_stem", "f55fa642d5ebcba2c5246fe6499b1c4f6803c10f14f5299c8e59819d5dc"),
|
||||
FULL_OAK_BARCH("blocks_full_oak_barch", "22e4bb979efefd2ddb3f8b1545e59cd360492e12671ec371efc1f88af21ab83"),
|
||||
FULL_SPRUCE_BARCH("blocks_full_spruce_barch", "966cbdef8efb914d43a213be66b5396f75e5c1b9124f76f67d7cd32525748"),
|
||||
INVISIBLE_ITEM_FRAME("blocks_invisible_item_frame", "8122a503d7a6f57802b03af7624194a4c4f5077a99ae21dd276ce7db88bc38ae"),
|
||||
MOB_SPAWNER("blocks_mob_spawner", "db6bd9727abb55d5415265789d4f2984781a343c68dcaf57f554a5e9aa1cd"),
|
||||
MUSHROOM_BLOCK("blocks_mushroom_block", "3fa39ccf4788d9179a8795e6b72382d49297b39217146eda68ae78384355b13"),
|
||||
MUSHROOM_STEM("blocks_mushroom_stem", "84d541275c7f924bcb9eb2dbbf4b866b7649c330a6a013b53d584fd4ddf186ca"),
|
||||
NETHER_PORTAL("blocks_nether_portal", "b0bfc2577f6e26c6c6f7365c2c4076bccee653124989382ce93bca4fc9e39b"),
|
||||
PISTON_HEAD("blocks_piston_head", "aa868ce917c09af8e4c350a5807041f6509bf2b89aca45e591fbbd7d4b117d"),
|
||||
POWERED_REDSTONE_LAMP("blocks_powered_redstone_lamp", "7eb4b34519fe15847dbea7229179feeb6ea57712d165dcc8ff6b785bb58911b0"),
|
||||
RED_MUSHROOM("blocks_red_mushroom", "732dbd6612e9d3f42947b5ca8785bfb334258f3ceb83ad69a5cdeebea4cd65"),
|
||||
SMOOTH_RED_SANDSTONE("blocks_smooth_red_sandstone", "a2da7aa1ae6cc9d6c36c18a460d2398162edc2207fdfc9e28a7bf84d7441b8a2"),
|
||||
SMOOTH_SANDSTONE("blocks_smooth_sandstone", "38fffbb0b8fdec6f62b17c451ab214fb86e4e355b116be961a9ae93eb49a43"),
|
||||
SMOOTH_STONE("blocks_smooth_stone", "8dd0cd158c2bb6618650e3954b2d29237f5b4c0ddc7d258e17380ab6979f071"),
|
||||
DEBUG_STICK("blocks_debug_stick", "badc048a7ce78f7dad72a07da27d85c0916881e5522eeed1e3daf217a38c1a");
|
||||
|
||||
public static final NamespacedKey CUSTOM_BLOCK_KEY = new NamespacedKey(BuildSystemPlugin.get(), "custom-block");
|
||||
|
||||
private final String messageKey;
|
||||
private final String skullUrl;
|
||||
|
||||
CustomBlock(String messageKey, String skullUrl) {
|
||||
this.messageKey = messageKey;
|
||||
this.skullUrl = skullUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Contract("null -> null")
|
||||
public static CustomBlock of(@Nullable ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
if (itemMeta == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String identifier = itemMeta.getPersistentDataContainer().get(CUSTOM_BLOCK_KEY, PersistentDataType.STRING);
|
||||
if (identifier == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String customBlock = identifier.toUpperCase(Locale.ROOT);
|
||||
try {
|
||||
return CustomBlock.valueOf(customBlock);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message key for this custom block.
|
||||
*
|
||||
* @return The message key associated with this custom block
|
||||
*/
|
||||
public String getMessageKey() {
|
||||
return messageKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL for the skull texture of this custom block.
|
||||
*
|
||||
* @return The URL of the skull texture for this custom block
|
||||
*/
|
||||
public String getSkullUrl() {
|
||||
return skullUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the custom block identifier in the provided item's {@link PersistentDataContainer}.
|
||||
*
|
||||
* @param itemStack The item to store the custom block identifier in
|
||||
* @return The modified item stack with the custom block identifier stored
|
||||
*/
|
||||
public ItemStack storeCustomBlock(ItemStack itemStack) {
|
||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
itemMeta.getPersistentDataContainer().set(CUSTOM_BLOCK_KEY, PersistentDataType.STRING, this.name());
|
||||
itemStack.setItemMeta(itemMeta);
|
||||
return itemStack;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user