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; } }