diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index ca1fc44d0..c05a7d2c3 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -105,8 +105,8 @@ public final class Grasscutter { // Load all resources. Grasscutter.updateDayOfWeek(); - ResourceLoader.loadAll(); ScriptLoader.init(); + ResourceLoader.loadAll(); // Generate handbooks. Tools.createGmHandbooks(false); diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 1b01a08dc..23dd7589c 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -8,17 +8,17 @@ import com.google.gson.annotations.SerializedName; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; -import emu.grasscutter.data.binout.config.ConfigEntityAvatar; -import emu.grasscutter.data.binout.config.ConfigEntityBase; -import emu.grasscutter.data.binout.config.ConfigEntityGadget; -import emu.grasscutter.data.binout.config.ConfigEntityMonster; +import emu.grasscutter.data.binout.config.*; import emu.grasscutter.data.common.PointData; import emu.grasscutter.game.managers.blossom.BlossomConfig; import emu.grasscutter.game.quest.QuestEncryptionKey; +import emu.grasscutter.game.quest.RewindData; +import emu.grasscutter.game.quest.TeleportData; import emu.grasscutter.game.world.SpawnDataEntry; import emu.grasscutter.game.world.SpawnDataEntry.GridBlockId; import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.scripts.ScriptLoader; import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.JsonUtils; import emu.grasscutter.utils.TsvUtils; @@ -31,9 +31,11 @@ import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArraySet; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.val; import org.reflections.Reflections; @@ -109,6 +111,9 @@ public class ResourceLoader { loadNpcBornData(); loadBlossomResources(); cacheTalentLevelSets(); + // Load special ability in certain scene/dungeon + loadConfigLevelEntityData(); + loadQuestShareConfig(); Grasscutter.getLogger().info(translate("messages.status.resources.finish")); loadedAll = true; @@ -639,6 +644,75 @@ public class ResourceLoader { } } + private static void loadConfigLevelEntityData() { + // Load from BinOutput + val pattern = Pattern.compile("ConfigLevelEntity_(.+?)\\.json"); + + try { + var stream = Files.newDirectoryStream(getResourcePath("BinOutput/LevelEntity/"), "ConfigLevelEntity_*.json"); + stream.forEach(path -> { + val matcher = pattern.matcher(path.getFileName().toString()); + if (!matcher.find()) return; + Map config; + + try { + config = JsonUtils.loadToMap(path, String.class, ConfigLevelEntity.class); + } catch (Exception e) { + Grasscutter.getLogger().error("Error loading player ability embryos:", e); + return; + } + GameData.getConfigLevelEntityDataMap().putAll(config); + }); + stream.close(); + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading config level entity: no files found"); + return; + } + + if (GameData.getConfigLevelEntityDataMap() == null || GameData.getConfigLevelEntityDataMap().isEmpty()) { + Grasscutter.getLogger().error("No config level entity loaded!"); + return; + } + } + + private static void loadQuestShareConfig() { + // Load from BinOutput + val pattern = Pattern.compile("Q(.+?)\\ShareConfig.lua"); + + try { + var bindings = ScriptLoader.getEngine().createBindings(); + var stream = Files.newDirectoryStream(getResourcePath("Scripts/Quest/Share/"), "Q*ShareConfig.lua"); + stream.forEach(path -> { + val matcher = pattern.matcher(path.getFileName().toString()); + if (!matcher.find()) return; + + var cs = ScriptLoader.getScript("Quest/Share/" + path.getFileName().toString()); + if (cs == null) return; + + try{ + cs.eval(bindings); + // these are Map + var teleportDataMap = ScriptLoader.getSerializer().toMap(TeleportData.class, bindings.get("quest_data")); + var rewindDataMap = ScriptLoader.getSerializer().toMap(RewindData.class, bindings.get("rewind_data")); + // convert them to Map and cache + GameData.getTeleportDataMap().putAll(teleportDataMap.entrySet().stream().collect(Collectors.toMap(entry -> Integer.valueOf(entry.getKey()), Entry::getValue))); + GameData.getRewindDataMap().putAll(rewindDataMap.entrySet().stream().collect(Collectors.toMap(entry -> Integer.valueOf(entry.getKey()), Entry::getValue))); + } catch (Throwable e){ + Grasscutter.getLogger().error("Error while loading Quest Share Config: {}", path.getFileName().toString()); + } + }); + stream.close(); + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading Quest Share Config: no files found"); + return; + } + if (GameData.getTeleportDataMap() == null || GameData.getTeleportDataMap().isEmpty() + || GameData.getRewindDataMap() == null || GameData.getRewindDataMap().isEmpty()) { + Grasscutter.getLogger().error("No Quest Share Config loaded!"); + return; + } + } + // private static HashSet modifierActionTypes = new HashSet<>(); public static class AbilityConfigData { public AbilityData Default; diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 9c888a51b..2439587f1 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -918,7 +918,7 @@ public class Player { List specifiedAvatarList = getTeamManager().getActiveTeam(); if (avatarIds != null && avatarIds.size() > 0){ - // certain scene could limit specifc avatars' entry + // certain scene could limit a specific avatar's entry specifiedAvatarList.clear(); for (int id : avatarIds){ var avatar = getAvatars().getAvatarById(id);