mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-20 07:29:24 +00:00
364 lines
14 KiB
Diff
364 lines
14 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
|
Date: Wed, 12 Oct 2022 10:42:15 -0400
|
|
Subject: [PATCH] Leaf Config
|
|
|
|
TODO - Dreeam: Add header comment, world config, Bump Night Config to 3.7.1
|
|
|
|
Co-authored-by: MrHua269 <wangxyper@163.com>
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index 4ee48737f52e24f6e7148709068c568b36a736da..f7c47c49b91952bf24995332b2d7d57a277b76cf 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -14,6 +14,9 @@ val alsoShade: Configuration by configurations.creating
|
|
|
|
dependencies {
|
|
implementation(project(":leaf-api")) // Gale start - project setup - Depend on own API // Leaf
|
|
+
|
|
+ implementation("com.electronwill.night-config:toml:3.6.7") // Leaf - Night config // Dreeam TODO: Bump to 3.7.1
|
|
+
|
|
// Paper start
|
|
implementation("org.jline:jline-terminal-jansi:3.21.0")
|
|
implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
|
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
|
|
index 76a1b31a55b1838dc80b796f997edaddbcaa755c..bbeb88843f210abdf1cafed11394380cfcab0e09 100644
|
|
--- a/src/main/java/net/minecraft/server/Main.java
|
|
+++ b/src/main/java/net/minecraft/server/Main.java
|
|
@@ -123,6 +123,8 @@ public class Main {
|
|
Bootstrap.bootStrap();
|
|
Bootstrap.validate();
|
|
Util.startTimerHackThread();
|
|
+ org.dreeam.leaf.config.LeafConfig.loadConfig(); // Leaf
|
|
+ org.dreeam.leaf.config.LeafConfig.setupLatch(); // Leaf
|
|
Path path1 = Paths.get("server.properties");
|
|
DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support
|
|
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/ConfigInfo.java b/src/main/java/org/dreeam/leaf/config/ConfigInfo.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..6fbc0ad44069fbb3d85d3a6a4633e8e756196dfe
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/ConfigInfo.java
|
|
@@ -0,0 +1,11 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface ConfigInfo {
|
|
+ String baseName();
|
|
+
|
|
+ String comments() default "";
|
|
+}
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/DoNotLoad.java b/src/main/java/org/dreeam/leaf/config/DoNotLoad.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..42ce82d388336906a91547b81f6f70766f2b10f0
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/DoNotLoad.java
|
|
@@ -0,0 +1,8 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface DoNotLoad {
|
|
+}
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/EnumConfigCategory.java b/src/main/java/org/dreeam/leaf/config/EnumConfigCategory.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f69663d0cfebcdb598ac808d06cb069572dd6052
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/EnumConfigCategory.java
|
|
@@ -0,0 +1,21 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+public enum EnumConfigCategory {
|
|
+
|
|
+ ASYNC("async"),
|
|
+ PERFORMANCE("performance"),
|
|
+ NETWORK("network"),
|
|
+ FIXES("fixes"),
|
|
+ MISC("misc"),
|
|
+ GAMEPLAY("gameplay");
|
|
+
|
|
+ private final String baseKeyName;
|
|
+
|
|
+ EnumConfigCategory(String baseKeyName) {
|
|
+ this.baseKeyName = baseKeyName;
|
|
+ }
|
|
+
|
|
+ public String getBaseKeyName() {
|
|
+ return this.baseKeyName;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/HotReloadUnsupported.java b/src/main/java/org/dreeam/leaf/config/HotReloadUnsupported.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f7ab1ff5f298ff1e5e16fe5396d1e9e62a55fdfb
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/HotReloadUnsupported.java
|
|
@@ -0,0 +1,8 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface HotReloadUnsupported {
|
|
+}
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/IConfigModule.java b/src/main/java/org/dreeam/leaf/config/IConfigModule.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..da1474fa0512e50bedc8dda787bf6a1214f1ce37
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/IConfigModule.java
|
|
@@ -0,0 +1,23 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+public interface IConfigModule {
|
|
+
|
|
+ EnumConfigCategory getCategory();
|
|
+
|
|
+ String getBaseName();
|
|
+
|
|
+ default void onLoaded(CommentedFileConfig configInstance) {
|
|
+ }
|
|
+
|
|
+ default <T> T get(String keyName, T defaultValue, @NotNull CommentedFileConfig config) {
|
|
+ if (!config.contains(keyName)) {
|
|
+ config.set(keyName, defaultValue);
|
|
+ return defaultValue;
|
|
+ }
|
|
+
|
|
+ return config.get(keyName);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/org/dreeam/leaf/config/LeafConfig.java b/src/main/java/org/dreeam/leaf/config/LeafConfig.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b20ad36bb89e5226d94928832fdbcce7e096d6e2
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/config/LeafConfig.java
|
|
@@ -0,0 +1,220 @@
|
|
+package org.dreeam.leaf.config;
|
|
+
|
|
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
|
+import org.jetbrains.annotations.Contract;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.net.JarURLConnection;
|
|
+import java.net.URL;
|
|
+import java.net.URLDecoder;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+import java.util.*;
|
|
+import java.util.concurrent.CompletableFuture;
|
|
+import java.util.jar.JarEntry;
|
|
+import java.util.jar.JarFile;
|
|
+
|
|
+import org.apache.logging.log4j.LogManager;
|
|
+import org.apache.logging.log4j.Logger;
|
|
+import org.bukkit.craftbukkit.scheduler.MinecraftInternalPlugin;
|
|
+
|
|
+public class LeafConfig {
|
|
+ public static final Logger LOGGER = LogManager.getLogger(LeafConfig.class.getName());
|
|
+ private static final File baseConfigFolder = new File("leaf_config");
|
|
+ private static final File baseConfigFile = new File(baseConfigFolder, "leaf_global_config.toml");
|
|
+ private static final Set<IConfigModule> allInstanced = new HashSet<>();
|
|
+ private static CommentedFileConfig configFileInstance;
|
|
+ public static boolean alreadyInited = false;
|
|
+ private static MinecraftInternalPlugin NULL_PLUGIN = new MinecraftInternalPlugin();
|
|
+
|
|
+ public static void setupLatch() {
|
|
+ alreadyInited = true;
|
|
+ }
|
|
+
|
|
+ public static void reload() {
|
|
+ dropAllInstanced();
|
|
+ try {
|
|
+ loadConfig();
|
|
+ } catch (Exception e) {
|
|
+ LOGGER.error(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Contract(" -> new")
|
|
+ public static @NotNull CompletableFuture<Void> reloadAsync() {
|
|
+ return new CompletableFuture<>();
|
|
+ }
|
|
+
|
|
+ public static void dropAllInstanced() {
|
|
+ allInstanced.clear();
|
|
+ }
|
|
+
|
|
+ public static void loadConfig() throws IOException {
|
|
+ baseConfigFolder.mkdirs();
|
|
+
|
|
+ if (!baseConfigFile.exists()) {
|
|
+ baseConfigFile.createNewFile();
|
|
+ }
|
|
+
|
|
+ configFileInstance = CommentedFileConfig.ofConcurrent(baseConfigFile);
|
|
+
|
|
+ configFileInstance.load();
|
|
+ configFileInstance.setComment("", """
|
|
+ Leaf Config
|
|
+ Github Repo: https://github.com/Winds-Studio/Leaf
|
|
+ Discord: dreeam___ | QQ: 2682173972"""); // Leaf TODO - need to fix
|
|
+
|
|
+ try {
|
|
+ instanceAllModule();
|
|
+ loadAllModules();
|
|
+ } catch (Exception e) {
|
|
+ LOGGER.error("Failed to load config modules!", e);
|
|
+ }
|
|
+
|
|
+ configFileInstance.save();
|
|
+ }
|
|
+
|
|
+ private static void loadAllModules() throws IllegalAccessException {
|
|
+ for (IConfigModule instanced : allInstanced) {
|
|
+ loadForSingle(instanced);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
|
+ for (Class<?> clazz : getClasses("org.dreeam.leaf.config.modules")) {
|
|
+ if (IConfigModule.class.isAssignableFrom(clazz)) {
|
|
+ allInstanced.add((IConfigModule) clazz.getConstructor().newInstance());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException {
|
|
+ final EnumConfigCategory category = singleConfigModule.getCategory();
|
|
+
|
|
+ Field[] fields = singleConfigModule.getClass().getDeclaredFields();
|
|
+
|
|
+ for (Field field : fields) {
|
|
+ int modifiers = field.getModifiers();
|
|
+ if (Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
|
|
+ boolean skipLoad = field.getAnnotation(DoNotLoad.class) != null || (alreadyInited && field.getAnnotation(HotReloadUnsupported.class) != null);
|
|
+ ConfigInfo configInfo = field.getAnnotation(ConfigInfo.class);
|
|
+
|
|
+ if (skipLoad || configInfo == null) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final String fullConfigKeyName = category.getBaseKeyName() + "." + singleConfigModule.getBaseName() + "." + configInfo.baseName();
|
|
+
|
|
+ field.setAccessible(true);
|
|
+ final Object currentValue = field.get(null);
|
|
+
|
|
+ if (!configFileInstance.contains(fullConfigKeyName)) {
|
|
+ if (currentValue == null) {
|
|
+ throw new UnsupportedOperationException("Config " + singleConfigModule.getBaseName() + "tried to add an null default value!");
|
|
+ }
|
|
+
|
|
+ final String comments = configInfo.comments();
|
|
+
|
|
+ if (!comments.isBlank()) {
|
|
+ configFileInstance.setComment(fullConfigKeyName, comments);
|
|
+ }
|
|
+
|
|
+ configFileInstance.add(fullConfigKeyName, currentValue);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final Object actuallyValue = configFileInstance.get(fullConfigKeyName);
|
|
+ field.set(null, actuallyValue);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ singleConfigModule.onLoaded(configFileInstance);
|
|
+ }
|
|
+
|
|
+ public static @NotNull Set<Class<?>> getClasses(String pack) {
|
|
+ Set<Class<?>> classes = new LinkedHashSet<>();
|
|
+ String packageDirName = pack.replace('.', '/');
|
|
+ Enumeration<URL> dirs;
|
|
+
|
|
+ try {
|
|
+ dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
|
|
+ while (dirs.hasMoreElements()) {
|
|
+ URL url = dirs.nextElement();
|
|
+ String protocol = url.getProtocol();
|
|
+ if ("file".equals(protocol)) {
|
|
+ String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8);
|
|
+ findClassesInPackageByFile(pack, filePath, classes);
|
|
+ } else if ("jar".equals(protocol)) {
|
|
+ JarFile jar;
|
|
+ try {
|
|
+ jar = ((JarURLConnection) url.openConnection()).getJarFile();
|
|
+ Enumeration<JarEntry> entries = jar.entries();
|
|
+ findClassesInPackageByJar(pack, entries, packageDirName, classes);
|
|
+ } catch (IOException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } catch (IOException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+
|
|
+ return classes;
|
|
+ }
|
|
+
|
|
+ private static void findClassesInPackageByFile(String packageName, String packagePath, Set<Class<?>> classes) {
|
|
+ File dir = new File(packagePath);
|
|
+
|
|
+ if (!dir.exists() || !dir.isDirectory()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ File[] dirfiles = dir.listFiles((file) -> file.isDirectory() || file.getName().endsWith(".class"));
|
|
+ if (dirfiles != null) {
|
|
+ for (File file : dirfiles) {
|
|
+ if (file.isDirectory()) {
|
|
+ findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), classes);
|
|
+ } else {
|
|
+ String className = file.getName().substring(0, file.getName().length() - 6);
|
|
+ try {
|
|
+ classes.add(Class.forName(packageName + '.' + className));
|
|
+ } catch (ClassNotFoundException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, Set<Class<?>> classes) {
|
|
+ while (entries.hasMoreElements()) {
|
|
+ JarEntry entry = entries.nextElement();
|
|
+ String name = entry.getName();
|
|
+
|
|
+ if (name.charAt(0) == '/') {
|
|
+ name = name.substring(1);
|
|
+ }
|
|
+
|
|
+ if (name.startsWith(packageDirName)) {
|
|
+ int idx = name.lastIndexOf('/');
|
|
+
|
|
+ if (idx != -1) {
|
|
+ packageName = name.substring(0, idx).replace('/', '.');
|
|
+ }
|
|
+
|
|
+ if (name.endsWith(".class") && !entry.isDirectory()) {
|
|
+ String className = name.substring(packageName.length() + 1, name.length() - 6);
|
|
+ try {
|
|
+ classes.add(Class.forName(packageName + '.' + className));
|
|
+ } catch (ClassNotFoundException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|