9
0
mirror of https://github.com/Dreeam-qwq/Gale.git synced 2025-12-22 08:19:31 +00:00
Files
Gale/patches/server/0009-Gale-configuration.patch
2023-08-29 22:19:20 +02:00

907 lines
49 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martijn Muijsers <martijnmuijsers@live.nl>
Date: Wed, 23 Nov 2022 21:05:47 +0100
Subject: [PATCH] Gale configuration
License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
Gale - https://galemc.org
This patch is based on the following patch:
"Paper config files"
By: Jake Potrebic <jake.m.potrebic@gmail.com>
As part of: Paper (https://github.com/PaperMC/Paper)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index a2f71a6d1a9e98133dff6cd0f625da9435a8af14..1b9d997c31ab281ce9f4719f53b0ad78a430789d 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -242,7 +242,10 @@ public class TimingsExport extends Thread {
parent.put("config", createObject(
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null))
+ // Gale start - Gale configuration - include in timings
+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)),
+ pair("gale", mapAsJSON(Bukkit.spigot().getGaleConfig(), null))
+ // Gale end - Gale configuration - include in timings
));
new TimingsExport(listeners, parent, history).start();
@@ -283,7 +286,7 @@ public class TimingsExport extends Thread {
return timingsCost;
}
- private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) {
+ public static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { // Gale - Gale configuration
JSONObject object = new JSONObject();
for (String key : config.getKeys(false)) {
diff --git a/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java b/src/main/java/io/papermc/paper/configuration/ConfigurationPart.java
index 7a4a7a654fe2516ed894a68f2657344df9d70f4c..82e6716c006492b9f24f148a918944b50231a158 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 { // Gale - Gale 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 9ef6712c70fcd8912a79f3f61e351aac09572cf3..80a8362c299d02c26781f06be5b8ee6cada8efbe 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;
@@ -88,7 +91,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) { // Gale - Gale 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 +151,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()); // Gale - Gale configuration
}
this.applyWorldConfigTransformations(contextMap, node);
final W instance = node.require(this.worldConfigClass);
@@ -207,7 +210,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()); // Gale - Gale configuration
}
this.applyWorldConfigTransformations(contextMap, worldNode);
this.applyDefaultsAwareWorldConfigTransformations(contextMap, worldNode, defaultsNode);
@@ -308,4 +311,25 @@ public abstract class Configurations<G, W> {
return "ContextKey{" + this.name + "}";
}
}
+
+ // Gale start - Gale configuration
+
+ public static final String legacyWorldsSectionKey = "__________WORLDS__________";
+ public static final String legacyWorldDefaultsSectionKey = "__defaults__";
+
+ @Deprecated
+ public YamlConfiguration createLegacyObject(final MinecraftServer server) {
+ YamlConfiguration global = YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.globalConfigFileName).toFile());
+ ConfigurationSection worlds = global.createSection(legacyWorldsSectionKey);
+ worlds.set(legacyWorldDefaultsSectionKey, 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();
+
+ // Gale end - Gale 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..6d19b985222d78750828fd2719c1fbf738e69a56 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.galemc.gale.configuration.GaleWorldConfiguration;
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>> { // Gale - Gale 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() {
+ // Gale start - Gale configuration
+ public static FieldDiscoverer<?> galeWorldConfig(Configurations.ContextMap contextMap) {
+ final Map<Class<?>, Object> overrides = Map.of(
+ GaleWorldConfiguration.class, new GaleWorldConfiguration(
+ contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(),
+ contextMap.require(Configurations.WORLD_KEY)
+ )
+ );
+ return new InnerClassFieldDiscoverer(overrides);
+ }
+ // Gale end - Gale configuration
+
+ public static FieldDiscoverer<?> globalConfig() { // Gale - Gale 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 e471960e0443392f6f54732b052a4debf2a8fd97..c56b9264d83ae98a4cc0945ea1bd919e9a5de57a 100644
--- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
+++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
@@ -135,7 +135,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
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"); // Gale - Gale configuration
public PaperConfigurations(final Path globalFolder) {
@@ -300,7 +300,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
}
}
- private static ContextMap createWorldContextMap(ServerLevel level) {
+ public static ContextMap createWorldContextMap(ServerLevel level) { // Gale - Gale configuration
return createWorldContextMap(level.convertable.levelDirectory.path(), level.serverLevelData.getLevelName(), level.dimension().location(), level.spigotConfig);
}
@@ -401,17 +401,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();
@@ -434,9 +423,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 { // Gale - Gale configuration
if (!Files.isDirectory(path)) {
Files.createDirectories(path);
}
}
+
+ // Gale start - Gale configuration
+ @Override
+ public int getWorldConfigurationCurrentVersion() {
+ return WorldConfiguration.CURRENT_VERSION;
+ }
+ // Gale end - Gale configuration
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 3f31b91ac6c9cb4d2b19536b6a6a2ab0f1b0df20..15d60a311c44a66c0ff2fdff989f93c27be64c40 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -3,9 +3,6 @@ package net.minecraft.server;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
-import co.aikar.timings.Timings;
-import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
-import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -86,7 +83,6 @@ import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerPlayerGameMode;
-import net.minecraft.server.level.TicketType;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.network.ServerConnectionListener;
@@ -110,7 +106,6 @@ import net.minecraft.util.NativeModuleLister;
import net.minecraft.util.ProgressListener;
import net.minecraft.util.RandomSource;
import net.minecraft.util.SignatureValidator;
-import net.minecraft.util.Unit;
import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.profiling.EmptyProfileResults;
import net.minecraft.util.profiling.ProfileResults;
@@ -161,6 +156,9 @@ import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.loot.LootDataManager;
+import net.minecraft.world.phys.Vec2;
+import net.minecraft.world.phys.Vec3;
+import org.galemc.gale.configuration.GaleConfigurations;
import org.slf4j.Logger;
// CraftBukkit start
@@ -305,6 +303,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public final double[] recentTps = new double[ 3 ];
// Spigot end
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
+ public final GaleConfigurations galeConfigurations; // Gale - Gale configuration
public static long currentTickLong = 0L; // Paper
public volatile Thread shutdownThread; // Paper
@@ -407,6 +406,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.galeConfigurations = services.galeConfigurations(); // Gale - Gale configuration
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/Services.java b/src/main/java/net/minecraft/server/Services.java
index a9b2c8cd4dcd3f884e4306bebee9334d3848fce5..3430a1ac3252ff9a457ee36ffc112503a25e4272 100644
--- a/src/main/java/net/minecraft/server/Services.java
+++ b/src/main/java/net/minecraft/server/Services.java
@@ -9,12 +9,13 @@ import java.io.File;
import javax.annotation.Nullable;
import net.minecraft.server.players.GameProfileCache;
import net.minecraft.util.SignatureValidator;
+import org.galemc.gale.configuration.GaleConfigurations;
// Paper start
-public record Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations) {
+public record Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations, @javax.annotation.Nullable GaleConfigurations galeConfigurations) { // Gale - Gale configuration
public Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache) {
- this(sessionService, servicesKeySet, profileRepository, profileCache, null);
+ this(sessionService, servicesKeySet, profileRepository, profileCache, null, null); // Gale - Gale configuration
}
@Override
@@ -22,6 +23,11 @@ public record Services(MinecraftSessionService sessionService, ServicesKeySet se
return java.util.Objects.requireNonNull(this.paperConfigurations);
}
// Paper end
+ // Gale start - Gale configuration
+ public GaleConfigurations galeConfigurations() {
+ return java.util.Objects.requireNonNull(this.galeConfigurations);
+ }
+ // Gale end - Gale 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
@@ -32,7 +38,10 @@ public record Services(MinecraftSessionService sessionService, ServicesKeySet se
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, authenticationService.getServicesKeySet(), gameProfileRepository, gameProfileCache, paperConfigurations);
+ // Gale start - Gale configuration
+ GaleConfigurations galeConfigurations = GaleConfigurations.setup(configDirPath);
+ return new Services(minecraftSessionService, authenticationService.getServicesKeySet(), gameProfileRepository, gameProfileCache, paperConfigurations, galeConfigurations);
+ // Gale end - Gale 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 c49802c936ae8e3f4dc1badd98414d96714ecd60..feff4844b1e19466f05a4116a221746acc3262f2 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -1,20 +1,15 @@
package net.minecraft.server.dedicated;
-import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.DataFixer;
import com.mojang.logging.LogUtils;
-import java.io.BufferedReader;
+
import java.io.BufferedWriter;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Proxy;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Collections;
-import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.function.BooleanSupplier;
@@ -208,6 +203,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();
+ // Gale start - Gale configuration
+ galeConfigurations.initializeGlobalConfiguration();
+ galeConfigurations.initializeWorldDefaultsConfiguration();
+ // Gale end - Gale 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/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 18aac3da3c88f33b1a71a5920a8daa27e9723913..513916690d2579760f59edecb1a273f475d54adf 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -132,12 +132,10 @@ import net.minecraft.world.level.chunk.storage.EntityStorage;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.dimension.end.EndDragonFight;
-import net.minecraft.world.level.entity.EntityPersistentStorage;
import net.minecraft.world.level.entity.EntityTickList;
import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.level.entity.LevelCallback;
import net.minecraft.world.level.entity.LevelEntityGetter;
-import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.gameevent.DynamicGameEventListener;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.GameEventDispatcher;
@@ -647,7 +645,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Holder holder = worlddimension.type(); // CraftBukkit - decompile error
// Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
- super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), 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, minecraftserver.registryAccess(), worlddimension.type(), 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.galeConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig)), executor); // Paper - Async-Anti-Xray - Pass executor // Gale - Gale 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/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index f39ab10c5b0b8d86b579a5b683491204c51db70b..f95aa6362605c10145a212ed4b7df42ad443f4cf 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1,10 +1,7 @@
package net.minecraft.world.level;
-import co.aikar.timings.Timing;
-import co.aikar.timings.Timings;
import com.destroystokyo.paper.event.server.ServerExceptionEvent;
import com.destroystokyo.paper.exception.ServerInternalException;
-import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import java.io.IOException;
@@ -17,7 +14,6 @@ import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
-import net.minecraft.ReportedException;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
@@ -44,8 +40,6 @@ import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageSources;
import net.minecraft.world.entity.Entity;
-import net.minecraft.world.entity.boss.EnderDragonPart;
-import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
@@ -91,17 +85,15 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket;
import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket;
import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket;
import org.bukkit.Bukkit;
-import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.block.CapturedBlockState;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.util.CraftSpawnCategory;
-import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.event.block.BlockPhysicsEvent;
-import org.bukkit.event.world.GenericGameEvent;
+import org.galemc.gale.configuration.GaleWorldConfiguration;
// CraftBukkit end
public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -174,6 +166,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return this.paperConfig;
}
// Paper end
+ // Gale start - Gale configuration
+ private final GaleWorldConfiguration galeConfig;
+ public GaleWorldConfiguration galeConfig() {
+ return this.galeConfig;
+ }
+ // Gale end - Gale configuration
public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
@@ -273,9 +271,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract ResourceKey<LevelStem> getTypeKey();
- protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, 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, RegistryAccess iregistrycustom, 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, GaleWorldConfiguration> galeWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor // Gale - Gale configuration
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
+ this.galeConfig = galeWorldConfigCreator.apply(this.spigotConfig); // Gale - Gale configuration
this.generator = gen;
this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0f2d8cc6d8a6f6fb53658c0f49de3b76cc716ea1..04dfa4f59921ec5fcea6fb6989847fc5164ccfda 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1057,6 +1057,7 @@ public final class CraftServer implements Server {
org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot
this.console.paperConfigurations.reloadConfigs(this.console);
+ this.console.galeConfigurations.reloadConfigs(this.console); // Gale - Gale 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))
@@ -2932,6 +2933,14 @@ public final class CraftServer implements Server {
return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console);
}
+ // Gale start - Gale configuration - API
+ @Override
+ public YamlConfiguration getGaleConfig()
+ {
+ return CraftServer.this.console.galeConfigurations.createLegacyObject(CraftServer.this.console);
+ }
+ // Gale end - Gale configuration - API
+
@Override
public void restart() {
org.spigotmc.RestartCommand.restart();
diff --git a/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java b/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java
new file mode 100644
index 0000000000000000000000000000000000000000..9571aae593999d11b3908856b0295a7d6b588007
--- /dev/null
+++ b/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java
@@ -0,0 +1,289 @@
+// Gale - Gale configuration
+
+package org.galemc.gale.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.collections.FastutilMapSerializer;
+import io.papermc.paper.configuration.serializer.PacketClassSerializer;
+import io.papermc.paper.configuration.serializer.StringRepresentableSerializer;
+import io.papermc.paper.configuration.serializer.collections.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.registries.Registries;
+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.IOException;
+import java.lang.reflect.Type;
+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 GaleConfigurations extends Configurations<GaleGlobalConfiguration, GaleWorldConfiguration> {
+
+ private static final Logger LOGGER = LogUtils.getLogger();
+ static final String GLOBAL_CONFIG_FILE_NAME = "gale-global.yml";
+ static final String WORLD_DEFAULTS_CONFIG_FILE_NAME = "gale-world-defaults.yml";
+ static final String WORLD_CONFIG_FILE_NAME = "gale-world.yml";
+ public static final String CONFIG_DIR = "config";
+
+ private static final String GLOBAL_HEADER = String.format("""
+ This is the global configuration file for Gale.
+ 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 Gale,
+ join us in our Discord, 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/GaleMC/Gale/wiki
+ Discord: https://discord.gg/gwezNT8c24""", WORLD_CONFIG_FILE_NAME);
+
+ private static final String WORLD_DEFAULTS_HEADER = """
+ This is the world defaults configuration file for Gale.
+ 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 Gale,
+ join us in our Discord, 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/GaleMC/Gale/wiki
+ Discord: https://discord.gg/gwezNT8c24""";
+
+ private static final Function<ContextMap, String> WORLD_HEADER = map -> String.format("""
+ This is a world configuration file for Gale.
+ 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/GaleMC/Gale/wiki for more information.
+ """;
+
+ public GaleConfigurations(final Path globalFolder) {
+ super(globalFolder, GaleGlobalConfiguration.class, GaleWorldConfiguration.class, GLOBAL_CONFIG_FILE_NAME, WORLD_DEFAULTS_CONFIG_FILE_NAME, WORLD_CONFIG_FILE_NAME);
+ }
+
+ @Override
+ protected YamlConfigurationLoader.Builder createLoaderBuilder() {
+ return super.createLoaderBuilder()
+ .defaultOptions(GaleConfigurations::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(GaleConfigurations::defaultGlobalOptions);
+ }
+
+ private static ConfigurationOptions defaultGlobalOptions(ConfigurationOptions options) {
+ return options
+ .header(GLOBAL_HEADER)
+ .serializers(builder -> builder.register(new PacketClassSerializer()));
+ }
+
+ @Override
+ public GaleGlobalConfiguration initializeGlobalConfiguration() throws ConfigurateException {
+ GaleGlobalConfiguration configuration = super.initializeGlobalConfiguration();
+ GaleGlobalConfiguration.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.galeWorldConfig(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(IntOr.Disabled.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<?>>() {}, Registries.ENTITY_TYPE, true))
+ .register(new RegistryValueSerializer<>(Item.class, Registries.ITEM, true))
+ .register(new RegistryHolderSerializer<>(new TypeToken<ConfiguredFeature<?, ?>>() {}, Registries.CONFIGURED_FEATURE, false))
+ .register(new RegistryHolderSerializer<>(Item.class, Registries.ITEM, 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 Gale world config file for " + world + " didn't have a version set, assuming latest");
+ version.raw(GaleWorldConfiguration.CURRENT_VERSION);
+ }
+ if (GaleRemovedConfigurations.REMOVED_WORLD_PATHS.length > 0) {
+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder();
+ for (NodePath path : GaleRemovedConfigurations.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 (GaleRemovedConfigurations.REMOVED_GLOBAL_PATHS.length > 0) {
+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder();
+ for (NodePath path : GaleRemovedConfigurations.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 GaleWorldConfiguration 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 Gale 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, GaleGlobalConfiguration.get()));
+ this.initializeWorldDefaultsConfiguration();
+ for (ServerLevel level : server.getAllLevels()) {
+ this.createWorldConfig(PaperConfigurations.createWorldContextMap(level), reloader(this.worldConfigClass, level.galeConfig()));
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("Could not reload Gale configuration files", ex);
+ }
+ }
+
+ public static GaleConfigurations setup(final Path configDir) throws Exception {
+ try {
+ PaperConfigurations.createDirectoriesSymlinkAware(configDir);
+ return new GaleConfigurations(configDir);
+ } catch (final IOException ex) {
+ throw new RuntimeException("Could not setup GaleConfigurations", ex);
+ }
+ }
+
+ @Override
+ public int getWorldConfigurationCurrentVersion() {
+ return GaleWorldConfiguration.CURRENT_VERSION;
+ }
+
+}
diff --git a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f8fd98f96cd390ba43033521982a13044df91cf
--- /dev/null
+++ b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
@@ -0,0 +1,30 @@
+// Gale - Gale configuration
+
+package org.galemc.gale.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 GaleGlobalConfiguration extends ConfigurationPart {
+ static final int CURRENT_VERSION = 1;
+ private static GaleGlobalConfiguration instance;
+ public static GaleGlobalConfiguration get() {
+ return instance;
+ }
+ static void set(GaleGlobalConfiguration instance) {
+ GaleGlobalConfiguration.instance = instance;
+ }
+
+ @Setting(Configuration.VERSION_FIELD)
+ public int version = CURRENT_VERSION;
+
+ public SmallOptimizations smallOptimizations;
+ public class SmallOptimizations extends ConfigurationPart {
+
+ public int dummyValue = 0;
+
+ }
+
+}
diff --git a/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java b/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java
new file mode 100644
index 0000000000000000000000000000000000000000..9db322100dacbf2343fbb86e3e83d99febfa9d9d
--- /dev/null
+++ b/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java
@@ -0,0 +1,13 @@
+// Gale - Gale configuration
+
+package org.galemc.gale.configuration;
+
+import org.spongepowered.configurate.NodePath;
+
+interface GaleRemovedConfigurations {
+
+ NodePath[] REMOVED_WORLD_PATHS = {};
+
+ NodePath[] REMOVED_GLOBAL_PATHS = {};
+
+}
diff --git a/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java b/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..b82bb95b524c95cdefb81abef906eded0717e9a1
--- /dev/null
+++ b/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java
@@ -0,0 +1,40 @@
+// Gale - Gale configuration
+
+package org.galemc.gale.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 GaleWorldConfiguration extends ConfigurationPart {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ public static final int CURRENT_VERSION = 1;
+
+ private transient final SpigotWorldConfig spigotConfig;
+ private transient final ResourceLocation worldKey;
+ public GaleWorldConfiguration(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 SmallOptimizations smallOptimizations;
+ public class SmallOptimizations extends ConfigurationPart {
+
+ public int dummyValue = 0;
+
+ }
+
+}
diff --git a/src/main/java/org/galemc/gale/configuration/timingsexport/GaleConfigurationTimingsExport.java b/src/main/java/org/galemc/gale/configuration/timingsexport/GaleConfigurationTimingsExport.java
new file mode 100644
index 0000000000000000000000000000000000000000..579c2e69d8f6ce8398eb1297d1d1ead98c9068a5
--- /dev/null
+++ b/src/main/java/org/galemc/gale/configuration/timingsexport/GaleConfigurationTimingsExport.java
@@ -0,0 +1,19 @@
+// Gale - Gale configuration
+
+package org.galemc.gale.configuration.timingsexport;
+
+import co.aikar.timings.TimingsExport;
+import org.bukkit.Bukkit;
+import org.jetbrains.annotations.NotNull;
+import org.json.simple.JSONObject;
+
+public final class GaleConfigurationTimingsExport {
+
+ private GaleConfigurationTimingsExport() {}
+
+ public static @NotNull JSONObject get() {
+ var json = TimingsExport.mapAsJSON(Bukkit.spigot().getGaleConfig(), null);
+ return json;
+ }
+
+}