package emu.grasscutter.data; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.config.*; import emu.grasscutter.data.binout.routes.*; import emu.grasscutter.data.custom.*; import emu.grasscutter.data.excels.*; import emu.grasscutter.data.excels.achievement.*; import emu.grasscutter.data.excels.activity.*; import emu.grasscutter.data.excels.avatar.*; import emu.grasscutter.data.excels.codex.*; import emu.grasscutter.data.excels.dungeon.*; import emu.grasscutter.data.excels.monster.*; import emu.grasscutter.data.excels.quest.*; import emu.grasscutter.data.excels.reliquary.*; import emu.grasscutter.data.excels.tower.*; import emu.grasscutter.data.excels.trial.*; import emu.grasscutter.data.excels.weapon.*; import emu.grasscutter.data.excels.world.*; import emu.grasscutter.data.server.*; import emu.grasscutter.game.dungeons.*; import emu.grasscutter.game.quest.*; import emu.grasscutter.game.quest.enums.QuestCond; import emu.grasscutter.game.world.*; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.*; import java.lang.reflect.Field; import java.util.*; import javax.annotation.Nullable; import lombok.Getter; import lombok.val; @SuppressWarnings({"unused", "MismatchedQueryAndUpdateOfCollection"}) public final class GameData { @Getter private static final Map abilityDataMap = new HashMap<>(); @Getter private static final Int2ObjectMap scenePointEntryMap = new Int2ObjectOpenHashMap<>(); // BinOutputs @Getter private static final Int2ObjectMap homeworldDefaultSaveData = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap abilityHashes = new Int2ObjectOpenHashMap<>(); @Deprecated(forRemoval = true) @Getter private static final Map abilityModifiers = new HashMap<>(); @Getter private static final Map avatarConfigData = new HashMap<>(); @Getter private static final Map gadgetConfigData = new HashMap<>(); @Getter private static final Map monsterConfigData = new HashMap<>(); @Getter private static final Map openConfigEntries = new HashMap<>(); private static final Int2ObjectMap mainQuestData = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap questsKeys = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap npcBornData = new Int2ObjectOpenHashMap<>(); private static final Map abilityEmbryos = new HashMap<>(); // ExcelConfigs @Getter private static final Int2ObjectMap activityCondExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dungeonPassConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dungeonChallengeConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap> sceneRouteData = new Int2ObjectOpenHashMap<>(); @Getter private static final ArrayList codexReliquaryArrayList = new ArrayList<>(); private static final Int2ObjectMap achievementDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap achievementGoalDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap activityDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap activityShopDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap activityWatcherDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarCostumeDataItemIdMap = new Int2ObjectLinkedOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarCostumeDataMap = new Int2ObjectLinkedOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarReplaceCostumeDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarFetterLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarFlycloakDataMap = new Int2ObjectLinkedOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarSkillDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap avatarTalentDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap battlePassMissionDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap battlePassRewardDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap blossomRefreshExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap buffDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap chapterDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap cityDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap codexAnimalDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap codexMaterialDataIdMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap codexQuestDataIdMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap codexReliquaryDataIdMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap codexWeaponDataIdMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap cookBonusDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap cookRecipeDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap compoundDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dropTableDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dropMaterialDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap dungeonEntryDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap envAnimalGatherConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap equipAffixDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap forgeDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap gadgetDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap gatherDataMap = new Int2ObjectOpenHashMap<>(); @Getter @Deprecated // This is to prevent people from using this map. This is for the resource loader // only! private static final Int2ObjectMap guideTriggerDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap homeWorldBgmDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap investigationMonsterDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap itemDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap monsterCurveDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap monsterDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap monsterDescribeDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap monsterSpecialNameDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap musicGameBasicDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap npcDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap openStateDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap personalLineDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap playerLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap proudSkillDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap questDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap questGlobalVarDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap reliquaryAffixDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap reliquaryMainPropDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap reliquarySetDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>(); @Getter private static final Int2ObjectMap talkConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap triggerExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap trialAvatarDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap trialAvatarActivityDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap trialAvatarActivityDataDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap trialAvatarTemplateDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap trialReliquaryDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap weaponCurveDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap weaponLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap weaponPromoteDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap weatherDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap worldAreaDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap rewindDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap teleportDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap refreshPolicyExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap avatarPromoteDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap reliquaryLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap shopGoodsDataMap = new Int2ObjectOpenHashMap<>(); // The following are accessed via getMapByResourceDef, and will show as unused private static final Int2ObjectMap codexMaterialDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap codexQuestDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap codexReliquaryDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap codexWeaponDataMap = new Int2ObjectOpenHashMap<>(); // Custom community server resources @Getter private static final Int2ObjectMap> dungeonDropDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap gadgetMappingMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap activityCondGroupMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap groupReplacements = new Int2ObjectOpenHashMap<>(); // Cache @Getter private static final IntList scenePointIdList = new IntArrayList(); @Getter private static final List openStateList = new ArrayList<>(); @Getter private static final Map> scenePointsPerScene = new HashMap<>(); @Getter private static final Map scriptSceneDataMap = new HashMap<>(); @Getter private static final Map guideTriggerDataStringMap = new HashMap<>(); @Getter private static final Map configLevelEntityDataMap = new HashMap<>(); @Getter private static final Int2ObjectMap proudSkillGroupLevels = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2IntMap proudSkillGroupMaxLevels = new Int2IntOpenHashMap(); @Getter private static final Int2ObjectMap avatarSkillLevels = new Int2ObjectOpenHashMap<>(); @Getter private static final Map> beginCondQuestMap = new HashMap<>(); // cache filled by QuestData @Getter private static final Map questTalkMap = new HashMap<>(); @Getter private static final Int2ObjectMap trialAvatarCustomData = new Int2ObjectOpenHashMap<>(); @Getter private static final Map trialAvatarActivityCustomData = new HashMap<>(); @Getter private static final Map trialAvatarActivityDataCustomData = new HashMap<>(); @Getter private static final Int2IntMap trialAvatarIndexIdTrialActivityDataDataMap = new Int2IntOpenHashMap(); private static Map> fetters = new HashMap<>(); private static Map> shopGoods = new HashMap<>(); // Getters with different names that stay for now public static Int2ObjectMap getMainQuestDataMap() { return mainQuestData; } public static Int2ObjectMap getMainQuestEncryptionMap() { return questsKeys; } public static Int2ObjectMap getSceneNpcBornData() { return npcBornData; } public static Map getAbilityEmbryoInfo() { return abilityEmbryos; } // Getters that get values rather than containers. If Lombok ever gets syntactic sugar for this, // we should adopt that. public static AbilityData getAbilityData(String abilityName) { return abilityDataMap.get(abilityName); } public static IntSet getAvatarSkillLevels(int avatarSkillId) { return avatarSkillLevels.get(avatarSkillId); } public static IntSet getProudSkillGroupLevels(int proudSkillGroupId) { return proudSkillGroupLevels.get(proudSkillGroupId); } public static int getProudSkillGroupMaxLevel(int proudSkillGroupId) { return proudSkillGroupMaxLevels.getOrDefault(proudSkillGroupId, 0); } // Multi-keyed getters public static AvatarPromoteData getAvatarPromoteData(int promoteId, int promoteLevel) { return avatarPromoteDataMap.get((promoteId << 8) + promoteLevel); } public static WeaponPromoteData getWeaponPromoteData(int promoteId, int promoteLevel) { return weaponPromoteDataMap.get((promoteId << 8) + promoteLevel); } public static ReliquaryLevelData getRelicLevelData(int rankLevel, int level) { return reliquaryLevelDataMap.get((rankLevel << 8) + level); } public static ScenePointEntry getScenePointEntryById(int sceneId, int pointId) { return scenePointEntryMap.get((sceneId << 16) + pointId); } // Non-nullable value getters public static int getAvatarLevelExpRequired(int level) { return Optional.ofNullable(avatarLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); } public static int getAvatarFetterLevelExpRequired(int level) { return Optional.ofNullable(avatarFetterLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); } public static int getRelicExpRequired(int rankLevel, int level) { return Optional.ofNullable(getRelicLevelData(rankLevel, level)).map(d -> d.getExp()).orElse(0); } // Generic getter public static Int2ObjectMap getMapByResourceDef(Class resourceDefinition) { Int2ObjectMap map = null; try { Field field = GameData.class.getDeclaredField( Utils.lowerCaseFirstChar(resourceDefinition.getSimpleName()) + "Map"); field.setAccessible(true); map = (Int2ObjectMap) field.get(null); field.setAccessible(false); } catch (Exception e) { Grasscutter.getLogger() .error("Error fetching resource map for " + resourceDefinition.getSimpleName(), e); } return map; } public static int getWeaponExpRequired(int rankLevel, int level) { WeaponLevelData levelData = weaponLevelDataMap.get(level); if (levelData == null) { return 0; } try { return levelData.getRequiredExps()[rankLevel - 1]; } catch (Exception e) { return 0; } } public static Map> getFetterDataEntries() { if (fetters.isEmpty()) { fetterDataMap.forEach( (k, v) -> { if (!fetters.containsKey(v.getAvatarId())) { fetters.put(v.getAvatarId(), new ArrayList<>()); } fetters.get(v.getAvatarId()).add(k); }); } return fetters; } public static Map> getShopGoodsDataEntries() { if (shopGoods.isEmpty()) { shopGoodsDataMap.forEach( (k, v) -> { if (!shopGoods.containsKey(v.getShopType())) shopGoods.put(v.getShopType(), new ArrayList<>()); shopGoods.get(v.getShopType()).add(v); }); } return shopGoods; } /** * Fetches the route data for a scene by ID. * * @param sceneId The ID of the scene to fetch the route data for. * @return The route data for the scene, or an empty map if the scene has no route data. */ public static Int2ObjectMap getSceneRoutes(int sceneId) { return sceneRouteData.computeIfAbsent(sceneId, k -> new Int2ObjectOpenHashMap<>()); } /** * Fetches the trial data * * @param trialAvatarIndexId * @return */ @Nullable public static TrialAvatarActivityDataData getTrialAvatarActivityDataByAvatarIndex( int trialAvatarIndexId) { // prefer custom data over official data val dataId = trialAvatarIndexIdTrialActivityDataDataMap.get(trialAvatarIndexId); val datamap = GameData.getTrialAvatarActivityDataCustomData().isEmpty() ? GameData.getTrialAvatarActivityDataDataMap() : GameData.getTrialAvatarActivityDataCustomData(); return datamap.get(dataId); } @Nullable public static List getQuestDataByConditions( QuestCond questCond, int param0, String questStr) { return beginCondQuestMap.get(QuestData.questConditionKey(questCond, param0, questStr)); } public static Int2ObjectMap getAchievementDataMap() { AchievementData.divideIntoGroups(); return achievementDataMap; } }