Merge branch 'development' into unstable

# Conflicts:
#	build.gradle
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityActionGenerateElemBallOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityAppliedAbilityOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityAppliedModifierOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityAttachedModifierOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityControlBlockOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityEmbryoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityIdentifierOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityInvocationsNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityInvokeArgumentOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityInvokeEntryHeadOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityInvokeEntryOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityMetaModifierChangeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityMetaReInitOverrideMapOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityMixinRecoverInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityScalarTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityScalarValueEntryOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilityStringOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AbilitySyncStateInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AchievementAllDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AchievementOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AchievementUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityPushTipsDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityPushTipsStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityScheduleInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityScheduleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityShopSheetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityTakeWatcherRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityTakeWatcherRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityUpdateWatcherNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ActivityWatcherInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddBackupAvatarTeamReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddBackupAvatarTeamRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddNoGachaAvatarCardNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddNoGachaAvatarCardTransferItemOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddQuestContentProgressReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AddQuestContentProgressRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AdjustTrackingInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AiSkillCdInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AiSyncInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AiThreatInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AllWidgetDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AnchorPointDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AnimatorParameterValueInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AnimatorParameterValueInfoPairOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AnnounceDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AskAddFriendNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AskAddFriendReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AskAddFriendRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AttackHitEffectResultOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AttackResultOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarAddNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarChangeCostumeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarChangeCostumeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarChangeCostumeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarChangeElementTypeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarChangeElementTypeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarDieAnimationEndReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarDieAnimationEndRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarEnterSceneInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarEquipAffixInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarEquipAffixStartNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarEquipChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExcelInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionAllDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionAllDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionCallBackReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionCallBackRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionGetRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionGetRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionStartReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionStartRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarExpeditionStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFetterDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFetterInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFightPropNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFightPropUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFlycloakChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarFollowRouteNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarGainCostumeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarGainFlycloakNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarLifeStateChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarPromoteReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarPromoteRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarPropChangeReasonNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarPropNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarRenameInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarRenameInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSatiationDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSatiationDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillDepotChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillMaxChargeCountNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillUpgradeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarSkillUpgradeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarTeamAllDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarTeamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarTeamResonanceInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarTeamUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarUnlockTalentNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarUpgradeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarUpgradeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarWearFlycloakReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/AvatarWearFlycloakRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BackMyWorldRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BatchBuyGoodsReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BatchBuyGoodsRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassAllDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassCurScheduleUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassCycleOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassMissionDelNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassMissionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassMissionUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassProductOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassRewardTagOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassRewardTakeOptionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassScheduleOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BattlePassUnlockStatusOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BirthdayOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BlockInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BlossomBriefInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BlossomBriefInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BlossomChestInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BonusActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BonusActivityInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BonusActivityInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BonusOpActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BossChestInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutActionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutBrickInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutElementReactionCounterOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutPhysicalObjectModifierOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutPhysicalObjectOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutSnapShotOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutSpawnPointOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutSyncConnectUidInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BreakoutVector2OuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BuyBattlePassLevelReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BuyBattlePassLevelRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BuyGoodsParamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BuyGoodsReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/BuyGoodsRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CalcWeaponUpgradeReturnItemsReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CalcWeaponUpgradeReturnItemsRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CanUseSkillNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CancelFinishParentQuestNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CardProductRewardNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChallengeBriefOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChallengeDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChallengeFinishTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeAvatarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeAvatarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeEnergyReasonOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeGameTimeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeGameTimeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeHpReasonOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeMailStarNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeMpTeamAvatarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeMpTeamAvatarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeTeamNameReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChangeTeamNameRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChannellerSlabLoopDungeonResultInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChapterStateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChapterStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CharAmusementAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChatEmojiCollectionDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChatInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CheckAddItemExceedLimitNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChildQuestOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChooseCurAvatarTeamReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ChooseCurAvatarTeamRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CityReputationQuestInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientAIStateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientAbilityChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientAbilityInitFinishNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientCollectorDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientInputTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientLoadingCostumeVerificationNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClientLockGameTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ClosedItemNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CodexDataFullNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CodexDataUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CodexTypeDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CodexTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CoinCollectOperatorInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CoinCollectTeamAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombatInvocationsNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombatInvokeEntryOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombatTypeArgumentOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombineDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombineFormulaDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombineReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CombineRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CompoundBoostTakeStatusTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CompoundDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CompoundQueueDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CookDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CookRecipeDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CookRecipeDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CreateEntityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CreateGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CreateVehicleReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CreateVehicleRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CrystalLinkAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CrystalLinkDungeonAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CurVehicleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CustomCommonNodeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CustomDungeonFinishTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CustomDungeonResultInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CustomGadgetTreeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CutSceneBeginNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/CutSceneExtraParamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyDungeonEntryInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskFilterCityReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskFilterCityRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskProgressNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DailyTaskUnlockedCitiesNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DealAddFriendReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DealAddFriendResultTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DealAddFriendRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DelBackupAvatarTeamReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DelBackupAvatarTeamRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DelMailReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DelMailRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DelTeamEntityNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DeleteFriendNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DeleteFriendReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DeleteFriendRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DeshretObeliskGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DestroyMaterialReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DestroyMaterialRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DoGachaReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DoGachaRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DoSetPlayerBornDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DropHintNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DropItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DropItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonCandidateTeamChangeAvatarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonCandidateTeamChangeAvatarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonChallengeBeginNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonChallengeFinishNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonEnterPosInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonEntryInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonEntryInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonEntryInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonEntryPointInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonSettleNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonShowReminderNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonSlipRevivePointActivateReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonSlipRevivePointActivateRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonWayPointActivateReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonWayPointActivateRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/DungeonWayPointNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EchoShellInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EffigyChallengeDungeonResultInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EndCameraSceneLookNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterSceneDoneReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterSceneDoneRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterScenePeerNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterSceneReadyReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterSceneReadyRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterTransPointRegionNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterWorldAreaReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EnterWorldAreaRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityAbilityInvokeEntryOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityAiSyncNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityAuthorityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityClientDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityClientExtraInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityEnvironmentInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityFightPropChangeReasonNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityFightPropUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityMoveInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EntityRendererChangedInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EquipOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EquipParamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EquipRoguelikeRuneReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EquipRoguelikeRuneRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAiSyncCombatThreatInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAiSyncSkillCdNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAnimatorParameterInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAvatarLockChairReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAvatarLockChairRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAvatarSitDownNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtAvatarStandUpNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtBeingHitInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtCreateGadgetNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtDestroyGadgetNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtDoSkillSuccNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/EvtEntityRenderersChangedNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ExitTransPointRegionNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FeatureBlockInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FetterDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FightPropPairOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FindHilichurlAcceptQuestNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FindHilichurlFinishSecondQuestNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FinishedParentQuestNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FinishedParentQuestUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FishPoolInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FishtankFishInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FleurFairMusicGameSettleReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FleurFairMusicGameSettleRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FleurFairMusicGameStartReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FleurFairMusicGameStartRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForceUpdateInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeFormulaDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeGetQueueDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeGetQueueDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeQueueDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeQueueDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeQueueManipulateReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeQueueManipulateRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeQueueManipulateTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeStartReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForgeStartRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ForwardTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FoundationInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FoundationStatusOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FriendBriefOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FriendEnterHomeOptionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FriendOnlineStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureCurModuleArrangeCountNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeBeHelpedDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeBeHelpedNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeCancelReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeCancelRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeFinishNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeHelpDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeHelpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeHelpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeMakeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeSlotOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeStartReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureMakeStartRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/FurnitureOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GCGTCTavernChallengeDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaItemOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaTransferItemOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaUpInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaWishReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GachaWishRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetAutoPickDropInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetBornTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetCrucibleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetGeneralRewardInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetInteractReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetInteractRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetPlayInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GadgetStateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GalleryStopReasonOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GameplayRecommendationElementReliquaryRequestOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GameplayRecommendationElementReliquaryResponseOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GameplayRecommendationReliquaryMainPropDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GameplayRecommendationReliquaryRequestOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GameplayRecommendationReliquaryResponseOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GatherGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetActivityInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetActivityInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetActivityShopSheetInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetActivityShopSheetInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllH5ActivityInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllH5ActivityInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllMailNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllMailReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllMailResultNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllMailRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllUnlockNameCardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAllUnlockNameCardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAuthkeyReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetAuthkeyRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetBlossomBriefInfoListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetBlossomBriefInfoListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetChatEmojiCollectionReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetChatEmojiCollectionRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetCompoundDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetCompoundDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetDailyDungeonEntryInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetDailyDungeonEntryInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetFriendShowAvatarInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetFriendShowAvatarInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetFriendShowNameCardInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetFriendShowNameCardInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetFurnitureCurModuleArrangeCountReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetGachaInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetGachaInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetHomeLevelUpRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetHomeLevelUpRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetInvestigationMonsterReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetInvestigationMonsterRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetMailItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetMailItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetMapAreaRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOnlinePlayerInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOnlinePlayerInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOnlinePlayerListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOnlinePlayerListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOpActivityInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetOpActivityInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetParentQuestVideoKeyReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetParentQuestVideoKeyRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerAskFriendListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerAskFriendListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerBlacklistRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerFriendListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerFriendListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerHomeCompInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerSocialDetailReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerSocialDetailRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerTokenReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetPlayerTokenRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetQuestLackingResourceReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetQuestLackingResourceRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetQuestTalkHistoryReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetQuestTalkHistoryRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetRegionSearchReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetSceneAreaReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetSceneAreaRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetScenePointReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetScenePointRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetShopReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetShopRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetShopmallDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetShopmallDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetUgcReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetUgcRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetUgcTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetWidgetSlotReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetWidgetSlotRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetWorldMpInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GetWorldMpInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GroupSuiteNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/GroupUnloadNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/H5ActivityIdsNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/H5ActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HitColliderTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HitCollisionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HitTreeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeAllUnlockedBgmIdListNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeAnimalDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBasicInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBasicInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBlockArrangementInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBlockDotPatternOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBlockFieldDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeBlockSubFieldDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeBgmNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeBgmReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeBgmRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeEditModeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeEditModeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeModuleReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChangeModuleRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChooseModuleReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeChooseModuleRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeComfortInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeCustomFurnitureInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeCustomFurnitureInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeEditCustomFurnitureReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeEditCustomFurnitureRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeEnterEditModeFinishReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeEnterEditModeFinishRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeFurnitureCustomSuiteDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeFurnitureDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeFurnitureGroupDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeFurnitureSuiteDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGetArrangementInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGetArrangementInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGetBasicInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGetOnlineStatusReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGetOnlineStatusRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeGroupPlayerInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopBuyGoodsReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopBuyGoodsRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopGoodsListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopGoodsListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopGoodsOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopInfoChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeLimitedShopOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeMarkPointFurnitureDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeMarkPointNPCDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeMarkPointNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeMarkPointSceneDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeMarkPointSuiteDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeModuleComfortInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeModuleSeenReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeModuleSeenRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeModuleUnlockNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeNewUnlockedBgmIdListNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeNpcDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomePreChangeEditModeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceTakeFetterExpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceTakeFetterExpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceTakeHomeCoinReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeResourceTakeHomeCoinRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSceneArrangementInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSceneInitFinishReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSceneInitFinishRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSceneJumpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSceneJumpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSeekFurnitureAllRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSeekFurnitureGalleryScoreNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSeekFurnitureOneRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeSeekFurniturePlayerScoreOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeUpdateArrangementInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HomeUpdateArrangementInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/HostPlayerNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InferencePageInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InfernceWordInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InstableSprayAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InterOpTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InteractTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InvestigationMonsterOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InvestigationMonsterUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InvestigationQuestDailyNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/InvestigationReadQuestDailyNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/IrodoriChessEquipCardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/IrodoriChessEquipCardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemAddHintNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemCdGroupTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemGivingReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemGivingRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemHintOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemParamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemRenameAvatarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ItemRenameAvatarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LanternProjectionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LanternProjectionLevelInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LanternRiteFireworksChallengeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LanternRiteFireworksInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LanternRiteFireworksStageInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LevelupCityReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LifeStateChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LockedPersonallineDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LunaRiteHintStatusTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/LunchBoxDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MPLevelEntityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MailChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MailCollectStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MailDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MailItemOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MailTextContentOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MapAreaInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MapMarkFromTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MapMarkPointOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MapMarkPointTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MarkMapReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MarkMapRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MarkNewNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MarkTargetInvestigationMonsterNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MassivePropParamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MassivePropSyncInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialDeleteInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialDeleteReturnNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialDeleteReturnTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialDeleteUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MaterialOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MathQuaternionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/McoinExchangeHcoinReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/McoinExchangeHcoinRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MiracleRingDeliverItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MiracleRingDeliverItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MistTrialBestAvatarOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MistTrialLevelDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ModifierActionOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ModifierDurabilityOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ModifierPropertyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MonsterAIConfigHashNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MonsterBornTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MonsterPointArrayRouteUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MonsterRouteOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MotionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MotionStateOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MovingPlatformTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MpPlayRewardInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MpSettingTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MuqadasPotionDungeonSettleNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameActivityDetailInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameSettleReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameSettleRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameStartReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/MusicGameStartRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/NightCrowGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/NpcTalkReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/NpcTalkRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ObstacleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ObstacleModifyNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OfferingInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OneoffGatherPointDetectorDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OnlinePlayerInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OpActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OpenStateChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/OpenStateUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PSPlayerApplyEnterMpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PSPlayerApplyEnterMpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ParamListOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ParentQuestInferenceDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ParentQuestOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ParentQuestRandomInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PathfindingEnterSceneReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PathfindingEnterSceneRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PersonalLineAllDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PersonalLineAllDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PersonalSceneJumpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PersonalSceneJumpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PingReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PingRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlatformChangeRouteNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlatformInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlatformStartRouteNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlatformStopRouteNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlatformTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayTeamEntityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpResultNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpResultReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpResultRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerApplyEnterMpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerChatNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerChatReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerChatRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCompoundMaterialBoostReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCompoundMaterialBoostRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCompoundMaterialReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCompoundMaterialRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCookArgsReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCookArgsRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCookReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerCookRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerDieTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerEnterDungeonReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerEnterDungeonRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerEnterSceneInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerEnterSceneNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerForceExitRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerGameTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerGetForceQuitBanInfoReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerGetForceQuitBanInfoRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerHomeCompInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerHomeCompInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerLevelRewardUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerLocationInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerLoginReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerLoginRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerPropChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerPropChangeReasonNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerPropNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerQuitDungeonReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerRTTInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerSetPauseReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerSetPauseRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerStoreNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerWidgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerWorldLocationInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerWorldSceneInfoListNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PlayerWorldSceneInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PostEnterSceneReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PostEnterSceneRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PotionAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PotionDungeonResultInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PrivateChatNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PrivateChatReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ProfilePictureChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ProfilePictureOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PropChangeReasonOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PropPairOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PropValueOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ProtEntityTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ProudSkillChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ProudSkillExtraLevelNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PullPrivateChatReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PullPrivateChatRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PullRecentChatReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/PullRecentChatRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryCodexMonsterBeKilledNumReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryCodexMonsterBeKilledNumRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryCurrRegionHttpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryFilterOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryPathReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryPathRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QueryRegionListHttpRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestCreateEntityReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestCreateEntityRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestDelNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestDestroyEntityReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestDestroyEntityRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestDestroyNpcReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestDestroyNpcRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestGlobalVarNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestGlobalVarOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestListNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestListUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestProgressUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestRenameAvatarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestRenameAvatarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestTransmitReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestTransmitRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestUpdateQuestTimeVarNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestUpdateQuestVarNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestUpdateQuestVarReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestUpdateQuestVarRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuestVarOpOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/QuickUseWidgetRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReadMailNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReadPrivateChatReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RecordUsageOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RegionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RegionSimpleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryDecomposeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryDecomposeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryFilterStateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryFilterStateSaveNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryPromoteReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryPromoteRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryUpgradeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ReliquaryUpgradeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ResVersionConfigOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ResinChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ResinCostTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RobotPushPlayerDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RogueAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RogueDiaryDungeonSettleNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RogueShowAvatarTeamInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RoguelikeGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RouteOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RoutePointChangeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/RoutePointOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalesmanDeliverItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalesmanDeliverItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalesmanStatusTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalvageBundleChallengeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalvageChallengeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalvageScoreChallengeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SalvageStageInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneAreaUnlockNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneAreaWeatherNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneAvatarStaminaStepReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityAiInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityAppearNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityDisappearNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityDrownReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityDrownRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneEntityMoveNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneFishInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneForceLockNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneForceUnlockNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneGalleryHomeSeekFurnitureInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneInitFinishRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneKickPlayerReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneKickPlayerRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneMonsterInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneNpcInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ScenePlayerInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ScenePlayerInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ScenePlayerLocationNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneReliquaryInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneRouteChangeInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneRouteChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneTeamAvatarOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneTeamUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneTransToPointReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneTransToPointRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SceneWeaponInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ScreenInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SeaLampActivityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SeaLampContributeItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SeaLampContributeItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SeaLampSectionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SeeMonsterReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SelectWorktopOptionReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SelectWorktopOptionRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServantInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerAnnounceNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerAnnounceRevokeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerBuffChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerBuffOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerCondMeetQuestListUpdateNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerGlobalValueChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ServerTimeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetBattlePassViewedReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetBattlePassViewedRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetChatEmojiCollectionReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetChatEmojiCollectionRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetEntityClientDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetEquipLockStateReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetEquipLockStateRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetFriendEnterHomeOptionReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetFriendEnterHomeOptionRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetIsAutoUnlockSpecificEquipReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetIsAutoUnlockSpecificEquipRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetNameCardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetNameCardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetOpenStateReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetOpenStateRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerBirthdayReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerBirthdayRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerBornDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerBornDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerHeadImageReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerHeadImageRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerNameReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerNameRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerPropReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerPropRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerSignatureReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetPlayerSignatureRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetUpAvatarTeamReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetUpAvatarTeamRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetUpLunchBoxWidgetReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetUpLunchBoxWidgetRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetWidgetSlotReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SetWidgetSlotRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShopCardProductOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShopConcertProductOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShopGoodsOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShopMcoinProductOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShopOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShortAbilityHashPairOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShowAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ShowEquipOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SkipPlayerGameTimeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SkipPlayerGameTimeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SkyCrystalDetectorDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SkyCrystalDetectorQuickUseResultOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SocialDetailOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SocialShowAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StatueGadgetInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StopServerInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StoreItemChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StoreItemDelNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StoreTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StoreWeightLimitNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/StrengthenPointDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SumoAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SumoDungeonSettleNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SyncScenePlayTeamEntityNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/SyncTeamEntityNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeAchievementGoalRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeAchievementGoalRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeAchievementRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeAchievementRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBackGivingItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBackGivingItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBattlePassMissionPointReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBattlePassMissionPointRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBattlePassRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeBattlePassRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeCityReputationParentQuestReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeCityReputationParentQuestRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeCompoundOutputReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeCompoundOutputRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeFurnitureMakeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeFurnitureMakeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeMaterialDeleteReturnReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeMaterialDeleteReturnRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakePlayerLevelRewardReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakePlayerLevelRewardRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeoffEquipReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TakeoffEquipRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TanukiTravelFinishGuideQuestNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TanukiTravelLevelDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TeamChainChooseAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TeamEnterSceneInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TeamEntityInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ToTheMoonEnterSceneReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ToTheMoonQueryPathReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/ToTheMoonQueryPathRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerAllDataReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerAllDataRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerCurLevelRecordChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerCurLevelRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerEnterLevelReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerEnterLevelRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerFloorRecordChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerFloorRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerLevelEndNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerLevelRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerLevelStarCondDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerLevelStarCondNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerMiddleLevelChangeTeamNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerMonthlyBriefOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerTeamOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerTeamSelectReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TowerTeamSelectRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TrackingIOInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TreasureMapRegionInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TreasureMapRegionInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TrialAvatarFirstPassDungeonNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TrialAvatarGrantRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TrialAvatarInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TriggerCreateGadgetToEquipPartNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TryEnterHomeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/TryEnterHomeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UgcMusicBriefInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UgcMusicNoteOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UgcMusicRecordOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UgcMusicTrackOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UgcTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/Uint32PairOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnionCmdNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnionCmdOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockAvatarTalentReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockAvatarTalentRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockNameCardNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockPersonalLineReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockPersonalLineRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockTransPointReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockTransPointRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockedFurnitureFormulaDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UnlockedFurnitureSuiteDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UpdateAbilityCreatedMovingPlatformNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UpdatePlayerShowAvatarListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UpdatePlayerShowAvatarListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UpdatePlayerShowNameCardListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UpdatePlayerShowNameCardListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UseItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/UseItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/Vector3IntOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VectorOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VectorPlaneOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleInteractReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleInteractRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleInteractTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleLocationInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleMemberOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VehicleStaminaNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VintageBoothUsedItemDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VintageMarketDeliverItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VintageMarketDeliverItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/VisionTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponAwakenReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponAwakenRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponPromoteReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponPromoteRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponUpgradeReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeaponUpgradeRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WearEquipReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WearEquipRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeatherInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeatherWizardDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeekendDjinnInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WeeklyBossResinDiscountInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetCoolDownDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetCoolDownNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetCreateLocationInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetCreatorInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetCreatorOpTypeOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetDoBagReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetDoBagRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetGadgetAllDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetGadgetDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetGadgetDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetSlotChangeNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetSlotDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetSlotOpOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WidgetSlotTagOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WindSeedClientNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampAcceptAllGiveItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampAcceptAllGiveItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampAcceptGiveItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampAcceptGiveItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampAcceptItemResultInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGetCanGiveFriendItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGetCanGiveFriendItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGetRecvItemListReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGetRecvItemListRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGiveFriendItemReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampGiveFriendItemRspOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampRecvItemDataOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WinterCampRecvItemNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorktopInfoOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorktopOptionNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldChestOpenNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldDataNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldOwnerBlossomBriefInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldOwnerDailyTaskNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerDieNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerInfoNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerLocationNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerRTTNotifyOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerReviveReqOuterClass.java
#	src/generated/main/java/emu/grasscutter/net/proto/WorldPlayerReviveRspOuterClass.java
#	src/main/java/emu/grasscutter/GameConstants.java
#	src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
#	src/main/java/emu/grasscutter/utils/Language.java
This commit is contained in:
KingRainbow44
2023-04-30 23:08:05 -04:00
1322 changed files with 1181402 additions and 956194 deletions

