diff --git a/src/main/java/emu/grasscutter/Configuration.java b/src/main/java/emu/grasscutter/Configuration.java
index 7f7bf16fe..7adc334c1 100644
--- a/src/main/java/emu/grasscutter/Configuration.java
+++ b/src/main/java/emu/grasscutter/Configuration.java
@@ -1,12 +1,7 @@
package emu.grasscutter;
-import com.google.gson.JsonObject;
-import emu.grasscutter.Grasscutter.*;
-import emu.grasscutter.game.mail.Mail.*;
+import emu.grasscutter.utils.ConfigContainer;
-import java.io.FileReader;
-import java.lang.reflect.Field;
-import java.util.Arrays;
import java.util.Locale;
import static emu.grasscutter.Grasscutter.config;
@@ -17,56 +12,14 @@ import static emu.grasscutter.Grasscutter.config;
* Use `import static emu.grasscutter.Configuration.*;`
* to import all configuration constants.
*/
-public final class Configuration {
- private static int version() {
- return 1;
- }
-
- /**
- * Attempts to update the server's existing configuration to the latest configuration.
- */
- public static void updateConfig() {
- try { // Check if the server is using a legacy config.
- JsonObject configObject = Grasscutter.getGsonFactory()
- .fromJson(new FileReader(Grasscutter.configFile), JsonObject.class);
- if(!configObject.has("version")) {
- Grasscutter.getLogger().info("Updating legacy configuration...");
- Grasscutter.saveConfig(null);
- }
- } catch (Exception ignored) { }
-
- var existing = config.version;
- var latest = version();
-
- if(existing == latest)
- return;
-
- // Create a new configuration instance.
- Configuration updated = new Configuration();
- // Update all configuration fields.
- Field[] fields = Configuration.class.getDeclaredFields();
- Arrays.stream(fields).forEach(field -> {
- try {
- field.set(updated, field.get(config));
- } catch (Exception exception) {
- Grasscutter.getLogger().error("Failed to update a configuration field.", exception);
- }
- });
-
- try { // Save configuration & reload.
- Grasscutter.saveConfig(updated);
- Grasscutter.reloadConfig();
- } catch (Exception exception) {
- Grasscutter.getLogger().warn("Failed to inject the updated configuration.", exception);
- }
- }
+public final class Configuration extends ConfigContainer {
/*
* Constants
*/
// 'c' is short for 'config' and makes code look 'cleaner'.
- public static final Configuration c = config;
+ public static final ConfigContainer c = config;
public static final Locale LANGUAGE = config.language.language;
public static final Locale FALLBACK_LANGUAGE = config.language.fallback;
@@ -135,178 +88,4 @@ public final class Configuration {
public static int lr(int left, int right) {
return left == 0 ? right : left;
}
-
- /*
- * Configuration data.
- */
-
- public Structure folderStructure;
- public Database databaseInfo;
- public Language language;
- public Account account;
- public Server server;
-
- // DO NOT. TOUCH. THE VERSION NUMBER.
- public int version = version();
-
- /* Option containers. */
-
- public static class Database {
- public String connectionUri = "mongodb://localhost:27017";
- public String collection = "grasscutter";
- }
-
- public static class Structure {
- public String resources = "./resources/";
- public String data = "./data/";
- public String packets = "./packets/";
- public String keys = "./keys/";
- public String scripts = "./resources/scripts/";
- public String plugins = "./plugins/";
-
- // UNUSED (potentially added later?)
- // public String dumps = "./dumps/";
- }
-
- public static class Server {
- public ServerDebugMode debugLevel = ServerDebugMode.NONE;
- public ServerRunMode runMode = ServerRunMode.HYBRID;
-
- public Dispatch dispatch = new Dispatch();
- public Game game = new Game();
- }
-
- public static class Language {
- public Locale language = Locale.getDefault();
- public Locale fallback = Locale.US;
- }
-
- public static class Account {
- public boolean autoCreate = false;
- public String[] defaultPermissions = {};
- }
-
- /* Server options. */
-
- public static class Dispatch {
- public String bindAddress = "0.0.0.0";
- /* This is the address used in URLs. */
- public String accessAddress = "127.0.0.1";
-
- public int bindPort = 443;
- /* This is the port used in URLs. */
- public int accessPort = 443;
-
- public Encryption encryption = new Encryption();
- public Policies policies = new Policies();
- public Region[] regions = {};
-
- public String defaultName = "Grasscutter";
- }
-
- public static class Game {
- public String bindAddress = "0.0.0.0";
- /* This is the address used in the default region. */
- public String accessAddress = "127.0.0.1";
-
- public int bindPort = 443;
- /* This is the port used in the default region. */
- public int accessPort = 443;
-
- public GameOptions gameOptions = new GameOptions();
- public JoinOptions joinOptions = new JoinOptions();
- public ConsoleAccount serverAccount = new ConsoleAccount();
- }
-
- /* Data containers. */
-
- public static class Encryption {
- public boolean useEncryption = true;
- /* Should 'https' be appended to URLs? */
- public boolean useInRouting = true;
- public String keystore = "./keystore.p12";
- public String keystorePassword = "123456";
- }
-
- public static class Policies {
- public CORS cors = new CORS();
-
- public static class CORS {
- public boolean enabled = false;
- public String[] allowedOrigins = new String[]{"*"};
- }
- }
-
- public static class GameOptions {
- public InventoryLimits inventoryLimits = new InventoryLimits();
- public AvatarLimits avatarLimits = new AvatarLimits();
- public int worldEntityLimit = 1000; // Unenforced. TODO: Implement.
-
- public boolean watchGachaConfig = false;
- public boolean enableShopItems = true;
- public boolean staminaUsage = true;
- public Rates rates = new Rates();
-
- public Database databaseInfo = new Database();
-
- public static class InventoryLimits {
- public int weapons = 2000;
- public int relics = 2000;
- public int materials = 2000;
- public int furniture = 2000;
- public int all = 30000;
- }
-
- public static class AvatarLimits {
- public int singlePlayerTeam = 4;
- public int multiplayerTeam = 4;
- }
-
- public static class Rates {
- public float adventureExp = 1.0f;
- public float mora = 1.0f;
- public float leyLines = 1.0f;
- }
- }
-
- public static class JoinOptions {
- public int[] welcomeEmotes = {2007, 1002, 4010};
- public String welcomeMessage = "Welcome to a Grasscutter server.";
- public Mail welcomeMail = new Mail();
-
- public static class Mail {
- public String title = "Welcome to Grasscutter!";
- public String content = """
- Hi there!\r
- First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r
- \r
- Check out our:\r
-
- """;
- public String sender = "Lawnmower";
- public MailItem[] items = {
- new MailItem(13509, 1, 1),
- new MailItem(201, 99999, 1)
- };
- }
- }
-
- public static class ConsoleAccount {
- public int avatarId = 10000007;
- public int nameCardId = 210001;
- public int adventureRank = 1;
- public int worldLevel = 0;
-
- public String nickName = "Server";
- public String signature = "Welcome to Grasscutter!";
- }
-
- /* Objects. */
-
- public static class Region {
- public String Name = "os_usa";
- public String Title = "Grasscutter";
- public String Ip = "127.0.0.1";
- public int Port = 22102;
- }
}
\ No newline at end of file
diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java
index 6ba8bd986..73e761e6e 100644
--- a/src/main/java/emu/grasscutter/Grasscutter.java
+++ b/src/main/java/emu/grasscutter/Grasscutter.java
@@ -1,14 +1,13 @@
package emu.grasscutter;
import java.io.*;
-import java.lang.reflect.Field;
-import java.util.Arrays;
import java.util.Calendar;
import emu.grasscutter.command.CommandMap;
import emu.grasscutter.plugin.PluginManager;
import emu.grasscutter.plugin.api.ServerHook;
import emu.grasscutter.scripts.ScriptLoader;
+import emu.grasscutter.utils.ConfigContainer;
import emu.grasscutter.utils.Utils;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
@@ -52,16 +51,16 @@ public final class Grasscutter {
private static PluginManager pluginManager;
public static final Reflections reflector = new Reflections("emu.grasscutter");
- public static final Configuration config;
+ public static ConfigContainer config;
static {
// Declare logback configuration.
System.setProperty("logback.configurationFile", "src/main/resources/logback.xml");
// Load server configuration.
- config = Grasscutter.loadConfig();
+ Grasscutter.loadConfig();
// Attempt to update configuration.
- Configuration.updateConfig();
+ ConfigContainer.updateConfig();
// Load translation files.
Grasscutter.loadLanguage();
@@ -144,34 +143,20 @@ public final class Grasscutter {
/**
* Attempts to load the configuration from a file.
- * @return The config from the file, or a new instance.
*/
- public static Configuration loadConfig() {
+ public static void loadConfig() {
try (FileReader file = new FileReader(configFile)) {
- return gson.fromJson(file, Configuration.class);
- } catch (Exception e) {
+ config = gson.fromJson(file, ConfigContainer.class);
+ } catch (Exception exception) {
Grasscutter.saveConfig(null);
- return new Configuration();
+ config = new ConfigContainer();
+ } catch (Error error) {
+ // Occurred probably from an outdated config file.
+ Grasscutter.saveConfig(null);
+ config = new ConfigContainer();
}
}
- /**
- * Attempts to reload the configuration from the file.
- * Uses reflection to **replace** the fields in the config.
- */
- public static void reloadConfig() {
- Configuration fileConfig = Grasscutter.loadConfig();
-
- Field[] fields = Configuration.class.getDeclaredFields();
- Arrays.stream(fields).forEach(field -> {
- try {
- field.set(config, field.get(fileConfig));
- } catch (Exception exception) {
- Grasscutter.getLogger().error("Failed to update a configuration field.", exception);
- }
- });
- }
-
public static void loadLanguage() {
var locale = config.language.language;
language = Language.getLanguage(Utils.getLanguageCode(locale));
@@ -181,8 +166,8 @@ public final class Grasscutter {
* Saves the provided server configuration.
* @param config The configuration to save, or null for a new one.
*/
- public static void saveConfig(@Nullable Configuration config) {
- if(config == null) config = new Configuration();
+ public static void saveConfig(@Nullable ConfigContainer config) {
+ if(config == null) config = new ConfigContainer();
try (FileWriter file = new FileWriter(configFile)) {
file.write(gson.toJson(config));
@@ -231,7 +216,7 @@ public final class Grasscutter {
}
}
- public static Configuration getConfig() {
+ public static ConfigContainer getConfig() {
return config;
}
diff --git a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java
index 40b8994ec..9414a89c4 100644
--- a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java
@@ -16,7 +16,7 @@ public final class ReloadCommand implements CommandHandler {
public void execute(Player sender, Player targetPlayer, List args) {
CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_start"));
- Grasscutter.reloadConfig();
+ Grasscutter.loadConfig();
Grasscutter.loadLanguage();
Grasscutter.getGameServer().getGachaManager().load();
Grasscutter.getGameServer().getDropManager().load();
diff --git a/src/main/java/emu/grasscutter/utils/ConfigContainer.java b/src/main/java/emu/grasscutter/utils/ConfigContainer.java
new file mode 100644
index 000000000..a848dff39
--- /dev/null
+++ b/src/main/java/emu/grasscutter/utils/ConfigContainer.java
@@ -0,0 +1,229 @@
+package emu.grasscutter.utils;
+
+import com.google.gson.JsonObject;
+import emu.grasscutter.Grasscutter;
+
+import java.io.FileReader;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Locale;
+
+import static emu.grasscutter.Grasscutter.config;
+
+/**
+ * *when your JVM fails*
+ */
+public class ConfigContainer {
+ private static int version() {
+ return 1;
+ }
+
+ /**
+ * Attempts to update the server's existing configuration to the latest
+ */
+ public static void updateConfig() {
+ try { // Check if the server is using a legacy config.
+ JsonObject configObject = Grasscutter.getGsonFactory()
+ .fromJson(new FileReader(Grasscutter.configFile), JsonObject.class);
+ if(!configObject.has("version")) {
+ Grasscutter.getLogger().info("Updating legacy ..");
+ Grasscutter.saveConfig(null);
+ }
+ } catch (Exception ignored) { }
+
+ var existing = config.version;
+ var latest = version();
+
+ if(existing == latest)
+ return;
+
+ // Create a new configuration instance.
+ ConfigContainer updated = new ConfigContainer();
+ // Update all configuration fields.
+ Field[] fields = ConfigContainer.class.getDeclaredFields();
+ Arrays.stream(fields).forEach(field -> {
+ try {
+ field.set(updated, field.get(config));
+ } catch (Exception exception) {
+ Grasscutter.getLogger().error("Failed to update a configuration field.", exception);
+ }
+ }); updated.version = version();
+
+ try { // Save configuration & reload.
+ Grasscutter.saveConfig(updated);
+ Grasscutter.loadConfig();
+ } catch (Exception exception) {
+ Grasscutter.getLogger().warn("Failed to inject the updated ", exception);
+ }
+ }
+
+ public Structure folderStructure = new Structure();
+ public Database databaseInfo = new Database();
+ public Language language = new Language();
+ public Account account = new Account();
+ public Server server = new Server();
+
+ // DO NOT. TOUCH. THE VERSION NUMBER.
+ public int version = version();
+
+ /* Option containers. */
+
+ public static class Database {
+ public String connectionUri = "mongodb://localhost:27017";
+ public String collection = "grasscutter";
+ }
+
+ public static class Structure {
+ public String resources = "./resources/";
+ public String data = "./data/";
+ public String packets = "./packets/";
+ public String keys = "./keys/";
+ public String scripts = "./resources/scripts/";
+ public String plugins = "./plugins/";
+
+ // UNUSED (potentially added later?)
+ // public String dumps = "./dumps/";
+ }
+
+ public static class Server {
+ public Grasscutter.ServerDebugMode debugLevel = Grasscutter.ServerDebugMode.NONE;
+ public Grasscutter.ServerRunMode runMode = Grasscutter.ServerRunMode.HYBRID;
+
+ public Dispatch dispatch = new Dispatch();
+ public Game game = new Game();
+ }
+
+ public static class Language {
+ public Locale language = Locale.getDefault();
+ public Locale fallback = Locale.US;
+ }
+
+ public static class Account {
+ public boolean autoCreate = false;
+ public String[] defaultPermissions = {};
+ }
+
+ /* Server options. */
+
+ public static class Dispatch {
+ public String bindAddress = "0.0.0.0";
+ /* This is the address used in URLs. */
+ public String accessAddress = "127.0.0.1";
+
+ public int bindPort = 443;
+ /* This is the port used in URLs. */
+ public int accessPort = 443;
+
+ public Encryption encryption = new Encryption();
+ public Policies policies = new Policies();
+ public Region[] regions = {};
+
+ public String defaultName = "Grasscutter";
+ }
+
+ public static class Game {
+ public String bindAddress = "0.0.0.0";
+ /* This is the address used in the default region. */
+ public String accessAddress = "127.0.0.1";
+
+ public int bindPort = 443;
+ /* This is the port used in the default region. */
+ public int accessPort = 443;
+
+ public GameOptions gameOptions = new GameOptions();
+ public JoinOptions joinOptions = new JoinOptions();
+ public ConsoleAccount serverAccount = new ConsoleAccount();
+ }
+
+ /* Data containers. */
+
+ public static class Encryption {
+ public boolean useEncryption = true;
+ /* Should 'https' be appended to URLs? */
+ public boolean useInRouting = true;
+ public String keystore = "./keystore.p12";
+ public String keystorePassword = "123456";
+ }
+
+ public static class Policies {
+ public Policies.CORS cors = new Policies.CORS();
+
+ public static class CORS {
+ public boolean enabled = false;
+ public String[] allowedOrigins = new String[]{"*"};
+ }
+ }
+
+ public static class GameOptions {
+ public GameOptions.InventoryLimits inventoryLimits = new GameOptions.InventoryLimits();
+ public GameOptions.AvatarLimits avatarLimits = new GameOptions.AvatarLimits();
+ public int worldEntityLimit = 1000; // Unenforced. TODO: Implement.
+
+ public boolean watchGachaConfig = false;
+ public boolean enableShopItems = true;
+ public boolean staminaUsage = true;
+ public GameOptions.Rates rates = new GameOptions.Rates();
+
+ public Database databaseInfo = new Database();
+
+ public static class InventoryLimits {
+ public int weapons = 2000;
+ public int relics = 2000;
+ public int materials = 2000;
+ public int furniture = 2000;
+ public int all = 30000;
+ }
+
+ public static class AvatarLimits {
+ public int singlePlayerTeam = 4;
+ public int multiplayerTeam = 4;
+ }
+
+ public static class Rates {
+ public float adventureExp = 1.0f;
+ public float mora = 1.0f;
+ public float leyLines = 1.0f;
+ }
+ }
+
+ public static class JoinOptions {
+ public int[] welcomeEmotes = {2007, 1002, 4010};
+ public String welcomeMessage = "Welcome to a Grasscutter server.";
+ public JoinOptions.Mail welcomeMail = new JoinOptions.Mail();
+
+ public static class Mail {
+ public String title = "Welcome to Grasscutter!";
+ public String content = """
+ Hi there!\r
+ First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r
+ \r
+ Check out our:\r
+
+ """;
+ public String sender = "Lawnmower";
+ public emu.grasscutter.game.mail.Mail.MailItem[] items = {
+ new emu.grasscutter.game.mail.Mail.MailItem(13509, 1, 1),
+ new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1)
+ };
+ }
+ }
+
+ public static class ConsoleAccount {
+ public int avatarId = 10000007;
+ public int nameCardId = 210001;
+ public int adventureRank = 1;
+ public int worldLevel = 0;
+
+ public String nickName = "Server";
+ public String signature = "Welcome to Grasscutter!";
+ }
+
+ /* Objects. */
+
+ public static class Region {
+ public String Name = "os_usa";
+ public String Title = "Grasscutter";
+ public String Ip = "127.0.0.1";
+ public int Port = 22102;
+ }
+}
diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java
index 6b8365170..4af62bfb4 100644
--- a/src/main/java/emu/grasscutter/utils/Utils.java
+++ b/src/main/java/emu/grasscutter/utils/Utils.java
@@ -11,7 +11,6 @@ import java.util.Map;
import java.util.Random;
import java.util.Locale;
-import emu.grasscutter.Configuration;
import emu.grasscutter.Grasscutter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
@@ -175,7 +174,7 @@ public final class Utils {
* Checks for required files and folders before startup.
*/
public static void startupCheck() {
- Configuration config = Grasscutter.getConfig();
+ ConfigContainer config = Grasscutter.getConfig();
Logger logger = Grasscutter.getLogger();
boolean exit = false;