1063 lines
63 KiB
Diff
1063 lines
63 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: MartijnMuijsers <martijnmuijsers@live.nl>
|
|
Date: Thu, 13 Oct 2022 18:09:28 +0200
|
|
Subject: [PATCH] Suki Patches
|
|
|
|
Original code by SuCraft, licensed under GPL-3.0.
|
|
You can find the original code on https://github.com/SuCraft/Suki
|
|
0002-Suki-configuration-and-commands.patch
|
|
0012-Only-refresh-lootables-for-players.patch
|
|
0013-Optimize-harmless-explosions.patch
|
|
0016-Send-more-packets-immediately.patch
|
|
0017-Flush-after-more-packets.patch
|
|
0018-Do-not-relocate-corrupted-chunks.patch
|
|
0015-Multithreading environment variables.patch
|
|
|
|
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
|
|
index 2cc44fbf8e5bd436b6d4e19f6c06b351e750cb31..991b06836df310913a14ce1c60979a2c2944b0e5 100644
|
|
--- a/src/main/java/co/aikar/timings/TimingsExport.java
|
|
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
|
|
@@ -29,6 +29,7 @@ import net.kyori.adventure.text.event.ClickEvent;
|
|
import net.kyori.adventure.text.format.NamedTextColor;
|
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
|
import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.dedicated.DedicatedServer;
|
|
import org.apache.commons.lang.StringUtils;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Material;
|
|
@@ -242,7 +243,8 @@ public class TimingsExport extends Thread {
|
|
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
|
|
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
|
|
pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Pufferfish
|
|
- pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)) // Pufferfish
|
|
+ pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)), // Pufferfish
|
|
+ pair("suki", mapAsJSON(Bukkit.spigot().getSukiConfig(), null)) // Suki - Suki configuration
|
|
));
|
|
|
|
new TimingsExport(listeners, parent, history).start();
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java b/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java
|
|
index 7a4a7a654fe2516ed894a68f2657344df9d70f4c..0a501c3ba5382dae230122066c131de631edff0d 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java
|
|
@@ -1,6 +1,6 @@
|
|
package io.papermc.paper.configuration;
|
|
|
|
-abstract class ConfigurationPart {
|
|
+public abstract class ConfigurationPart { // Suki - Suki configuration
|
|
|
|
public static abstract class Post extends ConfigurationPart {
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/Configurations.java b/src/main/java/io/papermc/paper/configuration/Configurations.java
|
|
index c2dca89291361d60cbf160cab77749cb0130035a..aedd5aec308dd206ce149e2b303323e5a8adb88e 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/Configurations.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/Configurations.java
|
|
@@ -5,7 +5,10 @@ import io.leangen.geantyref.TypeToken;
|
|
import io.papermc.paper.configuration.constraint.Constraint;
|
|
import io.papermc.paper.configuration.constraint.Constraints;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
+import org.bukkit.configuration.ConfigurationSection;
|
|
+import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
import org.jetbrains.annotations.MustBeInvokedByOverriders;
|
|
import org.slf4j.Logger;
|
|
@@ -17,6 +20,8 @@ import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
|
import org.spongepowered.configurate.serialize.SerializationException;
|
|
import org.spongepowered.configurate.util.CheckedFunction;
|
|
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
|
+import org.sucraft.suki.configuration.SukiConfigurations;
|
|
+import org.sucraft.suki.configuration.SukiWorldConfiguration;
|
|
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Type;
|
|
@@ -88,7 +93,7 @@ public abstract class Configurations<G, W> {
|
|
};
|
|
}
|
|
|
|
- static <T> CheckedFunction<ConfigurationNode, T, SerializationException> reloader(Class<T> type, T instance) {
|
|
+ public static <T> CheckedFunction<ConfigurationNode, T, SerializationException> reloader(Class<T> type, T instance) { // Suki - Suki configuration
|
|
return node -> {
|
|
ObjectMapper.Factory factory = (ObjectMapper.Factory) Objects.requireNonNull(node.options().serializers().get(type));
|
|
ObjectMapper.Mutable<T> mutable = (ObjectMapper.Mutable<T>) factory.get(type);
|
|
@@ -148,7 +153,7 @@ public abstract class Configurations<G, W> {
|
|
final YamlConfigurationLoader loader = result.loader();
|
|
final ConfigurationNode node = loader.load();
|
|
if (result.isNewFile()) { // add version to new files
|
|
- node.node(Configuration.VERSION_FIELD).raw(WorldConfiguration.CURRENT_VERSION);
|
|
+ node.node(Configuration.VERSION_FIELD).raw(getWorldConfigurationCurrentVersion()); // Suki - Suki configuration
|
|
}
|
|
this.applyWorldConfigTransformations(contextMap, node);
|
|
final W instance = node.require(this.worldConfigClass);
|
|
@@ -207,7 +212,7 @@ public abstract class Configurations<G, W> {
|
|
.build();
|
|
final ConfigurationNode worldNode = worldLoader.load();
|
|
if (newFile) { // set the version field if new file
|
|
- worldNode.node(Configuration.VERSION_FIELD).set(WorldConfiguration.CURRENT_VERSION);
|
|
+ worldNode.node(Configuration.VERSION_FIELD).set(getWorldConfigurationCurrentVersion()); // Suki - Suki configuration
|
|
}
|
|
this.applyWorldConfigTransformations(contextMap, worldNode);
|
|
this.applyDefaultsAwareWorldConfigTransformations(contextMap, worldNode, defaultsNode);
|
|
@@ -308,4 +313,21 @@ public abstract class Configurations<G, W> {
|
|
return "ContextKey{" + this.name + "}";
|
|
}
|
|
}
|
|
+
|
|
+ // Suki start - Suki configuration
|
|
+
|
|
+ @Deprecated
|
|
+ public YamlConfiguration createLegacyObject(final MinecraftServer server) {
|
|
+ YamlConfiguration global = YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.globalConfigFileName).toFile());
|
|
+ ConfigurationSection worlds = global.createSection("__________WORLDS__________");
|
|
+ worlds.set("__defaults__", YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.defaultWorldConfigFileName).toFile()));
|
|
+ for (ServerLevel level : server.getAllLevels()) {
|
|
+ worlds.set(level.getWorld().getName(), YamlConfiguration.loadConfiguration(getWorldConfigFile(level).toFile()));
|
|
+ }
|
|
+ return global;
|
|
+ }
|
|
+
|
|
+ public abstract int getWorldConfigurationCurrentVersion();
|
|
+ // Suki end - Suki configuration
|
|
+
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/InnerClassFieldDiscoverer.java b/src/main/java/io/papermc/paper/configuration/InnerClassFieldDiscoverer.java
|
|
index a0aa1f1a7adf986d500a2135aa42e138aa3c4f08..bc3907beb2aa63259300e8960039bd59397d071e 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/InnerClassFieldDiscoverer.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/InnerClassFieldDiscoverer.java
|
|
@@ -5,6 +5,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|
import org.spongepowered.configurate.objectmapping.FieldDiscoverer;
|
|
import org.spongepowered.configurate.serialize.SerializationException;
|
|
import org.spongepowered.configurate.util.CheckedSupplier;
|
|
+import org.sucraft.suki.configuration.SukiWorldConfiguration;
|
|
|
|
import java.lang.reflect.AnnotatedType;
|
|
import java.lang.reflect.Constructor;
|
|
@@ -17,7 +18,7 @@ import java.util.Map;
|
|
|
|
import static io.leangen.geantyref.GenericTypeReflector.erase;
|
|
|
|
-final class InnerClassFieldDiscoverer implements FieldDiscoverer<Map<Field, Object>> {
|
|
+public final class InnerClassFieldDiscoverer implements FieldDiscoverer<Map<Field, Object>> { // Suki - Suki configuration
|
|
|
|
private final Map<Class<?>, Object> instanceMap = new HashMap<>();
|
|
private final Map<Class<?>, Object> overrides;
|
|
@@ -136,7 +137,19 @@ final class InnerClassFieldDiscoverer implements FieldDiscoverer<Map<Field, Obje
|
|
return new InnerClassFieldDiscoverer(overrides);
|
|
}
|
|
|
|
- static FieldDiscoverer<?> globalConfig() {
|
|
+ // Suki start - Suki configuration
|
|
+ public static FieldDiscoverer<?> sukiWorldConfig(Configurations.ContextMap contextMap) {
|
|
+ final Map<Class<?>, Object> overrides = Map.of(
|
|
+ SukiWorldConfiguration.class, new SukiWorldConfiguration(
|
|
+ contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(),
|
|
+ contextMap.require(Configurations.WORLD_KEY)
|
|
+ )
|
|
+ );
|
|
+ return new InnerClassFieldDiscoverer(overrides);
|
|
+ }
|
|
+ // Suki end - Suki configuration
|
|
+
|
|
+ public static FieldDiscoverer<?> globalConfig() { // Suki - Suki configuration
|
|
return new InnerClassFieldDiscoverer(Collections.emptyMap());
|
|
}
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
index e731de3ac158c5a4cff236c6f5001674cd488a77..06a6cecfa01c676285ea894c3ed77d0e2d96ba91 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
|
|
@@ -125,13 +125,13 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
|
|
See https://docs.papermc.io/paper/configuration for more information.
|
|
""";
|
|
|
|
- private static final Supplier<SpigotWorldConfig> SPIGOT_WORLD_DEFAULTS = Suppliers.memoize(() -> new SpigotWorldConfig(RandomStringUtils.randomAlphabetic(255)) {
|
|
+ public static final Supplier<SpigotWorldConfig> SPIGOT_WORLD_DEFAULTS = Suppliers.memoize(() -> new SpigotWorldConfig(RandomStringUtils.randomAlphabetic(255)) { // Suki - Suki configuration
|
|
@Override // override to ensure "verbose" is false
|
|
public void init() {
|
|
SpigotConfig.readConfig(SpigotWorldConfig.class, this);
|
|
}
|
|
});
|
|
- static final ContextKey<Supplier<SpigotWorldConfig>> SPIGOT_WORLD_CONFIG_CONTEXT_KEY = new ContextKey<>(new TypeToken<Supplier<SpigotWorldConfig>>() {}, "spigot world config");
|
|
+ public static final ContextKey<Supplier<SpigotWorldConfig>> SPIGOT_WORLD_CONFIG_CONTEXT_KEY = new ContextKey<>(new TypeToken<Supplier<SpigotWorldConfig>>() {}, "spigot world config"); // Suki - Suki configuration
|
|
|
|
|
|
public PaperConfigurations(final Path globalFolder) {
|
|
@@ -293,7 +293,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
|
|
}
|
|
}
|
|
|
|
- private static ContextMap createWorldContextMap(ServerLevel level) {
|
|
+ public static ContextMap createWorldContextMap(ServerLevel level) { // Suki - Suki configuration
|
|
return createWorldContextMap(level.convertable.levelDirectory.path(), level.serverLevelData.getLevelName(), level.dimension().location(), level.spigotConfig);
|
|
}
|
|
|
|
@@ -394,17 +394,6 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
|
|
return Files.exists(legacyConfig) && Files.isRegularFile(legacyConfig);
|
|
}
|
|
|
|
- @Deprecated
|
|
- public YamlConfiguration createLegacyObject(final MinecraftServer server) {
|
|
- YamlConfiguration global = YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.globalConfigFileName).toFile());
|
|
- ConfigurationSection worlds = global.createSection("__________WORLDS__________");
|
|
- worlds.set("__defaults__", YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.defaultWorldConfigFileName).toFile()));
|
|
- for (ServerLevel level : server.getAllLevels()) {
|
|
- worlds.set(level.getWorld().getName(), YamlConfiguration.loadConfiguration(getWorldConfigFile(level).toFile()));
|
|
- }
|
|
- return global;
|
|
- }
|
|
-
|
|
@Deprecated
|
|
public static YamlConfiguration loadLegacyConfigFile(File configFile) throws Exception {
|
|
YamlConfiguration config = new YamlConfiguration();
|
|
@@ -427,9 +416,16 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
|
|
}
|
|
|
|
// Symlinks are not correctly checked in createDirectories
|
|
- static void createDirectoriesSymlinkAware(Path path) throws IOException {
|
|
+ public static void createDirectoriesSymlinkAware(Path path) throws IOException { // Suki - Suki configuration
|
|
if (!Files.isDirectory(path)) {
|
|
Files.createDirectories(path);
|
|
}
|
|
}
|
|
+
|
|
+ // Suki start - Suki configuration
|
|
+ @Override
|
|
+ public int getWorldConfigurationCurrentVersion() {
|
|
+ return WorldConfiguration.CURRENT_VERSION;
|
|
+ }
|
|
+ // Suki end - Suki configuration
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
|
index b759f82b265542f42821e35ead56a5c073625d36..f93cbf0812801bb503db26e623d988e4eeb8b126 100644
|
|
--- a/src/main/java/net/minecraft/Util.java
|
|
+++ b/src/main/java/net/minecraft/Util.java
|
|
@@ -27,7 +27,6 @@ import java.net.URL;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.spi.FileSystemProvider;
|
|
-import java.security.AccessController;
|
|
import java.security.PrivilegedActionException;
|
|
import java.security.PrivilegedExceptionAction;
|
|
import java.time.Duration;
|
|
@@ -151,9 +150,15 @@ public class Util {
|
|
}
|
|
|
|
private static ExecutorService makeExecutor(String s, int priorityModifier) { // Paper - add priority
|
|
+ // Suki start - multithreading environment variables
|
|
+ return makeExecutor(s, priorityModifier, -1);
|
|
+ }
|
|
+
|
|
+ public static ExecutorService makeExecutor(String s, int priorityModifier, int specificThreads) {
|
|
+ // Suki end - multithreading environment variables
|
|
// Paper start - use simpler thread pool that allows 1 thread
|
|
// Paper start - also try to avoid suffocating the system with the worldgen workers
|
|
- int cpus = Runtime.getRuntime().availableProcessors() / 2;
|
|
+ int cpus = Integer.getInteger("suki.systemcpus.forexecutors", Runtime.getRuntime().availableProcessors() / 2); // Suki - multithreading environment variables
|
|
int i;
|
|
if (cpus <= 4) {
|
|
i = cpus <= 2 ? 1 : 2;
|
|
@@ -166,6 +171,11 @@ public class Util {
|
|
i = Math.min(8, i);
|
|
// Paper end - also try to avoid suffocating the system with the worldgen workers
|
|
i = Integer.getInteger("Paper.WorkerThreadCount", i);
|
|
+ // Suki start - multithreading environment variables
|
|
+ if (specificThreads > 0) {
|
|
+ i = specificThreads;
|
|
+ }
|
|
+ // Suki end - multithreading environment variables
|
|
ExecutorService executorService;
|
|
|
|
if (i <= 0) {
|
|
@@ -173,7 +183,7 @@ public class Util {
|
|
} else {
|
|
//executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<Runnable>(), target -> new net.minecraft.server.ServerWorkerThread(target, s, priorityModifier)); // JettPack
|
|
// JettPack start
|
|
- executorService = Integer.getInteger("Paper.WorkerThreadCount", i) <= 0 ? MoreExecutors.newDirectExecutorService() : new AbstractExecutorService(){
|
|
+ executorService = new AbstractExecutorService(){ // Suki - multithreading environment variables
|
|
private volatile boolean shutdown = false;
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
|
index e1563410e0711de5cf9363978125e637929392da..948e988cdcf3edb0ceb0bd397d0579a1784d9ae1 100644
|
|
--- a/src/main/java/net/minecraft/network/Connection.java
|
|
+++ b/src/main/java/net/minecraft/network/Connection.java
|
|
@@ -355,7 +355,11 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
packet instanceof net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket ||
|
|
packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket ||
|
|
packet instanceof net.minecraft.network.protocol.game.ClientboundClearTitlesPacket ||
|
|
- packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket;
|
|
+ // Suki start - send more packets immediately
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundMapItemDataPacket;
|
|
+ // Suki end - send more packets immediately
|
|
}
|
|
// Paper end
|
|
}
|
|
@@ -406,7 +410,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
|
private void sendPacket(Packet<?> packet, @Nullable PacketSendListener callbacks, Boolean flushConditional) {
|
|
this.packetWrites.getAndIncrement(); // must be befeore using canFlush
|
|
boolean effectiveFlush = flushConditional == null ? this.canFlush : flushConditional.booleanValue();
|
|
- final boolean flush = effectiveFlush || packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket || packet instanceof ClientboundDisconnectPacket; // no delay for certain packets
|
|
+ // Suki start - flush after more packets
|
|
+ final boolean flush = effectiveFlush ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket ||
|
|
+ packet instanceof ClientboundDisconnectPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundForgetLevelChunkPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket ||
|
|
+ packet instanceof net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; // no delay for certain packets
|
|
+ // Suki end - flush after more packets
|
|
// Paper end - add flush parameter
|
|
ConnectionProtocol enumprotocol = ConnectionProtocol.getProtocolForPacket(packet);
|
|
ConnectionProtocol enumprotocol1 = this.getCurrentProtocol();
|
|
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
|
index 07b0b0993c01763b39d1c9a387447ec76b5de190..72e700a775403eec2d1a32859279401351b836b1 100644
|
|
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
|
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
|
@@ -55,8 +55,8 @@ import java.util.function.Supplier;
|
|
|
|
public final class MCUtil {
|
|
public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor(
|
|
- 0, 2, 60L, TimeUnit.SECONDS,
|
|
- new LinkedBlockingQueue<>(),
|
|
+ Integer.getInteger("suki.threads.asyncexecutor", 4), Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, // JettPack // Suki - multithreading environment variables
|
|
+ new LinkedBlockingQueue<>(),
|
|
new ThreadFactoryBuilder()
|
|
.setNameFormat("Paper Async Task Handler Thread - %1$d")
|
|
.setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(MinecraftServer.LOGGER))
|
|
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
|
|
index 5962f7a2b185d7d54a0f9e341a4fdf6e6f1c1ec5..8c80520396bc7e34bac25354c1fcdb38b71000c7 100644
|
|
--- a/src/main/java/net/minecraft/server/Main.java
|
|
+++ b/src/main/java/net/minecraft/server/Main.java
|
|
@@ -318,7 +318,7 @@ public class Main {
|
|
// Paper start - fix and optimise world upgrading
|
|
public static void convertWorldButItWorks(net.minecraft.resources.ResourceKey<net.minecraft.world.level.dimension.LevelStem> dimensionType, net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess worldSession,
|
|
DataFixer dataFixer, Optional<net.minecraft.resources.ResourceKey<com.mojang.serialization.Codec<? extends net.minecraft.world.level.chunk.ChunkGenerator>>> generatorKey, boolean removeCaches) {
|
|
- int threads = Runtime.getRuntime().availableProcessors() * 3 / 8;
|
|
+ int threads = Integer.getInteger("suki.threads.upgradeworld", Integer.getInteger("suki.systemcpus.forupgradeworld", Runtime.getRuntime().availableProcessors()) * 3 / 8); // Suki - multithreading environment variables
|
|
final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldSession.getLevelId(), worldSession.levelDirectory.path().toFile(), threads, dataFixer, generatorKey, removeCaches);
|
|
worldUpgrader.convert();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index a444c8c57a2ab16eba45b0379841a69ff60a5586..ede16b015b9dde07a7346e0bffde53082145798b 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -294,6 +294,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
public final double[] recentTps = new double[ 4 ]; // Purpur
|
|
// Spigot end
|
|
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
|
|
+ public final org.sucraft.suki.configuration.SukiConfigurations sukiConfigurations; // Suki - Suki configuration
|
|
public static long currentTickLong = 0L; // Paper
|
|
public boolean lagging = false; // Purpur
|
|
protected boolean upnp = false; // Purpur
|
|
@@ -313,8 +314,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
thread.setUncaughtExceptionHandler((thread1, throwable) -> {
|
|
MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable);
|
|
});
|
|
- if (Runtime.getRuntime().availableProcessors() > 4) {
|
|
- thread.setPriority(8);
|
|
+ // Suki start - multithreading environment variables
|
|
+ if (Integer.getInteger("suki.mainthreadpriority", -1) != -1 || Runtime.getRuntime().availableProcessors() > 4) {
|
|
+ thread.setPriority(Integer.getInteger("suki.mainthreadpriority", 8));
|
|
+ // Suki end - multithreading environment variables
|
|
}
|
|
|
|
S s0 = serverFactory.apply(thread); // CraftBukkit - decompile error
|
|
@@ -400,6 +403,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
// Paper end
|
|
Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this));
|
|
this.paperConfigurations = services.paperConfigurations(); // Paper
|
|
+ this.sukiConfigurations = services.sukiConfigurations(); // Suki - Suki configuration
|
|
}
|
|
// CraftBukkit end
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Services.java b/src/main/java/net/minecraft/server/Services.java
|
|
index ef6ff78af2ae747e939895b82ee9d11c75012dcd..05d011ff1053fafd9b1d440911fbe123a54305ce 100644
|
|
--- a/src/main/java/net/minecraft/server/Services.java
|
|
+++ b/src/main/java/net/minecraft/server/Services.java
|
|
@@ -8,10 +8,10 @@ import net.minecraft.server.players.GameProfileCache;
|
|
import net.minecraft.util.SignatureValidator;
|
|
|
|
// Paper start
|
|
-public record Services(MinecraftSessionService sessionService, SignatureValidator serviceSignatureValidator, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations) {
|
|
+public record Services(MinecraftSessionService sessionService, SignatureValidator serviceSignatureValidator, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations, @javax.annotation.Nullable org.sucraft.suki.configuration.SukiConfigurations sukiConfigurations) { // Suki - Suki configuration
|
|
|
|
public Services(MinecraftSessionService sessionService, SignatureValidator signatureValidator, GameProfileRepository profileRepository, GameProfileCache profileCache) {
|
|
- this(sessionService, signatureValidator, profileRepository, profileCache, null);
|
|
+ this(sessionService, signatureValidator, profileRepository, profileCache, null, null); // Suki - Suki configuration
|
|
}
|
|
|
|
@Override
|
|
@@ -19,6 +19,12 @@ public record Services(MinecraftSessionService sessionService, SignatureValidato
|
|
return java.util.Objects.requireNonNull(this.paperConfigurations);
|
|
}
|
|
// Paper end
|
|
+ // Suki start - Suki configuration
|
|
+ @Override
|
|
+ public org.sucraft.suki.configuration.SukiConfigurations sukiConfigurations() {
|
|
+ return java.util.Objects.requireNonNull(this.sukiConfigurations);
|
|
+ }
|
|
+ // Suki end - Suki configuration
|
|
public static final String USERID_CACHE_FILE = "usercache.json"; // Paper - private -> public
|
|
|
|
public static Services create(YggdrasilAuthenticationService authenticationService, File rootDirectory, File userCacheFile, joptsimple.OptionSet optionSet) throws Exception { // Paper
|
|
@@ -30,7 +36,11 @@ public record Services(MinecraftSessionService sessionService, SignatureValidato
|
|
final java.nio.file.Path legacyConfigPath = ((File) optionSet.valueOf("paper-settings")).toPath();
|
|
final java.nio.file.Path configDirPath = ((File) optionSet.valueOf("paper-settings-directory")).toPath();
|
|
io.papermc.paper.configuration.PaperConfigurations paperConfigurations = io.papermc.paper.configuration.PaperConfigurations.setup(legacyConfigPath, configDirPath, rootDirectory.toPath(), (File) optionSet.valueOf("spigot-settings"));
|
|
- return new Services(minecraftSessionService, signatureValidator, gameProfileRepository, gameProfileCache, paperConfigurations);
|
|
+ // Suki start - Suki configuration
|
|
+ final java.nio.file.Path sukiLegacyConfigPath = legacyConfigPath.resolveSibling("suki.yml");
|
|
+ org.sucraft.suki.configuration.SukiConfigurations sukiConfigurations = org.sucraft.suki.configuration.SukiConfigurations.setup(sukiLegacyConfigPath, configDirPath, rootDirectory.toPath(), (File) optionSet.valueOf("spigot-settings"));
|
|
+ return new Services(minecraftSessionService, signatureValidator, gameProfileRepository, gameProfileCache, paperConfigurations, sukiConfigurations);
|
|
+ // Suki end - Suki configuration
|
|
// Paper end
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
index 383045ae681d5366761c807a0032156203cdf9c9..3e7dd41555263e8361db08d1380c767fe0ba8886 100644
|
|
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
|
@@ -213,6 +213,10 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
|
io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc.
|
|
paperConfigurations.initializeGlobalConfiguration();
|
|
paperConfigurations.initializeWorldDefaultsConfiguration();
|
|
+ // Suki start - Suki configuration
|
|
+ sukiConfigurations.initializeGlobalConfiguration();
|
|
+ sukiConfigurations.initializeWorldDefaultsConfiguration();
|
|
+ // Suki end - Suki configuration
|
|
// Paper start - moved up to right after PlayerList creation but before file load/save
|
|
if (this.convertOldUsers()) {
|
|
this.getProfileCache().save(false); // Paper
|
|
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
|
index 01ca7156d86243a80cd343a2a66be9ebedcc3b7c..852ec490e2a53803ca72a3ec0d994cbefb1f5fcd 100644
|
|
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
|
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
|
@@ -97,7 +97,7 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
|
|
public final Settings<DedicatedServerProperties>.MutableValue<Integer> playerIdleTimeout;
|
|
public final Settings<DedicatedServerProperties>.MutableValue<Boolean> whiteList;
|
|
public final boolean enforceSecureProfile;
|
|
- private final DedicatedServerProperties.WorldGenProperties worldGenProperties;
|
|
+ public final DedicatedServerProperties.WorldGenProperties worldGenProperties; // Suki - Suki configuration- include vanilla server.properties in timings
|
|
@Nullable
|
|
private WorldGenSettings worldGenSettings;
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
index 2a9219e0139670674319a7cf17ad664582b42715..ba95c8ba2fdcb73065c2fc219f94528239751f33 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
@@ -533,7 +533,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
|
|
// Holder holder = worlddimension.typeHolder(); // CraftBukkit - decompile error
|
|
// Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
|
|
- super(iworlddataserver, resourcekey, worlddimension.typeHolder(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig)), executor); // Paper - Async-Anti-Xray - Pass executor
|
|
+ super(iworlddataserver, resourcekey, worlddimension.typeHolder(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig)), spigotConfig -> minecraftserver.sukiConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig)), executor); // Paper - Async-Anti-Xray - Pass executor // Suki - Suki configuration
|
|
this.pvpMode = minecraftserver.isPvpAllowed();
|
|
this.convertable = convertable_conversionsession;
|
|
this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile());
|
|
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
|
|
index c9def2202d7c2a523858ec124df2beaf994d9888..3a7bcee2e4b1c4ef2ba303b0200ae846357c5982 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Explosion.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
|
|
@@ -152,6 +152,7 @@ public class Explosion {
|
|
int i;
|
|
int j;
|
|
|
|
+ if (this.fire || this.blockInteraction != BlockInteraction.NONE) { // Suki - optimize explosions - don't run block processing if neither flag is set
|
|
for (int k = 0; k < 16; ++k) {
|
|
for (i = 0; i < 16; ++i) {
|
|
for (j = 0; j < 16; ++j) {
|
|
@@ -191,8 +192,8 @@ public class Explosion {
|
|
if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) {
|
|
BlockEntity extension = this.level.getBlockEntity(blockposition);
|
|
if (extension instanceof net.minecraft.world.level.block.piston.PistonMovingBlockEntity blockEntity && blockEntity.isSourcePiston()) {
|
|
- net.minecraft.core.Direction direction = iblockdata.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
|
|
- set.add(blockposition.relative(direction.getOpposite()));
|
|
+ net.minecraft.core.Direction direction = iblockdata.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
|
|
+ set.add(blockposition.relative(direction.getOpposite()));
|
|
}
|
|
}
|
|
// Paper end
|
|
@@ -206,6 +207,7 @@ public class Explosion {
|
|
}
|
|
}
|
|
}
|
|
+ } // Suki - optimize explosions - don't run block processing if neither flag is set
|
|
|
|
this.toBlow.addAll(set);
|
|
float f2 = this.radius * 2.0F;
|
|
@@ -296,7 +298,7 @@ public class Explosion {
|
|
boolean flag1 = this.blockInteraction != Explosion.BlockInteraction.NONE;
|
|
|
|
if (particles) {
|
|
- if (this.radius >= 2.0F && flag1) {
|
|
+ if (this.radius >= 2.0F) {
|
|
this.level.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
|
|
} else {
|
|
this.level.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 9f0126aedb94f74d01dc47112496160cc4e1f02c..dc3f2b26e19619adf80827d26b95209ded973c2a 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -172,7 +172,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
return this.paperConfig;
|
|
}
|
|
// Paper end
|
|
+ // Suki start - Suki configuration
|
|
+ private final org.sucraft.suki.configuration.SukiWorldConfiguration sukiConfig;
|
|
|
|
+ public org.sucraft.suki.configuration.SukiWorldConfiguration sukiConfig() {
|
|
+ return this.sukiConfig;
|
|
+ }
|
|
+
|
|
+ // Suki end - Suki configuration
|
|
public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
|
|
public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur
|
|
|
|
@@ -327,10 +334,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
@Override public final int getHeight() { return this.height; }
|
|
// Pufferfish end
|
|
|
|
- protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
|
|
+ protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, java.util.function.Function<org.spigotmc.SpigotWorldConfig, org.sucraft.suki.configuration.SukiWorldConfiguration> sukiWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor // Suki - Suki configuration
|
|
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
|
|
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
|
|
this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur
|
|
+ this.sukiConfig = sukiWorldConfigCreator.apply(this.spigotConfig); // Suki - Suki configuration
|
|
this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur
|
|
this.generator = gen;
|
|
this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
|
index 13e749a3c40f0b2cc002f13675a9a56eedbefdac..01ea0068e1c5a2bf0ad18bfa58bc98a7a2a98ef7 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
|
@@ -69,6 +69,15 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
|
}
|
|
|
|
public void unpackLootTable(@Nullable Player player) {
|
|
+ // Suki start - only refresh lootables for players
|
|
+ if (this.level.getServer() != null) {
|
|
+ if (this.level.sukiConfig().lootables.onlyRefreshForPlayers) {
|
|
+ if (player == null) {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Suki end - only refresh lootables for players
|
|
if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper
|
|
LootTable lootTable = this.level.getServer().getLootTables().get(this.lootTable);
|
|
if (player instanceof ServerPlayer) {
|
|
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
|
index 34e351e04ac57e47e3cea671c61cc01d17983b77..f583ae81fb60027c47aaecdb6451462cd0d72936 100644
|
|
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
|
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
|
@@ -30,6 +30,7 @@ import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.nbt.ShortTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.ServerChunkCache;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
|
@@ -157,7 +158,14 @@ public class ChunkSerializer {
|
|
ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate
|
|
|
|
if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
|
|
- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkPos, chunkPos, chunkcoordintpair1});
|
|
+ // Suki start - do not relocate corrupted chunks
|
|
+ if (world.sukiConfig().relocateCorruptedChunks.enabled) {
|
|
+ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkPos, chunkPos, chunkcoordintpair1});
|
|
+ } else {
|
|
+ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; stopping the server. (Expected {}, got {})", new Object[]{chunkPos, chunkPos, chunkcoordintpair1});
|
|
+ MinecraftServer.getServer().stopServer();
|
|
+ }
|
|
+ // Suki end - do not relocate corrupted chunks
|
|
}
|
|
|
|
UpgradeData chunkconverter = nbt.contains("UpgradeData", 10) ? new UpgradeData(nbt.getCompound("UpgradeData"), world) : UpgradeData.EMPTY;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index 4f029b96bf8deee597dbb56974e4519a1422f96d..9e47bbefdb373a75a9903b19c23e9191b9c84846 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -242,6 +242,7 @@ import org.jetbrains.annotations.NotNull;
|
|
import org.yaml.snakeyaml.Yaml;
|
|
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
|
import org.yaml.snakeyaml.error.MarkedYAMLException;
|
|
+import net.minecraft.Util; // KeYi
|
|
|
|
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
|
|
|
|
@@ -1013,6 +1014,7 @@ public final class CraftServer implements Server {
|
|
org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot
|
|
this.console.paperConfigurations.reloadConfigs(this.console);
|
|
org.purpurmc.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur
|
|
+ this.console.sukiConfigurations.reloadConfigs(this.console); // Suki - Suki configuration
|
|
for (ServerLevel world : this.console.getAllLevels()) {
|
|
// world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty
|
|
world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean))
|
|
@@ -1295,9 +1297,11 @@ public final class CraftServer implements Server {
|
|
worldKey = ResourceKey.create(net.minecraft.core.Registry.DIMENSION_REGISTRY, new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper
|
|
}
|
|
|
|
- ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, worlddimension, this.getServer().progressListenerFactory.create(11),
|
|
+ // Suki start - multithreading environment variables
|
|
+ int levelExecutorThreads = Integer.getInteger("suki.threads.levelexecutor", -1);
|
|
+ ServerLevel internal = (ServerLevel) new ServerLevel(this.console, levelExecutorThreads > 0 ? Util.makeExecutor(name, -1, levelExecutorThreads) : console.executor, worldSession, worlddata, worldKey, worlddimension, this.getServer().progressListenerFactory.create(11),
|
|
worlddata.worldGenSettings().isDebug(), j, creator.environment() == Environment.NORMAL ? list : ImmutableList.of(), true, creator.environment(), generator, biomeProvider);
|
|
-
|
|
+ // Suki end - multithreading environment variables
|
|
if (!(this.worlds.containsKey(name.toLowerCase(java.util.Locale.ENGLISH)))) {
|
|
return null;
|
|
}
|
|
@@ -2840,6 +2844,13 @@ public final class CraftServer implements Server {
|
|
return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console);
|
|
}
|
|
|
|
+ // Suki start - Suki configuration
|
|
+ @Override
|
|
+ public YamlConfiguration getSukiConfig() {
|
|
+ return CraftServer.this.console.sukiConfigurations.createLegacyObject(CraftServer.this.console);
|
|
+ }
|
|
+ // Suki end - Suki configuration
|
|
+
|
|
// Purpur start
|
|
@Override
|
|
public YamlConfiguration getPurpurConfig() {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
|
index 8e06bc11fb28baee3407bbfe9d7b3689d6f85ff2..ce1190a6b0fb1e4f00e0d573edd42e2456c7e1e2 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java
|
|
@@ -5,6 +5,7 @@ import org.bukkit.util.permissions.DefaultPermissions;
|
|
|
|
public final class CraftDefaultPermissions {
|
|
private static final String ROOT = "minecraft";
|
|
+ private static final String SUKI_ROOT = "suki"; // Suki - Suki permissions
|
|
|
|
private CraftDefaultPermissions() {}
|
|
|
|
diff --git a/src/main/java/org/sucraft/suki/configuration/SukiConfigurations.java b/src/main/java/org/sucraft/suki/configuration/SukiConfigurations.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b64077fa2ff5c85b7c07868841a133f9e1b20c15
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/sucraft/suki/configuration/SukiConfigurations.java
|
|
@@ -0,0 +1,296 @@
|
|
+// Suki - Suki configuration
|
|
+
|
|
+package org.sucraft.suki.configuration;
|
|
+
|
|
+import com.google.common.collect.Table;
|
|
+import com.mojang.logging.LogUtils;
|
|
+import io.leangen.geantyref.TypeToken;
|
|
+import io.papermc.paper.configuration.Configuration;
|
|
+import io.papermc.paper.configuration.ConfigurationPart;
|
|
+import io.papermc.paper.configuration.Configurations;
|
|
+import io.papermc.paper.configuration.InnerClassFieldDiscoverer;
|
|
+import io.papermc.paper.configuration.NestedSetting;
|
|
+import io.papermc.paper.configuration.PaperConfigurations;
|
|
+import io.papermc.paper.configuration.legacy.RequiresSpigotInitialization;
|
|
+import io.papermc.paper.configuration.serializer.ComponentSerializer;
|
|
+import io.papermc.paper.configuration.serializer.EnumValueSerializer;
|
|
+import io.papermc.paper.configuration.serializer.FastutilMapSerializer;
|
|
+import io.papermc.paper.configuration.serializer.PacketClassSerializer;
|
|
+import io.papermc.paper.configuration.serializer.StringRepresentableSerializer;
|
|
+import io.papermc.paper.configuration.serializer.TableSerializer;
|
|
+import io.papermc.paper.configuration.serializer.collections.MapSerializer;
|
|
+import io.papermc.paper.configuration.serializer.registry.RegistryHolderSerializer;
|
|
+import io.papermc.paper.configuration.serializer.registry.RegistryValueSerializer;
|
|
+import io.papermc.paper.configuration.transformation.Transformations;
|
|
+import io.papermc.paper.configuration.type.BooleanOrDefault;
|
|
+import io.papermc.paper.configuration.type.DoubleOrDefault;
|
|
+import io.papermc.paper.configuration.type.Duration;
|
|
+import io.papermc.paper.configuration.type.EngineMode;
|
|
+import io.papermc.paper.configuration.type.IntOr;
|
|
+import io.papermc.paper.configuration.type.fallback.FallbackValueSerializer;
|
|
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
|
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
|
+import it.unimi.dsi.fastutil.objects.Reference2LongMap;
|
|
+import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap;
|
|
+import net.minecraft.core.Registry;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.world.entity.EntityType;
|
|
+import net.minecraft.world.item.Item;
|
|
+import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
|
+import org.slf4j.Logger;
|
|
+import org.spongepowered.configurate.ConfigurateException;
|
|
+import org.spongepowered.configurate.ConfigurationNode;
|
|
+import org.spongepowered.configurate.ConfigurationOptions;
|
|
+import org.spongepowered.configurate.NodePath;
|
|
+import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
|
+import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
|
+import org.spongepowered.configurate.transformation.TransformAction;
|
|
+import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.lang.reflect.Type;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.util.Collections;
|
|
+import java.util.List;
|
|
+import java.util.function.Function;
|
|
+
|
|
+import static io.leangen.geantyref.GenericTypeReflector.erase;
|
|
+
|
|
+@SuppressWarnings("Convert2Diamond")
|
|
+public class SukiConfigurations extends Configurations<SukiGlobalConfiguration, SukiWorldConfiguration> {
|
|
+
|
|
+ private static final Logger LOGGER = LogUtils.getLogger();
|
|
+ static final String GLOBAL_CONFIG_FILE_NAME = "suki-global.yml";
|
|
+ static final String WORLD_DEFAULTS_CONFIG_FILE_NAME = "suki-world-defaults.yml";
|
|
+ static final String WORLD_CONFIG_FILE_NAME = "suki-world.yml";
|
|
+ public static final String CONFIG_DIR = "config";
|
|
+
|
|
+ private static final String GLOBAL_HEADER = String.format("""
|
|
+ This is the global configuration file for Suki.
|
|
+ As you can see, there's a lot to configure. Some options may impact gameplay, so use
|
|
+ with caution, and make sure you know what each option does before configuring.
|
|
+
|
|
+ If you need help with the configuration or have any questions related to Suki,
|
|
+ join us in our Discord for SuCraft, or check the GitHub Wiki pages.
|
|
+
|
|
+ The world configuration options are inside
|
|
+ their respective world folder. The files are named %s
|
|
+
|
|
+ Wiki: https://github.com/SuCraft/Suki/wiki
|
|
+ Discord: https://discord.com/invite/pbsPkpUjG4""", WORLD_CONFIG_FILE_NAME);
|
|
+
|
|
+ private static final String WORLD_DEFAULTS_HEADER = """
|
|
+ This is the world defaults configuration file for Suki.
|
|
+ As you can see, there's a lot to configure. Some options may impact gameplay, so use
|
|
+ with caution, and make sure you know what each option does before configuring.
|
|
+
|
|
+ If you need help with the configuration or have any questions related to Suki,
|
|
+ join us in our Discord for SuCraft, or check the GitHub Wiki pages.
|
|
+
|
|
+ Configuration options here apply to all worlds, unless you specify overrides inside
|
|
+ the world-specific config file inside each world folder.
|
|
+
|
|
+ Wiki: https://github.com/SuCraft/Suki/wiki
|
|
+ Discord: https://discord.com/invite/pbsPkpUjG4""";
|
|
+
|
|
+ private static final Function<ContextMap, String> WORLD_HEADER = map -> String.format("""
|
|
+ This is a world configuration file for Suki.
|
|
+ This file may start empty but can be filled with settings to override ones in the %s/%s
|
|
+
|
|
+ World: %s (%s)""",
|
|
+ CONFIG_DIR,
|
|
+ WORLD_DEFAULTS_CONFIG_FILE_NAME,
|
|
+ map.require(WORLD_NAME),
|
|
+ map.require(WORLD_KEY)
|
|
+ );
|
|
+
|
|
+ private static final String MOVED_NOTICE = """
|
|
+ The global and world default configuration files have moved to %s
|
|
+ and the world-specific configuration file has been moved inside
|
|
+ the respective world folder.
|
|
+
|
|
+ See https://github.com/SuCraft/Suki/wiki for more information.
|
|
+ """;
|
|
+
|
|
+ public SukiConfigurations(final Path globalFolder) {
|
|
+ super(globalFolder, SukiGlobalConfiguration.class, SukiWorldConfiguration.class, GLOBAL_CONFIG_FILE_NAME, WORLD_DEFAULTS_CONFIG_FILE_NAME, WORLD_CONFIG_FILE_NAME);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected YamlConfigurationLoader.Builder createLoaderBuilder() {
|
|
+ return super.createLoaderBuilder()
|
|
+ .defaultOptions(SukiConfigurations::defaultOptions);
|
|
+ }
|
|
+
|
|
+ private static ConfigurationOptions defaultOptions(ConfigurationOptions options) {
|
|
+ return options.serializers(builder -> builder
|
|
+ .register(MapSerializer.TYPE, new MapSerializer(false))
|
|
+ .register(new EnumValueSerializer())
|
|
+ .register(new ComponentSerializer())
|
|
+ );
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected ObjectMapper.Factory.Builder createGlobalObjectMapperFactoryBuilder() {
|
|
+ return defaultGlobalFactoryBuilder(super.createGlobalObjectMapperFactoryBuilder());
|
|
+ }
|
|
+
|
|
+ private static ObjectMapper.Factory.Builder defaultGlobalFactoryBuilder(ObjectMapper.Factory.Builder builder) {
|
|
+ return builder.addDiscoverer(InnerClassFieldDiscoverer.globalConfig());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder() {
|
|
+ return super.createGlobalLoaderBuilder()
|
|
+ .defaultOptions(SukiConfigurations::defaultGlobalOptions);
|
|
+ }
|
|
+
|
|
+ private static ConfigurationOptions defaultGlobalOptions(ConfigurationOptions options) {
|
|
+ return options
|
|
+ .header(GLOBAL_HEADER)
|
|
+ .serializers(builder -> builder.register(new PacketClassSerializer()));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public SukiGlobalConfiguration initializeGlobalConfiguration() throws ConfigurateException {
|
|
+ SukiGlobalConfiguration configuration = super.initializeGlobalConfiguration();
|
|
+ SukiGlobalConfiguration.set(configuration);
|
|
+ return configuration;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected ContextMap.Builder createDefaultContextMap() {
|
|
+ return super.createDefaultContextMap()
|
|
+ .put(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY, PaperConfigurations.SPIGOT_WORLD_DEFAULTS);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected ObjectMapper.Factory.Builder createWorldObjectMapperFactoryBuilder(final ContextMap contextMap) {
|
|
+ return super.createWorldObjectMapperFactoryBuilder(contextMap)
|
|
+ .addNodeResolver(new RequiresSpigotInitialization.Factory(contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get()))
|
|
+ .addNodeResolver(new NestedSetting.Factory())
|
|
+ .addDiscoverer(InnerClassFieldDiscoverer.sukiWorldConfig(contextMap));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected YamlConfigurationLoader.Builder createWorldConfigLoaderBuilder(final ContextMap contextMap) {
|
|
+ return super.createWorldConfigLoaderBuilder(contextMap)
|
|
+ .defaultOptions(options -> options
|
|
+ .header(contextMap.require(WORLD_NAME).equals(WORLD_DEFAULTS) ? WORLD_DEFAULTS_HEADER : WORLD_HEADER.apply(contextMap))
|
|
+ .serializers(serializers -> serializers
|
|
+ .register(new TypeToken<Reference2IntMap<?>>() {}, new FastutilMapSerializer.SomethingToPrimitive<Reference2IntMap<?>>(Reference2IntOpenHashMap::new, Integer.TYPE))
|
|
+ .register(new TypeToken<Reference2LongMap<?>>() {}, new FastutilMapSerializer.SomethingToPrimitive<Reference2LongMap<?>>(Reference2LongOpenHashMap::new, Long.TYPE))
|
|
+ .register(new TypeToken<Table<?, ?, ?>>() {}, new TableSerializer())
|
|
+ .register(new StringRepresentableSerializer())
|
|
+ .register(IntOr.Default.SERIALIZER)
|
|
+ .register(DoubleOrDefault.SERIALIZER)
|
|
+ .register(BooleanOrDefault.SERIALIZER)
|
|
+ .register(Duration.SERIALIZER)
|
|
+ .register(EngineMode.SERIALIZER)
|
|
+ .register(FallbackValueSerializer.create(contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(), MinecraftServer::getServer))
|
|
+ .register(new RegistryValueSerializer<>(new TypeToken<EntityType<?>>() {}, Registry.ENTITY_TYPE_REGISTRY, true))
|
|
+ .register(new RegistryValueSerializer<>(Item.class, Registry.ITEM_REGISTRY, true))
|
|
+ .register(new RegistryHolderSerializer<>(new TypeToken<ConfiguredFeature<?, ?>>() {}, Registry.CONFIGURED_FEATURE_REGISTRY, false))
|
|
+ .register(new RegistryHolderSerializer<>(Item.class, Registry.ITEM_REGISTRY, true))
|
|
+ )
|
|
+ );
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void applyWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode node) throws ConfigurateException {
|
|
+ final ConfigurationNode version = node.node(Configuration.VERSION_FIELD);
|
|
+ final String world = contextMap.require(WORLD_NAME);
|
|
+ if (version.virtual()) {
|
|
+ LOGGER.warn("The Suki world config file for " + world + " didn't have a version set, assuming latest");
|
|
+ version.raw(SukiWorldConfiguration.CURRENT_VERSION);
|
|
+ }
|
|
+ if (SukiRemovedConfigurations.REMOVED_WORLD_PATHS.length > 0) {
|
|
+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder();
|
|
+ for (NodePath path : SukiRemovedConfigurations.REMOVED_WORLD_PATHS) {
|
|
+ builder.addAction(path, TransformAction.remove());
|
|
+ }
|
|
+ builder.build().apply(node);
|
|
+ }
|
|
+ // ADD FUTURE TRANSFORMS HERE
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void applyGlobalConfigTransformations(ConfigurationNode node) throws ConfigurateException {
|
|
+ if (SukiRemovedConfigurations.REMOVED_GLOBAL_PATHS.length > 0) {
|
|
+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder();
|
|
+ for (NodePath path : SukiRemovedConfigurations.REMOVED_GLOBAL_PATHS) {
|
|
+ builder.addAction(path, TransformAction.remove());
|
|
+ }
|
|
+ builder.build().apply(node);
|
|
+ }
|
|
+ // ADD FUTURE TRANSFORMS HERE
|
|
+ }
|
|
+
|
|
+ private static final List<Transformations.DefaultsAware> DEFAULT_AWARE_TRANSFORMATIONS = Collections.emptyList();
|
|
+
|
|
+ @Override
|
|
+ protected void applyDefaultsAwareWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode worldNode, final ConfigurationNode defaultsNode) throws ConfigurateException {
|
|
+ final ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder();
|
|
+ // ADD FUTURE TRANSFORMS HERE (these transforms run after the defaults have been merged into the node)
|
|
+ DEFAULT_AWARE_TRANSFORMATIONS.forEach(transform -> transform.apply(builder, contextMap, defaultsNode));
|
|
+
|
|
+ ConfigurationTransformation transformation;
|
|
+ try {
|
|
+ transformation = builder.build(); // build throws IAE if no actions were provided (bad zml)
|
|
+ } catch (IllegalArgumentException ignored) {
|
|
+ return;
|
|
+ }
|
|
+ transformation.apply(worldNode);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public SukiWorldConfiguration createWorldConfig(final ContextMap contextMap) {
|
|
+ final String levelName = contextMap.require(WORLD_NAME);
|
|
+ try {
|
|
+ return super.createWorldConfig(contextMap);
|
|
+ } catch (IOException exception) {
|
|
+ throw new RuntimeException("Could not create Suki world config for " + levelName, exception);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected boolean isConfigType(final Type type) {
|
|
+ return ConfigurationPart.class.isAssignableFrom(erase(type));
|
|
+ }
|
|
+
|
|
+ public void reloadConfigs(MinecraftServer server) {
|
|
+ try {
|
|
+ this.initializeGlobalConfiguration(reloader(this.globalConfigClass, SukiGlobalConfiguration.get()));
|
|
+ this.initializeWorldDefaultsConfiguration();
|
|
+ for (ServerLevel level : server.getAllLevels()) {
|
|
+ this.createWorldConfig(PaperConfigurations.createWorldContextMap(level), reloader(this.worldConfigClass, level.sukiConfig()));
|
|
+ }
|
|
+ } catch (Exception ex) {
|
|
+ throw new RuntimeException("Could not reload Suki configuration files", ex);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static SukiConfigurations setup(final Path legacyConfig, final Path configDir, final Path worldFolder, final File spigotConfig) throws Exception {
|
|
+ final Path legacy = Files.isSymbolicLink(legacyConfig) ? Files.readSymbolicLink(legacyConfig) : legacyConfig;
|
|
+ final Path replacementFile = legacy.resolveSibling(legacyConfig.getFileName() + "-README.txt");
|
|
+ if (Files.notExists(replacementFile)) {
|
|
+ Files.createFile(replacementFile);
|
|
+ Files.writeString(replacementFile, String.format(MOVED_NOTICE, configDir.toAbsolutePath()));
|
|
+ }
|
|
+ try {
|
|
+ PaperConfigurations.createDirectoriesSymlinkAware(configDir);
|
|
+ return new SukiConfigurations(configDir);
|
|
+ } catch (final IOException ex) {
|
|
+ throw new RuntimeException("Could not setup SukiConfigurations", ex);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getWorldConfigurationCurrentVersion() {
|
|
+ return SukiWorldConfiguration.CURRENT_VERSION;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/org/sucraft/suki/configuration/SukiGlobalConfiguration.java b/src/main/java/org/sucraft/suki/configuration/SukiGlobalConfiguration.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ba7c3818d17db725e6c39f4e0837b1fd1a3d0dfb
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/sucraft/suki/configuration/SukiGlobalConfiguration.java
|
|
@@ -0,0 +1,31 @@
|
|
+// Suki - Suki configuration
|
|
+
|
|
+package org.sucraft.suki.configuration;
|
|
+
|
|
+import io.papermc.paper.configuration.Configuration;
|
|
+import io.papermc.paper.configuration.ConfigurationPart;
|
|
+import org.spongepowered.configurate.objectmapping.meta.Setting;
|
|
+
|
|
+@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"})
|
|
+public class SukiGlobalConfiguration extends ConfigurationPart {
|
|
+ static final int CURRENT_VERSION = 18;
|
|
+ private static SukiGlobalConfiguration instance;
|
|
+ public static SukiGlobalConfiguration get() {
|
|
+ return instance;
|
|
+ }
|
|
+ static void set(SukiGlobalConfiguration instance) {
|
|
+ SukiGlobalConfiguration.instance = instance;
|
|
+ }
|
|
+
|
|
+ @Setting(Configuration.VERSION_FIELD)
|
|
+ public int version = CURRENT_VERSION;
|
|
+
|
|
+ public GlobalDummyPart globalDummyPart;
|
|
+
|
|
+ public class GlobalDummyPart extends ConfigurationPart {
|
|
+
|
|
+ int globalDummyValue = 0;
|
|
+
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/org/sucraft/suki/configuration/SukiRemovedConfigurations.java b/src/main/java/org/sucraft/suki/configuration/SukiRemovedConfigurations.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b4fd4190b899d4dea9420074d96e6431c2a3fafb
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/sucraft/suki/configuration/SukiRemovedConfigurations.java
|
|
@@ -0,0 +1,13 @@
|
|
+// Suki - Suki configuration
|
|
+
|
|
+package org.sucraft.suki.configuration;
|
|
+
|
|
+import org.spongepowered.configurate.NodePath;
|
|
+
|
|
+interface SukiRemovedConfigurations {
|
|
+
|
|
+ NodePath[] REMOVED_WORLD_PATHS = {};
|
|
+
|
|
+ NodePath[] REMOVED_GLOBAL_PATHS = {};
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/org/sucraft/suki/configuration/SukiWorldConfiguration.java b/src/main/java/org/sucraft/suki/configuration/SukiWorldConfiguration.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..03d16da38f36b3c2e21c8c16758fe219c1d2f597
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/sucraft/suki/configuration/SukiWorldConfiguration.java
|
|
@@ -0,0 +1,60 @@
|
|
+// Suki - Suki configuration
|
|
+
|
|
+package org.sucraft.suki.configuration;
|
|
+
|
|
+import com.mojang.logging.LogUtils;
|
|
+import io.papermc.paper.configuration.Configuration;
|
|
+import io.papermc.paper.configuration.ConfigurationPart;
|
|
+import io.papermc.paper.configuration.PaperConfigurations;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import org.slf4j.Logger;
|
|
+import org.spigotmc.SpigotWorldConfig;
|
|
+import org.spongepowered.configurate.objectmapping.meta.Setting;
|
|
+
|
|
+@SuppressWarnings({"FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"})
|
|
+public class SukiWorldConfiguration extends ConfigurationPart {
|
|
+ private static final Logger LOGGER = LogUtils.getLogger();
|
|
+ public static final int CURRENT_VERSION = 19;
|
|
+
|
|
+ private transient final SpigotWorldConfig spigotConfig;
|
|
+ private transient final ResourceLocation worldKey;
|
|
+ public SukiWorldConfiguration(SpigotWorldConfig spigotConfig, ResourceLocation worldKey) {
|
|
+ this.spigotConfig = spigotConfig;
|
|
+ this.worldKey = worldKey;
|
|
+ }
|
|
+
|
|
+ public boolean isDefault() {
|
|
+ return this.worldKey.equals(PaperConfigurations.WORLD_DEFAULTS_KEY);
|
|
+ }
|
|
+
|
|
+ @Setting(Configuration.VERSION_FIELD)
|
|
+ public int version = CURRENT_VERSION;
|
|
+
|
|
+ public WorldDummyPart worldDummyPart;
|
|
+
|
|
+ public class WorldDummyPart extends ConfigurationPart {
|
|
+
|
|
+ int worldDummyValue = 0;
|
|
+
|
|
+ }
|
|
+ // Suki start - only refresh lootables for players
|
|
+
|
|
+ public Lootables lootables;
|
|
+
|
|
+ public class Lootables extends ConfigurationPart {
|
|
+ public boolean onlyRefreshForPlayers = false;
|
|
+ }
|
|
+
|
|
+ // Suki end - only refresh lootables for players
|
|
+
|
|
+ // Suki start - do not relocate corrupted chunks
|
|
+
|
|
+ public RelocateCorruptedChunks relocateCorruptedChunks;
|
|
+
|
|
+ public class RelocateCorruptedChunks extends ConfigurationPart {
|
|
+ public boolean enabled = true;
|
|
+ }
|
|
+
|
|
+ // Suki end - do not relocated corrupted chunks
|
|
+
|
|
+}
|