View File

@@ -1,513 +1,465 @@
package emu.grasscutter.utils;
import static emu.grasscutter.config.Configuration.FALLBACK_LANGUAGE;
import static emu.grasscutter.utils.FileUtils.getResourcePath;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.data.excels.AchievementData;
import emu.grasscutter.game.player.Player;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.EqualsAndHashCode;
public final class Language {
private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>();
private static final int TEXTMAP_CACHE_VERSION = 0x9CCACE04;
private static final Pattern textMapKeyValueRegex = Pattern.compile("\"(\\d+)\": \"(.+)\"");
private static final Path TEXTMAP_CACHE_PATH =
Path.of(Utils.toFilePath("cache/TextMapCache.bin"));
private static boolean scannedTextmaps =
false; // Ensure that we don't infinitely rescan on cache misses that don't exist
private static Int2ObjectMap<TextStrings> textMapStrings;
private final String languageCode;
private final Map<String, String> translations = new ConcurrentHashMap<>();
/** Reads a file and creates a language instance. */
private Language(LanguageStreamDescription description) {
languageCode = description.getLanguageCode();
try {
var object =
JsonUtils.decode(
Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class);
object
.entrySet()
.forEach(entry -> putFlattenedKey(translations, entry.getKey(), entry.getValue()));
} catch (Exception exception) {
Grasscutter.getLogger()
.warn("Failed to load language file: " + description.getLanguageCode(), exception);
}
}
/**
* Creates a language instance from a code.
*
* @param langCode The language code.
* @return A language instance.
*/
public static Language getLanguage(String langCode) {
if (cachedLanguages.containsKey(langCode)) {
return cachedLanguages.get(langCode);
}
var fallbackLanguageCode = Utils.getLanguageCode(FALLBACK_LANGUAGE);
var description = getLanguageFileDescription(langCode, fallbackLanguageCode);
var actualLanguageCode = description.getLanguageCode();
Language languageInst;
if (description.getLanguageFile() != null) {
languageInst = new Language(description);
cachedLanguages.put(actualLanguageCode, languageInst);
} else {
languageInst = cachedLanguages.get(actualLanguageCode);
cachedLanguages.put(langCode, languageInst);
}
return languageInst;
}
/**
* Returns the translated value from the key while substituting arguments.
*
* @param key The key of the translated value to return.
* @param args The arguments to substitute.
* @return A translated value with arguments substituted.
*/
public static String translate(String key, Object... args) {
String translated = Grasscutter.getLanguage().get(key);
for (int i = 0; i < args.length; i++) {
args[i] =
switch (args[i].getClass().getSimpleName()) {
case "String" -> args[i];
case "TextStrings" -> ((TextStrings) args[i])
.get(0)
.replace("\\\\n", "\\n"); // TODO: Change this to server language
default -> args[i].toString();
};
}
try {
return translated.formatted(args);
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to format string: " + key, exception);
return translated;
}
}
/**
* Returns the translated value from the key while substituting arguments.
*
* @param player Target player
* @param key The key of the translated value to return.
* @param args The arguments to substitute.
* @return A translated value with arguments substituted.
*/
public static String translate(Player player, String key, Object... args) {
if (player == null) {
return translate(key, args);
}
var langCode = Utils.getLanguageCode(player.getAccount().getLocale());
String translated = getLanguage(langCode).get(key);
for (int i = 0; i < args.length; i++) {
args[i] =
switch (args[i].getClass().getSimpleName()) {
case "String" -> args[i];
case "TextStrings" -> ((TextStrings) args[i])
.getGC(langCode)
.replace("\\\\n", "\n"); // Note that we don't unescape \n for server console
default -> args[i].toString();
};
}
try {
return translated.formatted(args);
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to format string: " + key, exception);
return translated;
}
}
/**
* Recursive helper function to flatten a Json tree Converts input like {"foo": {"bar": "baz"}} to
* {"foo.bar": "baz"}
*
* @param map The map to insert the keys into
* @param key The flattened key of the current element
* @param element The current element
*/
private static void putFlattenedKey(Map<String, String> map, String key, JsonElement element) {
if (element.isJsonObject()) {
element
.getAsJsonObject()
.entrySet()
.forEach(
entry -> {
String keyPrefix = key.isEmpty() ? "" : key + ".";
putFlattenedKey(map, keyPrefix + entry.getKey(), entry.getValue());
});
} else {
map.put(key, element.getAsString());
}
}
/**
* create a LanguageStreamDescription
*
* @param languageCode The name of the language code.
* @param fallbackLanguageCode The name of the fallback language code.
*/
private static LanguageStreamDescription getLanguageFileDescription(
String languageCode, String fallbackLanguageCode) {
var fileName = languageCode + ".json";
var fallback = fallbackLanguageCode + ".json";
String actualLanguageCode = languageCode;
InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName);
if (file == null) { // Provided fallback language.
Grasscutter.getLogger()
.warn("Failed to load language file: " + fileName + ", falling back to: " + fallback);
actualLanguageCode = fallbackLanguageCode;
if (cachedLanguages.containsKey(actualLanguageCode)) {
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/" + fallback);
}
if (file == null) { // Fallback the fallback language.
Grasscutter.getLogger()
.warn("Failed to load language file: " + fallback + ", falling back to: en-US.json");
actualLanguageCode = "en-US";
if (cachedLanguages.containsKey(actualLanguageCode)) {
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/en-US.json");
}
if (file == null)
throw new RuntimeException(
"Unable to load the primary, fallback, and 'en-US' language files.");
return new LanguageStreamDescription(actualLanguageCode, file);
}
private static Int2ObjectMap<String> loadTextMapFile(String language, IntSet nameHashes) {
Int2ObjectMap<String> output = new Int2ObjectOpenHashMap<>();
try (BufferedReader file =
Files.newBufferedReader(
getResourcePath("TextMap/TextMap" + language + ".json"), StandardCharsets.UTF_8)) {
Matcher matcher = textMapKeyValueRegex.matcher("");
return new Int2ObjectOpenHashMap<>(
file.lines()
.sequential()
.map(matcher::reset) // Side effects, but it's faster than making a new one
.filter(Matcher::find)
.filter(
m ->
nameHashes.contains(
(int) Long.parseLong(m.group(1)))) // TODO: Cache this parse somehow
.collect(
Collectors.toMap(
m -> (int) Long.parseLong(m.group(1)),
m -> m.group(2).replace("\\\"", "\""))));
} catch (Exception e) {
Grasscutter.getLogger().error("Error loading textmap: " + language);
Grasscutter.getLogger().error(e.toString());
}
return output;
}
private static Int2ObjectMap<TextStrings> loadTextMapFiles(IntSet nameHashes) {
Map<Integer, Int2ObjectMap<String>>
mapLanguageMaps = // Separate step to process the textmaps in parallel
TextStrings.LIST_LANGUAGES.parallelStream()
.collect(
Collectors.toConcurrentMap(
s -> TextStrings.MAP_LANGUAGES.getInt(s),
s -> loadTextMapFile(s, nameHashes)));
List<Int2ObjectMap<String>> languageMaps =
IntStream.range(0, TextStrings.NUM_LANGUAGES)
.mapToObj(i -> mapLanguageMaps.get(i))
.collect(Collectors.toList());
Map<TextStrings, TextStrings> canonicalTextStrings = new HashMap<>();
return new Int2ObjectOpenHashMap<TextStrings>(
nameHashes
.intStream()
.boxed()
.collect(
Collectors.toMap(
key -> key,
key -> {
TextStrings t =
new TextStrings(
IntStream.range(0, TextStrings.NUM_LANGUAGES)
.mapToObj(i -> languageMaps.get(i).get((int) key))
.collect(Collectors.toList()),
key);
return canonicalTextStrings.computeIfAbsent(t, x -> t);
})));
}
@SuppressWarnings("unchecked")
private static Int2ObjectMap<TextStrings> loadTextMapsCache() throws Exception {
try (ObjectInputStream file =
new ObjectInputStream(
new BufferedInputStream(Files.newInputStream(TEXTMAP_CACHE_PATH), 0x100000))) {
final int fileVersion = file.readInt();
if (fileVersion != TEXTMAP_CACHE_VERSION) throw new Exception("Invalid cache version");
return (Int2ObjectMap<TextStrings>) file.readObject();
}
}
private static void saveTextMapsCache(Int2ObjectMap<TextStrings> input) throws IOException {
try {
Files.createDirectory(Path.of("cache"));
} catch (FileAlreadyExistsException ignored) {
}
try (ObjectOutputStream file =
new ObjectOutputStream(
new BufferedOutputStream(
Files.newOutputStream(TEXTMAP_CACHE_PATH, StandardOpenOption.CREATE), 0x100000))) {
file.writeInt(TEXTMAP_CACHE_VERSION);
file.writeObject(input);
}
}
@Deprecated(forRemoval = true)
public static Int2ObjectMap<TextStrings> getTextMapStrings() {
if (textMapStrings == null) loadTextMaps();
return textMapStrings;
}
public static TextStrings getTextMapKey(int key) {
if ((textMapStrings == null) || (!scannedTextmaps && !textMapStrings.containsKey(key)))
loadTextMaps();
return textMapStrings.get(key);
}
public static TextStrings getTextMapKey(long hash) {
return getTextMapKey((int) hash);
}
public static void loadTextMaps() {
// Check system timestamps on cache and resources
try {
long cacheModified = Files.getLastModifiedTime(TEXTMAP_CACHE_PATH).toMillis();
long textmapsModified =
Files.list(getResourcePath("TextMap"))
.filter(path -> path.toString().endsWith(".json"))
.map(
path -> {
try {
return Files.getLastModifiedTime(path).toMillis();
} catch (Exception ignored) {
Grasscutter.getLogger()
.debug("Exception while checking modified time: ", path);
return Long.MAX_VALUE; // Don't use cache, something has gone wrong
}
})
.max(Long::compare)
.get();
Grasscutter.getLogger()
.debug(
"Cache modified %d, textmap modified %d".formatted(cacheModified, textmapsModified));
if (textmapsModified < cacheModified) {
// Try loading from cache
Grasscutter.getLogger().info("Loading cached 'TextMaps'...");
textMapStrings = loadTextMapsCache();
return;
}
} catch (Exception e) {
Grasscutter.getLogger().debug("Exception while checking cache: ", e);
}
// Regenerate cache
Grasscutter.getLogger().debug("Generating TextMaps cache");
ResourceLoader.loadAll();
IntSet usedHashes = new IntOpenHashSet();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.forEach(
a -> {
usedHashes.add((int) a.getTitleTextMapHash());
usedHashes.add((int) a.getDescTextMapHash());
});
GameData.getAvatarDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getAvatarSkillDataMap()
.forEach(
(k, v) -> {
usedHashes.add((int) v.getNameTextMapHash());
usedHashes.add((int) v.getDescTextMapHash());
});
GameData.getItemDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getHomeWorldBgmDataMap()
.forEach((k, v) -> usedHashes.add((int) v.getBgmNameTextMapHash()));
GameData.getMonsterDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getMainQuestDataMap().forEach((k, v) -> usedHashes.add((int) v.getTitleTextMapHash()));
GameData.getQuestDataMap().forEach((k, v) -> usedHashes.add((int) v.getDescTextMapHash()));
// Incidental strings
usedHashes.add((int) 4233146695L); // Character
usedHashes.add((int) 4231343903L); // Weapon
usedHashes.add((int) 332935371L); // Standard Wish
usedHashes.add((int) 2272170627L); // Character Event Wish
usedHashes.add((int) 3352513147L); // Character Event Wish-2
usedHashes.add((int) 2864268523L); // Weapon Event Wish
textMapStrings = loadTextMapFiles(usedHashes);
scannedTextmaps = true;
try {
saveTextMapsCache(textMapStrings);
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to save TextMap cache: ", e);
}
}
/** get language code */
public String getLanguageCode() {
return languageCode;
}
/**
* Returns the value (as a string) from a nested key.
*
* @param key The key to look for.
* @return The value (as a string) from a nested key.
*/
public String get(String key) {
if (translations.containsKey(key)) return translations.get(key);
String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: ";
String result = valueNotFoundPattern + key;
if (!languageCode.equals("en-US")) {
String englishValue = getLanguage("en-US").get(key);
if (!englishValue.contains(valueNotFoundPattern)) {
result += "\nhere is english version:\n" + englishValue;
}
}
return result;
}
private static class LanguageStreamDescription {
private final String languageCode;
private final InputStream languageFile;
public LanguageStreamDescription(String languageCode, InputStream languageFile) {
this.languageCode = languageCode;
this.languageFile = languageFile;
}
public String getLanguageCode() {
return languageCode;
}
public InputStream getLanguageFile() {
return languageFile;
}
}
@EqualsAndHashCode
public static class TextStrings implements Serializable {
public static final String[] ARR_LANGUAGES = {
"EN", "CHS", "CHT", "JP", "KR", "DE", "ES", "FR", "ID", "PT", "RU", "TH", "VI"
};
public static final String[] ARR_GC_LANGUAGES = {
"en-US", "zh-CN", "zh-TW", "ja-JP", "ko-KR", "en-US", "es-ES", "fr-FR", "en-US", "en-US",
"ru-RU", "en-US", "en-US"
}; // TODO: Update the placeholder en-US entries if we ever add GC translations for the missing
// client languages
public static final int NUM_LANGUAGES = ARR_LANGUAGES.length;
public static final List<String> LIST_LANGUAGES = Arrays.asList(ARR_LANGUAGES);
public static final Object2IntMap<String>
MAP_LANGUAGES = // Map "EN": 0, "CHS": 1, ..., "VI": 12
new Object2IntOpenHashMap<>(
IntStream.range(0, ARR_LANGUAGES.length)
.boxed()
.collect(Collectors.toMap(i -> ARR_LANGUAGES[i], i -> i)));
public static final Object2IntMap<String> MAP_GC_LANGUAGES = // Map "en-US": 0, "zh-CN": 1, ...
new Object2IntOpenHashMap<>(
IntStream.range(0, ARR_GC_LANGUAGES.length)
.boxed()
.collect(
Collectors.toMap(
i -> ARR_GC_LANGUAGES[i],
i -> i,
(i1, i2) -> i1))); // Have to handle duplicates referring back to the first
public String[] strings = new String[ARR_LANGUAGES.length];
public TextStrings() {}
public TextStrings(String init) {
for (int i = 0; i < NUM_LANGUAGES; i++) this.strings[i] = init;
}
public TextStrings(List<String> strings, int key) {
// Some hashes don't have strings for some languages :(
String nullReplacement = "[N/A] %d".formatted((long) key & 0xFFFFFFFFL);
for (int i = 0; i < NUM_LANGUAGES; i++) { // Find first non-null if there is any
String s = strings.get(i);
if (s != null) {
nullReplacement = "[%s] - %s".formatted(ARR_LANGUAGES[i], s);
break;
}
}
for (int i = 0; i < NUM_LANGUAGES; i++) {
String s = strings.get(i);
if (s != null) this.strings[i] = s;
else this.strings[i] = nullReplacement;
}
}
public static List<Language> getLanguages() {
return Arrays.stream(ARR_GC_LANGUAGES).map(Language::getLanguage).toList();
}
public String get(int languageIndex) {
return strings[languageIndex];
}
public String get(String languageCode) {
return strings[MAP_LANGUAGES.getOrDefault(languageCode, 0)];
}
public String getGC(String languageCode) {
return strings[MAP_GC_LANGUAGES.getOrDefault(languageCode, 0)];
}
public boolean set(String languageCode, String string) {
int index = MAP_LANGUAGES.getOrDefault(languageCode, -1);
if (index < 0) return false;
strings[index] = string;
return true;
}
}
}
package emu.grasscutter.utils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.data.excels.AchievementData;
import emu.grasscutter.game.player.Player;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.EqualsAndHashCode;
import static emu.grasscutter.config.Configuration.*;
import static emu.grasscutter.utils.FileUtils.getResourcePath;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Language {
private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>();
private final String languageCode;
private final Map<String, String> translations = new ConcurrentHashMap<>();
private static boolean scannedTextmaps = false; // Ensure that we don't infinitely rescan on cache misses that don't exist
/**
* Creates a language instance from a code.
* @param langCode The language code.
* @return A language instance.
*/
public static Language getLanguage(String langCode) {
if (cachedLanguages.containsKey(langCode)) {
return cachedLanguages.get(langCode);
}
var fallbackLanguageCode = Utils.getLanguageCode(FALLBACK_LANGUAGE);
var description = getLanguageFileDescription(langCode, fallbackLanguageCode);
var actualLanguageCode = description.getLanguageCode();
Language languageInst;
if (description.getLanguageFile() != null) {
languageInst = new Language(description);
cachedLanguages.put(actualLanguageCode, languageInst);
} else {
languageInst = cachedLanguages.get(actualLanguageCode);
cachedLanguages.put(langCode, languageInst);
}
return languageInst;
}
/**
* Returns the translated value from the key while substituting arguments.
* @param key The key of the translated value to return.
* @param args The arguments to substitute.
* @return A translated value with arguments substituted.
*/
public static String translate(String key, Object... args) {
String translated = Grasscutter.getLanguage().get(key);
for (int i = 0; i < args.length; i++) {
args[i] = switch (args[i].getClass().getSimpleName()) {
case "String" -> args[i];
case "TextStrings" -> ((TextStrings) args[i]).get(0).replace("\\\\n", "\\n"); // TODO: Change this to server language
default -> args[i].toString();
};
}
try {
return translated.formatted(args);
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to format string: " + key, exception);
return translated;
}
}
/**
* Returns the translated value from the key while substituting arguments.
* @param player Target player
* @param key The key of the translated value to return.
* @param args The arguments to substitute.
* @return A translated value with arguments substituted.
*/
public static String translate(Player player, String key, Object... args) {
if (player == null) {
return translate(key, args);
}
var langCode = Utils.getLanguageCode(player.getAccount().getLocale());
String translated = getLanguage(langCode).get(key);
for (int i = 0; i < args.length; i++) {
args[i] = switch (args[i].getClass().getSimpleName()) {
case "String" -> args[i];
case "TextStrings" -> ((TextStrings) args[i]).getGC(langCode).replace("\\\\n", "\n"); // Note that we don't unescape \n for server console
default -> args[i].toString();
};
}
try {
return translated.formatted(args);
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to format string: " + key, exception);
return translated;
}
}
/**
* get language code
*/
public String getLanguageCode() {
return languageCode;
}
/**
* Recursive helper function to flatten a Json tree
* Converts input like {"foo": {"bar": "baz"}} to {"foo.bar": "baz"}
* @param map The map to insert the keys into
* @param key The flattened key of the current element
* @param element The current element
*/
private static void putFlattenedKey(Map<String,String> map, String key, JsonElement element) {
if (element.isJsonObject()) {
element.getAsJsonObject().entrySet().forEach(entry -> {
String keyPrefix = key.isEmpty() ? "" : key + ".";
putFlattenedKey(map, keyPrefix + entry.getKey(), entry.getValue());
});
} else {
map.put(key, element.getAsString());
}
}
/**
* Reads a file and creates a language instance.
*/
private Language(LanguageStreamDescription description) {
languageCode = description.getLanguageCode();
try {
var object = JsonUtils.decode(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class);
object.entrySet().forEach(entry -> putFlattenedKey(translations, entry.getKey(), entry.getValue()));
} catch (Exception exception) {
Grasscutter.getLogger().warn("Failed to load language file: " + description.getLanguageCode(), exception);
}
}
/**
* create a LanguageStreamDescription
* @param languageCode The name of the language code.
* @param fallbackLanguageCode The name of the fallback language code.
*/
private static LanguageStreamDescription getLanguageFileDescription(String languageCode, String fallbackLanguageCode) {
var fileName = languageCode + ".json";
var fallback = fallbackLanguageCode + ".json";
String actualLanguageCode = languageCode;
InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName);
if (file == null) { // Provided fallback language.
Grasscutter.getLogger().warn("Failed to load language file: " + fileName + ", falling back to: " + fallback);
actualLanguageCode = fallbackLanguageCode;
if (cachedLanguages.containsKey(actualLanguageCode)) {
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/" + fallback);
}
if (file == null) { // Fallback the fallback language.
Grasscutter.getLogger().warn("Failed to load language file: " + fallback + ", falling back to: en-US.json");
actualLanguageCode = "en-US";
if (cachedLanguages.containsKey(actualLanguageCode)) {
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/en-US.json");
}
if (file == null)
throw new RuntimeException("Unable to load the primary, fallback, and 'en-US' language files.");
return new LanguageStreamDescription(actualLanguageCode, file);
}
/**
* Returns the value (as a string) from a nested key.
* @param key The key to look for.
* @return The value (as a string) from a nested key.
*/
public String get(String key) {
if (translations.containsKey(key)) return translations.get(key);
String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: ";
String result = valueNotFoundPattern + key;
if (!languageCode.equals("en-US")) {
String englishValue = getLanguage("en-US").get(key);
if (!englishValue.contains(valueNotFoundPattern)) {
result += "\nhere is english version:\n" + englishValue;
}
}
return result;
}
private static class LanguageStreamDescription {
private final String languageCode;
private final InputStream languageFile;
public LanguageStreamDescription(String languageCode, InputStream languageFile) {
this.languageCode = languageCode;
this.languageFile = languageFile;
}
public String getLanguageCode() {
return languageCode;
}
public InputStream getLanguageFile() {
return languageFile;
}
}
private static final int TEXTMAP_CACHE_VERSION = 0x9CCACE04;
@EqualsAndHashCode public static class TextStrings implements Serializable {
public static final String[] ARR_LANGUAGES = {"EN", "CHS", "CHT", "JP", "KR", "DE", "ES", "FR", "ID", "PT", "RU", "TH", "VI"};
public static final String[] ARR_GC_LANGUAGES = {"en-US", "zh-CN", "zh-TW", "ja-JP", "ko-KR", "en-US", "es-ES", "fr-FR", "en-US", "en-US", "ru-RU", "en-US", "en-US"}; // TODO: Update the placeholder en-US entries if we ever add GC translations for the missing client languages
public static final int NUM_LANGUAGES = ARR_LANGUAGES.length;
public static final List<String> LIST_LANGUAGES = Arrays.asList(ARR_LANGUAGES);
public static final Object2IntMap<String> MAP_LANGUAGES = // Map "EN": 0, "CHS": 1, ..., "VI": 12
new Object2IntOpenHashMap<>(
IntStream.range(0, ARR_LANGUAGES.length)
.boxed()
.collect(Collectors.toMap(i -> ARR_LANGUAGES[i], i -> i)));
public static final Object2IntMap<String> MAP_GC_LANGUAGES = // Map "en-US": 0, "zh-CN": 1, ...
new Object2IntOpenHashMap<>(
IntStream.range(0, ARR_GC_LANGUAGES.length)
.boxed()
.collect(Collectors.toMap(i -> ARR_GC_LANGUAGES[i], i -> i, (i1, i2) -> i1))); // Have to handle duplicates referring back to the first
public String[] strings = new String[ARR_LANGUAGES.length];
public TextStrings() {};
public TextStrings(String init) {
for (int i = 0; i < NUM_LANGUAGES; i++)
this.strings[i] = init;
};
public TextStrings(List<String> strings, int key) {
// Some hashes don't have strings for some languages :(
String nullReplacement = "[N/A] %d".formatted((long) key & 0xFFFFFFFFL);
for (int i = 0; i < NUM_LANGUAGES; i++) { // Find first non-null if there is any
String s = strings.get(i);
if (s != null) {
nullReplacement = "[%s] - %s".formatted(ARR_LANGUAGES[i], s);
break;
}
}
for (int i = 0; i < NUM_LANGUAGES; i++) {
String s = strings.get(i);
if (s != null)
this.strings[i] = s;
else
this.strings[i] = nullReplacement;
}
}
public static List<Language> getLanguages() {
return Arrays.stream(ARR_GC_LANGUAGES).map(Language::getLanguage).toList();
}
public String get(int languageIndex) {
return strings[languageIndex];
}
public String get(String languageCode) {
return strings[MAP_LANGUAGES.getOrDefault(languageCode, 0)];
}
public String getGC(String languageCode) {
return strings[MAP_GC_LANGUAGES.getOrDefault(languageCode, 0)];
}
public boolean set(String languageCode, String string) {
int index = MAP_LANGUAGES.getOrDefault(languageCode, -1);
if (index < 0) return false;
strings[index] = string;
return true;
}
}
private static final Pattern textMapKeyValueRegex = Pattern.compile("\"(\\d+)\": \"(.+)\"");
private static Int2ObjectMap<String> loadTextMapFile(String language, IntSet nameHashes) {
Int2ObjectMap<String> output = new Int2ObjectOpenHashMap<>();
try (BufferedReader file = Files.newBufferedReader(getResourcePath("TextMap/TextMap"+language+".json"), StandardCharsets.UTF_8)) {
Matcher matcher = textMapKeyValueRegex.matcher("");
return new Int2ObjectOpenHashMap<>(
file.lines()
.sequential()
.map(matcher::reset) // Side effects, but it's faster than making a new one
.filter(Matcher::find)
.filter(m -> nameHashes.contains((int) Long.parseLong(m.group(1)))) // TODO: Cache this parse somehow
.collect(Collectors.toMap(
m -> (int) Long.parseLong(m.group(1)),
m -> m.group(2).replace("\\\"", "\""))));
} catch (Exception e) {
Grasscutter.getLogger().error("Error loading textmap: " + language);
Grasscutter.getLogger().error(e.toString());
}
return output;
}
private static Int2ObjectMap<TextStrings> loadTextMapFiles(IntSet nameHashes) {
Map<Integer, Int2ObjectMap<String>> mapLanguageMaps = // Separate step to process the textmaps in parallel
TextStrings.LIST_LANGUAGES.parallelStream().collect(
Collectors.toConcurrentMap(s -> TextStrings.MAP_LANGUAGES.getInt(s), s -> loadTextMapFile(s, nameHashes)));
List<Int2ObjectMap<String>> languageMaps =
IntStream.range(0, TextStrings.NUM_LANGUAGES)
.mapToObj(i -> mapLanguageMaps.get(i))
.collect(Collectors.toList());
Map<TextStrings, TextStrings> canonicalTextStrings = new HashMap<>();
return new Int2ObjectOpenHashMap<TextStrings>(
nameHashes
.intStream()
.boxed()
.collect(Collectors.toMap(key -> key, key -> {
TextStrings t = new TextStrings(
IntStream.range(0, TextStrings.NUM_LANGUAGES)
.mapToObj(i -> languageMaps.get(i).get((int) key))
.collect(Collectors.toList()), (int) key);
return canonicalTextStrings.computeIfAbsent(t, x -> t);
}))
);
}
@SuppressWarnings("unchecked")
private static Int2ObjectMap<TextStrings> loadTextMapsCache() throws Exception {
try (ObjectInputStream file = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(TEXTMAP_CACHE_PATH), 0x100000))) {
final int fileVersion = file.readInt();
if (fileVersion != TEXTMAP_CACHE_VERSION)
throw new Exception("Invalid cache version");
return (Int2ObjectMap<TextStrings>) file.readObject();
}
}
private static void saveTextMapsCache(Int2ObjectMap<TextStrings> input) throws IOException {
try {
Files.createDirectory(Path.of("cache"));
} catch (FileAlreadyExistsException ignored) {};
try (ObjectOutputStream file = new ObjectOutputStream(new BufferedOutputStream(Files.newOutputStream(TEXTMAP_CACHE_PATH, StandardOpenOption.CREATE), 0x100000))) {
file.writeInt(TEXTMAP_CACHE_VERSION);
file.writeObject(input);
}
}
private static Int2ObjectMap<TextStrings> textMapStrings;
private static final Path TEXTMAP_CACHE_PATH = Path.of(Utils.toFilePath("cache/TextMapCache.bin"));
@Deprecated(forRemoval = true)
public static Int2ObjectMap<TextStrings> getTextMapStrings() {
if (textMapStrings == null)
loadTextMaps();
return textMapStrings;
}
public static TextStrings getTextMapKey(int key) {
if ((textMapStrings == null) || (!scannedTextmaps && !textMapStrings.containsKey(key)))
loadTextMaps();
return textMapStrings.get(key);
}
public static TextStrings getTextMapKey(long hash) {
return getTextMapKey((int) hash);
}
public static void loadTextMaps() {
// Check system timestamps on cache and resources
try {
long cacheModified = Files.getLastModifiedTime(TEXTMAP_CACHE_PATH).toMillis();
long textmapsModified = Files.list(getResourcePath("TextMap"))
.filter(path -> path.toString().endsWith(".json"))
.map(path -> {
try {
return Files.getLastModifiedTime(path).toMillis();
} catch (Exception ignored) {
Grasscutter.getLogger().debug("Exception while checking modified time: ", path);
return Long.MAX_VALUE; // Don't use cache, something has gone wrong
}
})
.max(Long::compare)
.get();
Grasscutter.getLogger().debug("Cache modified %d, textmap modified %d".formatted(cacheModified, textmapsModified));
if (textmapsModified < cacheModified) {
// Try loading from cache
Grasscutter.getLogger().info("Loading cached 'TextMaps'...");
textMapStrings = loadTextMapsCache();
return;
}
} catch (Exception e) {
Grasscutter.getLogger().debug("Exception while checking cache: ", e);
}
// Regenerate cache
Grasscutter.getLogger().debug("Generating TextMaps cache");
ResourceLoader.loadAll();
IntSet usedHashes = new IntOpenHashSet();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.forEach(a -> {
usedHashes.add((int) a.getTitleTextMapHash());
usedHashes.add((int) a.getDescTextMapHash());
});
GameData.getAvatarDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getAvatarSkillDataMap().forEach((k, v) -> {
usedHashes.add((int) v.getNameTextMapHash());
usedHashes.add((int) v.getDescTextMapHash());
});
GameData.getItemDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getHomeWorldBgmDataMap().forEach((k, v) -> usedHashes.add((int) v.getBgmNameTextMapHash()));
GameData.getMonsterDataMap().forEach((k, v) -> usedHashes.add((int) v.getNameTextMapHash()));
GameData.getMainQuestDataMap().forEach((k, v) -> usedHashes.add((int) v.getTitleTextMapHash()));
GameData.getQuestDataMap().forEach((k, v) -> usedHashes.add((int) v.getDescTextMapHash()));
// Incidental strings
usedHashes.add((int) 4233146695L); // Character
usedHashes.add((int) 4231343903L); // Weapon
usedHashes.add((int) 332935371L); // Standard Wish
usedHashes.add((int) 2272170627L); // Character Event Wish
usedHashes.add((int) 3352513147L); // Character Event Wish-2
usedHashes.add((int) 2864268523L); // Weapon Event Wish
textMapStrings = loadTextMapFiles(usedHashes);
scannedTextmaps = true;
try {
saveTextMapsCache(textMapStrings);
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to save TextMap cache: ", e);
};
}
}