From c6323e97596b303d1b6384ac93967831c59a34f2 Mon Sep 17 00:00:00 2001 From: AnimeGitB Date: Tue, 9 Aug 2022 21:44:44 +0930 Subject: [PATCH] Funnel all gson calls into helper functions Add deprecated getGsonFactory for plugin compat until 3.0 --- .../java/emu/grasscutter/Grasscutter.java | 11 +- .../grasscutter/config/ConfigContainer.java | 6 +- .../java/emu/grasscutter/data/DataLoader.java | 19 +++ .../emu/grasscutter/data/ResourceLoader.java | 151 ++++++++---------- .../game/activity/ActivityManager.java | 13 +- .../game/activity/PlayerActivityData.java | 3 +- .../musicgame/MusicGameActivityHandler.java | 4 +- .../game/combine/CombineManger.java | 17 +- .../emu/grasscutter/game/drop/DropSystem.java | 10 +- .../dungeons/challenge/DungeonChallenge.java | 14 +- .../game/expedition/ExpeditionSystem.java | 13 +- .../grasscutter/game/gacha/GachaSystem.java | 13 +- .../game/managers/energy/EnergyManager.java | 20 +-- .../emu/grasscutter/game/shop/ShopSystem.java | 23 ++- .../game/systems/AnnouncementSystem.java | 7 +- .../grasscutter/game/tower/TowerSystem.java | 9 +- .../game/world/WorldDataSystem.java | 18 +-- .../net/packet/PacketOpcodesUtils.java | 3 +- .../emu/grasscutter/plugin/PluginManager.java | 2 +- .../java/emu/grasscutter/utils/Language.java | 2 +- .../java/emu/grasscutter/utils/Utils.java | 56 ++++++- 21 files changed, 194 insertions(+), 220 deletions(-) diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index d7d64fb61..0f3827ab8 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -3,7 +3,6 @@ package emu.grasscutter; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import emu.grasscutter.auth.AuthenticationSystem; import emu.grasscutter.auth.DefaultAuthentication; @@ -56,7 +55,6 @@ public final class Grasscutter { private static Language language; - private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); public static final File configFile = new File("./config.json"); private static int day; // Current day of week. @@ -203,8 +201,8 @@ public final class Grasscutter { } // If the file already exists, we attempt to load it. - try (FileReader file = new FileReader(configFile)) { - config = gson.fromJson(file, ConfigContainer.class); + try { + config = Utils.loadJsonToClass(configFile.getPath(), ConfigContainer.class); } catch (Exception exception) { getLogger().error("There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); System.exit(1); @@ -220,7 +218,7 @@ public final class Grasscutter { if (config == null) config = new ConfigContainer(); try (FileWriter file = new FileWriter(configFile)) { - file.write(gson.toJson(config)); + file.write(Utils.jsonEncode(config)); } catch (IOException ignored) { Grasscutter.getLogger().error("Unable to write to config file."); } catch (Exception e) { @@ -272,8 +270,9 @@ public final class Grasscutter { return consoleLineReader; } + @Deprecated(forRemoval = true) public static Gson getGsonFactory() { - return gson; + return Utils.getGsonFactory(); } public static HttpServer getHttpServer() { diff --git a/src/main/java/emu/grasscutter/config/ConfigContainer.java b/src/main/java/emu/grasscutter/config/ConfigContainer.java index 5d94c14b7..f6e84a7db 100644 --- a/src/main/java/emu/grasscutter/config/ConfigContainer.java +++ b/src/main/java/emu/grasscutter/config/ConfigContainer.java @@ -4,10 +4,9 @@ import com.google.gson.JsonObject; import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter.ServerDebugMode; import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.utils.Utils; -import java.nio.charset.StandardCharsets; import java.util.Set; -import java.io.FileReader; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Locale; @@ -27,8 +26,7 @@ public class ConfigContainer { */ public static void updateConfig() { try { // Check if the server is using a legacy config. - JsonObject configObject = Grasscutter.getGsonFactory() - .fromJson(new FileReader(Grasscutter.configFile, StandardCharsets.UTF_8), JsonObject.class); + JsonObject configObject = Utils.loadJsonToClass(Grasscutter.configFile.getPath(), JsonObject.class); if (!configObject.has("version")) { Grasscutter.getLogger().info("Updating legacy .."); Grasscutter.saveConfig(null); diff --git a/src/main/java/emu/grasscutter/data/DataLoader.java b/src/main/java/emu/grasscutter/data/DataLoader.java index 902996593..d7f1a7c72 100644 --- a/src/main/java/emu/grasscutter/data/DataLoader.java +++ b/src/main/java/emu/grasscutter/data/DataLoader.java @@ -15,6 +15,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Path; import java.util.List; +import java.util.Map; public class DataLoader { @@ -69,6 +70,24 @@ public class DataLoader { return null; } + public static T loadClass(String resourcePath, Class classType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return Utils.loadJsonToClass(reader, classType); + } + } + + public static List loadList(String resourcePath, Class classType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return Utils.loadJsonToList(reader, classType); + } + } + + public static Map loadMap(String resourcePath, Class keyType, Class valueType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return Utils.loadJsonToMap(reader, keyType, valueType); + } + } + public static void checkAllFiles() { try { List filenames = FileUtils.getPathsFromResource("/defaults/data/"); diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 5ceb756fd..56aa89dfb 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -2,7 +2,6 @@ package emu.grasscutter.data; import com.google.gson.JsonElement; import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.AbilityModifier.AbilityConfigData; @@ -21,7 +20,6 @@ import lombok.SneakyThrows; import org.reflections.Reflections; import java.io.*; -import java.lang.reflect.Type; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -29,6 +27,7 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static emu.grasscutter.config.Configuration.DATA; import static emu.grasscutter.config.Configuration.RESOURCE; import static emu.grasscutter.utils.Language.translate; @@ -119,15 +118,13 @@ public class ResourceLoader { } @SuppressWarnings({"rawtypes", "unchecked"}) - protected static void loadFromResource(Class c, String fileName, Int2ObjectMap map) throws Exception { - try (FileReader fileReader = new FileReader(RESOURCE("ExcelBinOutput/" + fileName))) { - List list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, c).getType()); + protected static void loadFromResource(Class c, String fileName, Int2ObjectMap map) throws Exception { + List list = Utils.loadJsonToList(RESOURCE("ExcelBinOutput/" + fileName), c); - for (Object o : list) { - GameResource res = (GameResource) o; - res.onLoad(); - map.put(res.getId(), res); - } + for (T o : list) { + GameResource res = (GameResource) o; + res.onLoad(); + map.put(res.getId(), res); } } @@ -140,7 +137,6 @@ public class ResourceLoader { return; } - List scenePointList = new ArrayList<>(); for (File file : Objects.requireNonNull(folder.listFiles())) { ScenePointConfig config; Integer sceneId; @@ -152,8 +148,8 @@ public class ResourceLoader { continue; } - try (FileReader fileReader = new FileReader(file)) { - config = Grasscutter.getGsonFactory().fromJson(fileReader, ScenePointConfig.class); + try { + config = Utils.loadJsonToClass(file.getPath(), ScenePointConfig.class); } catch (Exception e) { e.printStackTrace(); continue; @@ -163,22 +159,20 @@ public class ResourceLoader { continue; } + List scenePoints = new ArrayList<>(); for (Map.Entry entry : config.points.entrySet()) { - PointData pointData = Grasscutter.getGsonFactory().fromJson(entry.getValue(), PointData.class); - pointData.setId(Integer.parseInt(entry.getKey())); + int id = Integer.parseInt(entry.getKey()); + String name = sceneId + "_" + entry.getKey(); + PointData pointData = Utils.jsonDecode(entry.getValue(), PointData.class); + pointData.setId(id); - ScenePointEntry sl = new ScenePointEntry(sceneId + "_" + entry.getKey(), pointData); - scenePointList.add(sl); - GameData.getScenePointIdList().add(pointData.getId()); + GameData.getScenePointIdList().add(id); + GameData.getScenePointEntries().put(name, new ScenePointEntry(name, pointData)); + scenePoints.add(id); pointData.updateDailyDungeon(); } - - GameData.getScenePointsPerScene().put(sceneId, new ArrayList<>()); - for (ScenePointEntry entry : scenePointList) { - GameData.getScenePointEntries().put(entry.getName(), entry); - GameData.getScenePointsPerScene().get(sceneId).add(entry.getPointData().getId()); - } + GameData.getScenePointsPerScene().put(sceneId, scenePoints); } } @@ -186,15 +180,15 @@ public class ResourceLoader { List embryoList = null; // Read from cached file if exists - try (InputStream embryoCache = DataLoader.load("AbilityEmbryos.json", false)) { - embryoList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(embryoCache), TypeToken.getParameterized(Collection.class, AbilityEmbryoEntry.class).getType()); + try { + embryoList = Utils.loadJsonToList(DATA("AbilityEmbryos.json"), AbilityEmbryoEntry.class); } catch (Exception ignored) {} if (embryoList == null) { // Load from BinOutput Pattern pattern = Pattern.compile("(?<=ConfigAvatar_)(.*?)(?=.json)"); - embryoList = new LinkedList<>(); + embryoList = new ArrayList<>(); File folder = new File(Utils.toFilePath(RESOURCE("BinOutput/Avatar/"))); File[] files = folder.listFiles(); if (files == null) { @@ -213,8 +207,8 @@ public class ResourceLoader { continue; } - try (FileReader fileReader = new FileReader(file)) { - config = Grasscutter.getGsonFactory().fromJson(fileReader, AvatarConfig.class); + try { + config = Utils.loadJsonToClass(file.getPath(), AvatarConfig.class); } catch (Exception e) { e.printStackTrace(); continue; @@ -229,14 +223,10 @@ public class ResourceLoader { embryoList.add(al); } - File playerElementsFile = new File(Utils.toFilePath(RESOURCE("BinOutput/AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"))); - - if (playerElementsFile.exists()) { - try (FileReader fileReader = new FileReader(playerElementsFile)) { - GameDepot.setPlayerAbilities(Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken>(){}.getType())); - } catch (Exception e) { - e.printStackTrace(); - } + try { + GameDepot.setPlayerAbilities(Utils.loadJsonToMap(RESOURCE("BinOutput/AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"), String.class, AvatarConfig.class)); + } catch (Exception e) { + e.printStackTrace(); } } @@ -262,8 +252,8 @@ public class ResourceLoader { for (File file : files) { List abilityConfigList; - try (FileReader fileReader = new FileReader(file)) { - abilityConfigList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, AbilityConfigData.class).getType()); + try { + abilityConfigList = Utils.loadJsonToList(file.getPath(), AbilityConfigData.class); } catch (Exception e) { e.printStackTrace(); continue; @@ -320,11 +310,8 @@ public class ResourceLoader { for (String name : spawnDataNames) { // Load spawn entries from file try (InputStreamReader reader = DataLoader.loadReader(name)) { - Type type = TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType(); - List list = Grasscutter.getGsonFactory().fromJson(reader, type); - // Add spawns to group if it already exists in our spawn group map - spawnEntryMap.addAll(list); + spawnEntryMap.addAll(Utils.loadJsonToList(reader, SpawnGroupEntry.class)); } catch (Exception ignored) {} } @@ -354,13 +341,12 @@ public class ResourceLoader { // Read from cached file if exists List list = null; - try (InputStream openConfigCache = DataLoader.load("OpenConfig.json", false)) { - list = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(openConfigCache), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType()); + try { + list = Utils.loadJsonToList(DATA("OpenConfig.json"), OpenConfigEntry.class); } catch (Exception ignored) {} if (list == null) { Map map = new TreeMap<>(); - java.lang.reflect.Type type = new TypeToken>() {}.getType(); String[] folderNames = {"BinOutput/Talent/EquipTalents/", "BinOutput/Talent/AvatarTalents/"}; for (String name : folderNames) { @@ -374,11 +360,10 @@ public class ResourceLoader { if (!file.getName().endsWith(".json")) { continue; } - Map config; - try (FileReader fileReader = new FileReader(file)) { - config = Grasscutter.getGsonFactory().fromJson(fileReader, type); + try { + config = Utils.loadJsonToMap(file.getPath(), String.class, OpenConfigData[].class); } catch (Exception e) { e.printStackTrace(); continue; @@ -414,8 +399,8 @@ public class ResourceLoader { for (File file : folder.listFiles()) { MainQuestData mainQuest = null; - try (FileReader fileReader = new FileReader(file)) { - mainQuest = Grasscutter.getGsonFactory().fromJson(fileReader, MainQuestData.class); + try { + mainQuest = Utils.loadJsonToClass(file.getPath(), MainQuestData.class); } catch (Exception e) { e.printStackTrace(); continue; @@ -424,16 +409,14 @@ public class ResourceLoader { GameData.getMainQuestDataMap().put(mainQuest.getId(), mainQuest); } - try (Reader reader = new FileReader(RESOURCE("QuestEncryptionKeys.json"))) { - List keys = Grasscutter.getGsonFactory().fromJson( - reader, - TypeToken.getParameterized(List.class, QuestEncryptionKey.class).getType()); + try { + List keys = DataLoader.loadList("QuestEncryptionKeys.json", QuestEncryptionKey.class); Int2ObjectMap questEncryptionMap = GameData.getMainQuestEncryptionMap(); keys.forEach(key -> questEncryptionMap.put(key.getMainQuestId(), key)); Grasscutter.getLogger().debug("Loaded {} quest keys.", questEncryptionMap.size()); - } catch (FileNotFoundException ignored) { - Grasscutter.getLogger().error("Unable to load quest keys - ./resources/QuestEncryptionKeys.json not found."); + } catch (FileNotFoundException | NullPointerException ignored) { + Grasscutter.getLogger().warn("Unable to load quest keys - ./resources/QuestEncryptionKeys.json not found."); } catch (Exception e) { Grasscutter.getLogger().error("Unable to load quest keys.", e); } @@ -450,8 +433,8 @@ public class ResourceLoader { for (File file : folder.listFiles()) { ScriptSceneData sceneData; - try (FileReader fileReader = new FileReader(file)) { - sceneData = Grasscutter.getGsonFactory().fromJson(fileReader, ScriptSceneData.class); + try { + sceneData = Utils.loadJsonToClass(file.getPath(), ScriptSceneData.class); } catch (Exception e) { e.printStackTrace(); continue; @@ -463,43 +446,41 @@ public class ResourceLoader { Grasscutter.getLogger().debug("Loaded " + GameData.getScriptSceneDataMap().size() + " ScriptSceneDatas."); } - @SneakyThrows - private static void loadHomeworldDefaultSaveData(){ - var folder = Files.list(Path.of(RESOURCE("BinOutput/HomeworldDefaultSave"))).toList(); - var pattern = Pattern.compile("scene(.*)_home_config.json"); - - for (var file : folder) { - var matcher = pattern.matcher(file.getFileName().toString()); + @SneakyThrows + private static void loadHomeworldDefaultSaveData() { + var pattern = Pattern.compile("scene(.*)_home_config.json"); + Files.list(Path.of(RESOURCE("BinOutput/HomeworldDefaultSave"))).forEach(file -> { + String filename = file.getFileName().toString(); + var matcher = pattern.matcher(filename); if (!matcher.find()) { - continue; + return; } - var sceneId = matcher.group(1); - - var data = Grasscutter.getGsonFactory().fromJson(Files.readString(file), HomeworldDefaultSaveData.class); - - GameData.getHomeworldDefaultSaveData().put(Integer.parseInt(sceneId), data); - } + try { + var sceneId = Integer.parseInt(matcher.group(1)); + var data = Utils.loadJsonToClass(filename, HomeworldDefaultSaveData.class); + GameData.getHomeworldDefaultSaveData().put(sceneId, data); + } catch (Exception ignored) {} + }); Grasscutter.getLogger().debug("Loaded " + GameData.getHomeworldDefaultSaveData().size() + " HomeworldDefaultSaveDatas."); } @SneakyThrows private static void loadNpcBornData() { - var folder = Files.list(Path.of(RESOURCE("BinOutput/Scene/SceneNpcBorn"))).toList(); - - for (var file : folder) { + Files.list(Path.of(RESOURCE("BinOutput/Scene/SceneNpcBorn"))).forEach(file -> { if (file.toFile().isDirectory()) { - continue; + return; } + try { + var data = Utils.loadJsonToClass(file.getFileName().toString(), SceneNpcBornData.class); + if (data.getBornPosList() == null || data.getBornPosList().size() == 0) { + return; + } - var data = Grasscutter.getGsonFactory().fromJson(Files.readString(file), SceneNpcBornData.class); - if (data.getBornPosList() == null || data.getBornPosList().size() == 0) { - continue; - } - - data.setIndex(SceneIndexManager.buildIndex(3, data.getBornPosList(), item -> item.getPos().toPoint())); - GameData.getSceneNpcBornData().put(data.getSceneId(), data); - } + data.setIndex(SceneIndexManager.buildIndex(3, data.getBornPosList(), item -> item.getPos().toPoint())); + GameData.getSceneNpcBornData().put(data.getSceneId(), data); + } catch (Exception ignored) {} + }); Grasscutter.getLogger().debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneNpcBornDatas."); } diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java index f4cd55f0c..a859d848f 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java @@ -1,7 +1,6 @@ package emu.grasscutter.game.activity; import com.esotericsoftware.reflectasm.ConstructorAccess; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; @@ -14,9 +13,6 @@ import emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify; import lombok.Getter; import org.reflections.Reflections; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -45,13 +41,8 @@ public class ActivityManager extends BasePlayerManager { activityWatcherTypeMap.put(typeName.value(), ConstructorAccess.get(item)); }); - try (Reader reader = DataLoader.loadReader("ActivityConfig.json")) { - List activities = Grasscutter.getGsonFactory().fromJson( - reader, - TypeToken.getParameterized(List.class, ActivityConfigItem.class).getType()); - - - activities.forEach(item -> { + try { + DataLoader.loadList("ActivityConfig.json", ActivityConfigItem.class).forEach(item -> { var activityData = GameData.getActivityDataMap().get(item.getActivityId()); if (activityData == null) { Grasscutter.getLogger().warn("activity {} not exist.", item.getActivityId()); diff --git a/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java b/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java index 3a4b207f3..033157aac 100644 --- a/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java +++ b/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java @@ -13,6 +13,7 @@ import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass; import emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify; +import emu.grasscutter.utils.Utils; import lombok.AccessLevel; import lombok.Builder; import lombok.Data; @@ -68,7 +69,7 @@ public class PlayerActivityData { } public void setDetail(Object detail){ - this.detail = Grasscutter.getGsonFactory().toJson(detail); + this.detail = Utils.jsonEncode(detail); } public void takeWatcherReward(int watcherId) { diff --git a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java index 7b8b81004..4c0930afa 100644 --- a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java +++ b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java @@ -8,6 +8,7 @@ import emu.grasscutter.game.props.ActivityType; import emu.grasscutter.net.proto.ActivityInfoOuterClass; import emu.grasscutter.net.proto.MusicBriefInfoOuterClass; import emu.grasscutter.net.proto.MusicGameActivityDetailInfoOuterClass; +import emu.grasscutter.utils.Utils; import java.util.stream.Collectors; @@ -47,8 +48,7 @@ public class MusicGameActivityHandler extends ActivityHandler { playerActivityData.save(); } - return Grasscutter.getGsonFactory().fromJson(playerActivityData.getDetail(), - MusicGamePlayerData.class); + return Utils.jsonDecode(playerActivityData.getDetail(), MusicGamePlayerData.class); } public boolean setMusicGameRecord(PlayerActivityData playerActivityData, MusicGamePlayerData.MusicGameRecord newRecord) { diff --git a/src/main/java/emu/grasscutter/game/combine/CombineManger.java b/src/main/java/emu/grasscutter/game/combine/CombineManger.java index 4aaacb88a..20b2e9a4b 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineManger.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineManger.java @@ -6,8 +6,6 @@ import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.excels.CombineData; import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.Inventory; -import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.ItemUseOp; @@ -19,18 +17,12 @@ import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify; import emu.grasscutter.server.packet.send.PacketCombineRsp; import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp; import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import com.google.gson.reflect.TypeToken; - public class CombineManger extends BaseGameSystem { private final static Int2ObjectMap> reliquaryDecomposeData = new Int2ObjectOpenHashMap<>(); @@ -40,13 +32,10 @@ public class CombineManger extends BaseGameSystem { public static void initialize() { // Read the data we need for strongbox. - try (Reader fileReader = DataLoader.loadReader("ReliquaryDecompose.json")) { - List decomposeEntries = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ReliquaryDecomposeEntry.class).getType()); - - for (ReliquaryDecomposeEntry entry : decomposeEntries) { + try { + DataLoader.loadList("ReliquaryDecompose.json", ReliquaryDecomposeEntry.class).forEach(entry -> { reliquaryDecomposeData.put(entry.getConfigId(), entry.getItems()); - } - + }); Grasscutter.getLogger().debug("Loaded {} reliquary decompose entries.", reliquaryDecomposeData.size()); } catch (Exception ex) { diff --git a/src/main/java/emu/grasscutter/game/drop/DropSystem.java b/src/main/java/emu/grasscutter/game/drop/DropSystem.java index b2b28852a..7c4dc44bb 100644 --- a/src/main/java/emu/grasscutter/game/drop/DropSystem.java +++ b/src/main/java/emu/grasscutter/game/drop/DropSystem.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.drop; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; @@ -19,9 +18,6 @@ import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Collection; import java.util.List; public class DropSystem extends BaseGameSystem { @@ -38,9 +34,9 @@ public class DropSystem extends BaseGameSystem { } public synchronized void load() { - try (Reader fileReader = DataLoader.loadReader("Drop.json")) { - getDropData().clear(); - List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType()); + getDropData().clear(); + try { + List banners = DataLoader.loadList("Drop.json", DropInfo.class); if (banners.size() > 0) { for (DropInfo di : banners) { getDropData().put(di.getMonsterId(), di.getDropDataList()); diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java index 844f23c5c..3455b4add 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java @@ -24,16 +24,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -import com.google.gson.reflect.TypeToken; - public class DungeonChallenge extends WorldChallenge { /** @@ -46,13 +41,10 @@ public class DungeonChallenge extends WorldChallenge { public static void initialize() { // Read the data we need for dungeon rewards drops. - try (Reader fileReader = DataLoader.loadReader("DungeonDrop.json")) { - List dungeonDropList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DungeonDrop.class).getType()); - - for (DungeonDrop entry : dungeonDropList) { + try { + DataLoader.loadList("DungeonDrop.json", DungeonDrop.class).forEach(entry -> { dungeonDropData.put(entry.getDungeonId(), entry.getDrops()); - } - + }); Grasscutter.getLogger().debug("Loaded {} dungeon drop data entries.", dungeonDropData.size()); } catch (Exception ex) { diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java index ddc0535d5..351b81b31 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.expedition; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.server.game.BaseGameSystem; @@ -8,12 +7,6 @@ import emu.grasscutter.server.game.GameServer; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import static emu.grasscutter.config.Configuration.*; - -import java.io.FileReader; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Collection; import java.util.List; public class ExpeditionSystem extends BaseGameSystem { @@ -30,9 +23,9 @@ public class ExpeditionSystem extends BaseGameSystem { } public synchronized void load() { - try (Reader fileReader = DataLoader.loadReader("ExpeditionReward.json")) { - getExpeditionRewardDataList().clear(); - List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ExpeditionRewardInfo.class).getType()); + getExpeditionRewardDataList().clear(); + try { + List banners = DataLoader.loadList("ExpeditionReward.json", ExpeditionRewardInfo.class); if (banners.size() > 0) { for (ExpeditionRewardInfo di : banners) { getExpeditionRewardDataList().put(di.getExpId(), di.getExpeditionRewardDataList()); diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java b/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java index 1d24c0b79..afe1bb21e 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java @@ -3,18 +3,11 @@ package emu.grasscutter.game.gacha; import static emu.grasscutter.config.Configuration.*; import java.io.File; -import java.io.FileReader; -import java.io.InputStreamReader; -import java.io.Reader; import java.nio.file.*; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.concurrent.ThreadLocalRandom; -import com.google.gson.reflect.TypeToken; - import com.sun.nio.file.SensitivityWatchEventModifier; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; @@ -76,9 +69,9 @@ public class GachaSystem extends BaseGameSystem { } public synchronized void load() { - try (Reader fileReader = DataLoader.loadReader("Banners.json")) { - getGachaBanners().clear(); - List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, GachaBanner.class).getType()); + getGachaBanners().clear(); + try { + List banners = DataLoader.loadList("Banners.json", GachaBanner.class); if (banners.size() > 0) { for (GachaBanner banner : banners) { getGachaBanners().put(banner.getScheduleId(), banner); diff --git a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java index cf449977a..3fc42d730 100644 --- a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java +++ b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java @@ -31,9 +31,6 @@ import emu.grasscutter.utils.Position; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,7 +39,6 @@ import java.util.concurrent.ThreadLocalRandom; import static emu.grasscutter.config.Configuration.GAME_OPTIONS; -import com.google.gson.reflect.TypeToken; import com.google.protobuf.InvalidProtocolBufferException; public class EnergyManager extends BasePlayerManager { @@ -60,12 +56,10 @@ public class EnergyManager extends BasePlayerManager { public static void initialize() { // Read the data we need for monster energy drops. - try (Reader fileReader = DataLoader.loadReader("EnergyDrop.json")) { - List energyDropList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, EnergyDropEntry.class).getType()); - - for (EnergyDropEntry entry : energyDropList) { + try { + DataLoader.loadList("EnergyDrop.json", EnergyDropEntry.class).forEach(entry -> { energyDropData.put(entry.getDropId(), entry.getDropList()); - } + }); Grasscutter.getLogger().debug("Energy drop data successfully loaded."); } @@ -74,12 +68,10 @@ public class EnergyManager extends BasePlayerManager { } // Read the data for particle generation from skills - try (Reader fileReader = new InputStreamReader(DataLoader.load("SkillParticleGeneration.json"))) { - List skillParticleGenerationList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, SkillParticleGenerationEntry.class).getType()); - - for (SkillParticleGenerationEntry entry : skillParticleGenerationList) { + try { + DataLoader.loadList("SkillParticleGeneration.json", SkillParticleGenerationEntry.class).forEach(entry -> { skillParticleGenerationData.put(entry.getAvatarId(), entry.getAmountList()); - } + }); Grasscutter.getLogger().debug("Skill particle generation data successfully loaded."); } diff --git a/src/main/java/emu/grasscutter/game/shop/ShopSystem.java b/src/main/java/emu/grasscutter/game/shop/ShopSystem.java index 006af71d2..ef2a39d1a 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopSystem.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopSystem.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.shop; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; @@ -14,11 +13,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import static emu.grasscutter.config.Configuration.*; -import java.io.FileReader; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -60,9 +55,9 @@ public class ShopSystem extends BaseGameSystem { } private void loadShop() { - try (Reader fileReader = DataLoader.loadReader("Shop.json")) { - getShopData().clear(); - List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType()); + getShopData().clear(); + try { + List banners = DataLoader.loadList("Shop.json", ShopTable.class); if (banners.size() > 0) { for (ShopTable shopTable : banners) { for (ShopInfo cost : shopTable.getItems()) { @@ -104,9 +99,9 @@ public class ShopSystem extends BaseGameSystem { } private void loadShopChest() { - try (Reader fileReader = DataLoader.loadReader("ShopChest.json")) { - getShopChestData().clear(); - List shopChestTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestTable.class).getType()); + getShopChestData().clear(); + try { + List shopChestTableList = DataLoader.loadList("ShopChest.json", ShopChestTable.class); if (shopChestTableList.size() > 0) { getShopChestData().addAll(shopChestTableList); Grasscutter.getLogger().debug("ShopChest data successfully loaded."); @@ -119,9 +114,9 @@ public class ShopSystem extends BaseGameSystem { } private void loadShopChestBatchUse() { - try (Reader fileReader = DataLoader.loadReader("ShopChestBatchUse.json")) { - getShopChestBatchUseData().clear(); - List shopChestBatchUseTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestBatchUseTable.class).getType()); + getShopChestBatchUseData().clear(); + try { + List shopChestBatchUseTableList = DataLoader.loadList("ShopChestBatchUse.json", ShopChestBatchUseTable.class); if (shopChestBatchUseTableList.size() > 0) { getShopChestBatchUseData().addAll(shopChestBatchUseTableList); Grasscutter.getLogger().debug("ShopChestBatchUse data successfully loaded."); diff --git a/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java b/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java index 510a3f61a..e27415237 100644 --- a/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java +++ b/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.systems; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.game.player.Player; @@ -16,7 +15,6 @@ import lombok.Data; import lombok.Getter; import lombok.experimental.FieldDefaults; -import java.io.InputStreamReader; import java.util.*; @Getter @@ -30,9 +28,8 @@ public class AnnouncementSystem extends BaseGameSystem { } private int loadConfig() { - try (var fileReader = DataLoader.loadReader("Announcement.json")) { - List announceConfigItems = Grasscutter.getGsonFactory().fromJson(fileReader, - TypeToken.getParameterized(List.class, AnnounceConfigItem.class).getType()); + try { + List announceConfigItems = DataLoader.loadList("Announcement.json", AnnounceConfigItem.class); announceConfigItemMap.clear(); announceConfigItems.forEach(i -> announceConfigItemMap.put(i.getTemplateId(), i)); diff --git a/src/main/java/emu/grasscutter/game/tower/TowerSystem.java b/src/main/java/emu/grasscutter/game/tower/TowerSystem.java index 1282d710a..014c5ddd7 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerSystem.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerSystem.java @@ -7,11 +7,6 @@ import emu.grasscutter.data.excels.TowerScheduleData; import emu.grasscutter.server.game.BaseGameSystem; import emu.grasscutter.server.game.GameServer; -import static emu.grasscutter.config.Configuration.*; - -import java.io.FileReader; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.ArrayList; import java.util.List; @@ -25,8 +20,8 @@ public class TowerSystem extends BaseGameSystem { private TowerScheduleConfig towerScheduleConfig; public synchronized void load() { - try (Reader fileReader = DataLoader.loadReader("TowerSchedule.json")) { - towerScheduleConfig = Grasscutter.getGsonFactory().fromJson(fileReader, TowerScheduleConfig.class); + try { + towerScheduleConfig = DataLoader.loadClass("TowerSchedule.json", TowerScheduleConfig.class); } catch (Exception e) { Grasscutter.getLogger().error("Unable to load tower schedule config.", e); } diff --git a/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java b/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java index 9251057aa..4715434b0 100644 --- a/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java +++ b/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.world; -import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; @@ -17,9 +16,6 @@ import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.server.game.BaseGameSystem; import emu.grasscutter.server.game.GameServer; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,15 +38,11 @@ public class WorldDataSystem extends BaseGameSystem { // set the special chest first chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler()); - try (Reader reader = DataLoader.loadReader("ChestReward.json")) { - List chestReward = Grasscutter.getGsonFactory().fromJson( - reader, - TypeToken.getParameterized(List.class, ChestReward.class).getType()); - - chestReward.forEach(reward -> - reward.getObjNames().forEach( - name -> chestInteractHandlerMap.putIfAbsent(name, new NormalChestInteractHandler(reward)))); - + try { + DataLoader.loadList("ChestReward.json", ChestReward.class) + .forEach(reward -> + reward.getObjNames().forEach(name -> + chestInteractHandlerMap.putIfAbsent(name, new NormalChestInteractHandler(reward)))); } catch (Exception e) { Grasscutter.getLogger().error("Unable to load chest reward config.", e); } diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java index ac915b2a4..009aa9404 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java @@ -12,6 +12,7 @@ import java.util.stream.Collectors; import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; +import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -59,7 +60,7 @@ public class PacketOpcodesUtils { .filter(e -> e.getIntKey() > 0) .collect(Collectors.toMap(Int2ObjectMap.Entry::getIntKey, Int2ObjectMap.Entry::getValue, (k, v) -> v, TreeMap::new)); // Write to file - writer.write(Grasscutter.getGsonFactory().toJson(packetIds)); + writer.write(Utils.jsonEncode(packetIds)); Grasscutter.getLogger().info("Dumped packet ids."); } catch (IOException e) { e.printStackTrace(); diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index d2df184d6..72edc9df1 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -82,7 +82,7 @@ public final class PluginManager { InputStreamReader fileReader = new InputStreamReader(configFile.openStream()); // Create a plugin config instance from the config file. - PluginConfig pluginConfig = Grasscutter.getGsonFactory().fromJson(fileReader, PluginConfig.class); + PluginConfig pluginConfig = Utils.loadJsonToClass(fileReader, PluginConfig.class); // Check if the plugin config is valid. if (!pluginConfig.validate()) { Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " has an invalid config file."); diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index 27ae4ee5d..6249739d2 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -130,7 +130,7 @@ public final class Language { languageCode = description.getLanguageCode(); try { - languageData = Grasscutter.getGsonFactory().fromJson(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class); + languageData = Utils.jsonDecode(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class); } catch (Exception exception) { Grasscutter.getLogger().warn("Failed to load language file: " + description.getLanguageCode(), exception); } diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index 45f6b563a..98d66e7b8 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -20,12 +20,25 @@ import it.unimi.dsi.fastutil.ints.IntList; import org.slf4j.Logger; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + import javax.annotation.Nullable; import static emu.grasscutter.utils.Language.translate; @SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) public final class Utils { + private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + @Deprecated(forRemoval = true) + public static Gson getGsonFactory() { + return gson; + } + public static final Random random = new Random(); public static int randomRange(int min, int max) { @@ -158,8 +171,7 @@ public final class Utils { * @param object The object to log. */ public static void logObject(Object object) { - String asJson = Grasscutter.getGsonFactory().toJson(object); - Grasscutter.getLogger().info(asJson); + Grasscutter.getLogger().info(jsonEncode(object)); } /** @@ -357,6 +369,44 @@ public final class Utils { return Base64.getDecoder().decode(toDecode); } + /* + * Encode an object to a JSON string + */ + public static String jsonEncode(Object object) { + return gson.toJson(object); + } + + public static T jsonDecode(JsonElement jsonElement, Class classType) throws JsonSyntaxException { + return gson.fromJson(jsonElement, classType); + } + + public static T loadJsonToClass(InputStreamReader fileReader, Class classType) throws IOException { + return gson.fromJson(fileReader, classType); + } + public static T loadJsonToClass(String filename, Class classType) throws IOException { + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadJsonToClass(fileReader, classType); + } + } + + public static List loadJsonToList(InputStreamReader fileReader, Class classType) throws IOException { + return gson.fromJson(fileReader, TypeToken.getParameterized(List.class, classType).getType()); + } + public static List loadJsonToList(String filename, Class classType) throws IOException { + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadJsonToList(fileReader, classType); + } + } + + public static Map loadJsonToMap(InputStreamReader fileReader, Class keyType, Class valueType) throws IOException { + return gson.fromJson(fileReader, TypeToken.getParameterized(Map.class, keyType, valueType).getType()); + } + public static Map loadJsonToMap(String filename, Class keyType, Class valueType) throws IOException { + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadJsonToMap(fileReader, keyType, valueType); + } + } + /** * Safely JSON decodes a given string. * @param jsonData The JSON-encoded data. @@ -364,7 +414,7 @@ public final class Utils { */ public static T jsonDecode(String jsonData, Class classType) { try { - return Grasscutter.getGsonFactory().fromJson(jsonData, classType); + return gson.fromJson(jsonData, classType); } catch (Exception ignored) { return null; }