mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-19 14:59:32 +00:00
1939 lines
81 KiB
Diff
1939 lines
81 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
Date: Fri, 29 Oct 2021 16:52:57 +0800
|
|
Subject: [PATCH] Leaves Server Config And Command
|
|
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index 0c537cd70a1b8a7d7ccd78ba212de0cae8cb6bbc..d3bc2ed92763b701d91a8c705818e7f4e12e45f0 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -221,6 +221,14 @@ tasks.registerRunTask("runDevServer") {
|
|
jvmArgs("-DPaper.pushPaperAssetsRoot=true")
|
|
}
|
|
|
|
+// Leaves start - create config file
|
|
+tasks.registerRunTask("createLeavesConfig") {
|
|
+ description = "Create a new leaves.yml"
|
|
+ mainClass = "org.leavesmc.leaves.config.GlobalConfigCreator"
|
|
+ classpath(sourceSets.main.map { it.runtimeClasspath })
|
|
+}
|
|
+// Leaves end - create config file
|
|
+
|
|
tasks.registerRunTask("runBundler") {
|
|
description = "Spin up a test server from the Mojang mapped bundler jar"
|
|
classpath(rootProject.tasks.named<io.papermc.paperweight.tasks.CreateBundlerJar>("createMojmapBundlerJar").flatMap { it.outputZip })
|
|
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
index a108ebfe472c908e86e0af2cfd9cb63083f58eb5..f97b2cb3ea855e6e250cabf357a050cd52be8f70 100644
|
|
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
@@ -238,6 +238,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
|
this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark
|
|
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
|
|
|
|
+ org.leavesmc.leaves.LeavesConfig.init((java.io.File) options.valueOf("leaves-settings")); // Leaves - Server Config
|
|
+ System.setProperty("spark.serverconfigs.extra", "leaves.yml"); // Leaves - spark config
|
|
+
|
|
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics // Leaves - down
|
|
|
|
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..25e8b14e79edcf0ad2bcd224e049e0c04f8a5e5c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -1100,6 +1100,7 @@ public final class CraftServer implements Server {
|
|
playerMetadata.removeAll(plugin);
|
|
}
|
|
// Paper end
|
|
+ org.leavesmc.leaves.LeavesConfig.init((File) console.options.valueOf("leaves-settings")); // Leaves - Server Config
|
|
this.reloadData();
|
|
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
|
|
io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
|
|
@@ -2989,6 +2990,14 @@ public final class CraftServer implements Server {
|
|
{
|
|
return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console);
|
|
}
|
|
+
|
|
+ // Leaves start - add config to timings report
|
|
+ @Override
|
|
+ public YamlConfiguration getLeavesConfig()
|
|
+ {
|
|
+ return org.leavesmc.leaves.LeavesConfig.config;
|
|
+ }
|
|
+ /// Leaves end - add config to timings report
|
|
|
|
@Override
|
|
public void restart() {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
index 3f81f87def8e591938618c3ade8daaf5ab0f84a7..4f3c67cd469dd9c05cf8b917fe890451d1219a9c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
@@ -168,6 +168,14 @@ public class Main {
|
|
.ofType(File.class)
|
|
.defaultsTo(new File("paper.yml"))
|
|
.describedAs("Yml file");
|
|
+
|
|
+ // Leaves start - Server Config
|
|
+ acceptsAll(asList("leaves", "leaves-settings"), "File for leaves settings")
|
|
+ .withRequiredArg()
|
|
+ .ofType(File.class)
|
|
+ .defaultsTo(new File("leaves.yml"))
|
|
+ .describedAs("Yml file");
|
|
+ // Leaves end - Server Config
|
|
|
|
acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.")
|
|
.withRequiredArg()
|
|
diff --git a/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/src/main/java/org/leavesmc/leaves/LeavesConfig.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..313beaa7eef481bfc42d89959e227dac6558fab9
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/LeavesConfig.java
|
|
@@ -0,0 +1,901 @@
|
|
+package org.leavesmc.leaves;
|
|
+
|
|
+import com.destroystokyo.paper.util.SneakyThrow;
|
|
+import io.papermc.paper.configuration.GlobalConfiguration;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import org.bukkit.Bukkit;
|
|
+import org.bukkit.command.Command;
|
|
+import org.bukkit.configuration.file.YamlConfiguration;
|
|
+import org.leavesmc.leaves.command.LeavesCommand;
|
|
+import org.leavesmc.leaves.config.ConfigVerifyImpl;
|
|
+import org.leavesmc.leaves.config.GlobalConfig;
|
|
+import org.leavesmc.leaves.config.GlobalConfigManager;
|
|
+import org.leavesmc.leaves.config.RemovedConfig;
|
|
+import org.leavesmc.leaves.util.MathUtils;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+import java.util.Locale;
|
|
+import java.util.logging.Level;
|
|
+import java.util.Random;
|
|
+
|
|
+import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule;
|
|
+import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules;
|
|
+
|
|
+import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeatureSet;
|
|
+import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeature;
|
|
+
|
|
+public final class LeavesConfig {
|
|
+
|
|
+ public static final String CONFIG_HEADER = "Configuration file for Leaves.";
|
|
+ public static final int CURRENT_CONFIG_VERSION = 6;
|
|
+
|
|
+ private static File configFile;
|
|
+ public static YamlConfiguration config;
|
|
+
|
|
+ public static void init(final File file) {
|
|
+ LeavesConfig.configFile = file;
|
|
+ config = new YamlConfiguration();
|
|
+ config.options().setHeader(Collections.singletonList(CONFIG_HEADER));
|
|
+ config.options().copyDefaults(true);
|
|
+
|
|
+ if (!file.exists()) {
|
|
+ try {
|
|
+ boolean is = file.createNewFile();
|
|
+ if (!is) {
|
|
+ throw new IOException("Can't create file");
|
|
+ }
|
|
+ } catch (final Exception ex) {
|
|
+ Bukkit.getLogger().log(Level.SEVERE, "Failure to create leaves config", ex);
|
|
+ }
|
|
+ } else {
|
|
+ try {
|
|
+ config.load(file);
|
|
+ } catch (final Exception ex) {
|
|
+ Bukkit.getLogger().log(Level.SEVERE, "Failure to load leaves config", ex);
|
|
+ SneakyThrow.sneaky(ex); /* Rethrow, this is critical */
|
|
+ throw new RuntimeException(ex); // unreachable
|
|
+ }
|
|
+ }
|
|
+
|
|
+ LeavesConfig.config.set("config-version", CURRENT_CONFIG_VERSION);
|
|
+
|
|
+ GlobalConfigManager.init();
|
|
+
|
|
+ registerCommand("leaves", new LeavesCommand("leaves"));
|
|
+ }
|
|
+
|
|
+ public static void save() {
|
|
+ try {
|
|
+ config.save(LeavesConfig.configFile);
|
|
+ } catch (final Exception ex) {
|
|
+ Bukkit.getLogger().log(Level.SEVERE, "Unable to save leaves config", ex);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void registerCommand(String name, Command command) {
|
|
+ MinecraftServer.getServer().server.getCommandMap().register(name, "leaves", command);
|
|
+ MinecraftServer.getServer().server.syncCommands();
|
|
+ }
|
|
+
|
|
+ public static void unregisterCommand(String name) {
|
|
+ name = name.toLowerCase(Locale.ENGLISH).trim();
|
|
+ MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove(name);
|
|
+ MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove("leaves:" + name);
|
|
+ MinecraftServer.getServer().server.syncCommands();
|
|
+ }
|
|
+
|
|
+ // Leaves start - modify
|
|
+
|
|
+ // Leaves start - modify - fakeplayer
|
|
+
|
|
+ @RemovedConfig(name = "enable", category = "fakeplayer", transform = true)
|
|
+ @GlobalConfig(name = "enable", category = {"modify", "fakeplayer"}, verify = FakeplayerVerify.class)
|
|
+ public static boolean fakeplayerSupport = true;
|
|
+
|
|
+ private static class FakeplayerVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (value) {
|
|
+ registerCommand("bot", new org.leavesmc.leaves.bot.BotCommand("bot"));
|
|
+ org.leavesmc.leaves.bot.agent.Actions.registerAll();
|
|
+ } else {
|
|
+ unregisterCommand("bot");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @RemovedConfig(name = "unable-fakeplayer-names", category = "fakeplayer", convert = ConfigVerifyImpl.ListConfigVerify.STRING.class, transform = true)
|
|
+ @GlobalConfig(name = "unable-fakeplayer-names", category = {"modify", "fakeplayer"}, verify = ConfigVerifyImpl.ListConfigVerify.STRING.class)
|
|
+ public static List<String> unableFakeplayerNames = List.of("player-name");
|
|
+
|
|
+ @GlobalConfig(name = "limit", category = {"modify", "fakeplayer"}, verify = ConfigVerifyImpl.IntConfigVerify.class)
|
|
+ public static int fakeplayerLimit = 10;
|
|
+
|
|
+ @GlobalConfig(name = "prefix", category = {"modify", "fakeplayer"}, verify = ConfigVerifyImpl.StringConfigVerify.class)
|
|
+ public static String fakeplayerPrefix = "";
|
|
+
|
|
+ @GlobalConfig(name = "suffix", category = {"modify", "fakeplayer"}, verify = ConfigVerifyImpl.StringConfigVerify.class)
|
|
+ public static String fakeplayerSuffix = "";
|
|
+
|
|
+ @GlobalConfig(name = "always-send-data", category = {"modify", "fakeplayer"})
|
|
+ public static boolean alwaysSendFakeplayerData = true;
|
|
+
|
|
+ @GlobalConfig(name = "resident-fakeplayer", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerResident = false;
|
|
+
|
|
+ @GlobalConfig(name = "open-fakeplayer-inventory", category = {"modify", "fakeplayer"})
|
|
+ public static boolean openFakeplayerInventory = false;
|
|
+
|
|
+ @GlobalConfig(name = "skip-sleep-check", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerSkipSleep = false;
|
|
+
|
|
+ @GlobalConfig(name = "spawn-phantom", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerSpawnPhantom = false;
|
|
+
|
|
+ @GlobalConfig(name = "regen-amount", category = {"modify", "fakeplayer"}, verify = RegenAmountVerify.class)
|
|
+ public static double fakeplayerRegenAmount = 0.0;
|
|
+
|
|
+ private static class RegenAmountVerify extends ConfigVerifyImpl.DoubleConfigVerify {
|
|
+ @Override
|
|
+ public void check(Double old, Double value) throws IllegalArgumentException {
|
|
+ if (value < 0.0) {
|
|
+ throw new IllegalArgumentException("regen-amount need >= 0.0");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "use-action", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerUseAction = true;
|
|
+
|
|
+ @GlobalConfig(name = "modify-config", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerModifyConfig = false;
|
|
+
|
|
+ @GlobalConfig(name = "manual-save-and-load", category = {"modify", "fakeplayer"})
|
|
+ public static boolean fakeplayerManualSaveAndLoad = false;
|
|
+
|
|
+ @GlobalConfig(name = "cache-skin", category = {"modify", "fakeplayer"}, lock = true)
|
|
+ public static boolean fakeplayerCacheSkin = false;
|
|
+
|
|
+ // Leaves end - modify - fakeplayer
|
|
+
|
|
+ // Leaves start - modify - minecraft-old
|
|
+
|
|
+ @RemovedConfig(name = "shears-in-dispenser-can-zero-amount", category = {}, transform = true)
|
|
+ @RemovedConfig(name = "shears-in-dispenser-can-zero-amount", category = "modify", transform = true)
|
|
+ @GlobalConfig(name = "shears-in-dispenser-can-zero-amount", category = {"modify", "minecraft-old"})
|
|
+ public static boolean shearsInDispenserCanZeroAmount = false;
|
|
+
|
|
+ @RemovedConfig(name = "instant-block-updater-reintroduced", category = "modify", transform = true)
|
|
+ @GlobalConfig(name = "instant-block-updater-reintroduced", category = {"modify", "minecraft-old"}, lock = true)
|
|
+ public static boolean instantBlockUpdaterReintroduced = false;
|
|
+
|
|
+ @GlobalConfig(name = "armor-stand-cant-kill-by-mob-projectile", category = {"modify", "minecraft-old"})
|
|
+ public static boolean armorStandCantKillByMobProjectile = false;
|
|
+
|
|
+ @GlobalConfig(name = "cce-update-suppression", category = {"modify", "minecraft-old"})
|
|
+ public static boolean cceUpdateSuppression = false;
|
|
+
|
|
+ @GlobalConfig(name = "villager-infinite-discounts", category = {"modify", "minecraft-old"}, verify = VillagerInfiniteDiscountsVerify.class)
|
|
+ public static boolean villagerInfiniteDiscounts = false;
|
|
+
|
|
+ private static class VillagerInfiniteDiscountsVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ org.leavesmc.leaves.util.VillagerInfiniteDiscountHelper.doVillagerInfiniteDiscount(value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "copper-bulb-1gt-delay", category = {"modify", "minecraft-old"})
|
|
+ public static boolean copperBulb1gt = false;
|
|
+
|
|
+ @GlobalConfig(name = "crafter-1gt-delay", category = {"modify", "minecraft-old"})
|
|
+ public static boolean crafter1gt = false;
|
|
+
|
|
+ @RemovedConfig(name = "redstone-wire-dont-connect-if-on-trapdoor", category = "modify", transform = true)
|
|
+ @GlobalConfig(name = "redstone-wire-dont-connect-if-on-trapdoor", category = {"modify", "minecraft-old"})
|
|
+ public static boolean redstoneDontCantOnTrapDoor = false;
|
|
+
|
|
+ @RemovedConfig(name = "zero-tick-plants", category = "modify", transform = true)
|
|
+ @GlobalConfig(name = "zero-tick-plants", category = {"modify", "minecraft-old"})
|
|
+ public static boolean zeroTickPlants = false;
|
|
+
|
|
+ @RemovedConfig(name = "loot-world-random", category = {"modify", "minecraft-old"}, transform = true)
|
|
+ @GlobalConfig(name = "rng-fishing", category = {"modify", "minecraft-old"}, lock = true, verify = RNGFishingVerify.class)
|
|
+ public static boolean rngFishing = false;
|
|
+
|
|
+ private static class RNGFishingVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ LeavesFeatureSet.register(LeavesFeature.of("rng_fishing", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "allow-grindstone-overstacking", category = {"modify", "minecraft-old"})
|
|
+ public static boolean allowGrindstoneOverstacking = false;
|
|
+
|
|
+ @GlobalConfig(name = "allow-entity-portal-with-passenger", category = {"modify", "minecraft-old"})
|
|
+ public static boolean allowEntityPortalWithPassenger = true;
|
|
+
|
|
+ @GlobalConfig(name = "disable-gateway-portal-entity-ticking", category = {"modify", "minecraft-old"})
|
|
+ public static boolean disableGatewayPortalEntityTicking = false;
|
|
+
|
|
+ @GlobalConfig(name = "disable-LivingEntity-ai-step-alive-check", category = {"modify", "minecraft-old"})
|
|
+ public static boolean disableLivingEntityAiStepAliveCheck = false;
|
|
+
|
|
+ @GlobalConfig(name = "fix-fortress-mob-spawn", category = {"modify", "minecraft-old"})
|
|
+ public static boolean fixFortressMobSpawn = false;
|
|
+
|
|
+ @GlobalConfig(name = "old-block-entity-behaviour", category = {"modify", "minecraft-old"})
|
|
+ public static boolean oldBlockEntityBehaviour = false;
|
|
+
|
|
+ @GlobalConfig(name = "allow-bad-omen-trigger-raid", category = {"modify", "minecraft-old", "revert-raid-changes"})
|
|
+ public static boolean allowBadOmenTriggerRaid = false;
|
|
+
|
|
+ @GlobalConfig(name = "give-bad-omen-when-kill-patrol-leader", category = {"modify", "minecraft-old", "revert-raid-changes"})
|
|
+ public static boolean giveBadOmenWhenKillPatrolLeader = false;
|
|
+
|
|
+ @GlobalConfig(name = "allow-anvil-destroy-item-entities", category = {"modify", "minecraft-old"})
|
|
+ public static boolean allowAnvilDestroyItemEntities = false;
|
|
+
|
|
+ // Leaves end - modify - minecraft-old
|
|
+
|
|
+ // Leaves start - modify - elytra-aeronautics
|
|
+
|
|
+ @GlobalConfig(name = "no-chunk-load", category = {"modify", "elytra-aeronautics"})
|
|
+ public static boolean elytraAeronauticsNoChunk = false;
|
|
+
|
|
+ @GlobalConfig(name = "no-chunk-height", category = {"modify", "elytra-aeronautics"}, verify = ConfigVerifyImpl.DoubleConfigVerify.class)
|
|
+ public static double elytraAeronauticsNoChunkHeight = 500.0D;
|
|
+
|
|
+ @GlobalConfig(name = "no-chunk-speed", category = {"modify", "elytra-aeronautics"}, verify = ConfigVerifyImpl.DoubleConfigVerify.class)
|
|
+ public static double elytraAeronauticsNoChunkSpeed = -1.0D;
|
|
+
|
|
+ @GlobalConfig(name = "message", category = {"modify", "elytra-aeronautics"})
|
|
+ public static boolean elytraAeronauticsNoChunkMes = true;
|
|
+
|
|
+ @GlobalConfig(name = "message-start", category = {"modify", "elytra-aeronautics"}, verify = ConfigVerifyImpl.StringConfigVerify.class)
|
|
+ public static String elytraAeronauticsNoChunkStartMes = "Flight enter cruise mode";
|
|
+
|
|
+ @GlobalConfig(name = "message-end", category = {"modify", "elytra-aeronautics"}, verify = ConfigVerifyImpl.StringConfigVerify.class)
|
|
+ public static String elytraAeronauticsNoChunkEndMes = "Flight exit cruise mode";
|
|
+
|
|
+ // Leaves end - modify - elytra-aeronautics
|
|
+
|
|
+ @RemovedConfig(name = "redstone-shears-wrench", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "redstone-shears-wrench", category = "modify")
|
|
+ public static boolean redstoneShearsWrench = true;
|
|
+
|
|
+ @RemovedConfig(name = "budding-amethyst-can-push-by-piston", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "budding-amethyst-can-push-by-piston", category = "modify")
|
|
+ public static boolean buddingAmethystCanPushByPiston = false;
|
|
+
|
|
+ @RemovedConfig(name = "spectator-dont-get-advancement", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "spectator-dont-get-advancement", category = "modify")
|
|
+ public static boolean spectatorDontGetAdvancement = false;
|
|
+
|
|
+ @RemovedConfig(name = "stick-change-armorstand-arm-status", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "stick-change-armorstand-arm-status", category = "modify")
|
|
+ public static boolean stickChangeArmorStandArmStatus = true;
|
|
+
|
|
+ @RemovedConfig(name = "snowball-and-egg-can-knockback-player", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "snowball-and-egg-can-knockback-player", category = "modify")
|
|
+ public static boolean snowballAndEggCanKnockback = true;
|
|
+
|
|
+ @GlobalConfig(name = "flatten-triangular-distribution", category = "modify")
|
|
+ public static boolean flattenTriangularDistribution = false;
|
|
+
|
|
+ @GlobalConfig(name = "player-operation-limiter", category = "modify")
|
|
+ public static boolean playerOperationLimiter = false;
|
|
+
|
|
+ @GlobalConfig(name = "renewable-elytra", category = "modify", verify = RenewableElytraVerify.class)
|
|
+ public static double renewableElytra = -1.0F;
|
|
+
|
|
+ private static class RenewableElytraVerify extends ConfigVerifyImpl.DoubleConfigVerify {
|
|
+ @Override
|
|
+ public void check(Double old, Double value) throws IllegalArgumentException {
|
|
+ if (value > 1.0) {
|
|
+ throw new IllegalArgumentException("renewable-elytra need <= 1.0f");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static int shulkerBoxStackSize = 1;
|
|
+ @GlobalConfig(name = "stackable-shulker-boxes", category = "modify", verify = StackableShulkerVerify.class)
|
|
+ private static String stackableShulkerBoxes = "false";
|
|
+
|
|
+ private static class StackableShulkerVerify extends ConfigVerifyImpl.StringConfigVerify {
|
|
+ @Override
|
|
+ public void check(String old, String value) throws IllegalArgumentException {
|
|
+ String realValue = MathUtils.isNumeric(value) ? value : value.equals("true") ? "2" : "1";
|
|
+ shulkerBoxStackSize = Integer.parseInt(realValue);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "force-void-trade", category = "modify")
|
|
+ public static boolean forceVoidTrade = false;
|
|
+
|
|
+ @GlobalConfig(name = "disable-moved-wrongly-threshold", category = "modify")
|
|
+ public static boolean disableMovedWronglyThreshold = false;
|
|
+
|
|
+ @GlobalConfig(name = "mc-technical-survival-mode", category = "modify", verify = McTechnicalModeVerify.class, lock = true)
|
|
+ public static boolean mcTechnicalMode = true;
|
|
+
|
|
+ private static class McTechnicalModeVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (value) {
|
|
+ org.leavesmc.leaves.util.McTechnicalModeHelper.doMcTechnicalMode();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "return-nether-portal-fix", category = "modify")
|
|
+ public static boolean netherPortalFix = false;
|
|
+
|
|
+ @GlobalConfig(name = "use-vanilla-random", category = "modify", lock = true, verify = UseVanillaRandomVerify.class)
|
|
+ public static boolean useVanillaRandom = false;
|
|
+
|
|
+ private static class UseVanillaRandomVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ LeavesFeatureSet.register(LeavesFeature.of("use_vanilla_random", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "fix-update-suppression-crash", category = "modify")
|
|
+ public static boolean updateSuppressionCrashFix = true;
|
|
+
|
|
+ @GlobalConfig(name = "bedrock-break-list", category = "modify", lock = true)
|
|
+ public static boolean bedrockBreakList = false;
|
|
+
|
|
+ @GlobalConfig(name = "disable-distance-check-for-use-item", category = "modify", verify = DisableDistanceCheckForUseItemVerify.class)
|
|
+ public static boolean disableDistanceCheckForUseItem = false;
|
|
+
|
|
+ private static class DisableDistanceCheckForUseItemVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (alternativeBlockPlacement != AlternativePlaceType.NONE && !value) {
|
|
+ throw new IllegalArgumentException("alternative-block-placement is enable, disable-distance-check-for-use-item always need true");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "no-feather-falling-trample", category = "modify")
|
|
+ public static boolean noFeatherFallingTrample = false;
|
|
+
|
|
+ @GlobalConfig(name = "shared-villager-discounts", category = "modify")
|
|
+ public static boolean sharedVillagerDiscounts = false;
|
|
+
|
|
+ @GlobalConfig(name = "disable-check-out-of-order-command", category = "modify")
|
|
+ public static boolean disableCheckOutOfOrderCommand = false;
|
|
+
|
|
+ @GlobalConfig(name = "despawn-enderman-with-block", category = "modify")
|
|
+ public static boolean despawnEndermanWithBlock = false;
|
|
+
|
|
+ @GlobalConfig(name = "creative-no-clip", category = "modify", verify = CreativeNoClipVerify.class)
|
|
+ public static boolean creativeNoClip = false;
|
|
+
|
|
+ private static class CreativeNoClipVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ CarpetRules.register(CarpetRule.of("carpet", "creativeNoClip", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "shave-snow-layers", category = "modify")
|
|
+ public static boolean shaveSnowLayers = true;
|
|
+
|
|
+ @GlobalConfig(name = "ignore-lc", category = "modify")
|
|
+ public static boolean ignoreLC = false;
|
|
+
|
|
+ @GlobalConfig(name = "disable-packet-limit", category = "modify")
|
|
+ public static boolean disablePacketLimit = false;
|
|
+
|
|
+ @GlobalConfig(name = "lava-riptide", category = "modify", verify = LavaRiptideVerify.class)
|
|
+ public static boolean lavaRiptide = false;
|
|
+
|
|
+ private static class LavaRiptideVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ LeavesFeatureSet.register(LeavesFeature.of("lava_riptide", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "no-block-update-command", category = "modify", verify = NoBlockUpdateVerify.class)
|
|
+ public static boolean noBlockUpdateCommand = false;
|
|
+
|
|
+ @GlobalConfig(name = "no-tnt-place-update", category = "modify")
|
|
+ public static boolean noTNTPlaceUpdate = false;
|
|
+
|
|
+ private static class NoBlockUpdateVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (value) {
|
|
+ registerCommand("blockupdate", new org.leavesmc.leaves.command.NoBlockUpdateCommand("blockupdate"));
|
|
+ } else {
|
|
+ unregisterCommand("blockupdate");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "raider-die-skip-self-raid-check", category = "modify")
|
|
+ public static boolean skipSelfRaidCheck = false;
|
|
+
|
|
+ @GlobalConfig(name = "container-passthrough", category = "modify")
|
|
+ public static boolean containerPassthrough = false;
|
|
+
|
|
+ @GlobalConfig(name = "avoid-anvil-too-expensive", category = "modify", verify = AnvilNotExpensiveVerify.class)
|
|
+ public static boolean avoidAnvilTooExpensive = false;
|
|
+
|
|
+ private static class AnvilNotExpensiveVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ CarpetRules.register(CarpetRule.of("pca", "avoidAnvilTooExpensive", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "bow-infinity-fix", category = "modify")
|
|
+ public static boolean bowInfinityFix = false;
|
|
+
|
|
+ @GlobalConfig(name = "hopper-counter", category = "modify")
|
|
+ public static boolean hopperCounter = false;
|
|
+
|
|
+ @GlobalConfig(name = "spider-jockeys-drop-gapples", category = "modify", verify = JockeysDropGAppleVerify.class)
|
|
+ public static double spiderJockeysDropGapples = -1.0;
|
|
+
|
|
+ private static class JockeysDropGAppleVerify extends ConfigVerifyImpl.DoubleConfigVerify {
|
|
+ @Override
|
|
+ public void check(Double old, Double value) throws IllegalArgumentException {
|
|
+ if (value > 1.0) {
|
|
+ throw new IllegalArgumentException("spider-jockeys-drop-gapples need <= 1.0f");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "renewable-deepslate", category = "modify")
|
|
+ public static boolean renewableDeepslate = false;
|
|
+
|
|
+ @GlobalConfig(name = "renewable-sponges", category = "modify")
|
|
+ public static boolean renewableSponges = false;
|
|
+
|
|
+ @GlobalConfig(name = "renewable-coral", category = "modify", verify = RenewableCoralVerify.class)
|
|
+ public static RenewableCoralType renewableCoral = RenewableCoralType.FALSE;
|
|
+
|
|
+ public enum RenewableCoralType {
|
|
+ FALSE, TRUE, EXPANDED
|
|
+ }
|
|
+
|
|
+ private static class RenewableCoralVerify extends ConfigVerifyImpl.EnumConfigVerify<RenewableCoralType> {
|
|
+ @Override
|
|
+ public void check(RenewableCoralType old, RenewableCoralType value) throws IllegalArgumentException {
|
|
+ CarpetRules.register(CarpetRule.of("carpet", "renewableCoral", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "fast-resume", category = "modify")
|
|
+ public static boolean fastResume = false;
|
|
+
|
|
+ @GlobalConfig(name = "force-peaceful-mode", category = "modify", verify = ForcePeacefulModeVerify.class)
|
|
+ public static int forcePeacefulMode = -1;
|
|
+
|
|
+ private static class ForcePeacefulModeVerify extends ConfigVerifyImpl.IntConfigVerify {
|
|
+ @Override
|
|
+ public void check(Integer old, Integer value) throws IllegalArgumentException {
|
|
+ for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
|
|
+ level.chunkSource.peacefulModeSwitchTick = value;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "disable-vault-blacklist", category = "modify")
|
|
+ public static boolean disableVaultBlacklist = false;
|
|
+
|
|
+ @RemovedConfig(name = "tick-command", category = "modify")
|
|
+ @RemovedConfig(name = "player-can-edit-sign", category = "modify")
|
|
+ @RemovedConfig(name = "mending-compatibility-infinity", category = {"modify", "minecraft-old"})
|
|
+ @RemovedConfig(name = "protection-stacking", category = {"modify", "minecraft-old"})
|
|
+ public static boolean removedModify = false;
|
|
+
|
|
+ // Leaves end - modify
|
|
+
|
|
+ // Leaves start - performance
|
|
+
|
|
+ // Leaves start - performance - remove
|
|
+
|
|
+ @GlobalConfig(name = "tick-guard-lambda", category = {"performance", "remove"})
|
|
+ public static boolean removeTickGuardLambda = true;
|
|
+
|
|
+ @GlobalConfig(name = "inventory-contains-iterators", category = {"performance", "remove"})
|
|
+ public static boolean removeInventoryContainsIterators = true;
|
|
+
|
|
+ @GlobalConfig(name = "range-check-streams-and-iterators", category = {"performance", "remove"})
|
|
+ public static boolean removeRangeCheckStreams = true;
|
|
+
|
|
+ @GlobalConfig(name = "damage-lambda", category = {"performance", "remove"})
|
|
+ public static boolean removeDamageLambda = true;
|
|
+
|
|
+ // Leaves end - performance - remove
|
|
+
|
|
+ @GlobalConfig(name = "optimized-dragon-respawn", category = "performance")
|
|
+ public static boolean optimizedDragonRespawn = false;
|
|
+
|
|
+ @GlobalConfig(name = "dont-send-useless-entity-packets", category = "performance")
|
|
+ public static boolean dontSendUselessEntityPackets = true;
|
|
+
|
|
+ @GlobalConfig(name = "enable-suffocation-optimization", category = "performance")
|
|
+ public static boolean enableSuffocationOptimization = true;
|
|
+
|
|
+ @GlobalConfig(name = "check-spooky-season-once-an-hour", category = "performance")
|
|
+ public static boolean checkSpookySeasonOnceAnHour = true;
|
|
+
|
|
+ @GlobalConfig(name = "optimize-chunk-ticking", category = "performance", lock = true)
|
|
+ public static boolean optimizeChunkTicking = true;
|
|
+
|
|
+ @GlobalConfig(name = "entity-target-find-optimization", category = "performance")
|
|
+ public static boolean entityTargetFindingOptimization = true;
|
|
+
|
|
+ @GlobalConfig(name = "use-more-thread-unsafe-random", category = "performance")
|
|
+ public static boolean useMoreThreadUnsafeRandom = true;
|
|
+
|
|
+ @GlobalConfig(name = "inactive-goal-selector-disable", category = "performance")
|
|
+ public static boolean throttleInactiveGoalSelectorTick = false;
|
|
+
|
|
+ @GlobalConfig(name = "reduce-entity-allocations", category = "performance")
|
|
+ public static boolean reduceEntityAllocations = true;
|
|
+
|
|
+ @GlobalConfig(name = "cache-climb-check", category = "performance")
|
|
+ public static boolean cacheClimbCheck = true;
|
|
+
|
|
+ @GlobalConfig(name = "biome-temperatures-use-aging-cache", category = "performance", lock = true)
|
|
+ public static boolean biomeTemperaturesUseAgingCache = true;
|
|
+
|
|
+ @GlobalConfig(name = "reduce-chuck-load-and-lookup", category = "performance")
|
|
+ public static boolean reduceChuckLoadAndLookup = true;
|
|
+
|
|
+ @GlobalConfig(name = "improve-fluid-direction-caching", category = "performance", lock = true)
|
|
+ public static boolean improveFluidDirectionCaching = true;
|
|
+
|
|
+ @GlobalConfig(name = "cache-ignite-odds", category = "performance")
|
|
+ public static boolean cacheIgniteOdds = true;
|
|
+
|
|
+ @GlobalConfig(name = "faster-chunk-serialization", category = "performance")
|
|
+ public static boolean fasterChunkSerialization = true;
|
|
+
|
|
+ @GlobalConfig(name = "cache-world-generator-sea-level", category = "performance")
|
|
+ public static boolean cacheWorldGeneratorSeaLevel = true;
|
|
+
|
|
+ @GlobalConfig(name = "skip-secondary-POI-sensor-if-absent", category = "performance")
|
|
+ public static boolean skipSecondaryPOISensorIfAbsent = true;
|
|
+
|
|
+ @GlobalConfig(name = "store-mob-counts-in-array", category = "performance")
|
|
+ public static boolean storeMobCountsInArray = true;
|
|
+
|
|
+ @GlobalConfig(name = "cache-BlockStatePairKey-hash", category = "performance")
|
|
+ public static boolean cacheBlockStatePairKeyHash = true;
|
|
+
|
|
+ @GlobalConfig(name = "optimize-noise-generation", category = "performance")
|
|
+ public static boolean optimizeNoiseGeneration = false;
|
|
+
|
|
+ @GlobalConfig(name = "optimize-sun-burn-tick", category = "performance")
|
|
+ public static boolean optimizeSunBurnTick = true;
|
|
+
|
|
+ @GlobalConfig(name = "optimized-CubePointRange", category = "performance")
|
|
+ public static boolean optimizedCubePointRange = true;
|
|
+
|
|
+ @GlobalConfig(name = "check-frozen-ticks-before-landing-block", category = "performance")
|
|
+ public static boolean checkFrozenTicksBeforeLandingBlock = true;
|
|
+
|
|
+ @GlobalConfig(name = "skip-entity-move-if-movement-is-zero", category = "performance")
|
|
+ public static boolean skipEntityMoveIfMovementIsZero = true;
|
|
+
|
|
+ @GlobalConfig(name = "skip-cloning-advancement-criteria", category = "performance")
|
|
+ public static boolean skipCloningAdvancementCriteria = false;
|
|
+
|
|
+ @GlobalConfig(name = "skip-negligible-planar-movement-multiplication", category = "performance")
|
|
+ public static boolean skipNegligiblePlanarMovementMultiplication = true;
|
|
+
|
|
+ @GlobalConfig(name = "fix-villagers-dont-release-memory", category = "performance")
|
|
+ public static boolean villagersDontReleaseMemoryFix = false;
|
|
+
|
|
+ @RemovedConfig(name = "cache-ominous-banner-item", category = "performance")
|
|
+ @RemovedConfig(name = "use-optimized-collection", category = "performance")
|
|
+ @RemovedConfig(name = "async-pathfinding", category = "performance")
|
|
+ @RemovedConfig(name = "async-mob-spawning", category = "performance")
|
|
+ @RemovedConfig(name = "async-entity-tracker", category = "performance")
|
|
+ @RemovedConfig(name = "fix-paper-6045", category = {"performance", "fix"})
|
|
+ @RemovedConfig(name = "fix-paper-9372", category = {"performance", "fix"})
|
|
+ @RemovedConfig(name = "skip-clone-loot-parameters", category = "performance")
|
|
+ @RemovedConfig(name = "skip-poi-find-in-vehicle", category = "performance")
|
|
+ @RemovedConfig(name = "strip-raytracing-for-entity", category = "performance")
|
|
+ @RemovedConfig(name = "get-nearby-players-streams", category = {"performance", "remove"})
|
|
+ @RemovedConfig(name = "optimize-world-generation-and-block-access", category = "performance")
|
|
+ @RemovedConfig(name = "cache-CubeVoxelShape-shape-array", category = "performance")
|
|
+ @RemovedConfig(name = "reduce-entity-fluid-lookup", category = "performance")
|
|
+ @RemovedConfig(name = "optimize-entity-coordinate-key", category = "performance")
|
|
+ public static boolean removedPerformance = true;
|
|
+
|
|
+ // Leaves end - performance
|
|
+
|
|
+ // Leaves start - protocol
|
|
+
|
|
+ // Leaves start - protocol - bladeren
|
|
+
|
|
+ @GlobalConfig(name = "protocol", category = {"protocol", "bladeren"})
|
|
+ public static boolean bladerenLeavesProtocol = true;
|
|
+
|
|
+ @GlobalConfig(name = "mspt-sync-protocol", category = {"protocol", "bladeren"}, verify = MSPTSyncVerify.class)
|
|
+ public static boolean msptSyncProtocol = false;
|
|
+
|
|
+ private static class MSPTSyncVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ LeavesFeatureSet.register(LeavesFeature.of("mspt_sync", value));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "mspt-sync-tick-interval", category = {"protocol", "bladeren"}, verify = MSPTSyncIntervalVerify.class)
|
|
+ public static int msptSyncTickInterval = 20;
|
|
+
|
|
+ private static class MSPTSyncIntervalVerify extends ConfigVerifyImpl.IntConfigVerify {
|
|
+ @Override
|
|
+ public void check(Integer old, Integer value) throws IllegalArgumentException {
|
|
+ if (value <= 0) {
|
|
+ throw new IllegalArgumentException("mspt-sync-tick-interval need > 0");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Leaves end - protocol - bladeren
|
|
+
|
|
+ // Leaves start - protocol - syncmatica
|
|
+
|
|
+ @GlobalConfig(name = "enable", category = {"protocol", "syncmatica"}, verify = SyncmaticaVerify.class)
|
|
+ public static boolean syncmaticaProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "quota", category = {"protocol", "syncmatica"})
|
|
+ public static boolean syncmaticaQuota = false;
|
|
+
|
|
+ @GlobalConfig(name = "quota-limit", category = {"protocol", "syncmatica"}, verify = ConfigVerifyImpl.IntConfigVerify.class)
|
|
+ public static int syncmaticaQuotaLimit = 40000000;
|
|
+
|
|
+ public static class SyncmaticaVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (value) {
|
|
+ org.leavesmc.leaves.protocol.syncmatica.SyncmaticaProtocol.init();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Leaves end - protocol - syncmatica
|
|
+
|
|
+ @RemovedConfig(name = "pca-sync-protocol", category = "protocol", transform = true)
|
|
+ @GlobalConfig(name = "pca-sync-protocol", category = {"protocol", "pca"}, verify = PcaVerify.class)
|
|
+ public static boolean pcaSyncProtocol = false;
|
|
+
|
|
+ public static class PcaVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (old != null && old != value) {
|
|
+ org.leavesmc.leaves.protocol.PcaSyncProtocol.onConfigModify(value);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @RemovedConfig(name = "pca-sync-player-entity", category = "protocol", convert = PcaPlayerEntityVerify.class, transform = true)
|
|
+ @GlobalConfig(name = "pca-sync-player-entity", category = {"protocol", "pca"}, verify = PcaPlayerEntityVerify.class)
|
|
+ public static PcaPlayerEntityType pcaSyncPlayerEntity = PcaPlayerEntityType.OPS;
|
|
+
|
|
+ public enum PcaPlayerEntityType {
|
|
+ NOBODY, BOT, OPS, OPS_AND_SELF, EVERYONE
|
|
+ }
|
|
+
|
|
+ private static class PcaPlayerEntityVerify extends ConfigVerifyImpl.EnumConfigVerify<PcaPlayerEntityType> {
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "bbor-protocol", category = "protocol")
|
|
+ public static boolean bborProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "jade-protocol", category = "protocol")
|
|
+ public static boolean jadeProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "alternative-block-placement", category = "protocol", verify = AlternativePlaceVerify.class)
|
|
+ public static AlternativePlaceType alternativeBlockPlacement = AlternativePlaceType.NONE;
|
|
+
|
|
+ public enum AlternativePlaceType {
|
|
+ NONE, CARPET, CARPET_FIX, LITEMATICA
|
|
+ }
|
|
+
|
|
+ private static class AlternativePlaceVerify extends ConfigVerifyImpl.EnumConfigVerify<AlternativePlaceType> {
|
|
+ @Override
|
|
+ public void runAfterLoader(AlternativePlaceType value, boolean firstLoad) {
|
|
+ if (value != AlternativePlaceType.NONE) {
|
|
+ disableDistanceCheckForUseItem = true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "appleskin-protocol", category = "protocol")
|
|
+ public static boolean appleskinProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "xaero-map-protocol", category = "protocol")
|
|
+ public static boolean xaeroMapProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "xaero-map-server-id", category = "protocol", verify = ConfigVerifyImpl.IntConfigVerify.class)
|
|
+ public static int xaeroMapServerID = new Random().nextInt();
|
|
+
|
|
+ @RemovedConfig(name = "servux-protocol", category = "protocol", transform = true)
|
|
+ @GlobalConfig(name = "structure-protocol", category = {"protocol", "servux"})
|
|
+ public static boolean servuxStructureProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "entity-protocol", category = {"protocol", "servux"})
|
|
+ public static boolean servuxEntityProtocol = false;
|
|
+
|
|
+ @GlobalConfig(name = "leaves-carpet-support", category = "protocol")
|
|
+ public static boolean leavesCarpetSupport = false;
|
|
+
|
|
+ // Leaves end - protocol
|
|
+
|
|
+ // Leaves start - misc
|
|
+
|
|
+ // Leaves start - misc - auto-update
|
|
+
|
|
+ @GlobalConfig(name = "enable", category = {"misc", "auto-update"}, lock = true, verify = AutoUpdateVerify.class)
|
|
+ public static boolean autoUpdate = false;
|
|
+
|
|
+ private static class AutoUpdateVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void runAfterLoader(Boolean value, boolean firstLoad) {
|
|
+ if (firstLoad) {
|
|
+ org.leavesmc.leaves.util.LeavesUpdateHelper.init();
|
|
+ if (value) {
|
|
+ LeavesLogger.LOGGER.warning("Auto-Update is not completely safe. Enabling it may cause data security problems!");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "download-source", category = {"misc", "auto-update"}, lock = true, verify = DownloadSourceVerify.class)
|
|
+ public static String autoUpdateSource = "application";
|
|
+
|
|
+ public static class DownloadSourceVerify extends ConfigVerifyImpl.StringConfigVerify {
|
|
+ private static final List<String> suggestSourceList = List.of("application", "ghproxy", "cloud");
|
|
+
|
|
+ @Override
|
|
+ public List<String> valueSuggest() {
|
|
+ return suggestSourceList;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "allow-experimental", category = {"misc", "auto-update"})
|
|
+ public static Boolean autoUpdateAllowExperimental = false;
|
|
+
|
|
+ @GlobalConfig(name = "time", category = {"misc", "auto-update"}, lock = true, verify = ConfigVerifyImpl.ListConfigVerify.STRING.class)
|
|
+ public static List<String> autoUpdateTime = List.of("14:00", "2:00");
|
|
+
|
|
+ // Leaves end - misc - auto-update
|
|
+
|
|
+ // Leaves start - misc - extra-yggdrasil-service
|
|
+
|
|
+ @GlobalConfig(name = "enable", category = {"misc", "extra-yggdrasil-service"}, verify = ExtraYggdrasilVerify.class)
|
|
+ public static boolean extraYggdrasilService = false;
|
|
+
|
|
+ public static class ExtraYggdrasilVerify extends ConfigVerifyImpl.BooleanConfigVerify {
|
|
+ @Override
|
|
+ public void check(Boolean old, Boolean value) throws IllegalArgumentException {
|
|
+ if (value) {
|
|
+ LeavesLogger.LOGGER.warning("extra-yggdrasil-service is an unofficial support. Enabling it may cause data security problems!");
|
|
+ GlobalConfiguration.get().unsupportedSettings.performUsernameValidation = true; // always check username
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "login-protect", category = {"misc", "extra-yggdrasil-service"})
|
|
+ public static boolean extraYggdrasilLoginProtect = false;
|
|
+
|
|
+ @GlobalConfig(name = "urls", category = {"misc", "extra-yggdrasil-service"}, lock = true, verify = ExtraYggdrasilUrlsVerify.class)
|
|
+ public static List<String> extraYggdrasilServiceList = List.of("https://url.with.authlib-injector-yggdrasil");
|
|
+
|
|
+ public static class ExtraYggdrasilUrlsVerify extends ConfigVerifyImpl.ListConfigVerify<String> {
|
|
+ @Override
|
|
+ public void check(List<String> old, List<String> value) throws IllegalArgumentException {
|
|
+ org.leavesmc.leaves.profile.LeavesMinecraftSessionService.initExtraYggdrasilList(value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Leaves end - misc - extra-yggdrasil-service
|
|
+
|
|
+ @GlobalConfig(name = "disable-method-profiler", category = "misc")
|
|
+ public static boolean disableMethodProfiler = true;
|
|
+
|
|
+ @RemovedConfig(name = "no-chat-sign", category = {}, transform = true)
|
|
+ @GlobalConfig(name = "no-chat-sign", category = "misc")
|
|
+ public static boolean noChatSign = true;
|
|
+
|
|
+ @GlobalConfig(name = "dont-respond-ping-before-start-fully", category = "misc")
|
|
+ public static boolean dontRespondPingBeforeStart = true;
|
|
+
|
|
+ @GlobalConfig(name = "server-lang", category = "misc", lock = true, verify = ServerLangVerify.class)
|
|
+ public static String serverLang = "en_us";
|
|
+
|
|
+ private static class ServerLangVerify extends ConfigVerifyImpl.StringConfigVerify {
|
|
+ private static final List<String> supportLang = List.of("en_us", "zh_cn");
|
|
+
|
|
+ @Override
|
|
+ public void check(String old, String value) throws IllegalArgumentException {
|
|
+ if (!supportLang.contains(value)) {
|
|
+ throw new IllegalArgumentException("lang " + value + " not supported");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "server-mod-name", category = "misc", verify = ConfigVerifyImpl.StringConfigVerify.class)
|
|
+ public static String serverModName = "Leaves";
|
|
+
|
|
+ @GlobalConfig(name = "bstats-privacy-mode", category = "misc")
|
|
+ public static boolean bstatsPrivacyMode = false;
|
|
+
|
|
+ @GlobalConfig(name = "force-minecraft-command", category = "misc")
|
|
+ public static boolean forceMinecraftCommand = false;
|
|
+
|
|
+ @GlobalConfig(name = "leaves-packet-event", category = "misc")
|
|
+ public static boolean leavesPacketEvent = true;
|
|
+
|
|
+ // Leaves end - misc
|
|
+
|
|
+ // Leaves start - region
|
|
+
|
|
+ @GlobalConfig(name = "format", category = "region", lock = true, verify = RegionFormatVerify.class)
|
|
+ public static org.leavesmc.leaves.region.RegionFileFormat regionFormat = org.leavesmc.leaves.region.RegionFileFormat.ANVIL;
|
|
+
|
|
+ private static class RegionFormatVerify extends ConfigVerifyImpl.EnumConfigVerify<org.leavesmc.leaves.region.RegionFileFormat> {
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "flush-frequency", category = {"region", "linear"}, lock = true, verify = ConfigVerifyImpl.IntConfigVerify.class)
|
|
+ public static int linearFlushFrequency = 10;
|
|
+
|
|
+ @GlobalConfig(name = "auto-convert-anvil-to-linear", category = {"region", "linear"}, lock = true)
|
|
+ public static boolean autoConvertAnvilToLinear = false;
|
|
+
|
|
+ @GlobalConfig(name = "flush-max-threads", category = {"region", "linear"}, lock = true, verify = ConfigVerifyImpl.IntConfigVerify.class)
|
|
+ public static int linearFlushThreads = 1;
|
|
+
|
|
+ public static int getLinearFlushThreads() {
|
|
+ if (linearFlushThreads < 0) {
|
|
+ return Math.max(Runtime.getRuntime().availableProcessors() + linearFlushThreads, 1);
|
|
+ } else {
|
|
+ return Math.max(linearFlushThreads, 1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @GlobalConfig(name = "compression-level", category = {"region", "linear"}, lock = true, verify = LinearCompressVerify.class)
|
|
+ public static int linearCompressionLevel = 1;
|
|
+
|
|
+ private static class LinearCompressVerify extends ConfigVerifyImpl.IntConfigVerify {
|
|
+ @Override
|
|
+ public void check(Integer old, Integer value) throws IllegalArgumentException {
|
|
+ if (value < 1 || value > 22) {
|
|
+ throw new IllegalArgumentException("linear.compression-level need between 1 and 22");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @RemovedConfig(name = "crash-on-broken-symlink", category = {"region", "linear"})
|
|
+ public static boolean linearCrashOnBrokenSymlink = true;
|
|
+
|
|
+ // Leaves end - region
|
|
+
|
|
+ // Leaves start - fix
|
|
+
|
|
+ @GlobalConfig(name = "vanilla-hopper", category = "fix")
|
|
+ public static boolean vanillaHopper = false;
|
|
+
|
|
+ @RemovedConfig(name = "spigot-EndPlatform-destroy", category = "fix")
|
|
+ public static boolean spigotEndPlatformDestroy = false;
|
|
+
|
|
+ // Leaves end - region
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/CommandArgument.java b/src/main/java/org/leavesmc/leaves/command/CommandArgument.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0bccbf7816ef621316f0da4911ec112f4753f88e
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/CommandArgument.java
|
|
@@ -0,0 +1,55 @@
|
|
+package org.leavesmc.leaves.command;
|
|
+
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.Arrays;
|
|
+import java.util.List;
|
|
+
|
|
+public class CommandArgument {
|
|
+
|
|
+ public static final CommandArgument EMPTY = new CommandArgument();
|
|
+
|
|
+ private final List<CommandArgumentType<?>> argumentTypes;
|
|
+ private final List<List<String>> tabComplete;
|
|
+
|
|
+ private CommandArgument(CommandArgumentType<?>... argumentTypes) {
|
|
+ this.argumentTypes = List.of(argumentTypes);
|
|
+ this.tabComplete = new ArrayList<>();
|
|
+ for (int i = 0; i < argumentTypes.length; i++) {
|
|
+ tabComplete.add(new ArrayList<>());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static CommandArgument of(CommandArgumentType<?>... argumentTypes) {
|
|
+ return new CommandArgument(argumentTypes);
|
|
+ }
|
|
+
|
|
+ public List<String> tabComplete(int n) {
|
|
+ if (tabComplete.size() > n) {
|
|
+ return tabComplete.get(n);
|
|
+ } else {
|
|
+ return List.of();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public CommandArgument setTabComplete(int index, List<String> list) {
|
|
+ tabComplete.set(index, list);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public CommandArgument setAllTabComplete(List<List<String>> tabComplete) {
|
|
+ this.tabComplete.clear();
|
|
+ this.tabComplete.addAll(tabComplete);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ public CommandArgumentResult parse(int index, String @NotNull [] args) {
|
|
+ Object[] result = new Object[argumentTypes.size()];
|
|
+ Arrays.fill(result, null);
|
|
+ for (int i = index, j = 0; i < args.length && j < result.length; i++, j++) {
|
|
+ result[j] = argumentTypes.get(j).pasre(args[i]);
|
|
+ }
|
|
+ return new CommandArgumentResult(new ArrayList<>(Arrays.asList(result)));
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java b/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..46aa6eaa75b65aad6bdbe4a5f517b42e87bcca77
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java
|
|
@@ -0,0 +1,69 @@
|
|
+package org.leavesmc.leaves.command;
|
|
+
|
|
+import net.minecraft.core.BlockPos;
|
|
+import org.bukkit.util.Vector;
|
|
+
|
|
+import java.util.List;
|
|
+import java.util.Objects;
|
|
+
|
|
+public class CommandArgumentResult {
|
|
+
|
|
+ private final List<Object> result;
|
|
+
|
|
+ public CommandArgumentResult(List<Object> result) {
|
|
+ this.result = result;
|
|
+ }
|
|
+
|
|
+ public int readInt(int def) {
|
|
+ return Objects.requireNonNullElse(read(Integer.class), def);
|
|
+ }
|
|
+
|
|
+ public double readDouble(double def) {
|
|
+ return Objects.requireNonNullElse(read(Double.class), def);
|
|
+ }
|
|
+
|
|
+ public float readFloat(float def) {
|
|
+ return Objects.requireNonNullElse(read(Float.class), def);
|
|
+ }
|
|
+
|
|
+ public String readString(String def) {
|
|
+ return Objects.requireNonNullElse(read(String.class), def);
|
|
+ }
|
|
+
|
|
+ public boolean readBoolean(boolean def) {
|
|
+ return Objects.requireNonNullElse(read(Boolean.class), def);
|
|
+ }
|
|
+
|
|
+ public BlockPos readPos() {
|
|
+ Integer[] pos = {read(Integer.class), read(Integer.class), read(Integer.class)};
|
|
+ for (Integer po : pos) {
|
|
+ if (po == null) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ return new BlockPos(pos[0], pos[1], pos[2]);
|
|
+ }
|
|
+
|
|
+ public Vector readVector() {
|
|
+ Double[] pos = {read(Double.class), read(Double.class), read(Double.class)};
|
|
+ for (Double po : pos) {
|
|
+ if (po == null) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ return new Vector(pos[0], pos[1], pos[2]);
|
|
+ }
|
|
+
|
|
+ public <T> T read(Class<T> tClass) {
|
|
+ if (result.isEmpty()) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ Object obj = result.remove(0);
|
|
+ if (tClass.isInstance(obj)) {
|
|
+ return tClass.cast(obj);
|
|
+ } else {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java b/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..4ca3508475bbd9771768704e300fe12b717489d6
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java
|
|
@@ -0,0 +1,55 @@
|
|
+package org.leavesmc.leaves.command;
|
|
+
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+public abstract class CommandArgumentType<E> {
|
|
+
|
|
+ public static final CommandArgumentType<Integer> INTEGER = new CommandArgumentType<>() {
|
|
+ @Override
|
|
+ public Integer pasre(@NotNull String arg) {
|
|
+ try {
|
|
+ return Integer.parseInt(arg);
|
|
+ } catch (NumberFormatException e) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ public static final CommandArgumentType<Double> DOUBLE = new CommandArgumentType<>() {
|
|
+ @Override
|
|
+ public Double pasre(@NotNull String arg) {
|
|
+ try {
|
|
+ return Double.parseDouble(arg);
|
|
+ } catch (NumberFormatException e) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ public static final CommandArgumentType<Float> FLOAT = new CommandArgumentType<>() {
|
|
+ @Override
|
|
+ public Float pasre(@NotNull String arg) {
|
|
+ try {
|
|
+ return Float.parseFloat(arg);
|
|
+ } catch (NumberFormatException e) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ public static final CommandArgumentType<String> STRING = new CommandArgumentType<>() {
|
|
+ @Override
|
|
+ public String pasre(@NotNull String arg) {
|
|
+ return arg;
|
|
+ }
|
|
+ };
|
|
+
|
|
+ public static final CommandArgumentType<Boolean> BOOLEAN = new CommandArgumentType<>() {
|
|
+ @Override
|
|
+ public Boolean pasre(@NotNull String arg) {
|
|
+ return Boolean.parseBoolean(arg);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ public abstract E pasre(@NotNull String arg);
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java b/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..393163c80b9e2ce04b089e90d20eefd7b7ad8366
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java
|
|
@@ -0,0 +1,117 @@
|
|
+package org.leavesmc.leaves.command;
|
|
+
|
|
+import it.unimi.dsi.fastutil.Pair;
|
|
+import net.minecraft.Util;
|
|
+import org.bukkit.Bukkit;
|
|
+import org.bukkit.Location;
|
|
+import org.bukkit.command.Command;
|
|
+import org.bukkit.command.CommandSender;
|
|
+import org.bukkit.permissions.Permission;
|
|
+import org.bukkit.permissions.PermissionDefault;
|
|
+import org.bukkit.plugin.PluginManager;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+import org.leavesmc.leaves.command.subcommands.*;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collections;
|
|
+import java.util.HashMap;
|
|
+import java.util.List;
|
|
+import java.util.Locale;
|
|
+import java.util.Map;
|
|
+import java.util.Set;
|
|
+import java.util.stream.Collectors;
|
|
+
|
|
+import static net.kyori.adventure.text.Component.text;
|
|
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
|
+
|
|
+public final class LeavesCommand extends Command {
|
|
+ static final String BASE_PERM = "bukkit.command.leaves.";
|
|
+ // subcommand label -> subcommand
|
|
+ private static final Map<String, LeavesSubcommand> SUBCOMMANDS = Util.make(() -> {
|
|
+ final Map<Set<String>, LeavesSubcommand> commands = new HashMap<>();
|
|
+ commands.put(Set.of("config"), new ConfigCommand());
|
|
+
|
|
+ return commands.entrySet().stream()
|
|
+ .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
|
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
|
+ });
|
|
+ private static final Set<String> COMPLETABLE_SUBCOMMANDS = SUBCOMMANDS.entrySet().stream().filter(entry -> entry.getValue().tabCompletes()).map(Map.Entry::getKey).collect(Collectors.toSet());
|
|
+
|
|
+ public LeavesCommand(final String name) {
|
|
+ super(name);
|
|
+ this.description = "Leaves related commands";
|
|
+ this.usageMessage = "/leaves [" + String.join(" | ", SUBCOMMANDS.keySet()) + "]";
|
|
+ final List<String> permissions = new ArrayList<>();
|
|
+ permissions.add("bukkit.command.leaves");
|
|
+ permissions.addAll(SUBCOMMANDS.keySet().stream().map(s -> BASE_PERM + s).toList());
|
|
+ this.setPermission(String.join(";", permissions));
|
|
+ final PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
|
+ for (final String perm : permissions) {
|
|
+ if (pluginManager.getPermission(perm) == null) {
|
|
+ pluginManager.addPermission(new Permission(perm, PermissionDefault.OP));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static boolean testPermission(final CommandSender sender, final String permission) {
|
|
+ if (sender.hasPermission(BASE_PERM + permission) || sender.hasPermission("bukkit.command.leaves")) {
|
|
+ return true;
|
|
+ }
|
|
+ sender.sendMessage(Bukkit.permissionMessage());
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+
|
|
+ @Override
|
|
+ public List<String> tabComplete(final @NotNull CommandSender sender, final @NotNull String alias, final String[] args, final @Nullable Location location) throws IllegalArgumentException {
|
|
+ if (args.length <= 1) {
|
|
+ return LeavesCommandUtil.getListMatchingLast(sender, args, COMPLETABLE_SUBCOMMANDS);
|
|
+ }
|
|
+
|
|
+ final @Nullable Pair<String, LeavesSubcommand> subCommand = resolveCommand(args[0]);
|
|
+ if (subCommand != null) {
|
|
+ return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length));
|
|
+ }
|
|
+
|
|
+ return Collections.emptyList();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean execute(final @NotNull CommandSender sender, final @NotNull String commandLabel, final String[] args) {
|
|
+ if (!testPermission(sender)) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ if (args.length == 0) {
|
|
+ sender.sendMessage(text("Usage: " + this.usageMessage, RED));
|
|
+ return false;
|
|
+ }
|
|
+ final Pair<String, LeavesSubcommand> subCommand = resolveCommand(args[0]);
|
|
+
|
|
+ if (subCommand == null) {
|
|
+ sender.sendMessage(text("Usage: " + this.usageMessage, RED));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!testPermission(sender, subCommand.first())) {
|
|
+ return true;
|
|
+ }
|
|
+ final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length);
|
|
+ return subCommand.second().execute(sender, subCommand.first(), choppedArgs);
|
|
+ }
|
|
+
|
|
+ @Nullable
|
|
+ private static Pair<String, LeavesSubcommand> resolveCommand(String label) {
|
|
+ label = label.toLowerCase(Locale.ENGLISH);
|
|
+ LeavesSubcommand subCommand = SUBCOMMANDS.get(label);
|
|
+
|
|
+ if (subCommand != null) {
|
|
+ return Pair.of(label, subCommand);
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java b/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..4b61fccc71d98a7b69bb7f88fb88ea0a55ca1ed2
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java
|
|
@@ -0,0 +1,18 @@
|
|
+package org.leavesmc.leaves.command;
|
|
+
|
|
+import org.bukkit.command.CommandSender;
|
|
+
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+
|
|
+public interface LeavesSubcommand {
|
|
+ boolean execute(CommandSender sender, String subCommand, String[] args);
|
|
+
|
|
+ default List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
|
+ return Collections.emptyList();
|
|
+ }
|
|
+
|
|
+ default boolean tabCompletes() {
|
|
+ return true;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java b/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..78471bde136d982f19f23beb3b121e4b254d124b
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java
|
|
@@ -0,0 +1,83 @@
|
|
+package org.leavesmc.leaves.command.subcommands;
|
|
+
|
|
+import net.kyori.adventure.text.Component;
|
|
+import net.kyori.adventure.text.JoinConfiguration;
|
|
+import net.kyori.adventure.text.format.NamedTextColor;
|
|
+import org.bukkit.command.CommandSender;
|
|
+import org.leavesmc.leaves.command.LeavesCommandUtil;
|
|
+import org.leavesmc.leaves.command.LeavesSubcommand;
|
|
+import org.leavesmc.leaves.config.GlobalConfigManager;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+
|
|
+public class ConfigCommand implements LeavesSubcommand {
|
|
+
|
|
+ @Override
|
|
+ public boolean execute(CommandSender sender, String subCommand, String[] args) {
|
|
+ if (args.length < 1) {
|
|
+ sender.sendMessage(Component.text("Leaves Config", NamedTextColor.GRAY));
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ GlobalConfigManager.VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]);
|
|
+ if (verifiedConfig == null) {
|
|
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
|
+ Component.text("Config ", NamedTextColor.GRAY),
|
|
+ Component.text(args[0], NamedTextColor.RED),
|
|
+ Component.text(" is Not Found.", NamedTextColor.GRAY)
|
|
+ ));
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ if (args.length > 1) {
|
|
+ try {
|
|
+ verifiedConfig.set(args[1]);
|
|
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
|
+ Component.text("Config ", NamedTextColor.GRAY),
|
|
+ Component.text(args[0], NamedTextColor.AQUA),
|
|
+ Component.text(" changed to ", NamedTextColor.GRAY),
|
|
+ Component.text(verifiedConfig.getString(), NamedTextColor.AQUA)
|
|
+ ));
|
|
+ } catch (IllegalArgumentException exception) {
|
|
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
|
+ Component.text("Config ", NamedTextColor.GRAY),
|
|
+ Component.text(args[0], NamedTextColor.RED),
|
|
+ Component.text(" modify error by ", NamedTextColor.GRAY),
|
|
+ Component.text(exception.getMessage(), NamedTextColor.RED)
|
|
+ ));
|
|
+ }
|
|
+ } else {
|
|
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
|
+ Component.text("Config ", NamedTextColor.GRAY),
|
|
+ Component.text(args[0], NamedTextColor.AQUA),
|
|
+ Component.text(" value is ", NamedTextColor.GRAY),
|
|
+ Component.text(verifiedConfig.getString(), NamedTextColor.AQUA)
|
|
+ ));
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<String> tabComplete(CommandSender sender, String subCommand, String[] args) {
|
|
+ switch (args.length) {
|
|
+ case 1 -> {
|
|
+ List<String> list = new ArrayList<>(GlobalConfigManager.getVerifiedConfigPaths());
|
|
+ return LeavesCommandUtil.getListMatchingLast(sender, args, list);
|
|
+ }
|
|
+
|
|
+ case 2 -> {
|
|
+ GlobalConfigManager.VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]);
|
|
+ if (verifiedConfig != null) {
|
|
+ return LeavesCommandUtil.getListMatchingLast(sender, args, verifiedConfig.verify().valueSuggest());
|
|
+ } else {
|
|
+ return Collections.singletonList("<ERROR CONFIG>");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return Collections.emptyList();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/ConfigConvert.java b/src/main/java/org/leavesmc/leaves/config/ConfigConvert.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..2ce05259acfeb2e28895502b72afd66938bf520b
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/ConfigConvert.java
|
|
@@ -0,0 +1,20 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+public interface ConfigConvert<E> {
|
|
+
|
|
+ E convert(String value) throws IllegalArgumentException;
|
|
+
|
|
+ default E loadConvert(Object value) throws IllegalArgumentException {
|
|
+ try {
|
|
+ return (E) value;
|
|
+ } catch (ClassCastException e) {
|
|
+ throw new IllegalArgumentException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ default Object saveConvert(E value) {
|
|
+ return value;
|
|
+ }
|
|
+
|
|
+ Class<E> getFieldClass();
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/ConfigVerify.java b/src/main/java/org/leavesmc/leaves/config/ConfigVerify.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b77b9648829268d7fa591e059ddbc584a38ebd49
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/ConfigVerify.java
|
|
@@ -0,0 +1,16 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import java.util.List;
|
|
+
|
|
+public interface ConfigVerify<E> extends ConfigConvert<E> {
|
|
+
|
|
+ default void check(E old, E value) throws IllegalArgumentException {
|
|
+ }
|
|
+
|
|
+ default List<String> valueSuggest() {
|
|
+ return List.of("<value>");
|
|
+ }
|
|
+
|
|
+ default void runAfterLoader(E value, boolean firstLoad) {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/ConfigVerifyImpl.java b/src/main/java/org/leavesmc/leaves/config/ConfigVerifyImpl.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b0a71eaaeebb9887ee74f3a06fe46fc9ff41c7cb
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/ConfigVerifyImpl.java
|
|
@@ -0,0 +1,117 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+import java.lang.reflect.ParameterizedType;
|
|
+import java.lang.reflect.Type;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.Locale;
|
|
+
|
|
+public abstract class ConfigVerifyImpl<E> implements ConfigVerify<E> {
|
|
+
|
|
+ private Class<E> fieldClass;
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ConfigVerifyImpl() {
|
|
+ Type superClass = getClass().getGenericSuperclass();
|
|
+ if (superClass instanceof ParameterizedType) {
|
|
+ Type[] actualTypeArguments = ((ParameterizedType) superClass).getActualTypeArguments();
|
|
+ if (actualTypeArguments[0] instanceof Class) {
|
|
+ this.fieldClass = (Class<E>) actualTypeArguments[0];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<E> getFieldClass() {
|
|
+ return fieldClass;
|
|
+ }
|
|
+
|
|
+ public static class BooleanConfigVerify extends ConfigVerifyImpl<Boolean> {
|
|
+
|
|
+ @Override
|
|
+ public Boolean convert(String value) throws IllegalArgumentException {
|
|
+ return Boolean.parseBoolean(value);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<String> valueSuggest() {
|
|
+ return List.of("false", "true");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class IntConfigVerify extends ConfigVerifyImpl<Integer> {
|
|
+ @Override
|
|
+ public Integer convert(String value) throws IllegalArgumentException {
|
|
+ return Integer.parseInt(value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class StringConfigVerify extends ConfigVerifyImpl<String> {
|
|
+ @Override
|
|
+ public String convert(String value) throws IllegalArgumentException {
|
|
+ return value;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class DoubleConfigVerify extends ConfigVerifyImpl<Double> {
|
|
+ @Override
|
|
+ public Double convert(String value) throws IllegalArgumentException {
|
|
+ return Double.parseDouble(value);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public abstract static class ListConfigVerify<E> extends ConfigVerifyImpl<List<E>> {
|
|
+ public static class STRING extends ListConfigVerify<String> {
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<E> convert(String value) throws IllegalArgumentException {
|
|
+ throw new IllegalArgumentException("not support"); // TODO
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public abstract static class EnumConfigVerify<E extends Enum<E>> extends ConfigVerifyImpl<E> {
|
|
+
|
|
+ private final Class<E> enumClass;
|
|
+ private final List<String> enumValues;
|
|
+
|
|
+ @SuppressWarnings({"unchecked", "unused"})
|
|
+ public EnumConfigVerify() {
|
|
+ Type genericSuperclass = getClass().getGenericSuperclass();
|
|
+ Type[] typeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
|
|
+ this.enumClass = (Class<E>) typeArguments[0];
|
|
+ this.enumValues = new ArrayList<>() {{
|
|
+ for (E e : enumClass.getEnumConstants()) {
|
|
+ add(e.name().toLowerCase(Locale.ROOT));
|
|
+ }
|
|
+ }};
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public E convert(@NotNull String value) throws IllegalArgumentException {
|
|
+ return Enum.valueOf(enumClass, value.toUpperCase(Locale.ROOT));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public E loadConvert(@NotNull Object value) throws IllegalArgumentException {
|
|
+ return this.convert(value.toString());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object saveConvert(@NotNull E value) {
|
|
+ return value.toString().toUpperCase(Locale.ROOT);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<String> valueSuggest() {
|
|
+ return enumValues;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<E> getFieldClass() {
|
|
+ return enumClass;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/GlobalConfig.java b/src/main/java/org/leavesmc/leaves/config/GlobalConfig.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d55ffed5026edfa1d37e310edbb74ac56b0d0c81
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/GlobalConfig.java
|
|
@@ -0,0 +1,19 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+import java.lang.annotation.Target;
|
|
+
|
|
+@Target(ElementType.FIELD)
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface GlobalConfig {
|
|
+
|
|
+ String name();
|
|
+
|
|
+ String[] category();
|
|
+
|
|
+ boolean lock() default false;
|
|
+
|
|
+ Class<? extends ConfigVerify<?>> verify() default ConfigVerifyImpl.BooleanConfigVerify.class;
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/GlobalConfigCreator.java b/src/main/java/org/leavesmc/leaves/config/GlobalConfigCreator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..26304b8d8fcfbe68325b686fe37171e2851dbd81
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/GlobalConfigCreator.java
|
|
@@ -0,0 +1,56 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import org.bukkit.configuration.file.YamlConfiguration;
|
|
+import org.leavesmc.leaves.LeavesConfig;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.util.Collections;
|
|
+
|
|
+public class GlobalConfigCreator {
|
|
+
|
|
+ public static void main(String[] args) {
|
|
+ YamlConfiguration config = new YamlConfiguration();
|
|
+ config.options().setHeader(Collections.singletonList(LeavesConfig.CONFIG_HEADER));
|
|
+
|
|
+ config.set("config-version", LeavesConfig.CURRENT_CONFIG_VERSION);
|
|
+
|
|
+ Class<LeavesConfig> clazz = LeavesConfig.class;
|
|
+
|
|
+ for (Field field : clazz.getDeclaredFields()) {
|
|
+ if (Modifier.isStatic(field.getModifiers())) {
|
|
+ field.setAccessible(true);
|
|
+
|
|
+ GlobalConfig globalConfig = field.getAnnotation(GlobalConfig.class);
|
|
+ if (globalConfig != null) {
|
|
+ try {
|
|
+ GlobalConfigManager.VerifiedConfig verifiedConfig = GlobalConfigManager.VerifiedConfig.build(globalConfig, field);
|
|
+
|
|
+ ConfigVerify<? super Object> verify = verifiedConfig.verify();
|
|
+ boolean isEnumConfig = verify instanceof ConfigVerifyImpl.EnumConfigVerify;
|
|
+
|
|
+ Object defValue = isEnumConfig ? field.get(null).toString() : field.get(null);
|
|
+ config.set(verifiedConfig.path(), defValue);
|
|
+ } catch (Exception e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ config.set("settings.protocol.xaero-map-server-id", 0);
|
|
+
|
|
+ try {
|
|
+ File file = new File("leaves.yml");
|
|
+ if (file.exists()) {
|
|
+ file.delete();
|
|
+ }
|
|
+ file.createNewFile();
|
|
+ config.save(file);
|
|
+ } catch (IOException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/GlobalConfigManager.java b/src/main/java/org/leavesmc/leaves/config/GlobalConfigManager.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..7eb14d1725bb250f8a5983bad1f4641dc51aa939
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/GlobalConfigManager.java
|
|
@@ -0,0 +1,204 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import org.bukkit.Bukkit;
|
|
+import org.leavesmc.leaves.LeavesConfig;
|
|
+import org.leavesmc.leaves.LeavesLogger;
|
|
+
|
|
+import java.lang.reflect.Constructor;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+import java.util.Set;
|
|
+import java.util.logging.Level;
|
|
+
|
|
+public class GlobalConfigManager {
|
|
+
|
|
+ private static boolean firstLoad = true;
|
|
+ private static final Map<String, VerifiedConfig> verifiedConfigs = new HashMap<>();
|
|
+
|
|
+ public static void init() {
|
|
+ verifiedConfigs.clear();
|
|
+
|
|
+ Class<LeavesConfig> clazz = LeavesConfig.class;
|
|
+ for (Field field : clazz.getDeclaredFields()) {
|
|
+ if (Modifier.isStatic(field.getModifiers())) {
|
|
+ field.setAccessible(true);
|
|
+
|
|
+ for (RemovedConfig removedConfig : field.getAnnotationsByType(RemovedConfig.class)) {
|
|
+ RemovedVerifiedConfig verifiedConfig = RemovedVerifiedConfig.build(removedConfig, field);
|
|
+ verifiedConfig.run();
|
|
+ }
|
|
+
|
|
+ GlobalConfig globalConfig = field.getAnnotation(GlobalConfig.class);
|
|
+ if (globalConfig != null) {
|
|
+ try {
|
|
+ VerifiedConfig verifiedConfig = VerifiedConfig.build(globalConfig, field);
|
|
+
|
|
+ if (globalConfig.lock() && !firstLoad) {
|
|
+ verifiedConfigs.put(verifiedConfig.path.substring("settings.".length()), verifiedConfig);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ ConfigVerify<? super Object> verify = verifiedConfig.verify;
|
|
+
|
|
+ Object defValue = verify.saveConvert(field.get(null));
|
|
+ LeavesConfig.config.addDefault(verifiedConfig.path, defValue);
|
|
+
|
|
+ try {
|
|
+ Object savedValue = LeavesConfig.config.get(verifiedConfig.path);
|
|
+ if (savedValue == null) {
|
|
+ throw new IllegalArgumentException("?");
|
|
+ }
|
|
+
|
|
+ if (savedValue.getClass() != verify.getFieldClass()) {
|
|
+ savedValue = verify.loadConvert(savedValue);
|
|
+ }
|
|
+
|
|
+ verify.check(null, savedValue);
|
|
+
|
|
+ field.set(null, savedValue);
|
|
+ } catch (IllegalArgumentException | ClassCastException e) {
|
|
+ LeavesConfig.config.set(verifiedConfig.path, defValue);
|
|
+ LeavesLogger.LOGGER.warning(e.getMessage() + ", reset to " + defValue);
|
|
+ }
|
|
+
|
|
+ verifiedConfigs.put(verifiedConfig.path.substring("settings.".length()), verifiedConfig);
|
|
+ } catch (Exception e) {
|
|
+ Bukkit.getLogger().log(Level.SEVERE, "Failure to load leaves config", e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ verifiedConfigs.forEach((path, config) -> config.verify.runAfterLoader(config.get(), firstLoad));
|
|
+
|
|
+ firstLoad = false;
|
|
+ LeavesConfig.save();
|
|
+ }
|
|
+
|
|
+ public static VerifiedConfig getVerifiedConfig(String path) {
|
|
+ return verifiedConfigs.get(path);
|
|
+ }
|
|
+
|
|
+ public static Set<String> getVerifiedConfigPaths() {
|
|
+ return verifiedConfigs.keySet();
|
|
+ }
|
|
+
|
|
+ public record RemovedVerifiedConfig(RemovedConfig config, ConfigConvert<? super Object> convert, Field field, String path) {
|
|
+
|
|
+ public void run() {
|
|
+ if (config.transform()) {
|
|
+ if (LeavesConfig.config.contains(path)) {
|
|
+ Object savedValue = LeavesConfig.config.get(path);
|
|
+ if (savedValue != null) {
|
|
+ try {
|
|
+ if (savedValue.getClass() != convert.getFieldClass()) {
|
|
+ savedValue = convert.loadConvert(savedValue);
|
|
+ }
|
|
+ field.set(null, savedValue);
|
|
+ } catch (IllegalAccessException | IllegalArgumentException e) {
|
|
+ LeavesLogger.LOGGER.warning("Failure to load leaves config" + path, e);
|
|
+ }
|
|
+ } else {
|
|
+ LeavesLogger.LOGGER.warning("Failed to convert saved value for " + path + ", reset to default");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ LeavesConfig.config.set(path, null);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("all")
|
|
+ public static RemovedVerifiedConfig build(RemovedConfig config, Field field) {
|
|
+ StringBuilder path = new StringBuilder("settings.");
|
|
+ for (int i = 0; i < config.category().length; i++) {
|
|
+ path.append(config.category()[i]).append(".");
|
|
+ }
|
|
+ path.append(config.name());
|
|
+
|
|
+ ConfigConvert configConvert = null;
|
|
+ try {
|
|
+ Constructor<? extends ConfigConvert<?>> constructor = config.convert().getDeclaredConstructor();
|
|
+ constructor.setAccessible(true);
|
|
+ configConvert = constructor.newInstance();
|
|
+ } catch (Exception e) {
|
|
+ LeavesLogger.LOGGER.warning("Failure to load leaves config" + path, e);
|
|
+ }
|
|
+
|
|
+ return new RemovedVerifiedConfig(config, configConvert, field, path.toString());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public record VerifiedConfig(GlobalConfig config, ConfigVerify<? super Object> verify, Field field, String path) {
|
|
+
|
|
+ public void set(String realValue) throws IllegalArgumentException {
|
|
+ Object value;
|
|
+ try {
|
|
+ value = verify.convert(realValue);
|
|
+ } catch (IllegalArgumentException e) {
|
|
+ throw new IllegalArgumentException("value parse error: " + e.getMessage());
|
|
+ }
|
|
+
|
|
+ verify.check(this.get(), value);
|
|
+
|
|
+ try {
|
|
+ LeavesConfig.config.set(path, verify.saveConvert(value));
|
|
+ LeavesConfig.save();
|
|
+ if (config.lock()) {
|
|
+ throw new IllegalArgumentException("locked, will load after restart");
|
|
+ }
|
|
+ field.set(null, value);
|
|
+ } catch (IllegalAccessException e) {
|
|
+ throw new IllegalArgumentException(e.getMessage());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public String getString() {
|
|
+ Object value = this.get();
|
|
+
|
|
+ Object savedValue = LeavesConfig.config.get(path);
|
|
+ try {
|
|
+ if (savedValue != null) {
|
|
+ if (verify.getFieldClass() != savedValue.getClass()) {
|
|
+ savedValue = verify.loadConvert(savedValue);
|
|
+ }
|
|
+
|
|
+ if (!savedValue.equals(value)) {
|
|
+ return value.toString() + "(" + savedValue + " after restart)";
|
|
+ }
|
|
+ }
|
|
+ } catch (IllegalArgumentException ignore) {
|
|
+ }
|
|
+ return value.toString();
|
|
+ }
|
|
+
|
|
+ public Object get() {
|
|
+ try {
|
|
+ return field.get(null);
|
|
+ } catch (IllegalAccessException e) {
|
|
+ LeavesLogger.LOGGER.log(Level.SEVERE, "Failure to get " + path + " value", e);
|
|
+ return "<VALUE ERROR>";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("all")
|
|
+ public static VerifiedConfig build(GlobalConfig config, Field field) {
|
|
+ StringBuilder path = new StringBuilder("settings.");
|
|
+ for (int i = 0; i < config.category().length; i++) {
|
|
+ path.append(config.category()[i]).append(".");
|
|
+ }
|
|
+ path.append(config.name());
|
|
+
|
|
+ ConfigVerify configVerify = null;
|
|
+ try {
|
|
+ Constructor<? extends ConfigVerify<?>> constructor = config.verify().getDeclaredConstructor();
|
|
+ constructor.setAccessible(true);
|
|
+ configVerify = constructor.newInstance();
|
|
+ } catch (Exception e) {
|
|
+ LeavesLogger.LOGGER.warning("Failure to load leaves config" + path, e);
|
|
+ }
|
|
+
|
|
+ return new VerifiedConfig(config, configVerify, field, path.toString());
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/RemovedConfig.java b/src/main/java/org/leavesmc/leaves/config/RemovedConfig.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..a0f222d0fe7bbc09d3b894e121ad5b303c29375f
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/RemovedConfig.java
|
|
@@ -0,0 +1,21 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.lang.annotation.Repeatable;
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+import java.lang.annotation.Target;
|
|
+
|
|
+@Target(ElementType.FIELD)
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+@Repeatable(RemovedConfigs.class)
|
|
+public @interface RemovedConfig {
|
|
+
|
|
+ String name();
|
|
+
|
|
+ String[] category();
|
|
+
|
|
+ boolean transform() default false;
|
|
+
|
|
+ Class<? extends ConfigConvert<?>> convert() default ConfigVerifyImpl.BooleanConfigVerify.class;
|
|
+}
|
|
diff --git a/src/main/java/org/leavesmc/leaves/config/RemovedConfigs.java b/src/main/java/org/leavesmc/leaves/config/RemovedConfigs.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b1ab6db328b562a8ab7d2091b47b81cee739adf1
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/config/RemovedConfigs.java
|
|
@@ -0,0 +1,12 @@
|
|
+package org.leavesmc.leaves.config;
|
|
+
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+import java.lang.annotation.Target;
|
|
+
|
|
+@Target(ElementType.FIELD)
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface RemovedConfigs {
|
|
+ RemovedConfig[] value();
|
|
+}
|