diff --git a/Minosoft.iml b/Minosoft.iml deleted file mode 100644 index 8bc82d596..000000000 --- a/Minosoft.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.java b/src/main/java/de/bixilon/minosoft/Minosoft.java index af9501b33..67b9e18b6 100644 --- a/src/main/java/de/bixilon/minosoft/Minosoft.java +++ b/src/main/java/de/bixilon/minosoft/Minosoft.java @@ -50,9 +50,7 @@ import java.util.UUID; public final class Minosoft { public static final HashSet eventManagers = new HashSet<>(); private static final CountUpAndDownLatch startStatusLatch = new CountUpAndDownLatch(1); - public static HashBiMap accountList; public static MojangAccount selectedAccount; - public static ArrayList serverList; public static Configuration config; public static void main(String[] args) { @@ -112,8 +110,6 @@ public final class Minosoft { // set log level from config Log.setLevel(LogLevels.valueOf(config.getString(ConfigurationPaths.StringPaths.GENERAL_LOG_LEVEL))); Log.info(String.format("Logging info with level: %s", Log.getLevel())); - - serverList = config.getServers(); progress.countDown(); }, "Configuration", String.format("Load config file (%s)", StaticConfiguration.CONFIG_FILENAME), Priorities.HIGHEST, TaskImportance.REQUIRED)); @@ -139,8 +135,7 @@ public final class Minosoft { taskWorker.addTask(new Task(progress -> { Log.debug("Refreshing account token..."); checkClientToken(); - accountList = config.getMojangAccounts(); - selectAccount(accountList.get(config.getString(ConfigurationPaths.StringPaths.ACCOUNT_SELECTED))); + selectAccount(config.getAccountList().get(config.getString(ConfigurationPaths.StringPaths.ACCOUNT_SELECTED))); }, "Token refresh", "Refresh selected account token", Priorities.LOW, TaskImportance.OPTIONAL, "Configuration")); taskWorker.addTask(new Task(progress -> { @@ -195,7 +190,6 @@ public final class Minosoft { } MojangAccount.RefreshStates refreshState = account.refreshToken(); if (refreshState == MojangAccount.RefreshStates.ERROR) { - accountList.remove(account.getUserId()); account.delete(); AccountListCell.listView.getItems().remove(account); selectedAccount = null; @@ -211,14 +205,6 @@ public final class Minosoft { return config; } - public static ArrayList getServerList() { - return serverList; - } - - public static HashBiMap getAccountList() { - return accountList; - } - public static MojangAccount getSelectedAccount() { return selectedAccount; } diff --git a/src/main/java/de/bixilon/minosoft/config/Configuration.java b/src/main/java/de/bixilon/minosoft/config/Configuration.java index 0f07b0230..b456334f9 100644 --- a/src/main/java/de/bixilon/minosoft/config/Configuration.java +++ b/src/main/java/de/bixilon/minosoft/config/Configuration.java @@ -14,9 +14,7 @@ package de.bixilon.minosoft.config; import com.google.common.collect.HashBiMap; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; +import com.google.gson.*; import de.bixilon.minosoft.gui.main.Server; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.util.Util; @@ -25,11 +23,15 @@ import de.bixilon.minosoft.util.mojang.api.MojangAccount; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; public class Configuration { public static final int LATEST_CONFIG_VERSION = 1; - final JsonObject config; + private final static JsonObject DEFAULT_CONFIGURATION = JsonParser.parseReader(new InputStreamReader(Configuration.class.getResourceAsStream("/config/" + StaticConfiguration.CONFIG_FILENAME))).getAsJsonObject(); + private final HashMap config = new HashMap<>(); + private final HashBiMap accountList = HashBiMap.create(); + private final HashBiMap serverList = HashBiMap.create(); private final Object lock = new Object(); public Configuration() throws IOException, ConfigMigrationException { @@ -47,7 +49,23 @@ public class Configuration { Files.copy(input, Paths.get(file.getAbsolutePath())); file = new File(StaticConfiguration.HOME_DIRECTORY + "config/" + StaticConfiguration.CONFIG_FILENAME); } - config = Util.readJsonFromFile(file.getAbsolutePath()); + + JsonObject json = Util.readJsonFromFile(file.getAbsolutePath()); + for (ConfigurationPaths.ConfigurationPath path : ConfigurationPaths.ALL_PATHS) { + config.put(path, getData(json, path)); + } + + // servers + for (Map.Entry entry : json.getAsJsonObject("servers").getAsJsonObject("entries").entrySet()) { + serverList.put(Integer.parseInt(entry.getKey()), Server.deserialize(entry.getValue().getAsJsonObject())); + } + + // accounts + for (Map.Entry entry : json.getAsJsonObject("accounts").getAsJsonObject("entries").entrySet()) { + MojangAccount account = MojangAccount.deserialize(entry.getValue().getAsJsonObject()); + accountList.put(account.getUserId(), account); + } + int configVersion = getInt(ConfigurationPaths.IntegerPaths.GENERAL_CONFIG_VERSION); if (configVersion > LATEST_CONFIG_VERSION) { throw new ConfigMigrationException(String.format("Configuration was migrated to newer config format (version=%d, expected=%d). Downgrading the config file is unsupported!", configVersion, LATEST_CONFIG_VERSION)); @@ -76,9 +94,27 @@ public class Configuration { e.printStackTrace(); return; } + JsonObject jsonObject = DEFAULT_CONFIGURATION.deepCopy(); synchronized (config) { - gson.toJson(config, writer); + + // accounts + JsonObject accountsEntriesJson = jsonObject.getAsJsonObject("servers").getAsJsonObject("entries"); + for (Map.Entry entry : serverList.entrySet()) { + accountsEntriesJson.add(String.valueOf(entry.getKey()), entry.getValue().serialize()); + } + + // servers + JsonObject serversEntriesJson = jsonObject.getAsJsonObject("accounts").getAsJsonObject("entries"); + for (Map.Entry entry : accountList.entrySet()) { + serversEntriesJson.add(entry.getKey(), entry.getValue().serialize()); + } + + // rest of data + for (ConfigurationPaths.ConfigurationPath path : ConfigurationPaths.ALL_PATHS) { + saveData(jsonObject, path, config.get(path)); + } } + gson.toJson(jsonObject, writer); try { writer.close(); } catch (IOException e) { @@ -99,65 +135,39 @@ public class Configuration { } public boolean getBoolean(ConfigurationPaths.BooleanPaths path) { - return switch (path) { - case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").get("fake-network-brand").getAsBoolean(); - case NETWORK_SHOW_LAN_SERVERS -> config.getAsJsonObject("network").get("show-lan-servers").getAsBoolean(); - case DEBUG_VERIFY_ASSETS -> config.getAsJsonObject("debug").get("verify-assets").getAsBoolean(); - }; + return (boolean) config.get(path); } public void putBoolean(ConfigurationPaths.BooleanPaths path, boolean value) { - switch (path) { - case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").addProperty("fake-network-brand", value); - case NETWORK_SHOW_LAN_SERVERS -> config.getAsJsonObject("network").addProperty("show-lan-servers", value); - case DEBUG_VERIFY_ASSETS -> config.getAsJsonObject("debug").addProperty("verify-assets", value); - } + config.put(path, value); } public int getInt(ConfigurationPaths.IntegerPaths path) { - return switch (path) { - case GENERAL_CONFIG_VERSION -> config.getAsJsonObject("general").get("version").getAsInt(); - case GAME_RENDER_DISTANCE -> config.getAsJsonObject("game").get("render-distance").getAsInt(); - }; + return (int) config.get(path); } public void putInt(ConfigurationPaths.IntegerPaths path, int value) { - switch (path) { - case GENERAL_CONFIG_VERSION -> config.getAsJsonObject("general").addProperty("version", value); - case GAME_RENDER_DISTANCE -> config.getAsJsonObject("game").addProperty("render-distance", value); - } + config.put(path, value); } public String getString(ConfigurationPaths.StringPaths path) { - return switch (path) { - case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").get("selected").getAsString(); - case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").get("log-level").getAsString(); - case GENERAL_LANGUAGE -> config.getAsJsonObject("general").get("language").getAsString(); - case RESOURCES_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").get("resources").getAsString(); - case CLIENT_TOKEN -> config.getAsJsonObject("accounts").get("client-token").getAsString(); - }; + return (String) config.get(path); } public void putString(ConfigurationPaths.StringPaths path, String value) { - switch (path) { - case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").addProperty("selected", value); - case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").addProperty("log-level", value); - case GENERAL_LANGUAGE -> config.getAsJsonObject("general").addProperty("language", value); - case RESOURCES_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").addProperty("resources", value); - case CLIENT_TOKEN -> config.getAsJsonObject("accounts").addProperty("client-token", value); - } + config.put(path, value); } public void putMojangAccount(MojangAccount account) { - config.getAsJsonObject("accounts").getAsJsonObject("entries").add(account.getUserId(), account.serialize()); + accountList.put(account.getUserId(), account); } public void putServer(Server server) { - config.getAsJsonObject("servers").getAsJsonObject("entries").add(String.valueOf(server.getId()), server.serialize()); + serverList.put(server.getId(), server); } public void removeServer(Server server) { - config.getAsJsonObject("servers").getAsJsonObject("entries").remove(String.valueOf(server.getId())); + serverList.remove(server.getId()); } public void saveToFile() { @@ -166,29 +176,16 @@ public class Configuration { } } - public HashBiMap getMojangAccounts() { - HashBiMap accounts = HashBiMap.create(); - JsonObject entries = config.getAsJsonObject("accounts").getAsJsonObject("entries"); - entries.keySet().forEach((entry) -> { - MojangAccount account = MojangAccount.deserialize(entries.get(entry).getAsJsonObject()); - accounts.put(account.getUserId(), account); - }); - return accounts; - } - - public ArrayList getServers() { - ArrayList servers = new ArrayList<>(); - JsonObject entries = config.getAsJsonObject("servers").getAsJsonObject("entries"); - entries.keySet().forEach((entry) -> servers.add(Server.deserialize(entries.get(entry).getAsJsonObject()))); - return servers; - } - public void removeAccount(MojangAccount account) { - config.getAsJsonObject("accounts").getAsJsonObject("entries").remove(account.getUserId()); + accountList.remove(account.getUserId()); } - public JsonObject getConfig() { - return config; + public HashBiMap getServerList() { + return serverList; + } + + public HashBiMap getAccountList() { + return accountList; } private void migrateConfiguration() throws ConfigMigrationException { @@ -209,4 +206,53 @@ public class Configuration { default -> throw new ConfigMigrationException("Can not migrate config: Unknown config version " + nextVersion); } } + + private Object getData(JsonObject json, ConfigurationPaths.ConfigurationPath path) { + if (path instanceof ConfigurationPaths.BooleanPaths booleanPath) { + return switch (booleanPath) { + case NETWORK_FAKE_CLIENT_BRAND -> json.getAsJsonObject("network").get("fake-network-brand").getAsBoolean(); + case NETWORK_SHOW_LAN_SERVERS -> json.getAsJsonObject("network").get("show-lan-servers").getAsBoolean(); + case DEBUG_VERIFY_ASSETS -> json.getAsJsonObject("debug").get("verify-assets").getAsBoolean(); + }; + } + if (path instanceof ConfigurationPaths.IntegerPaths integerPath) { + return switch (integerPath) { + case GENERAL_CONFIG_VERSION -> json.getAsJsonObject("general").get("version").getAsInt(); + case GAME_RENDER_DISTANCE -> json.getAsJsonObject("game").get("render-distance").getAsInt(); + }; + } + if (path instanceof ConfigurationPaths.StringPaths stringPath) { + return switch (stringPath) { + case ACCOUNT_SELECTED -> json.getAsJsonObject("accounts").get("selected").getAsString(); + case GENERAL_LOG_LEVEL -> json.getAsJsonObject("general").get("log-level").getAsString(); + case GENERAL_LANGUAGE -> json.getAsJsonObject("general").get("language").getAsString(); + case RESOURCES_URL -> json.getAsJsonObject("download").getAsJsonObject("urls").get("resources").getAsString(); + case CLIENT_TOKEN -> json.getAsJsonObject("accounts").get("client-token").getAsString(); + }; + } + throw new RuntimeException(); + } + + private void saveData(JsonObject input, ConfigurationPaths.ConfigurationPath path, Object data) { + if (data instanceof Boolean bool) { + switch ((ConfigurationPaths.BooleanPaths) path) { + case NETWORK_FAKE_CLIENT_BRAND -> input.getAsJsonObject("network").addProperty("fake-network-brand", bool); + case NETWORK_SHOW_LAN_SERVERS -> input.getAsJsonObject("network").addProperty("show-lan-servers", bool); + case DEBUG_VERIFY_ASSETS -> input.getAsJsonObject("debug").addProperty("verify-assets", bool); + } + } else if (data instanceof Integer integer) { + switch ((ConfigurationPaths.IntegerPaths) path) { + case GENERAL_CONFIG_VERSION -> input.getAsJsonObject("general").addProperty("version", integer); + case GAME_RENDER_DISTANCE -> input.getAsJsonObject("game").addProperty("render-distance", integer); + } + } else if (data instanceof String string) { + switch ((ConfigurationPaths.StringPaths) path) { + case ACCOUNT_SELECTED -> input.getAsJsonObject("accounts").addProperty("selected", string); + case GENERAL_LOG_LEVEL -> input.getAsJsonObject("general").addProperty("log-level", string); + case GENERAL_LANGUAGE -> input.getAsJsonObject("general").addProperty("language", string); + case RESOURCES_URL -> input.getAsJsonObject("download").getAsJsonObject("urls").addProperty("resources", string); + case CLIENT_TOKEN -> input.getAsJsonObject("accounts").addProperty("client-token", string); + } + } + } } diff --git a/src/main/java/de/bixilon/minosoft/config/ConfigurationPaths.java b/src/main/java/de/bixilon/minosoft/config/ConfigurationPaths.java index dc1316f52..492674eac 100644 --- a/src/main/java/de/bixilon/minosoft/config/ConfigurationPaths.java +++ b/src/main/java/de/bixilon/minosoft/config/ConfigurationPaths.java @@ -13,8 +13,19 @@ package de.bixilon.minosoft.config; +import java.util.Arrays; +import java.util.HashSet; + public abstract class ConfigurationPaths { - public enum StringPaths { + static HashSet ALL_PATHS = new HashSet<>(); + + static { + ALL_PATHS.addAll(Arrays.asList(StringPaths.values())); + ALL_PATHS.addAll(Arrays.asList(BooleanPaths.values())); + ALL_PATHS.addAll(Arrays.asList(IntegerPaths.values())); + } + + public enum StringPaths implements ConfigurationPath { GENERAL_LOG_LEVEL, CLIENT_TOKEN, RESOURCES_URL, @@ -22,14 +33,17 @@ public abstract class ConfigurationPaths { GENERAL_LANGUAGE, } - public enum BooleanPaths { + public enum BooleanPaths implements ConfigurationPath { NETWORK_FAKE_CLIENT_BRAND, NETWORK_SHOW_LAN_SERVERS, DEBUG_VERIFY_ASSETS } - public enum IntegerPaths { + public enum IntegerPaths implements ConfigurationPath { GENERAL_CONFIG_VERSION, GAME_RENDER_DISTANCE } + + public interface ConfigurationPath { + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/main/AccountListCell.java b/src/main/java/de/bixilon/minosoft/gui/main/AccountListCell.java index 5592f9386..9df1aca87 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/AccountListCell.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/AccountListCell.java @@ -102,10 +102,10 @@ public class AccountListCell extends ListCell implements Initiali public void delete() { account.delete(); if (Minosoft.getSelectedAccount() == account) { - if (Minosoft.getAccountList().isEmpty()) { + if (Minosoft.getConfig().getAccountList().isEmpty()) { Minosoft.selectAccount(null); } else { - Minosoft.selectAccount(Minosoft.getAccountList().values().iterator().next()); + Minosoft.selectAccount(Minosoft.getConfig().getAccountList().values().iterator().next()); } listView.refresh(); } diff --git a/src/main/java/de/bixilon/minosoft/gui/main/AccountWindow.java b/src/main/java/de/bixilon/minosoft/gui/main/AccountWindow.java index bfff0d48b..0f9909eb5 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/AccountWindow.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/AccountWindow.java @@ -46,7 +46,7 @@ public class AccountWindow implements Initializable { public void initialize(URL url, ResourceBundle resourceBundle) { AccountListCell.listView.setCellFactory((lv) -> AccountListCell.newInstance()); - ObservableList accounts = FXCollections.observableArrayList(Minosoft.getAccountList().values()); + ObservableList accounts = FXCollections.observableArrayList(Minosoft.getConfig().getAccountList().values()); AccountListCell.listView.setItems(accounts); accountPane.setCenter(AccountListCell.listView); @@ -91,7 +91,7 @@ public class AccountWindow implements Initializable { if (attempt.succeeded()) { // login okay MojangAccount account = attempt.getAccount(); - Minosoft.accountList.put(account.getUserId(), account); + Minosoft.getConfig().putMojangAccount(account); account.saveToConfig(); AccountListCell.listView.getItems().add(account); Log.info(String.format("Added and saved account (playerName=%s, email=%s, uuid=%s)", account.getPlayerName(), account.getMojangUserName(), account.getUUID())); diff --git a/src/main/java/de/bixilon/minosoft/gui/main/Launcher.java b/src/main/java/de/bixilon/minosoft/gui/main/Launcher.java index b0fc5c4f4..d2745a131 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/Launcher.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/Launcher.java @@ -62,7 +62,7 @@ public class Launcher { ServerListCell.listView.setCellFactory((lv) -> ServerListCell.newInstance()); ObservableList servers = FXCollections.observableArrayList(); - servers.addAll(Minosoft.serverList); + servers.addAll(Minosoft.getConfig().getServerList().values()); ServerListCell.listView.setItems(servers); LANServerListener.removeAll(); // remove all LAN Servers diff --git a/src/main/java/de/bixilon/minosoft/gui/main/MainWindow.java b/src/main/java/de/bixilon/minosoft/gui/main/MainWindow.java index 8863da32e..9247b31d5 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/MainWindow.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/MainWindow.java @@ -203,7 +203,7 @@ public class MainWindow implements Initializable { if (server1 == null) { server1 = new Server(Server.getNextServerId(), serverName, serverAddress, desiredVersionId); - Minosoft.serverList.add(server1); + Minosoft.getConfig().putServer(server1); ServerListCell.listView.getItems().add(server1); } else { server1.setName(serverName); diff --git a/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java b/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java index d9691b054..a96bc77f0 100644 --- a/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java +++ b/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java @@ -105,7 +105,6 @@ public class MojangAccount { } public void delete() { - Minosoft.getAccountList().remove(this.getUserId()); Minosoft.getConfig().removeAccount(this); Minosoft.getConfig().saveToFile(); }