From fc05602128e923d285be8c6f30f7d3a9d6dead90 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Fri, 31 Mar 2023 22:30:45 -0400 Subject: [PATCH] Run Spotless on `src/main` --- .../java/emu/grasscutter/GameConstants.java | 65 +- .../java/emu/grasscutter/Grasscutter.java | 645 ++- .../auth/AuthenticationSystem.java | 281 +- .../emu/grasscutter/auth/Authenticator.java | 42 +- .../auth/DefaultAuthentication.java | 143 +- .../auth/DefaultAuthenticators.java | 709 +-- .../auth/ExternalAuthenticator.java | 68 +- .../grasscutter/auth/OAuthAuthenticator.java | 72 +- .../java/emu/grasscutter/command/Command.java | 56 +- .../grasscutter/command/CommandHandler.java | 178 +- .../grasscutter/command/CommandHelpers.java | 107 +- .../emu/grasscutter/command/CommandMap.java | 684 +-- .../command/DefaultPermissionHandler.java | 65 +- .../command/PermissionHandler.java | 19 +- .../command/commands/AccountCommand.java | 284 +- .../command/commands/AchievementCommand.java | 291 +- .../command/commands/AnnounceCommand.java | 151 +- .../command/commands/BanCommand.java | 126 +- .../command/commands/ClearCommand.java | 208 +- .../command/commands/CoopCommand.java | 106 +- .../command/commands/EnterDungeonCommand.java | 89 +- .../command/commands/HealCommand.java | 76 +- .../command/commands/HelpCommand.java | 175 +- .../command/commands/KickCommand.java | 59 +- .../command/commands/KillAllCommand.java | 101 +- .../commands/KillCharacterCommand.java | 73 +- .../command/commands/LanguageCommand.java | 111 +- .../command/commands/ListCommand.java | 109 +- .../command/commands/PermissionCommand.java | 147 +- .../command/commands/PositionCommand.java | 49 +- .../command/commands/QuestCommand.java | 128 +- .../command/commands/ReloadCommand.java | 56 +- .../command/commands/ResetConstCommand.java | 85 +- .../commands/ResetShopLimitCommand.java | 43 +- .../command/commands/SendMailCommand.java | 443 +- .../command/commands/SendMessageCommand.java | 75 +- .../command/commands/SetConstCommand.java | 180 +- .../commands/SetFetterLevelCommand.java | 100 +- .../command/commands/SetPropCommand.java | 529 +-- .../command/commands/SetStatsCommand.java | 374 +- .../command/commands/SpawnCommand.java | 434 +- .../command/commands/StopCommand.java | 51 +- .../command/commands/TalentCommand.java | 249 +- .../command/commands/TeamCommand.java | 526 +-- .../command/commands/TeleportAllCommand.java | 67 +- .../command/commands/TeleportCommand.java | 146 +- .../command/commands/UnBanCommand.java | 80 +- .../command/commands/UnlockAllCommand.java | 82 +- .../command/commands/WeatherCommand.java | 95 +- .../emu/grasscutter/config/Configuration.java | 238 +- .../java/emu/grasscutter/data/DataLoader.java | 300 +- .../java/emu/grasscutter/data/GameData.java | 821 ++-- .../java/emu/grasscutter/data/GameDepot.java | 164 +- .../emu/grasscutter/data/GameResource.java | 22 +- .../emu/grasscutter/data/ResourceLoader.java | 1218 +++--- .../emu/grasscutter/data/ResourceType.java | 82 +- .../data/binout/AbilityEmbryoEntry.java | 44 +- .../data/binout/AbilityModifier.java | 367 +- .../data/binout/AbilityModifierEntry.java | 72 +- .../grasscutter/data/binout/ConfigGadget.java | 28 +- .../binout/ConfigGadgetCombatProperty.java | 36 +- .../data/binout/HomeworldDefaultSaveData.java | 117 +- .../data/binout/MainQuestData.java | 159 +- .../data/binout/OpenConfigEntry.java | 143 +- .../data/binout/SceneNpcBornData.java | 53 +- .../data/binout/SceneNpcBornEntry.java | 73 +- .../data/binout/ScenePointEntry.java | 50 +- .../data/binout/ScriptSceneData.java | 39 +- .../grasscutter/data/common/CurveInfo.java | 38 +- .../grasscutter/data/common/DynamicFloat.java | 202 +- .../data/common/FightPropData.java | 50 +- .../data/common/ItemParamData.java | 75 +- .../data/common/ItemParamStringData.java | 53 +- .../grasscutter/data/common/PointData.java | 119 +- .../data/common/PropGrowCurve.java | 29 +- .../data/excels/AchievementData.java | 195 +- .../grasscutter/data/excels/ActivityData.java | 72 +- .../data/excels/ActivityShopData.java | 54 +- .../data/excels/ActivityWatcherData.java | 76 +- .../data/excels/AvatarCostumeData.java | 75 +- .../data/excels/AvatarCurveData.java | 72 +- .../data/excels/AvatarFetterLevelData.java | 46 +- .../data/excels/AvatarFlycloakData.java | 46 +- .../data/excels/AvatarLevelData.java | 46 +- .../data/excels/AvatarPromoteData.java | 149 +- .../data/excels/AvatarSkillData.java | 49 +- .../data/excels/AvatarSkillDepotData.java | 175 +- .../data/excels/AvatarTalentData.java | 139 +- .../data/excels/BattlePassMissionData.java | 143 +- .../data/excels/BattlePassRewardData.java | 52 +- .../excels/BlossomRefreshExcelConfigData.java | 91 +- .../emu/grasscutter/data/excels/BuffData.java | 55 +- .../grasscutter/data/excels/ChapterData.java | 65 +- .../emu/grasscutter/data/excels/CityData.java | 49 +- .../data/excels/CodexAnimalData.java | 50 +- .../data/excels/CodexQuestData.java | 82 +- .../data/excels/CodexReliquaryData.java | 103 +- .../grasscutter/data/excels/CombineData.java | 164 +- .../grasscutter/data/excels/CompoundData.java | 46 +- .../data/excels/CookBonusData.java | 85 +- .../data/excels/CookRecipeData.java | 47 +- .../data/excels/DailyDungeonData.java | 87 +- .../grasscutter/data/excels/DungeonData.java | 69 +- .../data/excels/DungeonEntryData.java | 33 +- .../excels/EnvAnimalGatherConfigData.java | 71 +- .../data/excels/EquipAffixData.java | 119 +- .../data/excels/FetterCharacterCardData.java | 47 +- .../grasscutter/data/excels/FetterData.java | 70 +- .../grasscutter/data/excels/ForgeData.java | 56 +- .../data/excels/FurnitureMakeConfigData.java | 71 +- .../grasscutter/data/excels/GatherData.java | 96 +- .../data/excels/HomeWorldBgmData.java | 60 +- .../data/excels/HomeWorldLevelData.java | 63 +- .../data/excels/InvestigationMonsterData.java | 64 +- .../emu/grasscutter/data/excels/ItemData.java | 301 +- .../data/excels/MonsterCurveData.java | 64 +- .../grasscutter/data/excels/MonsterData.java | 219 +- .../data/excels/MonsterDescribeData.java | 33 +- .../data/excels/MusicGameBasicData.java | 35 +- .../data/excels/PersonalLineData.java | 46 +- .../data/excels/PlayerLevelData.java | 42 +- .../data/excels/ProudSkillData.java | 129 +- .../grasscutter/data/excels/QuestData.java | 271 +- .../data/excels/ReliquaryAffixData.java | 46 +- .../data/excels/ReliquaryLevelData.java | 93 +- .../data/excels/ReliquaryMainPropData.java | 40 +- .../data/excels/ReliquarySetData.java | 64 +- .../grasscutter/data/excels/RewardData.java | 53 +- .../data/excels/RewardPreviewData.java | 69 +- .../grasscutter/data/excels/SceneData.java | 36 +- .../data/excels/ShopGoodsData.java | 222 +- .../data/excels/TowerLevelData.java | 68 +- .../data/excels/TowerScheduleData.java | 100 +- .../data/excels/TriggerExcelConfigData.java | 29 +- .../data/excels/WeaponCurveData.java | 64 +- .../data/excels/WeaponLevelData.java | 46 +- .../data/excels/WeaponPromoteData.java | 149 +- .../grasscutter/data/excels/WeatherData.java | 63 +- .../data/excels/WorldAreaData.java | 62 +- .../data/excels/WorldLevelData.java | 46 +- .../grasscutter/database/DatabaseCounter.java | 46 +- .../grasscutter/database/DatabaseHelper.java | 825 ++-- .../grasscutter/database/DatabaseManager.java | 245 +- .../java/emu/grasscutter/game/Account.java | 486 +-- .../emu/grasscutter/game/CoopRequest.java | 62 +- .../game/ability/AbilityManager.java | 450 +- .../game/ability/HealAbilityManager.java | 399 +- .../game/achievement/Achievement.java | 78 +- .../AchievementControlReturns.java | 95 +- .../game/achievement/Achievements.java | 616 +-- .../game/activity/ActivityConfigItem.java | 41 +- .../game/activity/ActivityHandler.java | 189 +- .../game/activity/ActivityManager.java | 311 +- .../game/activity/ActivityWatcher.java | 51 +- .../game/activity/ActivityWatcherType.java | 27 +- .../game/activity/DefaultActivityHandler.java | 32 +- .../game/activity/DefaultWatcher.java | 22 +- .../game/activity/GameActivity.java | 27 +- .../game/activity/PlayerActivityData.java | 260 +- .../musicgame/MusicGameActivityHandler.java | 196 +- .../activity/musicgame/MusicGameBeatmap.java | 203 +- .../musicgame/MusicGamePlayerData.java | 173 +- .../musicgame/MusicGameScoreTrigger.java | 46 +- .../emu/grasscutter/game/avatar/Avatar.java | 1979 ++++----- .../game/avatar/AvatarStorage.java | 346 +- .../game/battlepass/BattlePassManager.java | 807 ++-- .../game/battlepass/BattlePassMission.java | 150 +- .../game/battlepass/BattlePassReward.java | 101 +- .../game/battlepass/BattlePassSystem.java | 158 +- .../emu/grasscutter/game/chat/ChatSystem.java | 419 +- .../game/chat/ChatSystemHandler.java | 52 +- .../game/combine/CombineManger.java | 275 +- .../game/combine/CombineResult.java | 88 +- .../game/combine/ReliquaryDecomposeEntry.java | 48 +- .../emu/grasscutter/game/drop/DropData.java | 106 +- .../emu/grasscutter/game/drop/DropInfo.java | 32 +- .../emu/grasscutter/game/drop/DropSystem.java | 218 +- .../game/dungeons/DungeonDrop.java | 48 +- .../game/dungeons/DungeonDropEntry.java | 102 +- .../game/dungeons/DungeonSystem.java | 234 +- .../dungeons/TowerDungeonSettleListener.java | 65 +- .../dungeons/challenge/DungeonChallenge.java | 407 +- .../dungeons/challenge/WorldChallenge.java | 281 +- .../challenge/factory/ChallengeFactory.java | 67 +- .../factory/ChallengeFactoryHandler.java | 38 +- .../DungeonChallengeFactoryHandler.java | 81 +- .../DungeonGuardChallengeFactoryHandler.java | 79 +- .../KillGadgetChallengeFactoryHandler.java | 81 +- .../KillMonsterChallengeFactoryHandler.java | 77 +- .../challenge/trigger/ChallengeTrigger.java | 44 +- .../challenge/trigger/GuardTrigger.java | 52 +- .../challenge/trigger/InTimeTrigger.java | 26 +- .../challenge/trigger/KillGadgetTrigger.java | 47 +- .../challenge/trigger/KillMonsterTrigger.java | 47 +- .../grasscutter/game/entity/EntityAvatar.java | 677 +-- .../game/entity/EntityBaseGadget.java | 115 +- .../game/entity/EntityClientGadget.java | 241 +- .../grasscutter/game/entity/EntityGadget.java | 396 +- .../grasscutter/game/entity/EntityItem.java | 274 +- .../game/entity/EntityMonster.java | 493 ++- .../grasscutter/game/entity/EntityNPC.java | 147 +- .../grasscutter/game/entity/EntityRegion.java | 183 +- .../EntitySolarIsotomaClientGadget.java | 66 +- .../game/entity/EntityVehicle.java | 245 +- .../grasscutter/game/entity/GameEntity.java | 477 +- .../game/entity/gadget/GadgetChest.java | 159 +- .../game/entity/gadget/GadgetContent.java | 44 +- .../entity/gadget/GadgetGatherObject.java | 167 +- .../game/entity/gadget/GadgetGatherPoint.java | 162 +- .../game/entity/gadget/GadgetObject.java | 42 +- .../entity/gadget/GadgetRewardStatue.java | 60 +- .../game/entity/gadget/GadgetWorktop.java | 133 +- .../chest/BossChestInteractHandler.java | 112 +- .../chest/NormalChestInteractHandler.java | 92 +- .../worktop/WorktopWorktopOptionHandler.java | 14 +- .../game/entity/platform/EntityPlatform.java | 198 +- .../EntitySolarIsotomaElevatorPlatform.java | 289 +- .../game/expedition/ExpeditionInfo.java | 50 +- .../game/expedition/ExpeditionRewardData.java | 33 +- .../expedition/ExpeditionRewardDataList.java | 41 +- .../game/expedition/ExpeditionRewardInfo.java | 21 +- .../game/expedition/ExpeditionSystem.java | 83 +- .../grasscutter/game/friends/FriendsList.java | 508 +-- .../grasscutter/game/friends/Friendship.java | 232 +- .../game/friends/PlayerProfile.java | 211 +- .../grasscutter/game/gacha/GachaBanner.java | 644 +-- .../grasscutter/game/gacha/GachaRecord.java | 156 +- .../grasscutter/game/gacha/GachaSystem.java | 920 ++-- .../game/gacha/PlayerGachaBannerInfo.java | 254 +- .../game/home/FurnitureMakeSlotItem.java | 63 +- .../emu/grasscutter/game/home/GameHome.java | 699 +-- .../grasscutter/game/home/HomeAnimalItem.java | 71 +- .../grasscutter/game/home/HomeBlockItem.java | 173 +- .../game/home/HomeFurnitureItem.java | 162 +- .../grasscutter/game/home/HomeNPCItem.java | 76 +- .../grasscutter/game/home/HomeSceneItem.java | 193 +- .../game/inventory/EquipInventoryTab.java | 78 +- .../grasscutter/game/inventory/EquipType.java | 93 +- .../grasscutter/game/inventory/GameItem.java | 752 ++-- .../grasscutter/game/inventory/Inventory.java | 1078 ++--- .../game/inventory/InventoryTab.java | 26 +- .../grasscutter/game/inventory/ItemDef.java | 54 +- .../game/inventory/ItemQuality.java | 93 +- .../grasscutter/game/inventory/ItemType.java | 93 +- .../game/inventory/MaterialInventoryTab.java | 78 +- .../game/inventory/MaterialType.java | 161 +- .../java/emu/grasscutter/game/mail/Mail.java | 261 +- .../grasscutter/game/mail/MailHandler.java | 216 +- .../game/managers/FurnitureManager.java | 320 +- .../game/managers/ResinManager.java | 301 +- .../game/managers/SatiationManager.java | 230 +- .../game/managers/SotSManager.java | 401 +- .../managers/blossom/BlossomActivity.java | 292 +- .../game/managers/blossom/BlossomConfig.java | 26 +- .../game/managers/blossom/BlossomManager.java | 478 +- .../game/managers/blossom/BlossomType.java | 74 +- .../cooking/ActiveCookCompoundData.java | 112 +- .../cooking/CookingCompoundManager.java | 298 +- .../game/managers/cooking/CookingManager.java | 369 +- .../deforestation/DeforestationManager.java | 201 +- .../managers/deforestation/HitTreeRecord.java | 106 +- .../game/managers/energy/EnergyManager.java | 776 ++-- .../energy/SkillParticleGenerationEntry.java | 32 +- .../energy/SkillParticleGenerationInfo.java | 28 +- .../managers/forging/ActiveForgeData.java | 193 +- .../game/managers/forging/ForgingManager.java | 623 +-- .../game/managers/mapmark/MapMark.java | 124 +- .../managers/mapmark/MapMarksManager.java | 170 +- .../stamina/AfterUpdateStaminaListener.java | 24 +- .../stamina/BeforeUpdateStaminaListener.java | 47 +- .../game/managers/stamina/Consumption.java | 35 +- .../managers/stamina/ConsumptionType.java | 74 +- .../game/player/BasePlayerDataManager.java | 47 +- .../game/player/BasePlayerManager.java | 42 +- .../game/player/InvokeHandler.java | 125 +- .../game/player/PlayerBirthday.java | 133 +- .../game/player/PlayerBuffManager.java | 438 +- .../grasscutter/game/player/PlayerCodex.java | 277 +- .../game/player/PlayerCollectionRecords.java | 136 +- .../game/player/PlayerProgressManager.java | 458 +- .../emu/grasscutter/game/player/TeamInfo.java | 192 +- .../grasscutter/game/player/TeamManager.java | 1434 +++--- .../grasscutter/game/props/ActionReason.java | 425 +- .../grasscutter/game/props/ActivityType.java | 78 +- .../props/BattlePassMissionRefreshType.java | 36 +- .../game/props/BattlePassMissionStatus.java | 52 +- .../grasscutter/game/props/ClimateType.java | 111 +- .../grasscutter/game/props/ElementType.java | 205 +- .../grasscutter/game/props/EnterReason.java | 143 +- .../grasscutter/game/props/EntityIdType.java | 44 +- .../grasscutter/game/props/EntityType.java | 215 +- .../grasscutter/game/props/FetterState.java | 87 +- .../grasscutter/game/props/FightProperty.java | 489 ++- .../emu/grasscutter/game/props/GrowCurve.java | 205 +- .../ItemUseAction/ItemUseAcceptQuest.java | 38 +- .../props/ItemUseAction/ItemUseAction.java | 163 +- .../ItemUseAction/ItemUseAddAllEnergy.java | 48 +- .../props/ItemUseAction/ItemUseAddCurHp.java | 44 +- .../ItemUseAction/ItemUseAddCurStamina.java | 38 +- .../ItemUseAction/ItemUseAddElemEnergy.java | 68 +- .../props/ItemUseAction/ItemUseAddEnergy.java | 123 +- .../props/ItemUseAction/ItemUseAddExp.java | 36 +- .../props/ItemUseAction/ItemUseAddItem.java | 50 +- .../ItemUseAction/ItemUseAddReliquaryExp.java | 28 +- .../ItemUseAction/ItemUseAddSelectItem.java | 44 +- .../ItemUseAction/ItemUseAddServerBuff.java | 50 +- .../ItemUseAction/ItemUseAddWeaponExp.java | 28 +- .../ItemUseAction/ItemUseChestSelectItem.java | 75 +- .../ItemUseAction/ItemUseCombineItem.java | 62 +- .../ItemUseAction/ItemUseGainAvatar.java | 101 +- .../ItemUseAction/ItemUseGainCardProduct.java | 35 +- .../ItemUseAction/ItemUseGainCostume.java | 46 +- .../ItemUseAction/ItemUseGainFlycloak.java | 46 +- .../ItemUseAction/ItemUseGainNameCard.java | 37 +- .../ItemUseGrantSelectReward.java | 44 +- .../game/props/ItemUseAction/ItemUseInt.java | 29 +- .../ItemUseAction/ItemUseMakeGadget.java | 52 +- .../ItemUseAction/ItemUseOpenRandomChest.java | 55 +- .../ItemUseAction/ItemUseReliveAvatar.java | 35 +- .../ItemUseAction/ItemUseUnlockCodex.java | 38 +- .../ItemUseAction/ItemUseUnlockCombine.java | 48 +- .../ItemUseUnlockCookRecipe.java | 48 +- .../ItemUseAction/ItemUseUnlockForge.java | 48 +- .../ItemUseUnlockFurnitureFormula.java | 48 +- .../ItemUseUnlockFurnitureSuite.java | 48 +- .../ItemUseAction/ItemUseUnlockHomeBgm.java | 40 +- .../ItemUseUnlockHomeModule.java | 50 +- .../ItemUseUnlockPaidBattlePassNormal.java | 39 +- .../props/ItemUseAction/UseItemParams.java | 66 +- .../emu/grasscutter/game/props/ItemUseOp.java | 147 +- .../grasscutter/game/props/ItemUseTarget.java | 75 +- .../emu/grasscutter/game/props/LifeState.java | 87 +- .../grasscutter/game/props/MonsterType.java | 91 +- .../game/props/PlayerProperty.java | 191 +- .../emu/grasscutter/game/props/SceneType.java | 93 +- .../game/props/ServerBuffType.java | 71 +- .../game/props/WatcherTriggerType.java | 677 +-- .../grasscutter/game/props/WeaponType.java | 139 +- .../grasscutter/game/quest/GameMainQuest.java | 844 ++-- .../emu/grasscutter/game/quest/GameQuest.java | 499 ++- .../grasscutter/game/quest/QuestSystem.java | 203 +- .../grasscutter/game/quest/QuestValue.java | 21 +- .../grasscutter/game/quest/RewindData.java | 56 +- .../game/quest/conditions/BaseCondition.java | 36 +- .../conditions/ConditionCompleteTalk.java | 60 +- .../quest/conditions/ConditionLuaNotify.java | 34 +- .../ConditionPlayerLevelEqualGreater.java | 34 +- .../ConditionQuestGlobalVarEqual.java | 40 +- .../ConditionQuestGlobalVarGreater.java | 40 +- .../ConditionQuestGlobalVarLess.java | 40 +- .../conditions/ConditionQuestVarEqual.java | 39 +- .../conditions/ConditionQuestVarGreater.java | 39 +- .../conditions/ConditionQuestVarLess.java | 39 +- .../quest/conditions/ConditionStateEqual.java | 52 +- .../conditions/ConditionStateNotEqual.java | 52 +- .../game/quest/content/BaseContent.java | 36 +- .../quest/content/ContentCompleteAnyTalk.java | 51 +- .../quest/content/ContentCompleteTalk.java | 57 +- .../quest/content/ContentEnterDungeon.java | 34 +- .../game/quest/content/ContentEnterRoom.java | 34 +- .../game/quest/content/ContentFinishPlot.java | 41 +- .../quest/content/ContentGameTimeTick.java | 45 +- .../quest/content/ContentInteractGadget.java | 34 +- .../game/quest/content/ContentLeaveScene.java | 34 +- .../game/quest/content/ContentLuaNotify.java | 34 +- .../quest/content/ContentNotFinishPlot.java | 49 +- .../quest/content/ContentQuestStateEqual.java | 42 +- .../content/ContentQuestStateNotEqual.java | 46 +- .../quest/content/ContentQuestVarEqual.java | 39 +- .../quest/content/ContentQuestVarGreater.java | 39 +- .../quest/content/ContentQuestVarLess.java | 39 +- .../game/quest/content/ContentSkill.java | 29 +- .../quest/content/ContentTriggerFire.java | 48 +- .../content/ContentUnlockTransPoint.java | 31 +- .../game/quest/enums/LogicType.java | 86 +- .../game/quest/enums/ParentQuestState.java | 36 +- .../game/quest/enums/QuestGuideType.java | 34 +- .../game/quest/enums/QuestShowType.java | 32 +- .../game/quest/enums/QuestState.java | 52 +- .../game/quest/enums/QuestTrigger.java | 523 +-- .../game/quest/enums/QuestType.java | 44 +- .../game/quest/enums/ShowQuestGuideType.java | 34 +- .../game/quest/exec/ExecAddQuestProgress.java | 48 +- .../quest/exec/ExecDecQuestGlobalVar.java | 36 +- .../quest/exec/ExecIncQuestGlobalVar.java | 35 +- .../game/quest/exec/ExecNotifyGroupLua.java | 64 +- .../quest/exec/ExecRefreshGroupSuite.java | 72 +- .../quest/exec/ExecSetQuestGlobalVar.java | 35 +- .../game/quest/exec/ExecUnlockArea.java | 42 +- .../game/quest/handlers/QuestBaseHandler.java | 20 +- .../game/quest/handlers/QuestExecHandler.java | 20 +- .../emu/grasscutter/game/shop/ShopInfo.java | 221 +- .../emu/grasscutter/game/shop/ShopLimit.java | 86 +- .../emu/grasscutter/game/shop/ShopSystem.java | 227 +- .../emu/grasscutter/game/shop/ShopType.java | 214 +- .../game/systems/AnnouncementSystem.java | 215 +- .../game/systems/InventorySystem.java | 1745 ++++---- .../emu/grasscutter/game/tower/TowerData.java | 44 +- .../game/tower/TowerLevelRecord.java | 120 +- .../grasscutter/game/tower/TowerManager.java | 310 +- .../game/tower/TowerScheduleConfig.java | 69 +- .../grasscutter/game/tower/TowerSystem.java | 175 +- .../grasscutter/game/world/ChestReward.java | 42 +- .../emu/grasscutter/game/world/Scene.java | 1627 +++---- .../game/world/SpawnDataEntry.java | 210 +- .../emu/grasscutter/game/world/World.java | 706 +-- .../game/world/WorldDataSystem.java | 300 +- .../grasscutter/net/packet/BasePacket.java | 281 +- .../emu/grasscutter/net/packet/Opcodes.java | 30 +- .../grasscutter/net/packet/PacketHandler.java | 18 +- .../grasscutter/net/packet/PacketOpcodes.java | 3850 ++++++++--------- .../net/packet/PacketOpcodesUtils.java | 147 +- .../grasscutter/net/packet/PacketWriter.java | 353 +- .../java/emu/grasscutter/plugin/Plugin.java | 259 +- .../emu/grasscutter/plugin/PluginConfig.java | 40 +- .../grasscutter/plugin/PluginIdentifier.java | 51 +- .../emu/grasscutter/plugin/PluginManager.java | 640 +-- .../java/emu/grasscutter/plugin/api/Item.java | 10 +- .../grasscutter/plugin/api/PlayerHook.java | 246 +- .../grasscutter/plugin/api/ServerHook.java | 255 +- .../scripts/SceneIndexManager.java | 70 +- .../scripts/SceneScriptManager.java | 1092 ++--- .../emu/grasscutter/scripts/ScriptLib.java | 1174 ++--- .../emu/grasscutter/scripts/ScriptLoader.java | 302 +- .../emu/grasscutter/scripts/ScriptUtils.java | 53 +- .../scripts/constants/EventType.java | 253 +- .../scripts/constants/ScriptGadgetState.java | 48 +- .../scripts/constants/ScriptRegionShape.java | 18 +- .../grasscutter/scripts/data/SceneBlock.java | 164 +- .../scripts/data/SceneBusiness.java | 20 +- .../grasscutter/scripts/data/SceneConfig.java | 30 +- .../grasscutter/scripts/data/SceneGadget.java | 54 +- .../scripts/data/SceneGarbage.java | 23 +- .../grasscutter/scripts/data/SceneGroup.java | 318 +- .../scripts/data/SceneInitConfig.java | 24 +- .../grasscutter/scripts/data/SceneMeta.java | 146 +- .../scripts/data/SceneMonster.java | 38 +- .../grasscutter/scripts/data/SceneNPC.java | 20 +- .../grasscutter/scripts/data/SceneObject.java | 38 +- .../grasscutter/scripts/data/SceneRegion.java | 79 +- .../grasscutter/scripts/data/SceneSuite.java | 122 +- .../scripts/data/SceneTrigger.java | 104 +- .../grasscutter/scripts/data/SceneVar.java | 26 +- .../grasscutter/scripts/data/ScriptArgs.java | 132 +- .../scripts/serializer/LuaSerializer.java | 485 ++- .../serializer/LuaTableJacksonSerializer.java | 378 +- .../scripts/serializer/Serializer.java | 27 +- .../service/ScriptMonsterSpawnService.java | 78 +- .../service/ScriptMonsterTideService.java | 188 +- .../grasscutter/server/event/Cancellable.java | 14 +- .../emu/grasscutter/server/event/Event.java | 55 +- .../server/event/EventHandler.java | 182 +- .../server/event/HandlerPriority.java | 30 +- .../event/dispatch/QueryAllRegionsEvent.java | 42 +- .../dispatch/QueryCurrentRegionEvent.java | 42 +- .../event/entity/EntityDamageEvent.java | 63 +- .../server/event/entity/EntityDeathEvent.java | 42 +- .../server/event/entity/EntityMoveEvent.java | 63 +- .../event/game/PlayerCreationEvent.java | 54 +- .../game/ReceiveCommandFeedbackEvent.java | 63 +- .../server/event/game/ReceivePacketEvent.java | 70 +- .../server/event/game/SendPacketEvent.java | 60 +- .../server/event/game/ServerTickEvent.java | 47 +- .../event/internal/ServerStartEvent.java | 37 +- .../event/internal/ServerStopEvent.java | 37 +- .../server/event/player/PlayerMoveEvent.java | 86 +- .../server/event/player/PlayerQuitEvent.java | 20 +- .../event/player/PlayerReceiveMailEvent.java | 48 +- .../event/player/PlayerTeamDeathEvent.java | 41 +- .../event/player/PlayerTeleportEvent.java | 116 +- .../event/player/PlayerUseFoodEvent.java | 49 +- .../server/event/types/EntityEvent.java | 36 +- .../server/event/types/GameEvent.java | 16 +- .../server/event/types/PlayerEvent.java | 36 +- .../server/event/types/ServerEvent.java | 44 +- .../grasscutter/server/game/GameServer.java | 556 +-- .../server/game/GameServerPacketHandler.java | 214 +- .../grasscutter/server/game/GameSession.java | 546 ++- .../server/game/GameSessionManager.java | 230 +- .../emu/grasscutter/server/http/Router.java | 68 +- .../server/http/dispatch/DispatchHandler.java | 290 +- .../server/http/dispatch/RegionHandler.java | 634 +-- .../DocumentationServerHandler.java | 40 +- .../GachaMappingRequestHandler.java | 50 +- .../documentation/HandbookRequestHandler.java | 352 +- .../documentation/RootRequestHandler.java | 83 +- .../http/handlers/AnnouncementsHandler.java | 219 +- .../server/http/handlers/GachaHandler.java | 293 +- .../server/http/handlers/GenericHandler.java | 142 +- .../server/http/handlers/LogHandler.java | 44 +- .../http/objects/ComboTokenReqJson.java | 30 +- .../http/objects/ComboTokenResJson.java | 34 +- .../server/http/objects/HttpJsonResponse.java | 94 +- .../http/objects/LoginAccountRequestJson.java | 14 +- .../server/http/objects/LoginResultJson.java | 76 +- .../http/objects/LoginTokenRequestJson.java | 12 +- .../objects/WebStaticVersionResponse.java | 70 +- .../server/packet/recv/Handler.java | 31 +- .../recv/HandlerAbilityInvocationsNotify.java | 49 +- .../HandlerActivityTakeWatcherRewardReq.java | 54 +- .../recv/HandlerAddBackupAvatarTeamReq.java | 28 +- .../HandlerAddQuestContentProgressReq.java | 74 +- .../packet/recv/HandlerAskAddFriendReq.java | 37 +- .../recv/HandlerAvatarChangeCostumeReq.java | 54 +- .../HandlerAvatarChangeElementTypeReq.java | 136 +- .../recv/HandlerAvatarDieAnimationEndReq.java | 37 +- .../HandlerAvatarExpeditionAllDataReq.java | 34 +- .../HandlerAvatarExpeditionGetRewardReq.java | 91 +- .../HandlerAvatarFetterLevelRewardReq.java | 108 +- .../packet/recv/HandlerAvatarPromoteReq.java | 39 +- .../recv/HandlerAvatarSkillUpgradeReq.java | 44 +- .../packet/recv/HandlerAvatarUpgradeReq.java | 47 +- .../recv/HandlerAvatarWearFlycloakReq.java | 51 +- .../packet/recv/HandlerBackMyWorldReq.java | 68 +- .../recv/HandlerBuyBattlePassLevelReq.java | 43 +- .../packet/recv/HandlerBuyGoodsReq.java | 160 +- ...andlerCalcWeaponUpgradeReturnItemsReq.java | 70 +- .../packet/recv/HandlerChangeAvatarReq.java | 37 +- .../packet/recv/HandlerChangeGameTimeReq.java | 53 +- .../recv/HandlerChangeMailStarNotify.java | 68 +- .../recv/HandlerChangeMpTeamAvatarReq.java | 37 +- .../packet/recv/HandlerChangeTeamNameReq.java | 37 +- .../recv/HandlerChooseCurAvatarTeamReq.java | 37 +- .../HandlerClientAbilityInitFinishNotify.java | 64 +- .../recv/HandlerCombatInvocationsNotify.java | 351 +- .../server/packet/recv/HandlerCombineReq.java | 98 +- .../packet/recv/HandlerCreateVehicleReq.java | 45 +- .../packet/recv/HandlerDealAddFriendReq.java | 40 +- .../recv/HandlerDelBackupAvatarTeamReq.java | 32 +- .../server/packet/recv/HandlerDelMailReq.java | 37 +- .../packet/recv/HandlerDeleteFriendReq.java | 37 +- .../recv/HandlerDestroyMaterialReq.java | 39 +- .../server/packet/recv/HandlerDoGachaReq.java | 37 +- .../recv/HandlerDungeonEntryInfoReq.java | 37 +- .../packet/recv/HandlerEnterSceneDoneReq.java | 104 +- .../recv/HandlerEnterSceneReadyReq.java | 37 +- .../HandlerEnterTransPointRegionNotify.java | 28 +- .../packet/recv/HandlerEnterWorldAreaReq.java | 45 +- .../recv/HandlerEntityAiSyncNotify.java | 43 +- ...andlerEvtAiSyncCombatThreatInfoNotify.java | 31 +- .../recv/HandlerEvtAiSyncSkillCdNotify.java | 31 +- .../recv/HandlerEvtAvatarLockChairReq.java | 50 +- .../recv/HandlerEvtAvatarSitDownNotify.java | 40 +- .../recv/HandlerEvtAvatarStandUpNotify.java | 39 +- .../recv/HandlerEvtCreateGadgetNotify.java | 75 +- .../recv/HandlerEvtDestroyGadgetNotify.java | 37 +- ...andlerEvtEntityRenderersChangedNotify.java | 65 +- .../HandlerExitTransPointRegionNotify.java | 28 +- .../recv/HandlerForgeGetQueueDataReq.java | 28 +- .../recv/HandlerForgeQueueManipulateReq.java | 32 +- .../packet/recv/HandlerForgeStartReq.java | 36 +- .../packet/recv/HandlerFurnitureMakeReq.java | 31 +- .../recv/HandlerFurnitureMakeStartReq.java | 38 +- .../packet/recv/HandlerGachaWishReq.java | 62 +- .../packet/recv/HandlerGadgetInteractReq.java | 44 +- .../recv/HandlerGetActivityInfoReq.java | 43 +- .../HandlerGetActivityShopSheetInfoReq.java | 37 +- .../recv/HandlerGetAllH5ActivityInfoReq.java | 33 +- .../packet/recv/HandlerGetAllMailReq.java | 37 +- .../recv/HandlerGetAllUnlockNameCardReq.java | 33 +- .../packet/recv/HandlerGetAuthkeyReq.java | 33 +- .../HandlerGetDailyDungeonEntryInfoReq.java | 39 +- .../HandlerGetFriendShowAvatarInfoReq.java | 52 +- .../HandlerGetFriendShowNameCardInfoReq.java | 46 +- ...rGetFurnitureCurModuleArrangeCountReq.java | 33 +- .../packet/recv/HandlerGetGachaInfoReq.java | 34 +- .../recv/HandlerGetHomeLevelUpRewardReq.java | 82 +- .../HandlerGetInvestigationMonsterReq.java | 47 +- .../packet/recv/HandlerGetMailItemReq.java | 38 +- .../recv/HandlerGetPlayerBlacklistReq.java | 33 +- .../recv/HandlerGetPlayerFriendListReq.java | 32 +- .../recv/HandlerGetPlayerHomeCompInfoReq.java | 33 +- .../recv/HandlerGetPlayerSocialDetailReq.java | 52 +- .../packet/recv/HandlerGetPlayerTokenReq.java | 284 +- .../recv/HandlerGetRegionSearchReq.java | 31 +- .../packet/recv/HandlerGetSceneAreaReq.java | 39 +- .../packet/recv/HandlerGetScenePointReq.java | 39 +- .../server/packet/recv/HandlerGetShopReq.java | 36 +- .../recv/HandlerGetShopmallDataReq.java | 35 +- .../packet/recv/HandlerGetWidgetSlotReq.java | 37 +- .../packet/recv/HandlerGetWorldMpInfoReq.java | 33 +- .../packet/recv/HandlerHitTreeNotify.java | 36 +- .../recv/HandlerHomeChangeEditModeReq.java | 53 +- .../recv/HandlerHomeChangeModuleReq.java | 74 +- .../recv/HandlerHomeChooseModuleReq.java | 51 +- .../HandlerHomeEnterEditModeFinishReq.java | 39 +- .../HandlerHomeGetArrangementInfoReq.java | 40 +- .../recv/HandlerHomeGetBasicInfoReq.java | 35 +- .../HandlerHomeResourceTakeFetterExpReq.java | 35 +- .../HandlerHomeResourceTakeHomeCoinReq.java | 35 +- .../recv/HandlerHomeSceneInitFinishReq.java | 33 +- .../packet/recv/HandlerHomeSceneJumpReq.java | 97 +- .../HandlerHomeUpdateArrangementInfoReq.java | 54 +- .../server/packet/recv/HandlerMarkMapReq.java | 34 +- .../recv/HandlerMcoinExchangeHcoinReq.java | 59 +- .../HandlerMonsterAIConfigHashNotify.java | 31 +- .../HandlerMusicGameCreateBeatmapReq.java | 134 +- .../recv/HandlerMusicGameGetBeatmapReq.java | 62 +- .../HandlerMusicGameSearchBeatmapReq.java | 57 +- .../recv/HandlerMusicGameSettleReq.java | 126 +- .../packet/recv/HandlerMusicGameStartReq.java | 39 +- ...rMusicGameStartToPlayOthersBeatmapReq.java | 41 +- .../server/packet/recv/HandlerNpcTalkReq.java | 119 +- .../recv/HandlerObstacleModifyNotify.java | 31 +- .../recv/HandlerPathfindingEnterSceneReq.java | 37 +- .../recv/HandlerPersonalLineAllDataReq.java | 35 +- .../recv/HandlerPersonalSceneJumpReq.java | 69 +- .../server/packet/recv/HandlerPingReq.java | 47 +- .../recv/HandlerPlayerApplyEnterMpReq.java | 44 +- .../HandlerPlayerApplyEnterMpResultReq.java | 44 +- .../packet/recv/HandlerPlayerChatReq.java | 61 +- .../HandlerPlayerCompoundMaterialReq.java | 33 +- .../packet/recv/HandlerPlayerCookArgsReq.java | 33 +- .../packet/recv/HandlerPlayerCookReq.java | 33 +- .../recv/HandlerPlayerEnterDungeonReq.java | 42 +- .../recv/HandlerPlayerForceExitReq.java | 56 +- .../HandlerPlayerGetForceQuitBanInfoReq.java | 51 +- .../packet/recv/HandlerPlayerLoginReq.java | 103 +- .../recv/HandlerPlayerQuitDungeonReq.java | 31 +- .../packet/recv/HandlerPlayerSetPauseReq.java | 55 +- .../packet/recv/HandlerPostEnterSceneReq.java | 48 +- .../packet/recv/HandlerPrivateChatReq.java | 53 +- .../recv/HandlerPullPrivateChatReq.java | 44 +- .../packet/recv/HandlerPullRecentChatReq.java | 28 +- ...andlerQueryCodexMonsterBeKilledNumReq.java | 38 +- .../packet/recv/HandlerQueryPathReq.java | 48 +- .../recv/HandlerQuestUpdateQuestVarReq.java | 90 +- .../packet/recv/HandlerQuickUseWidgetReq.java | 106 +- .../packet/recv/HandlerReadMailNotify.java | 68 +- .../recv/HandlerReliquaryDecomposeReq.java | 36 +- .../recv/HandlerReliquaryUpgradeReq.java | 44 +- .../recv/HandlerSceneEntityDrownReq.java | 70 +- .../recv/HandlerSceneInitFinishReq.java | 80 +- .../recv/HandlerSceneKickPlayerReq.java | 54 +- .../recv/HandlerSceneTransToPointReq.java | 72 +- .../recv/HandlerSelectWorktopOptionReq.java | 78 +- .../HandlerSetEntityClientDataNotify.java | 57 +- .../recv/HandlerSetEquipLockStateReq.java | 40 +- .../packet/recv/HandlerSetNameCardReq.java | 34 +- .../recv/HandlerSetPlayerBirthdayReq.java | 133 +- .../recv/HandlerSetPlayerBornDataReq.java | 170 +- .../recv/HandlerSetPlayerHeadImageReq.java | 46 +- .../packet/recv/HandlerSetPlayerNameReq.java | 47 +- .../packet/recv/HandlerSetPlayerPropReq.java | 68 +- .../recv/HandlerSetPlayerSignatureReq.java | 47 +- .../recv/HandlerSetUpAvatarTeamReq.java | 40 +- .../recv/HandlerSetUpLunchBoxWidgetReq.java | 37 +- .../packet/recv/HandlerSetWidgetSlotReq.java | 74 +- .../HandlerTakeAchievementGoalRewardReq.java | 33 +- .../recv/HandlerTakeBattlePassRewardReq.java | 34 +- .../recv/HandlerTakeFurnitureMakeReq.java | 40 +- .../recv/HandlerTakePlayerLevelRewardReq.java | 78 +- .../packet/recv/HandlerTakeoffEquipReq.java | 43 +- .../packet/recv/HandlerTowerAllDataReq.java | 38 +- .../recv/HandlerTowerEnterLevelReq.java | 42 +- .../recv/HandlerTowerTeamSelectReq.java | 53 +- .../packet/recv/HandlerTryEnterHomeReq.java | 134 +- .../packet/recv/HandlerUnionCmdNotify.java | 85 +- .../recv/HandlerUnlockAvatarTalentReq.java | 43 +- .../recv/HandlerUnlockPersonalLineReq.java | 55 +- .../recv/HandlerUnlockTransPointReq.java | 48 +- ...ateAbilityCreatedMovingPlatformNotify.java | 66 +- .../HandlerUpdatePlayerShowAvatarListReq.java | 45 +- ...andlerUpdatePlayerShowNameCardListReq.java | 42 +- .../server/packet/recv/HandlerUseItemReq.java | 61 +- .../recv/HandlerVehicleInteractReq.java | 44 +- .../packet/recv/HandlerWeaponAwakenReq.java | 42 +- .../packet/recv/HandlerWeaponPromoteReq.java | 42 +- .../packet/recv/HandlerWeaponUpgradeReq.java | 51 +- .../packet/recv/HandlerWearEquipReq.java | 43 +- .../packet/recv/HandlerWidgetDoBagReq.java | 87 +- .../recv/HandlerWorldPlayerReviveReq.java | 35 +- .../send/PackageTakeCompoundOutputRsp.java | 32 +- .../server/packet/send/Packet.java | 23 +- .../send/PacketAbilityChangeNotify.java | 41 +- .../send/PacketAbilityInvocationsNotify.java | 60 +- .../send/PacketAchievementAllDataNotify.java | 46 +- .../send/PacketAchievementUpdateNotify.java | 40 +- .../packet/send/PacketActivityInfoNotify.java | 38 +- .../PacketActivityScheduleInfoNotify.java | 63 +- .../PacketActivityTakeWatcherRewardRsp.java | 38 +- .../PacketActivityUpdateWatcherNotify.java | 40 +- .../send/PacketAddBackupAvatarTeamRsp.java | 43 +- .../PacketAddQuestContentProgressRsp.java | 37 +- .../send/PacketAllWidgetDataNotify.java | 113 +- .../packet/send/PacketAskAddFriendNotify.java | 41 +- .../packet/send/PacketAskAddFriendRsp.java | 34 +- .../packet/send/PacketAvatarAddNotify.java | 38 +- .../send/PacketAvatarChangeCostumeNotify.java | 37 +- .../send/PacketAvatarChangeCostumeRsp.java | 62 +- .../PacketAvatarChangeElementTypeRsp.java | 47 +- .../packet/send/PacketAvatarDataNotify.java | 80 +- .../send/PacketAvatarDieAnimationEndRsp.java | 36 +- .../send/PacketAvatarEquipChangeNotify.java | 80 +- .../PacketAvatarExpeditionAllDataRsp.java | 58 +- .../PacketAvatarExpeditionCallBackRsp.java | 37 +- .../PacketAvatarExpeditionDataNotify.java | 45 +- .../PacketAvatarExpeditionGetRewardRsp.java | 44 +- .../send/PacketAvatarExpeditionStartRsp.java | 37 +- .../send/PacketAvatarFetterDataNotify.java | 98 +- .../PacketAvatarFetterLevelRewardRsp.java | 71 +- .../send/PacketAvatarFightPropNotify.java | 41 +- .../PacketAvatarFightPropUpdateNotify.java | 43 +- .../PacketAvatarFlycloakChangeNotify.java | 41 +- .../send/PacketAvatarGainCostumeNotify.java | 35 +- .../send/PacketAvatarGainFlycloakNotify.java | 35 +- .../PacketAvatarLifeStateChangeNotify.java | 125 +- .../packet/send/PacketAvatarPromoteRsp.java | 36 +- .../packet/send/PacketAvatarPropNotify.java | 99 +- .../send/PacketAvatarSatiationDataNotify.java | 94 +- .../send/PacketAvatarSkillChangeNotify.java | 49 +- .../PacketAvatarSkillDepotChangeNotify.java | 53 +- .../send/PacketAvatarSkillInfoNotify.java | 42 +- ...PacketAvatarSkillMaxChargeCountNotify.java | 43 +- .../send/PacketAvatarSkillUpgradeRsp.java | 45 +- .../send/PacketAvatarTeamAllDataNotify.java | 55 +- .../send/PacketAvatarTeamUpdateNotify.java | 41 +- .../send/PacketAvatarUnlockTalentNotify.java | 45 +- .../packet/send/PacketAvatarUpgradeRsp.java | 54 +- .../send/PacketAvatarWearFlycloakRsp.java | 60 +- .../packet/send/PacketBackMyWorldRsp.java | 32 +- .../send/PacketBattlePassAllDataNotify.java | 70 +- ...cketBattlePassCurScheduleUpdateNotify.java | 45 +- .../PacketBattlePassMissionUpdateNotify.java | 66 +- .../send/PacketBlossomBriefInfoNotify.java | 29 +- .../send/PacketBuyBattlePassLevelRsp.java | 34 +- .../server/packet/send/PacketBuyGoodsRsp.java | 44 +- ...PacketCalcWeaponUpgradeReturnItemsRsp.java | 67 +- .../packet/send/PacketCanUseSkillNotify.java | 38 +- .../send/PacketCardProductRewardNotify.java | 47 +- .../send/PacketChallengeDataNotify.java | 43 +- .../packet/send/PacketChangeAvatarRsp.java | 41 +- .../packet/send/PacketChangeGameTimeRsp.java | 37 +- .../send/PacketChangeMpTeamAvatarRsp.java | 47 +- .../packet/send/PacketChangeTeamNameRsp.java | 36 +- .../packet/send/PacketChapterStateNotify.java | 39 +- .../send/PacketChooseCurAvatarTeamRsp.java | 34 +- .../PacketClientAbilityInitFinishNotify.java | 58 +- .../send/PacketCodexDataFullNotify.java | 210 +- .../send/PacketCodexDataUpdateNotify.java | 56 +- .../send/PacketCombatInvocationsNotify.java | 60 +- .../packet/send/PacketCombineDataNotify.java | 35 +- .../send/PacketCombineFormulaDataNotify.java | 36 +- .../server/packet/send/PacketCombineRsp.java | 114 +- .../packet/send/PacketCompoundDataNotify.java | 43 +- .../packet/send/PacketCookDataNotify.java | 39 +- .../send/PacketCookRecipeDataNotify.java | 55 +- .../packet/send/PacketCreateVehicleRsp.java | 108 +- .../packet/send/PacketDealAddFriendRsp.java | 41 +- .../send/PacketDelBackupAvatarTeamRsp.java | 47 +- .../server/packet/send/PacketDelMailRsp.java | 39 +- .../send/PacketDelTeamEntityNotify.java | 62 +- .../packet/send/PacketDeleteFriendNotify.java | 34 +- .../packet/send/PacketDeleteFriendRsp.java | 34 +- .../packet/send/PacketDestroyMaterialRsp.java | 45 +- .../server/packet/send/PacketDoGachaRsp.java | 135 +- .../PacketDungeonChallengeBeginNotify.java | 45 +- .../PacketDungeonChallengeFinishNotify.java | 43 +- .../send/PacketDungeonEntryInfoRsp.java | 72 +- .../send/PacketDungeonSettleNotify.java | 126 +- .../send/PacketDungeonShowReminderNotify.java | 36 +- .../packet/send/PacketEnterSceneDoneRsp.java | 37 +- .../send/PacketEnterScenePeerNotify.java | 45 +- .../packet/send/PacketEnterSceneReadyRsp.java | 37 +- .../packet/send/PacketEnterWorldAreaRsp.java | 41 +- .../packet/send/PacketEntityAiSyncNotify.java | 42 +- ...cketEntityFightPropChangeReasonNotify.java | 160 +- .../PacketEntityFightPropUpdateNotify.java | 43 +- .../send/PacketEvtAvatarLockChairRsp.java | 48 +- .../send/PacketEvtAvatarSitDownNotify.java | 41 +- .../send/PacketEvtAvatarStandUpNotify.java | 43 +- ...PacketEvtEntityRenderersChangedNotify.java | 29 +- .../send/PacketFinishedParentQuestNotify.java | 52 +- ...PacketFinishedParentQuestUpdateNotify.java | 64 +- .../packet/send/PacketForgeDataNotify.java | 51 +- .../send/PacketForgeFormulaDataNotify.java | 36 +- .../send/PacketForgeGetQueueDataRsp.java | 53 +- .../send/PacketForgeQueueDataNotify.java | 52 +- .../send/PacketForgeQueueManipulateRsp.java | 89 +- .../packet/send/PacketForgeStartRsp.java | 36 +- ...tFurnitureCurModuleArrangeCountNotify.java | 38 +- .../packet/send/PacketFurnitureMakeRsp.java | 52 +- .../send/PacketFurnitureMakeStartRsp.java | 57 +- .../packet/send/PacketGachaWishRsp.java | 47 +- .../PacketGadgetAutoPickDropInfoNotify.java | 41 +- .../packet/send/PacketGadgetInteractRsp.java | 83 +- .../packet/send/PacketGadgetStateNotify.java | 43 +- .../packet/send/PacketGetActivityInfoRsp.java | 43 +- .../PacketGetActivityShopSheetInfoRsp.java | 102 +- .../packet/send/PacketGetAllMailRsp.java | 165 +- .../send/PacketGetAllUnlockNameCardRsp.java | 37 +- .../packet/send/PacketGetAuthkeyRsp.java | 37 +- .../send/PacketGetChatEmojiCollectionRsp.java | 43 +- .../packet/send/PacketGetCompoundDataRsp.java | 45 +- .../PacketGetDailyDungeonEntryInfoRsp.java | 83 +- .../PacketGetFriendShowAvatarInfoRsp.java | 47 +- .../PacketGetFriendShowNameCardInfoRsp.java | 42 +- .../packet/send/PacketGetGachaInfoRsp.java | 31 +- .../send/PacketGetHomeLevelUpRewardRsp.java | 48 +- .../PacketGetInvestigationMonsterRsp.java | 49 +- .../packet/send/PacketGetMailItemRsp.java | 139 +- .../send/PacketGetOnlinePlayerListRsp.java | 58 +- .../send/PacketGetPlayerAskFriendListRsp.java | 50 +- .../send/PacketGetPlayerFriendListRsp.java | 92 +- .../send/PacketGetPlayerSocialDetailRsp.java | 48 +- .../packet/send/PacketGetPlayerTokenRsp.java | 162 +- .../packet/send/PacketGetSceneAreaRsp.java | 53 +- .../packet/send/PacketGetScenePointRsp.java | 65 +- .../server/packet/send/PacketGetShopRsp.java | 169 +- .../packet/send/PacketGetShopmallDataRsp.java | 42 +- .../packet/send/PacketGetWidgetSlotRsp.java | 81 +- .../packet/send/PacketGetWorldMpInfoRsp.java | 37 +- .../packet/send/PacketGroupSuiteNotify.java | 97 +- .../packet/send/PacketGroupUnloadNotify.java | 39 +- .../send/PacketH5ActivityIdsNotify.java | 33 +- .../PacketHomeAllUnlockedBgmIdListNotify.java | 49 +- .../send/PacketHomeBasicInfoNotify.java | 73 +- .../send/PacketHomeChangeBgmNotify.java | 33 +- .../packet/send/PacketHomeChangeBgmRsp.java | 32 +- .../send/PacketHomeChangeEditModeRsp.java | 36 +- .../send/PacketHomeChangeModuleRsp.java | 39 +- .../send/PacketHomeChooseModuleRsp.java | 39 +- .../send/PacketHomeComfortInfoNotify.java | 94 +- .../PacketHomeEnterEditModeFinishRsp.java | 23 +- .../send/PacketHomeGetArrangementInfoRsp.java | 59 +- .../send/PacketHomeMarkPointNotify.java | 91 +- .../packet/send/PacketHomeModuleSeenRsp.java | 37 +- .../send/PacketHomeModuleUnlockNotify.java | 35 +- .../PacketHomeNewUnlockedBgmIdListNotify.java | 35 +- .../packet/send/PacketHomeResourceNotify.java | 73 +- .../PacketHomeResourceTakeFetterExpRsp.java | 60 +- .../PacketHomeResourceTakeHomeCoinRsp.java | 60 +- .../send/PacketHomeSceneInitFinishRsp.java | 33 +- .../packet/send/PacketHomeSceneJumpRsp.java | 36 +- .../PacketHomeUpdateArrangementInfoRsp.java | 23 +- .../packet/send/PacketHostPlayerNotify.java | 41 +- .../packet/send/PacketItemAddHintNotify.java | 71 +- .../packet/send/PacketLaunchFireworksRsp.java | 24 +- .../send/PacketLifeStateChangeNotify.java | 141 +- .../packet/send/PacketMailChangeNotify.java | 150 +- .../server/packet/send/PacketMarkMapRsp.java | 69 +- .../packet/send/PacketMarkNewNotify.java | 41 +- .../send/PacketMcoinExchangeHcoinRsp.java | 37 +- .../send/PacketMusicGameCreateBeatmapRsp.java | 41 +- .../send/PacketMusicGameGetBeatmapRsp.java | 56 +- .../send/PacketMusicGameSearchBeatmapRsp.java | 70 +- .../packet/send/PacketMusicGameSettleRsp.java | 38 +- .../packet/send/PacketMusicGameStartRsp.java | 37 +- ...tMusicGameStartToPlayOthersBeatmapRsp.java | 41 +- .../server/packet/send/PacketNpcTalkRsp.java | 39 +- .../send/PacketOpenStateChangeNotify.java | 60 +- .../send/PacketPathfindingEnterSceneRsp.java | 22 +- .../send/PacketPersonalLineAllDataRsp.java | 68 +- .../send/PacketPersonalSceneJumpRsp.java | 38 +- .../server/packet/send/PacketPingRsp.java | 34 +- .../send/PacketPlatformStartRouteNotify.java | 43 +- .../send/PacketPlatformStopRouteNotify.java | 43 +- .../send/PacketPlayerApplyEnterMpNotify.java | 39 +- .../PacketPlayerApplyEnterMpResultNotify.java | 81 +- .../PacketPlayerApplyEnterMpResultRsp.java | 39 +- .../send/PacketPlayerApplyEnterMpRsp.java | 35 +- .../packet/send/PacketPlayerChatNotify.java | 119 +- .../packet/send/PacketPlayerChatRsp.java | 32 +- .../send/PacketPlayerCompoundMaterialRsp.java | 73 +- .../packet/send/PacketPlayerCookArgsRsp.java | 33 +- .../packet/send/PacketPlayerCookRsp.java | 85 +- .../packet/send/PacketPlayerDataNotify.java | 57 +- .../send/PacketPlayerEnterDungeonRsp.java | 36 +- .../PacketPlayerEnterSceneInfoNotify.java | 115 +- .../send/PacketPlayerEnterSceneNotify.java | 168 +- .../send/PacketPlayerGameTimeNotify.java | 41 +- .../PacketPlayerGetForceQuitBanInfoRsp.java | 35 +- .../send/PacketPlayerHomeCompInfoNotify.java | 64 +- .../PacketPlayerLevelRewardUpdateNotify.java | 43 +- .../packet/send/PacketPlayerLoginRsp.java | 144 +- .../send/PacketPlayerPropChangeNotify.java | 44 +- .../PacketPlayerPropChangeReasonNotify.java | 58 +- .../packet/send/PacketPlayerPropNotify.java | 47 +- .../packet/send/PacketPlayerSetPauseRsp.java | 26 +- .../packet/send/PacketPlayerStoreNotify.java | 63 +- .../packet/send/PacketPlayerTimeNotify.java | 43 +- .../PacketPlayerWorldSceneInfoListNotify.java | 147 +- .../packet/send/PacketPostEnterSceneRsp.java | 37 +- .../packet/send/PacketPrivateChatNotify.java | 98 +- .../send/PacketProudSkillChangeNotify.java | 45 +- .../PacketProudSkillExtraLevelNotify.java | 45 +- .../packet/send/PacketPullPrivateChatRsp.java | 55 +- .../packet/send/PacketPullRecentChatRsp.java | 36 +- ...PacketQueryCodexMonsterBeKilledNumRsp.java | 53 +- .../packet/send/PacketQueryPathRsp.java | 50 +- .../packet/send/PacketQuestListNotify.java | 51 +- .../send/PacketQuestListUpdateNotify.java | 62 +- .../send/PacketQuestProgressUpdateNotify.java | 59 +- .../send/PacketQuestUpdateQuestVarRsp.java | 37 +- .../send/PacketReliquaryDecomposeRsp.java | 56 +- .../send/PacketReliquaryUpgradeRsp.java | 53 +- .../packet/send/PacketResinChangeNotify.java | 47 +- .../send/PacketSceneAreaUnlockNotify.java | 52 +- .../send/PacketSceneAreaWeatherNotify.java | 41 +- .../send/PacketSceneEntityAppearNotify.java | 100 +- .../PacketSceneEntityDisappearNotify.java | 69 +- .../send/PacketSceneEntityDrownRsp.java | 2 - .../send/PacketSceneEntityMoveNotify.java | 45 +- .../packet/send/PacketSceneInitFinishRsp.java | 35 +- .../packet/send/PacketSceneKickPlayerRsp.java | 57 +- .../send/PacketScenePlayerInfoNotify.java | 67 +- .../send/PacketScenePlayerLocationNotify.java | 46 +- .../send/PacketScenePointUnlockNotify.java | 60 +- .../send/PacketSceneTeamUpdateNotify.java | 93 +- .../packet/send/PacketSceneTimeNotify.java | 43 +- .../send/PacketSceneTransToPointRsp.java | 66 +- .../send/PacketSelectWorktopOptionRsp.java | 39 +- .../send/PacketServerAnnounceNotify.java | 76 +- .../PacketServerAnnounceRevokeNotify.java | 36 +- .../send/PacketServerBuffChangeNotify.java | 77 +- .../packet/send/PacketServerTimeNotify.java | 35 +- .../send/PacketSetBattlePassViewedRsp.java | 35 +- .../send/PacketSetEquipLockStateRsp.java | 45 +- .../packet/send/PacketSetNameCardRsp.java | 34 +- .../packet/send/PacketSetOpenStateRsp.java | 50 +- .../send/PacketSetPlayerBirthdayRsp.java | 55 +- .../send/PacketSetPlayerHeadImageRsp.java | 41 +- .../packet/send/PacketSetPlayerNameRsp.java | 37 +- .../packet/send/PacketSetPlayerPropRsp.java | 35 +- .../send/PacketSetPlayerSignatureRsp.java | 37 +- .../packet/send/PacketSetUpAvatarTeamRsp.java | 49 +- .../send/PacketSetUpLunchBoxWidgetRsp.java | 35 +- .../packet/send/PacketSetWidgetSlotRsp.java | 35 +- .../send/PacketSkipPlayerGameTimeRsp.java | 39 +- .../send/PacketStoreItemChangeNotify.java | 74 +- .../packet/send/PacketStoreItemDelNotify.java | 74 +- .../send/PacketStoreWeightLimitNotify.java | 53 +- .../PacketSyncScenePlayTeamEntityNotify.java | 37 +- .../send/PacketSyncTeamEntityNotify.java | 77 +- .../PacketTakeAchievementGoalRewardRsp.java | 60 +- .../send/PacketTakeAchievementRewardReq.java | 35 +- .../send/PacketTakeAchievementRewardRsp.java | 60 +- .../PacketTakeBattlePassMissionPointRsp.java | 20 +- .../send/PacketTakeBattlePassRewardRsp.java | 54 +- .../send/PacketTakeFurnitureMakeRsp.java | 74 +- .../send/PacketTakePlayerLevelRewardRsp.java | 53 +- .../packet/send/PacketTakeoffEquipRsp.java | 36 +- .../packet/send/PacketTowerAllDataRsp.java | 138 +- ...PacketTowerCurLevelRecordChangeNotify.java | 48 +- .../packet/send/PacketTowerEnterLevelRsp.java | 45 +- .../PacketTowerFloorRecordChangeNotify.java | 63 +- .../send/PacketTowerLevelStarCondNotify.java | 65 +- ...acketTowerMiddleLevelChangeTeamNotify.java | 36 +- .../packet/send/PacketTowerTeamSelectRsp.java | 33 +- .../packet/send/PacketTryEnterHomeRsp.java | 85 +- .../send/PacketUnlockAvatarTalentRsp.java | 41 +- .../send/PacketUnlockNameCardNotify.java | 34 +- .../send/PacketUnlockPersonalLineRsp.java | 38 +- .../send/PacketUnlockTransPointRsp.java | 35 +- ...ketUnlockedFurnitureFormulaDataNotify.java | 43 +- ...acketUnlockedFurnitureSuiteDataNotify.java | 42 +- .../PacketUpdatePlayerShowAvatarListRsp.java | 44 +- ...PacketUpdatePlayerShowNameCardListRsp.java | 40 +- .../server/packet/send/PacketUseItemRsp.java | 62 +- .../packet/send/PacketVehicleInteractRsp.java | 134 +- .../send/PacketVehicleStaminaNotify.java | 36 +- .../packet/send/PacketWeaponAwakenRsp.java | 60 +- .../packet/send/PacketWeaponPromoteRsp.java | 43 +- .../packet/send/PacketWeaponUpgradeRsp.java | 50 +- .../packet/send/PacketWearEquipRsp.java | 36 +- .../send/PacketWidgetCoolDownNotify.java | 50 +- .../packet/send/PacketWidgetDoBagRsp.java | 57 +- .../send/PacketWidgetGadgetDataNotify.java | 84 +- .../send/PacketWidgetSlotChangeNotify.java | 91 +- .../send/PacketWorktopOptionNotify.java | 46 +- .../packet/send/PacketWorldDataNotify.java | 51 +- .../send/PacketWorldPlayerDieNotify.java | 38 +- .../send/PacketWorldPlayerInfoNotify.java | 50 +- .../send/PacketWorldPlayerLocationNotify.java | 44 +- .../send/PacketWorldPlayerRTTNotify.java | 54 +- .../send/PacketWorldPlayerReviveRsp.java | 32 +- .../server/scheduler/AsyncServerTask.java | 206 +- .../server/scheduler/ServerTask.java | 132 +- .../server/scheduler/ServerTaskScheduler.java | 307 +- src/main/java/emu/grasscutter/task/Task.java | 71 +- .../emu/grasscutter/task/TaskHandler.java | 32 +- .../java/emu/grasscutter/task/TaskMap.java | 346 +- .../task/tasks/AnnouncementTask.java | 118 +- .../emu/grasscutter/task/tasks/MoonCard.java | 69 +- .../java/emu/grasscutter/tools/Dumpers.java | 32 +- .../java/emu/grasscutter/tools/Tools.java | 717 +-- .../java/emu/grasscutter/utils/Crypto.java | 152 +- .../emu/grasscutter/utils/DateHelper.java | 40 +- .../java/emu/grasscutter/utils/FileUtils.java | 515 +-- .../utils/JlineLogbackAppender.java | 36 +- .../emu/grasscutter/utils/JsonAdapters.java | 348 +- .../java/emu/grasscutter/utils/JsonUtils.java | 247 +- .../java/emu/grasscutter/utils/Language.java | 979 +++-- .../java/emu/grasscutter/utils/Location.java | 83 +- .../emu/grasscutter/utils/MessageHandler.java | 42 +- .../java/emu/grasscutter/utils/Position.java | 397 +- .../emu/grasscutter/utils/ProtoHelper.java | 20 +- .../utils/ServerLogEventAppender.java | 54 +- .../java/emu/grasscutter/utils/SparseSet.java | 126 +- .../grasscutter/utils/StartupArguments.java | 260 +- .../java/emu/grasscutter/utils/TsvUtils.java | 1272 +++--- .../java/emu/grasscutter/utils/Utils.java | 885 ++-- .../emu/grasscutter/utils/WeightedList.java | 58 +- 1003 files changed, 60650 insertions(+), 58050 deletions(-) diff --git a/src/main/java/emu/grasscutter/GameConstants.java b/src/main/java/emu/grasscutter/GameConstants.java index 8bf50c831..4741f81c4 100644 --- a/src/main/java/emu/grasscutter/GameConstants.java +++ b/src/main/java/emu/grasscutter/GameConstants.java @@ -1,30 +1,35 @@ -package emu.grasscutter; - -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.Utils; - -import java.util.Arrays; - -public final class GameConstants { - public static final int DEFAULT_TEAMS = 4; - public static final int MAX_TEAMS = 10; - public static final int MAIN_CHARACTER_MALE = 10000005; - public static final int MAIN_CHARACTER_FEMALE = 10000007; - public static final Position START_POSITION = new Position(2747, 194, -1719); - public static final int MAX_FRIENDS = 60; - public static final int MAX_FRIEND_REQUESTS = 50; - public static final int SERVER_CONSOLE_UID = 99; // The UID of the server console's "player". - public static final int BATTLE_PASS_MAX_LEVEL = 50; - public static final int BATTLE_PASS_POINT_PER_LEVEL = 1000; - public static final int BATTLE_PASS_POINT_PER_WEEK = 10000; - public static final int BATTLE_PASS_LEVEL_PRICE = 150; - public static final int BATTLE_PASS_CURRENT_INDEX = 2; - // Default entity ability hashes. - public static final String[] DEFAULT_ABILITY_STRINGS = { - "Avatar_DefaultAbility_VisionReplaceDieInvincible", "Avatar_DefaultAbility_AvartarInShaderChange", "Avatar_SprintBS_Invincible", - "Avatar_Freeze_Duration_Reducer", "Avatar_Attack_ReviveEnergy", "Avatar_Component_Initializer", "Avatar_FallAnthem_Achievement_Listener" - }; - public static final int[] DEFAULT_ABILITY_HASHES = Arrays.stream(DEFAULT_ABILITY_STRINGS).mapToInt(Utils::abilityHash).toArray(); - public static final int DEFAULT_ABILITY_NAME = Utils.abilityHash("Default"); - public static String VERSION = "3.5.0"; -} +package emu.grasscutter; + +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; +import java.util.Arrays; + +public final class GameConstants { + public static final int DEFAULT_TEAMS = 4; + public static final int MAX_TEAMS = 10; + public static final int MAIN_CHARACTER_MALE = 10000005; + public static final int MAIN_CHARACTER_FEMALE = 10000007; + public static final Position START_POSITION = new Position(2747, 194, -1719); + public static final int MAX_FRIENDS = 60; + public static final int MAX_FRIEND_REQUESTS = 50; + public static final int SERVER_CONSOLE_UID = 99; // The UID of the server console's "player". + public static final int BATTLE_PASS_MAX_LEVEL = 50; + public static final int BATTLE_PASS_POINT_PER_LEVEL = 1000; + public static final int BATTLE_PASS_POINT_PER_WEEK = 10000; + public static final int BATTLE_PASS_LEVEL_PRICE = 150; + public static final int BATTLE_PASS_CURRENT_INDEX = 2; + // Default entity ability hashes. + public static final String[] DEFAULT_ABILITY_STRINGS = { + "Avatar_DefaultAbility_VisionReplaceDieInvincible", + "Avatar_DefaultAbility_AvartarInShaderChange", + "Avatar_SprintBS_Invincible", + "Avatar_Freeze_Duration_Reducer", + "Avatar_Attack_ReviveEnergy", + "Avatar_Component_Initializer", + "Avatar_FallAnthem_Achievement_Listener" + }; + public static final int[] DEFAULT_ABILITY_HASHES = + Arrays.stream(DEFAULT_ABILITY_STRINGS).mapToInt(Utils::abilityHash).toArray(); + public static final int DEFAULT_ABILITY_NAME = Utils.abilityHash("Default"); + public static String VERSION = "3.5.0"; +} diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index 6d04a8adf..f4240c565 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -1,323 +1,322 @@ -package emu.grasscutter; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import emu.grasscutter.auth.AuthenticationSystem; -import emu.grasscutter.auth.DefaultAuthentication; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.command.DefaultPermissionHandler; -import emu.grasscutter.command.PermissionHandler; -import emu.grasscutter.config.ConfigContainer; -import emu.grasscutter.data.ResourceLoader; -import emu.grasscutter.database.DatabaseManager; -import emu.grasscutter.plugin.PluginManager; -import emu.grasscutter.plugin.api.ServerHook; -import emu.grasscutter.scripts.ScriptLoader; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.http.HttpServer; -import emu.grasscutter.server.http.dispatch.DispatchHandler; -import emu.grasscutter.server.http.dispatch.RegionHandler; -import emu.grasscutter.server.http.documentation.DocumentationServerHandler; -import emu.grasscutter.server.http.handlers.AnnouncementsHandler; -import emu.grasscutter.server.http.handlers.GachaHandler; -import emu.grasscutter.server.http.handlers.GenericHandler; -import emu.grasscutter.server.http.handlers.LogHandler; -import emu.grasscutter.tools.Tools; -import emu.grasscutter.utils.*; -import lombok.Getter; -import lombok.Setter; -import org.jline.reader.EndOfFileException; -import org.jline.reader.LineReader; -import org.jline.reader.LineReaderBuilder; -import org.jline.reader.UserInterruptException; -import org.jline.terminal.Terminal; -import org.jline.terminal.TerminalBuilder; -import org.reflections.Reflections; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.io.File; -import java.io.FileWriter; -import java.io.IOError; -import java.io.IOException; -import java.util.Calendar; - -import static emu.grasscutter.config.Configuration.SERVER; -import static emu.grasscutter.utils.Language.translate; - -public final class Grasscutter { - public static final File configFile = new File("./config.json"); - public static final Reflections reflector = new Reflections("emu.grasscutter"); - @Getter private static final Logger logger = - (Logger) LoggerFactory.getLogger(Grasscutter.class); - - @Getter public static ConfigContainer config; - - @Getter @Setter private static Language language; - @Getter @Setter private static String preferredLanguage; - - @Getter private static int currentDayOfWeek; - @Setter private static ServerRunMode runModeOverride = null; // Config override for run mode - - @Getter private static HttpServer httpServer; - @Getter private static GameServer gameServer; - @Getter private static PluginManager pluginManager; - @Getter private static CommandMap commandMap; - - @Getter @Setter private static AuthenticationSystem authenticationSystem; - @Getter @Setter private static PermissionHandler permissionHandler; - - private static LineReader consoleLineReader = null; - - static { - // Declare logback configuration. - System.setProperty("logback.configurationFile", "src/main/resources/logback.xml"); - - // Disable the MongoDB logger. - var mongoLogger = (Logger) LoggerFactory.getLogger("org.mongodb.driver"); - mongoLogger.setLevel(Level.OFF); - - // Load server configuration. - Grasscutter.loadConfig(); - // Attempt to update configuration. - ConfigContainer.updateConfig(); - - // Load translation files. - Grasscutter.loadLanguage(); - - // Check server structure. - Utils.startupCheck(); - } - - public static void main(String[] args) throws Exception { - Crypto.loadKeys(); // Load keys from buffers. - - // Parse start-up arguments. - if (StartupArguments.parse(args)) { - System.exit(0); // Exit early. - } - - // Create command map. - commandMap = new CommandMap(true); - - // Initialize server. - logger.info(translate("messages.status.starting")); - logger.info(translate("messages.status.game_version", GameConstants.VERSION)); - logger.info(translate("messages.status.version", BuildConfig.VERSION, BuildConfig.GIT_HASH)); - - // Load all resources. - Grasscutter.updateDayOfWeek(); - ResourceLoader.loadAll(); - ScriptLoader.init(); - - // Generate handbooks. - Tools.createGmHandbooks(false); - - // Initialize database. - DatabaseManager.initialize(); - - // Initialize the default systems. - authenticationSystem = new DefaultAuthentication(); - permissionHandler = new DefaultPermissionHandler(); - - // Create server instances. - httpServer = new HttpServer(); - gameServer = new GameServer(); - // Create a server hook instance with both servers. - new ServerHook(gameServer, httpServer); - - // Create plugin manager instance. - pluginManager = new PluginManager(); - // Add HTTP routes after loading plugins. - httpServer.addRouter(HttpServer.UnhandledRequestRouter.class); - httpServer.addRouter(HttpServer.DefaultRequestRouter.class); - httpServer.addRouter(RegionHandler.class); - httpServer.addRouter(LogHandler.class); - httpServer.addRouter(GenericHandler.class); - httpServer.addRouter(AnnouncementsHandler.class); - httpServer.addRouter(DispatchHandler.class); - httpServer.addRouter(GachaHandler.class); - httpServer.addRouter(DocumentationServerHandler.class); - - // Start servers. - var runMode = Grasscutter.getRunMode(); - if (runMode == ServerRunMode.HYBRID) { - httpServer.start(); - gameServer.start(); - } else if (runMode == ServerRunMode.DISPATCH_ONLY) { - httpServer.start(); - } else if (runMode == ServerRunMode.GAME_ONLY) { - gameServer.start(); - } else { - logger.error(translate("messages.status.run_mode_error", runMode)); - logger.error(translate("messages.status.run_mode_help")); - logger.error(translate("messages.status.shutdown")); - System.exit(1); - } - - // Enable all plugins. - pluginManager.enablePlugins(); - - // Hook into shutdown event. - Runtime.getRuntime().addShutdownHook(new Thread(Grasscutter::onShutdown)); - - // Open console. - Grasscutter.startConsole(); - } - - /** - * Server shutdown event. - */ - private static void onShutdown() { - // Disable all plugins. - if (pluginManager != null) - pluginManager.disablePlugins(); - } - - /* - * Methods for the language system component. - */ - - public static void loadLanguage() { - var locale = config.language.language; - language = Language.getLanguage(Utils.getLanguageCode(locale)); - } - - /* - * Methods for the configuration system component. - */ - - /** - * Attempts to load the configuration from a file. - */ - public static void loadConfig() { - // Check if config.json exists. If not, we generate a new config. - if (!configFile.exists()) { - getLogger().info("config.json could not be found. Generating a default configuration ..."); - config = new ConfigContainer(); - Grasscutter.saveConfig(config); - return; - } - - // If the file already exists, we attempt to load it. - try { - config = JsonUtils.loadToClass(configFile.toPath(), ConfigContainer.class); - } catch (Exception exception) { - getLogger().error("There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); - System.exit(1); - } - } - - /** - * Saves the provided server configuration. - * - * @param config The configuration to save, or null for a new one. - */ - public static void saveConfig(@Nullable ConfigContainer config) { - if (config == null) config = new ConfigContainer(); - - try (FileWriter file = new FileWriter(configFile)) { - file.write(JsonUtils.encode(config)); - } catch (IOException ignored) { - logger.error("Unable to write to config file."); - } catch (Exception e) { - logger.error("Unable to save config file.", e); - } - } - - /* - * Getters for the various server components. - */ - - public static Language getLanguage(String langCode) { - return Language.getLanguage(langCode); - } - - public static ServerRunMode getRunMode() { - return Grasscutter.runModeOverride != null ? Grasscutter.runModeOverride : SERVER.runMode; - } - - public static LineReader getConsole() { - if (consoleLineReader == null) { - Terminal terminal = null; - try { - terminal = TerminalBuilder.builder().jna(true).build(); - } catch (Exception e) { - try { - // Fallback to a dumb jline terminal. - terminal = TerminalBuilder.builder().dumb(true).build(); - } catch (Exception ignored) { - // When dumb is true, build() never throws. - } - } - - consoleLineReader = LineReaderBuilder.builder() - .terminal(terminal) - .build(); - } - - return consoleLineReader; - } - - /* - * Utility methods. - */ - - public static void updateDayOfWeek() { - Calendar calendar = Calendar.getInstance(); - Grasscutter.currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - logger.debug("Set day of week to " + currentDayOfWeek); - } - - public static void startConsole() { - // Console should not start in dispatch only mode. - if (SERVER.runMode == ServerRunMode.DISPATCH_ONLY) { - logger.info(translate("messages.dispatch.no_commands_error")); - return; - } else { - logger.info(translate("messages.status.done")); - } - - String input = null; - var isLastInterrupted = false; - while (config.server.game.enableConsole) { - try { - input = consoleLineReader.readLine("> "); - } catch (UserInterruptException e) { - if (!isLastInterrupted) { - isLastInterrupted = true; - logger.info("Press Ctrl-C again to shutdown."); - continue; - } else { - Runtime.getRuntime().exit(0); - } - } catch (EndOfFileException e) { - logger.info("EOF detected."); - continue; - } catch (IOError e) { - logger.error("An IO error occurred while trying to read from console.", e); - return; - } - - isLastInterrupted = false; - - try { - commandMap.invoke(null, null, input); - } catch (Exception e) { - logger.error(translate("messages.game.command_error"), e); - } - } - } - - /* - * Enums for the configuration. - */ - - public enum ServerRunMode { - HYBRID, DISPATCH_ONLY, GAME_ONLY - } - - public enum ServerDebugMode { - ALL, MISSING, WHITELIST, BLACKLIST, NONE - } -} +package emu.grasscutter; + +import static emu.grasscutter.config.Configuration.SERVER; +import static emu.grasscutter.utils.Language.translate; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import emu.grasscutter.auth.AuthenticationSystem; +import emu.grasscutter.auth.DefaultAuthentication; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.command.DefaultPermissionHandler; +import emu.grasscutter.command.PermissionHandler; +import emu.grasscutter.config.ConfigContainer; +import emu.grasscutter.data.ResourceLoader; +import emu.grasscutter.database.DatabaseManager; +import emu.grasscutter.plugin.PluginManager; +import emu.grasscutter.plugin.api.ServerHook; +import emu.grasscutter.scripts.ScriptLoader; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.http.HttpServer; +import emu.grasscutter.server.http.dispatch.DispatchHandler; +import emu.grasscutter.server.http.dispatch.RegionHandler; +import emu.grasscutter.server.http.documentation.DocumentationServerHandler; +import emu.grasscutter.server.http.handlers.AnnouncementsHandler; +import emu.grasscutter.server.http.handlers.GachaHandler; +import emu.grasscutter.server.http.handlers.GenericHandler; +import emu.grasscutter.server.http.handlers.LogHandler; +import emu.grasscutter.tools.Tools; +import emu.grasscutter.utils.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOError; +import java.io.IOException; +import java.util.Calendar; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import org.jline.reader.EndOfFileException; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.UserInterruptException; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; +import org.reflections.Reflections; +import org.slf4j.LoggerFactory; + +public final class Grasscutter { + public static final File configFile = new File("./config.json"); + public static final Reflections reflector = new Reflections("emu.grasscutter"); + @Getter private static final Logger logger = (Logger) LoggerFactory.getLogger(Grasscutter.class); + + @Getter public static ConfigContainer config; + + @Getter @Setter private static Language language; + @Getter @Setter private static String preferredLanguage; + + @Getter private static int currentDayOfWeek; + @Setter private static ServerRunMode runModeOverride = null; // Config override for run mode + + @Getter private static HttpServer httpServer; + @Getter private static GameServer gameServer; + @Getter private static PluginManager pluginManager; + @Getter private static CommandMap commandMap; + + @Getter @Setter private static AuthenticationSystem authenticationSystem; + @Getter @Setter private static PermissionHandler permissionHandler; + + private static LineReader consoleLineReader = null; + + static { + // Declare logback configuration. + System.setProperty("logback.configurationFile", "src/main/resources/logback.xml"); + + // Disable the MongoDB logger. + var mongoLogger = (Logger) LoggerFactory.getLogger("org.mongodb.driver"); + mongoLogger.setLevel(Level.OFF); + + // Load server configuration. + Grasscutter.loadConfig(); + // Attempt to update configuration. + ConfigContainer.updateConfig(); + + // Load translation files. + Grasscutter.loadLanguage(); + + // Check server structure. + Utils.startupCheck(); + } + + public static void main(String[] args) throws Exception { + Crypto.loadKeys(); // Load keys from buffers. + + // Parse start-up arguments. + if (StartupArguments.parse(args)) { + System.exit(0); // Exit early. + } + + // Create command map. + commandMap = new CommandMap(true); + + // Initialize server. + logger.info(translate("messages.status.starting")); + logger.info(translate("messages.status.game_version", GameConstants.VERSION)); + logger.info(translate("messages.status.version", BuildConfig.VERSION, BuildConfig.GIT_HASH)); + + // Load all resources. + Grasscutter.updateDayOfWeek(); + ResourceLoader.loadAll(); + ScriptLoader.init(); + + // Generate handbooks. + Tools.createGmHandbooks(false); + + // Initialize database. + DatabaseManager.initialize(); + + // Initialize the default systems. + authenticationSystem = new DefaultAuthentication(); + permissionHandler = new DefaultPermissionHandler(); + + // Create server instances. + httpServer = new HttpServer(); + gameServer = new GameServer(); + // Create a server hook instance with both servers. + new ServerHook(gameServer, httpServer); + + // Create plugin manager instance. + pluginManager = new PluginManager(); + // Add HTTP routes after loading plugins. + httpServer.addRouter(HttpServer.UnhandledRequestRouter.class); + httpServer.addRouter(HttpServer.DefaultRequestRouter.class); + httpServer.addRouter(RegionHandler.class); + httpServer.addRouter(LogHandler.class); + httpServer.addRouter(GenericHandler.class); + httpServer.addRouter(AnnouncementsHandler.class); + httpServer.addRouter(DispatchHandler.class); + httpServer.addRouter(GachaHandler.class); + httpServer.addRouter(DocumentationServerHandler.class); + + // Start servers. + var runMode = Grasscutter.getRunMode(); + if (runMode == ServerRunMode.HYBRID) { + httpServer.start(); + gameServer.start(); + } else if (runMode == ServerRunMode.DISPATCH_ONLY) { + httpServer.start(); + } else if (runMode == ServerRunMode.GAME_ONLY) { + gameServer.start(); + } else { + logger.error(translate("messages.status.run_mode_error", runMode)); + logger.error(translate("messages.status.run_mode_help")); + logger.error(translate("messages.status.shutdown")); + System.exit(1); + } + + // Enable all plugins. + pluginManager.enablePlugins(); + + // Hook into shutdown event. + Runtime.getRuntime().addShutdownHook(new Thread(Grasscutter::onShutdown)); + + // Open console. + Grasscutter.startConsole(); + } + + /** Server shutdown event. */ + private static void onShutdown() { + // Disable all plugins. + if (pluginManager != null) pluginManager.disablePlugins(); + } + + /* + * Methods for the language system component. + */ + + public static void loadLanguage() { + var locale = config.language.language; + language = Language.getLanguage(Utils.getLanguageCode(locale)); + } + + /* + * Methods for the configuration system component. + */ + + /** Attempts to load the configuration from a file. */ + public static void loadConfig() { + // Check if config.json exists. If not, we generate a new config. + if (!configFile.exists()) { + getLogger().info("config.json could not be found. Generating a default configuration ..."); + config = new ConfigContainer(); + Grasscutter.saveConfig(config); + return; + } + + // If the file already exists, we attempt to load it. + try { + config = JsonUtils.loadToClass(configFile.toPath(), ConfigContainer.class); + } catch (Exception exception) { + getLogger() + .error( + "There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); + System.exit(1); + } + } + + /** + * Saves the provided server configuration. + * + * @param config The configuration to save, or null for a new one. + */ + public static void saveConfig(@Nullable ConfigContainer config) { + if (config == null) config = new ConfigContainer(); + + try (FileWriter file = new FileWriter(configFile)) { + file.write(JsonUtils.encode(config)); + } catch (IOException ignored) { + logger.error("Unable to write to config file."); + } catch (Exception e) { + logger.error("Unable to save config file.", e); + } + } + + /* + * Getters for the various server components. + */ + + public static Language getLanguage(String langCode) { + return Language.getLanguage(langCode); + } + + public static ServerRunMode getRunMode() { + return Grasscutter.runModeOverride != null ? Grasscutter.runModeOverride : SERVER.runMode; + } + + public static LineReader getConsole() { + if (consoleLineReader == null) { + Terminal terminal = null; + try { + terminal = TerminalBuilder.builder().jna(true).build(); + } catch (Exception e) { + try { + // Fallback to a dumb jline terminal. + terminal = TerminalBuilder.builder().dumb(true).build(); + } catch (Exception ignored) { + // When dumb is true, build() never throws. + } + } + + consoleLineReader = LineReaderBuilder.builder().terminal(terminal).build(); + } + + return consoleLineReader; + } + + /* + * Utility methods. + */ + + public static void updateDayOfWeek() { + Calendar calendar = Calendar.getInstance(); + Grasscutter.currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); + logger.debug("Set day of week to " + currentDayOfWeek); + } + + public static void startConsole() { + // Console should not start in dispatch only mode. + if (SERVER.runMode == ServerRunMode.DISPATCH_ONLY) { + logger.info(translate("messages.dispatch.no_commands_error")); + return; + } else { + logger.info(translate("messages.status.done")); + } + + String input = null; + var isLastInterrupted = false; + while (config.server.game.enableConsole) { + try { + input = consoleLineReader.readLine("> "); + } catch (UserInterruptException e) { + if (!isLastInterrupted) { + isLastInterrupted = true; + logger.info("Press Ctrl-C again to shutdown."); + continue; + } else { + Runtime.getRuntime().exit(0); + } + } catch (EndOfFileException e) { + logger.info("EOF detected."); + continue; + } catch (IOError e) { + logger.error("An IO error occurred while trying to read from console.", e); + return; + } + + isLastInterrupted = false; + + try { + commandMap.invoke(null, null, input); + } catch (Exception e) { + logger.error(translate("messages.game.command_error"), e); + } + } + } + + /* + * Enums for the configuration. + */ + + public enum ServerRunMode { + HYBRID, + DISPATCH_ONLY, + GAME_ONLY + } + + public enum ServerDebugMode { + ALL, + MISSING, + WHITELIST, + BLACKLIST, + NONE + } +} diff --git a/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java b/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java index 79b25db29..34b910f0a 100644 --- a/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java +++ b/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java @@ -1,148 +1,133 @@ -package emu.grasscutter.auth; - -import emu.grasscutter.game.Account; -import emu.grasscutter.server.http.objects.*; -import io.javalin.http.Context; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -import javax.annotation.Nullable; - -/** - * Defines an authenticator for the server. - * Can be changed by plugins. - */ -public interface AuthenticationSystem { - - /** - * Generates an authentication request from a {@link LoginAccountRequestJson} object. - * - * @param ctx The Javalin context. - * @param jsonData The JSON data. - * @return An authentication request. - */ - static AuthenticationRequest fromPasswordRequest(Context ctx, LoginAccountRequestJson jsonData) { - return AuthenticationRequest.builder() - .context(ctx) - .passwordRequest(jsonData) - .build(); - } - - /** - * Generates an authentication request from a {@link LoginTokenRequestJson} object. - * - * @param ctx The Javalin context. - * @param jsonData The JSON data. - * @return An authentication request. - */ - static AuthenticationRequest fromTokenRequest(Context ctx, LoginTokenRequestJson jsonData) { - return AuthenticationRequest.builder() - .context(ctx) - .tokenRequest(jsonData) - .build(); - } - - /** - * Generates an authentication request from a {@link ComboTokenReqJson} object. - * - * @param ctx The Javalin context. - * @param jsonData The JSON data. - * @return An authentication request. - */ - static AuthenticationRequest fromComboTokenRequest(Context ctx, ComboTokenReqJson jsonData, - ComboTokenReqJson.LoginTokenData tokenData) { - return AuthenticationRequest.builder() - .context(ctx) - .sessionKeyRequest(jsonData) - .sessionKeyData(tokenData) - .build(); - } - - /** - * Generates an authentication request from a {@link Context} object. - * - * @param ctx The Javalin context. - * @return An authentication request. - */ - static AuthenticationRequest fromExternalRequest(Context ctx) { - return AuthenticationRequest.builder().context(ctx).build(); - } - - /** - * Called when a user requests to make an account. - * - * @param username The provided username. - * @param password The provided password. (SHA-256'ed) - */ - void createAccount(String username, String password); - - /** - * Called when a user requests to reset their password. - * - * @param username The username of the account to reset. - */ - void resetPassword(String username); - - /** - * Called by plugins to internally verify a user's identity. - * - * @param details A unique identifier to identify the user. (For example: a JWT token) - * @return The user's account if the verification was successful, null if the user was unable to be verified. - */ - Account verifyUser(String details); - - /** - * This is the authenticator used for password authentication. - * - * @return An authenticator. - */ - Authenticator getPasswordAuthenticator(); - - /** - * This is the authenticator used for token authentication. - * - * @return An authenticator. - */ - Authenticator getTokenAuthenticator(); - - /** - * This is the authenticator used for session authentication. - * - * @return An authenticator. - */ - Authenticator getSessionKeyAuthenticator(); - - /** - * This is the authenticator used for handling external authentication requests. - * - * @return An authenticator. - */ - ExternalAuthenticator getExternalAuthenticator(); - - /** - * This is the authenticator used for handling OAuth authentication requests. - * - * @return An authenticator. - */ - OAuthAuthenticator getOAuthAuthenticator(); - - /** - * A data container that holds relevant data for authenticating a client. - */ - @Builder - @AllArgsConstructor - @Getter - class AuthenticationRequest { - private final Context context; - - @Nullable - private final LoginAccountRequestJson passwordRequest; - @Nullable - private final LoginTokenRequestJson tokenRequest; - @Nullable - private final ComboTokenReqJson sessionKeyRequest; - @Nullable - private final ComboTokenReqJson.LoginTokenData sessionKeyData; - } -} +package emu.grasscutter.auth; + +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.*; +import io.javalin.http.Context; +import javax.annotation.Nullable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +/** Defines an authenticator for the server. Can be changed by plugins. */ +public interface AuthenticationSystem { + + /** + * Generates an authentication request from a {@link LoginAccountRequestJson} object. + * + * @param ctx The Javalin context. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromPasswordRequest(Context ctx, LoginAccountRequestJson jsonData) { + return AuthenticationRequest.builder().context(ctx).passwordRequest(jsonData).build(); + } + + /** + * Generates an authentication request from a {@link LoginTokenRequestJson} object. + * + * @param ctx The Javalin context. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromTokenRequest(Context ctx, LoginTokenRequestJson jsonData) { + return AuthenticationRequest.builder().context(ctx).tokenRequest(jsonData).build(); + } + + /** + * Generates an authentication request from a {@link ComboTokenReqJson} object. + * + * @param ctx The Javalin context. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromComboTokenRequest( + Context ctx, ComboTokenReqJson jsonData, ComboTokenReqJson.LoginTokenData tokenData) { + return AuthenticationRequest.builder() + .context(ctx) + .sessionKeyRequest(jsonData) + .sessionKeyData(tokenData) + .build(); + } + + /** + * Generates an authentication request from a {@link Context} object. + * + * @param ctx The Javalin context. + * @return An authentication request. + */ + static AuthenticationRequest fromExternalRequest(Context ctx) { + return AuthenticationRequest.builder().context(ctx).build(); + } + + /** + * Called when a user requests to make an account. + * + * @param username The provided username. + * @param password The provided password. (SHA-256'ed) + */ + void createAccount(String username, String password); + + /** + * Called when a user requests to reset their password. + * + * @param username The username of the account to reset. + */ + void resetPassword(String username); + + /** + * Called by plugins to internally verify a user's identity. + * + * @param details A unique identifier to identify the user. (For example: a JWT token) + * @return The user's account if the verification was successful, null if the user was unable to + * be verified. + */ + Account verifyUser(String details); + + /** + * This is the authenticator used for password authentication. + * + * @return An authenticator. + */ + Authenticator getPasswordAuthenticator(); + + /** + * This is the authenticator used for token authentication. + * + * @return An authenticator. + */ + Authenticator getTokenAuthenticator(); + + /** + * This is the authenticator used for session authentication. + * + * @return An authenticator. + */ + Authenticator getSessionKeyAuthenticator(); + + /** + * This is the authenticator used for handling external authentication requests. + * + * @return An authenticator. + */ + ExternalAuthenticator getExternalAuthenticator(); + + /** + * This is the authenticator used for handling OAuth authentication requests. + * + * @return An authenticator. + */ + OAuthAuthenticator getOAuthAuthenticator(); + + /** A data container that holds relevant data for authenticating a client. */ + @Builder + @AllArgsConstructor + @Getter + class AuthenticationRequest { + private final Context context; + + @Nullable private final LoginAccountRequestJson passwordRequest; + @Nullable private final LoginTokenRequestJson tokenRequest; + @Nullable private final ComboTokenReqJson sessionKeyRequest; + @Nullable private final ComboTokenReqJson.LoginTokenData sessionKeyData; + } +} diff --git a/src/main/java/emu/grasscutter/auth/Authenticator.java b/src/main/java/emu/grasscutter/auth/Authenticator.java index 57f5bbce7..ae8a21a29 100644 --- a/src/main/java/emu/grasscutter/auth/Authenticator.java +++ b/src/main/java/emu/grasscutter/auth/Authenticator.java @@ -1,20 +1,22 @@ -package emu.grasscutter.auth; - -import emu.grasscutter.server.http.objects.ComboTokenResJson; -import emu.grasscutter.server.http.objects.LoginResultJson; - -/** - * Handles username/password authentication from the client. - * - * @param The response object type. Should be {@link LoginResultJson} or {@link ComboTokenResJson} - */ -public interface Authenticator { - - /** - * Attempt to authenticate the client with the provided credentials. - * - * @param request The authentication request wrapped in a {@link AuthenticationSystem.AuthenticationRequest} object. - * @return The result of the login in an object. - */ - T authenticate(AuthenticationSystem.AuthenticationRequest request); -} +package emu.grasscutter.auth; + +import emu.grasscutter.server.http.objects.ComboTokenResJson; +import emu.grasscutter.server.http.objects.LoginResultJson; + +/** + * Handles username/password authentication from the client. + * + * @param The response object type. Should be {@link LoginResultJson} or {@link + * ComboTokenResJson} + */ +public interface Authenticator { + + /** + * Attempt to authenticate the client with the provided credentials. + * + * @param request The authentication request wrapped in a {@link + * AuthenticationSystem.AuthenticationRequest} object. + * @return The result of the login in an object. + */ + T authenticate(AuthenticationSystem.AuthenticationRequest request); +} diff --git a/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java b/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java index f0148bbb0..41e55f056 100644 --- a/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java +++ b/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java @@ -1,71 +1,72 @@ -package emu.grasscutter.auth; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.auth.DefaultAuthenticators.*; -import emu.grasscutter.game.Account; -import emu.grasscutter.server.http.objects.ComboTokenResJson; -import emu.grasscutter.server.http.objects.LoginResultJson; - -import static emu.grasscutter.config.Configuration.ACCOUNT; -import static emu.grasscutter.utils.Language.translate; - -/** - * The default Grasscutter authentication implementation. - * Allows all users to access any account. - */ -public final class DefaultAuthentication implements AuthenticationSystem { - private final Authenticator passwordAuthenticator; - private final Authenticator tokenAuthenticator = new TokenAuthenticator(); - private final Authenticator sessionKeyAuthenticator = new SessionKeyAuthenticator(); - private final ExternalAuthenticator externalAuthenticator = new ExternalAuthentication(); - private final OAuthAuthenticator oAuthAuthenticator = new OAuthAuthentication(); - - public DefaultAuthentication() { - if (ACCOUNT.EXPERIMENTAL_RealPassword) { - passwordAuthenticator = new ExperimentalPasswordAuthenticator(); - } else { - passwordAuthenticator = new PasswordAuthenticator(); - } - } - - @Override - public void createAccount(String username, String password) { - // Unhandled. The default authenticator doesn't store passwords. - } - - @Override - public void resetPassword(String username) { - // Unhandled. The default authenticator doesn't store passwords. - } - - @Override - public Account verifyUser(String details) { - Grasscutter.getLogger().info(translate("messages.dispatch.authentication.default_unable_to_verify")); - return null; - } - - @Override - public Authenticator getPasswordAuthenticator() { - return this.passwordAuthenticator; - } - - @Override - public Authenticator getTokenAuthenticator() { - return this.tokenAuthenticator; - } - - @Override - public Authenticator getSessionKeyAuthenticator() { - return this.sessionKeyAuthenticator; - } - - @Override - public ExternalAuthenticator getExternalAuthenticator() { - return this.externalAuthenticator; - } - - @Override - public OAuthAuthenticator getOAuthAuthenticator() { - return this.oAuthAuthenticator; - } -} +package emu.grasscutter.auth; + +import static emu.grasscutter.config.Configuration.ACCOUNT; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.DefaultAuthenticators.*; +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.ComboTokenResJson; +import emu.grasscutter.server.http.objects.LoginResultJson; + +/** + * The default Grasscutter authentication implementation. Allows all users to access any account. + */ +public final class DefaultAuthentication implements AuthenticationSystem { + private final Authenticator passwordAuthenticator; + private final Authenticator tokenAuthenticator = new TokenAuthenticator(); + private final Authenticator sessionKeyAuthenticator = + new SessionKeyAuthenticator(); + private final ExternalAuthenticator externalAuthenticator = new ExternalAuthentication(); + private final OAuthAuthenticator oAuthAuthenticator = new OAuthAuthentication(); + + public DefaultAuthentication() { + if (ACCOUNT.EXPERIMENTAL_RealPassword) { + passwordAuthenticator = new ExperimentalPasswordAuthenticator(); + } else { + passwordAuthenticator = new PasswordAuthenticator(); + } + } + + @Override + public void createAccount(String username, String password) { + // Unhandled. The default authenticator doesn't store passwords. + } + + @Override + public void resetPassword(String username) { + // Unhandled. The default authenticator doesn't store passwords. + } + + @Override + public Account verifyUser(String details) { + Grasscutter.getLogger() + .info(translate("messages.dispatch.authentication.default_unable_to_verify")); + return null; + } + + @Override + public Authenticator getPasswordAuthenticator() { + return this.passwordAuthenticator; + } + + @Override + public Authenticator getTokenAuthenticator() { + return this.tokenAuthenticator; + } + + @Override + public Authenticator getSessionKeyAuthenticator() { + return this.sessionKeyAuthenticator; + } + + @Override + public ExternalAuthenticator getExternalAuthenticator() { + return this.externalAuthenticator; + } + + @Override + public OAuthAuthenticator getOAuthAuthenticator() { + return this.oAuthAuthenticator; + } +} diff --git a/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java b/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java index 441a42324..a30191910 100644 --- a/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java +++ b/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java @@ -1,346 +1,363 @@ -package emu.grasscutter.auth; - -import at.favre.lib.crypto.bcrypt.BCrypt; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.server.http.objects.ComboTokenResJson; -import emu.grasscutter.server.http.objects.LoginResultJson; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; - -import javax.crypto.Cipher; -import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; - -import static emu.grasscutter.config.Configuration.ACCOUNT; -import static emu.grasscutter.utils.Language.translate; - -/** - * A class containing default authenticators. - */ -public final class DefaultAuthenticators { - - /** - * Handles the authentication request from the username and password form. - */ - public static class PasswordAuthenticator implements Authenticator { - @Override - public LoginResultJson authenticate(AuthenticationRequest request) { - var response = new LoginResultJson(); - - var requestData = request.getPasswordRequest(); - assert requestData != null; // This should never be null. - int playerCount = Grasscutter.getGameServer().getPlayers().size(); - - boolean successfulLogin = false; - String address = request.getContext().ip(); - String responseMessage = translate("messages.dispatch.account.username_error"); - String loggerMessage = ""; - - // Get account from database. - Account account = DatabaseHelper.getAccountByName(requestData.account); - if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { - // Check if account exists. - if (account == null && ACCOUNT.autoCreate) { - // This account has been created AUTOMATICALLY. There will be no permissions added. - account = DatabaseHelper.createAccountWithUid(requestData.account, 0); - - // Check if the account was created successfully. - if (account == null) { - responseMessage = translate("messages.dispatch.account.username_create_error"); - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_error", address)); - } else { - // Continue with login. - successfulLogin = true; - - // Log the creation. - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_success", address, response.data.account.uid)); - } - } else if (account != null) - successfulLogin = true; - else - loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address); - - } else { - responseMessage = translate("messages.dispatch.account.server_max_player_limit"); - loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); - } - - - // Set response data. - if (successfulLogin) { - response.message = "OK"; - response.data.account.uid = account.getId(); - response.data.account.token = account.generateSessionKey(); - response.data.account.email = account.getEmail(); - - loggerMessage = translate("messages.dispatch.account.login_success", address, account.getId()); - } else { - response.retcode = -201; - response.message = responseMessage; - - } - Grasscutter.getLogger().info(loggerMessage); - - return response; - } - } - - public static class ExperimentalPasswordAuthenticator implements Authenticator { - @Override - public LoginResultJson authenticate(AuthenticationRequest request) { - var response = new LoginResultJson(); - - var requestData = request.getPasswordRequest(); - assert requestData != null; // This should never be null. - int playerCount = Grasscutter.getGameServer().getPlayers().size(); - - boolean successfulLogin = false; - String address = request.getContext().ip(); - String responseMessage = translate("messages.dispatch.account.username_error"); - String loggerMessage = ""; - String decryptedPassword = ""; - try { - byte[] key = FileUtils.readResource("/keys/auth_private-key.der"); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - RSAPrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); - - Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - - cipher.init(Cipher.DECRYPT_MODE, private_key); - - decryptedPassword = new String(cipher.doFinal(Utils.base64Decode(request.getPasswordRequest().password)), StandardCharsets.UTF_8); - } catch (Exception ignored) { - decryptedPassword = request.getPasswordRequest().password; - } - - if (decryptedPassword == null) { - successfulLogin = false; - loggerMessage = translate("messages.dispatch.account.login_password_error", address); - responseMessage = translate("messages.dispatch.account.password_error"); - } - - // Get account from database. - Account account = DatabaseHelper.getAccountByName(requestData.account); - if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { - // Check if account exists. - if (account == null && ACCOUNT.autoCreate) { - // This account has been created AUTOMATICALLY. There will be no permissions added. - if (decryptedPassword.length() >= 8) { - account = DatabaseHelper.createAccountWithUid(requestData.account, 0); - account.setPassword(BCrypt.withDefaults().hashToString(12, decryptedPassword.toCharArray())); - account.save(); - - // Check if the account was created successfully. - if (account == null) { - responseMessage = translate("messages.dispatch.account.username_create_error"); - loggerMessage = translate("messages.dispatch.account.account_login_create_error", address); - } else { - // Continue with login. - successfulLogin = true; - - // Log the creation. - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_success", address, response.data.account.uid)); - } - } else { - successfulLogin = false; - loggerMessage = translate("messages.dispatch.account.login_password_error", address); - responseMessage = translate("messages.dispatch.account.password_length_error"); - } - } else if (account != null) { - if (account.getPassword() != null && !account.getPassword().isEmpty()) { - if (BCrypt.verifyer().verify(decryptedPassword.toCharArray(), account.getPassword()).verified) { - successfulLogin = true; - } else { - successfulLogin = false; - loggerMessage = translate("messages.dispatch.account.login_password_error", address); - responseMessage = translate("messages.dispatch.account.password_error"); - } - } else { - successfulLogin = false; - loggerMessage = translate("messages.dispatch.account.login_password_storage_error", address); - responseMessage = translate("messages.dispatch.account.password_storage_error"); - } - } else { - loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address); - } - } else { - responseMessage = translate("messages.dispatch.account.server_max_player_limit"); - loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); - } - - - // Set response data. - if (successfulLogin) { - response.message = "OK"; - response.data.account.uid = account.getId(); - response.data.account.token = account.generateSessionKey(); - response.data.account.email = account.getEmail(); - - loggerMessage = translate("messages.dispatch.account.login_success", address, account.getId()); - } else { - response.retcode = -201; - response.message = responseMessage; - - } - Grasscutter.getLogger().info(loggerMessage); - - return response; - } - } - - /** - * Handles the authentication request from the game when using a registry token. - */ - public static class TokenAuthenticator implements Authenticator { - @Override - public LoginResultJson authenticate(AuthenticationRequest request) { - var response = new LoginResultJson(); - - var requestData = request.getTokenRequest(); - assert requestData != null; - - boolean successfulLogin; - String address = request.getContext().ip(); - String loggerMessage; - int playerCount = Grasscutter.getGameServer().getPlayers().size(); - - // Log the attempt. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", address)); - - if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { - - // Get account from database. - Account account = DatabaseHelper.getAccountById(requestData.uid); - - // Check if account exists/token is valid. - successfulLogin = account != null && account.getSessionKey().equals(requestData.token); - - // Set response data. - if (successfulLogin) { - response.message = "OK"; - response.data.account.uid = account.getId(); - response.data.account.token = account.getSessionKey(); - response.data.account.email = account.getEmail(); - - // Log the login. - loggerMessage = translate("messages.dispatch.account.login_token_success", address, requestData.uid); - } else { - response.retcode = -201; - response.message = translate("messages.dispatch.account.account_cache_error"); - - // Log the failure. - loggerMessage = translate("messages.dispatch.account.login_token_error", address); - } - - } else { - response.retcode = -201; - response.message = translate("messages.dispatch.account.server_max_player_limit"); - - loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); - } - - Grasscutter.getLogger().info(loggerMessage); - return response; - } - } - - /** - * Handles the authentication request from the game when using a combo token/session key. - */ - public static class SessionKeyAuthenticator implements Authenticator { - @Override - public ComboTokenResJson authenticate(AuthenticationRequest request) { - var response = new ComboTokenResJson(); - - var requestData = request.getSessionKeyRequest(); - var loginData = request.getSessionKeyData(); - assert requestData != null; - assert loginData != null; - - boolean successfulLogin; - String address = request.getContext().ip(); - String loggerMessage; - int playerCount = Grasscutter.getGameServer().getPlayers().size(); - - if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { - // Get account from database. - Account account = DatabaseHelper.getAccountById(loginData.uid); - - // Check if account exists/token is valid. - successfulLogin = account != null && account.getSessionKey().equals(loginData.token); - - // Set response data. - if (successfulLogin) { - response.message = "OK"; - response.data.open_id = account.getId(); - response.data.combo_id = "157795300"; - response.data.combo_token = account.generateLoginToken(); - - // Log the login. - loggerMessage = translate("messages.dispatch.account.combo_token_success", address); - - } else { - response.retcode = -201; - response.message = translate("messages.dispatch.account.session_key_error"); - - // Log the failure. - loggerMessage = translate("messages.dispatch.account.combo_token_error", address); - } - } else { - response.retcode = -201; - response.message = translate("messages.dispatch.account.server_max_player_limit"); - - loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); - } - - Grasscutter.getLogger().info(loggerMessage); - return response; - } - } - - /** - * Handles authentication requests from external sources. - */ - public static class ExternalAuthentication implements ExternalAuthenticator { - @Override - public void handleLogin(AuthenticationRequest request) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - - @Override - public void handleAccountCreation(AuthenticationRequest request) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - - @Override - public void handlePasswordReset(AuthenticationRequest request) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - } - - /** - * Handles authentication requests from OAuth sources.Zenlith - */ - public static class OAuthAuthentication implements OAuthAuthenticator { - @Override - public void handleLogin(AuthenticationRequest request) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - - @Override - public void handleRedirection(AuthenticationRequest request, ClientType type) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - - @Override - public void handleTokenProcess(AuthenticationRequest request) { - request.getContext().result("Authentication is not available with the default authentication method."); - } - } -} +package emu.grasscutter.auth; + +import static emu.grasscutter.config.Configuration.ACCOUNT; +import static emu.grasscutter.utils.Language.translate; + +import at.favre.lib.crypto.bcrypt.BCrypt; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.ComboTokenResJson; +import emu.grasscutter.server.http.objects.LoginResultJson; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; +import javax.crypto.Cipher; + +/** A class containing default authenticators. */ +public final class DefaultAuthenticators { + + /** Handles the authentication request from the username and password form. */ + public static class PasswordAuthenticator implements Authenticator { + @Override + public LoginResultJson authenticate(AuthenticationRequest request) { + var response = new LoginResultJson(); + + var requestData = request.getPasswordRequest(); + assert requestData != null; // This should never be null. + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + boolean successfulLogin = false; + String address = request.getContext().ip(); + String responseMessage = translate("messages.dispatch.account.username_error"); + String loggerMessage = ""; + + // Get account from database. + Account account = DatabaseHelper.getAccountByName(requestData.account); + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + // Check if account exists. + if (account == null && ACCOUNT.autoCreate) { + // This account has been created AUTOMATICALLY. There will be no permissions added. + account = DatabaseHelper.createAccountWithUid(requestData.account, 0); + + // Check if the account was created successfully. + if (account == null) { + responseMessage = translate("messages.dispatch.account.username_create_error"); + Grasscutter.getLogger() + .info(translate("messages.dispatch.account.account_login_create_error", address)); + } else { + // Continue with login. + successfulLogin = true; + + // Log the creation. + Grasscutter.getLogger() + .info( + translate( + "messages.dispatch.account.account_login_create_success", + address, + response.data.account.uid)); + } + } else if (account != null) successfulLogin = true; + else + loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address); + + } else { + responseMessage = translate("messages.dispatch.account.server_max_player_limit"); + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + // Set response data. + if (successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.generateSessionKey(); + response.data.account.email = account.getEmail(); + + loggerMessage = + translate("messages.dispatch.account.login_success", address, account.getId()); + } else { + response.retcode = -201; + response.message = responseMessage; + } + Grasscutter.getLogger().info(loggerMessage); + + return response; + } + } + + public static class ExperimentalPasswordAuthenticator implements Authenticator { + @Override + public LoginResultJson authenticate(AuthenticationRequest request) { + var response = new LoginResultJson(); + + var requestData = request.getPasswordRequest(); + assert requestData != null; // This should never be null. + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + boolean successfulLogin = false; + String address = request.getContext().ip(); + String responseMessage = translate("messages.dispatch.account.username_error"); + String loggerMessage = ""; + String decryptedPassword = ""; + try { + byte[] key = FileUtils.readResource("/keys/auth_private-key.der"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + RSAPrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); + + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + + cipher.init(Cipher.DECRYPT_MODE, private_key); + + decryptedPassword = + new String( + cipher.doFinal(Utils.base64Decode(request.getPasswordRequest().password)), + StandardCharsets.UTF_8); + } catch (Exception ignored) { + decryptedPassword = request.getPasswordRequest().password; + } + + if (decryptedPassword == null) { + successfulLogin = false; + loggerMessage = translate("messages.dispatch.account.login_password_error", address); + responseMessage = translate("messages.dispatch.account.password_error"); + } + + // Get account from database. + Account account = DatabaseHelper.getAccountByName(requestData.account); + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + // Check if account exists. + if (account == null && ACCOUNT.autoCreate) { + // This account has been created AUTOMATICALLY. There will be no permissions added. + if (decryptedPassword.length() >= 8) { + account = DatabaseHelper.createAccountWithUid(requestData.account, 0); + account.setPassword( + BCrypt.withDefaults().hashToString(12, decryptedPassword.toCharArray())); + account.save(); + + // Check if the account was created successfully. + if (account == null) { + responseMessage = translate("messages.dispatch.account.username_create_error"); + loggerMessage = + translate("messages.dispatch.account.account_login_create_error", address); + } else { + // Continue with login. + successfulLogin = true; + + // Log the creation. + Grasscutter.getLogger() + .info( + translate( + "messages.dispatch.account.account_login_create_success", + address, + response.data.account.uid)); + } + } else { + successfulLogin = false; + loggerMessage = translate("messages.dispatch.account.login_password_error", address); + responseMessage = translate("messages.dispatch.account.password_length_error"); + } + } else if (account != null) { + if (account.getPassword() != null && !account.getPassword().isEmpty()) { + if (BCrypt.verifyer() + .verify(decryptedPassword.toCharArray(), account.getPassword()) + .verified) { + successfulLogin = true; + } else { + successfulLogin = false; + loggerMessage = translate("messages.dispatch.account.login_password_error", address); + responseMessage = translate("messages.dispatch.account.password_error"); + } + } else { + successfulLogin = false; + loggerMessage = + translate("messages.dispatch.account.login_password_storage_error", address); + responseMessage = translate("messages.dispatch.account.password_storage_error"); + } + } else { + loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address); + } + } else { + responseMessage = translate("messages.dispatch.account.server_max_player_limit"); + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + // Set response data. + if (successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.generateSessionKey(); + response.data.account.email = account.getEmail(); + + loggerMessage = + translate("messages.dispatch.account.login_success", address, account.getId()); + } else { + response.retcode = -201; + response.message = responseMessage; + } + Grasscutter.getLogger().info(loggerMessage); + + return response; + } + } + + /** Handles the authentication request from the game when using a registry token. */ + public static class TokenAuthenticator implements Authenticator { + @Override + public LoginResultJson authenticate(AuthenticationRequest request) { + var response = new LoginResultJson(); + + var requestData = request.getTokenRequest(); + assert requestData != null; + + boolean successfulLogin; + String address = request.getContext().ip(); + String loggerMessage; + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + // Log the attempt. + Grasscutter.getLogger() + .info(translate("messages.dispatch.account.login_token_attempt", address)); + + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + + // Get account from database. + Account account = DatabaseHelper.getAccountById(requestData.uid); + + // Check if account exists/token is valid. + successfulLogin = account != null && account.getSessionKey().equals(requestData.token); + + // Set response data. + if (successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.getSessionKey(); + response.data.account.email = account.getEmail(); + + // Log the login. + loggerMessage = + translate("messages.dispatch.account.login_token_success", address, requestData.uid); + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.account_cache_error"); + + // Log the failure. + loggerMessage = translate("messages.dispatch.account.login_token_error", address); + } + + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.server_max_player_limit"); + + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + Grasscutter.getLogger().info(loggerMessage); + return response; + } + } + + /** Handles the authentication request from the game when using a combo token/session key. */ + public static class SessionKeyAuthenticator implements Authenticator { + @Override + public ComboTokenResJson authenticate(AuthenticationRequest request) { + var response = new ComboTokenResJson(); + + var requestData = request.getSessionKeyRequest(); + var loginData = request.getSessionKeyData(); + assert requestData != null; + assert loginData != null; + + boolean successfulLogin; + String address = request.getContext().ip(); + String loggerMessage; + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + // Get account from database. + Account account = DatabaseHelper.getAccountById(loginData.uid); + + // Check if account exists/token is valid. + successfulLogin = account != null && account.getSessionKey().equals(loginData.token); + + // Set response data. + if (successfulLogin) { + response.message = "OK"; + response.data.open_id = account.getId(); + response.data.combo_id = "157795300"; + response.data.combo_token = account.generateLoginToken(); + + // Log the login. + loggerMessage = translate("messages.dispatch.account.combo_token_success", address); + + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.session_key_error"); + + // Log the failure. + loggerMessage = translate("messages.dispatch.account.combo_token_error", address); + } + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.server_max_player_limit"); + + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + Grasscutter.getLogger().info(loggerMessage); + return response; + } + } + + /** Handles authentication requests from external sources. */ + public static class ExternalAuthentication implements ExternalAuthenticator { + @Override + public void handleLogin(AuthenticationRequest request) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + + @Override + public void handleAccountCreation(AuthenticationRequest request) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + + @Override + public void handlePasswordReset(AuthenticationRequest request) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + } + + /** Handles authentication requests from OAuth sources.Zenlith */ + public static class OAuthAuthentication implements OAuthAuthenticator { + @Override + public void handleLogin(AuthenticationRequest request) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + + @Override + public void handleRedirection(AuthenticationRequest request, ClientType type) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + + @Override + public void handleTokenProcess(AuthenticationRequest request) { + request + .getContext() + .result("Authentication is not available with the default authentication method."); + } + } +} diff --git a/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java b/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java index 555163520..024306e23 100644 --- a/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java +++ b/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java @@ -1,36 +1,32 @@ -package emu.grasscutter.auth; - -import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; - -/** - * Handles authentication via external routes. - */ -public interface ExternalAuthenticator { - - /** - * Called when an external login request is made. - * - * @param request The authentication request. - */ - void handleLogin(AuthenticationRequest request); - - /** - * Called when an external account creation request is made. - * - * @param request The authentication request. - *

- * For developers: Use AuthenticationRequest#getRequest() to get the request body. - * Use AuthenticationRequest#getResponse() to get the response body. - */ - void handleAccountCreation(AuthenticationRequest request); - - /** - * Called when an external password reset request is made. - * - * @param request The authentication request. - *

- * For developers: Use AuthenticationRequest#getRequest() to get the request body. - * Use AuthenticationRequest#getResponse() to get the response body. - */ - void handlePasswordReset(AuthenticationRequest request); -} +package emu.grasscutter.auth; + +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; + +/** Handles authentication via external routes. */ +public interface ExternalAuthenticator { + + /** + * Called when an external login request is made. + * + * @param request The authentication request. + */ + void handleLogin(AuthenticationRequest request); + + /** + * Called when an external account creation request is made. + * + * @param request The authentication request. + *

For developers: Use AuthenticationRequest#getRequest() to get the request body. Use + * AuthenticationRequest#getResponse() to get the response body. + */ + void handleAccountCreation(AuthenticationRequest request); + + /** + * Called when an external password reset request is made. + * + * @param request The authentication request. + *

For developers: Use AuthenticationRequest#getRequest() to get the request body. Use + * AuthenticationRequest#getResponse() to get the response body. + */ + void handlePasswordReset(AuthenticationRequest request); +} diff --git a/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java b/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java index 429df5a6a..b0214a925 100644 --- a/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java +++ b/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java @@ -1,38 +1,34 @@ -package emu.grasscutter.auth; - -import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; - -/** - * Handles authentication via OAuth routes. - */ -public interface OAuthAuthenticator { - - /** - * Called when an OAuth login request is made. - * - * @param request The authentication request. - */ - void handleLogin(AuthenticationRequest request); - - /** - * Called when a client requests to redirect to login page. - * - * @param request The authentication request. - */ - void handleRedirection(AuthenticationRequest request, ClientType clientType); - - /** - * Called when an OAuth login requests callback. - * - * @param request The authentication request. - */ - void handleTokenProcess(AuthenticationRequest request); - - /** - * The type of the client. - * Used for handling redirection. - */ - enum ClientType { - DESKTOP, MOBILE - } -} +package emu.grasscutter.auth; + +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; + +/** Handles authentication via OAuth routes. */ +public interface OAuthAuthenticator { + + /** + * Called when an OAuth login request is made. + * + * @param request The authentication request. + */ + void handleLogin(AuthenticationRequest request); + + /** + * Called when a client requests to redirect to login page. + * + * @param request The authentication request. + */ + void handleRedirection(AuthenticationRequest request, ClientType clientType); + + /** + * Called when an OAuth login requests callback. + * + * @param request The authentication request. + */ + void handleTokenProcess(AuthenticationRequest request); + + /** The type of the client. Used for handling redirection. */ + enum ClientType { + DESKTOP, + MOBILE + } +} diff --git a/src/main/java/emu/grasscutter/command/Command.java b/src/main/java/emu/grasscutter/command/Command.java index 2055b6256..f3c58bc51 100644 --- a/src/main/java/emu/grasscutter/command/Command.java +++ b/src/main/java/emu/grasscutter/command/Command.java @@ -1,28 +1,28 @@ -package emu.grasscutter.command; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface Command { - String label() default ""; - - String[] aliases() default {}; - - String[] usage() default {""}; - - String permission() default ""; - - String permissionTargeted() default ""; - - TargetRequirement targetRequirement() default TargetRequirement.ONLINE; - - boolean threading() default false; - - enum TargetRequirement { - NONE, // targetPlayer is not required - OFFLINE, // targetPlayer must be offline - PLAYER, // targetPlayer can be online or offline - ONLINE // targetPlayer must be online - } -} +package emu.grasscutter.command; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Command { + String label() default ""; + + String[] aliases() default {}; + + String[] usage() default {""}; + + String permission() default ""; + + String permissionTargeted() default ""; + + TargetRequirement targetRequirement() default TargetRequirement.ONLINE; + + boolean threading() default false; + + enum TargetRequirement { + NONE, // targetPlayer is not required + OFFLINE, // targetPlayer must be offline + PLAYER, // targetPlayer can be online or offline + ONLINE // targetPlayer must be online + } +} diff --git a/src/main/java/emu/grasscutter/command/CommandHandler.java b/src/main/java/emu/grasscutter/command/CommandHandler.java index d7ad1d8ef..b9f072941 100644 --- a/src/main/java/emu/grasscutter/command/CommandHandler.java +++ b/src/main/java/emu/grasscutter/command/CommandHandler.java @@ -1,90 +1,88 @@ -package emu.grasscutter.command; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent; - -import java.util.List; -import java.util.StringJoiner; - -import static emu.grasscutter.utils.Language.translate; - -public interface CommandHandler { - - /** - * Send a message to the target. - * - * @param player The player to send the message to, or null for the server console. - * @param message The message to send. - */ - static void sendMessage(Player player, String message) { - // Call command feedback event. - ReceiveCommandFeedbackEvent event = new ReceiveCommandFeedbackEvent(player, message); - event.call(); - if (event.isCanceled()) { // If event is not cancelled, continue. - return; - } - - // Send message to target. - if (player == null) { - Grasscutter.getLogger().info(event.getMessage()); - } else { - player.dropMessage(event.getMessage().replace("\n\t", "\n\n")); - } - } - - static void sendTranslatedMessage(Player player, String messageKey, Object... args) { - sendMessage(player, translate(player, messageKey, args)); - } - - default String getUsageString(Player player, String... args) { - Command annotation = this.getClass().getAnnotation(Command.class); - String usage_prefix = translate(player, "commands.execution.usage_prefix"); - String command = annotation.label(); - for (String alias : annotation.aliases()) { - if (alias.length() < command.length()) - command = alias; - } - if (player != null) { - command = "/" + command; - } - String target = switch (annotation.targetRequirement()) { - case NONE -> ""; - case OFFLINE -> "@ "; // TODO: make translation keys for offline and online players - case ONLINE -> - (player == null) ? "@ " : "[@] "; // TODO: make translation keys for offline and online players - case PLAYER -> (player == null) ? "@ " : "[@] "; - }; - String[] usages = annotation.usage(); - StringJoiner joiner = new StringJoiner("\n\t"); - for (String usage : usages) - joiner.add(usage_prefix + command + " " + target + usage); - return joiner.toString(); - } - - default void sendUsageMessage(Player player, String... args) { - sendMessage(player, getUsageString(player, args)); - } - - default String getLabel() { - return this.getClass().getAnnotation(Command.class).label(); - } - - default String getDescriptionKey() { - Command annotation = this.getClass().getAnnotation(Command.class); - return "commands.%s.description".formatted(annotation.label()); - } - - default String getDescriptionString(Player player) { - return translate(player, getDescriptionKey()); - } - - /** - * Called when a player/console invokes a command. - * - * @param sender The player/console that invoked the command. - * @param args The arguments to the command. - */ - default void execute(Player sender, Player targetPlayer, List args) { - } -} +package emu.grasscutter.command; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent; +import java.util.List; +import java.util.StringJoiner; + +public interface CommandHandler { + + /** + * Send a message to the target. + * + * @param player The player to send the message to, or null for the server console. + * @param message The message to send. + */ + static void sendMessage(Player player, String message) { + // Call command feedback event. + ReceiveCommandFeedbackEvent event = new ReceiveCommandFeedbackEvent(player, message); + event.call(); + if (event.isCanceled()) { // If event is not cancelled, continue. + return; + } + + // Send message to target. + if (player == null) { + Grasscutter.getLogger().info(event.getMessage()); + } else { + player.dropMessage(event.getMessage().replace("\n\t", "\n\n")); + } + } + + static void sendTranslatedMessage(Player player, String messageKey, Object... args) { + sendMessage(player, translate(player, messageKey, args)); + } + + default String getUsageString(Player player, String... args) { + Command annotation = this.getClass().getAnnotation(Command.class); + String usage_prefix = translate(player, "commands.execution.usage_prefix"); + String command = annotation.label(); + for (String alias : annotation.aliases()) { + if (alias.length() < command.length()) command = alias; + } + if (player != null) { + command = "/" + command; + } + String target = + switch (annotation.targetRequirement()) { + case NONE -> ""; + case OFFLINE -> "@ "; // TODO: make translation keys for offline and online players + case ONLINE -> (player == null) + ? "@ " + : "[@] "; // TODO: make translation keys for offline and online players + case PLAYER -> (player == null) ? "@ " : "[@] "; + }; + String[] usages = annotation.usage(); + StringJoiner joiner = new StringJoiner("\n\t"); + for (String usage : usages) joiner.add(usage_prefix + command + " " + target + usage); + return joiner.toString(); + } + + default void sendUsageMessage(Player player, String... args) { + sendMessage(player, getUsageString(player, args)); + } + + default String getLabel() { + return this.getClass().getAnnotation(Command.class).label(); + } + + default String getDescriptionKey() { + Command annotation = this.getClass().getAnnotation(Command.class); + return "commands.%s.description".formatted(annotation.label()); + } + + default String getDescriptionString(Player player) { + return translate(player, getDescriptionKey()); + } + + /** + * Called when a player/console invokes a command. + * + * @param sender The player/console that invoked the command. + * @param args The arguments to the command. + */ + default void execute(Player sender, Player targetPlayer, List args) {} +} diff --git a/src/main/java/emu/grasscutter/command/CommandHelpers.java b/src/main/java/emu/grasscutter/command/CommandHelpers.java index b5cf92972..aa1f68840 100644 --- a/src/main/java/emu/grasscutter/command/CommandHelpers.java +++ b/src/main/java/emu/grasscutter/command/CommandHelpers.java @@ -1,50 +1,57 @@ -package emu.grasscutter.command; - -import javax.annotation.Nonnull; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class CommandHelpers { - public static final Pattern lvlRegex = Pattern.compile("(? List parseIntParameters(List args, @Nonnull T params, Map> map) { - args.removeIf(arg -> { - var argL = arg.toLowerCase(); - boolean deleteArg = false; - for (var entry : map.entrySet()) { - int argNum = matchIntOrNeg(entry.getKey(), argL); - if (argNum != -1) { - entry.getValue().accept(params, argNum); - deleteArg = true; - } - } - return deleteArg; - }); - return args; - } -} +package emu.grasscutter.command; + +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; + +public class CommandHelpers { + public static final Pattern lvlRegex = + Pattern.compile("(? List parseIntParameters( + List args, @Nonnull T params, Map> map) { + args.removeIf( + arg -> { + var argL = arg.toLowerCase(); + boolean deleteArg = false; + for (var entry : map.entrySet()) { + int argNum = matchIntOrNeg(entry.getKey(), argL); + if (argNum != -1) { + entry.getValue().accept(params, argNum); + deleteArg = true; + } + } + return deleteArg; + }); + return args; + } +} diff --git a/src/main/java/emu/grasscutter/command/CommandMap.java b/src/main/java/emu/grasscutter/command/CommandMap.java index 7f30f02b6..89f387471 100644 --- a/src/main/java/emu/grasscutter/command/CommandMap.java +++ b/src/main/java/emu/grasscutter/command/CommandMap.java @@ -1,330 +1,354 @@ -package emu.grasscutter.command; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import org.reflections.Reflections; - -import java.util.*; - -import static emu.grasscutter.config.Configuration.SERVER; - -@SuppressWarnings({"UnusedReturnValue", "unused"}) -public final class CommandMap { - private static final int INVALID_UID = Integer.MIN_VALUE; - private static final String consoleId = "console"; - private final Map commands = new TreeMap<>(); - private final Map aliases = new TreeMap<>(); - private final Map annotations = new TreeMap<>(); - private final Object2IntMap targetPlayerIds = new Object2IntOpenHashMap<>(); - - public CommandMap() { - this(false); - } - - public CommandMap(boolean scan) { - if (scan) this.scan(); - } - - public static CommandMap getInstance() { - return Grasscutter.getCommandMap(); - } - - private static int getUidFromString(String input) { - try { - return Integer.parseInt(input); - } catch (NumberFormatException ignored) { - var account = DatabaseHelper.getAccountByName(input); - if (account == null) return INVALID_UID; - var player = DatabaseHelper.getPlayerByAccount(account); - if (player == null) return INVALID_UID; - // We will be immediately fetching the player again after this, - // but offline vs online Player safety is more important than saving a lookup - return player.getUid(); - } - } - - /** - * Register a command handler. - * - * @param label The command label. - * @param command The command handler. - * @return Instance chaining. - */ - public CommandMap registerCommand(String label, CommandHandler command) { - Grasscutter.getLogger().debug("Registered command: " + label); - label = label.toLowerCase(); - - // Get command data. - Command annotation = command.getClass().getAnnotation(Command.class); - this.annotations.put(label, annotation); - this.commands.put(label, command); - - // Register aliases. - for (String alias : annotation.aliases()) { - this.aliases.put(alias, command); - this.annotations.put(alias, annotation); - } - return this; - } - - /** - * Removes a registered command handler. - * - * @param label The command label. - * @return Instance chaining. - */ - public CommandMap unregisterCommand(String label) { - Grasscutter.getLogger().debug("Unregistered command: " + label); - - CommandHandler handler = this.commands.get(label); - if (handler == null) return this; - - Command annotation = handler.getClass().getAnnotation(Command.class); - this.annotations.remove(label); - this.commands.remove(label); - - // Unregister aliases. - for (String alias : annotation.aliases()) { - this.aliases.remove(alias); - this.annotations.remove(alias); - } - - return this; - } - - public List getAnnotationsAsList() { - return new ArrayList<>(this.annotations.values()); - } - - public Map getAnnotations() { - return new LinkedHashMap<>(this.annotations); - } - - /** - * Returns a list of all registered commands. - * - * @return All command handlers as a list. - */ - public List getHandlersAsList() { - return new ArrayList<>(this.commands.values()); - } - - public Map getHandlers() { - return this.commands; - } - - /** - * Returns a handler by label/alias. - * - * @param label The command label. - * @return The command handler. - */ - public CommandHandler getHandler(String label) { - CommandHandler handler = this.commands.get(label); - if (handler == null) { - // Try getting by alias - handler = this.aliases.get(label); - } - return handler; - } - - private Player getTargetPlayer(String playerId, Player player, Player targetPlayer, List args) { - // Top priority: If any @UID argument is present, override targetPlayer with it. - for (int i = 0; i < args.size(); i++) { - String arg = args.get(i); - if (arg.startsWith("@")) { - arg = args.remove(i).substring(1); - if (arg.equals("")) { - // This is a special case to target nothing, distinct from failing to assign a target. - // This is specifically to allow in-game players to run a command without targeting themselves or anyone else. - return null; - } - int uid = getUidFromString(arg); - if (uid == INVALID_UID) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid"); - throw new IllegalArgumentException(); - } - targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); - if (targetPlayer == null) { - CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); - throw new IllegalArgumentException(); - } - return targetPlayer; - } - } - - // Next priority: If we invoked with a target, use that. - // By default, this only happens when you message another player in-game with a command. - if (targetPlayer != null) { - return targetPlayer; - } - - // Next priority: Use previously-set target. (see /target [[@]UID]) - if (targetPlayerIds.containsKey(playerId)) { - targetPlayer = Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.getInt(playerId), true); - // We check every time in case the target is deleted after being targeted - if (targetPlayer == null) { - CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); - throw new IllegalArgumentException(); - } - return targetPlayer; - } - - // Lowest priority: Target the player invoking the command. In the case of the console, this will return null. - return player; - } - - private boolean setPlayerTarget(String playerId, Player player, String targetUid) { - if (targetUid.equals("")) { // Clears the default targetPlayer. - targetPlayerIds.removeInt(playerId); - CommandHandler.sendTranslatedMessage(player, "commands.execution.clear_target"); - return true; - } - - // Sets default targetPlayer to the UID provided. - int uid = getUidFromString(targetUid); - if (uid == INVALID_UID) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid"); - return false; - } - Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); - if (targetPlayer == null) { - CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); - return false; - } - - targetPlayerIds.put(playerId, uid); - String target = uid + " (" + targetPlayer.getAccount().getUsername() + ")"; - CommandHandler.sendTranslatedMessage(player, "commands.execution.set_target", target); - CommandHandler.sendTranslatedMessage(player, targetPlayer.isOnline() ? "commands.execution.set_target_online" : "commands.execution.set_target_offline", target); - return true; - } - - /** - * Invoke a command handler with the given arguments. - * - * @param player The player invoking the command or null for the server console. - * @param rawMessage The messaged used to invoke the command. - */ - public void invoke(Player player, Player targetPlayer, String rawMessage) { - // The console outputs in-game command. [{Account Username} (Player UID: {Player Uid})] - if (SERVER.logCommands) { - if (player != null) { - Grasscutter.getLogger().info("Command used by [" + player.getAccount().getUsername() + " (Player UID: " + player.getUid() + ")]: " + rawMessage); - } else { - Grasscutter.getLogger().info("Command used by server console: " + rawMessage); - } - } - - rawMessage = rawMessage.trim(); - if (rawMessage.length() == 0) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.not_specified"); - return; - } - - // Parse message. - String[] split = rawMessage.split(" "); - String label = split[0].toLowerCase(); - List args = new ArrayList<>(Arrays.asList(split).subList(1, split.length)); - String playerId = (player == null) ? consoleId : player.getAccount().getId(); - - // Check for special cases - currently only target command. - if (label.startsWith("@")) { // @[UID] - this.setPlayerTarget(playerId, player, label.substring(1)); - return; - } else if (label.equalsIgnoreCase("target")) { // target [[@]UID] - if (args.size() > 0) { - String targetUidStr = args.get(0); - if (targetUidStr.startsWith("@")) { - targetUidStr = targetUidStr.substring(1); - } - this.setPlayerTarget(playerId, player, targetUidStr); - return; - } else { - this.setPlayerTarget(playerId, player, ""); - return; - } - } - - // Get command handler. - CommandHandler handler = this.getHandler(label); - - // Check if the handler is null. - if (handler == null) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.unknown_command", label); - return; - } - - // Get the command's annotation. - Command annotation = this.annotations.get(label); - - // Resolve targetPlayer - try { - targetPlayer = getTargetPlayer(playerId, player, targetPlayer, args); - } catch (IllegalArgumentException e) { - return; - } - - // Check for permissions. - if (!Grasscutter.getPermissionHandler().checkPermission(player, targetPlayer, annotation.permission(), this.annotations.get(label).permissionTargeted())) { - return; - } - - // Check if command has unfulfilled constraints on targetPlayer - Command.TargetRequirement targetRequirement = annotation.targetRequirement(); - if (targetRequirement != Command.TargetRequirement.NONE) { - if (targetPlayer == null) { - handler.sendUsageMessage(player); - CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target"); - return; - } - - if ((targetRequirement == Command.TargetRequirement.ONLINE) && !targetPlayer.isOnline()) { - handler.sendUsageMessage(player); - CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_online"); - return; - } - - if ((targetRequirement == Command.TargetRequirement.OFFLINE) && targetPlayer.isOnline()) { - handler.sendUsageMessage(player); - CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_offline"); - return; - } - } - - // Copy player and handler to final properties. - final Player targetPlayerF = targetPlayer; // Is there a better way to do this? - final CommandHandler handlerF = handler; // Is there a better way to do this? - - // Invoke execute method for handler. - Runnable runnable = () -> handlerF.execute(player, targetPlayerF, args); - if (annotation.threading()) { - new Thread(runnable).start(); - } else { - runnable.run(); - } - } - - /** - * Scans for all classes annotated with {@link Command} and registers them. - */ - private void scan() { - Reflections reflector = Grasscutter.reflector; - Set> classes = reflector.getTypesAnnotatedWith(Command.class); - - classes.forEach(annotated -> { - try { - Command cmdData = annotated.getAnnotation(Command.class); - Object object = annotated.getDeclaredConstructor().newInstance(); - if (object instanceof CommandHandler) - this.registerCommand(cmdData.label(), (CommandHandler) object); - else Grasscutter.getLogger().error("Class " + annotated.getName() + " is not a CommandHandler!"); - } catch (Exception exception) { - Grasscutter.getLogger().error("Failed to register command handler for " + annotated.getSimpleName(), exception); - } - }); - } -} +package emu.grasscutter.command; + +import static emu.grasscutter.config.Configuration.SERVER; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.*; +import org.reflections.Reflections; + +@SuppressWarnings({"UnusedReturnValue", "unused"}) +public final class CommandMap { + private static final int INVALID_UID = Integer.MIN_VALUE; + private static final String consoleId = "console"; + private final Map commands = new TreeMap<>(); + private final Map aliases = new TreeMap<>(); + private final Map annotations = new TreeMap<>(); + private final Object2IntMap targetPlayerIds = new Object2IntOpenHashMap<>(); + + public CommandMap() { + this(false); + } + + public CommandMap(boolean scan) { + if (scan) this.scan(); + } + + public static CommandMap getInstance() { + return Grasscutter.getCommandMap(); + } + + private static int getUidFromString(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException ignored) { + var account = DatabaseHelper.getAccountByName(input); + if (account == null) return INVALID_UID; + var player = DatabaseHelper.getPlayerByAccount(account); + if (player == null) return INVALID_UID; + // We will be immediately fetching the player again after this, + // but offline vs online Player safety is more important than saving a lookup + return player.getUid(); + } + } + + /** + * Register a command handler. + * + * @param label The command label. + * @param command The command handler. + * @return Instance chaining. + */ + public CommandMap registerCommand(String label, CommandHandler command) { + Grasscutter.getLogger().debug("Registered command: " + label); + label = label.toLowerCase(); + + // Get command data. + Command annotation = command.getClass().getAnnotation(Command.class); + this.annotations.put(label, annotation); + this.commands.put(label, command); + + // Register aliases. + for (String alias : annotation.aliases()) { + this.aliases.put(alias, command); + this.annotations.put(alias, annotation); + } + return this; + } + + /** + * Removes a registered command handler. + * + * @param label The command label. + * @return Instance chaining. + */ + public CommandMap unregisterCommand(String label) { + Grasscutter.getLogger().debug("Unregistered command: " + label); + + CommandHandler handler = this.commands.get(label); + if (handler == null) return this; + + Command annotation = handler.getClass().getAnnotation(Command.class); + this.annotations.remove(label); + this.commands.remove(label); + + // Unregister aliases. + for (String alias : annotation.aliases()) { + this.aliases.remove(alias); + this.annotations.remove(alias); + } + + return this; + } + + public List getAnnotationsAsList() { + return new ArrayList<>(this.annotations.values()); + } + + public Map getAnnotations() { + return new LinkedHashMap<>(this.annotations); + } + + /** + * Returns a list of all registered commands. + * + * @return All command handlers as a list. + */ + public List getHandlersAsList() { + return new ArrayList<>(this.commands.values()); + } + + public Map getHandlers() { + return this.commands; + } + + /** + * Returns a handler by label/alias. + * + * @param label The command label. + * @return The command handler. + */ + public CommandHandler getHandler(String label) { + CommandHandler handler = this.commands.get(label); + if (handler == null) { + // Try getting by alias + handler = this.aliases.get(label); + } + return handler; + } + + private Player getTargetPlayer( + String playerId, Player player, Player targetPlayer, List args) { + // Top priority: If any @UID argument is present, override targetPlayer with it. + for (int i = 0; i < args.size(); i++) { + String arg = args.get(i); + if (arg.startsWith("@")) { + arg = args.remove(i).substring(1); + if (arg.equals("")) { + // This is a special case to target nothing, distinct from failing to assign a target. + // This is specifically to allow in-game players to run a command without targeting + // themselves or anyone else. + return null; + } + int uid = getUidFromString(arg); + if (uid == INVALID_UID) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid"); + throw new IllegalArgumentException(); + } + targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); + if (targetPlayer == null) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); + throw new IllegalArgumentException(); + } + return targetPlayer; + } + } + + // Next priority: If we invoked with a target, use that. + // By default, this only happens when you message another player in-game with a command. + if (targetPlayer != null) { + return targetPlayer; + } + + // Next priority: Use previously-set target. (see /target [[@]UID]) + if (targetPlayerIds.containsKey(playerId)) { + targetPlayer = + Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.getInt(playerId), true); + // We check every time in case the target is deleted after being targeted + if (targetPlayer == null) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); + throw new IllegalArgumentException(); + } + return targetPlayer; + } + + // Lowest priority: Target the player invoking the command. In the case of the console, this + // will return null. + return player; + } + + private boolean setPlayerTarget(String playerId, Player player, String targetUid) { + if (targetUid.equals("")) { // Clears the default targetPlayer. + targetPlayerIds.removeInt(playerId); + CommandHandler.sendTranslatedMessage(player, "commands.execution.clear_target"); + return true; + } + + // Sets default targetPlayer to the UID provided. + int uid = getUidFromString(targetUid); + if (uid == INVALID_UID) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid"); + return false; + } + Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); + if (targetPlayer == null) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); + return false; + } + + targetPlayerIds.put(playerId, uid); + String target = uid + " (" + targetPlayer.getAccount().getUsername() + ")"; + CommandHandler.sendTranslatedMessage(player, "commands.execution.set_target", target); + CommandHandler.sendTranslatedMessage( + player, + targetPlayer.isOnline() + ? "commands.execution.set_target_online" + : "commands.execution.set_target_offline", + target); + return true; + } + + /** + * Invoke a command handler with the given arguments. + * + * @param player The player invoking the command or null for the server console. + * @param rawMessage The messaged used to invoke the command. + */ + public void invoke(Player player, Player targetPlayer, String rawMessage) { + // The console outputs in-game command. [{Account Username} (Player UID: {Player Uid})] + if (SERVER.logCommands) { + if (player != null) { + Grasscutter.getLogger() + .info( + "Command used by [" + + player.getAccount().getUsername() + + " (Player UID: " + + player.getUid() + + ")]: " + + rawMessage); + } else { + Grasscutter.getLogger().info("Command used by server console: " + rawMessage); + } + } + + rawMessage = rawMessage.trim(); + if (rawMessage.length() == 0) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.not_specified"); + return; + } + + // Parse message. + String[] split = rawMessage.split(" "); + String label = split[0].toLowerCase(); + List args = new ArrayList<>(Arrays.asList(split).subList(1, split.length)); + String playerId = (player == null) ? consoleId : player.getAccount().getId(); + + // Check for special cases - currently only target command. + if (label.startsWith("@")) { // @[UID] + this.setPlayerTarget(playerId, player, label.substring(1)); + return; + } else if (label.equalsIgnoreCase("target")) { // target [[@]UID] + if (args.size() > 0) { + String targetUidStr = args.get(0); + if (targetUidStr.startsWith("@")) { + targetUidStr = targetUidStr.substring(1); + } + this.setPlayerTarget(playerId, player, targetUidStr); + return; + } else { + this.setPlayerTarget(playerId, player, ""); + return; + } + } + + // Get command handler. + CommandHandler handler = this.getHandler(label); + + // Check if the handler is null. + if (handler == null) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.unknown_command", label); + return; + } + + // Get the command's annotation. + Command annotation = this.annotations.get(label); + + // Resolve targetPlayer + try { + targetPlayer = getTargetPlayer(playerId, player, targetPlayer, args); + } catch (IllegalArgumentException e) { + return; + } + + // Check for permissions. + if (!Grasscutter.getPermissionHandler() + .checkPermission( + player, + targetPlayer, + annotation.permission(), + this.annotations.get(label).permissionTargeted())) { + return; + } + + // Check if command has unfulfilled constraints on targetPlayer + Command.TargetRequirement targetRequirement = annotation.targetRequirement(); + if (targetRequirement != Command.TargetRequirement.NONE) { + if (targetPlayer == null) { + handler.sendUsageMessage(player); + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target"); + return; + } + + if ((targetRequirement == Command.TargetRequirement.ONLINE) && !targetPlayer.isOnline()) { + handler.sendUsageMessage(player); + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_online"); + return; + } + + if ((targetRequirement == Command.TargetRequirement.OFFLINE) && targetPlayer.isOnline()) { + handler.sendUsageMessage(player); + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_offline"); + return; + } + } + + // Copy player and handler to final properties. + final Player targetPlayerF = targetPlayer; // Is there a better way to do this? + final CommandHandler handlerF = handler; // Is there a better way to do this? + + // Invoke execute method for handler. + Runnable runnable = () -> handlerF.execute(player, targetPlayerF, args); + if (annotation.threading()) { + new Thread(runnable).start(); + } else { + runnable.run(); + } + } + + /** Scans for all classes annotated with {@link Command} and registers them. */ + private void scan() { + Reflections reflector = Grasscutter.reflector; + Set> classes = reflector.getTypesAnnotatedWith(Command.class); + + classes.forEach( + annotated -> { + try { + Command cmdData = annotated.getAnnotation(Command.class); + Object object = annotated.getDeclaredConstructor().newInstance(); + if (object instanceof CommandHandler) + this.registerCommand(cmdData.label(), (CommandHandler) object); + else + Grasscutter.getLogger() + .error("Class " + annotated.getName() + " is not a CommandHandler!"); + } catch (Exception exception) { + Grasscutter.getLogger() + .error( + "Failed to register command handler for " + annotated.getSimpleName(), + exception); + } + }); + } +} diff --git a/src/main/java/emu/grasscutter/command/DefaultPermissionHandler.java b/src/main/java/emu/grasscutter/command/DefaultPermissionHandler.java index bc669d81c..593c1b924 100644 --- a/src/main/java/emu/grasscutter/command/DefaultPermissionHandler.java +++ b/src/main/java/emu/grasscutter/command/DefaultPermissionHandler.java @@ -1,32 +1,33 @@ -package emu.grasscutter.command; - -import emu.grasscutter.game.Account; -import emu.grasscutter.game.player.Player; - -public class DefaultPermissionHandler implements PermissionHandler { - @Override - public boolean EnablePermissionCommand() { - return true; - } - - @Override - public boolean checkPermission(Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted) { - if (player == null) { - return true; - } - - Account account = player.getAccount(); - if (player != targetPlayer) { // Additional permission required for targeting another player - if (!permissionNodeTargeted.isEmpty() && !account.hasPermission(permissionNodeTargeted)) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); - return false; - } - } - if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) { - CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); - return false; - } - - return true; - } -} +package emu.grasscutter.command; + +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; + +public class DefaultPermissionHandler implements PermissionHandler { + @Override + public boolean EnablePermissionCommand() { + return true; + } + + @Override + public boolean checkPermission( + Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted) { + if (player == null) { + return true; + } + + Account account = player.getAccount(); + if (player != targetPlayer) { // Additional permission required for targeting another player + if (!permissionNodeTargeted.isEmpty() && !account.hasPermission(permissionNodeTargeted)) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); + return false; + } + } + if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) { + CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); + return false; + } + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/command/PermissionHandler.java b/src/main/java/emu/grasscutter/command/PermissionHandler.java index c21ff0ca6..d16e027bc 100644 --- a/src/main/java/emu/grasscutter/command/PermissionHandler.java +++ b/src/main/java/emu/grasscutter/command/PermissionHandler.java @@ -1,9 +1,10 @@ -package emu.grasscutter.command; - -import emu.grasscutter.game.player.Player; - -public interface PermissionHandler { - boolean EnablePermissionCommand(); - - boolean checkPermission(Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted); -} +package emu.grasscutter.command; + +import emu.grasscutter.game.player.Player; + +public interface PermissionHandler { + boolean EnablePermissionCommand(); + + boolean checkPermission( + Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted); +} diff --git a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java index 1f02b5fa9..9fb70024a 100644 --- a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java @@ -1,139 +1,145 @@ -package emu.grasscutter.command.commands; - -import at.favre.lib.crypto.bcrypt.BCrypt; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.config.Configuration; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.player.Player; - -import java.util.List; - -import static emu.grasscutter.utils.Language.translate; - -@Command( - label = "account", - usage = { - "create []", // Only with EXPERIMENTAL_RealPassword == false - "delete ", - "create []", // Only with EXPERIMENTAL_RealPassword == true - "resetpass "}, // Only with EXPERIMENTAL_RealPassword == true - targetRequirement = Command.TargetRequirement.NONE) -public final class AccountCommand implements CommandHandler { - @Override - public void execute(Player sender, Player targetPlayer, List args) { - if (sender != null) { - CommandHandler.sendTranslatedMessage(sender, "commands.generic.console_execute_error"); - return; - } - - if (args.size() < 2) { - sendUsageMessage(sender); - return; - } - - String action = args.get(0); - String username = args.get(1); - - switch (action) { - default: - sendUsageMessage(sender); - return; - case "create": - int uid = 0; - String password = ""; - - if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { - if (args.size() < 3) { - CommandHandler.sendMessage(sender, "EXPERIMENTAL_RealPassword requires a password argument"); - CommandHandler.sendMessage(sender, "Usage: account create [uid]"); - return; - } - password = args.get(2); - - if (args.size() == 4) { - try { - uid = Integer.parseInt(args.get(3)); - } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid")); - if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { - CommandHandler.sendMessage(sender, "EXPERIMENTAL_RealPassword requires argument 2 to be a password, not a uid"); - CommandHandler.sendMessage(sender, "Usage: account create [uid]"); - } - return; - } - } - } else { - if (args.size() > 2) { - try { - uid = Integer.parseInt(args.get(2)); - } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid")); - return; - } - } - } - - emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithUid(username, uid); - if (account == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.account.exists")); - return; - } else { - if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { - account.setPassword(BCrypt.withDefaults().hashToString(12, password.toCharArray())); - } - account.addPermission("*"); - account.save(); // Save account to database. - - CommandHandler.sendMessage(sender, translate(sender, "commands.account.create", account.getReservedPlayerUid())); - } - return; - case "delete": - // Get the account we want to delete. - Account toDelete = DatabaseHelper.getAccountByName(username); - - if (toDelete == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account")); - return; - } - - DatabaseHelper.deleteAccount(toDelete); - CommandHandler.sendMessage(sender, translate(sender, "commands.account.delete")); - return; - case "resetpass": - if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { - CommandHandler.sendMessage(sender, "resetpass requires EXPERIMENTAL_RealPassword to be true."); - return; - } - - if (args.size() != 3) { - CommandHandler.sendMessage(sender, "Invalid Args"); - CommandHandler.sendMessage(sender, "Usage: account resetpass "); - return; - } - - Account toUpdate = DatabaseHelper.getAccountByName(username); - - if (toUpdate == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account")); - return; - } - - // Make sure player can't stay logged in with old password. - kickAccount(toUpdate); - - toUpdate.setPassword(BCrypt.withDefaults().hashToString(12, args.get(2).toCharArray())); - toUpdate.save(); - CommandHandler.sendMessage(sender, "Password Updated."); - } - } - - private void kickAccount(Account account) { - Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); - if (player != null) { - player.getSession().close(); - } - } -} +package emu.grasscutter.command.commands; + +import static emu.grasscutter.utils.Language.translate; + +import at.favre.lib.crypto.bcrypt.BCrypt; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.config.Configuration; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; +import java.util.List; + +@Command( + label = "account", + usage = { + "create []", // Only with EXPERIMENTAL_RealPassword == false + "delete ", + "create []", // Only with EXPERIMENTAL_RealPassword == true + "resetpass " + }, // Only with EXPERIMENTAL_RealPassword == true + targetRequirement = Command.TargetRequirement.NONE) +public final class AccountCommand implements CommandHandler { + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (sender != null) { + CommandHandler.sendTranslatedMessage(sender, "commands.generic.console_execute_error"); + return; + } + + if (args.size() < 2) { + sendUsageMessage(sender); + return; + } + + String action = args.get(0); + String username = args.get(1); + + switch (action) { + default: + sendUsageMessage(sender); + return; + case "create": + int uid = 0; + String password = ""; + + if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { + if (args.size() < 3) { + CommandHandler.sendMessage( + sender, "EXPERIMENTAL_RealPassword requires a password argument"); + CommandHandler.sendMessage(sender, "Usage: account create [uid]"); + return; + } + password = args.get(2); + + if (args.size() == 4) { + try { + uid = Integer.parseInt(args.get(3)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid")); + if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { + CommandHandler.sendMessage( + sender, + "EXPERIMENTAL_RealPassword requires argument 2 to be a password, not a uid"); + CommandHandler.sendMessage( + sender, "Usage: account create [uid]"); + } + return; + } + } + } else { + if (args.size() > 2) { + try { + uid = Integer.parseInt(args.get(2)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid")); + return; + } + } + } + + emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithUid(username, uid); + if (account == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.account.exists")); + return; + } else { + if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { + account.setPassword(BCrypt.withDefaults().hashToString(12, password.toCharArray())); + } + account.addPermission("*"); + account.save(); // Save account to database. + + CommandHandler.sendMessage( + sender, translate(sender, "commands.account.create", account.getReservedPlayerUid())); + } + return; + case "delete": + // Get the account we want to delete. + Account toDelete = DatabaseHelper.getAccountByName(username); + + if (toDelete == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account")); + return; + } + + DatabaseHelper.deleteAccount(toDelete); + CommandHandler.sendMessage(sender, translate(sender, "commands.account.delete")); + return; + case "resetpass": + if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) { + CommandHandler.sendMessage( + sender, "resetpass requires EXPERIMENTAL_RealPassword to be true."); + return; + } + + if (args.size() != 3) { + CommandHandler.sendMessage(sender, "Invalid Args"); + CommandHandler.sendMessage(sender, "Usage: account resetpass "); + return; + } + + Account toUpdate = DatabaseHelper.getAccountByName(username); + + if (toUpdate == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account")); + return; + } + + // Make sure player can't stay logged in with old password. + kickAccount(toUpdate); + + toUpdate.setPassword(BCrypt.withDefaults().hashToString(12, args.get(2).toCharArray())); + toUpdate.save(); + CommandHandler.sendMessage(sender, "Password Updated."); + } + } + + private void kickAccount(Account account) { + Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (player != null) { + player.getSession().close(); + } + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/AchievementCommand.java b/src/main/java/emu/grasscutter/command/commands/AchievementCommand.java index 87c730394..932580b3a 100644 --- a/src/main/java/emu/grasscutter/command/commands/AchievementCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AchievementCommand.java @@ -1,133 +1,158 @@ -package emu.grasscutter.command.commands; - -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AchievementData; -import emu.grasscutter.game.achievement.AchievementControlReturns; -import emu.grasscutter.game.achievement.Achievements; -import emu.grasscutter.game.player.Player; - -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -@Command( - label = "achievement", - usage = {"(grant|revoke) ", "progress ", "grantall", "revokeall"}, - aliases = {"am"}, - permission = "player.achievement", - permissionTargeted = "player.achievement.others", - targetRequirement = Command.TargetRequirement.PLAYER, - threading = true) -public class AchievementCommand implements CommandHandler { - private static void sendSuccessMessage(Player sender, String cmd, Object... args) { - CommandHandler.sendTranslatedMessage(sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args); - } - - private static Optional parseInt(String s) { - try { - return Optional.of(Integer.parseInt(s)); - } catch (NumberFormatException e) { - return Optional.empty(); - } - } - - private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) { - var counter = new AtomicInteger(); - GameData.getAchievementDataMap().values().stream() - .filter(AchievementData::isUsed) - .filter(AchievementData::isParent) - .forEach(data -> { - var success = achievements.grant(data.getId()); - if (success.getRet() == AchievementControlReturns.Return.SUCCESS) { - counter.addAndGet(success.getChangedAchievementStatusNum()); - } - }); - - sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname()); - } - - private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) { - var counter = new AtomicInteger(); - GameData.getAchievementDataMap().values().stream() - .filter(AchievementData::isUsed) - .filter(AchievementData::isParent) - .forEach(data -> { - var success = achievements.revoke(data.getId()); - if (success.getRet() == AchievementControlReturns.Return.SUCCESS) { - counter.addAndGet(success.getChangedAchievementStatusNum()); - } - }); - - sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname()); - } - - @Override - public void execute(Player sender, Player targetPlayer, List args) { - if (args.size() < 1) { - this.sendUsageMessage(sender); - return; - } - - var command = args.remove(0).toLowerCase(); - var achievements = Achievements.getByPlayer(targetPlayer); - switch (command) { - case "grant" -> this.grant(sender, targetPlayer, achievements, args); - case "revoke" -> this.revoke(sender, targetPlayer, achievements, args); - case "progress" -> this.progress(sender, targetPlayer, achievements, args); - case "grantall" -> grantAll(sender, targetPlayer, achievements); - case "revokeall" -> revokeAll(sender, targetPlayer, achievements); - default -> this.sendUsageMessage(sender); - } - } - - private void grant(Player sender, Player targetPlayer, Achievements achievements, List args) { - if (args.size() < 1) { - this.sendUsageMessage(sender); - } - - parseInt(args.remove(0)).ifPresentOrElse(integer -> { - var ret = achievements.grant(integer); - switch (ret.getRet()) { - case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname()); - case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey()); - case ALREADY_ACHIEVED -> - CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey(), targetPlayer.getNickname()); - } - }, () -> this.sendUsageMessage(sender)); - } - - private void revoke(Player sender, Player targetPlayer, Achievements achievements, List args) { - if (args.size() < 1) { - this.sendUsageMessage(sender); - } - - parseInt(args.remove(0)).ifPresentOrElse(integer -> { - var ret = achievements.revoke(integer); - switch (ret.getRet()) { - case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname()); - case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey()); - case NOT_YET_ACHIEVED -> - CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey(), targetPlayer.getNickname()); - } - }, () -> this.sendUsageMessage(sender)); - } - - private void progress(Player sender, Player targetPlayer, Achievements achievements, List args) { - if (args.size() < 2) { - this.sendUsageMessage(sender); - } - - parseInt(args.remove(0)).ifPresentOrElse(integer -> { - parseInt(args.remove(0)).ifPresentOrElse(progress -> { - var ret = achievements.progress(integer, progress); - switch (ret.getRet()) { - case SUCCESS -> - sendSuccessMessage(sender, "progress", targetPlayer.getNickname(), integer, progress); - case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey()); - } - }, () -> this.sendUsageMessage(sender)); - }, () -> this.sendUsageMessage(sender)); - } -} +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AchievementData; +import emu.grasscutter.game.achievement.AchievementControlReturns; +import emu.grasscutter.game.achievement.Achievements; +import emu.grasscutter.game.player.Player; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +@Command( + label = "achievement", + usage = { + "(grant|revoke) ", + "progress ", + "grantall", + "revokeall" + }, + aliases = {"am"}, + permission = "player.achievement", + permissionTargeted = "player.achievement.others", + targetRequirement = Command.TargetRequirement.PLAYER, + threading = true) +public class AchievementCommand implements CommandHandler { + private static void sendSuccessMessage(Player sender, String cmd, Object... args) { + CommandHandler.sendTranslatedMessage( + sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args); + } + + private static Optional parseInt(String s) { + try { + return Optional.of(Integer.parseInt(s)); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) { + var counter = new AtomicInteger(); + GameData.getAchievementDataMap().values().stream() + .filter(AchievementData::isUsed) + .filter(AchievementData::isParent) + .forEach( + data -> { + var success = achievements.grant(data.getId()); + if (success.getRet() == AchievementControlReturns.Return.SUCCESS) { + counter.addAndGet(success.getChangedAchievementStatusNum()); + } + }); + + sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname()); + } + + private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) { + var counter = new AtomicInteger(); + GameData.getAchievementDataMap().values().stream() + .filter(AchievementData::isUsed) + .filter(AchievementData::isParent) + .forEach( + data -> { + var success = achievements.revoke(data.getId()); + if (success.getRet() == AchievementControlReturns.Return.SUCCESS) { + counter.addAndGet(success.getChangedAchievementStatusNum()); + } + }); + + sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname()); + } + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.size() < 1) { + this.sendUsageMessage(sender); + return; + } + + var command = args.remove(0).toLowerCase(); + var achievements = Achievements.getByPlayer(targetPlayer); + switch (command) { + case "grant" -> this.grant(sender, targetPlayer, achievements, args); + case "revoke" -> this.revoke(sender, targetPlayer, achievements, args); + case "progress" -> this.progress(sender, targetPlayer, achievements, args); + case "grantall" -> grantAll(sender, targetPlayer, achievements); + case "revokeall" -> revokeAll(sender, targetPlayer, achievements); + default -> this.sendUsageMessage(sender); + } + } + + private void grant( + Player sender, Player targetPlayer, Achievements achievements, List args) { + if (args.size() < 1) { + this.sendUsageMessage(sender); + } + + parseInt(args.remove(0)) + .ifPresentOrElse( + integer -> { + var ret = achievements.grant(integer); + switch (ret.getRet()) { + case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname()); + case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage( + sender, ret.getRet().getKey()); + case ALREADY_ACHIEVED -> CommandHandler.sendTranslatedMessage( + sender, ret.getRet().getKey(), targetPlayer.getNickname()); + } + }, + () -> this.sendUsageMessage(sender)); + } + + private void revoke( + Player sender, Player targetPlayer, Achievements achievements, List args) { + if (args.size() < 1) { + this.sendUsageMessage(sender); + } + + parseInt(args.remove(0)) + .ifPresentOrElse( + integer -> { + var ret = achievements.revoke(integer); + switch (ret.getRet()) { + case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname()); + case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage( + sender, ret.getRet().getKey()); + case NOT_YET_ACHIEVED -> CommandHandler.sendTranslatedMessage( + sender, ret.getRet().getKey(), targetPlayer.getNickname()); + } + }, + () -> this.sendUsageMessage(sender)); + } + + private void progress( + Player sender, Player targetPlayer, Achievements achievements, List args) { + if (args.size() < 2) { + this.sendUsageMessage(sender); + } + + parseInt(args.remove(0)) + .ifPresentOrElse( + integer -> { + parseInt(args.remove(0)) + .ifPresentOrElse( + progress -> { + var ret = achievements.progress(integer, progress); + switch (ret.getRet()) { + case SUCCESS -> sendSuccessMessage( + sender, "progress", targetPlayer.getNickname(), integer, progress); + case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage( + sender, ret.getRet().getKey()); + } + }, + () -> this.sendUsageMessage(sender)); + }, + () -> this.sendUsageMessage(sender)); + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/AnnounceCommand.java b/src/main/java/emu/grasscutter/command/commands/AnnounceCommand.java index dbccd43de..81f5a41a9 100644 --- a/src/main/java/emu/grasscutter/command/commands/AnnounceCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AnnounceCommand.java @@ -1,73 +1,78 @@ -package emu.grasscutter.command.commands; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify; - -import java.util.Collections; -import java.util.List; -import java.util.Random; - -import static emu.grasscutter.utils.Language.translate; - -@Command(label = "announce", - usage = {"", "refresh", "(tpl|revoke) "}, - permission = "server.announce", - aliases = {"a"}, - targetRequirement = Command.TargetRequirement.NONE) -public final class AnnounceCommand implements CommandHandler { - - @Override - public void execute(Player sender, Player targetPlayer, List args) { - var manager = Grasscutter.getGameServer().getAnnouncementSystem(); - if (args.size() < 1) { - sendUsageMessage(sender); - return; - } - - switch (args.get(0)) { - case "tpl": - if (args.size() < 2) { - sendUsageMessage(sender); - return; - } - - var templateId = Integer.parseInt(args.get(1)); - var tpl = manager.getAnnounceConfigItemMap().get(templateId); - if (tpl == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.announce.not_found", templateId)); - return; - } - - manager.broadcast(Collections.singletonList(tpl)); - CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", tpl.getTemplateId())); - break; - - case "refresh": - var num = manager.refresh(); - CommandHandler.sendMessage(sender, translate(sender, "commands.announce.refresh_success", num)); - break; - - case "revoke": - if (args.size() < 2) { - sendUsageMessage(sender); - return; - } - - var templateId1 = Integer.parseInt(args.get(1)); - manager.revoke(templateId1); - CommandHandler.sendMessage(sender, translate(sender, "commands.announce.revoke_done", templateId1)); - break; - - default: - var id = new Random().nextInt(10000, 99999); - var text = String.join(" ", args); - manager.getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(text, id))); - - CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", id)); - } - - } -} +package emu.grasscutter.command.commands; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +@Command( + label = "announce", + usage = {"", "refresh", "(tpl|revoke) "}, + permission = "server.announce", + aliases = {"a"}, + targetRequirement = Command.TargetRequirement.NONE) +public final class AnnounceCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + var manager = Grasscutter.getGameServer().getAnnouncementSystem(); + if (args.size() < 1) { + sendUsageMessage(sender); + return; + } + + switch (args.get(0)) { + case "tpl": + if (args.size() < 2) { + sendUsageMessage(sender); + return; + } + + var templateId = Integer.parseInt(args.get(1)); + var tpl = manager.getAnnounceConfigItemMap().get(templateId); + if (tpl == null) { + CommandHandler.sendMessage( + sender, translate(sender, "commands.announce.not_found", templateId)); + return; + } + + manager.broadcast(Collections.singletonList(tpl)); + CommandHandler.sendMessage( + sender, translate(sender, "commands.announce.send_success", tpl.getTemplateId())); + break; + + case "refresh": + var num = manager.refresh(); + CommandHandler.sendMessage( + sender, translate(sender, "commands.announce.refresh_success", num)); + break; + + case "revoke": + if (args.size() < 2) { + sendUsageMessage(sender); + return; + } + + var templateId1 = Integer.parseInt(args.get(1)); + manager.revoke(templateId1); + CommandHandler.sendMessage( + sender, translate(sender, "commands.announce.revoke_done", templateId1)); + break; + + default: + var id = new Random().nextInt(10000, 99999); + var text = String.join(" ", args); + manager + .getOnlinePlayers() + .forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(text, id))); + + CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", id)); + } + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/BanCommand.java b/src/main/java/emu/grasscutter/command/commands/BanCommand.java index 61ce4b309..dd13616dc 100644 --- a/src/main/java/emu/grasscutter/command/commands/BanCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/BanCommand.java @@ -1,64 +1,62 @@ -package emu.grasscutter.command.commands; - -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.game.GameSession; - -import java.util.List; - -@Command( - label = "ban", - usage = {"[

- * Use `import static emu.grasscutter.Configuration.*;` - * to import all configuration constants. - */ -public final class Configuration extends ConfigContainer { - - /* - * Constants - */ - - // 'c' is short for 'config' and makes code look 'cleaner'. - public static final ConfigContainer c = config; - - public static final Locale LANGUAGE = config.language.language; - public static final Locale FALLBACK_LANGUAGE = config.language.fallback; - public static final String DOCUMENT_LANGUAGE = config.language.document; - public static final Server SERVER = config.server; - public static final Database DATABASE = config.databaseInfo; - public static final Account ACCOUNT = config.account; - public static final HTTP HTTP_INFO = config.server.http; - public static final Game GAME_INFO = config.server.game; - public static final Dispatch DISPATCH_INFO = config.server.dispatch; - public static final DebugMode DEBUG_MODE_INFO = config.server.debugMode; - public static final Encryption HTTP_ENCRYPTION = config.server.http.encryption; - public static final Policies HTTP_POLICIES = config.server.http.policies; - public static final Files HTTP_STATIC_FILES = config.server.http.files; - public static final GameOptions GAME_OPTIONS = config.server.game.gameOptions; - public static final GameOptions.InventoryLimits INVENTORY_LIMITS = config.server.game.gameOptions.inventoryLimits; - private static final String DATA_FOLDER = config.folderStructure.data; - private static final String PLUGINS_FOLDER = config.folderStructure.plugins; - private static final String SCRIPTS_FOLDER = config.folderStructure.scripts; - private static final String PACKETS_FOLDER = config.folderStructure.packets; - - /* - * Utilities - */ - @Deprecated(forRemoval = true) - public static String DATA() { - return DATA_FOLDER; - } - - @Deprecated(forRemoval = true) - public static String DATA(String path) { - return Path.of(DATA_FOLDER, path).toString(); - } - - @Deprecated(forRemoval = true) - public static Path getResourcePath(String path) { - return FileUtils.getResourcePath(path); - } - - @Deprecated(forRemoval = true) - public static String RESOURCE(String path) { - return FileUtils.getResourcePath(path).toString(); - } - - @Deprecated(forRemoval = true) - public static String PLUGIN() { - return PLUGINS_FOLDER; - } - - public static String PLUGIN(String path) { - return Path.of(PLUGINS_FOLDER, path).toString(); - } - - @Deprecated(forRemoval = true) - public static String SCRIPT(String path) { - return Path.of(SCRIPTS_FOLDER, path).toString(); - } - - @Deprecated(forRemoval = true) - public static String PACKET(String path) { - return Path.of(PACKETS_FOLDER, path).toString(); - } - - /** - * Fallback method. - * - * @param left Attempt to use. - * @param right Use if left is undefined. - * @return Left or right. - */ - public static T lr(T left, T right) { - return left == null ? right : left; - } - - /** - * {@link Configuration#lr(Object, Object)} for {@link String}s. - * - * @param left Attempt to use. - * @param right Use if left is empty. - * @return Left or right. - */ - public static String lr(String left, String right) { - return left.isEmpty() ? right : left; - } - - /** - * {@link Configuration#lr(Object, Object)} for {@link Integer}s. - * - * @param left Attempt to use. - * @param right Use if left is 0. - * @return Left or right. - */ - public static int lr(int left, int right) { - return left == 0 ? right : left; - } -} +package emu.grasscutter.config; + +import static emu.grasscutter.Grasscutter.config; + +import emu.grasscutter.utils.FileUtils; +import java.nio.file.Path; +import java.util.Locale; + +/** + * A data container for the server's configuration. + * + *

Use `import static emu.grasscutter.Configuration.*;` to import all configuration constants. + */ +public final class Configuration extends ConfigContainer { + + /* + * Constants + */ + + // 'c' is short for 'config' and makes code look 'cleaner'. + public static final ConfigContainer c = config; + + public static final Locale LANGUAGE = config.language.language; + public static final Locale FALLBACK_LANGUAGE = config.language.fallback; + public static final String DOCUMENT_LANGUAGE = config.language.document; + public static final Server SERVER = config.server; + public static final Database DATABASE = config.databaseInfo; + public static final Account ACCOUNT = config.account; + public static final HTTP HTTP_INFO = config.server.http; + public static final Game GAME_INFO = config.server.game; + public static final Dispatch DISPATCH_INFO = config.server.dispatch; + public static final DebugMode DEBUG_MODE_INFO = config.server.debugMode; + public static final Encryption HTTP_ENCRYPTION = config.server.http.encryption; + public static final Policies HTTP_POLICIES = config.server.http.policies; + public static final Files HTTP_STATIC_FILES = config.server.http.files; + public static final GameOptions GAME_OPTIONS = config.server.game.gameOptions; + public static final GameOptions.InventoryLimits INVENTORY_LIMITS = + config.server.game.gameOptions.inventoryLimits; + private static final String DATA_FOLDER = config.folderStructure.data; + private static final String PLUGINS_FOLDER = config.folderStructure.plugins; + private static final String SCRIPTS_FOLDER = config.folderStructure.scripts; + private static final String PACKETS_FOLDER = config.folderStructure.packets; + + /* + * Utilities + */ + @Deprecated(forRemoval = true) + public static String DATA() { + return DATA_FOLDER; + } + + @Deprecated(forRemoval = true) + public static String DATA(String path) { + return Path.of(DATA_FOLDER, path).toString(); + } + + @Deprecated(forRemoval = true) + public static Path getResourcePath(String path) { + return FileUtils.getResourcePath(path); + } + + @Deprecated(forRemoval = true) + public static String RESOURCE(String path) { + return FileUtils.getResourcePath(path).toString(); + } + + @Deprecated(forRemoval = true) + public static String PLUGIN() { + return PLUGINS_FOLDER; + } + + public static String PLUGIN(String path) { + return Path.of(PLUGINS_FOLDER, path).toString(); + } + + @Deprecated(forRemoval = true) + public static String SCRIPT(String path) { + return Path.of(SCRIPTS_FOLDER, path).toString(); + } + + @Deprecated(forRemoval = true) + public static String PACKET(String path) { + return Path.of(PACKETS_FOLDER, path).toString(); + } + + /** + * Fallback method. + * + * @param left Attempt to use. + * @param right Use if left is undefined. + * @return Left or right. + */ + public static T lr(T left, T right) { + return left == null ? right : left; + } + + /** + * {@link Configuration#lr(Object, Object)} for {@link String}s. + * + * @param left Attempt to use. + * @param right Use if left is empty. + * @return Left or right. + */ + public static String lr(String left, String right) { + return left.isEmpty() ? right : left; + } + + /** + * {@link Configuration#lr(Object, Object)} for {@link Integer}s. + * + * @param left Attempt to use. + * @param right Use if left is 0. + * @return Left or right. + */ + public static int lr(int left, int right) { + return left == 0 ? right : left; + } +} diff --git a/src/main/java/emu/grasscutter/data/DataLoader.java b/src/main/java/emu/grasscutter/data/DataLoader.java index 023cbc246..98a7d3567 100644 --- a/src/main/java/emu/grasscutter/data/DataLoader.java +++ b/src/main/java/emu/grasscutter/data/DataLoader.java @@ -1,147 +1,153 @@ -package emu.grasscutter.data; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.server.http.handlers.GachaHandler; -import emu.grasscutter.tools.Tools; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.JsonUtils; -import emu.grasscutter.utils.TsvUtils; -import lombok.val; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -public class DataLoader { - - /** - * Load a data file by its name. If the file isn't found within the /data directory then it will fallback to the default within the jar resources - * - * @param resourcePath The path to the data file to be loaded. - * @return InputStream of the data file. - * @throws FileNotFoundException - * @see #load(String, boolean) - */ - public static InputStream load(String resourcePath) throws FileNotFoundException { - return load(resourcePath, true); - } - - /** - * Creates an input stream reader for a data file. If the file isn't found within the /data directory then it will fallback to the default within the jar resources - * - * @param resourcePath The path to the data file to be loaded. - * @return InputStreamReader of the data file. - * @throws IOException - * @throws FileNotFoundException - * @see #load(String, boolean) - */ - public static InputStreamReader loadReader(String resourcePath) throws IOException, FileNotFoundException { - try { - InputStream is = load(resourcePath, true); - return new InputStreamReader(is); - } catch (FileNotFoundException exception) { - throw exception; - } - } - - /** - * Load a data file by its name. - * - * @param resourcePath The path to the data file to be loaded. - * @param useFallback If the file does not exist in the /data directory, should it use the default file in the jar? - * @return InputStream of the data file. - * @throws FileNotFoundException - */ - public static InputStream load(String resourcePath, boolean useFallback) throws FileNotFoundException { - Path path = useFallback - ? FileUtils.getDataPath(resourcePath) - : FileUtils.getDataUserPath(resourcePath); - if (Files.exists(path)) { - // Data is in the resource directory - try { - return Files.newInputStream(path); - } catch (IOException e) { - throw new FileNotFoundException(e.getMessage()); // This is evil but so is changing the function signature at this point - } - } - return null; - } - - public static T loadClass(String resourcePath, Class classType) throws IOException { - try (InputStreamReader reader = loadReader(resourcePath)) { - return JsonUtils.loadToClass(reader, classType); - } - } - - public static List loadList(String resourcePath, Class classType) throws IOException { - try (InputStreamReader reader = loadReader(resourcePath)) { - return JsonUtils.loadToList(reader, classType); - } - } - - public static Map loadMap(String resourcePath, Class keyType, Class valueType) throws IOException { - try (InputStreamReader reader = loadReader(resourcePath)) { - return JsonUtils.loadToMap(reader, keyType, valueType); - } - } - - public static List loadTableToList(String resourcePath, Class classType) throws IOException { - val path = FileUtils.getDataPathTsjJsonTsv(resourcePath); - Grasscutter.getLogger().debug("Loading data table from: " + path); - return switch (FileUtils.getFileExtension(path)) { - case "json" -> JsonUtils.loadToList(path, classType); - case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType); - case "tsv" -> TsvUtils.loadTsvToListSetField(path, classType); - default -> null; - }; - } - - public static void checkAllFiles() { - try { - List filenames = FileUtils.getPathsFromResource("/defaults/data/"); - - if (filenames == null) { - Grasscutter.getLogger().error("We were unable to locate your default data files."); - } //else for (Path file : filenames) { - // String relativePath = String.valueOf(file).split("defaults[\\\\\\/]data[\\\\\\/]")[1]; - - // checkAndCopyData(relativePath); - // } - } catch (Exception e) { - Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e); - } - - generateGachaMappings(); - } - - private static void checkAndCopyData(String name) { - // TODO: Revisit this if default dumping is ever reintroduced - Path filePath = FileUtils.getDataPath(name); - - if (!Files.exists(filePath)) { - var root = filePath.getParent(); - if (root.toFile().mkdirs()) - Grasscutter.getLogger().info("Created data folder '" + root + "'"); - - Grasscutter.getLogger().debug("Creating default '" + name + "' data"); - FileUtils.copyResource("/defaults/data/" + name, filePath.toString()); - } - } - - private static void generateGachaMappings() { - var path = GachaHandler.getGachaMappingsPath(); - if (!Files.exists(path)) { - try { - Grasscutter.getLogger().debug("Creating default '" + path + "' data"); - Tools.createGachaMappings(path); - } catch (Exception exception) { - Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception); - } - } - } -} +package emu.grasscutter.data; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.server.http.handlers.GachaHandler; +import emu.grasscutter.tools.Tools; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.JsonUtils; +import emu.grasscutter.utils.TsvUtils; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import lombok.val; + +public class DataLoader { + + /** + * Load a data file by its name. If the file isn't found within the /data directory then it will + * fallback to the default within the jar resources + * + * @param resourcePath The path to the data file to be loaded. + * @return InputStream of the data file. + * @throws FileNotFoundException + * @see #load(String, boolean) + */ + public static InputStream load(String resourcePath) throws FileNotFoundException { + return load(resourcePath, true); + } + + /** + * Creates an input stream reader for a data file. If the file isn't found within the /data + * directory then it will fallback to the default within the jar resources + * + * @param resourcePath The path to the data file to be loaded. + * @return InputStreamReader of the data file. + * @throws IOException + * @throws FileNotFoundException + * @see #load(String, boolean) + */ + public static InputStreamReader loadReader(String resourcePath) + throws IOException, FileNotFoundException { + try { + InputStream is = load(resourcePath, true); + return new InputStreamReader(is); + } catch (FileNotFoundException exception) { + throw exception; + } + } + + /** + * Load a data file by its name. + * + * @param resourcePath The path to the data file to be loaded. + * @param useFallback If the file does not exist in the /data directory, should it use the default + * file in the jar? + * @return InputStream of the data file. + * @throws FileNotFoundException + */ + public static InputStream load(String resourcePath, boolean useFallback) + throws FileNotFoundException { + Path path = + useFallback ? FileUtils.getDataPath(resourcePath) : FileUtils.getDataUserPath(resourcePath); + if (Files.exists(path)) { + // Data is in the resource directory + try { + return Files.newInputStream(path); + } catch (IOException e) { + throw new FileNotFoundException( + e.getMessage()); // This is evil but so is changing the function signature at this point + } + } + return null; + } + + public static T loadClass(String resourcePath, Class classType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return JsonUtils.loadToClass(reader, classType); + } + } + + public static List loadList(String resourcePath, Class classType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return JsonUtils.loadToList(reader, classType); + } + } + + public static Map loadMap( + String resourcePath, Class keyType, Class valueType) throws IOException { + try (InputStreamReader reader = loadReader(resourcePath)) { + return JsonUtils.loadToMap(reader, keyType, valueType); + } + } + + public static List loadTableToList(String resourcePath, Class classType) + throws IOException { + val path = FileUtils.getDataPathTsjJsonTsv(resourcePath); + Grasscutter.getLogger().debug("Loading data table from: " + path); + return switch (FileUtils.getFileExtension(path)) { + case "json" -> JsonUtils.loadToList(path, classType); + case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType); + case "tsv" -> TsvUtils.loadTsvToListSetField(path, classType); + default -> null; + }; + } + + public static void checkAllFiles() { + try { + List filenames = FileUtils.getPathsFromResource("/defaults/data/"); + + if (filenames == null) { + Grasscutter.getLogger().error("We were unable to locate your default data files."); + } // else for (Path file : filenames) { + // String relativePath = String.valueOf(file).split("defaults[\\\\\\/]data[\\\\\\/]")[1]; + + // checkAndCopyData(relativePath); + // } + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e); + } + + generateGachaMappings(); + } + + private static void checkAndCopyData(String name) { + // TODO: Revisit this if default dumping is ever reintroduced + Path filePath = FileUtils.getDataPath(name); + + if (!Files.exists(filePath)) { + var root = filePath.getParent(); + if (root.toFile().mkdirs()) + Grasscutter.getLogger().info("Created data folder '" + root + "'"); + + Grasscutter.getLogger().debug("Creating default '" + name + "' data"); + FileUtils.copyResource("/defaults/data/" + name, filePath.toString()); + } + } + + private static void generateGachaMappings() { + var path = GachaHandler.getGachaMappingsPath(); + if (!Files.exists(path)) { + try { + Grasscutter.getLogger().debug("Creating default '" + path + "' data"); + Tools.createGachaMappings(path); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 6418b0917..6b92c1dd5 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -1,346 +1,475 @@ -package emu.grasscutter.data; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.binout.*; -import emu.grasscutter.data.excels.*; -import emu.grasscutter.game.quest.QuestEncryptionKey; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.*; -import lombok.Getter; -import lombok.experimental.Tolerate; - -import java.lang.reflect.Field; -import java.util.*; - -public class GameData { - protected static final Map abilityDataMap = new HashMap<>(); - protected static final Int2ObjectMap scenePointEntryMap = new Int2ObjectOpenHashMap<>(); - // BinOutputs - @Getter - private static final Int2ObjectMap homeworldDefaultSaveData = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap abilityHashes = new Int2ObjectOpenHashMap<>(); - @Deprecated(forRemoval = true) - @Getter - private static final Map abilityModifiers = new HashMap<>(); - @Getter - private static final Map gadgetConfigData = new HashMap<>(); - @Getter - private static final Map openConfigEntries = new HashMap<>(); - @Deprecated(forRemoval = true) - @Getter - private static final Map scenePointEntries = new HashMap<>(); - private static final Int2ObjectMap mainQuestData = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap questsKeys = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap npcBornData = new Int2ObjectOpenHashMap<>(); - private static final Map abilityEmbryos = new HashMap<>(); - - // ExcelConfigs - @Getter - private static final ArrayList codexReliquaryArrayList = new ArrayList<>(); - private static final Int2ObjectMap achievementDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap achievementGoalDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap activityDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap activityShopDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap activityWatcherDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarCostumeDataItemIdMap = new Int2ObjectLinkedOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarCostumeDataMap = new Int2ObjectLinkedOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarFetterLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarFlycloakDataMap = new Int2ObjectLinkedOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarSkillDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap avatarTalentDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap battlePassMissionDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap battlePassRewardDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap blossomRefreshExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap buffDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap chapterDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap cityDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap codexAnimalDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap codexMaterialDataIdMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap codexQuestDataIdMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap codexReliquaryDataIdMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap codexWeaponDataIdMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap cookBonusDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap cookRecipeDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap compoundDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap dungeonEntryDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap envAnimalGatherConfigDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap equipAffixDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap forgeDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap gadgetDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap gatherDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap homeWorldBgmDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap investigationMonsterDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap itemDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap monsterCurveDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap monsterDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap monsterDescribeDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap musicGameBasicDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap npcDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap openStateDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap personalLineDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap playerLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap proudSkillDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap questDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap reliquaryAffixDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap reliquaryMainPropDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap reliquarySetDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>(); - @Getter - private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap triggerExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap weaponCurveDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap weaponLevelDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap weaponPromoteDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap weatherDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap worldAreaDataMap = new Int2ObjectOpenHashMap<>(); - @Getter - private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap avatarPromoteDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap reliquaryLevelDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap shopGoodsDataMap = new Int2ObjectOpenHashMap<>(); - // The following are accessed via getMapByResourceDef, and will show as unused - private static final Int2ObjectMap codexMaterialDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap codexQuestDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap codexReliquaryDataMap = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap codexWeaponDataMap = new Int2ObjectOpenHashMap<>(); - - // Cache - @Getter - private static final IntList scenePointIdList = new IntArrayList(); - @Getter - private static final List openStateList = new ArrayList<>(); - @Getter - private static final Map> scenePointsPerScene = new HashMap<>(); - @Getter - private static final Map scriptSceneDataMap = new HashMap<>(); - protected static Int2ObjectMap proudSkillGroupLevels = new Int2ObjectOpenHashMap<>(); - protected static Int2IntMap proudSkillGroupMaxLevels = new Int2IntOpenHashMap(); - protected static Int2ObjectMap avatarSkillLevels = new Int2ObjectOpenHashMap<>(); - private static final Map> fetters = new HashMap<>(); - private static final Map> shopGoods = new HashMap<>(); - - // Getters with wrong names, remove later - @Deprecated(forRemoval = true) - public static Int2ObjectMap getcodexReliquaryIdMap() { - return codexReliquaryDataIdMap; - } - - @Deprecated(forRemoval = true) - public static Int2ObjectMap getDungeonEntryDatatMap() { - return dungeonEntryDataMap; - } - - @Deprecated(forRemoval = true) - @Tolerate - public static ArrayList getcodexReliquaryArrayList() { - return codexReliquaryArrayList; - } - - // Getters with different names that stay for now - public static Int2ObjectMap getMainQuestDataMap() { - return mainQuestData; - } - - public static Int2ObjectMap getMainQuestEncryptionMap() { - return questsKeys; - } - - public static Int2ObjectMap getSceneNpcBornData() { - return npcBornData; - } - - public static Map getAbilityEmbryoInfo() { - return abilityEmbryos; - } - - // Getters that get values rather than containers. If Lombok ever gets syntactic sugar for this, we should adopt that. - public static AbilityData getAbilityData(String abilityName) { - return abilityDataMap.get(abilityName); - } - - public static IntSet getAvatarSkillLevels(int avatarSkillId) { - return avatarSkillLevels.get(avatarSkillId); - } - - public static IntSet getProudSkillGroupLevels(int proudSkillGroupId) { - return proudSkillGroupLevels.get(proudSkillGroupId); - } - - public static int getProudSkillGroupMaxLevel(int proudSkillGroupId) { - return proudSkillGroupMaxLevels.getOrDefault(proudSkillGroupId, 0); - } - - // Multi-keyed getters - public static AvatarPromoteData getAvatarPromoteData(int promoteId, int promoteLevel) { - return avatarPromoteDataMap.get((promoteId << 8) + promoteLevel); - } - - public static WeaponPromoteData getWeaponPromoteData(int promoteId, int promoteLevel) { - return weaponPromoteDataMap.get((promoteId << 8) + promoteLevel); - } - - public static ReliquaryLevelData getRelicLevelData(int rankLevel, int level) { - return reliquaryLevelDataMap.get((rankLevel << 8) + level); - } - - public static ScenePointEntry getScenePointEntryById(int sceneId, int pointId) { - return scenePointEntryMap.get((sceneId << 16) + pointId); - } - - // Non-nullable value getters - public static int getAvatarLevelExpRequired(int level) { - return Optional.ofNullable(avatarLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); - } - - public static int getAvatarFetterLevelExpRequired(int level) { - return Optional.ofNullable(avatarFetterLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); - } - - public static int getRelicExpRequired(int rankLevel, int level) { - return Optional.ofNullable(getRelicLevelData(rankLevel, level)).map(d -> d.getExp()).orElse(0); - } - - - // Generic getter - public static Int2ObjectMap getMapByResourceDef(Class resourceDefinition) { - Int2ObjectMap map = null; - - try { - Field field = GameData.class.getDeclaredField(Utils.lowerCaseFirstChar(resourceDefinition.getSimpleName()) + "Map"); - - field.setAccessible(true); - map = (Int2ObjectMap) field.get(null); - field.setAccessible(false); - } catch (Exception e) { - Grasscutter.getLogger().error("Error fetching resource map for " + resourceDefinition.getSimpleName(), e); - } - - return map; - } - - - public static int getWeaponExpRequired(int rankLevel, int level) { - WeaponLevelData levelData = weaponLevelDataMap.get(level); - if (levelData == null) { - return 0; - } - try { - return levelData.getRequiredExps()[rankLevel - 1]; - } catch (Exception e) { - return 0; - } - } - - public static Map> getFetterDataEntries() { - if (fetters.isEmpty()) { - fetterDataMap.forEach((k, v) -> { - if (!fetters.containsKey(v.getAvatarId())) { - fetters.put(v.getAvatarId(), new ArrayList<>()); - } - fetters.get(v.getAvatarId()).add(k); - }); - } - - return fetters; - } - - public static Map> getShopGoodsDataEntries() { - if (shopGoods.isEmpty()) { - shopGoodsDataMap.forEach((k, v) -> { - if (!shopGoods.containsKey(v.getShopType())) - shopGoods.put(v.getShopType(), new ArrayList<>()); - shopGoods.get(v.getShopType()).add(v); - }); - } - - return shopGoods; - } - - public static Int2ObjectMap getAchievementDataMap() { - AchievementData.divideIntoGroups(); - return achievementDataMap; - } -} +package emu.grasscutter.data; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.*; +import emu.grasscutter.data.excels.*; +import emu.grasscutter.game.quest.QuestEncryptionKey; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.*; +import java.lang.reflect.Field; +import java.util.*; +import lombok.Getter; +import lombok.experimental.Tolerate; + +public class GameData { + protected static final Map abilityDataMap = new HashMap<>(); + protected static final Int2ObjectMap scenePointEntryMap = + new Int2ObjectOpenHashMap<>(); + // BinOutputs + @Getter + private static final Int2ObjectMap homeworldDefaultSaveData = + new Int2ObjectOpenHashMap<>(); + + @Getter private static final Int2ObjectMap abilityHashes = new Int2ObjectOpenHashMap<>(); + + @Deprecated(forRemoval = true) + @Getter + private static final Map abilityModifiers = new HashMap<>(); + + @Getter private static final Map gadgetConfigData = new HashMap<>(); + @Getter private static final Map openConfigEntries = new HashMap<>(); + + @Deprecated(forRemoval = true) + @Getter + private static final Map scenePointEntries = new HashMap<>(); + + private static final Int2ObjectMap mainQuestData = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap questsKeys = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap npcBornData = new Int2ObjectOpenHashMap<>(); + private static final Map abilityEmbryos = new HashMap<>(); + + // ExcelConfigs + @Getter + private static final ArrayList codexReliquaryArrayList = new ArrayList<>(); + + private static final Int2ObjectMap achievementDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap achievementGoalDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap activityDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap activityShopDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap activityWatcherDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarCostumeDataItemIdMap = + new Int2ObjectLinkedOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarCostumeDataMap = + new Int2ObjectLinkedOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarCurveDataMap = + new Int2ObjectLinkedOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarFetterLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarFlycloakDataMap = + new Int2ObjectLinkedOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarSkillDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarSkillDepotDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap avatarTalentDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap battlePassMissionDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap battlePassRewardDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap + blossomRefreshExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter private static final Int2ObjectMap buffDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap chapterDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter private static final Int2ObjectMap cityDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap codexAnimalDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap codexMaterialDataIdMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap codexQuestDataIdMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap codexReliquaryDataIdMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap codexWeaponDataIdMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap cookBonusDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap cookRecipeDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap compoundDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap dailyDungeonDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap dungeonEntryDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap envAnimalGatherConfigDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap equipAffixDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap fetterCharacterCardDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap forgeDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap furnitureMakeConfigDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap gadgetDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap gatherDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap homeWorldBgmDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap homeWorldLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap investigationMonsterDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter private static final Int2ObjectMap itemDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap monsterCurveDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap monsterDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap monsterDescribeDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap musicGameBasicDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter private static final Int2ObjectMap npcDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap openStateDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap personalLineDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap playerLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap proudSkillDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap questDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap reliquaryAffixDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap reliquaryMainPropDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap reliquarySetDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap rewardPreviewDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap towerFloorDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap towerLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap towerScheduleDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap triggerExcelConfigDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap weaponCurveDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap weaponLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap weaponPromoteDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap weatherDataMap = new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap worldAreaDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap worldLevelDataMap = + new Int2ObjectOpenHashMap<>(); + + private static final Int2ObjectMap avatarPromoteDataMap = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap reliquaryLevelDataMap = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap shopGoodsDataMap = + new Int2ObjectOpenHashMap<>(); + // The following are accessed via getMapByResourceDef, and will show as unused + private static final Int2ObjectMap codexMaterialDataMap = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexQuestDataMap = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexReliquaryDataMap = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexWeaponDataMap = + new Int2ObjectOpenHashMap<>(); + + // Cache + @Getter private static final IntList scenePointIdList = new IntArrayList(); + @Getter private static final List openStateList = new ArrayList<>(); + @Getter private static final Map> scenePointsPerScene = new HashMap<>(); + @Getter private static final Map scriptSceneDataMap = new HashMap<>(); + protected static Int2ObjectMap proudSkillGroupLevels = new Int2ObjectOpenHashMap<>(); + protected static Int2IntMap proudSkillGroupMaxLevels = new Int2IntOpenHashMap(); + protected static Int2ObjectMap avatarSkillLevels = new Int2ObjectOpenHashMap<>(); + private static final Map> fetters = new HashMap<>(); + private static final Map> shopGoods = new HashMap<>(); + + // Getters with wrong names, remove later + @Deprecated(forRemoval = true) + public static Int2ObjectMap getcodexReliquaryIdMap() { + return codexReliquaryDataIdMap; + } + + @Deprecated(forRemoval = true) + public static Int2ObjectMap getDungeonEntryDatatMap() { + return dungeonEntryDataMap; + } + + @Deprecated(forRemoval = true) + @Tolerate + public static ArrayList getcodexReliquaryArrayList() { + return codexReliquaryArrayList; + } + + // Getters with different names that stay for now + public static Int2ObjectMap getMainQuestDataMap() { + return mainQuestData; + } + + public static Int2ObjectMap getMainQuestEncryptionMap() { + return questsKeys; + } + + public static Int2ObjectMap getSceneNpcBornData() { + return npcBornData; + } + + public static Map getAbilityEmbryoInfo() { + return abilityEmbryos; + } + + // Getters that get values rather than containers. If Lombok ever gets syntactic sugar for this, + // we should adopt that. + public static AbilityData getAbilityData(String abilityName) { + return abilityDataMap.get(abilityName); + } + + public static IntSet getAvatarSkillLevels(int avatarSkillId) { + return avatarSkillLevels.get(avatarSkillId); + } + + public static IntSet getProudSkillGroupLevels(int proudSkillGroupId) { + return proudSkillGroupLevels.get(proudSkillGroupId); + } + + public static int getProudSkillGroupMaxLevel(int proudSkillGroupId) { + return proudSkillGroupMaxLevels.getOrDefault(proudSkillGroupId, 0); + } + + // Multi-keyed getters + public static AvatarPromoteData getAvatarPromoteData(int promoteId, int promoteLevel) { + return avatarPromoteDataMap.get((promoteId << 8) + promoteLevel); + } + + public static WeaponPromoteData getWeaponPromoteData(int promoteId, int promoteLevel) { + return weaponPromoteDataMap.get((promoteId << 8) + promoteLevel); + } + + public static ReliquaryLevelData getRelicLevelData(int rankLevel, int level) { + return reliquaryLevelDataMap.get((rankLevel << 8) + level); + } + + public static ScenePointEntry getScenePointEntryById(int sceneId, int pointId) { + return scenePointEntryMap.get((sceneId << 16) + pointId); + } + + // Non-nullable value getters + public static int getAvatarLevelExpRequired(int level) { + return Optional.ofNullable(avatarLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); + } + + public static int getAvatarFetterLevelExpRequired(int level) { + return Optional.ofNullable(avatarFetterLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0); + } + + public static int getRelicExpRequired(int rankLevel, int level) { + return Optional.ofNullable(getRelicLevelData(rankLevel, level)).map(d -> d.getExp()).orElse(0); + } + + // Generic getter + public static Int2ObjectMap getMapByResourceDef(Class resourceDefinition) { + Int2ObjectMap map = null; + + try { + Field field = + GameData.class.getDeclaredField( + Utils.lowerCaseFirstChar(resourceDefinition.getSimpleName()) + "Map"); + + field.setAccessible(true); + map = (Int2ObjectMap) field.get(null); + field.setAccessible(false); + } catch (Exception e) { + Grasscutter.getLogger() + .error("Error fetching resource map for " + resourceDefinition.getSimpleName(), e); + } + + return map; + } + + public static int getWeaponExpRequired(int rankLevel, int level) { + WeaponLevelData levelData = weaponLevelDataMap.get(level); + if (levelData == null) { + return 0; + } + try { + return levelData.getRequiredExps()[rankLevel - 1]; + } catch (Exception e) { + return 0; + } + } + + public static Map> getFetterDataEntries() { + if (fetters.isEmpty()) { + fetterDataMap.forEach( + (k, v) -> { + if (!fetters.containsKey(v.getAvatarId())) { + fetters.put(v.getAvatarId(), new ArrayList<>()); + } + fetters.get(v.getAvatarId()).add(k); + }); + } + + return fetters; + } + + public static Map> getShopGoodsDataEntries() { + if (shopGoods.isEmpty()) { + shopGoodsDataMap.forEach( + (k, v) -> { + if (!shopGoods.containsKey(v.getShopType())) + shopGoods.put(v.getShopType(), new ArrayList<>()); + shopGoods.get(v.getShopType()).add(v); + }); + } + + return shopGoods; + } + + public static Int2ObjectMap getAchievementDataMap() { + AchievementData.divideIntoGroups(); + return achievementDataMap; + } +} diff --git a/src/main/java/emu/grasscutter/data/GameDepot.java b/src/main/java/emu/grasscutter/data/GameDepot.java index b9788b79a..7cf771d1f 100644 --- a/src/main/java/emu/grasscutter/data/GameDepot.java +++ b/src/main/java/emu/grasscutter/data/GameDepot.java @@ -1,78 +1,86 @@ -package emu.grasscutter.data; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.ResourceLoader.AvatarConfig; -import emu.grasscutter.data.excels.ReliquaryAffixData; -import emu.grasscutter.data.excels.ReliquaryMainPropData; -import emu.grasscutter.game.managers.blossom.BlossomConfig; -import emu.grasscutter.game.world.SpawnDataEntry; -import emu.grasscutter.utils.WeightedList; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class GameDepot { - public static final int[] BLOCK_SIZE = new int[]{50, 500};//Scales - - private static final Int2ObjectMap> relicRandomMainPropDepot = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap> relicMainPropDepot = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap> relicAffixDepot = new Int2ObjectOpenHashMap<>(); - - @Getter - @Setter - private static Map playerAbilities = new HashMap<>(); - @Getter - private static final HashMap> spawnLists = new HashMap<>(); - @Getter - @Setter - private static BlossomConfig blossomConfig; - - public static void load() { - for (ReliquaryMainPropData data : GameData.getReliquaryMainPropDataMap().values()) { - if (data.getWeight() <= 0 || data.getPropDepotId() <= 0) { - continue; - } - List list = relicMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new ArrayList<>()); - list.add(data); - WeightedList weightedList = relicRandomMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new WeightedList<>()); - weightedList.add(data.getWeight(), data); - } - for (ReliquaryAffixData data : GameData.getReliquaryAffixDataMap().values()) { - if (data.getWeight() <= 0 || data.getDepotId() <= 0) { - continue; - } - List list = relicAffixDepot.computeIfAbsent(data.getDepotId(), k -> new ArrayList<>()); - list.add(data); - } - // Let the server owner know if theyre missing weights - if (relicMainPropDepot.size() == 0 || relicAffixDepot.size() == 0) { - Grasscutter.getLogger().error("Relic properties are missing weights! Please check your ReliquaryMainPropExcelConfigData or ReliquaryAffixExcelConfigData files in your ExcelBinOutput folder."); - } - } - - public static ReliquaryMainPropData getRandomRelicMainProp(int depot) { - WeightedList depotList = relicRandomMainPropDepot.get(depot); - if (depotList == null) { - return null; - } - return depotList.next(); - } - - public static List getRelicMainPropList(int depot) { - return relicMainPropDepot.get(depot); - } - - public static List getRelicAffixList(int depot) { - return relicAffixDepot.get(depot); - } - - public static void addSpawnListById(HashMap> data) { - spawnLists.putAll(data); - } -} +package emu.grasscutter.data; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.ResourceLoader.AvatarConfig; +import emu.grasscutter.data.excels.ReliquaryAffixData; +import emu.grasscutter.data.excels.ReliquaryMainPropData; +import emu.grasscutter.game.managers.blossom.BlossomConfig; +import emu.grasscutter.game.world.SpawnDataEntry; +import emu.grasscutter.utils.WeightedList; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +public class GameDepot { + public static final int[] BLOCK_SIZE = new int[] {50, 500}; // Scales + + private static final Int2ObjectMap> relicRandomMainPropDepot = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap> relicMainPropDepot = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap> relicAffixDepot = + new Int2ObjectOpenHashMap<>(); + + @Getter @Setter private static Map playerAbilities = new HashMap<>(); + + @Getter + private static final HashMap> spawnLists = + new HashMap<>(); + + @Getter @Setter private static BlossomConfig blossomConfig; + + public static void load() { + for (ReliquaryMainPropData data : GameData.getReliquaryMainPropDataMap().values()) { + if (data.getWeight() <= 0 || data.getPropDepotId() <= 0) { + continue; + } + List list = + relicMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new ArrayList<>()); + list.add(data); + WeightedList weightedList = + relicRandomMainPropDepot.computeIfAbsent( + data.getPropDepotId(), k -> new WeightedList<>()); + weightedList.add(data.getWeight(), data); + } + for (ReliquaryAffixData data : GameData.getReliquaryAffixDataMap().values()) { + if (data.getWeight() <= 0 || data.getDepotId() <= 0) { + continue; + } + List list = + relicAffixDepot.computeIfAbsent(data.getDepotId(), k -> new ArrayList<>()); + list.add(data); + } + // Let the server owner know if theyre missing weights + if (relicMainPropDepot.size() == 0 || relicAffixDepot.size() == 0) { + Grasscutter.getLogger() + .error( + "Relic properties are missing weights! Please check your ReliquaryMainPropExcelConfigData or ReliquaryAffixExcelConfigData files in your ExcelBinOutput folder."); + } + } + + public static ReliquaryMainPropData getRandomRelicMainProp(int depot) { + WeightedList depotList = relicRandomMainPropDepot.get(depot); + if (depotList == null) { + return null; + } + return depotList.next(); + } + + public static List getRelicMainPropList(int depot) { + return relicMainPropDepot.get(depot); + } + + public static List getRelicAffixList(int depot) { + return relicAffixDepot.get(depot); + } + + public static void addSpawnListById( + HashMap> data) { + spawnLists.putAll(data); + } +} diff --git a/src/main/java/emu/grasscutter/data/GameResource.java b/src/main/java/emu/grasscutter/data/GameResource.java index fb2520893..661a558e3 100644 --- a/src/main/java/emu/grasscutter/data/GameResource.java +++ b/src/main/java/emu/grasscutter/data/GameResource.java @@ -1,12 +1,10 @@ -package emu.grasscutter.data; - -public abstract class GameResource { - - public int getId() { - return 0; - } - - public void onLoad() { - - } -} +package emu.grasscutter.data; + +public abstract class GameResource { + + public int getId() { + return 0; + } + + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 223066159..e0f49d7e0 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -1,563 +1,655 @@ -package emu.grasscutter.data; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.binout.*; -import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; -import emu.grasscutter.data.common.PointData; -import emu.grasscutter.game.managers.blossom.BlossomConfig; -import emu.grasscutter.game.quest.QuestEncryptionKey; -import emu.grasscutter.game.world.SpawnDataEntry; -import emu.grasscutter.game.world.SpawnDataEntry.GridBlockId; -import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; -import emu.grasscutter.scripts.SceneIndexManager; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.JsonUtils; -import emu.grasscutter.utils.TsvUtils; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntArraySet; -import lombok.val; -import org.reflections.Reflections; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import static emu.grasscutter.utils.FileUtils.getDataPath; -import static emu.grasscutter.utils.FileUtils.getResourcePath; -import static emu.grasscutter.utils.Language.translate; - -public class ResourceLoader { - - private static final Set loadedResources = new CopyOnWriteArraySet<>(); - private static boolean loadedAll = false; - - // Get a list of all resource classes, sorted by loadPriority - public static List> getResourceDefClasses() { - Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName()); - Set classes = reflections.getSubTypesOf(GameResource.class); - - List> classList = new ArrayList<>(classes.size()); - classes.forEach(o -> { - Class c = (Class) o; - if (c.getAnnotation(ResourceType.class) != null) { - classList.add(c); - } - }); - - classList.sort((a, b) -> b.getAnnotation(ResourceType.class).loadPriority().value() - a.getAnnotation(ResourceType.class).loadPriority().value()); - - return classList; - } - - // Get a list containing sets of all resource classes, sorted by loadPriority - protected static List>> getResourceDefClassesPrioritySets() { - val reflections = new Reflections(ResourceLoader.class.getPackage().getName()); - val classes = reflections.getSubTypesOf(GameResource.class); - val priorities = ResourceType.LoadPriority.getInOrder(); - Grasscutter.getLogger().debug("Priorities are " + priorities); - val map = new LinkedHashMap>>(priorities.size()); - priorities.forEach(p -> map.put(p, new HashSet<>())); - - classes.forEach(c -> { - // val c = (Class) o; - val annotation = c.getAnnotation(ResourceType.class); - if (annotation != null) { - map.get(annotation.loadPriority()).add(c); - } - }); - return List.copyOf(map.values()); - } - - public static void loadAll() { - if (loadedAll) return; - Grasscutter.getLogger().info(translate("messages.status.resources.loading")); - - // Load ability lists - loadAbilityEmbryos(); - loadOpenConfig(); - loadAbilityModifiers(); - // Load resources - loadResources(true); - // Process into depots - GameDepot.load(); - // Load spawn data and quests - loadGadgetConfigData(); - loadSpawnData(); - loadQuests(); - loadScriptSceneData(); - // Load scene points - must be done AFTER resources are loaded - loadScenePoints(); - // Load default home layout - loadHomeworldDefaultSaveData(); - loadNpcBornData(); - loadBlossomResources(); - cacheTalentLevelSets(); - - Grasscutter.getLogger().info(translate("messages.status.resources.finish")); - loadedAll = true; - } - - public static void loadResources() { - loadResources(false); - } - - public static void loadResources(boolean doReload) { - long startTime = System.nanoTime(); - val errors = new ConcurrentLinkedQueue>(); // Logger in a parallel stream will deadlock - - getResourceDefClassesPrioritySets().forEach(classes -> { - classes.stream() - .parallel().unordered() - .forEach(c -> { - val type = c.getAnnotation(ResourceType.class); - if (type == null) return; - - val map = GameData.getMapByResourceDef(c); - if (map == null) return; - - try { - loadFromResource(c, type, map, doReload); - } catch (Exception e) { - errors.add(Pair.of(Arrays.toString(type.name()), e)); - } - }); - }); - errors.forEach(pair -> Grasscutter.getLogger().error("Error loading resource file: " + pair.left(), pair.right())); - long endTime = System.nanoTime(); - long ns = (endTime - startTime); //divide by 1000000 to get milliseconds. - Grasscutter.getLogger().debug("Loading resources took " + ns + "ns == " + ns / 1000000 + "ms"); - } - - @SuppressWarnings("rawtypes") - protected static void loadFromResource(Class c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception { - val simpleName = c.getSimpleName(); - if (doReload || !loadedResources.contains(simpleName)) { - for (String name : type.name()) { - loadFromResource(c, FileUtils.getExcelPath(name), map); - } - loadedResources.add(simpleName); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - protected static void loadFromResource(Class c, Path filename, Int2ObjectMap map) throws Exception { - val results = switch (FileUtils.getFileExtension(filename)) { - case "json" -> JsonUtils.loadToList(filename, c); - case "tsj" -> TsvUtils.loadTsjToListSetField(filename, c); - case "tsv" -> TsvUtils.loadTsvToListSetField(filename, c); - default -> null; - }; - if (results == null) return; - results.forEach(o -> { - GameResource res = (GameResource) o; - res.onLoad(); - map.put(res.getId(), res); - }); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - protected static void loadFromResource(Class c, String fileName, Int2ObjectMap map) throws Exception { - JsonUtils.loadToList(getResourcePath("ExcelBinOutput/" + fileName), c).forEach(o -> { - GameResource res = (GameResource) o; - res.onLoad(); - map.put(res.getId(), res); - }); - } - - private static void loadScenePoints() { - val pattern = Pattern.compile("scene([0-9]+)_point\\.json"); - try { - Files.newDirectoryStream(getResourcePath("BinOutput/Scene/Point"), "scene*_point.json").forEach(path -> { - val matcher = pattern.matcher(path.getFileName().toString()); - if (!matcher.find()) return; - int sceneId = Integer.parseInt(matcher.group(1)); - - ScenePointConfig config; - try { - config = JsonUtils.loadToClass(path, ScenePointConfig.class); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - if (config.points == null) return; - - val scenePoints = new IntArrayList(); - config.points.forEach((pointId, pointData) -> { - val scenePoint = new ScenePointEntry(sceneId, pointData); - scenePoints.add(pointId); - pointData.setId(pointId); - - GameData.getScenePointIdList().add(pointId); - GameData.getScenePointEntries().put(scenePoint.getName(), scenePoint); - GameData.scenePointEntryMap.put((sceneId << 16) + pointId, scenePoint); - - pointData.updateDailyDungeon(); - }); - GameData.getScenePointsPerScene().put(sceneId, scenePoints); - }); - } catch (IOException e) { - Grasscutter.getLogger().error("Scene point files cannot be found, you cannot use teleport waypoints!"); - } - } - - private static void cacheTalentLevelSets() { - // All known levels, keyed by proudSkillGroupId - GameData.getProudSkillDataMap().forEach((id, data) -> - GameData.proudSkillGroupLevels - .computeIfAbsent(data.getProudSkillGroupId(), i -> new IntArraySet()) - .add(data.getLevel())); - // All known levels, keyed by avatarSkillId - GameData.getAvatarSkillDataMap().forEach((id, data) -> - GameData.avatarSkillLevels.put((int) id, GameData.proudSkillGroupLevels.get(data.getProudSkillGroupId()))); - // Maximum known levels, keyed by proudSkillGroupId - GameData.proudSkillGroupLevels.forEach((id, set) -> - GameData.proudSkillGroupMaxLevels.put((int) id, set.intStream().max().getAsInt())); - } - - private static void loadAbilityEmbryos() { - List embryoList = null; - - // Read from cached file if exists - try { - embryoList = JsonUtils.loadToList(getDataPath("AbilityEmbryos.json"), AbilityEmbryoEntry.class); - } catch (Exception ignored) { - } - - if (embryoList == null) { - // Load from BinOutput - val pattern = Pattern.compile("ConfigAvatar_(.+?)\\.json"); - - val l = new ArrayList(); - try { - Files.newDirectoryStream(getResourcePath("BinOutput/Avatar/"), "ConfigAvatar_*.json").forEach(path -> { - val matcher = pattern.matcher(path.getFileName().toString()); - if (!matcher.find()) return; - String avatarName = matcher.group(1); - AvatarConfig config; - - try { - config = JsonUtils.loadToClass(path, AvatarConfig.class); - } catch (Exception e) { - Grasscutter.getLogger().error("Error loading player ability embryos:", e); - return; - } - - if (config.abilities == null) return; - - int s = config.abilities.size(); - AbilityEmbryoEntry al = new AbilityEmbryoEntry(avatarName, config.abilities.stream().map(Object::toString).toArray(size -> new String[s])); - l.add(al); - }); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading ability embryos: no files found"); - return; - } - - embryoList = l; - - try { - GameDepot.setPlayerAbilities(JsonUtils.loadToMap(getResourcePath("BinOutput/AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"), String.class, AvatarConfig.class)); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading player abilities:", e); - } - } - - if (embryoList == null || embryoList.isEmpty()) { - Grasscutter.getLogger().error("No embryos loaded!"); - return; - } - - for (AbilityEmbryoEntry entry : embryoList) { - GameData.getAbilityEmbryoInfo().put(entry.getName(), entry); - } - } - - private static void loadAbilityModifiers() { - // Load from BinOutput - try (Stream paths = Files.walk(getResourcePath("BinOutput/Ability/Temp/"))) { - paths.filter(Files::isRegularFile).filter(path -> path.toString().endsWith(".json")).forEach(ResourceLoader::loadAbilityModifiers); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading ability modifiers: ", e); - } - // System.out.println("Loaded modifiers, found types:"); - // modifierActionTypes.stream().sorted().forEach(s -> System.out.printf("%s, ", s)); - // System.out.println("[End]"); - } - - private static void loadAbilityModifiers(Path path) { - try { - JsonUtils.loadToList(path, AbilityConfigData.class).forEach(data -> loadAbilityData(data.Default)); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading ability modifiers from path " + path.toString() + ": ", e); - } - } - - private static void loadAbilityData(AbilityData data) { - GameData.abilityDataMap.put(data.abilityName, data); - - val modifiers = data.modifiers; - if (modifiers == null || modifiers.size() == 0) return; - - String name = data.abilityName; - AbilityModifierEntry modifierEntry = new AbilityModifierEntry(name); - modifiers.forEach((key, modifier) -> { - Stream.ofNullable(modifier.onAdded).flatMap(Stream::of) - // .map(action -> {modifierActionTypes.add(action.$type); return action;}) - .filter(action -> action.type == AbilityModifierAction.Type.HealHP) - .forEach(action -> modifierEntry.getOnAdded().add(action)); - Stream.ofNullable(modifier.onThinkInterval).flatMap(Stream::of) - // .map(action -> {modifierActionTypes.add(action.$type); return action;}) - .filter(action -> action.type == AbilityModifierAction.Type.HealHP) - .forEach(action -> modifierEntry.getOnThinkInterval().add(action)); - Stream.ofNullable(modifier.onRemoved).flatMap(Stream::of) - // .map(action -> {modifierActionTypes.add(action.$type); return action;}) - .filter(action -> action.type == AbilityModifierAction.Type.HealHP) - .forEach(action -> modifierEntry.getOnRemoved().add(action)); - }); - - GameData.getAbilityModifiers().put(name, modifierEntry); - } - - private static void loadSpawnData() { - String[] spawnDataNames = {"Spawns.json", "GadgetSpawns.json"}; - ArrayList spawnEntryMap = new ArrayList<>(); - - for (String name : spawnDataNames) { - // Load spawn entries from file - try (InputStreamReader reader = DataLoader.loadReader(name)) { - // Add spawns to group if it already exists in our spawn group map - spawnEntryMap.addAll(JsonUtils.loadToList(reader, SpawnGroupEntry.class)); - } catch (Exception ignored) { - } - } - - if (spawnEntryMap.isEmpty()) { - Grasscutter.getLogger().error("No spawn data loaded!"); - return; - } - - HashMap> areaSort = new HashMap<>(); - //key = sceneId,x,z , value = ArrayList - for (SpawnGroupEntry entry : spawnEntryMap) { - entry.getSpawns().forEach( - s -> { - s.setGroup(entry); - GridBlockId point = s.getBlockId(); - if (!areaSort.containsKey(point)) { - areaSort.put(point, new ArrayList<>()); - } - areaSort.get(point).add(s); - } - ); - } - GameDepot.addSpawnListById(areaSort); - } - - private static void loadOpenConfig() { - // Read from cached file if exists - List list = null; - - try { - list = JsonUtils.loadToList(getDataPath("OpenConfig.json"), OpenConfigEntry.class); - } catch (Exception ignored) { - } - - if (list == null) { - Map map = new TreeMap<>(); - String[] folderNames = {"BinOutput/Talent/EquipTalents/", "BinOutput/Talent/AvatarTalents/"}; - - for (String folderName : folderNames) { - try { - Files.newDirectoryStream(getResourcePath(folderName), "*.json").forEach(path -> { - try { - JsonUtils.loadToMap(path, String.class, OpenConfigData[].class) - .forEach((name, data) -> map.put(name, new OpenConfigEntry(name, data))); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading open config: no files found in " + folderName); - return; - } - } - - list = new ArrayList<>(map.values()); - } - - if (list == null || list.isEmpty()) { - Grasscutter.getLogger().error("No openconfig entries loaded!"); - return; - } - - for (OpenConfigEntry entry : list) { - GameData.getOpenConfigEntries().put(entry.getName(), entry); - } - } - - private static void loadQuests() { - try { - Files.list(getResourcePath("BinOutput/Quest/")).forEach(path -> { - try { - val mainQuest = JsonUtils.loadToClass(path, MainQuestData.class); - GameData.getMainQuestDataMap().put(mainQuest.getId(), mainQuest); - } catch (IOException e) { - - } - }); - } catch (IOException e) { - Grasscutter.getLogger().error("Quest data missing"); - return; - } - - try { - val questEncryptionMap = GameData.getMainQuestEncryptionMap(); - String path = "QuestEncryptionKeys.json"; - try { - JsonUtils.loadToList(getResourcePath(path), QuestEncryptionKey.class).forEach(key -> questEncryptionMap.put(key.getMainQuestId(), key)); - } catch (IOException | NullPointerException ignored) { - } - try { - DataLoader.loadList(path, QuestEncryptionKey.class).forEach(key -> questEncryptionMap.put(key.getMainQuestId(), key)); - } catch (IOException | NullPointerException ignored) { - } - Grasscutter.getLogger().debug("Loaded {} quest keys.", questEncryptionMap.size()); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load quest keys.", e); - } - - Grasscutter.getLogger().debug("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas."); - } - - public static void loadScriptSceneData() { - try { - Files.list(getResourcePath("ScriptSceneData/")).forEach(path -> { - try { - GameData.getScriptSceneDataMap().put(path.getFileName().toString(), JsonUtils.loadToClass(path, ScriptSceneData.class)); - } catch (IOException e) { - e.printStackTrace(); - } - }); - Grasscutter.getLogger().debug("Loaded " + GameData.getScriptSceneDataMap().size() + " ScriptSceneDatas."); - } catch (IOException e) { - Grasscutter.getLogger().debug("ScriptSceneData folder missing or empty."); - } - } - - private static void loadHomeworldDefaultSaveData() { - val pattern = Pattern.compile("scene([0-9]+)_home_config\\.json"); - try { - Files.newDirectoryStream(getResourcePath("BinOutput/HomeworldDefaultSave"), "scene*_home_config.json").forEach(path -> { - val matcher = pattern.matcher(path.getFileName().toString()); - if (!matcher.find()) return; - - try { - val sceneId = Integer.parseInt(matcher.group(1)); - val data = JsonUtils.loadToClass(path, HomeworldDefaultSaveData.class); - GameData.getHomeworldDefaultSaveData().put(sceneId, data); - } catch (Exception ignored) { - } - }); - Grasscutter.getLogger().debug("Loaded " + GameData.getHomeworldDefaultSaveData().size() + " HomeworldDefaultSaveDatas."); - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to load HomeworldDefaultSave folder."); - } - } - - private static void loadNpcBornData() { - try { - Files.newDirectoryStream(getResourcePath("BinOutput/Scene/SceneNpcBorn/"), "*.json").forEach(path -> { - try { - val data = JsonUtils.loadToClass(path, SceneNpcBornData.class); - if (data.getBornPosList() == null || data.getBornPosList().size() == 0) { - return; - } - - data.setIndex(SceneIndexManager.buildIndex(3, data.getBornPosList(), item -> item.getPos().toPoint())); - GameData.getSceneNpcBornData().put(data.getSceneId(), data); - } catch (IOException ignored) { - } - }); - Grasscutter.getLogger().debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneNpcBornDatas."); - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to load SceneNpcBorn folder."); - } - } - - private static void loadGadgetConfigData() { - try { - Files.newDirectoryStream(getResourcePath("BinOutput/Gadget/"), "*.json").forEach(path -> { - try { - GameData.getGadgetConfigData().putAll(JsonUtils.loadToMap(path, String.class, ConfigGadget.class)); - } catch (Exception e) { - Grasscutter.getLogger().error("failed to load ConfigGadget entries for " + path.toString(), e); - } - }); - - Grasscutter.getLogger().debug("Loaded {} ConfigGadget entries.", GameData.getGadgetConfigData().size()); - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to load ConfigGadget folder."); - } - } - - private static void loadBlossomResources() { - try { - GameDepot.setBlossomConfig(DataLoader.loadClass("BlossomConfig.json", BlossomConfig.class)); - Grasscutter.getLogger().debug("Loaded BlossomConfig."); - } catch (IOException e) { - Grasscutter.getLogger().warn("Failed to load BlossomConfig."); - } - } - - // private static HashSet modifierActionTypes = new HashSet<>(); - public static class AbilityConfigData { - public AbilityData Default; - } - - public static class AvatarConfig { - @SerializedName(value = "abilities", alternate = {"targetAbilities"}) - public ArrayList abilities; - } - - // BinOutput configs - - public static class AvatarConfigAbility { - public String abilityName; - - public String toString() { - return abilityName; - } - } - - private static class OpenConfig { - public OpenConfigData[] data; - } - - public static class OpenConfigData { - public String $type; - public String abilityName; - - @SerializedName(value = "talentIndex", alternate = {"OJOFFKLNAHN"}) - public int talentIndex; - - @SerializedName(value = "skillID", alternate = {"overtime"}) - public int skillID; - - @SerializedName(value = "pointDelta", alternate = {"IGEBKIHPOIF"}) - public int pointDelta; - } - - public class ScenePointConfig { // Sadly this doesn't work as a local class in loadScenePoints() - public Map points; - } -} +package emu.grasscutter.data; + +import static emu.grasscutter.utils.FileUtils.getDataPath; +import static emu.grasscutter.utils.FileUtils.getResourcePath; +import static emu.grasscutter.utils.Language.translate; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.*; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.data.common.PointData; +import emu.grasscutter.game.managers.blossom.BlossomConfig; +import emu.grasscutter.game.quest.QuestEncryptionKey; +import emu.grasscutter.game.world.SpawnDataEntry; +import emu.grasscutter.game.world.SpawnDataEntry.GridBlockId; +import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; +import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.JsonUtils; +import emu.grasscutter.utils.TsvUtils; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntArraySet; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import lombok.val; +import org.reflections.Reflections; + +public class ResourceLoader { + + private static final Set loadedResources = new CopyOnWriteArraySet<>(); + private static boolean loadedAll = false; + + // Get a list of all resource classes, sorted by loadPriority + public static List> getResourceDefClasses() { + Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName()); + Set classes = reflections.getSubTypesOf(GameResource.class); + + List> classList = new ArrayList<>(classes.size()); + classes.forEach( + o -> { + Class c = (Class) o; + if (c.getAnnotation(ResourceType.class) != null) { + classList.add(c); + } + }); + + classList.sort( + (a, b) -> + b.getAnnotation(ResourceType.class).loadPriority().value() + - a.getAnnotation(ResourceType.class).loadPriority().value()); + + return classList; + } + + // Get a list containing sets of all resource classes, sorted by loadPriority + protected static List>> getResourceDefClassesPrioritySets() { + val reflections = new Reflections(ResourceLoader.class.getPackage().getName()); + val classes = reflections.getSubTypesOf(GameResource.class); + val priorities = ResourceType.LoadPriority.getInOrder(); + Grasscutter.getLogger().debug("Priorities are " + priorities); + val map = new LinkedHashMap>>(priorities.size()); + priorities.forEach(p -> map.put(p, new HashSet<>())); + + classes.forEach( + c -> { + // val c = (Class) o; + val annotation = c.getAnnotation(ResourceType.class); + if (annotation != null) { + map.get(annotation.loadPriority()).add(c); + } + }); + return List.copyOf(map.values()); + } + + public static void loadAll() { + if (loadedAll) return; + Grasscutter.getLogger().info(translate("messages.status.resources.loading")); + + // Load ability lists + loadAbilityEmbryos(); + loadOpenConfig(); + loadAbilityModifiers(); + // Load resources + loadResources(true); + // Process into depots + GameDepot.load(); + // Load spawn data and quests + loadGadgetConfigData(); + loadSpawnData(); + loadQuests(); + loadScriptSceneData(); + // Load scene points - must be done AFTER resources are loaded + loadScenePoints(); + // Load default home layout + loadHomeworldDefaultSaveData(); + loadNpcBornData(); + loadBlossomResources(); + cacheTalentLevelSets(); + + Grasscutter.getLogger().info(translate("messages.status.resources.finish")); + loadedAll = true; + } + + public static void loadResources() { + loadResources(false); + } + + public static void loadResources(boolean doReload) { + long startTime = System.nanoTime(); + val errors = + new ConcurrentLinkedQueue< + Pair>(); // Logger in a parallel stream will deadlock + + getResourceDefClassesPrioritySets() + .forEach( + classes -> { + classes.stream() + .parallel() + .unordered() + .forEach( + c -> { + val type = c.getAnnotation(ResourceType.class); + if (type == null) return; + + val map = GameData.getMapByResourceDef(c); + if (map == null) return; + + try { + loadFromResource(c, type, map, doReload); + } catch (Exception e) { + errors.add(Pair.of(Arrays.toString(type.name()), e)); + } + }); + }); + errors.forEach( + pair -> + Grasscutter.getLogger() + .error("Error loading resource file: " + pair.left(), pair.right())); + long endTime = System.nanoTime(); + long ns = (endTime - startTime); // divide by 1000000 to get milliseconds. + Grasscutter.getLogger().debug("Loading resources took " + ns + "ns == " + ns / 1000000 + "ms"); + } + + @SuppressWarnings("rawtypes") + protected static void loadFromResource( + Class c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception { + val simpleName = c.getSimpleName(); + if (doReload || !loadedResources.contains(simpleName)) { + for (String name : type.name()) { + loadFromResource(c, FileUtils.getExcelPath(name), map); + } + loadedResources.add(simpleName); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static void loadFromResource(Class c, Path filename, Int2ObjectMap map) + throws Exception { + val results = + switch (FileUtils.getFileExtension(filename)) { + case "json" -> JsonUtils.loadToList(filename, c); + case "tsj" -> TsvUtils.loadTsjToListSetField(filename, c); + case "tsv" -> TsvUtils.loadTsvToListSetField(filename, c); + default -> null; + }; + if (results == null) return; + results.forEach( + o -> { + GameResource res = (GameResource) o; + res.onLoad(); + map.put(res.getId(), res); + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected static void loadFromResource(Class c, String fileName, Int2ObjectMap map) + throws Exception { + JsonUtils.loadToList(getResourcePath("ExcelBinOutput/" + fileName), c) + .forEach( + o -> { + GameResource res = (GameResource) o; + res.onLoad(); + map.put(res.getId(), res); + }); + } + + private static void loadScenePoints() { + val pattern = Pattern.compile("scene([0-9]+)_point\\.json"); + try { + Files.newDirectoryStream(getResourcePath("BinOutput/Scene/Point"), "scene*_point.json") + .forEach( + path -> { + val matcher = pattern.matcher(path.getFileName().toString()); + if (!matcher.find()) return; + int sceneId = Integer.parseInt(matcher.group(1)); + + ScenePointConfig config; + try { + config = JsonUtils.loadToClass(path, ScenePointConfig.class); + } catch (Exception e) { + e.printStackTrace(); + return; + } + + if (config.points == null) return; + + val scenePoints = new IntArrayList(); + config.points.forEach( + (pointId, pointData) -> { + val scenePoint = new ScenePointEntry(sceneId, pointData); + scenePoints.add(pointId); + pointData.setId(pointId); + + GameData.getScenePointIdList().add(pointId); + GameData.getScenePointEntries().put(scenePoint.getName(), scenePoint); + GameData.scenePointEntryMap.put((sceneId << 16) + pointId, scenePoint); + + pointData.updateDailyDungeon(); + }); + GameData.getScenePointsPerScene().put(sceneId, scenePoints); + }); + } catch (IOException e) { + Grasscutter.getLogger() + .error("Scene point files cannot be found, you cannot use teleport waypoints!"); + } + } + + private static void cacheTalentLevelSets() { + // All known levels, keyed by proudSkillGroupId + GameData.getProudSkillDataMap() + .forEach( + (id, data) -> + GameData.proudSkillGroupLevels + .computeIfAbsent(data.getProudSkillGroupId(), i -> new IntArraySet()) + .add(data.getLevel())); + // All known levels, keyed by avatarSkillId + GameData.getAvatarSkillDataMap() + .forEach( + (id, data) -> + GameData.avatarSkillLevels.put( + (int) id, GameData.proudSkillGroupLevels.get(data.getProudSkillGroupId()))); + // Maximum known levels, keyed by proudSkillGroupId + GameData.proudSkillGroupLevels.forEach( + (id, set) -> + GameData.proudSkillGroupMaxLevels.put((int) id, set.intStream().max().getAsInt())); + } + + private static void loadAbilityEmbryos() { + List embryoList = null; + + // Read from cached file if exists + try { + embryoList = + JsonUtils.loadToList(getDataPath("AbilityEmbryos.json"), AbilityEmbryoEntry.class); + } catch (Exception ignored) { + } + + if (embryoList == null) { + // Load from BinOutput + val pattern = Pattern.compile("ConfigAvatar_(.+?)\\.json"); + + val l = new ArrayList(); + try { + Files.newDirectoryStream(getResourcePath("BinOutput/Avatar/"), "ConfigAvatar_*.json") + .forEach( + path -> { + val matcher = pattern.matcher(path.getFileName().toString()); + if (!matcher.find()) return; + String avatarName = matcher.group(1); + AvatarConfig config; + + try { + config = JsonUtils.loadToClass(path, AvatarConfig.class); + } catch (Exception e) { + Grasscutter.getLogger().error("Error loading player ability embryos:", e); + return; + } + + if (config.abilities == null) return; + + int s = config.abilities.size(); + AbilityEmbryoEntry al = + new AbilityEmbryoEntry( + avatarName, + config.abilities.stream() + .map(Object::toString) + .toArray(size -> new String[s])); + l.add(al); + }); + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading ability embryos: no files found"); + return; + } + + embryoList = l; + + try { + GameDepot.setPlayerAbilities( + JsonUtils.loadToMap( + getResourcePath( + "BinOutput/AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"), + String.class, + AvatarConfig.class)); + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading player abilities:", e); + } + } + + if (embryoList == null || embryoList.isEmpty()) { + Grasscutter.getLogger().error("No embryos loaded!"); + return; + } + + for (AbilityEmbryoEntry entry : embryoList) { + GameData.getAbilityEmbryoInfo().put(entry.getName(), entry); + } + } + + private static void loadAbilityModifiers() { + // Load from BinOutput + try (Stream paths = Files.walk(getResourcePath("BinOutput/Ability/Temp/"))) { + paths + .filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".json")) + .forEach(ResourceLoader::loadAbilityModifiers); + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading ability modifiers: ", e); + } + // System.out.println("Loaded modifiers, found types:"); + // modifierActionTypes.stream().sorted().forEach(s -> System.out.printf("%s, ", s)); + // System.out.println("[End]"); + } + + private static void loadAbilityModifiers(Path path) { + try { + JsonUtils.loadToList(path, AbilityConfigData.class) + .forEach(data -> loadAbilityData(data.Default)); + } catch (IOException e) { + Grasscutter.getLogger() + .error("Error loading ability modifiers from path " + path.toString() + ": ", e); + } + } + + private static void loadAbilityData(AbilityData data) { + GameData.abilityDataMap.put(data.abilityName, data); + + val modifiers = data.modifiers; + if (modifiers == null || modifiers.size() == 0) return; + + String name = data.abilityName; + AbilityModifierEntry modifierEntry = new AbilityModifierEntry(name); + modifiers.forEach( + (key, modifier) -> { + Stream.ofNullable(modifier.onAdded) + .flatMap(Stream::of) + // .map(action -> {modifierActionTypes.add(action.$type); return action;}) + .filter(action -> action.type == AbilityModifierAction.Type.HealHP) + .forEach(action -> modifierEntry.getOnAdded().add(action)); + Stream.ofNullable(modifier.onThinkInterval) + .flatMap(Stream::of) + // .map(action -> {modifierActionTypes.add(action.$type); return action;}) + .filter(action -> action.type == AbilityModifierAction.Type.HealHP) + .forEach(action -> modifierEntry.getOnThinkInterval().add(action)); + Stream.ofNullable(modifier.onRemoved) + .flatMap(Stream::of) + // .map(action -> {modifierActionTypes.add(action.$type); return action;}) + .filter(action -> action.type == AbilityModifierAction.Type.HealHP) + .forEach(action -> modifierEntry.getOnRemoved().add(action)); + }); + + GameData.getAbilityModifiers().put(name, modifierEntry); + } + + private static void loadSpawnData() { + String[] spawnDataNames = {"Spawns.json", "GadgetSpawns.json"}; + ArrayList spawnEntryMap = new ArrayList<>(); + + for (String name : spawnDataNames) { + // Load spawn entries from file + try (InputStreamReader reader = DataLoader.loadReader(name)) { + // Add spawns to group if it already exists in our spawn group map + spawnEntryMap.addAll(JsonUtils.loadToList(reader, SpawnGroupEntry.class)); + } catch (Exception ignored) { + } + } + + if (spawnEntryMap.isEmpty()) { + Grasscutter.getLogger().error("No spawn data loaded!"); + return; + } + + HashMap> areaSort = new HashMap<>(); + // key = sceneId,x,z , value = ArrayList + for (SpawnGroupEntry entry : spawnEntryMap) { + entry + .getSpawns() + .forEach( + s -> { + s.setGroup(entry); + GridBlockId point = s.getBlockId(); + if (!areaSort.containsKey(point)) { + areaSort.put(point, new ArrayList<>()); + } + areaSort.get(point).add(s); + }); + } + GameDepot.addSpawnListById(areaSort); + } + + private static void loadOpenConfig() { + // Read from cached file if exists + List list = null; + + try { + list = JsonUtils.loadToList(getDataPath("OpenConfig.json"), OpenConfigEntry.class); + } catch (Exception ignored) { + } + + if (list == null) { + Map map = new TreeMap<>(); + String[] folderNames = {"BinOutput/Talent/EquipTalents/", "BinOutput/Talent/AvatarTalents/"}; + + for (String folderName : folderNames) { + try { + Files.newDirectoryStream(getResourcePath(folderName), "*.json") + .forEach( + path -> { + try { + JsonUtils.loadToMap(path, String.class, OpenConfigData[].class) + .forEach((name, data) -> map.put(name, new OpenConfigEntry(name, data))); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } catch (IOException e) { + Grasscutter.getLogger() + .error("Error loading open config: no files found in " + folderName); + return; + } + } + + list = new ArrayList<>(map.values()); + } + + if (list == null || list.isEmpty()) { + Grasscutter.getLogger().error("No openconfig entries loaded!"); + return; + } + + for (OpenConfigEntry entry : list) { + GameData.getOpenConfigEntries().put(entry.getName(), entry); + } + } + + private static void loadQuests() { + try { + Files.list(getResourcePath("BinOutput/Quest/")) + .forEach( + path -> { + try { + val mainQuest = JsonUtils.loadToClass(path, MainQuestData.class); + GameData.getMainQuestDataMap().put(mainQuest.getId(), mainQuest); + } catch (IOException e) { + + } + }); + } catch (IOException e) { + Grasscutter.getLogger().error("Quest data missing"); + return; + } + + try { + val questEncryptionMap = GameData.getMainQuestEncryptionMap(); + String path = "QuestEncryptionKeys.json"; + try { + JsonUtils.loadToList(getResourcePath(path), QuestEncryptionKey.class) + .forEach(key -> questEncryptionMap.put(key.getMainQuestId(), key)); + } catch (IOException | NullPointerException ignored) { + } + try { + DataLoader.loadList(path, QuestEncryptionKey.class) + .forEach(key -> questEncryptionMap.put(key.getMainQuestId(), key)); + } catch (IOException | NullPointerException ignored) { + } + Grasscutter.getLogger().debug("Loaded {} quest keys.", questEncryptionMap.size()); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load quest keys.", e); + } + + Grasscutter.getLogger() + .debug("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas."); + } + + public static void loadScriptSceneData() { + try { + Files.list(getResourcePath("ScriptSceneData/")) + .forEach( + path -> { + try { + GameData.getScriptSceneDataMap() + .put( + path.getFileName().toString(), + JsonUtils.loadToClass(path, ScriptSceneData.class)); + } catch (IOException e) { + e.printStackTrace(); + } + }); + Grasscutter.getLogger() + .debug("Loaded " + GameData.getScriptSceneDataMap().size() + " ScriptSceneDatas."); + } catch (IOException e) { + Grasscutter.getLogger().debug("ScriptSceneData folder missing or empty."); + } + } + + private static void loadHomeworldDefaultSaveData() { + val pattern = Pattern.compile("scene([0-9]+)_home_config\\.json"); + try { + Files.newDirectoryStream( + getResourcePath("BinOutput/HomeworldDefaultSave"), "scene*_home_config.json") + .forEach( + path -> { + val matcher = pattern.matcher(path.getFileName().toString()); + if (!matcher.find()) return; + + try { + val sceneId = Integer.parseInt(matcher.group(1)); + val data = JsonUtils.loadToClass(path, HomeworldDefaultSaveData.class); + GameData.getHomeworldDefaultSaveData().put(sceneId, data); + } catch (Exception ignored) { + } + }); + Grasscutter.getLogger() + .debug( + "Loaded " + + GameData.getHomeworldDefaultSaveData().size() + + " HomeworldDefaultSaveDatas."); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to load HomeworldDefaultSave folder."); + } + } + + private static void loadNpcBornData() { + try { + Files.newDirectoryStream(getResourcePath("BinOutput/Scene/SceneNpcBorn/"), "*.json") + .forEach( + path -> { + try { + val data = JsonUtils.loadToClass(path, SceneNpcBornData.class); + if (data.getBornPosList() == null || data.getBornPosList().size() == 0) { + return; + } + + data.setIndex( + SceneIndexManager.buildIndex( + 3, data.getBornPosList(), item -> item.getPos().toPoint())); + GameData.getSceneNpcBornData().put(data.getSceneId(), data); + } catch (IOException ignored) { + } + }); + Grasscutter.getLogger() + .debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneNpcBornDatas."); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to load SceneNpcBorn folder."); + } + } + + private static void loadGadgetConfigData() { + try { + Files.newDirectoryStream(getResourcePath("BinOutput/Gadget/"), "*.json") + .forEach( + path -> { + try { + GameData.getGadgetConfigData() + .putAll(JsonUtils.loadToMap(path, String.class, ConfigGadget.class)); + } catch (Exception e) { + Grasscutter.getLogger() + .error("failed to load ConfigGadget entries for " + path.toString(), e); + } + }); + + Grasscutter.getLogger() + .debug("Loaded {} ConfigGadget entries.", GameData.getGadgetConfigData().size()); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to load ConfigGadget folder."); + } + } + + private static void loadBlossomResources() { + try { + GameDepot.setBlossomConfig(DataLoader.loadClass("BlossomConfig.json", BlossomConfig.class)); + Grasscutter.getLogger().debug("Loaded BlossomConfig."); + } catch (IOException e) { + Grasscutter.getLogger().warn("Failed to load BlossomConfig."); + } + } + + // private static HashSet modifierActionTypes = new HashSet<>(); + public static class AbilityConfigData { + public AbilityData Default; + } + + public static class AvatarConfig { + @SerializedName( + value = "abilities", + alternate = {"targetAbilities"}) + public ArrayList abilities; + } + + // BinOutput configs + + public static class AvatarConfigAbility { + public String abilityName; + + public String toString() { + return abilityName; + } + } + + private static class OpenConfig { + public OpenConfigData[] data; + } + + public static class OpenConfigData { + public String $type; + public String abilityName; + + @SerializedName( + value = "talentIndex", + alternate = {"OJOFFKLNAHN"}) + public int talentIndex; + + @SerializedName( + value = "skillID", + alternate = {"overtime"}) + public int skillID; + + @SerializedName( + value = "pointDelta", + alternate = {"IGEBKIHPOIF"}) + public int pointDelta; + } + + public class ScenePointConfig { // Sadly this doesn't work as a local class in loadScenePoints() + public Map points; + } +} diff --git a/src/main/java/emu/grasscutter/data/ResourceType.java b/src/main/java/emu/grasscutter/data/ResourceType.java index 563b0f091..9eb85904c 100644 --- a/src/main/java/emu/grasscutter/data/ResourceType.java +++ b/src/main/java/emu/grasscutter/data/ResourceType.java @@ -1,42 +1,40 @@ -package emu.grasscutter.data; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.List; -import java.util.stream.Stream; - -@Retention(RetentionPolicy.RUNTIME) -public @interface ResourceType { - - /** - * Names of the file that this Resource loads from - */ - String[] name(); - - /** - * Load priority - dictates which order to load this resource, with "highest" being loaded first - */ - LoadPriority loadPriority() default LoadPriority.NORMAL; - - enum LoadPriority { - HIGHEST(4), - HIGH(3), - NORMAL(2), - LOW(1), - LOWEST(0); - - private final int value; - - LoadPriority(int value) { - this.value = value; - } - - public static List getInOrder() { - return Stream.of(LoadPriority.values()).sorted((x, y) -> y.value() - x.value()).toList(); - } - - public int value() { - return value; - } - } -} +package emu.grasscutter.data; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; +import java.util.stream.Stream; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ResourceType { + + /** Names of the file that this Resource loads from */ + String[] name(); + + /** + * Load priority - dictates which order to load this resource, with "highest" being loaded first + */ + LoadPriority loadPriority() default LoadPriority.NORMAL; + + enum LoadPriority { + HIGHEST(4), + HIGH(3), + NORMAL(2), + LOW(1), + LOWEST(0); + + private final int value; + + LoadPriority(int value) { + this.value = value; + } + + public static List getInOrder() { + return Stream.of(LoadPriority.values()).sorted((x, y) -> y.value() - x.value()).toList(); + } + + public int value() { + return value; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java b/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java index 87bc4ba1e..e639eb0c5 100644 --- a/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java @@ -1,23 +1,21 @@ -package emu.grasscutter.data.binout; - -public class AbilityEmbryoEntry { - private String name; - private String[] abilities; - - public AbilityEmbryoEntry() { - - } - - public AbilityEmbryoEntry(String avatarName, String[] array) { - this.name = avatarName; - this.abilities = array; - } - - public String getName() { - return name; - } - - public String[] getAbilities() { - return abilities; - } -} +package emu.grasscutter.data.binout; + +public class AbilityEmbryoEntry { + private String name; + private String[] abilities; + + public AbilityEmbryoEntry() {} + + public AbilityEmbryoEntry(String avatarName, String[] array) { + this.name = avatarName; + this.abilities = array; + } + + public String getName() { + return name; + } + + public String[] getAbilities() { + return abilities; + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java index f05c7f3f9..c4f713d43 100644 --- a/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java +++ b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java @@ -1,97 +1,270 @@ -package emu.grasscutter.data.binout; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.common.DynamicFloat; - -import java.io.Serializable; - -public class AbilityModifier implements Serializable { - private static final long serialVersionUID = -2001232313615923575L; - - @SerializedName(value = "onAdded", alternate = {"KCICDEJLIJD"}) - public AbilityModifierAction[] onAdded; - @SerializedName(value = "onThinkInterval", alternate = {"PBDDACFFPOE"}) - public AbilityModifierAction[] onThinkInterval; - public AbilityModifierAction[] onRemoved; - public DynamicFloat duration = DynamicFloat.ZERO; - - public static class AbilityModifierAction { - @SerializedName("$type") - public Type type; - public String target; - @SerializedName(value = "amount", alternate = "PDLLIFICICJ") - public DynamicFloat amount = DynamicFloat.ZERO; - public DynamicFloat amountByCasterAttackRatio = DynamicFloat.ZERO; - public DynamicFloat amountByCasterCurrentHPRatio = DynamicFloat.ZERO; - public DynamicFloat amountByCasterMaxHPRatio = DynamicFloat.ZERO; - public DynamicFloat amountByGetDamage = DynamicFloat.ZERO; - public DynamicFloat amountByTargetCurrentHPRatio = DynamicFloat.ZERO; - public DynamicFloat amountByTargetMaxHPRatio = DynamicFloat.ZERO; - @SerializedName(value = "ignoreAbilityProperty", alternate = "HHFGADCJJDI") - public boolean ignoreAbilityProperty; - public String modifierName; - public enum Type { - ActCameraRadialBlur, ActCameraShake, AddAvatarSkillInfo, AddChargeBarValue, - AddClimateMeter, AddElementDurability, AddGlobalValue, AddGlobalValueToTarget, - AddRegionalPlayVarValue, ApplyModifier, AttachAbilityStateResistance, AttachBulletAimPoint, - AttachEffect, AttachEffectFirework, AttachElementTypeResistance, AttachModifier, - AttachUIEffect, AvatarCameraParam, AvatarEnterCameraShot, AvatarEnterFocus, - AvatarEnterViewBias, AvatarExitCameraShot, AvatarExitClimb, AvatarExitFocus, - AvatarExitViewBias, AvatarShareCDSkillStart, AvatarSkillStart, BroadcastNeuronStimulate, - CalcDvalinS04RebornPoint, CallLuaTask, ChangeEnviroWeather, ChangeFollowDampTime, - ChangeGadgetUIInteractHint, ChangePlayMode, ChangeTag, ChangeUGCRayTag, - ClearEndura, ClearGlobalPos, ClearGlobalValue, ClearLocalGadgets, - ClearLockTarget, ClearPos, ConfigAbilityAction, ControlEmotion, - CopyGlobalValue, CreateGadget, CreateMovingPlatform, CreateTile, - DamageByAttackValue, DebugLog, DestroyTile, DoBlink, - DoTileAction, DoWatcherSystemAction, DoWidgetSystemAction, DropSubfield, - DummyAction, DungeonFogEffects, ElementAttachForActivityGacha, EnableAIStealthy, - EnableAfterImage, EnableAvatarFlyStateTrail, EnableAvatarMoveOnWater, EnableBulletCollisionPluginTrigger, - EnableGadgetIntee, EnableHeadControl, EnableHitBoxByName, EnableMainInterface, - EnablePartControl, EnablePositionSynchronization, EnablePushColliderName, EnableRocketJump, - EnableSceneTransformByName, EnterCameraLock, EntityDoSkill, EquipAffixStart, - ExecuteGadgetLua, FireAISoundEvent, FireChargeBarEffect, FireEffect, - FireEffectFirework, FireEffectForStorm, FireFishingEvent, FireHitEffect, - FireSubEmitterEffect, FireUIEffect, FixedMonsterRushMove, ForceAirStateFly, - ForceEnableShakeOffButton, GenerateElemBall, GetFightProperty, GetInteractIdToGlobalValue, - GetPos, HealHP, HideUIBillBoard, IgnoreMoveColToRockCol, - KillGadget, KillPlayEntity, KillSelf, KillServerGadget, - LoseHP, ModifyAvatarSkillCD, ModifyVehicleSkillCD, PlayEmoSync, - Predicated, PushDvalinS01Process, PushInterActionByConfigPath, PushPos, - Randomed, ReTriggerAISkillInitialCD, RefreshUICombatBarLayout, RegisterAIActionPoint, - ReleaseAIActionPoint, RemoveAvatarSkillInfo, RemoveModifier, RemoveModifierByAbilityStateResistanceID, - RemoveServerBuff, RemoveUniqueModifier, RemoveVelocityForce, Repeated, - ResetAIAttackTarget, ResetAIResistTauntLevel, ResetAIThreatBroadcastRange, ResetAnimatorTrigger, - ReviveDeadAvatar, ReviveElemEnergy, ReviveStamina, SectorCityManeuver, - SendEffectTrigger, SendEffectTriggerToLineEffect, SendEvtElectricCoreMoveEnterP1, SendEvtElectricCoreMoveInterrupt, - ServerLuaCall, ServerLuaTriggerEvent, ServerMonsterLog, SetAIHitFeeling, - SetAISkillCDAvailableNow, SetAISkillCDMultiplier, SetAISkillGCD, SetAnimatorBool, - SetAnimatorFloat, SetAnimatorInt, SetAnimatorTrigger, SetAvatarCanShakeOff, - SetAvatarHitBuckets, SetCanDieImmediately, SetChargeBarValue, SetDvalinS01FlyState, - SetEmissionScaler, SetEntityScale, SetExtraAbilityEnable, SetExtraAbilityState, - SetGlobalDir, SetGlobalPos, SetGlobalValue, SetGlobalValueByTargetDistance, - SetGlobalValueToOverrideMap, SetKeepInAirVelocityForce, SetMaterialParamFloatByTransform, SetNeuronEnable, - SetOverrideMapValue, SetPartControlTarget, SetPoseBool, SetPoseFloat, - SetPoseInt, SetRandomOverrideMapValue, SetRegionalPlayVarValue, SetSelfAttackTarget, - SetSkillAnchor, SetSpecialCamera, SetSurroundAnchor, SetSystemValueToOverrideMap, - SetTargetNumToGlobalValue, SetUICombatBarAsh, SetUICombatBarSpark, SetVelocityIgnoreAirGY, - SetWeaponAttachPointRealName, SetWeaponBindState, ShowExtraAbility, ShowProgressBarAction, - ShowReminder, ShowScreenEffect, ShowTextMap, ShowUICombatBar, - StartDither, SumTargetWeightToSelfGlobalValue, Summon, SyncToStageScript, - TriggerAbility, TriggerAttackEvent, TriggerAttackTargetMapEvent, TriggerAudio, - TriggerAuxWeaponTrans, TriggerBullet, TriggerCreateGadgetToEquipPart, TriggerDropEquipParts, - TriggerFaceAnimation, TriggerGadgetInteractive, TriggerHideWeapon, TriggerSetCastShadow, - TriggerSetPassThrough, TriggerSetRenderersEnable, TriggerSetShadowRamp, TriggerSetVisible, - TriggerTaunt, TriggerThrowEquipPart, TriggerUGCGadgetMove, TryFindBlinkPoint, - TryFindBlinkPointByBorn, TryTriggerPlatformStartMove, TurnDirection, TurnDirectionToPos, - UpdateReactionDamage, UseSkillEliteSet, WidgetSkillStart - } - } - - //The following should be implemented into DynamicFloat if older resource formats need to be supported - // public static class AbilityModifierValue { - // public boolean isFormula; - // public boolean isDynamic; - // public String dynamicKey; - // } -} +package emu.grasscutter.data.binout; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.common.DynamicFloat; +import java.io.Serializable; + +public class AbilityModifier implements Serializable { + private static final long serialVersionUID = -2001232313615923575L; + + @SerializedName( + value = "onAdded", + alternate = {"KCICDEJLIJD"}) + public AbilityModifierAction[] onAdded; + + @SerializedName( + value = "onThinkInterval", + alternate = {"PBDDACFFPOE"}) + public AbilityModifierAction[] onThinkInterval; + + public AbilityModifierAction[] onRemoved; + public DynamicFloat duration = DynamicFloat.ZERO; + + public static class AbilityModifierAction { + @SerializedName("$type") + public Type type; + + public String target; + + @SerializedName(value = "amount", alternate = "PDLLIFICICJ") + public DynamicFloat amount = DynamicFloat.ZERO; + + public DynamicFloat amountByCasterAttackRatio = DynamicFloat.ZERO; + public DynamicFloat amountByCasterCurrentHPRatio = DynamicFloat.ZERO; + public DynamicFloat amountByCasterMaxHPRatio = DynamicFloat.ZERO; + public DynamicFloat amountByGetDamage = DynamicFloat.ZERO; + public DynamicFloat amountByTargetCurrentHPRatio = DynamicFloat.ZERO; + public DynamicFloat amountByTargetMaxHPRatio = DynamicFloat.ZERO; + + @SerializedName(value = "ignoreAbilityProperty", alternate = "HHFGADCJJDI") + public boolean ignoreAbilityProperty; + + public String modifierName; + + public enum Type { + ActCameraRadialBlur, + ActCameraShake, + AddAvatarSkillInfo, + AddChargeBarValue, + AddClimateMeter, + AddElementDurability, + AddGlobalValue, + AddGlobalValueToTarget, + AddRegionalPlayVarValue, + ApplyModifier, + AttachAbilityStateResistance, + AttachBulletAimPoint, + AttachEffect, + AttachEffectFirework, + AttachElementTypeResistance, + AttachModifier, + AttachUIEffect, + AvatarCameraParam, + AvatarEnterCameraShot, + AvatarEnterFocus, + AvatarEnterViewBias, + AvatarExitCameraShot, + AvatarExitClimb, + AvatarExitFocus, + AvatarExitViewBias, + AvatarShareCDSkillStart, + AvatarSkillStart, + BroadcastNeuronStimulate, + CalcDvalinS04RebornPoint, + CallLuaTask, + ChangeEnviroWeather, + ChangeFollowDampTime, + ChangeGadgetUIInteractHint, + ChangePlayMode, + ChangeTag, + ChangeUGCRayTag, + ClearEndura, + ClearGlobalPos, + ClearGlobalValue, + ClearLocalGadgets, + ClearLockTarget, + ClearPos, + ConfigAbilityAction, + ControlEmotion, + CopyGlobalValue, + CreateGadget, + CreateMovingPlatform, + CreateTile, + DamageByAttackValue, + DebugLog, + DestroyTile, + DoBlink, + DoTileAction, + DoWatcherSystemAction, + DoWidgetSystemAction, + DropSubfield, + DummyAction, + DungeonFogEffects, + ElementAttachForActivityGacha, + EnableAIStealthy, + EnableAfterImage, + EnableAvatarFlyStateTrail, + EnableAvatarMoveOnWater, + EnableBulletCollisionPluginTrigger, + EnableGadgetIntee, + EnableHeadControl, + EnableHitBoxByName, + EnableMainInterface, + EnablePartControl, + EnablePositionSynchronization, + EnablePushColliderName, + EnableRocketJump, + EnableSceneTransformByName, + EnterCameraLock, + EntityDoSkill, + EquipAffixStart, + ExecuteGadgetLua, + FireAISoundEvent, + FireChargeBarEffect, + FireEffect, + FireEffectFirework, + FireEffectForStorm, + FireFishingEvent, + FireHitEffect, + FireSubEmitterEffect, + FireUIEffect, + FixedMonsterRushMove, + ForceAirStateFly, + ForceEnableShakeOffButton, + GenerateElemBall, + GetFightProperty, + GetInteractIdToGlobalValue, + GetPos, + HealHP, + HideUIBillBoard, + IgnoreMoveColToRockCol, + KillGadget, + KillPlayEntity, + KillSelf, + KillServerGadget, + LoseHP, + ModifyAvatarSkillCD, + ModifyVehicleSkillCD, + PlayEmoSync, + Predicated, + PushDvalinS01Process, + PushInterActionByConfigPath, + PushPos, + Randomed, + ReTriggerAISkillInitialCD, + RefreshUICombatBarLayout, + RegisterAIActionPoint, + ReleaseAIActionPoint, + RemoveAvatarSkillInfo, + RemoveModifier, + RemoveModifierByAbilityStateResistanceID, + RemoveServerBuff, + RemoveUniqueModifier, + RemoveVelocityForce, + Repeated, + ResetAIAttackTarget, + ResetAIResistTauntLevel, + ResetAIThreatBroadcastRange, + ResetAnimatorTrigger, + ReviveDeadAvatar, + ReviveElemEnergy, + ReviveStamina, + SectorCityManeuver, + SendEffectTrigger, + SendEffectTriggerToLineEffect, + SendEvtElectricCoreMoveEnterP1, + SendEvtElectricCoreMoveInterrupt, + ServerLuaCall, + ServerLuaTriggerEvent, + ServerMonsterLog, + SetAIHitFeeling, + SetAISkillCDAvailableNow, + SetAISkillCDMultiplier, + SetAISkillGCD, + SetAnimatorBool, + SetAnimatorFloat, + SetAnimatorInt, + SetAnimatorTrigger, + SetAvatarCanShakeOff, + SetAvatarHitBuckets, + SetCanDieImmediately, + SetChargeBarValue, + SetDvalinS01FlyState, + SetEmissionScaler, + SetEntityScale, + SetExtraAbilityEnable, + SetExtraAbilityState, + SetGlobalDir, + SetGlobalPos, + SetGlobalValue, + SetGlobalValueByTargetDistance, + SetGlobalValueToOverrideMap, + SetKeepInAirVelocityForce, + SetMaterialParamFloatByTransform, + SetNeuronEnable, + SetOverrideMapValue, + SetPartControlTarget, + SetPoseBool, + SetPoseFloat, + SetPoseInt, + SetRandomOverrideMapValue, + SetRegionalPlayVarValue, + SetSelfAttackTarget, + SetSkillAnchor, + SetSpecialCamera, + SetSurroundAnchor, + SetSystemValueToOverrideMap, + SetTargetNumToGlobalValue, + SetUICombatBarAsh, + SetUICombatBarSpark, + SetVelocityIgnoreAirGY, + SetWeaponAttachPointRealName, + SetWeaponBindState, + ShowExtraAbility, + ShowProgressBarAction, + ShowReminder, + ShowScreenEffect, + ShowTextMap, + ShowUICombatBar, + StartDither, + SumTargetWeightToSelfGlobalValue, + Summon, + SyncToStageScript, + TriggerAbility, + TriggerAttackEvent, + TriggerAttackTargetMapEvent, + TriggerAudio, + TriggerAuxWeaponTrans, + TriggerBullet, + TriggerCreateGadgetToEquipPart, + TriggerDropEquipParts, + TriggerFaceAnimation, + TriggerGadgetInteractive, + TriggerHideWeapon, + TriggerSetCastShadow, + TriggerSetPassThrough, + TriggerSetRenderersEnable, + TriggerSetShadowRamp, + TriggerSetVisible, + TriggerTaunt, + TriggerThrowEquipPart, + TriggerUGCGadgetMove, + TryFindBlinkPoint, + TryFindBlinkPointByBorn, + TryTriggerPlatformStartMove, + TurnDirection, + TurnDirectionToPos, + UpdateReactionDamage, + UseSkillEliteSet, + WidgetSkillStart + } + } + + // The following should be implemented into DynamicFloat if older resource formats need to be + // supported + // public static class AbilityModifierValue { + // public boolean isFormula; + // public boolean isDynamic; + // public String dynamicKey; + // } +} diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java b/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java index 02d419b69..78d8c7289 100644 --- a/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java @@ -1,37 +1,35 @@ -package emu.grasscutter.data.binout; - -import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; - -import java.util.ArrayList; -import java.util.List; - -public class AbilityModifierEntry { - public List onModifierAdded; - public List onThinkInterval; - public List onRemoved; - private final String name; // Custom value - - public AbilityModifierEntry(String name) { - this.name = name; - this.onModifierAdded = new ArrayList<>(); - this.onThinkInterval = new ArrayList<>(); - this.onRemoved = new ArrayList<>(); - } - - public String getName() { - return name; - } - - public List getOnAdded() { - return onModifierAdded; - } - - public List getOnThinkInterval() { - return onThinkInterval; - } - - public List getOnRemoved() { - return onRemoved; - } - -} +package emu.grasscutter.data.binout; + +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import java.util.ArrayList; +import java.util.List; + +public class AbilityModifierEntry { + public List onModifierAdded; + public List onThinkInterval; + public List onRemoved; + private final String name; // Custom value + + public AbilityModifierEntry(String name) { + this.name = name; + this.onModifierAdded = new ArrayList<>(); + this.onThinkInterval = new ArrayList<>(); + this.onRemoved = new ArrayList<>(); + } + + public String getName() { + return name; + } + + public List getOnAdded() { + return onModifierAdded; + } + + public List getOnThinkInterval() { + return onThinkInterval; + } + + public List getOnRemoved() { + return onRemoved; + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/ConfigGadget.java b/src/main/java/emu/grasscutter/data/binout/ConfigGadget.java index 9bb9adc02..c9e9d807b 100644 --- a/src/main/java/emu/grasscutter/data/binout/ConfigGadget.java +++ b/src/main/java/emu/grasscutter/data/binout/ConfigGadget.java @@ -1,15 +1,13 @@ -package emu.grasscutter.data.binout; - -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import javax.annotation.Nullable; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ConfigGadget { - // There are more values that can be added that might be useful in the json - @Nullable - ConfigGadgetCombat combat; -} +package emu.grasscutter.data.binout; + +import javax.annotation.Nullable; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ConfigGadget { + // There are more values that can be added that might be useful in the json + @Nullable ConfigGadgetCombat combat; +} diff --git a/src/main/java/emu/grasscutter/data/binout/ConfigGadgetCombatProperty.java b/src/main/java/emu/grasscutter/data/binout/ConfigGadgetCombatProperty.java index 737d4f0fa..a2215b098 100644 --- a/src/main/java/emu/grasscutter/data/binout/ConfigGadgetCombatProperty.java +++ b/src/main/java/emu/grasscutter/data/binout/ConfigGadgetCombatProperty.java @@ -1,18 +1,18 @@ -package emu.grasscutter.data.binout; - -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ConfigGadgetCombatProperty { - float HP; - boolean isLockHP; - boolean isInvincible; - boolean isGhostToAllied; - float attack; - float defence; - float weight; - boolean useCreatorProperty; -} +package emu.grasscutter.data.binout; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ConfigGadgetCombatProperty { + float HP; + boolean isLockHP; + boolean isInvincible; + boolean isGhostToAllied; + float attack; + float defence; + float weight; + boolean useCreatorProperty; +} diff --git a/src/main/java/emu/grasscutter/data/binout/HomeworldDefaultSaveData.java b/src/main/java/emu/grasscutter/data/binout/HomeworldDefaultSaveData.java index d97eb2660..180682f3f 100644 --- a/src/main/java/emu/grasscutter/data/binout/HomeworldDefaultSaveData.java +++ b/src/main/java/emu/grasscutter/data/binout/HomeworldDefaultSaveData.java @@ -1,56 +1,61 @@ -package emu.grasscutter.data.binout; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class HomeworldDefaultSaveData { - - @SerializedName(value = "KFHBFNPDJBE", alternate = "PKACPHDGGEI") - List homeBlockLists; - @SerializedName(value = "IJNPADKGNKE", alternate = "MINCKHBNING") - Position bornPos; - @SerializedName("IPIIGEMFLHK") - Position bornRot; - @SerializedName("HHOLBNPIHEM") - Position djinPos; - @SerializedName("KNHCJKHCOAN") - HomeFurniture mainhouse; - - @SerializedName("NIHOJFEKFPG") - List doorLists; - @SerializedName("EPGELGEFJFK") - List stairLists; - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class HomeBlock { - - @SerializedName(value = "FGIJCELCGFI", alternate = "PGDPDIDJEEL") - int blockId; - - @SerializedName("BEAPOFELABD") - List furnitures; - - @SerializedName("MLIODLGDFHJ") - List persistentFurnitures; - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class HomeFurniture { - - @SerializedName(value = "ENHNGKJBJAB", alternate = "KMAAJJHPNBA") - int id; - @SerializedName(value = "NGIEEIOLPPO", alternate = "JFKAHNCPDME") - Position pos; - //@SerializedName(value = "HEOCEHKEBFM", alternate = "LKCKOOGFDBM") - Position rot; - } -} +package emu.grasscutter.data.binout; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.utils.Position; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class HomeworldDefaultSaveData { + + @SerializedName(value = "KFHBFNPDJBE", alternate = "PKACPHDGGEI") + List homeBlockLists; + + @SerializedName(value = "IJNPADKGNKE", alternate = "MINCKHBNING") + Position bornPos; + + @SerializedName("IPIIGEMFLHK") + Position bornRot; + + @SerializedName("HHOLBNPIHEM") + Position djinPos; + + @SerializedName("KNHCJKHCOAN") + HomeFurniture mainhouse; + + @SerializedName("NIHOJFEKFPG") + List doorLists; + + @SerializedName("EPGELGEFJFK") + List stairLists; + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + public static class HomeBlock { + + @SerializedName(value = "FGIJCELCGFI", alternate = "PGDPDIDJEEL") + int blockId; + + @SerializedName("BEAPOFELABD") + List furnitures; + + @SerializedName("MLIODLGDFHJ") + List persistentFurnitures; + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + public static class HomeFurniture { + + @SerializedName(value = "ENHNGKJBJAB", alternate = "KMAAJJHPNBA") + int id; + + @SerializedName(value = "NGIEEIOLPPO", alternate = "JFKAHNCPDME") + Position pos; + // @SerializedName(value = "HEOCEHKEBFM", alternate = "LKCKOOGFDBM") + Position rot; + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/MainQuestData.java b/src/main/java/emu/grasscutter/data/binout/MainQuestData.java index 3033390ec..ba9f17c31 100644 --- a/src/main/java/emu/grasscutter/data/binout/MainQuestData.java +++ b/src/main/java/emu/grasscutter/data/binout/MainQuestData.java @@ -1,81 +1,78 @@ -package emu.grasscutter.data.binout; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.game.quest.enums.QuestType; -import lombok.Data; - -import java.util.List; -import java.util.Objects; - -public class MainQuestData { - private int id; - private int ICLLDPJFIMA; - private int series; - private QuestType type; - - private long titleTextMapHash; - private int[] suggestTrackMainQuestList; - private int[] rewardIdList; - - private SubQuestData[] subQuests; - private List talks; - private long[] preloadLuaList; - - public int getId() { - return id; - } - - public int getSeries() { - return series; - } - - public QuestType getType() { - return type; - } - - public long getTitleTextMapHash() { - return titleTextMapHash; - } - - public int[] getSuggestTrackMainQuestList() { - return suggestTrackMainQuestList; - } - - public int[] getRewardIdList() { - return rewardIdList; - } - - public SubQuestData[] getSubQuests() { - return subQuests; - } - - public List getTalks() { - return talks; - } - - public void onLoad() { - this.talks = talks.stream().filter(Objects::nonNull).toList(); - } - - @Data - public static class SubQuestData { - private int subId; - private int order; - } - - - @Data - @Entity - public static class TalkData { - private int id; - private String heroTalk; - - public TalkData() { - } - - public TalkData(int id, String heroTalk) { - this.id = id; - this.heroTalk = heroTalk; - } - } -} +package emu.grasscutter.data.binout; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.game.quest.enums.QuestType; +import java.util.List; +import java.util.Objects; +import lombok.Data; + +public class MainQuestData { + private int id; + private int ICLLDPJFIMA; + private int series; + private QuestType type; + + private long titleTextMapHash; + private int[] suggestTrackMainQuestList; + private int[] rewardIdList; + + private SubQuestData[] subQuests; + private List talks; + private long[] preloadLuaList; + + public int getId() { + return id; + } + + public int getSeries() { + return series; + } + + public QuestType getType() { + return type; + } + + public long getTitleTextMapHash() { + return titleTextMapHash; + } + + public int[] getSuggestTrackMainQuestList() { + return suggestTrackMainQuestList; + } + + public int[] getRewardIdList() { + return rewardIdList; + } + + public SubQuestData[] getSubQuests() { + return subQuests; + } + + public List getTalks() { + return talks; + } + + public void onLoad() { + this.talks = talks.stream().filter(Objects::nonNull).toList(); + } + + @Data + public static class SubQuestData { + private int subId; + private int order; + } + + @Data + @Entity + public static class TalkData { + private int id; + private String heroTalk; + + public TalkData() {} + + public TalkData(int id, String heroTalk) { + this.id = id; + this.heroTalk = heroTalk; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java b/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java index 03971aa25..fa21fe4c8 100644 --- a/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java @@ -1,72 +1,71 @@ -package emu.grasscutter.data.binout; - -import emu.grasscutter.data.ResourceLoader.OpenConfigData; - -import java.util.ArrayList; -import java.util.List; - -public class OpenConfigEntry { - private final String name; - private String[] addAbilities; - private int extraTalentIndex; - private SkillPointModifier[] skillPointModifiers; - - public OpenConfigEntry(String name, OpenConfigData[] data) { - this.name = name; - - List abilityList = new ArrayList<>(); - List modList = new ArrayList<>(); - - for (OpenConfigData entry : data) { - if (entry.$type.contains("AddAbility")) { - abilityList.add(entry.abilityName); - } else if (entry.talentIndex > 0) { - this.extraTalentIndex = entry.talentIndex; - } else if (entry.$type.contains("ModifySkillPoint")) { - modList.add(new SkillPointModifier(entry.skillID, entry.pointDelta)); - } - } - - if (abilityList.size() > 0) { - this.addAbilities = abilityList.toArray(new String[0]); - } - - if (modList.size() > 0) { - this.skillPointModifiers = modList.toArray(new SkillPointModifier[0]); - } - } - - public String getName() { - return name; - } - - public String[] getAddAbilities() { - return addAbilities; - } - - public int getExtraTalentIndex() { - return extraTalentIndex; - } - - public SkillPointModifier[] getSkillPointModifiers() { - return skillPointModifiers; - } - - public static class SkillPointModifier { - private final int skillId; - private final int delta; - - public SkillPointModifier(int skillId, int delta) { - this.skillId = skillId; - this.delta = delta; - } - - public int getSkillId() { - return skillId; - } - - public int getDelta() { - return delta; - } - } -} +package emu.grasscutter.data.binout; + +import emu.grasscutter.data.ResourceLoader.OpenConfigData; +import java.util.ArrayList; +import java.util.List; + +public class OpenConfigEntry { + private final String name; + private String[] addAbilities; + private int extraTalentIndex; + private SkillPointModifier[] skillPointModifiers; + + public OpenConfigEntry(String name, OpenConfigData[] data) { + this.name = name; + + List abilityList = new ArrayList<>(); + List modList = new ArrayList<>(); + + for (OpenConfigData entry : data) { + if (entry.$type.contains("AddAbility")) { + abilityList.add(entry.abilityName); + } else if (entry.talentIndex > 0) { + this.extraTalentIndex = entry.talentIndex; + } else if (entry.$type.contains("ModifySkillPoint")) { + modList.add(new SkillPointModifier(entry.skillID, entry.pointDelta)); + } + } + + if (abilityList.size() > 0) { + this.addAbilities = abilityList.toArray(new String[0]); + } + + if (modList.size() > 0) { + this.skillPointModifiers = modList.toArray(new SkillPointModifier[0]); + } + } + + public String getName() { + return name; + } + + public String[] getAddAbilities() { + return addAbilities; + } + + public int getExtraTalentIndex() { + return extraTalentIndex; + } + + public SkillPointModifier[] getSkillPointModifiers() { + return skillPointModifiers; + } + + public static class SkillPointModifier { + private final int skillId; + private final int delta; + + public SkillPointModifier(int skillId, int delta) { + this.skillId = skillId; + this.delta = delta; + } + + public int getSkillId() { + return skillId; + } + + public int getDelta() { + return delta; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/SceneNpcBornData.java b/src/main/java/emu/grasscutter/data/binout/SceneNpcBornData.java index 97d3a8229..1b6d48226 100644 --- a/src/main/java/emu/grasscutter/data/binout/SceneNpcBornData.java +++ b/src/main/java/emu/grasscutter/data/binout/SceneNpcBornData.java @@ -1,29 +1,24 @@ -package emu.grasscutter.data.binout; - -import com.github.davidmoten.rtreemulti.RTree; -import com.github.davidmoten.rtreemulti.geometry.Geometry; -import emu.grasscutter.scripts.data.SceneGroup; -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class SceneNpcBornData { - int sceneId; - List bornPosList; - - /** - * Spatial Index For NPC - */ - transient RTree index; - - /** - * npc groups - */ - transient Map groups = new ConcurrentHashMap<>(); -} +package emu.grasscutter.data.binout; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class SceneNpcBornData { + int sceneId; + List bornPosList; + + /** Spatial Index For NPC */ + transient RTree index; + + /** npc groups */ + transient Map groups = new ConcurrentHashMap<>(); +} diff --git a/src/main/java/emu/grasscutter/data/binout/SceneNpcBornEntry.java b/src/main/java/emu/grasscutter/data/binout/SceneNpcBornEntry.java index f77ce657b..559414bbc 100644 --- a/src/main/java/emu/grasscutter/data/binout/SceneNpcBornEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/SceneNpcBornEntry.java @@ -1,31 +1,42 @@ -package emu.grasscutter.data.binout; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class SceneNpcBornEntry { - @SerializedName(value = "id", alternate = {"_id", "ID"}) - int id; - - @SerializedName(value = "configId", alternate = {"_configId"}) - int configId; - - @SerializedName(value = "pos", alternate = {"_pos"}) - Position pos; - - @SerializedName(value = "rot", alternate = {"_rot"}) - Position rot; - - @SerializedName(value = "groupId", alternate = {"_groupId"}) - int groupId; - - @SerializedName(value = "suiteIdList", alternate = {"_suiteIdList"}) - List suiteIdList; -} +package emu.grasscutter.data.binout; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.utils.Position; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class SceneNpcBornEntry { + @SerializedName( + value = "id", + alternate = {"_id", "ID"}) + int id; + + @SerializedName( + value = "configId", + alternate = {"_configId"}) + int configId; + + @SerializedName( + value = "pos", + alternate = {"_pos"}) + Position pos; + + @SerializedName( + value = "rot", + alternate = {"_rot"}) + Position rot; + + @SerializedName( + value = "groupId", + alternate = {"_groupId"}) + int groupId; + + @SerializedName( + value = "suiteIdList", + alternate = {"_suiteIdList"}) + List suiteIdList; +} diff --git a/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java b/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java index 2b42494b5..8209e624f 100644 --- a/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java @@ -1,26 +1,24 @@ -package emu.grasscutter.data.binout; - -import emu.grasscutter.data.common.PointData; -import lombok.Getter; - -public class ScenePointEntry { - @Getter - final private int sceneId; - @Getter - final private PointData pointData; - - @Deprecated(forRemoval = true) - public ScenePointEntry(String name, PointData pointData) { - this.sceneId = Integer.parseInt(name.split("_")[0]); - this.pointData = pointData; - } - - public ScenePointEntry(int sceneId, PointData pointData) { - this.sceneId = sceneId; - this.pointData = pointData; - } - - public String getName() { - return this.sceneId + "_" + this.pointData.getId(); - } -} +package emu.grasscutter.data.binout; + +import emu.grasscutter.data.common.PointData; +import lombok.Getter; + +public class ScenePointEntry { + @Getter private final int sceneId; + @Getter private final PointData pointData; + + @Deprecated(forRemoval = true) + public ScenePointEntry(String name, PointData pointData) { + this.sceneId = Integer.parseInt(name.split("_")[0]); + this.pointData = pointData; + } + + public ScenePointEntry(int sceneId, PointData pointData) { + this.sceneId = sceneId; + this.pointData = pointData; + } + + public String getName() { + return this.sceneId + "_" + this.pointData.getId(); + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/ScriptSceneData.java b/src/main/java/emu/grasscutter/data/binout/ScriptSceneData.java index 379671fd7..bf75aad4a 100644 --- a/src/main/java/emu/grasscutter/data/binout/ScriptSceneData.java +++ b/src/main/java/emu/grasscutter/data/binout/ScriptSceneData.java @@ -1,21 +1,18 @@ -package emu.grasscutter.data.binout; - -import com.google.gson.annotations.SerializedName; -import lombok.Data; - -import java.util.List; -import java.util.Map; - -@Data -public class ScriptSceneData { - Map scriptObjectList; - - @Data - public static class ScriptObject { - //private SceneGroup groups; - @SerializedName("dummy_points") - private Map> dummyPoints; - - - } -} +package emu.grasscutter.data.binout; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import java.util.Map; +import lombok.Data; + +@Data +public class ScriptSceneData { + Map scriptObjectList; + + @Data + public static class ScriptObject { + // private SceneGroup groups; + @SerializedName("dummy_points") + private Map> dummyPoints; + } +} diff --git a/src/main/java/emu/grasscutter/data/common/CurveInfo.java b/src/main/java/emu/grasscutter/data/common/CurveInfo.java index d9f814723..0535639f0 100644 --- a/src/main/java/emu/grasscutter/data/common/CurveInfo.java +++ b/src/main/java/emu/grasscutter/data/common/CurveInfo.java @@ -1,19 +1,19 @@ -package emu.grasscutter.data.common; - -public class CurveInfo { - private String type; - private String arith; - private float value; - - public String getType() { - return type; - } - - public String getArith() { - return arith; - } - - public float getValue() { - return value; - } -} +package emu.grasscutter.data.common; + +public class CurveInfo { + private String type; + private String arith; + private float value; + + public String getType() { + return type; + } + + public String getArith() { + return arith; + } + + public float getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/data/common/DynamicFloat.java b/src/main/java/emu/grasscutter/data/common/DynamicFloat.java index f5a09a566..acc5e1cf8 100644 --- a/src/main/java/emu/grasscutter/data/common/DynamicFloat.java +++ b/src/main/java/emu/grasscutter/data/common/DynamicFloat.java @@ -1,97 +1,105 @@ -package emu.grasscutter.data.common; - -import it.unimi.dsi.fastutil.floats.FloatArrayList; -import it.unimi.dsi.fastutil.objects.Object2FloatArrayMap; -import it.unimi.dsi.fastutil.objects.Object2FloatMap; -import lombok.val; - -import java.util.List; -import java.util.Optional; - -public class DynamicFloat { - public static DynamicFloat ZERO = new DynamicFloat(0f); - private List ops; - private boolean dynamic = false; - private float constant = 0f; - public DynamicFloat(float constant) { - this.constant = constant; - } - - public DynamicFloat(String key) { - this.dynamic = true; - this.ops = List.of(new StackOp(key)); - } - - public DynamicFloat(boolean b) { - this.dynamic = true; - this.ops = List.of(new StackOp(String.valueOf(b))); - } - - public DynamicFloat(List ops) { - this.dynamic = true; - this.ops = ops; - } - - public String toString(boolean nextBoolean) { - String key = String.valueOf(nextBoolean); - this.ops = List.of(new StackOp(key)); - return ops.toString(); - } - - public float get() { - return this.get(new Object2FloatArrayMap()); - } - - public float get(Object2FloatMap props) { - if (!dynamic) - return constant; - - val fl = new FloatArrayList(); - for (var op : this.ops) { - switch (op.op) { - case CONSTANT -> fl.push(op.fValue); - case KEY -> fl.push(props.getOrDefault(op.sValue, 0f)); - case ADD -> fl.push(fl.popFloat() + fl.popFloat()); - case SUB -> - fl.push(-fl.popFloat() + fl.popFloat()); // [f0, f1, f2] -> [f0, f1-f2] (opposite of RPN order) - case MUL -> fl.push(fl.popFloat() * fl.popFloat()); - case DIV -> fl.push((1f / fl.popFloat()) * fl.popFloat()); // [f0, f1, f2] -> [f0, f1/f2] - case NEXBOOLEAN -> fl.push(props.getOrDefault(Optional.of(op.bValue), 0f)); - } - } - - return fl.popFloat(); // well-formed data will always have only one value left at this point - } - - public static class StackOp { - public Op op; - - public float fValue; - public String sValue; - public boolean bValue; - public StackOp(String s) { - switch (s.toUpperCase()) { - case "ADD" -> this.op = Op.ADD; - case "SUB" -> this.op = Op.SUB; - case "MUL" -> this.op = Op.MUL; - case "DIV" -> this.op = Op.DIV; - default -> { - this.op = Op.KEY; - this.sValue = s; - } - } - } - - public StackOp(boolean b) { - this.op = Op.NEXBOOLEAN; - this.bValue = Boolean.parseBoolean(String.valueOf(b)); - } - - public StackOp(float f) { - this.op = Op.CONSTANT; - this.fValue = f; - } - - enum Op {CONSTANT, KEY, ADD, SUB, MUL, DIV, NEXBOOLEAN} - } -} +package emu.grasscutter.data.common; + +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.objects.Object2FloatArrayMap; +import it.unimi.dsi.fastutil.objects.Object2FloatMap; +import java.util.List; +import java.util.Optional; +import lombok.val; + +public class DynamicFloat { + public static DynamicFloat ZERO = new DynamicFloat(0f); + private List ops; + private boolean dynamic = false; + private float constant = 0f; + + public DynamicFloat(float constant) { + this.constant = constant; + } + + public DynamicFloat(String key) { + this.dynamic = true; + this.ops = List.of(new StackOp(key)); + } + + public DynamicFloat(boolean b) { + this.dynamic = true; + this.ops = List.of(new StackOp(String.valueOf(b))); + } + + public DynamicFloat(List ops) { + this.dynamic = true; + this.ops = ops; + } + + public String toString(boolean nextBoolean) { + String key = String.valueOf(nextBoolean); + this.ops = List.of(new StackOp(key)); + return ops.toString(); + } + + public float get() { + return this.get(new Object2FloatArrayMap()); + } + + public float get(Object2FloatMap props) { + if (!dynamic) return constant; + + val fl = new FloatArrayList(); + for (var op : this.ops) { + switch (op.op) { + case CONSTANT -> fl.push(op.fValue); + case KEY -> fl.push(props.getOrDefault(op.sValue, 0f)); + case ADD -> fl.push(fl.popFloat() + fl.popFloat()); + case SUB -> fl.push( + -fl.popFloat() + fl.popFloat()); // [f0, f1, f2] -> [f0, f1-f2] (opposite of RPN order) + case MUL -> fl.push(fl.popFloat() * fl.popFloat()); + case DIV -> fl.push((1f / fl.popFloat()) * fl.popFloat()); // [f0, f1, f2] -> [f0, f1/f2] + case NEXBOOLEAN -> fl.push(props.getOrDefault(Optional.of(op.bValue), 0f)); + } + } + + return fl.popFloat(); // well-formed data will always have only one value left at this point + } + + public static class StackOp { + public Op op; + + public float fValue; + public String sValue; + public boolean bValue; + + public StackOp(String s) { + switch (s.toUpperCase()) { + case "ADD" -> this.op = Op.ADD; + case "SUB" -> this.op = Op.SUB; + case "MUL" -> this.op = Op.MUL; + case "DIV" -> this.op = Op.DIV; + default -> { + this.op = Op.KEY; + this.sValue = s; + } + } + } + + public StackOp(boolean b) { + this.op = Op.NEXBOOLEAN; + this.bValue = Boolean.parseBoolean(String.valueOf(b)); + } + + public StackOp(float f) { + this.op = Op.CONSTANT; + this.fValue = f; + } + + enum Op { + CONSTANT, + KEY, + ADD, + SUB, + MUL, + DIV, + NEXBOOLEAN + } + } +} diff --git a/src/main/java/emu/grasscutter/data/common/FightPropData.java b/src/main/java/emu/grasscutter/data/common/FightPropData.java index cdc634a39..3f6adbcdb 100644 --- a/src/main/java/emu/grasscutter/data/common/FightPropData.java +++ b/src/main/java/emu/grasscutter/data/common/FightPropData.java @@ -1,25 +1,25 @@ -package emu.grasscutter.data.common; - -import emu.grasscutter.game.props.FightProperty; - -public class FightPropData { - private String propType; - private FightProperty prop; - private float value; - - public String getPropType() { - return propType; - } - - public float getValue() { - return value; - } - - public FightProperty getProp() { - return prop; - } - - public void onLoad() { - this.prop = FightProperty.getPropByName(propType); - } -} +package emu.grasscutter.data.common; + +import emu.grasscutter.game.props.FightProperty; + +public class FightPropData { + private String propType; + private FightProperty prop; + private float value; + + public String getPropType() { + return propType; + } + + public float getValue() { + return value; + } + + public FightProperty getProp() { + return prop; + } + + public void onLoad() { + this.prop = FightProperty.getPropByName(propType); + } +} diff --git a/src/main/java/emu/grasscutter/data/common/ItemParamData.java b/src/main/java/emu/grasscutter/data/common/ItemParamData.java index fe88ff3d7..ff4a1305f 100644 --- a/src/main/java/emu/grasscutter/data/common/ItemParamData.java +++ b/src/main/java/emu/grasscutter/data/common/ItemParamData.java @@ -1,36 +1,39 @@ -package emu.grasscutter.data.common; - -import com.google.gson.annotations.SerializedName; - -// Used in excels -public class ItemParamData { - @SerializedName(value = "id", alternate = {"itemId"}) - private int id; - - @SerializedName(value = "count", alternate = {"itemCount"}) - private int count; - - public ItemParamData() { - } - - public ItemParamData(int id, int count) { - this.id = id; - this.count = count; - } - - public int getId() { - return id; - } - - public int getItemId() { - return id; - } - - public int getCount() { - return count; - } - - public int getItemCount() { - return count; - } -} +package emu.grasscutter.data.common; + +import com.google.gson.annotations.SerializedName; + +// Used in excels +public class ItemParamData { + @SerializedName( + value = "id", + alternate = {"itemId"}) + private int id; + + @SerializedName( + value = "count", + alternate = {"itemCount"}) + private int count; + + public ItemParamData() {} + + public ItemParamData(int id, int count) { + this.id = id; + this.count = count; + } + + public int getId() { + return id; + } + + public int getItemId() { + return id; + } + + public int getCount() { + return count; + } + + public int getItemCount() { + return count; + } +} diff --git a/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java b/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java index e21841540..878c261d1 100644 --- a/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java +++ b/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java @@ -1,27 +1,26 @@ -package emu.grasscutter.data.common; - -public class ItemParamStringData { - private int id; - private String count; - - public ItemParamStringData() { - } - - public int getId() { - return id; - } - - public String getCount() { - return count; - } - - public ItemParamData toItemParamData() { - if (count.contains(";")) { - String[] split = count.split(";"); - count = count.split(";")[split.length - 1]; - } else if (count.contains(".")) { - return new ItemParamData(id, (int) Math.ceil(Double.parseDouble(count))); - } - return new ItemParamData(id, Integer.parseInt(count)); - } -} +package emu.grasscutter.data.common; + +public class ItemParamStringData { + private int id; + private String count; + + public ItemParamStringData() {} + + public int getId() { + return id; + } + + public String getCount() { + return count; + } + + public ItemParamData toItemParamData() { + if (count.contains(";")) { + String[] split = count.split(";"); + count = count.split(";")[split.length - 1]; + } else if (count.contains(".")) { + return new ItemParamData(id, (int) Math.ceil(Double.parseDouble(count))); + } + return new ItemParamData(id, Integer.parseInt(count)); + } +} diff --git a/src/main/java/emu/grasscutter/data/common/PointData.java b/src/main/java/emu/grasscutter/data/common/PointData.java index 749349f01..f8e6bc254 100644 --- a/src/main/java/emu/grasscutter/data/common/PointData.java +++ b/src/main/java/emu/grasscutter/data/common/PointData.java @@ -1,58 +1,61 @@ -package emu.grasscutter.data.common; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.DailyDungeonData; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import lombok.Getter; -import lombok.Setter; - -public class PointData { - @Getter - @Setter - private int id; - private String $type; - @Getter - private Position tranPos; - - @SerializedName(value = "dungeonIds", alternate = {"JHHFPGJNMIN"}) - @Getter - private int[] dungeonIds; - - @SerializedName(value = "dungeonRandomList", alternate = {"OIBKFJNBLHO"}) - @Getter - private int[] dungeonRandomList; - - @SerializedName(value = "tranSceneId", alternate = {"JHBICGBAPIH"}) - @Getter - @Setter - private int tranSceneId; - - public String getType() { - return $type; - } - - public void updateDailyDungeon() { - if (this.dungeonRandomList == null || this.dungeonRandomList.length == 0) { - return; - } - - IntList newDungeons = new IntArrayList(); - int day = Grasscutter.getCurrentDayOfWeek(); - - for (int randomId : this.dungeonRandomList) { - DailyDungeonData data = GameData.getDailyDungeonDataMap().get(randomId); - - if (data != null) { - for (int d : data.getDungeonsByDay(day)) { - newDungeons.add(d); - } - } - } - - this.dungeonIds = newDungeons.toIntArray(); - } -} +package emu.grasscutter.data.common; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.DailyDungeonData; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import lombok.Getter; +import lombok.Setter; + +public class PointData { + @Getter @Setter private int id; + private String $type; + @Getter private Position tranPos; + + @SerializedName( + value = "dungeonIds", + alternate = {"JHHFPGJNMIN"}) + @Getter + private int[] dungeonIds; + + @SerializedName( + value = "dungeonRandomList", + alternate = {"OIBKFJNBLHO"}) + @Getter + private int[] dungeonRandomList; + + @SerializedName( + value = "tranSceneId", + alternate = {"JHBICGBAPIH"}) + @Getter + @Setter + private int tranSceneId; + + public String getType() { + return $type; + } + + public void updateDailyDungeon() { + if (this.dungeonRandomList == null || this.dungeonRandomList.length == 0) { + return; + } + + IntList newDungeons = new IntArrayList(); + int day = Grasscutter.getCurrentDayOfWeek(); + + for (int randomId : this.dungeonRandomList) { + DailyDungeonData data = GameData.getDailyDungeonDataMap().get(randomId); + + if (data != null) { + for (int d : data.getDungeonsByDay(day)) { + newDungeons.add(d); + } + } + } + + this.dungeonIds = newDungeons.toIntArray(); + } +} diff --git a/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java b/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java index 33cb85ae9..b82bc3fbe 100644 --- a/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java +++ b/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java @@ -1,15 +1,14 @@ -package emu.grasscutter.data.common; - -public class PropGrowCurve { - private String type; - private String growCurve; - - public String getType() { - return this.type; - } - - public String getGrowCurve() { - return this.growCurve; - } - -} +package emu.grasscutter.data.common; + +public class PropGrowCurve { + private String type; + private String growCurve; + + public String getType() { + return this.type; + } + + public String getGrowCurve() { + return this.growCurve; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AchievementData.java b/src/main/java/emu/grasscutter/data/excels/AchievementData.java index 6e50ac5b0..e3e1d7c9c 100644 --- a/src/main/java/emu/grasscutter/data/excels/AchievementData.java +++ b/src/main/java/emu/grasscutter/data/excels/AchievementData.java @@ -1,96 +1,99 @@ -package emu.grasscutter.data.excels; - -import com.github.davidmoten.guavamini.Lists; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -@Getter -@ResourceType(name = "AchievementExcelConfigData.json") -public class AchievementData extends GameResource { - private static final AtomicBoolean isDivided = new AtomicBoolean(); - private int goalId; - private int preStageAchievementId; - private final Set groupAchievementIdList = new HashSet<>(); - private boolean isParent; - private long titleTextMapHash; - private long descTextMapHash; - private int finishRewardId; - private boolean isDeleteWatcherAfterFinish; - private int id; - private BattlePassMissionData.TriggerConfig triggerConfig; - private int progress; - private boolean isDisuse; - - public static void divideIntoGroups() { - if (isDivided.get()) { - return; - } - - isDivided.set(true); - var map = GameData.getAchievementDataMap(); - var achievementDataList = map.values().stream().filter(AchievementData::isUsed).toList(); - for (var data : achievementDataList) { - if (!data.hasPreStageAchievement() || data.hasGroupAchievements()) { - continue; - } - - List ids = Lists.newArrayList(); - int parentId = data.getId(); - while (true) { - var next = map.get(parentId + 1); - if (next == null || parentId != next.getPreStageAchievementId()) { - break; - } - - parentId++; - } - - map.get(parentId).isParent = true; - - while (true) { - ids.add(parentId); - var previous = map.get(--parentId); - if (previous == null) { - break; - } else if (!previous.hasPreStageAchievement()) { - ids.add(parentId); - break; - } - } - - for (int i : ids) { - map.get(i).groupAchievementIdList.addAll(ids); - } - } - - map.values().stream().filter(a -> !a.hasGroupAchievements() && a.isUsed()).forEach(a -> a.isParent = true); - } - - public boolean hasPreStageAchievement() { - return this.preStageAchievementId != 0; - } - - public boolean hasGroupAchievements() { - return !this.groupAchievementIdList.isEmpty(); - } - - public boolean isUsed() { - return !this.isDisuse; - } - - public Set getGroupAchievementIdList() { - return this.groupAchievementIdList.stream().collect(Collectors.toUnmodifiableSet()); - } - - public Set getExcludedGroupAchievementIdList() { - return this.groupAchievementIdList.stream().filter(integer -> integer != this.getId()).collect(Collectors.toUnmodifiableSet()); - } -} +package emu.grasscutter.data.excels; + +import com.github.davidmoten.guavamini.Lists; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import lombok.Getter; + +@Getter +@ResourceType(name = "AchievementExcelConfigData.json") +public class AchievementData extends GameResource { + private static final AtomicBoolean isDivided = new AtomicBoolean(); + private int goalId; + private int preStageAchievementId; + private final Set groupAchievementIdList = new HashSet<>(); + private boolean isParent; + private long titleTextMapHash; + private long descTextMapHash; + private int finishRewardId; + private boolean isDeleteWatcherAfterFinish; + private int id; + private BattlePassMissionData.TriggerConfig triggerConfig; + private int progress; + private boolean isDisuse; + + public static void divideIntoGroups() { + if (isDivided.get()) { + return; + } + + isDivided.set(true); + var map = GameData.getAchievementDataMap(); + var achievementDataList = map.values().stream().filter(AchievementData::isUsed).toList(); + for (var data : achievementDataList) { + if (!data.hasPreStageAchievement() || data.hasGroupAchievements()) { + continue; + } + + List ids = Lists.newArrayList(); + int parentId = data.getId(); + while (true) { + var next = map.get(parentId + 1); + if (next == null || parentId != next.getPreStageAchievementId()) { + break; + } + + parentId++; + } + + map.get(parentId).isParent = true; + + while (true) { + ids.add(parentId); + var previous = map.get(--parentId); + if (previous == null) { + break; + } else if (!previous.hasPreStageAchievement()) { + ids.add(parentId); + break; + } + } + + for (int i : ids) { + map.get(i).groupAchievementIdList.addAll(ids); + } + } + + map.values().stream() + .filter(a -> !a.hasGroupAchievements() && a.isUsed()) + .forEach(a -> a.isParent = true); + } + + public boolean hasPreStageAchievement() { + return this.preStageAchievementId != 0; + } + + public boolean hasGroupAchievements() { + return !this.groupAchievementIdList.isEmpty(); + } + + public boolean isUsed() { + return !this.isDisuse; + } + + public Set getGroupAchievementIdList() { + return this.groupAchievementIdList.stream().collect(Collectors.toUnmodifiableSet()); + } + + public Set getExcludedGroupAchievementIdList() { + return this.groupAchievementIdList.stream() + .filter(integer -> integer != this.getId()) + .collect(Collectors.toUnmodifiableSet()); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ActivityData.java b/src/main/java/emu/grasscutter/data/excels/ActivityData.java index d0188dd5f..5f71ec31b 100644 --- a/src/main/java/emu/grasscutter/data/excels/ActivityData.java +++ b/src/main/java/emu/grasscutter/data/excels/ActivityData.java @@ -1,35 +1,37 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.List; -import java.util.Objects; - -@ResourceType(name = "NewActivityExcelConfigData.json", loadPriority = ResourceType.LoadPriority.LOW) -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ActivityData extends GameResource { - int activityId; - String activityType; - List condGroupId; - List watcherId; - List watcherDataList; - - @Override - public int getId() { - return this.activityId; - } - - @Override - public void onLoad() { - this.watcherDataList = watcherId.stream().map(item -> GameData.getActivityWatcherDataMap().get(item.intValue())) - .filter(Objects::nonNull) - .toList(); - } - -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import java.util.Objects; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@ResourceType( + name = "NewActivityExcelConfigData.json", + loadPriority = ResourceType.LoadPriority.LOW) +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ActivityData extends GameResource { + int activityId; + String activityType; + List condGroupId; + List watcherId; + List watcherDataList; + + @Override + public int getId() { + return this.activityId; + } + + @Override + public void onLoad() { + this.watcherDataList = + watcherId.stream() + .map(item -> GameData.getActivityWatcherDataMap().get(item.intValue())) + .filter(Objects::nonNull) + .toList(); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ActivityShopData.java b/src/main/java/emu/grasscutter/data/excels/ActivityShopData.java index bf0f3db37..052e0572f 100644 --- a/src/main/java/emu/grasscutter/data/excels/ActivityShopData.java +++ b/src/main/java/emu/grasscutter/data/excels/ActivityShopData.java @@ -1,30 +1,24 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.shop.ShopType; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = "ActivityShopOverallExcelConfigData.json") -public class ActivityShopData extends GameResource { - @Getter - private int scheduleId; - @Getter - private ShopType shopType; - @Getter - private List sheetList; - - - @Override - public int getId() { - return getShopTypeId(); - } - - public int getShopTypeId() { - if (this.shopType == null) - this.shopType = ShopType.SHOP_TYPE_NONE; - return shopType.shopTypeId; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.shop.ShopType; +import java.util.List; +import lombok.Getter; + +@ResourceType(name = "ActivityShopOverallExcelConfigData.json") +public class ActivityShopData extends GameResource { + @Getter private int scheduleId; + @Getter private ShopType shopType; + @Getter private List sheetList; + + @Override + public int getId() { + return getShopTypeId(); + } + + public int getShopTypeId() { + if (this.shopType == null) this.shopType = ShopType.SHOP_TYPE_NONE; + return shopType.shopTypeId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ActivityWatcherData.java b/src/main/java/emu/grasscutter/data/excels/ActivityWatcherData.java index 7883743a8..6259edc4a 100644 --- a/src/main/java/emu/grasscutter/data/excels/ActivityWatcherData.java +++ b/src/main/java/emu/grasscutter/data/excels/ActivityWatcherData.java @@ -1,37 +1,39 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.WatcherTriggerType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@ResourceType(name = "NewActivityWatcherConfigData.json", loadPriority = ResourceType.LoadPriority.HIGH) -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ActivityWatcherData extends GameResource { - @Getter(onMethod_ = @Override) - int id; - int rewardID; - int progress; - WatcherTrigger triggerConfig; - - @Override - public void onLoad() { - triggerConfig.paramList = triggerConfig.paramList.stream().filter(x -> (x != null) && !x.isBlank()).toList(); - triggerConfig.watcherTriggerType = WatcherTriggerType.getTypeByName(triggerConfig.triggerType); - } - - @Getter - @FieldDefaults(level = AccessLevel.PRIVATE) - public static class WatcherTrigger { - String triggerType; - List paramList; - - transient WatcherTriggerType watcherTriggerType; - } - -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.WatcherTriggerType; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@ResourceType( + name = "NewActivityWatcherConfigData.json", + loadPriority = ResourceType.LoadPriority.HIGH) +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ActivityWatcherData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + + int rewardID; + int progress; + WatcherTrigger triggerConfig; + + @Override + public void onLoad() { + triggerConfig.paramList = + triggerConfig.paramList.stream().filter(x -> (x != null) && !x.isBlank()).toList(); + triggerConfig.watcherTriggerType = WatcherTriggerType.getTypeByName(triggerConfig.triggerType); + } + + @Getter + @FieldDefaults(level = AccessLevel.PRIVATE) + public static class WatcherTrigger { + String triggerType; + List paramList; + + transient WatcherTriggerType watcherTriggerType; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java b/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java index a05e0dbf6..99d7cfb1d 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java @@ -1,37 +1,38 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "AvatarCostumeExcelConfigData.json") -public class AvatarCostumeData extends GameResource { - @SerializedName(value = "skinId", alternate = "costumeId") - private int skinId; - private int itemId; - private int characterId; - private int quality; - - @Override - public int getId() { - return this.skinId; - } - - public int getItemId() { - return this.itemId; - } - - public int getCharacterId() { - return characterId; - } - - public int getQuality() { - return quality; - } - - @Override - public void onLoad() { - GameData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this); - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "AvatarCostumeExcelConfigData.json") +public class AvatarCostumeData extends GameResource { + @SerializedName(value = "skinId", alternate = "costumeId") + private int skinId; + + private int itemId; + private int characterId; + private int quality; + + @Override + public int getId() { + return this.skinId; + } + + public int getItemId() { + return this.itemId; + } + + public int getCharacterId() { + return characterId; + } + + public int getQuality() { + return quality; + } + + @Override + public void onLoad() { + GameData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java b/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java index 4e7815b13..cf23fcf1b 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java @@ -1,36 +1,36 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.CurveInfo; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -@ResourceType(name = "AvatarCurveExcelConfigData.json") -public class AvatarCurveData extends GameResource { - private int level; - private CurveInfo[] curveInfos; - - private Map curveInfoMap; - - @Override - public int getId() { - return this.level; - } - - public int getLevel() { - return level; - } - - public Map getCurveInfos() { - return curveInfoMap; - } - - @Override - public void onLoad() { - this.curveInfoMap = new HashMap<>(); - Stream.of(this.curveInfos).forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.CurveInfo; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +@ResourceType(name = "AvatarCurveExcelConfigData.json") +public class AvatarCurveData extends GameResource { + private int level; + private CurveInfo[] curveInfos; + + private Map curveInfoMap; + + @Override + public int getId() { + return this.level; + } + + public int getLevel() { + return level; + } + + public Map getCurveInfos() { + return curveInfoMap; + } + + @Override + public void onLoad() { + this.curveInfoMap = new HashMap<>(); + Stream.of(this.curveInfos) + .forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java b/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java index 776a213da..21fe202fa 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "AvatarFettersLevelExcelConfigData.json") -public class AvatarFetterLevelData extends GameResource { - private int fetterLevel; - private int needExp; - - @Override - public int getId() { - return this.fetterLevel; - } - - public int getLevel() { - return fetterLevel; - } - - public int getExp() { - return needExp; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "AvatarFettersLevelExcelConfigData.json") +public class AvatarFetterLevelData extends GameResource { + private int fetterLevel; + private int needExp; + + @Override + public int getId() { + return this.fetterLevel; + } + + public int getLevel() { + return fetterLevel; + } + + public int getExp() { + return needExp; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java b/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java index 1702a7bb1..dbcd4b4cb 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java @@ -1,24 +1,22 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "AvatarFlycloakExcelConfigData.json") -public class AvatarFlycloakData extends GameResource { - private int flycloakId; - private long nameTextMapHash; - - @Override - public int getId() { - return this.flycloakId; - } - - public long getNameTextMapHash() { - return nameTextMapHash; - } - - @Override - public void onLoad() { - - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "AvatarFlycloakExcelConfigData.json") +public class AvatarFlycloakData extends GameResource { + private int flycloakId; + private long nameTextMapHash; + + @Override + public int getId() { + return this.flycloakId; + } + + public long getNameTextMapHash() { + return nameTextMapHash; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java b/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java index eae0573ec..e2bb9bccf 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "AvatarLevelExcelConfigData.json") -public class AvatarLevelData extends GameResource { - private int level; - private int exp; - - @Override - public int getId() { - return this.level; - } - - public int getLevel() { - return level; - } - - public int getExp() { - return exp; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "AvatarLevelExcelConfigData.json") +public class AvatarLevelData extends GameResource { + private int level; + private int exp; + + @Override + public int getId() { + return this.level; + } + + public int getLevel() { + return level; + } + + public int getExp() { + return exp; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java b/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java index 69c471628..ad16eccdd 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java @@ -1,75 +1,74 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.FightPropData; -import emu.grasscutter.data.common.ItemParamData; - -import java.util.ArrayList; - -@ResourceType(name = "AvatarPromoteExcelConfigData.json") -public class AvatarPromoteData extends GameResource { - - private int avatarPromoteId; - private int promoteLevel; - private int scoinCost; - private ItemParamData[] costItems; - private int unlockMaxLevel; - private FightPropData[] addProps; - private int requiredPlayerLevel; - - @Override - public int getId() { - return (avatarPromoteId << 8) + promoteLevel; - } - - public int getAvatarPromoteId() { - return avatarPromoteId; - } - - public int getPromoteLevel() { - return promoteLevel; - } - - public ItemParamData[] getCostItems() { - return costItems; - } - - public int getCoinCost() { - return scoinCost; - } - - public FightPropData[] getAddProps() { - return addProps; - } - - public int getUnlockMaxLevel() { - return unlockMaxLevel; - } - - public int getRequiredPlayerLevel() { - return requiredPlayerLevel; - } - - @Override - public void onLoad() { - // Trim item params - ArrayList trim = new ArrayList<>(getAddProps().length); - for (ItemParamData itemParam : getCostItems()) { - if (itemParam.getId() == 0) { - continue; - } - trim.add(itemParam); - } - this.costItems = trim.toArray(new ItemParamData[trim.size()]); - // Trim fight prop data (just in case) - ArrayList parsed = new ArrayList<>(getAddProps().length); - for (FightPropData prop : getAddProps()) { - if (prop.getPropType() != null && prop.getValue() != 0f) { - prop.onLoad(); - parsed.add(prop); - } - } - this.addProps = parsed.toArray(new FightPropData[parsed.size()]); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.FightPropData; +import emu.grasscutter.data.common.ItemParamData; +import java.util.ArrayList; + +@ResourceType(name = "AvatarPromoteExcelConfigData.json") +public class AvatarPromoteData extends GameResource { + + private int avatarPromoteId; + private int promoteLevel; + private int scoinCost; + private ItemParamData[] costItems; + private int unlockMaxLevel; + private FightPropData[] addProps; + private int requiredPlayerLevel; + + @Override + public int getId() { + return (avatarPromoteId << 8) + promoteLevel; + } + + public int getAvatarPromoteId() { + return avatarPromoteId; + } + + public int getPromoteLevel() { + return promoteLevel; + } + + public ItemParamData[] getCostItems() { + return costItems; + } + + public int getCoinCost() { + return scoinCost; + } + + public FightPropData[] getAddProps() { + return addProps; + } + + public int getUnlockMaxLevel() { + return unlockMaxLevel; + } + + public int getRequiredPlayerLevel() { + return requiredPlayerLevel; + } + + @Override + public void onLoad() { + // Trim item params + ArrayList trim = new ArrayList<>(getAddProps().length); + for (ItemParamData itemParam : getCostItems()) { + if (itemParam.getId() == 0) { + continue; + } + trim.add(itemParam); + } + this.costItems = trim.toArray(new ItemParamData[trim.size()]); + // Trim fight prop data (just in case) + ArrayList parsed = new ArrayList<>(getAddProps().length); + for (FightPropData prop : getAddProps()) { + if (prop.getPropType() != null && prop.getValue() != 0f) { + prop.onLoad(); + parsed.add(prop); + } + } + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java b/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java index cd8a342a0..c0f4f289e 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java @@ -1,24 +1,25 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.game.props.ElementType; -import lombok.Getter; - -@ResourceType(name = "AvatarSkillExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) -@Getter -public class AvatarSkillData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private float cdTime; - private int costElemVal; - private int maxChargeNum; - private int triggerID; - private boolean isAttackCameraLock; - private int proudSkillGroupId; - private ElementType costElemType; - private long nameTextMapHash; - private long descTextMapHash; - private String abilityName; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.game.props.ElementType; +import lombok.Getter; + +@ResourceType(name = "AvatarSkillExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) +@Getter +public class AvatarSkillData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private float cdTime; + private int costElemVal; + private int maxChargeNum; + private int triggerID; + private boolean isAttackCameraLock; + private int proudSkillGroupId; + private ElementType costElemType; + private long nameTextMapHash; + private long descTextMapHash; + private String abilityName; +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java index dea6a312d..36818138b 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java @@ -1,86 +1,89 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameDepot; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceLoader.AvatarConfig; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.binout.AbilityEmbryoEntry; -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import lombok.Getter; - -import java.util.List; -import java.util.Optional; -import java.util.stream.IntStream; - -@ResourceType(name = "AvatarSkillDepotExcelConfigData.json", loadPriority = LoadPriority.HIGH) -@Getter -public class AvatarSkillDepotData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private int energySkill; - private int attackModeSkill; - - private List skills; - private List subSkills; - private List extraAbilities; - private List talents; - private List inherentProudSkillOpens; - - private String talentStarName; - private String skillDepotAbilityGroup; - - // Transient - private AvatarSkillData energySkillData; - private ElementType elementType; - private IntList abilities; - private int talentCostItemId; - - public void setAbilities(AbilityEmbryoEntry info) { - this.abilities = new IntArrayList(info.getAbilities().length); - for (String ability : info.getAbilities()) { - this.abilities.add(Utils.abilityHash(ability)); - } - } - - @Override - public void onLoad() { - // Set energy skill data - this.energySkillData = GameData.getAvatarSkillDataMap().get(this.energySkill); - if (this.energySkillData != null) { - this.elementType = this.energySkillData.getCostElemType(); - } else { - this.elementType = ElementType.None; - } - // Set embryo abilities (if player skill depot) - if (getSkillDepotAbilityGroup() != null && getSkillDepotAbilityGroup().length() > 0) { - AvatarConfig config = GameDepot.getPlayerAbilities().get(getSkillDepotAbilityGroup()); - - if (config != null) { - this.setAbilities(new AbilityEmbryoEntry(getSkillDepotAbilityGroup(), config.abilities.stream().map(Object::toString).toArray(String[]::new))); - } - } - - // Get constellation item from GameData - Optional.ofNullable(this.talents) - .map(talents -> talents.get(0)) - .map(i -> GameData.getAvatarTalentDataMap().get((int) i)) - .map(talentData -> talentData.getMainCostItemId()) - .ifPresent(itemId -> this.talentCostItemId = itemId); - } - - public IntStream getSkillsAndEnergySkill() { - return IntStream.concat(this.skills.stream().mapToInt(i -> i), IntStream.of(this.energySkill)) - .filter(skillId -> skillId > 0); - } - - @Getter - public static class InherentProudSkillOpens { - private int proudSkillGroupId; - private int needAvatarPromoteLevel; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceLoader.AvatarConfig; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.binout.AbilityEmbryoEntry; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import java.util.List; +import java.util.Optional; +import java.util.stream.IntStream; +import lombok.Getter; + +@ResourceType(name = "AvatarSkillDepotExcelConfigData.json", loadPriority = LoadPriority.HIGH) +@Getter +public class AvatarSkillDepotData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int energySkill; + private int attackModeSkill; + + private List skills; + private List subSkills; + private List extraAbilities; + private List talents; + private List inherentProudSkillOpens; + + private String talentStarName; + private String skillDepotAbilityGroup; + + // Transient + private AvatarSkillData energySkillData; + private ElementType elementType; + private IntList abilities; + private int talentCostItemId; + + public void setAbilities(AbilityEmbryoEntry info) { + this.abilities = new IntArrayList(info.getAbilities().length); + for (String ability : info.getAbilities()) { + this.abilities.add(Utils.abilityHash(ability)); + } + } + + @Override + public void onLoad() { + // Set energy skill data + this.energySkillData = GameData.getAvatarSkillDataMap().get(this.energySkill); + if (this.energySkillData != null) { + this.elementType = this.energySkillData.getCostElemType(); + } else { + this.elementType = ElementType.None; + } + // Set embryo abilities (if player skill depot) + if (getSkillDepotAbilityGroup() != null && getSkillDepotAbilityGroup().length() > 0) { + AvatarConfig config = GameDepot.getPlayerAbilities().get(getSkillDepotAbilityGroup()); + + if (config != null) { + this.setAbilities( + new AbilityEmbryoEntry( + getSkillDepotAbilityGroup(), + config.abilities.stream().map(Object::toString).toArray(String[]::new))); + } + } + + // Get constellation item from GameData + Optional.ofNullable(this.talents) + .map(talents -> talents.get(0)) + .map(i -> GameData.getAvatarTalentDataMap().get((int) i)) + .map(talentData -> talentData.getMainCostItemId()) + .ifPresent(itemId -> this.talentCostItemId = itemId); + } + + public IntStream getSkillsAndEnergySkill() { + return IntStream.concat(this.skills.stream().mapToInt(i -> i), IntStream.of(this.energySkill)) + .filter(skillId -> skillId > 0); + } + + @Getter + public static class InherentProudSkillOpens { + private int proudSkillGroupId; + private int needAvatarPromoteLevel; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java b/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java index 9deb8ee23..ea71bef91 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java @@ -1,70 +1,69 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.FightPropData; - -import java.util.ArrayList; - -@ResourceType(name = "AvatarTalentExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) -public class AvatarTalentData extends GameResource { - private int talentId; - private int prevTalent; - private long nameTextMapHash; - private String icon; - private int mainCostItemId; - private int mainCostItemCount; - private String openConfig; - private FightPropData[] addProps; - private float[] paramList; - - @Override - public int getId() { - return this.talentId; - } - - public int PrevTalent() { - return prevTalent; - } - - public long getNameTextMapHash() { - return nameTextMapHash; - } - - public String getIcon() { - return icon; - } - - public int getMainCostItemId() { - return mainCostItemId; - } - - public int getMainCostItemCount() { - return mainCostItemCount; - } - - public String getOpenConfig() { - return openConfig; - } - - public FightPropData[] getAddProps() { - return addProps; - } - - public float[] getParamList() { - return paramList; - } - - @Override - public void onLoad() { - ArrayList parsed = new ArrayList(getAddProps().length); - for (FightPropData prop : getAddProps()) { - if (prop.getPropType() != null || prop.getValue() == 0f) { - prop.onLoad(); - parsed.add(prop); - } - } - this.addProps = parsed.toArray(new FightPropData[parsed.size()]); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.FightPropData; +import java.util.ArrayList; + +@ResourceType(name = "AvatarTalentExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) +public class AvatarTalentData extends GameResource { + private int talentId; + private int prevTalent; + private long nameTextMapHash; + private String icon; + private int mainCostItemId; + private int mainCostItemCount; + private String openConfig; + private FightPropData[] addProps; + private float[] paramList; + + @Override + public int getId() { + return this.talentId; + } + + public int PrevTalent() { + return prevTalent; + } + + public long getNameTextMapHash() { + return nameTextMapHash; + } + + public String getIcon() { + return icon; + } + + public int getMainCostItemId() { + return mainCostItemId; + } + + public int getMainCostItemCount() { + return mainCostItemCount; + } + + public String getOpenConfig() { + return openConfig; + } + + public FightPropData[] getAddProps() { + return addProps; + } + + public float[] getParamList() { + return paramList; + } + + @Override + public void onLoad() { + ArrayList parsed = new ArrayList(getAddProps().length); + for (FightPropData prop : getAddProps()) { + if (prop.getPropType() != null || prop.getValue() == 0f) { + prop.onLoad(); + parsed.add(prop); + } + } + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/BattlePassMissionData.java b/src/main/java/emu/grasscutter/data/excels/BattlePassMissionData.java index c1bb1a295..4756a4a8c 100644 --- a/src/main/java/emu/grasscutter/data/excels/BattlePassMissionData.java +++ b/src/main/java/emu/grasscutter/data/excels/BattlePassMissionData.java @@ -1,69 +1,74 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.BattlePassMissionRefreshType; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus; -import lombok.Getter; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -@ResourceType(name = {"BattlePassMissionExcelConfigData.json"}) -@Getter -public class BattlePassMissionData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private int addPoint; - private int scheduleId; - private int progress; - private TriggerConfig triggerConfig; - private BattlePassMissionRefreshType refreshType; - - private transient Set mainParams; - - public WatcherTriggerType getTriggerType() { - return this.getTriggerConfig().getTriggerType(); - } - - public boolean isCycleRefresh() { - return getRefreshType() == null || getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE; - } - - public boolean isValidRefreshType() { - return getRefreshType() == null || - getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE || - getScheduleId() == 2701; - } - - @Override - public void onLoad() { - if (this.getTriggerConfig() != null) { - var params = getTriggerConfig().getParamList()[0]; - if ((params != null) && !params.isEmpty()) { - this.mainParams = Arrays.stream(params.split("[:;,]")).map(Integer::parseInt).collect(Collectors.toSet()); - } - } - } - - public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() { - var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder(); - - protoBuilder - .setMissionId(getId()) - .setTotalProgress(this.getProgress()) - .setRewardBattlePassPoint(this.getAddPoint()) - .setMissionStatus(MissionStatus.MISSION_STATUS_UNFINISHED) - .setMissionType(this.getRefreshType() == null ? 0 : this.getRefreshType().getValue()); - - return protoBuilder.build(); - } - - @Getter - public static class TriggerConfig { - private WatcherTriggerType triggerType; - private String[] paramList; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.BattlePassMissionRefreshType; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.Getter; + +@ResourceType(name = {"BattlePassMissionExcelConfigData.json"}) +@Getter +public class BattlePassMissionData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int addPoint; + private int scheduleId; + private int progress; + private TriggerConfig triggerConfig; + private BattlePassMissionRefreshType refreshType; + + private transient Set mainParams; + + public WatcherTriggerType getTriggerType() { + return this.getTriggerConfig().getTriggerType(); + } + + public boolean isCycleRefresh() { + return getRefreshType() == null + || getRefreshType() + == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE; + } + + public boolean isValidRefreshType() { + return getRefreshType() == null + || getRefreshType() + == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE + || getScheduleId() == 2701; + } + + @Override + public void onLoad() { + if (this.getTriggerConfig() != null) { + var params = getTriggerConfig().getParamList()[0]; + if ((params != null) && !params.isEmpty()) { + this.mainParams = + Arrays.stream(params.split("[:;,]")).map(Integer::parseInt).collect(Collectors.toSet()); + } + } + } + + public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() { + var protoBuilder = + emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder(); + + protoBuilder + .setMissionId(getId()) + .setTotalProgress(this.getProgress()) + .setRewardBattlePassPoint(this.getAddPoint()) + .setMissionStatus(MissionStatus.MISSION_STATUS_UNFINISHED) + .setMissionType(this.getRefreshType() == null ? 0 : this.getRefreshType().getValue()); + + return protoBuilder.build(); + } + + @Getter + public static class TriggerConfig { + private WatcherTriggerType triggerType; + private String[] paramList; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java b/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java index f16617513..ece418f8e 100644 --- a/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java +++ b/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java @@ -1,27 +1,25 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = "BattlePassRewardExcelConfigData.json") -@Getter -public class BattlePassRewardData extends GameResource { - private int indexId; - private int level; - private List freeRewardIdList; - private List paidRewardIdList; - - @Override - public int getId() { - // Reward ID is a combination of index and level. - // We do this to get a unique ID. - return this.indexId * 100 + this.level; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.Getter; + +@ResourceType(name = "BattlePassRewardExcelConfigData.json") +@Getter +public class BattlePassRewardData extends GameResource { + private int indexId; + private int level; + private List freeRewardIdList; + private List paidRewardIdList; + + @Override + public int getId() { + // Reward ID is a combination of index and level. + // We do this to get a unique ID. + return this.indexId * 100 + this.level; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/BlossomRefreshExcelConfigData.java b/src/main/java/emu/grasscutter/data/excels/BlossomRefreshExcelConfigData.java index e8496db24..66c2bc04f 100644 --- a/src/main/java/emu/grasscutter/data/excels/BlossomRefreshExcelConfigData.java +++ b/src/main/java/emu/grasscutter/data/excels/BlossomRefreshExcelConfigData.java @@ -1,45 +1,46 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = "BlossomRefreshExcelConfigData.json") -@Getter -public class BlossomRefreshExcelConfigData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - // Map details - private long nameTextMapHash; - private long descTextMapHash; - private String icon; - private String clientShowType; // BLOSSOM_SHOWTYPE_CHALLENGE, BLOSSOM_SHOWTYPE_NPCTALK - - // Refresh details - private String refreshType; // Leyline blossoms, magical ore outcrops - private int refreshCount; // Number of entries to spawn at refresh (1 for each leyline type for each city, 4 for magical ore for each city) - private String refreshTime; // Server time-of-day to refresh at - private RefreshCond[] refreshCondVec; // AR requirements etc. - - private int cityId; - private int blossomChestId; // 1 for mora, 2 for exp - private Drop[] dropVec; - - // Unknown details - // @Getter private int reviseLevel; - // @Getter private int campUpdateNeedCount; // Always 1 if specified - - @Getter - public static class Drop { - int dropId; - int previewReward; - } - - @Getter - public static class RefreshCond { - String type; - List param; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.Getter; + +@ResourceType(name = "BlossomRefreshExcelConfigData.json") +@Getter +public class BlossomRefreshExcelConfigData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + // Map details + private long nameTextMapHash; + private long descTextMapHash; + private String icon; + private String clientShowType; // BLOSSOM_SHOWTYPE_CHALLENGE, BLOSSOM_SHOWTYPE_NPCTALK + + // Refresh details + private String refreshType; // Leyline blossoms, magical ore outcrops + private int + refreshCount; // Number of entries to spawn at refresh (1 for each leyline type for each city, + // 4 for magical ore for each city) + private String refreshTime; // Server time-of-day to refresh at + private RefreshCond[] refreshCondVec; // AR requirements etc. + + private int cityId; + private int blossomChestId; // 1 for mora, 2 for exp + private Drop[] dropVec; + + // Unknown details + // @Getter private int reviseLevel; + // @Getter private int campUpdateNeedCount; // Always 1 if specified + + @Getter + public static class Drop { + int dropId; + int previewReward; + } + + @Getter + public static class RefreshCond { + String type; + List param; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/BuffData.java b/src/main/java/emu/grasscutter/data/excels/BuffData.java index b908fc666..f9c1a7dbf 100644 --- a/src/main/java/emu/grasscutter/data/excels/BuffData.java +++ b/src/main/java/emu/grasscutter/data/excels/BuffData.java @@ -1,27 +1,28 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.ServerBuffType; -import lombok.Getter; - -@ResourceType(name = "BuffExcelConfigData.json") -@Getter -public class BuffData extends GameResource { - private int groupId; - private int serverBuffId; - private float time; - private boolean isPersistent; - private ServerBuffType serverBuffType; - private String abilityName; - private String modifierName; - - @Override - public int getId() { - return this.serverBuffId; - } - - public void onLoad() { - this.serverBuffType = this.serverBuffType != null ? this.serverBuffType : ServerBuffType.SERVER_BUFF_NONE; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.ServerBuffType; +import lombok.Getter; + +@ResourceType(name = "BuffExcelConfigData.json") +@Getter +public class BuffData extends GameResource { + private int groupId; + private int serverBuffId; + private float time; + private boolean isPersistent; + private ServerBuffType serverBuffType; + private String abilityName; + private String modifierName; + + @Override + public int getId() { + return this.serverBuffId; + } + + public void onLoad() { + this.serverBuffType = + this.serverBuffType != null ? this.serverBuffType : ServerBuffType.SERVER_BUFF_NONE; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ChapterData.java b/src/main/java/emu/grasscutter/data/excels/ChapterData.java index da926d0c8..e0c38b3e2 100644 --- a/src/main/java/emu/grasscutter/data/excels/ChapterData.java +++ b/src/main/java/emu/grasscutter/data/excels/ChapterData.java @@ -1,32 +1,33 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.HashMap; -import java.util.Map; - -@ResourceType(name = "ChapterExcelConfigData.json") -@Getter -@Setter // TODO: remove on next API break -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ChapterData extends GameResource { - // Why public? TODO: privatise next API break - public static final Map beginQuestChapterMap = new HashMap<>(); - public static final Map endQuestChapterMap = new HashMap<>(); - @Getter(onMethod_ = @Override) - int id; - int beginQuestId; - int endQuestId; - int needPlayerLevel; - - @Override - public void onLoad() { - beginQuestChapterMap.put(beginQuestId, this); - beginQuestChapterMap.put(endQuestId, this); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.HashMap; +import java.util.Map; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "ChapterExcelConfigData.json") +@Getter +@Setter // TODO: remove on next API break +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ChapterData extends GameResource { + // Why public? TODO: privatise next API break + public static final Map beginQuestChapterMap = new HashMap<>(); + public static final Map endQuestChapterMap = new HashMap<>(); + + @Getter(onMethod_ = @Override) + int id; + + int beginQuestId; + int endQuestId; + int needPlayerLevel; + + @Override + public void onLoad() { + beginQuestChapterMap.put(beginQuestId, this); + beginQuestChapterMap.put(endQuestId, this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CityData.java b/src/main/java/emu/grasscutter/data/excels/CityData.java index e94627fde..55476008c 100644 --- a/src/main/java/emu/grasscutter/data/excels/CityData.java +++ b/src/main/java/emu/grasscutter/data/excels/CityData.java @@ -1,25 +1,24 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@ResourceType(name = "CityConfigData.json", loadPriority = ResourceType.LoadPriority.HIGH) -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class CityData extends GameResource { - int cityId; - int sceneId; - List areaIdVec; - - @Override - public int getId() { - return this.cityId; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "CityConfigData.json", loadPriority = ResourceType.LoadPriority.HIGH) +@Getter +@Setter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class CityData extends GameResource { + int cityId; + int sceneId; + List areaIdVec; + + @Override + public int getId() { + return this.cityId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java b/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java index 734a129da..dc7ed944a 100644 --- a/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java +++ b/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java @@ -1,23 +1,27 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -@ResourceType(name = {"AnimalCodexExcelConfigData.json"}) -@Getter -public class CodexAnimalData extends GameResource { - @Getter(onMethod_ = @Override) - private int Id; - private String type; - private int describeId; - private int sortOrder; - @SerializedName(value = "countType", alternate = {"OCCLHPBCDGL"}) - private CountType countType; - - public enum CountType { - CODEX_COUNT_TYPE_KILL, - CODEX_COUNT_TYPE_CAPTURE - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Getter; + +@ResourceType(name = {"AnimalCodexExcelConfigData.json"}) +@Getter +public class CodexAnimalData extends GameResource { + @Getter(onMethod_ = @Override) + private int Id; + + private String type; + private int describeId; + private int sortOrder; + + @SerializedName( + value = "countType", + alternate = {"OCCLHPBCDGL"}) + private CountType countType; + + public enum CountType { + CODEX_COUNT_TYPE_KILL, + CODEX_COUNT_TYPE_CAPTURE + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java b/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java index be9b25342..a78361df4 100644 --- a/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java +++ b/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java @@ -1,41 +1,41 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = {"QuestCodexExcelConfigData.json"}) -public class CodexQuestData extends GameResource { - private int Id; - private int parentQuestId; - private int chapterId; - private int sortOrder; - private boolean isDisuse; - - public int getParentQuestId() { - return parentQuestId; - } - - public int getId() { - return Id; - } - - public int getChapterId() { - return chapterId; - } - - public int getSortOrder() { - return sortOrder; - } - - public boolean getIsDisuse() { - return isDisuse; - } - - @Override - public void onLoad() { - if (!this.getIsDisuse()) { - GameData.getCodexQuestDataIdMap().put(this.getParentQuestId(), this); - } - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"QuestCodexExcelConfigData.json"}) +public class CodexQuestData extends GameResource { + private int Id; + private int parentQuestId; + private int chapterId; + private int sortOrder; + private boolean isDisuse; + + public int getParentQuestId() { + return parentQuestId; + } + + public int getId() { + return Id; + } + + public int getChapterId() { + return chapterId; + } + + public int getSortOrder() { + return sortOrder; + } + + public boolean getIsDisuse() { + return isDisuse; + } + + @Override + public void onLoad() { + if (!this.getIsDisuse()) { + GameData.getCodexQuestDataIdMap().put(this.getParentQuestId(), this); + } + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java b/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java index c0f5340f8..47c1631ff 100644 --- a/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java +++ b/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java @@ -1,56 +1,47 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import it.unimi.dsi.fastutil.ints.IntCollection; -import it.unimi.dsi.fastutil.ints.IntList; -import lombok.Getter; - -@ResourceType(name = {"ReliquaryCodexExcelConfigData.json"}) -public class CodexReliquaryData extends GameResource { - @Getter - private int Id; - @Getter - private int suitId; - @Getter - private int level; - @Getter - private int cupId; - @Getter - private int leatherId; - @Getter - private int capId; - @Getter - private int flowerId; - @Getter - private int sandId; - @Getter - private int sortOrder; - private transient IntCollection ids; - - public boolean containsId(int id) { - return getIds().contains(id); - } - - public IntCollection getIds() { - if (this.ids == null) { - int[] idsArr = {cupId, leatherId, capId, flowerId, sandId}; - this.ids = IntList.of(idsArr); - } - return this.ids; - } - - @Override - public void onLoad() { - // Normalize all itemIds to the 0-substat form - cupId = (cupId / 10) * 10; - leatherId = (leatherId / 10) * 10; - capId = (capId / 10) * 10; - flowerId = (flowerId / 10) * 10; - sandId = (sandId / 10) * 10; - - GameData.getCodexReliquaryArrayList().add(this); - GameData.getCodexReliquaryDataIdMap().put(getSuitId(), this); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import it.unimi.dsi.fastutil.ints.IntCollection; +import it.unimi.dsi.fastutil.ints.IntList; +import lombok.Getter; + +@ResourceType(name = {"ReliquaryCodexExcelConfigData.json"}) +public class CodexReliquaryData extends GameResource { + @Getter private int Id; + @Getter private int suitId; + @Getter private int level; + @Getter private int cupId; + @Getter private int leatherId; + @Getter private int capId; + @Getter private int flowerId; + @Getter private int sandId; + @Getter private int sortOrder; + private transient IntCollection ids; + + public boolean containsId(int id) { + return getIds().contains(id); + } + + public IntCollection getIds() { + if (this.ids == null) { + int[] idsArr = {cupId, leatherId, capId, flowerId, sandId}; + this.ids = IntList.of(idsArr); + } + return this.ids; + } + + @Override + public void onLoad() { + // Normalize all itemIds to the 0-substat form + cupId = (cupId / 10) * 10; + leatherId = (leatherId / 10) * 10; + capId = (capId / 10) * 10; + flowerId = (flowerId / 10) * 10; + sandId = (sandId / 10) * 10; + + GameData.getCodexReliquaryArrayList().add(this); + GameData.getCodexReliquaryDataIdMap().put(getSuitId(), this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CombineData.java b/src/main/java/emu/grasscutter/data/excels/CombineData.java index e14b902a7..f908d1c72 100644 --- a/src/main/java/emu/grasscutter/data/excels/CombineData.java +++ b/src/main/java/emu/grasscutter/data/excels/CombineData.java @@ -1,82 +1,82 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; - -import java.util.List; -import java.util.stream.Collectors; - -@ResourceType(name = "CombineExcelConfigData.json") -public class CombineData extends GameResource { - - private int combineId; - private int playerLevel; - private boolean isDefaultShow; - private int combineType; - private int subCombineType; - private int resultItemId; - private int resultItemCount; - private int scoinCost; - private List randomItems; - private List materialItems; - private String recipeType; - - @Override - public int getId() { - return this.combineId; - } - - @Override - public void onLoad() { - super.onLoad(); - // clean data - randomItems = randomItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); - materialItems = materialItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); - } - - public int getCombineId() { - return combineId; - } - - public int getPlayerLevel() { - return playerLevel; - } - - public boolean isDefaultShow() { - return isDefaultShow; - } - - public int getCombineType() { - return combineType; - } - - public int getSubCombineType() { - return subCombineType; - } - - public int getResultItemId() { - return resultItemId; - } - - public int getResultItemCount() { - return resultItemCount; - } - - public int getScoinCost() { - return scoinCost; - } - - public List getRandomItems() { - return randomItems; - } - - public List getMaterialItems() { - return materialItems; - } - - public String getRecipeType() { - return recipeType; - } - -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; +import java.util.stream.Collectors; + +@ResourceType(name = "CombineExcelConfigData.json") +public class CombineData extends GameResource { + + private int combineId; + private int playerLevel; + private boolean isDefaultShow; + private int combineType; + private int subCombineType; + private int resultItemId; + private int resultItemCount; + private int scoinCost; + private List randomItems; + private List materialItems; + private String recipeType; + + @Override + public int getId() { + return this.combineId; + } + + @Override + public void onLoad() { + super.onLoad(); + // clean data + randomItems = + randomItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); + materialItems = + materialItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); + } + + public int getCombineId() { + return combineId; + } + + public int getPlayerLevel() { + return playerLevel; + } + + public boolean isDefaultShow() { + return isDefaultShow; + } + + public int getCombineType() { + return combineType; + } + + public int getSubCombineType() { + return subCombineType; + } + + public int getResultItemId() { + return resultItemId; + } + + public int getResultItemCount() { + return resultItemCount; + } + + public int getScoinCost() { + return scoinCost; + } + + public List getRandomItems() { + return randomItems; + } + + public List getMaterialItems() { + return materialItems; + } + + public String getRecipeType() { + return recipeType; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CompoundData.java b/src/main/java/emu/grasscutter/data/excels/CompoundData.java index c17aa1195..d72cd28d1 100644 --- a/src/main/java/emu/grasscutter/data/excels/CompoundData.java +++ b/src/main/java/emu/grasscutter/data/excels/CompoundData.java @@ -1,22 +1,24 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = {"CompoundExcelConfigData.json"}, loadPriority = ResourceType.LoadPriority.LOW) -@Getter -public class CompoundData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private int groupID; - private int rankLevel; - private boolean isDefaultUnlocked; - private int costTime; - private int queueSize; - private List inputVec; - private List outputVec; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; +import lombok.Getter; + +@ResourceType( + name = {"CompoundExcelConfigData.json"}, + loadPriority = ResourceType.LoadPriority.LOW) +@Getter +public class CompoundData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int groupID; + private int rankLevel; + private boolean isDefaultUnlocked; + private int costTime; + private int queueSize; + private List inputVec; + private List outputVec; +} diff --git a/src/main/java/emu/grasscutter/data/excels/CookBonusData.java b/src/main/java/emu/grasscutter/data/excels/CookBonusData.java index c360760a1..50591dce9 100644 --- a/src/main/java/emu/grasscutter/data/excels/CookBonusData.java +++ b/src/main/java/emu/grasscutter/data/excels/CookBonusData.java @@ -1,42 +1,43 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; - -@ResourceType(name = {"CookBonusExcelConfigData.json"}, loadPriority = LoadPriority.LOW) -public class CookBonusData extends GameResource { - private int avatarId; - private int recipeId; - private int[] paramVec; - private int[] complexParamVec; - - @Override - public int getId() { - return this.avatarId; - } - - public int getAvatarId() { - return avatarId; - } - - public int getRecipeId() { - return recipeId; - } - - public int[] getParamVec() { - return paramVec; - } - - public int[] getComplexParamVec() { - return complexParamVec; - } - - public int getReplacementItemId() { - return this.paramVec[0]; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; + +@ResourceType( + name = {"CookBonusExcelConfigData.json"}, + loadPriority = LoadPriority.LOW) +public class CookBonusData extends GameResource { + private int avatarId; + private int recipeId; + private int[] paramVec; + private int[] complexParamVec; + + @Override + public int getId() { + return this.avatarId; + } + + public int getAvatarId() { + return avatarId; + } + + public int getRecipeId() { + return recipeId; + } + + public int[] getParamVec() { + return paramVec; + } + + public int[] getComplexParamVec() { + return complexParamVec; + } + + public int getReplacementItemId() { + return this.paramVec[0]; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/CookRecipeData.java b/src/main/java/emu/grasscutter/data/excels/CookRecipeData.java index 656d8ebca..f463980f9 100644 --- a/src/main/java/emu/grasscutter/data/excels/CookRecipeData.java +++ b/src/main/java/emu/grasscutter/data/excels/CookRecipeData.java @@ -1,23 +1,24 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.ItemParamData; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = {"CookRecipeExcelConfigData.json"}, loadPriority = LoadPriority.LOW) -@Getter -public class CookRecipeData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - - private int rankLevel; - private boolean isDefaultUnlocked; - private int maxProficiency; - - private List qualityOutputVec; - private List inputVec; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; +import lombok.Getter; + +@ResourceType( + name = {"CookRecipeExcelConfigData.json"}, + loadPriority = LoadPriority.LOW) +@Getter +public class CookRecipeData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int rankLevel; + private boolean isDefaultUnlocked; + private int maxProficiency; + + private List qualityOutputVec; + private List inputVec; +} diff --git a/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java b/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java index 62648f192..db6701f17 100644 --- a/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java +++ b/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java @@ -1,43 +1,44 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.Calendar; - -@ResourceType(name = "DailyDungeonConfigData.json") -public class DailyDungeonData extends GameResource { - private static final int[] empty = new int[0]; - private final Int2ObjectMap map; - @Getter(onMethod_ = @Override) - private int id; - private int[] monday; - private int[] tuesday; - private int[] wednesday; - private int[] thursday; - private int[] friday; - private int[] saturday; - private int[] sunday; - - public DailyDungeonData() { - this.map = new Int2ObjectOpenHashMap<>(); - } - - public int[] getDungeonsByDay(int day) { - return map.getOrDefault(day, empty); - } - - @Override - public void onLoad() { - map.put(Calendar.MONDAY, monday); - map.put(Calendar.TUESDAY, tuesday); - map.put(Calendar.WEDNESDAY, wednesday); - map.put(Calendar.THURSDAY, thursday); - map.put(Calendar.FRIDAY, friday); - map.put(Calendar.SATURDAY, saturday); - map.put(Calendar.SUNDAY, sunday); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.Calendar; +import lombok.Getter; + +@ResourceType(name = "DailyDungeonConfigData.json") +public class DailyDungeonData extends GameResource { + private static final int[] empty = new int[0]; + private final Int2ObjectMap map; + + @Getter(onMethod_ = @Override) + private int id; + + private int[] monday; + private int[] tuesday; + private int[] wednesday; + private int[] thursday; + private int[] friday; + private int[] saturday; + private int[] sunday; + + public DailyDungeonData() { + this.map = new Int2ObjectOpenHashMap<>(); + } + + public int[] getDungeonsByDay(int day) { + return map.getOrDefault(day, empty); + } + + @Override + public void onLoad() { + map.put(Calendar.MONDAY, monday); + map.put(Calendar.TUESDAY, tuesday); + map.put(Calendar.WEDNESDAY, wednesday); + map.put(Calendar.THURSDAY, thursday); + map.put(Calendar.FRIDAY, friday); + map.put(Calendar.SATURDAY, saturday); + map.put(Calendar.SUNDAY, sunday); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/DungeonData.java b/src/main/java/emu/grasscutter/data/excels/DungeonData.java index 73d6eb100..c558e2620 100644 --- a/src/main/java/emu/grasscutter/data/excels/DungeonData.java +++ b/src/main/java/emu/grasscutter/data/excels/DungeonData.java @@ -1,36 +1,33 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -@ResourceType(name = "DungeonExcelConfigData.json") -public class DungeonData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - @Getter - private int sceneId; - @Getter - private int showLevel; - private int passRewardPreviewID; - private String involveType; // TODO enum - - private RewardPreviewData previewData; - - @Getter - private int statueCostID; - @Getter - private int statueCostCount; - - public RewardPreviewData getRewardPreview() { - return previewData; - } - - @Override - public void onLoad() { - if (this.passRewardPreviewID > 0) { - this.previewData = GameData.getRewardPreviewDataMap().get(this.passRewardPreviewID); - } - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Getter; + +@ResourceType(name = "DungeonExcelConfigData.json") +public class DungeonData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + @Getter private int sceneId; + @Getter private int showLevel; + private int passRewardPreviewID; + private String involveType; // TODO enum + + private RewardPreviewData previewData; + + @Getter private int statueCostID; + @Getter private int statueCostCount; + + public RewardPreviewData getRewardPreview() { + return previewData; + } + + @Override + public void onLoad() { + if (this.passRewardPreviewID > 0) { + this.previewData = GameData.getRewardPreviewDataMap().get(this.passRewardPreviewID); + } + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/DungeonEntryData.java b/src/main/java/emu/grasscutter/data/excels/DungeonEntryData.java index f5b434403..3b21cd97e 100644 --- a/src/main/java/emu/grasscutter/data/excels/DungeonEntryData.java +++ b/src/main/java/emu/grasscutter/data/excels/DungeonEntryData.java @@ -1,16 +1,17 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; -import lombok.Setter; - -@ResourceType(name = "DungeonEntryExcelConfigData.json") -@Getter -@Setter // TODO: remove this next API break -public class DungeonEntryData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private int dungeonEntryId; - private int sceneId; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Getter; +import lombok.Setter; + +@ResourceType(name = "DungeonEntryExcelConfigData.json") +@Getter +@Setter // TODO: remove this next API break +public class DungeonEntryData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int dungeonEntryId; + private int sceneId; +} diff --git a/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java b/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java index 2aeb65ae1..7b2d16f67 100644 --- a/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java +++ b/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java @@ -1,35 +1,36 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; - -import java.util.List; - -@ResourceType(name = "EnvAnimalGatherExcelConfigData.json", loadPriority = ResourceType.LoadPriority.LOW) -public class EnvAnimalGatherConfigData extends GameResource { - private int animalId; - private String entityType; - private List gatherItemId; - private String excludeWeathers; - private int aliveTime; - private int escapeTime; - private int escapeRadius; - - @Override - public int getId() { - return animalId; - } - - public int getAnimalId() { - return animalId; - } - - public String getEntityType() { - return entityType; - } - - public ItemParamData getGatherItem() { - return gatherItemId.size() > 0 ? gatherItemId.get(0) : null; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; + +@ResourceType( + name = "EnvAnimalGatherExcelConfigData.json", + loadPriority = ResourceType.LoadPriority.LOW) +public class EnvAnimalGatherConfigData extends GameResource { + private int animalId; + private String entityType; + private List gatherItemId; + private String excludeWeathers; + private int aliveTime; + private int escapeTime; + private int escapeRadius; + + @Override + public int getId() { + return animalId; + } + + public int getAnimalId() { + return animalId; + } + + public String getEntityType() { + return entityType; + } + + public ItemParamData getGatherItem() { + return gatherItemId.size() > 0 ? gatherItemId.get(0) : null; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java b/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java index bf0c3d537..e832c6927 100644 --- a/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java +++ b/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java @@ -1,60 +1,59 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.FightPropData; - -import java.util.ArrayList; - -@ResourceType(name = "EquipAffixExcelConfigData.json") -public class EquipAffixData extends GameResource { - - private int affixId; - private int id; - private int level; - private long nameTextMapHash; - private String openConfig; - private FightPropData[] addProps; - private float[] paramList; - - @Override - public int getId() { - return affixId; - } - - public int getMainId() { - return id; - } - - public int getLevel() { - return level; - } - - public long getNameTextMapHash() { - return nameTextMapHash; - } - - public String getOpenConfig() { - return openConfig; - } - - public FightPropData[] getAddProps() { - return addProps; - } - - public float[] getParamList() { - return paramList; - } - - @Override - public void onLoad() { - ArrayList parsed = new ArrayList(getAddProps().length); - for (FightPropData prop : getAddProps()) { - if (prop.getPropType() != null && prop.getValue() != 0f) { - prop.onLoad(); - parsed.add(prop); - } - } - this.addProps = parsed.toArray(new FightPropData[parsed.size()]); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.FightPropData; +import java.util.ArrayList; + +@ResourceType(name = "EquipAffixExcelConfigData.json") +public class EquipAffixData extends GameResource { + + private int affixId; + private int id; + private int level; + private long nameTextMapHash; + private String openConfig; + private FightPropData[] addProps; + private float[] paramList; + + @Override + public int getId() { + return affixId; + } + + public int getMainId() { + return id; + } + + public int getLevel() { + return level; + } + + public long getNameTextMapHash() { + return nameTextMapHash; + } + + public String getOpenConfig() { + return openConfig; + } + + public FightPropData[] getAddProps() { + return addProps; + } + + public float[] getParamList() { + return paramList; + } + + @Override + public void onLoad() { + ArrayList parsed = new ArrayList(getAddProps().length); + for (FightPropData prop : getAddProps()) { + if (prop.getPropType() != null && prop.getValue() != 0f) { + prop.onLoad(); + parsed.add(prop); + } + } + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java b/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java index d4ef81fd9..a75e8910c 100644 --- a/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java +++ b/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java @@ -1,24 +1,23 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; - -@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) -public class FetterCharacterCardData extends GameResource { - private int avatarId; - private int rewardId; - - @Override - public int getId() { - return avatarId; - } - - public int getRewardId() { - return rewardId; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; + +@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) +public class FetterCharacterCardData extends GameResource { + private int avatarId; + private int rewardId; + + @Override + public int getId() { + return avatarId; + } + + public int getRewardId() { + return rewardId; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/FetterData.java b/src/main/java/emu/grasscutter/data/excels/FetterData.java index a32a90c4c..35c0a4ab9 100644 --- a/src/main/java/emu/grasscutter/data/excels/FetterData.java +++ b/src/main/java/emu/grasscutter/data/excels/FetterData.java @@ -1,32 +1,38 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.OpenCondData; - -import java.util.List; - -@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json", "PhotographExpressionExcelConfigData.json", "PhotographPosenameExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST) -public class FetterData extends GameResource { - private int avatarId; - private int fetterId; - private List openCond; - - @Override - public int getId() { - return fetterId; - } - - public int getAvatarId() { - return avatarId; - } - - public List getOpenConds() { - return openCond; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.OpenCondData; +import java.util.List; + +@ResourceType( + name = { + "FetterInfoExcelConfigData.json", + "FettersExcelConfigData.json", + "FetterStoryExcelConfigData.json", + "PhotographExpressionExcelConfigData.json", + "PhotographPosenameExcelConfigData.json" + }, + loadPriority = LoadPriority.HIGHEST) +public class FetterData extends GameResource { + private int avatarId; + private int fetterId; + private List openCond; + + @Override + public int getId() { + return fetterId; + } + + public int getAvatarId() { + return avatarId; + } + + public List getOpenConds() { + return openCond; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/ForgeData.java b/src/main/java/emu/grasscutter/data/excels/ForgeData.java index fe7c1e1e6..0aea092d0 100644 --- a/src/main/java/emu/grasscutter/data/excels/ForgeData.java +++ b/src/main/java/emu/grasscutter/data/excels/ForgeData.java @@ -1,27 +1,29 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.ItemParamData; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = {"ForgeExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST) -@Getter -public class ForgeData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private int playerLevel; - private int forgeType; - private int showItemId; - private int resultItemId; - private int resultItemCount; - private int forgeTime; - private int queueNum; - private int scoinCost; - private int priority; - private int forgePoint; - private List materialItems; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; +import lombok.Getter; + +@ResourceType( + name = {"ForgeExcelConfigData.json"}, + loadPriority = LoadPriority.HIGHEST) +@Getter +public class ForgeData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int playerLevel; + private int forgeType; + private int showItemId; + private int resultItemId; + private int resultItemCount; + private int forgeTime; + private int queueNum; + private int scoinCost; + private int priority; + private int forgePoint; + private List materialItems; +} diff --git a/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java b/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java index 91ff6a221..f7730f626 100644 --- a/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java +++ b/src/main/java/emu/grasscutter/data/excels/FurnitureMakeConfigData.java @@ -1,37 +1,34 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -@ResourceType(name = {"FurnitureMakeExcelConfigData.json"}) -public class FurnitureMakeConfigData extends GameResource { - - int configID; - int furnitureItemID; - int count; - int exp; - List materialItems; - int makeTime; - int maxAccelerateTime; - int quickFetchMaterialNum; - - @Override - public int getId() { - return configID; - } - - @Override - public void onLoad() { - this.materialItems = materialItems.stream() - .filter(x -> x.getId() > 0) - .toList(); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ResourceType(name = {"FurnitureMakeExcelConfigData.json"}) +public class FurnitureMakeConfigData extends GameResource { + + int configID; + int furnitureItemID; + int count; + int exp; + List materialItems; + int makeTime; + int maxAccelerateTime; + int quickFetchMaterialNum; + + @Override + public int getId() { + return configID; + } + + @Override + public void onLoad() { + this.materialItems = materialItems.stream().filter(x -> x.getId() > 0).toList(); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/GatherData.java b/src/main/java/emu/grasscutter/data/excels/GatherData.java index d7fb33818..2e0f47539 100644 --- a/src/main/java/emu/grasscutter/data/excels/GatherData.java +++ b/src/main/java/emu/grasscutter/data/excels/GatherData.java @@ -1,49 +1,47 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "GatherExcelConfigData.json") -public class GatherData extends GameResource { - private int pointType; - private int id; - private int gadgetId; - private int itemId; - private int cd; // Probably hours - private boolean isForbidGuest; - private boolean initDisableInteract; - - @Override - public int getId() { - return this.pointType; - } - - public int getGatherId() { - return id; - } - - public int getGadgetId() { - return gadgetId; - } - - public int getItemId() { - return itemId; - } - - public int getCd() { - return cd; - } - - public boolean isForbidGuest() { - return isForbidGuest; - } - - public boolean initDisableInteract() { - return initDisableInteract; - } - - @Override - public void onLoad() { - - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "GatherExcelConfigData.json") +public class GatherData extends GameResource { + private int pointType; + private int id; + private int gadgetId; + private int itemId; + private int cd; // Probably hours + private boolean isForbidGuest; + private boolean initDisableInteract; + + @Override + public int getId() { + return this.pointType; + } + + public int getGatherId() { + return id; + } + + public int getGadgetId() { + return gadgetId; + } + + public int getItemId() { + return itemId; + } + + public int getCd() { + return cd; + } + + public boolean isForbidGuest() { + return isForbidGuest; + } + + public boolean initDisableInteract() { + return initDisableInteract; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/HomeWorldBgmData.java b/src/main/java/emu/grasscutter/data/excels/HomeWorldBgmData.java index a13eb4a9f..16fb2d1cb 100644 --- a/src/main/java/emu/grasscutter/data/excels/HomeWorldBgmData.java +++ b/src/main/java/emu/grasscutter/data/excels/HomeWorldBgmData.java @@ -1,29 +1,31 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -@ResourceType(name = {"HomeWorldBgmExcelConfigData.json"}) -public class HomeWorldBgmData extends GameResource { - @SerializedName(value = "homeBgmId", alternate = "MJJENLEBKEF") - private int homeBgmId; - private boolean isDefaultUnlock; - private boolean NBIDHGOOCKD; - private boolean JJMNJMCCOKP; - private int cityId; - private int sortOrder; - private String GEGHMJBJMGB; - @SerializedName(value = "bgmNameTextMapHash", alternate = "LMLNBMJFFML") - private long bgmNameTextMapHash; - - @Override - public int getId() { - return this.homeBgmId; - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ResourceType(name = {"HomeWorldBgmExcelConfigData.json"}) +public class HomeWorldBgmData extends GameResource { + @SerializedName(value = "homeBgmId", alternate = "MJJENLEBKEF") + private int homeBgmId; + + private boolean isDefaultUnlock; + private boolean NBIDHGOOCKD; + private boolean JJMNJMCCOKP; + private int cityId; + private int sortOrder; + private String GEGHMJBJMGB; + + @SerializedName(value = "bgmNameTextMapHash", alternate = "LMLNBMJFFML") + private long bgmNameTextMapHash; + + @Override + public int getId() { + return this.homeBgmId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java b/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java index e707a3ac9..6c059d7a4 100644 --- a/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/HomeWorldLevelData.java @@ -1,32 +1,31 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -@ResourceType(name = {"HomeworldLevelExcelConfigData.json"}) -public class HomeWorldLevelData extends GameResource { - - int level; - int exp; - int homeCoinStoreLimit; - int homeFetterExpStoreLimit; - int rewardId; - int furnitureMakeSlotCount; - int outdoorUnlockBlockCount; - int freeUnlockModuleCount; - int deployNpcCount; - int limitShopGoodsCount; - List levelFuncs; - - @Override - public int getId() { - return level; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ResourceType(name = {"HomeworldLevelExcelConfigData.json"}) +public class HomeWorldLevelData extends GameResource { + + int level; + int exp; + int homeCoinStoreLimit; + int homeFetterExpStoreLimit; + int rewardId; + int furnitureMakeSlotCount; + int outdoorUnlockBlockCount; + int freeUnlockModuleCount; + int deployNpcCount; + int limitShopGoodsCount; + List levelFuncs; + + @Override + public int getId() { + return level; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/InvestigationMonsterData.java b/src/main/java/emu/grasscutter/data/excels/InvestigationMonsterData.java index a822bb7ce..1d84a2368 100644 --- a/src/main/java/emu/grasscutter/data/excels/InvestigationMonsterData.java +++ b/src/main/java/emu/grasscutter/data/excels/InvestigationMonsterData.java @@ -1,31 +1,33 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@ResourceType(name = "InvestigationMonsterConfigData.json", loadPriority = ResourceType.LoadPriority.LOW) -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class InvestigationMonsterData extends GameResource { - @Getter(onMethod_ = @Override) - int id; - int cityId; - List monsterIdList; - List groupIdList; - int rewardPreviewId; - String mapMarkCreateType; - String monsterCategory; - - CityData cityData; - - @Override - public void onLoad() { - this.cityData = GameData.getCityDataMap().get(cityId); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@ResourceType( + name = "InvestigationMonsterConfigData.json", + loadPriority = ResourceType.LoadPriority.LOW) +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class InvestigationMonsterData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + + int cityId; + List monsterIdList; + List groupIdList; + int rewardPreviewId; + String mapMarkCreateType; + String monsterCategory; + + CityData cityData; + + @Override + public void onLoad() { + this.cityData = GameData.getCityDataMap().get(cityId); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ItemData.java b/src/main/java/emu/grasscutter/data/excels/ItemData.java index 88fa85e3f..4ec5ccd00 100644 --- a/src/main/java/emu/grasscutter/data/excels/ItemData.java +++ b/src/main/java/emu/grasscutter/data/excels/ItemData.java @@ -1,147 +1,154 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemUseData; -import emu.grasscutter.game.inventory.EquipType; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.inventory.MaterialType; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.ItemUseAction.ItemUseAction; -import emu.grasscutter.game.props.ItemUseOp; -import emu.grasscutter.game.props.ItemUseTarget; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; -import lombok.Getter; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -@ResourceType(name = {"MaterialExcelConfigData.json", - "WeaponExcelConfigData.json", - "ReliquaryExcelConfigData.json", - "HomeWorldFurnitureExcelConfigData.json" -}) -@Getter -public class ItemData extends GameResource { - // Main - @Getter(onMethod_ = @Override) - private int id; - private final int stackLimit = 1; - private int maxUseCount; - private int rankLevel; - private String effectName; - private int rank; - private int weight; - private int gadgetId; - - private int[] destroyReturnMaterial; - private int[] destroyReturnMaterialCount; - - // Enums - private final ItemType itemType = ItemType.ITEM_NONE; - private MaterialType materialType = MaterialType.MATERIAL_NONE; - private EquipType equipType = EquipType.EQUIP_NONE; - private String effectType; - private String destroyRule; - - // Food - private String foodQuality; - private int[] satiationParams; - - // Usable item - private final ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE; - private List itemUse; - private List itemUseActions; - private final boolean useOnGain = false; - - // Relic - private int mainPropDepotId; - private int appendPropDepotId; - private int appendPropNum; - private int setId; - private int[] addPropLevels; - private int baseConvExp; - private int maxLevel; - - // Weapon - private int weaponPromoteId; - private int weaponBaseExp; - private int storyId; - private int avatarPromoteId; - private int awakenMaterial; - private int[] awakenCosts; - private int[] skillAffix; - private WeaponProperty[] weaponProp; - - // Hash - private long nameTextMapHash; - - // Furniture - private int comfort; - private List furnType; - private List furnitureGadgetID; - - @SerializedName(value = "roomSceneId", alternate = {"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK", "MFGACDIOHGF"}) - private int roomSceneId; - - // Custom - private transient IntSet addPropLevelSet; - - public WeaponProperty[] getWeaponProperties() { - return this.weaponProp; - } - - public boolean canAddRelicProp(int level) { - return this.addPropLevelSet != null && this.addPropLevelSet.contains(level); - } - - public boolean isEquip() { - return this.itemType == ItemType.ITEM_RELIQUARY || this.itemType == ItemType.ITEM_WEAPON; - } - - @Override - public void onLoad() { - if (this.itemType == ItemType.ITEM_RELIQUARY) { - if (this.addPropLevels != null && this.addPropLevels.length > 0) { - this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels); - } - } else if (this.itemType == ItemType.ITEM_WEAPON) { - this.equipType = EquipType.EQUIP_WEAPON; - } else { - this.equipType = EquipType.EQUIP_NONE; - } - - if (this.weaponProp != null) { - this.weaponProp = Arrays.stream(this.weaponProp).filter(prop -> prop.getPropType() != null).toArray(WeaponProperty[]::new); - } - - if (this.getFurnType() != null) { - this.furnType = this.furnType.stream().filter(x -> x > 0).toList(); - } - if (this.getFurnitureGadgetID() != null) { - this.furnitureGadgetID = this.furnitureGadgetID.stream().filter(x -> x > 0).toList(); - } - - // Prevent material type from being null - this.materialType = this.materialType == null ? MaterialType.MATERIAL_NONE : this.materialType; - - if (this.itemUse != null && !this.itemUse.isEmpty()) { - this.itemUseActions = this.itemUse.stream() - .filter(x -> x.getUseOp() != ItemUseOp.ITEM_USE_NONE) - .map(ItemUseAction::fromItemUseData) - .filter(Objects::nonNull) - .toList(); - } - } - - - @Getter - public static class WeaponProperty { - private FightProperty propType; - private float initValue; - private String type; - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemUseData; +import emu.grasscutter.game.inventory.EquipType; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.inventory.MaterialType; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.ItemUseAction.ItemUseAction; +import emu.grasscutter.game.props.ItemUseOp; +import emu.grasscutter.game.props.ItemUseTarget; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import lombok.Getter; + +@ResourceType( + name = { + "MaterialExcelConfigData.json", + "WeaponExcelConfigData.json", + "ReliquaryExcelConfigData.json", + "HomeWorldFurnitureExcelConfigData.json" + }) +@Getter +public class ItemData extends GameResource { + // Main + @Getter(onMethod_ = @Override) + private int id; + + private final int stackLimit = 1; + private int maxUseCount; + private int rankLevel; + private String effectName; + private int rank; + private int weight; + private int gadgetId; + + private int[] destroyReturnMaterial; + private int[] destroyReturnMaterialCount; + + // Enums + private final ItemType itemType = ItemType.ITEM_NONE; + private MaterialType materialType = MaterialType.MATERIAL_NONE; + private EquipType equipType = EquipType.EQUIP_NONE; + private String effectType; + private String destroyRule; + + // Food + private String foodQuality; + private int[] satiationParams; + + // Usable item + private final ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE; + private List itemUse; + private List itemUseActions; + private final boolean useOnGain = false; + + // Relic + private int mainPropDepotId; + private int appendPropDepotId; + private int appendPropNum; + private int setId; + private int[] addPropLevels; + private int baseConvExp; + private int maxLevel; + + // Weapon + private int weaponPromoteId; + private int weaponBaseExp; + private int storyId; + private int avatarPromoteId; + private int awakenMaterial; + private int[] awakenCosts; + private int[] skillAffix; + private WeaponProperty[] weaponProp; + + // Hash + private long nameTextMapHash; + + // Furniture + private int comfort; + private List furnType; + private List furnitureGadgetID; + + @SerializedName( + value = "roomSceneId", + alternate = {"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK", "MFGACDIOHGF"}) + private int roomSceneId; + + // Custom + private transient IntSet addPropLevelSet; + + public WeaponProperty[] getWeaponProperties() { + return this.weaponProp; + } + + public boolean canAddRelicProp(int level) { + return this.addPropLevelSet != null && this.addPropLevelSet.contains(level); + } + + public boolean isEquip() { + return this.itemType == ItemType.ITEM_RELIQUARY || this.itemType == ItemType.ITEM_WEAPON; + } + + @Override + public void onLoad() { + if (this.itemType == ItemType.ITEM_RELIQUARY) { + if (this.addPropLevels != null && this.addPropLevels.length > 0) { + this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels); + } + } else if (this.itemType == ItemType.ITEM_WEAPON) { + this.equipType = EquipType.EQUIP_WEAPON; + } else { + this.equipType = EquipType.EQUIP_NONE; + } + + if (this.weaponProp != null) { + this.weaponProp = + Arrays.stream(this.weaponProp) + .filter(prop -> prop.getPropType() != null) + .toArray(WeaponProperty[]::new); + } + + if (this.getFurnType() != null) { + this.furnType = this.furnType.stream().filter(x -> x > 0).toList(); + } + if (this.getFurnitureGadgetID() != null) { + this.furnitureGadgetID = this.furnitureGadgetID.stream().filter(x -> x > 0).toList(); + } + + // Prevent material type from being null + this.materialType = this.materialType == null ? MaterialType.MATERIAL_NONE : this.materialType; + + if (this.itemUse != null && !this.itemUse.isEmpty()) { + this.itemUseActions = + this.itemUse.stream() + .filter(x -> x.getUseOp() != ItemUseOp.ITEM_USE_NONE) + .map(ItemUseAction::fromItemUseData) + .filter(Objects::nonNull) + .toList(); + } + } + + @Getter + public static class WeaponProperty { + private FightProperty propType; + private float initValue; + private String type; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java b/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java index 54db27097..e7e0370f9 100644 --- a/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java @@ -1,32 +1,32 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.CurveInfo; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -@ResourceType(name = "MonsterCurveExcelConfigData.json") -public class MonsterCurveData extends GameResource { - private int level; - private CurveInfo[] curveInfos; - - private Map curveInfoMap; - - @Override - public int getId() { - return level; - } - - public float getMultByProp(String fightProp) { - return curveInfoMap.getOrDefault(fightProp, 1f); - } - - @Override - public void onLoad() { - this.curveInfoMap = new HashMap<>(); - Stream.of(this.curveInfos).forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.CurveInfo; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +@ResourceType(name = "MonsterCurveExcelConfigData.json") +public class MonsterCurveData extends GameResource { + private int level; + private CurveInfo[] curveInfos; + + private Map curveInfoMap; + + @Override + public int getId() { + return level; + } + + public float getMultByProp(String fightProp) { + return curveInfoMap.getOrDefault(fightProp, 1f); + } + + @Override + public void onLoad() { + this.curveInfoMap = new HashMap<>(); + Stream.of(this.curveInfos) + .forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/MonsterData.java b/src/main/java/emu/grasscutter/data/excels/MonsterData.java index 4e2e13796..6498d1cf1 100644 --- a/src/main/java/emu/grasscutter/data/excels/MonsterData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterData.java @@ -1,103 +1,116 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.PropGrowCurve; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.MonsterType; -import lombok.Getter; - -import java.util.List; -import java.util.Set; - -@ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW) -@Getter -public class MonsterData extends GameResource { - static public Set definedFightProperties = Set.of(FightProperty.FIGHT_PROP_BASE_HP, FightProperty.FIGHT_PROP_BASE_ATTACK, FightProperty.FIGHT_PROP_BASE_DEFENSE, FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, FightProperty.FIGHT_PROP_FIRE_SUB_HURT, FightProperty.FIGHT_PROP_ELEC_SUB_HURT, FightProperty.FIGHT_PROP_WATER_SUB_HURT, FightProperty.FIGHT_PROP_GRASS_SUB_HURT, FightProperty.FIGHT_PROP_WIND_SUB_HURT, FightProperty.FIGHT_PROP_ROCK_SUB_HURT, FightProperty.FIGHT_PROP_ICE_SUB_HURT); - - @Getter(onMethod_ = @Override) - private int id; - - private String monsterName; - private MonsterType type; - private String serverScript; - private List affix; - private String ai; - private int[] equips; - private List hpDrops; - private int killDropId; - private String excludeWeathers; - private int featureTagGroupID; - private int mpPropID; - private String skin; - private int describeId; - private int combatBGMLevel; - private int entityBudgetLevel; - - @SerializedName("hpBase") - private float baseHp; - @SerializedName("attackBase") - private float baseAttack; - @SerializedName("defenseBase") - private float baseDefense; - - private float fireSubHurt; - private float elecSubHurt; - private float grassSubHurt; - private float waterSubHurt; - private float windSubHurt; - private float rockSubHurt; - private float iceSubHurt; - private float physicalSubHurt; - private List propGrowCurves; - private long nameTextMapHash; - private int campID; - - // Transient - private int weaponId; - private MonsterDescribeData describeData; - - public float getFightProperty(FightProperty prop) { - return switch (prop) { - case FIGHT_PROP_BASE_HP -> this.baseHp; - case FIGHT_PROP_BASE_ATTACK -> this.baseAttack; - case FIGHT_PROP_BASE_DEFENSE -> this.baseDefense; - case FIGHT_PROP_PHYSICAL_SUB_HURT -> this.physicalSubHurt; - case FIGHT_PROP_FIRE_SUB_HURT -> this.fireSubHurt; - case FIGHT_PROP_ELEC_SUB_HURT -> this.elecSubHurt; - case FIGHT_PROP_WATER_SUB_HURT -> this.waterSubHurt; - case FIGHT_PROP_GRASS_SUB_HURT -> this.grassSubHurt; - case FIGHT_PROP_WIND_SUB_HURT -> this.windSubHurt; - case FIGHT_PROP_ROCK_SUB_HURT -> this.rockSubHurt; - case FIGHT_PROP_ICE_SUB_HURT -> this.iceSubHurt; - default -> 0f; - }; - } - - @Override - public void onLoad() { - this.describeData = GameData.getMonsterDescribeDataMap().get(this.getDescribeId()); - - for (int id : this.equips) { - if (id == 0) { - continue; - } - GadgetData gadget = GameData.getGadgetDataMap().get(id); - if (gadget == null) { - continue; - } - if (gadget.getItemJsonName().equals("Default_MonsterWeapon")) { - this.weaponId = id; - } - } - } - - @Getter - public class HpDrops { - private int DropId; - private int HpPercent; - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.PropGrowCurve; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.MonsterType; +import java.util.List; +import java.util.Set; +import lombok.Getter; + +@ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW) +@Getter +public class MonsterData extends GameResource { + public static Set definedFightProperties = + Set.of( + FightProperty.FIGHT_PROP_BASE_HP, + FightProperty.FIGHT_PROP_BASE_ATTACK, + FightProperty.FIGHT_PROP_BASE_DEFENSE, + FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, + FightProperty.FIGHT_PROP_FIRE_SUB_HURT, + FightProperty.FIGHT_PROP_ELEC_SUB_HURT, + FightProperty.FIGHT_PROP_WATER_SUB_HURT, + FightProperty.FIGHT_PROP_GRASS_SUB_HURT, + FightProperty.FIGHT_PROP_WIND_SUB_HURT, + FightProperty.FIGHT_PROP_ROCK_SUB_HURT, + FightProperty.FIGHT_PROP_ICE_SUB_HURT); + + @Getter(onMethod_ = @Override) + private int id; + + private String monsterName; + private MonsterType type; + private String serverScript; + private List affix; + private String ai; + private int[] equips; + private List hpDrops; + private int killDropId; + private String excludeWeathers; + private int featureTagGroupID; + private int mpPropID; + private String skin; + private int describeId; + private int combatBGMLevel; + private int entityBudgetLevel; + + @SerializedName("hpBase") + private float baseHp; + + @SerializedName("attackBase") + private float baseAttack; + + @SerializedName("defenseBase") + private float baseDefense; + + private float fireSubHurt; + private float elecSubHurt; + private float grassSubHurt; + private float waterSubHurt; + private float windSubHurt; + private float rockSubHurt; + private float iceSubHurt; + private float physicalSubHurt; + private List propGrowCurves; + private long nameTextMapHash; + private int campID; + + // Transient + private int weaponId; + private MonsterDescribeData describeData; + + public float getFightProperty(FightProperty prop) { + return switch (prop) { + case FIGHT_PROP_BASE_HP -> this.baseHp; + case FIGHT_PROP_BASE_ATTACK -> this.baseAttack; + case FIGHT_PROP_BASE_DEFENSE -> this.baseDefense; + case FIGHT_PROP_PHYSICAL_SUB_HURT -> this.physicalSubHurt; + case FIGHT_PROP_FIRE_SUB_HURT -> this.fireSubHurt; + case FIGHT_PROP_ELEC_SUB_HURT -> this.elecSubHurt; + case FIGHT_PROP_WATER_SUB_HURT -> this.waterSubHurt; + case FIGHT_PROP_GRASS_SUB_HURT -> this.grassSubHurt; + case FIGHT_PROP_WIND_SUB_HURT -> this.windSubHurt; + case FIGHT_PROP_ROCK_SUB_HURT -> this.rockSubHurt; + case FIGHT_PROP_ICE_SUB_HURT -> this.iceSubHurt; + default -> 0f; + }; + } + + @Override + public void onLoad() { + this.describeData = GameData.getMonsterDescribeDataMap().get(this.getDescribeId()); + + for (int id : this.equips) { + if (id == 0) { + continue; + } + GadgetData gadget = GameData.getGadgetDataMap().get(id); + if (gadget == null) { + continue; + } + if (gadget.getItemJsonName().equals("Default_MonsterWeapon")) { + this.weaponId = id; + } + } + } + + @Getter + public class HpDrops { + private int DropId; + private int HpPercent; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java b/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java index c667e3a2d..c5847d6b0 100644 --- a/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java @@ -1,16 +1,17 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import lombok.Getter; - -@ResourceType(name = "MonsterDescribeExcelConfigData.json", loadPriority = LoadPriority.HIGH) -@Getter -public class MonsterDescribeData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private long nameTextMapHash; - private int titleID; - private int specialNameLabID; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import lombok.Getter; + +@ResourceType(name = "MonsterDescribeExcelConfigData.json", loadPriority = LoadPriority.HIGH) +@Getter +public class MonsterDescribeData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private long nameTextMapHash; + private int titleID; + private int specialNameLabID; +} diff --git a/src/main/java/emu/grasscutter/data/excels/MusicGameBasicData.java b/src/main/java/emu/grasscutter/data/excels/MusicGameBasicData.java index 7297e9048..d2aae56c1 100644 --- a/src/main/java/emu/grasscutter/data/excels/MusicGameBasicData.java +++ b/src/main/java/emu/grasscutter/data/excels/MusicGameBasicData.java @@ -1,17 +1,18 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -@ResourceType(name = "MusicGameBasicConfigData.json") -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) -public class MusicGameBasicData extends GameResource { - @Getter(onMethod_ = @Override) - int id; - int musicID; - int musicLevel; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "MusicGameBasicConfigData.json") +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class MusicGameBasicData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + + int musicID; + int musicLevel; +} diff --git a/src/main/java/emu/grasscutter/data/excels/PersonalLineData.java b/src/main/java/emu/grasscutter/data/excels/PersonalLineData.java index ff7d7f29d..c3e6dd2c8 100644 --- a/src/main/java/emu/grasscutter/data/excels/PersonalLineData.java +++ b/src/main/java/emu/grasscutter/data/excels/PersonalLineData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@ResourceType(name = "PersonalLineExcelConfigData.json") -@Getter -@Setter // TODO: remove setters next API break -@FieldDefaults(level = AccessLevel.PRIVATE) -public class PersonalLineData extends GameResource { - @Getter(onMethod_ = @Override) - int id; - int avatarID; - List preQuestId; - int startQuestId; - int chapterId; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "PersonalLineExcelConfigData.json") +@Getter +@Setter // TODO: remove setters next API break +@FieldDefaults(level = AccessLevel.PRIVATE) +public class PersonalLineData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + + int avatarID; + List preQuestId; + int startQuestId; + int chapterId; +} diff --git a/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java b/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java index e5648189f..877e09e90 100644 --- a/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java @@ -1,21 +1,21 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -@ResourceType(name = "PlayerLevelExcelConfigData.json") -@Getter -public class PlayerLevelData extends GameResource { - private int level; - private int exp; - private int rewardId; - private final int expeditionLimitAdd = 0; - private int unlockWorldLevel; - private long unlockDescTextMapHash; - - @Override - public int getId() { - return this.level; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Getter; + +@ResourceType(name = "PlayerLevelExcelConfigData.json") +@Getter +public class PlayerLevelData extends GameResource { + private int level; + private int exp; + private int rewardId; + private final int expeditionLimitAdd = 0; + private int unlockWorldLevel; + private long unlockDescTextMapHash; + + @Override + public int getId() { + return this.level; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java b/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java index c2c08d38a..e60789aa2 100644 --- a/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java +++ b/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java @@ -1,72 +1,57 @@ -package emu.grasscutter.data.excels; - -import dev.morphia.annotations.Transient; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.FightPropData; -import emu.grasscutter.data.common.ItemParamData; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.List; - -@ResourceType(name = "ProudSkillExcelConfigData.json") -public class ProudSkillData extends GameResource { - private int proudSkillId; - @Getter - private int proudSkillGroupId; - @Getter - private int level; - @Getter - private int coinCost; - @Getter - private int breakLevel; - @Getter - private int proudSkillType; - @Getter - private String openConfig; - @Getter - private List costItems; - @Getter - private List filterConds; - @Getter - private List lifeEffectParams; - @Getter - private FightPropData[] addProps; - @Getter - private float[] paramList; - @Getter - private long[] paramDescList; - @Getter - private long nameTextMapHash; - @Transient - private Iterable totalCostItems; - - @Override - public int getId() { - return proudSkillId; - } - - public Iterable getTotalCostItems() { - if (this.totalCostItems == null) { - ArrayList total = (this.costItems != null) ? new ArrayList<>(this.costItems) : new ArrayList<>(1); - if (this.coinCost > 0) - total.add(new ItemParamData(202, this.coinCost)); - this.totalCostItems = total; - } - return this.totalCostItems; - } - - @Override - public void onLoad() { - // Fight props - ArrayList parsed = new ArrayList(getAddProps().length); - for (FightPropData prop : getAddProps()) { - if (prop.getPropType() != null && prop.getValue() != 0f) { - prop.onLoad(); - parsed.add(prop); - } - } - this.addProps = parsed.toArray(new FightPropData[parsed.size()]); - } -} +package emu.grasscutter.data.excels; + +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.FightPropData; +import emu.grasscutter.data.common.ItemParamData; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; + +@ResourceType(name = "ProudSkillExcelConfigData.json") +public class ProudSkillData extends GameResource { + private int proudSkillId; + @Getter private int proudSkillGroupId; + @Getter private int level; + @Getter private int coinCost; + @Getter private int breakLevel; + @Getter private int proudSkillType; + @Getter private String openConfig; + @Getter private List costItems; + @Getter private List filterConds; + @Getter private List lifeEffectParams; + @Getter private FightPropData[] addProps; + @Getter private float[] paramList; + @Getter private long[] paramDescList; + @Getter private long nameTextMapHash; + @Transient private Iterable totalCostItems; + + @Override + public int getId() { + return proudSkillId; + } + + public Iterable getTotalCostItems() { + if (this.totalCostItems == null) { + ArrayList total = + (this.costItems != null) ? new ArrayList<>(this.costItems) : new ArrayList<>(1); + if (this.coinCost > 0) total.add(new ItemParamData(202, this.coinCost)); + this.totalCostItems = total; + } + return this.totalCostItems; + } + + @Override + public void onLoad() { + // Fight props + ArrayList parsed = new ArrayList(getAddProps().length); + for (FightPropData prop : getAddProps()) { + if (prop.getPropType() != null && prop.getValue() != 0f) { + prop.onLoad(); + parsed.add(prop); + } + } + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/QuestData.java b/src/main/java/emu/grasscutter/data/excels/QuestData.java index 20a10b503..010fc6b17 100644 --- a/src/main/java/emu/grasscutter/data/excels/QuestData.java +++ b/src/main/java/emu/grasscutter/data/excels/QuestData.java @@ -1,134 +1,137 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.quest.enums.LogicType; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import lombok.AccessLevel; -import lombok.Data; -import lombok.Getter; -import lombok.ToString; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@ResourceType(name = "QuestExcelConfigData.json") -@Getter -@ToString -public class QuestData extends GameResource { - private int subId; - private int mainId; - private int order; - private long descTextMapHash; - - private boolean finishParent; - private boolean isRewind; - - private LogicType acceptCondComb; - private LogicType finishCondComb; - private LogicType failCondComb; - - private List acceptCond; - private List finishCond; - private List failCond; - private List beginExec; - private List finishExec; - private List failExec; - private Guide guide; - - //ResourceLoader not happy if you remove getId() ~~ - public int getId() { - return subId; - } - - //Added getSubId() for clarity - public int getSubId() { - return subId; - } - - public int getMainId() { - return mainId; - } - - public int getOrder() { - return order; - } - - public long getDescTextMapHash() { - return descTextMapHash; - } - - public boolean finishParent() { - return finishParent; - } - - public boolean isRewind() { - return isRewind; - } - - public LogicType getAcceptCondComb() { - return acceptCondComb == null ? LogicType.LOGIC_NONE : acceptCondComb; - } - - public List getAcceptCond() { - return acceptCond; - } - - public LogicType getFinishCondComb() { - return finishCondComb == null ? LogicType.LOGIC_NONE : finishCondComb; - } - - public List getFinishCond() { - return finishCond; - } - - public LogicType getFailCondComb() { - return failCondComb == null ? LogicType.LOGIC_NONE : failCondComb; - } - - public List getFailCond() { - return failCond; - } - - public void onLoad() { - this.acceptCond = acceptCond.stream().filter(p -> p.type != null).toList(); - this.finishCond = finishCond.stream().filter(p -> p.type != null).toList(); - this.failCond = failCond.stream().filter(p -> p.type != null).toList(); - - this.beginExec = beginExec.stream().filter(p -> p.type != null).toList(); - this.finishExec = finishExec.stream().filter(p -> p.type != null).toList(); - this.failExec = failExec.stream().filter(p -> p.type != null).toList(); - } - - @Data - public static class QuestCondition { - @SerializedName("_type") - private QuestTrigger type; - @SerializedName("_param") - private int[] param; - @SerializedName("_param_str") - private String paramStr; - @SerializedName("_count") - private String count; - - } - - @Data - public static class Guide { - private String type; - private List param; - private int guideScene; - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public class QuestExecParam { - @SerializedName("_type") - QuestTrigger type; - @SerializedName("_param") - String[] param; - @SerializedName("_count") - String count; - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "QuestExcelConfigData.json") +@Getter +@ToString +public class QuestData extends GameResource { + private int subId; + private int mainId; + private int order; + private long descTextMapHash; + + private boolean finishParent; + private boolean isRewind; + + private LogicType acceptCondComb; + private LogicType finishCondComb; + private LogicType failCondComb; + + private List acceptCond; + private List finishCond; + private List failCond; + private List beginExec; + private List finishExec; + private List failExec; + private Guide guide; + + // ResourceLoader not happy if you remove getId() ~~ + public int getId() { + return subId; + } + + // Added getSubId() for clarity + public int getSubId() { + return subId; + } + + public int getMainId() { + return mainId; + } + + public int getOrder() { + return order; + } + + public long getDescTextMapHash() { + return descTextMapHash; + } + + public boolean finishParent() { + return finishParent; + } + + public boolean isRewind() { + return isRewind; + } + + public LogicType getAcceptCondComb() { + return acceptCondComb == null ? LogicType.LOGIC_NONE : acceptCondComb; + } + + public List getAcceptCond() { + return acceptCond; + } + + public LogicType getFinishCondComb() { + return finishCondComb == null ? LogicType.LOGIC_NONE : finishCondComb; + } + + public List getFinishCond() { + return finishCond; + } + + public LogicType getFailCondComb() { + return failCondComb == null ? LogicType.LOGIC_NONE : failCondComb; + } + + public List getFailCond() { + return failCond; + } + + public void onLoad() { + this.acceptCond = acceptCond.stream().filter(p -> p.type != null).toList(); + this.finishCond = finishCond.stream().filter(p -> p.type != null).toList(); + this.failCond = failCond.stream().filter(p -> p.type != null).toList(); + + this.beginExec = beginExec.stream().filter(p -> p.type != null).toList(); + this.finishExec = finishExec.stream().filter(p -> p.type != null).toList(); + this.failExec = failExec.stream().filter(p -> p.type != null).toList(); + } + + @Data + public static class QuestCondition { + @SerializedName("_type") + private QuestTrigger type; + + @SerializedName("_param") + private int[] param; + + @SerializedName("_param_str") + private String paramStr; + + @SerializedName("_count") + private String count; + } + + @Data + public static class Guide { + private String type; + private List param; + private int guideScene; + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + public class QuestExecParam { + @SerializedName("_type") + QuestTrigger type; + + @SerializedName("_param") + String[] param; + + @SerializedName("_count") + String count; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java index 7d3ce800a..65863eee3 100644 --- a/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java @@ -1,22 +1,24 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.FightProperty; -import lombok.Getter; - -@ResourceType(name = "ReliquaryAffixExcelConfigData.json") -@Getter -public class ReliquaryAffixData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - - private int depotId; - private int groupId; - @SerializedName("propType") - private FightProperty fightProp; - private float propValue; - private int weight; - private int upgradeWeight; -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.FightProperty; +import lombok.Getter; + +@ResourceType(name = "ReliquaryAffixExcelConfigData.json") +@Getter +public class ReliquaryAffixData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int depotId; + private int groupId; + + @SerializedName("propType") + private FightProperty fightProp; + + private float propValue; + private int weight; + private int upgradeWeight; +} diff --git a/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java index f5b6c90a8..e0dec94ed 100644 --- a/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java @@ -1,48 +1,45 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.FightProperty; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; -import lombok.Getter; - -import java.util.List; - -@ResourceType(name = "ReliquaryLevelExcelConfigData.json") -public class ReliquaryLevelData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private Int2FloatMap propMap; - - @Getter - private int rank; - @Getter - private int level; - @Getter - private int exp; - private List addProps; - - public float getPropValue(FightProperty prop) { - return getPropValue(prop.getId()); - } - - public float getPropValue(int id) { - return propMap.getOrDefault(id, 0f); - } - - @Override - public void onLoad() { - this.id = (rank << 8) + this.getLevel(); - this.propMap = new Int2FloatOpenHashMap(); - for (RelicLevelProperty p : addProps) { - this.propMap.put(FightProperty.getPropByName(p.getPropType()).getId(), p.getValue()); - } - } - - @Getter - public class RelicLevelProperty { - private String propType; - private float value; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.FightProperty; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import java.util.List; +import lombok.Getter; + +@ResourceType(name = "ReliquaryLevelExcelConfigData.json") +public class ReliquaryLevelData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private Int2FloatMap propMap; + + @Getter private int rank; + @Getter private int level; + @Getter private int exp; + private List addProps; + + public float getPropValue(FightProperty prop) { + return getPropValue(prop.getId()); + } + + public float getPropValue(int id) { + return propMap.getOrDefault(id, 0f); + } + + @Override + public void onLoad() { + this.id = (rank << 8) + this.getLevel(); + this.propMap = new Int2FloatOpenHashMap(); + for (RelicLevelProperty p : addProps) { + this.propMap.put(FightProperty.getPropByName(p.getPropType()).getId(), p.getValue()); + } + } + + @Getter + public class RelicLevelProperty { + private String propType; + private float value; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java index cf8a1952a..8280b1dcf 100644 --- a/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java @@ -1,19 +1,21 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.FightProperty; -import lombok.Getter; - -@ResourceType(name = "ReliquaryMainPropExcelConfigData.json") -@Getter -public class ReliquaryMainPropData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - - private int propDepotId; - @SerializedName("propType") - private FightProperty fightProp; - private int weight; -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.FightProperty; +import lombok.Getter; + +@ResourceType(name = "ReliquaryMainPropExcelConfigData.json") +@Getter +public class ReliquaryMainPropData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private int propDepotId; + + @SerializedName("propType") + private FightProperty fightProp; + + private int weight; +} diff --git a/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java b/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java index 55967d239..603d987ef 100644 --- a/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java @@ -1,32 +1,32 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "ReliquarySetExcelConfigData.json") -public class ReliquarySetData extends GameResource { - private int setId; - private int[] setNeedNum; - - @SerializedName(value = "equipAffixId", alternate = {"EquipAffixId"}) - private int equipAffixId; - - @Override - public int getId() { - return setId; - } - - public int[] getSetNeedNum() { - return setNeedNum; - } - - public int getEquipAffixId() { - return equipAffixId; - } - - @Override - public void onLoad() { - - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "ReliquarySetExcelConfigData.json") +public class ReliquarySetData extends GameResource { + private int setId; + private int[] setNeedNum; + + @SerializedName( + value = "equipAffixId", + alternate = {"EquipAffixId"}) + private int equipAffixId; + + @Override + public int getId() { + return setId; + } + + public int[] getSetNeedNum() { + return setNeedNum; + } + + public int getEquipAffixId() { + return equipAffixId; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/RewardData.java b/src/main/java/emu/grasscutter/data/excels/RewardData.java index 1b5f0083f..aa7d0255d 100644 --- a/src/main/java/emu/grasscutter/data/excels/RewardData.java +++ b/src/main/java/emu/grasscutter/data/excels/RewardData.java @@ -1,27 +1,26 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; - -import java.util.List; - -@ResourceType(name = "RewardExcelConfigData.json") -public class RewardData extends GameResource { - public int rewardId; - public List rewardItemList; - - @Override - public int getId() { - return rewardId; - } - - public List getRewardItemList() { - return rewardItemList; - } - - @Override - public void onLoad() { - rewardItemList = rewardItemList.stream().filter(i -> i.getId() > 0).toList(); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; + +@ResourceType(name = "RewardExcelConfigData.json") +public class RewardData extends GameResource { + public int rewardId; + public List rewardItemList; + + @Override + public int getId() { + return rewardId; + } + + public List getRewardItemList() { + return rewardItemList; + } + + @Override + public void onLoad() { + rewardItemList = rewardItemList.stream().filter(i -> i.getId() > 0).toList(); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java b/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java index c0dc5d39f..c86b6cc99 100644 --- a/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java +++ b/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java @@ -1,34 +1,35 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.common.ItemParamStringData; -import lombok.Getter; - -import java.util.Arrays; - -@ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH) -public class RewardPreviewData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - private ItemParamStringData[] previewItems; - private ItemParamData[] previewItemsArray; - - public ItemParamData[] getPreviewItems() { - return previewItemsArray; - } - - @Override - public void onLoad() { - if (this.previewItems != null && this.previewItems.length > 0) { - this.previewItemsArray = Arrays.stream(this.previewItems) - .filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty()) - .map(ItemParamStringData::toItemParamData) - .toArray(size -> new ItemParamData[size]); - } else { - this.previewItemsArray = new ItemParamData[0]; - } - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.common.ItemParamStringData; +import java.util.Arrays; +import lombok.Getter; + +@ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH) +public class RewardPreviewData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + private ItemParamStringData[] previewItems; + private ItemParamData[] previewItemsArray; + + public ItemParamData[] getPreviewItems() { + return previewItemsArray; + } + + @Override + public void onLoad() { + if (this.previewItems != null && this.previewItems.length > 0) { + this.previewItemsArray = + Arrays.stream(this.previewItems) + .filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty()) + .map(ItemParamStringData::toItemParamData) + .toArray(size -> new ItemParamData[size]); + } else { + this.previewItemsArray = new ItemParamData[0]; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/SceneData.java b/src/main/java/emu/grasscutter/data/excels/SceneData.java index f198248d4..8c933354b 100644 --- a/src/main/java/emu/grasscutter/data/excels/SceneData.java +++ b/src/main/java/emu/grasscutter/data/excels/SceneData.java @@ -1,17 +1,19 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.SceneType; -import lombok.Getter; - -@ResourceType(name = "SceneExcelConfigData.json") -@Getter -public class SceneData extends GameResource { - @Getter(onMethod_ = @Override) - private int id; - @SerializedName("type") - private SceneType sceneType; - private String scriptData; -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.SceneType; +import lombok.Getter; + +@ResourceType(name = "SceneExcelConfigData.json") +@Getter +public class SceneData extends GameResource { + @Getter(onMethod_ = @Override) + private int id; + + @SerializedName("type") + private SceneType sceneType; + + private String scriptData; +} diff --git a/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java b/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java index d2d035ef0..1ad87fe20 100644 --- a/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java +++ b/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java @@ -1,110 +1,112 @@ -package emu.grasscutter.data.excels; - -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.shop.ShopInfo; - -import java.util.List; - -@ResourceType(name = "ShopGoodsExcelConfigData.json") -public class ShopGoodsData extends GameResource { - private int goodsId; - private int shopType; - private int itemId; - - private int itemCount; - - private int costScoin; - private int costHcoin; - private int costMcoin; - - private List costItems; - private int minPlayerLevel; - private int maxPlayerLevel; - - private int buyLimit; - @SerializedName(value = "subTabId", alternate = {"secondarySheetId"}) - private int subTabId; - - private String refreshType; - private transient ShopInfo.ShopRefreshType refreshTypeEnum; - - private int refreshParam; - - @Override - public void onLoad() { - if (this.refreshType == null) - this.refreshTypeEnum = ShopInfo.ShopRefreshType.NONE; - else { - this.refreshTypeEnum = switch (this.refreshType) { - case "SHOP_REFRESH_DAILY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_DAILY; - case "SHOP_REFRESH_WEEKLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_WEEKLY; - case "SHOP_REFRESH_MONTHLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_MONTHLY; - default -> ShopInfo.ShopRefreshType.NONE; - }; - } - } - - @Override - public int getId() { - return getGoodsId(); - } - - public int getGoodsId() { - return goodsId; - } - - public int getShopType() { - return shopType; - } - - public int getItemId() { - return itemId; - } - - public int getItemCount() { - return itemCount; - } - - public int getCostScoin() { - return costScoin; - } - - public int getCostHcoin() { - return costHcoin; - } - - public int getCostMcoin() { - return costMcoin; - } - - public List getCostItems() { - return costItems; - } - - public int getMinPlayerLevel() { - return minPlayerLevel; - } - - public int getMaxPlayerLevel() { - return maxPlayerLevel; - } - - public int getBuyLimit() { - return buyLimit; - } - - public int getSubTabId() { - return subTabId; - } - - public ShopInfo.ShopRefreshType getRefreshType() { - return refreshTypeEnum; - } - - public int getRefreshParam() { - return refreshParam; - } -} +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.shop.ShopInfo; +import java.util.List; + +@ResourceType(name = "ShopGoodsExcelConfigData.json") +public class ShopGoodsData extends GameResource { + private int goodsId; + private int shopType; + private int itemId; + + private int itemCount; + + private int costScoin; + private int costHcoin; + private int costMcoin; + + private List costItems; + private int minPlayerLevel; + private int maxPlayerLevel; + + private int buyLimit; + + @SerializedName( + value = "subTabId", + alternate = {"secondarySheetId"}) + private int subTabId; + + private String refreshType; + private transient ShopInfo.ShopRefreshType refreshTypeEnum; + + private int refreshParam; + + @Override + public void onLoad() { + if (this.refreshType == null) this.refreshTypeEnum = ShopInfo.ShopRefreshType.NONE; + else { + this.refreshTypeEnum = + switch (this.refreshType) { + case "SHOP_REFRESH_DAILY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_DAILY; + case "SHOP_REFRESH_WEEKLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_WEEKLY; + case "SHOP_REFRESH_MONTHLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_MONTHLY; + default -> ShopInfo.ShopRefreshType.NONE; + }; + } + } + + @Override + public int getId() { + return getGoodsId(); + } + + public int getGoodsId() { + return goodsId; + } + + public int getShopType() { + return shopType; + } + + public int getItemId() { + return itemId; + } + + public int getItemCount() { + return itemCount; + } + + public int getCostScoin() { + return costScoin; + } + + public int getCostHcoin() { + return costHcoin; + } + + public int getCostMcoin() { + return costMcoin; + } + + public List getCostItems() { + return costItems; + } + + public int getMinPlayerLevel() { + return minPlayerLevel; + } + + public int getMaxPlayerLevel() { + return maxPlayerLevel; + } + + public int getBuyLimit() { + return buyLimit; + } + + public int getSubTabId() { + return subTabId; + } + + public ShopInfo.ShopRefreshType getRefreshType() { + return refreshTypeEnum; + } + + public int getRefreshParam() { + return refreshParam; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java b/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java index 0f408eb58..c6bec8c07 100644 --- a/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java @@ -1,34 +1,34 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "TowerLevelExcelConfigData.json") -public class TowerLevelData extends GameResource { - - private int levelId; - private int levelIndex; - private int levelGroupId; - private int dungeonId; - - @Override - public int getId() { - return this.getLevelId(); - } - - public int getLevelId() { - return levelId; - } - - public int getLevelGroupId() { - return levelGroupId; - } - - public int getLevelIndex() { - return levelIndex; - } - - public int getDungeonId() { - return dungeonId; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "TowerLevelExcelConfigData.json") +public class TowerLevelData extends GameResource { + + private int levelId; + private int levelIndex; + private int levelGroupId; + private int dungeonId; + + @Override + public int getId() { + return this.getLevelId(); + } + + public int getLevelId() { + return levelId; + } + + public int getLevelGroupId() { + return levelGroupId; + } + + public int getLevelIndex() { + return levelIndex; + } + + public int getDungeonId() { + return dungeonId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java b/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java index 40300ac80..4c55a7a36 100644 --- a/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java +++ b/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java @@ -1,51 +1,49 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -import java.util.List; - -@ResourceType(name = "TowerScheduleExcelConfigData.json") -public class TowerScheduleData extends GameResource { - private int scheduleId; - private List entranceFloorId; - private List schedules; - private int monthlyLevelConfigId; - - @Override - public int getId() { - return scheduleId; - } - - @Override - public void onLoad() { - super.onLoad(); - this.schedules = this.schedules.stream() - .filter(item -> item.getFloorList().size() > 0) - .toList(); - } - - public int getScheduleId() { - return scheduleId; - } - - public List getEntranceFloorId() { - return entranceFloorId; - } - - public List getSchedules() { - return schedules; - } - - public int getMonthlyLevelConfigId() { - return monthlyLevelConfigId; - } - - public static class ScheduleDetail { - private List floorList; - - public List getFloorList() { - return floorList; - } - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import java.util.List; + +@ResourceType(name = "TowerScheduleExcelConfigData.json") +public class TowerScheduleData extends GameResource { + private int scheduleId; + private List entranceFloorId; + private List schedules; + private int monthlyLevelConfigId; + + @Override + public int getId() { + return scheduleId; + } + + @Override + public void onLoad() { + super.onLoad(); + this.schedules = + this.schedules.stream().filter(item -> item.getFloorList().size() > 0).toList(); + } + + public int getScheduleId() { + return scheduleId; + } + + public List getEntranceFloorId() { + return entranceFloorId; + } + + public List getSchedules() { + return schedules; + } + + public int getMonthlyLevelConfigId() { + return monthlyLevelConfigId; + } + + public static class ScheduleDetail { + private List floorList; + + public List getFloorList() { + return floorList; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/TriggerExcelConfigData.java b/src/main/java/emu/grasscutter/data/excels/TriggerExcelConfigData.java index d0a21ef20..f6c52fd5b 100644 --- a/src/main/java/emu/grasscutter/data/excels/TriggerExcelConfigData.java +++ b/src/main/java/emu/grasscutter/data/excels/TriggerExcelConfigData.java @@ -1,15 +1,14 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import lombok.Getter; - -@ResourceType(name = "TriggerExcelConfigData.json") -@Getter -public class TriggerExcelConfigData extends GameResource { - @Getter - private int id; - private int sceneId; - private int groupId; - private String triggerName; -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import lombok.Getter; + +@ResourceType(name = "TriggerExcelConfigData.json") +@Getter +public class TriggerExcelConfigData extends GameResource { + @Getter private int id; + private int sceneId; + private int groupId; + private String triggerName; +} diff --git a/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java b/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java index 2dd64c7f2..92fe9c097 100644 --- a/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java @@ -1,32 +1,32 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.CurveInfo; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -@ResourceType(name = "WeaponCurveExcelConfigData.json") -public class WeaponCurveData extends GameResource { - private int level; - private CurveInfo[] curveInfos; - - private Map curveInfosMap; - - @Override - public int getId() { - return level; - } - - public float getMultByProp(String fightProp) { - return curveInfosMap.getOrDefault(fightProp, 1f); - } - - @Override - public void onLoad() { - this.curveInfosMap = new HashMap<>(); - Stream.of(this.curveInfos).forEach(info -> this.curveInfosMap.put(info.getType(), info.getValue())); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.CurveInfo; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +@ResourceType(name = "WeaponCurveExcelConfigData.json") +public class WeaponCurveData extends GameResource { + private int level; + private CurveInfo[] curveInfos; + + private Map curveInfosMap; + + @Override + public int getId() { + return level; + } + + public float getMultByProp(String fightProp) { + return curveInfosMap.getOrDefault(fightProp, 1f); + } + + @Override + public void onLoad() { + this.curveInfosMap = new HashMap<>(); + Stream.of(this.curveInfos) + .forEach(info -> this.curveInfosMap.put(info.getType(), info.getValue())); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java b/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java index a0ac874a7..24375d286 100644 --- a/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "WeaponLevelExcelConfigData.json") -public class WeaponLevelData extends GameResource { - private int level; - private int[] requiredExps; - - @Override - public int getId() { - return this.level; - } - - public int getLevel() { - return level; - } - - public int[] getRequiredExps() { - return requiredExps; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "WeaponLevelExcelConfigData.json") +public class WeaponLevelData extends GameResource { + private int level; + private int[] requiredExps; + + @Override + public int getId() { + return this.level; + } + + public int getLevel() { + return level; + } + + public int[] getRequiredExps() { + return requiredExps; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java b/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java index 3738875cd..ce8da7747 100644 --- a/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java @@ -1,75 +1,74 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.FightPropData; -import emu.grasscutter.data.common.ItemParamData; - -import java.util.ArrayList; - -@ResourceType(name = "WeaponPromoteExcelConfigData.json") -public class WeaponPromoteData extends GameResource { - - private int weaponPromoteId; - private int promoteLevel; - private ItemParamData[] costItems; - private int coinCost; - private FightPropData[] addProps; - private int unlockMaxLevel; - private int requiredPlayerLevel; - - @Override - public int getId() { - return (weaponPromoteId << 8) + promoteLevel; - } - - public int getWeaponPromoteId() { - return weaponPromoteId; - } - - public int getPromoteLevel() { - return promoteLevel; - } - - public ItemParamData[] getCostItems() { - return costItems; - } - - public int getCoinCost() { - return coinCost; - } - - public FightPropData[] getAddProps() { - return addProps; - } - - public int getUnlockMaxLevel() { - return unlockMaxLevel; - } - - public int getRequiredPlayerLevel() { - return requiredPlayerLevel; - } - - @Override - public void onLoad() { - // Trim item params - ArrayList trim = new ArrayList<>(getAddProps().length); - for (ItemParamData itemParam : getCostItems()) { - if (itemParam.getId() == 0) { - continue; - } - trim.add(itemParam); - } - this.costItems = trim.toArray(new ItemParamData[trim.size()]); - // Trim fight prop data - ArrayList parsed = new ArrayList<>(getAddProps().length); - for (FightPropData prop : getAddProps()) { - if (prop.getPropType() != null && prop.getValue() != 0f) { - prop.onLoad(); - parsed.add(prop); - } - } - this.addProps = parsed.toArray(new FightPropData[parsed.size()]); - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.FightPropData; +import emu.grasscutter.data.common.ItemParamData; +import java.util.ArrayList; + +@ResourceType(name = "WeaponPromoteExcelConfigData.json") +public class WeaponPromoteData extends GameResource { + + private int weaponPromoteId; + private int promoteLevel; + private ItemParamData[] costItems; + private int coinCost; + private FightPropData[] addProps; + private int unlockMaxLevel; + private int requiredPlayerLevel; + + @Override + public int getId() { + return (weaponPromoteId << 8) + promoteLevel; + } + + public int getWeaponPromoteId() { + return weaponPromoteId; + } + + public int getPromoteLevel() { + return promoteLevel; + } + + public ItemParamData[] getCostItems() { + return costItems; + } + + public int getCoinCost() { + return coinCost; + } + + public FightPropData[] getAddProps() { + return addProps; + } + + public int getUnlockMaxLevel() { + return unlockMaxLevel; + } + + public int getRequiredPlayerLevel() { + return requiredPlayerLevel; + } + + @Override + public void onLoad() { + // Trim item params + ArrayList trim = new ArrayList<>(getAddProps().length); + for (ItemParamData itemParam : getCostItems()) { + if (itemParam.getId() == 0) { + continue; + } + trim.add(itemParam); + } + this.costItems = trim.toArray(new ItemParamData[trim.size()]); + // Trim fight prop data + ArrayList parsed = new ArrayList<>(getAddProps().length); + for (FightPropData prop : getAddProps()) { + if (prop.getPropType() != null && prop.getValue() != 0f) { + prop.onLoad(); + parsed.add(prop); + } + } + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/WeatherData.java b/src/main/java/emu/grasscutter/data/excels/WeatherData.java index 7664f78ae..9f5a639b5 100644 --- a/src/main/java/emu/grasscutter/data/excels/WeatherData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeatherData.java @@ -1,37 +1,26 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.ClimateType; -import lombok.Getter; - -@ResourceType(name = "WeatherExcelConfigData.json") -public class WeatherData extends GameResource { - @Getter - private int areaID; - @Getter - private int weatherAreaId; - @Getter - private String maxHeightStr; - @Getter - private int gadgetID; - @Getter - private boolean isDefaultValid; - @Getter - private String templateName; - @Getter - private int priority; - @Getter - private String profileName; - @Getter - private ClimateType defaultClimate; - @Getter - private boolean isUseDefault; - @Getter - private int sceneID; - - @Override - public int getId() { - return this.areaID; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.ClimateType; +import lombok.Getter; + +@ResourceType(name = "WeatherExcelConfigData.json") +public class WeatherData extends GameResource { + @Getter private int areaID; + @Getter private int weatherAreaId; + @Getter private String maxHeightStr; + @Getter private int gadgetID; + @Getter private boolean isDefaultValid; + @Getter private String templateName; + @Getter private int priority; + @Getter private String profileName; + @Getter private ClimateType defaultClimate; + @Getter private boolean isUseDefault; + @Getter private int sceneID; + + @Override + public int getId() { + return this.areaID; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java b/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java index d7df67086..320a2c8ba 100644 --- a/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java +++ b/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java @@ -1,32 +1,30 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.ElementType; - -@ResourceType(name = "WorldAreaConfigData.json") -public class WorldAreaData extends GameResource { - private int ID; - private int AreaID1; - private int AreaID2; - private int SceneID; - private ElementType elementType; - - @Override - public int getId() { - return (this.AreaID2 << 16) + this.AreaID1; - } - - public int getSceneID() { - return this.SceneID; - } - - public ElementType getElementType() { - return this.elementType; - } - - @Override - public void onLoad() { - - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.ElementType; + +@ResourceType(name = "WorldAreaConfigData.json") +public class WorldAreaData extends GameResource { + private int ID; + private int AreaID1; + private int AreaID2; + private int SceneID; + private ElementType elementType; + + @Override + public int getId() { + return (this.AreaID2 << 16) + this.AreaID1; + } + + public int getSceneID() { + return this.SceneID; + } + + public ElementType getElementType() { + return this.elementType; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java b/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java index 791ba37cb..6febcad91 100644 --- a/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java @@ -1,24 +1,22 @@ -package emu.grasscutter.data.excels; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "WorldLevelExcelConfigData.json") -public class WorldLevelData extends GameResource { - private int level; - private int monsterLevel; - - @Override - public int getId() { - return this.level; - } - - public int getMonsterLevel() { - return monsterLevel; - } - - @Override - public void onLoad() { - - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "WorldLevelExcelConfigData.json") +public class WorldLevelData extends GameResource { + private int level; + private int monsterLevel; + + @Override + public int getId() { + return this.level; + } + + public int getMonsterLevel() { + return monsterLevel; + } + + @Override + public void onLoad() {} +} diff --git a/src/main/java/emu/grasscutter/database/DatabaseCounter.java b/src/main/java/emu/grasscutter/database/DatabaseCounter.java index fa18ee165..498227017 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseCounter.java +++ b/src/main/java/emu/grasscutter/database/DatabaseCounter.java @@ -1,24 +1,22 @@ -package emu.grasscutter.database; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; - -@Entity(value = "counters", useDiscriminator = false) -public class DatabaseCounter { - @Id - private String id; - private int count; - - public DatabaseCounter() { - } - - public DatabaseCounter(String id) { - this.id = id; - this.count = 10000; - } - - public int getNextId() { - int id = ++count; - return id; - } -} +package emu.grasscutter.database; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; + +@Entity(value = "counters", useDiscriminator = false) +public class DatabaseCounter { + @Id private String id; + private int count; + + public DatabaseCounter() {} + + public DatabaseCounter(String id) { + this.id = id; + this.count = 10000; + } + + public int getNextId() { + int id = ++count; + return id; + } +} diff --git a/src/main/java/emu/grasscutter/database/DatabaseHelper.java b/src/main/java/emu/grasscutter/database/DatabaseHelper.java index 5debdd744..de3cb79e8 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseHelper.java +++ b/src/main/java/emu/grasscutter/database/DatabaseHelper.java @@ -1,373 +1,452 @@ -package emu.grasscutter.database; - -import com.mongodb.client.result.DeleteResult; -import dev.morphia.query.FindOptions; -import dev.morphia.query.Sort; -import dev.morphia.query.experimental.filters.Filters; -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.achievement.Achievements; -import emu.grasscutter.game.activity.PlayerActivityData; -import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.battlepass.BattlePassManager; -import emu.grasscutter.game.friends.Friendship; -import emu.grasscutter.game.gacha.GachaRecord; -import emu.grasscutter.game.home.GameHome; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.GameMainQuest; - -import java.util.List; -import java.util.stream.Stream; - -import static com.mongodb.client.model.Filters.eq; - -public final class DatabaseHelper { - public static Account createAccount(String username) { - return createAccountWithUid(username, 0); - } - - public static Account createAccountWithUid(String username, int reservedUid) { - // Unique names only - if (DatabaseHelper.checkIfAccountExists(username)) { - return null; - } - - // Make sure there are no id collisions - if (reservedUid > 0) { - // Cannot make account with the same uid as the server console - if (reservedUid == GameConstants.SERVER_CONSOLE_UID) { - return null; - } - - if (DatabaseHelper.checkIfAccountExists(reservedUid)) { - return null; - } - - // Make sure no existing player already has this id. - if (DatabaseHelper.checkIfPlayerExists(reservedUid)) { - return null; - } - } - - // Account - Account account = new Account(); - account.setUsername(username); - account.setId(Integer.toString(DatabaseManager.getNextId(account))); - - if (reservedUid > 0) { - account.setReservedPlayerUid(reservedUid); - } - - DatabaseHelper.saveAccount(account); - return account; - } - - @Deprecated - public static Account createAccountWithPassword(String username, String password) { - // Unique names only - Account exists = DatabaseHelper.getAccountByName(username); - if (exists != null) { - return null; - } - - // Account - Account account = new Account(); - account.setId(Integer.toString(DatabaseManager.getNextId(account))); - account.setUsername(username); - account.setPassword(password); - DatabaseHelper.saveAccount(account); - return account; - } - - public static void saveAccount(Account account) { - DatabaseManager.getAccountDatastore().save(account); - } - - public static Account getAccountByName(String username) { - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("username", username)).first(); - } - - public static Account getAccountByToken(String token) { - if (token == null) return null; - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("token", token)).first(); - } - - public static Account getAccountBySessionKey(String sessionKey) { - if (sessionKey == null) return null; - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("sessionKey", sessionKey)).first(); - } - - public static Account getAccountById(String uid) { - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first(); - } - - public static Account getAccountByPlayerId(int playerId) { - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("reservedPlayerId", playerId)).first(); - } - - public static boolean checkIfAccountExists(String name) { - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("username", name)).count() > 0; - } - - public static boolean checkIfAccountExists(int reservedUid) { - return DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("reservedPlayerId", reservedUid)).count() > 0; - } - - public static synchronized void deleteAccount(Account target) { - // To delete an account, we need to also delete all the other documents in the database that reference the account. - // This should optimally be wrapped inside a transaction, to make sure an error thrown mid-way does not leave the - // database in an inconsistent state, but unfortunately Mongo only supports that when we have a replica set ... - - Player player = Grasscutter.getGameServer().getPlayerByAccountId(target.getId()); - - // Close session first - if (player != null) { - player.getSession().close(); - } else { - player = getPlayerByAccount(target); - if (player == null) return; - } - int uid = player.getUid(); - // Delete data from collections - DatabaseManager.getGameDatabase().getCollection("achievements").deleteMany(eq("uid", uid)); - DatabaseManager.getGameDatabase().getCollection("activities").deleteMany(eq("uid", uid)); - DatabaseManager.getGameDatabase().getCollection("homes").deleteMany(eq("ownerUid", uid)); - DatabaseManager.getGameDatabase().getCollection("mail").deleteMany(eq("ownerUid", uid)); - DatabaseManager.getGameDatabase().getCollection("avatars").deleteMany(eq("ownerId", uid)); - DatabaseManager.getGameDatabase().getCollection("gachas").deleteMany(eq("ownerId", uid)); - DatabaseManager.getGameDatabase().getCollection("items").deleteMany(eq("ownerId", uid)); - DatabaseManager.getGameDatabase().getCollection("quests").deleteMany(eq("ownerUid", uid)); - DatabaseManager.getGameDatabase().getCollection("battlepass").deleteMany(eq("ownerUid", uid)); - - // Delete friendships. - // Here, we need to make sure to not only delete the deleted account's friendships, - // but also all friendship entries for that account's friends. - DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("ownerId", uid)); - DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("friendId", uid)); - - // Delete the player last. - DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("id", uid)).delete(); - - // Finally, delete the account itself. - DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("id", target.getId())).delete(); - } - - public static Stream getByGameClass(Class classType) { - return DatabaseManager.getGameDatastore().find(classType).stream(); - } - - @Deprecated(forRemoval = true) - public static List getAllPlayers() { - return DatabaseManager.getGameDatastore().find(Player.class).stream().toList(); - } - - public static Player getPlayerByUid(int id) { - return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", id)).first(); - } - - @Deprecated - public static Player getPlayerByAccount(Account account) { - return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("accountId", account.getId())).first(); - } - - public static Player getPlayerByAccount(Account account, Class playerClass) { - return DatabaseManager.getGameDatastore().find(playerClass).filter(Filters.eq("accountId", account.getId())).first(); - } - - public static boolean checkIfPlayerExists(int uid) { - return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", uid)).count() > 0; - } - - public static synchronized Player generatePlayerUid(Player character, int reservedId) { - // Check if reserved id - int id; - if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { - id = reservedId; - character.setUid(id); - } else { - do { - id = DatabaseManager.getNextId(character); - } - while (checkIfPlayerExists(id)); - character.setUid(id); - } - // Save to database - DatabaseManager.getGameDatastore().save(character); - return character; - } - - public static synchronized int getNextPlayerId(int reservedId) { - // Check if reserved id - int id; - if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { - id = reservedId; - } else { - do { - id = DatabaseManager.getNextId(Player.class); - } - while (checkIfPlayerExists(id)); - } - return id; - } - - public static void savePlayer(Player character) { - DatabaseManager.getGameDatastore().save(character); - } - - public static void saveAvatar(Avatar avatar) { - DatabaseManager.getGameDatastore().save(avatar); - } - - public static List getAvatars(Player player) { - return DatabaseManager.getGameDatastore().find(Avatar.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); - } - - public static void saveItem(GameItem item) { - DatabaseManager.getGameDatastore().save(item); - } - - public static boolean deleteItem(GameItem item) { - DeleteResult result = DatabaseManager.getGameDatastore().delete(item); - return result.wasAcknowledged(); - } - - public static List getInventoryItems(Player player) { - return DatabaseManager.getGameDatastore().find(GameItem.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); - } - - public static List getFriends(Player player) { - return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); - } - - public static List getReverseFriends(Player player) { - return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("friendId", player.getUid())).stream().toList(); - } - - public static void saveFriendship(Friendship friendship) { - DatabaseManager.getGameDatastore().save(friendship); - } - - public static void deleteFriendship(Friendship friendship) { - DatabaseManager.getGameDatastore().delete(friendship); - } - - public static Friendship getReverseFriendship(Friendship friendship) { - return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.and( - Filters.eq("ownerId", friendship.getFriendId()), - Filters.eq("friendId", friendship.getOwnerId()) - )).first(); - } - - public static List getGachaRecords(int ownerId, int page, int gachaType) { - return getGachaRecords(ownerId, page, gachaType, 10); - } - - public static List getGachaRecords(int ownerId, int page, int gachaType, int pageSize) { - return DatabaseManager.getGameDatastore().find(GachaRecord.class).filter( - Filters.eq("ownerId", ownerId), - Filters.eq("gachaType", gachaType) - ).iterator(new FindOptions() - .sort(Sort.descending("transactionDate")) - .skip(pageSize * page) - .limit(pageSize) - ).toList(); - } - - public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType) { - return getGachaRecordsMaxPage(ownerId, page, gachaType, 10); - } - - public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType, int pageSize) { - long count = DatabaseManager.getGameDatastore().find(GachaRecord.class).filter( - Filters.eq("ownerId", ownerId), - Filters.eq("gachaType", gachaType) - ).count(); - return count / 10 + (count % 10 > 0 ? 1 : 0); - } - - public static void saveGachaRecord(GachaRecord gachaRecord) { - DatabaseManager.getGameDatastore().save(gachaRecord); - } - - public static List getAllMail(Player player) { - return DatabaseManager.getGameDatastore().find(Mail.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); - } - - public static void saveMail(Mail mail) { - DatabaseManager.getGameDatastore().save(mail); - } - - public static boolean deleteMail(Mail mail) { - DeleteResult result = DatabaseManager.getGameDatastore().delete(mail); - return result.wasAcknowledged(); - } - - public static List getAllQuests(Player player) { - return DatabaseManager.getGameDatastore().find(GameMainQuest.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); - } - - public static void saveQuest(GameMainQuest quest) { - DatabaseManager.getGameDatastore().save(quest); - } - - public static boolean deleteQuest(GameMainQuest quest) { - return DatabaseManager.getGameDatastore().delete(quest).wasAcknowledged(); - } - - public static GameHome getHomeByUid(int id) { - return DatabaseManager.getGameDatastore().find(GameHome.class).filter(Filters.eq("ownerUid", id)).first(); - } - - public static void saveHome(GameHome gameHome) { - DatabaseManager.getGameDatastore().save(gameHome); - } - - public static BattlePassManager loadBattlePass(Player player) { - BattlePassManager manager = DatabaseManager.getGameDatastore().find(BattlePassManager.class).filter(Filters.eq("ownerUid", player.getUid())).first(); - if (manager == null) { - manager = new BattlePassManager(player); - manager.save(); - } else { - manager.setPlayer(player); - } - return manager; - } - - public static void saveBattlePass(BattlePassManager manager) { - DatabaseManager.getGameDatastore().save(manager); - } - - public static PlayerActivityData getPlayerActivityData(int uid, int activityId) { - return DatabaseManager.getGameDatastore().find(PlayerActivityData.class) - .filter(Filters.and(Filters.eq("uid", uid), Filters.eq("activityId", activityId))) - .first(); - } - - public static void savePlayerActivityData(PlayerActivityData playerActivityData) { - DatabaseManager.getGameDatastore().save(playerActivityData); - } - - public static MusicGameBeatmap getMusicGameBeatmap(long musicShareId) { - return DatabaseManager.getGameDatastore().find(MusicGameBeatmap.class) - .filter(Filters.eq("musicShareId", musicShareId)) - .first(); - } - - public static void saveMusicGameBeatmap(MusicGameBeatmap musicGameBeatmap) { - DatabaseManager.getGameDatastore().save(musicGameBeatmap); - } - - public static Achievements getAchievementData(int uid) { - return DatabaseManager.getGameDatastore().find(Achievements.class) - .filter(Filters.and(Filters.eq("uid", uid))) - .first(); - } - - public static void saveAchievementData(Achievements achievements) { - DatabaseManager.getGameDatastore().save(achievements); - } -} +package emu.grasscutter.database; + +import static com.mongodb.client.model.Filters.eq; + +import com.mongodb.client.result.DeleteResult; +import dev.morphia.query.FindOptions; +import dev.morphia.query.Sort; +import dev.morphia.query.experimental.filters.Filters; +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.achievement.Achievements; +import emu.grasscutter.game.activity.PlayerActivityData; +import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.battlepass.BattlePassManager; +import emu.grasscutter.game.friends.Friendship; +import emu.grasscutter.game.gacha.GachaRecord; +import emu.grasscutter.game.home.GameHome; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import java.util.List; +import java.util.stream.Stream; + +public final class DatabaseHelper { + public static Account createAccount(String username) { + return createAccountWithUid(username, 0); + } + + public static Account createAccountWithUid(String username, int reservedUid) { + // Unique names only + if (DatabaseHelper.checkIfAccountExists(username)) { + return null; + } + + // Make sure there are no id collisions + if (reservedUid > 0) { + // Cannot make account with the same uid as the server console + if (reservedUid == GameConstants.SERVER_CONSOLE_UID) { + return null; + } + + if (DatabaseHelper.checkIfAccountExists(reservedUid)) { + return null; + } + + // Make sure no existing player already has this id. + if (DatabaseHelper.checkIfPlayerExists(reservedUid)) { + return null; + } + } + + // Account + Account account = new Account(); + account.setUsername(username); + account.setId(Integer.toString(DatabaseManager.getNextId(account))); + + if (reservedUid > 0) { + account.setReservedPlayerUid(reservedUid); + } + + DatabaseHelper.saveAccount(account); + return account; + } + + @Deprecated + public static Account createAccountWithPassword(String username, String password) { + // Unique names only + Account exists = DatabaseHelper.getAccountByName(username); + if (exists != null) { + return null; + } + + // Account + Account account = new Account(); + account.setId(Integer.toString(DatabaseManager.getNextId(account))); + account.setUsername(username); + account.setPassword(password); + DatabaseHelper.saveAccount(account); + return account; + } + + public static void saveAccount(Account account) { + DatabaseManager.getAccountDatastore().save(account); + } + + public static Account getAccountByName(String username) { + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("username", username)) + .first(); + } + + public static Account getAccountByToken(String token) { + if (token == null) return null; + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("token", token)) + .first(); + } + + public static Account getAccountBySessionKey(String sessionKey) { + if (sessionKey == null) return null; + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("sessionKey", sessionKey)) + .first(); + } + + public static Account getAccountById(String uid) { + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("_id", uid)) + .first(); + } + + public static Account getAccountByPlayerId(int playerId) { + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("reservedPlayerId", playerId)) + .first(); + } + + public static boolean checkIfAccountExists(String name) { + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("username", name)) + .count() + > 0; + } + + public static boolean checkIfAccountExists(int reservedUid) { + return DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("reservedPlayerId", reservedUid)) + .count() + > 0; + } + + public static synchronized void deleteAccount(Account target) { + // To delete an account, we need to also delete all the other documents in the database that + // reference the account. + // This should optimally be wrapped inside a transaction, to make sure an error thrown mid-way + // does not leave the + // database in an inconsistent state, but unfortunately Mongo only supports that when we have a + // replica set ... + + Player player = Grasscutter.getGameServer().getPlayerByAccountId(target.getId()); + + // Close session first + if (player != null) { + player.getSession().close(); + } else { + player = getPlayerByAccount(target); + if (player == null) return; + } + int uid = player.getUid(); + // Delete data from collections + DatabaseManager.getGameDatabase().getCollection("achievements").deleteMany(eq("uid", uid)); + DatabaseManager.getGameDatabase().getCollection("activities").deleteMany(eq("uid", uid)); + DatabaseManager.getGameDatabase().getCollection("homes").deleteMany(eq("ownerUid", uid)); + DatabaseManager.getGameDatabase().getCollection("mail").deleteMany(eq("ownerUid", uid)); + DatabaseManager.getGameDatabase().getCollection("avatars").deleteMany(eq("ownerId", uid)); + DatabaseManager.getGameDatabase().getCollection("gachas").deleteMany(eq("ownerId", uid)); + DatabaseManager.getGameDatabase().getCollection("items").deleteMany(eq("ownerId", uid)); + DatabaseManager.getGameDatabase().getCollection("quests").deleteMany(eq("ownerUid", uid)); + DatabaseManager.getGameDatabase().getCollection("battlepass").deleteMany(eq("ownerUid", uid)); + + // Delete friendships. + // Here, we need to make sure to not only delete the deleted account's friendships, + // but also all friendship entries for that account's friends. + DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("ownerId", uid)); + DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("friendId", uid)); + + // Delete the player last. + DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("id", uid)).delete(); + + // Finally, delete the account itself. + DatabaseManager.getAccountDatastore() + .find(Account.class) + .filter(Filters.eq("id", target.getId())) + .delete(); + } + + public static Stream getByGameClass(Class classType) { + return DatabaseManager.getGameDatastore().find(classType).stream(); + } + + @Deprecated(forRemoval = true) + public static List getAllPlayers() { + return DatabaseManager.getGameDatastore().find(Player.class).stream().toList(); + } + + public static Player getPlayerByUid(int id) { + return DatabaseManager.getGameDatastore() + .find(Player.class) + .filter(Filters.eq("_id", id)) + .first(); + } + + @Deprecated + public static Player getPlayerByAccount(Account account) { + return DatabaseManager.getGameDatastore() + .find(Player.class) + .filter(Filters.eq("accountId", account.getId())) + .first(); + } + + public static Player getPlayerByAccount(Account account, Class playerClass) { + return DatabaseManager.getGameDatastore() + .find(playerClass) + .filter(Filters.eq("accountId", account.getId())) + .first(); + } + + public static boolean checkIfPlayerExists(int uid) { + return DatabaseManager.getGameDatastore() + .find(Player.class) + .filter(Filters.eq("_id", uid)) + .count() + > 0; + } + + public static synchronized Player generatePlayerUid(Player character, int reservedId) { + // Check if reserved id + int id; + if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { + id = reservedId; + character.setUid(id); + } else { + do { + id = DatabaseManager.getNextId(character); + } while (checkIfPlayerExists(id)); + character.setUid(id); + } + // Save to database + DatabaseManager.getGameDatastore().save(character); + return character; + } + + public static synchronized int getNextPlayerId(int reservedId) { + // Check if reserved id + int id; + if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { + id = reservedId; + } else { + do { + id = DatabaseManager.getNextId(Player.class); + } while (checkIfPlayerExists(id)); + } + return id; + } + + public static void savePlayer(Player character) { + DatabaseManager.getGameDatastore().save(character); + } + + public static void saveAvatar(Avatar avatar) { + DatabaseManager.getGameDatastore().save(avatar); + } + + public static List getAvatars(Player player) { + return DatabaseManager.getGameDatastore() + .find(Avatar.class) + .filter(Filters.eq("ownerId", player.getUid())) + .stream() + .toList(); + } + + public static void saveItem(GameItem item) { + DatabaseManager.getGameDatastore().save(item); + } + + public static boolean deleteItem(GameItem item) { + DeleteResult result = DatabaseManager.getGameDatastore().delete(item); + return result.wasAcknowledged(); + } + + public static List getInventoryItems(Player player) { + return DatabaseManager.getGameDatastore() + .find(GameItem.class) + .filter(Filters.eq("ownerId", player.getUid())) + .stream() + .toList(); + } + + public static List getFriends(Player player) { + return DatabaseManager.getGameDatastore() + .find(Friendship.class) + .filter(Filters.eq("ownerId", player.getUid())) + .stream() + .toList(); + } + + public static List getReverseFriends(Player player) { + return DatabaseManager.getGameDatastore() + .find(Friendship.class) + .filter(Filters.eq("friendId", player.getUid())) + .stream() + .toList(); + } + + public static void saveFriendship(Friendship friendship) { + DatabaseManager.getGameDatastore().save(friendship); + } + + public static void deleteFriendship(Friendship friendship) { + DatabaseManager.getGameDatastore().delete(friendship); + } + + public static Friendship getReverseFriendship(Friendship friendship) { + return DatabaseManager.getGameDatastore() + .find(Friendship.class) + .filter( + Filters.and( + Filters.eq("ownerId", friendship.getFriendId()), + Filters.eq("friendId", friendship.getOwnerId()))) + .first(); + } + + public static List getGachaRecords(int ownerId, int page, int gachaType) { + return getGachaRecords(ownerId, page, gachaType, 10); + } + + public static List getGachaRecords( + int ownerId, int page, int gachaType, int pageSize) { + return DatabaseManager.getGameDatastore() + .find(GachaRecord.class) + .filter(Filters.eq("ownerId", ownerId), Filters.eq("gachaType", gachaType)) + .iterator( + new FindOptions() + .sort(Sort.descending("transactionDate")) + .skip(pageSize * page) + .limit(pageSize)) + .toList(); + } + + public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType) { + return getGachaRecordsMaxPage(ownerId, page, gachaType, 10); + } + + public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType, int pageSize) { + long count = + DatabaseManager.getGameDatastore() + .find(GachaRecord.class) + .filter(Filters.eq("ownerId", ownerId), Filters.eq("gachaType", gachaType)) + .count(); + return count / 10 + (count % 10 > 0 ? 1 : 0); + } + + public static void saveGachaRecord(GachaRecord gachaRecord) { + DatabaseManager.getGameDatastore().save(gachaRecord); + } + + public static List getAllMail(Player player) { + return DatabaseManager.getGameDatastore() + .find(Mail.class) + .filter(Filters.eq("ownerUid", player.getUid())) + .stream() + .toList(); + } + + public static void saveMail(Mail mail) { + DatabaseManager.getGameDatastore().save(mail); + } + + public static boolean deleteMail(Mail mail) { + DeleteResult result = DatabaseManager.getGameDatastore().delete(mail); + return result.wasAcknowledged(); + } + + public static List getAllQuests(Player player) { + return DatabaseManager.getGameDatastore() + .find(GameMainQuest.class) + .filter(Filters.eq("ownerUid", player.getUid())) + .stream() + .toList(); + } + + public static void saveQuest(GameMainQuest quest) { + DatabaseManager.getGameDatastore().save(quest); + } + + public static boolean deleteQuest(GameMainQuest quest) { + return DatabaseManager.getGameDatastore().delete(quest).wasAcknowledged(); + } + + public static GameHome getHomeByUid(int id) { + return DatabaseManager.getGameDatastore() + .find(GameHome.class) + .filter(Filters.eq("ownerUid", id)) + .first(); + } + + public static void saveHome(GameHome gameHome) { + DatabaseManager.getGameDatastore().save(gameHome); + } + + public static BattlePassManager loadBattlePass(Player player) { + BattlePassManager manager = + DatabaseManager.getGameDatastore() + .find(BattlePassManager.class) + .filter(Filters.eq("ownerUid", player.getUid())) + .first(); + if (manager == null) { + manager = new BattlePassManager(player); + manager.save(); + } else { + manager.setPlayer(player); + } + return manager; + } + + public static void saveBattlePass(BattlePassManager manager) { + DatabaseManager.getGameDatastore().save(manager); + } + + public static PlayerActivityData getPlayerActivityData(int uid, int activityId) { + return DatabaseManager.getGameDatastore() + .find(PlayerActivityData.class) + .filter(Filters.and(Filters.eq("uid", uid), Filters.eq("activityId", activityId))) + .first(); + } + + public static void savePlayerActivityData(PlayerActivityData playerActivityData) { + DatabaseManager.getGameDatastore().save(playerActivityData); + } + + public static MusicGameBeatmap getMusicGameBeatmap(long musicShareId) { + return DatabaseManager.getGameDatastore() + .find(MusicGameBeatmap.class) + .filter(Filters.eq("musicShareId", musicShareId)) + .first(); + } + + public static void saveMusicGameBeatmap(MusicGameBeatmap musicGameBeatmap) { + DatabaseManager.getGameDatastore().save(musicGameBeatmap); + } + + public static Achievements getAchievementData(int uid) { + return DatabaseManager.getGameDatastore() + .find(Achievements.class) + .filter(Filters.and(Filters.eq("uid", uid))) + .first(); + } + + public static void saveAchievementData(Achievements achievements) { + DatabaseManager.getGameDatastore().save(achievements); + } +} diff --git a/src/main/java/emu/grasscutter/database/DatabaseManager.java b/src/main/java/emu/grasscutter/database/DatabaseManager.java index 9ccbe00fc..39c6e0994 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseManager.java +++ b/src/main/java/emu/grasscutter/database/DatabaseManager.java @@ -1,119 +1,126 @@ -package emu.grasscutter.database; - -import com.mongodb.MongoCommandException; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.MongoIterable; -import dev.morphia.Datastore; -import dev.morphia.Morphia; -import dev.morphia.annotations.Entity; -import dev.morphia.mapping.Mapper; -import dev.morphia.mapping.MapperOptions; -import dev.morphia.query.experimental.filters.Filters; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.game.Account; -import org.reflections.Reflections; - -import static emu.grasscutter.config.Configuration.DATABASE; -import static emu.grasscutter.config.Configuration.SERVER; - -public final class DatabaseManager { - private static Datastore gameDatastore; - private static Datastore dispatchDatastore; - - public static Datastore getGameDatastore() { - return gameDatastore; - } - - public static MongoDatabase getGameDatabase() { - return getGameDatastore().getDatabase(); - } - - // Yes. I very dislike this method. However, this will be good for now. - // TODO: Add dispatch routes for player account management - public static Datastore getAccountDatastore() { - if (SERVER.runMode == ServerRunMode.GAME_ONLY) { - return dispatchDatastore; - } else { - return gameDatastore; - } - } - - public static void initialize() { - // Initialize - MongoClient gameMongoClient = MongoClients.create(DATABASE.game.connectionUri); - - // Set mapper options. - MapperOptions mapperOptions = MapperOptions.builder() - .storeEmpties(true).storeNulls(false).build(); - - // Create data store. - gameDatastore = Morphia.createDatastore(gameMongoClient, DATABASE.game.collection, mapperOptions); - - // Map classes. - Class[] entities = new Reflections(Grasscutter.class.getPackageName()) - .getTypesAnnotatedWith(Entity.class) - .stream() - .filter(cls -> { - Entity e = cls.getAnnotation(Entity.class); - return e != null && !e.value().equals(Mapper.IGNORED_FIELDNAME); - }) - .toArray(Class[]::new); - - gameDatastore.getMapper().map(entities); - - // Ensure indexes for the game datastore - ensureIndexes(gameDatastore); - - if (SERVER.runMode == ServerRunMode.GAME_ONLY) { - MongoClient dispatchMongoClient = MongoClients.create(DATABASE.server.connectionUri); - - dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, DATABASE.server.collection, mapperOptions); - dispatchDatastore.getMapper().map(new Class[]{DatabaseCounter.class, Account.class}); - - // Ensure indexes for dispatch datastore - ensureIndexes(dispatchDatastore); - } - } - - /** - * Ensures the database indexes exist and rebuilds them if there is an error with them - * - * @param datastore The datastore to ensure indexes on - */ - private static void ensureIndexes(Datastore datastore) { - try { - datastore.ensureIndexes(); - } catch (MongoCommandException e) { - Grasscutter.getLogger().info("Mongo index error: ", e); - // Duplicate index error - if (e.getCode() == 85) { - // Drop all indexes and re add them - MongoIterable collections = datastore.getDatabase().listCollectionNames(); - for (String name : collections) { - datastore.getDatabase().getCollection(name).dropIndexes(); - } - // Add back indexes - datastore.ensureIndexes(); - } - } - } - - public static synchronized int getNextId(Class c) { - DatabaseCounter counter = getGameDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first(); - if (counter == null) { - counter = new DatabaseCounter(c.getSimpleName()); - } - try { - return counter.getNextId(); - } finally { - getGameDatastore().save(counter); - } - } - - public static synchronized int getNextId(Object o) { - return getNextId(o.getClass()); - } -} +package emu.grasscutter.database; + +import static emu.grasscutter.config.Configuration.DATABASE; +import static emu.grasscutter.config.Configuration.SERVER; + +import com.mongodb.MongoCommandException; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.MongoIterable; +import dev.morphia.Datastore; +import dev.morphia.Morphia; +import dev.morphia.annotations.Entity; +import dev.morphia.mapping.Mapper; +import dev.morphia.mapping.MapperOptions; +import dev.morphia.query.experimental.filters.Filters; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.game.Account; +import org.reflections.Reflections; + +public final class DatabaseManager { + private static Datastore gameDatastore; + private static Datastore dispatchDatastore; + + public static Datastore getGameDatastore() { + return gameDatastore; + } + + public static MongoDatabase getGameDatabase() { + return getGameDatastore().getDatabase(); + } + + // Yes. I very dislike this method. However, this will be good for now. + // TODO: Add dispatch routes for player account management + public static Datastore getAccountDatastore() { + if (SERVER.runMode == ServerRunMode.GAME_ONLY) { + return dispatchDatastore; + } else { + return gameDatastore; + } + } + + public static void initialize() { + // Initialize + MongoClient gameMongoClient = MongoClients.create(DATABASE.game.connectionUri); + + // Set mapper options. + MapperOptions mapperOptions = + MapperOptions.builder().storeEmpties(true).storeNulls(false).build(); + + // Create data store. + gameDatastore = + Morphia.createDatastore(gameMongoClient, DATABASE.game.collection, mapperOptions); + + // Map classes. + Class[] entities = + new Reflections(Grasscutter.class.getPackageName()) + .getTypesAnnotatedWith(Entity.class).stream() + .filter( + cls -> { + Entity e = cls.getAnnotation(Entity.class); + return e != null && !e.value().equals(Mapper.IGNORED_FIELDNAME); + }) + .toArray(Class[]::new); + + gameDatastore.getMapper().map(entities); + + // Ensure indexes for the game datastore + ensureIndexes(gameDatastore); + + if (SERVER.runMode == ServerRunMode.GAME_ONLY) { + MongoClient dispatchMongoClient = MongoClients.create(DATABASE.server.connectionUri); + + dispatchDatastore = + Morphia.createDatastore(dispatchMongoClient, DATABASE.server.collection, mapperOptions); + dispatchDatastore.getMapper().map(new Class[] {DatabaseCounter.class, Account.class}); + + // Ensure indexes for dispatch datastore + ensureIndexes(dispatchDatastore); + } + } + + /** + * Ensures the database indexes exist and rebuilds them if there is an error with them + * + * @param datastore The datastore to ensure indexes on + */ + private static void ensureIndexes(Datastore datastore) { + try { + datastore.ensureIndexes(); + } catch (MongoCommandException e) { + Grasscutter.getLogger().info("Mongo index error: ", e); + // Duplicate index error + if (e.getCode() == 85) { + // Drop all indexes and re add them + MongoIterable collections = datastore.getDatabase().listCollectionNames(); + for (String name : collections) { + datastore.getDatabase().getCollection(name).dropIndexes(); + } + // Add back indexes + datastore.ensureIndexes(); + } + } + } + + public static synchronized int getNextId(Class c) { + DatabaseCounter counter = + getGameDatastore() + .find(DatabaseCounter.class) + .filter(Filters.eq("_id", c.getSimpleName())) + .first(); + if (counter == null) { + counter = new DatabaseCounter(c.getSimpleName()); + } + try { + return counter.getNextId(); + } finally { + getGameDatastore().save(counter); + } + } + + public static synchronized int getNextId(Object o) { + return getNextId(o.getClass()); + } +} diff --git a/src/main/java/emu/grasscutter/game/Account.java b/src/main/java/emu/grasscutter/game/Account.java index 25987452e..6e4cd6f33 100644 --- a/src/main/java/emu/grasscutter/game/Account.java +++ b/src/main/java/emu/grasscutter/game/Account.java @@ -1,242 +1,244 @@ -package emu.grasscutter.game; - -import dev.morphia.annotations.*; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.Utils; -import org.bson.Document; - -import java.util.*; -import java.util.stream.Stream; - -import static emu.grasscutter.config.Configuration.ACCOUNT; -import static emu.grasscutter.config.Configuration.LANGUAGE; - -@Entity(value = "accounts", useDiscriminator = false) -public class Account { - @Id - private String id; - - @Indexed(options = @IndexOptions(unique = true)) - @Collation(locale = "simple", caseLevel = true) - private String username; - private String password; // Unused for now - - private int reservedPlayerId; - private String email; - - private String token; - private String sessionKey; // Session token for dispatch server - private final List permissions; - private Locale locale; - - private String banReason; - private int banEndTime; - private int banStartTime; - private boolean isBanned; - - @Deprecated - public Account() { - this.permissions = new ArrayList<>(); - this.locale = LANGUAGE; - } - - public static boolean permissionMatchesWildcard(String wildcard, String[] permissionParts) { - String[] wildcardParts = wildcard.split("\\."); - if (permissionParts.length < wildcardParts.length) { // A longer wildcard can never match a shorter permission - return false; - } - for (int i = 0; i < wildcardParts.length; i++) { - switch (wildcardParts[i]) { - case "**": // Recursing match - return true; - case "*": // Match only one layer - if (i >= (permissionParts.length - 1)) { - return true; - } - break; - default: // This layer isn't a wildcard, it needs to match exactly - if (!wildcardParts[i].equals(permissionParts[i])) { - return false; - } - } - } - // At this point the wildcard will have matched every layer, but if it is shorter then the permission then this is not a match at this point (no **). - return (wildcardParts.length == permissionParts.length); - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public int getReservedPlayerUid() { - return this.reservedPlayerId; - } - - public void setReservedPlayerUid(int playerId) { - this.reservedPlayerId = playerId; - } - - public String getEmail() { - if (email != null && !email.isEmpty()) { - return email; - } else { - return ""; - } - } - - public void setEmail(String email) { - this.email = email; - } - - public String getSessionKey() { - return this.sessionKey; - } - - public String generateSessionKey() { - this.sessionKey = Utils.bytesToHex(Crypto.createSessionKey(32)); - this.save(); - return this.sessionKey; - } - - public Locale getLocale() { - return locale; - } - - public void setLocale(Locale locale) { - this.locale = locale; - } - - public String getBanReason() { - return banReason; - } - - public void setBanReason(String banReason) { - this.banReason = banReason; - } - - public int getBanEndTime() { - return banEndTime; - } - - public void setBanEndTime(int banEndTime) { - this.banEndTime = banEndTime; - } - - public int getBanStartTime() { - return banStartTime; - } - - public void setBanStartTime(int banStartTime) { - this.banStartTime = banStartTime; - } - - public boolean isBanned() { - if (banEndTime > 0 && banEndTime < System.currentTimeMillis() / 1000) { - this.isBanned = false; - this.banEndTime = 0; - this.banStartTime = 0; - this.banReason = null; - save(); - } - - return isBanned; - } - - public void setBanned(boolean isBanned) { - this.isBanned = isBanned; - } - - /** - * The collection of a player's permissions. - */ - public List getPermissions() { - return this.permissions; - } - - public boolean addPermission(String permission) { - if (this.permissions.contains(permission)) return false; - this.permissions.add(permission); - return true; - } - - public boolean hasPermission(String permission) { - if (permission.isEmpty()) return true; - if (this.permissions.contains("*") && this.permissions.size() == 1) return true; - - // Add default permissions if it doesn't exist - List permissions = Stream.of(this.permissions, Arrays.asList(ACCOUNT.defaultPermissions)) - .flatMap(Collection::stream) - .distinct().toList(); - - if (permissions.contains(permission)) return true; - - String[] permissionParts = permission.split("\\."); - for (String p : permissions) { - if (p.startsWith("-") && permissionMatchesWildcard(p.substring(1), permissionParts)) return false; - if (permissionMatchesWildcard(p, permissionParts)) return true; - } - - return permissions.contains("*"); - } - - public boolean removePermission(String permission) { - return this.permissions.remove(permission); - } - - public void clearPermission() { - this.permissions.clear(); - } - - // TODO make unique - public String generateLoginToken() { - this.token = Utils.bytesToHex(Crypto.createSessionKey(32)); - this.save(); - return this.token; - } - - public void save() { - DatabaseHelper.saveAccount(this); - } - - @PreLoad - public void onLoad(Document document) { - // Grant the superuser permissions to accounts created before the permissions update - if (!document.containsKey("permissions")) { - this.addPermission("*"); - } - - // Set account default language as server default language - if (!document.containsKey("locale")) { - this.locale = LANGUAGE; - } - } -} +package emu.grasscutter.game; + +import static emu.grasscutter.config.Configuration.ACCOUNT; +import static emu.grasscutter.config.Configuration.LANGUAGE; + +import dev.morphia.annotations.*; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.utils.Crypto; +import emu.grasscutter.utils.Utils; +import java.util.*; +import java.util.stream.Stream; +import org.bson.Document; + +@Entity(value = "accounts", useDiscriminator = false) +public class Account { + @Id private String id; + + @Indexed(options = @IndexOptions(unique = true)) + @Collation(locale = "simple", caseLevel = true) + private String username; + + private String password; // Unused for now + + private int reservedPlayerId; + private String email; + + private String token; + private String sessionKey; // Session token for dispatch server + private final List permissions; + private Locale locale; + + private String banReason; + private int banEndTime; + private int banStartTime; + private boolean isBanned; + + @Deprecated + public Account() { + this.permissions = new ArrayList<>(); + this.locale = LANGUAGE; + } + + public static boolean permissionMatchesWildcard(String wildcard, String[] permissionParts) { + String[] wildcardParts = wildcard.split("\\."); + if (permissionParts.length + < wildcardParts.length) { // A longer wildcard can never match a shorter permission + return false; + } + for (int i = 0; i < wildcardParts.length; i++) { + switch (wildcardParts[i]) { + case "**": // Recursing match + return true; + case "*": // Match only one layer + if (i >= (permissionParts.length - 1)) { + return true; + } + break; + default: // This layer isn't a wildcard, it needs to match exactly + if (!wildcardParts[i].equals(permissionParts[i])) { + return false; + } + } + } + // At this point the wildcard will have matched every layer, but if it is shorter then the + // permission then this is not a match at this point (no **). + return (wildcardParts.length == permissionParts.length); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public int getReservedPlayerUid() { + return this.reservedPlayerId; + } + + public void setReservedPlayerUid(int playerId) { + this.reservedPlayerId = playerId; + } + + public String getEmail() { + if (email != null && !email.isEmpty()) { + return email; + } else { + return ""; + } + } + + public void setEmail(String email) { + this.email = email; + } + + public String getSessionKey() { + return this.sessionKey; + } + + public String generateSessionKey() { + this.sessionKey = Utils.bytesToHex(Crypto.createSessionKey(32)); + this.save(); + return this.sessionKey; + } + + public Locale getLocale() { + return locale; + } + + public void setLocale(Locale locale) { + this.locale = locale; + } + + public String getBanReason() { + return banReason; + } + + public void setBanReason(String banReason) { + this.banReason = banReason; + } + + public int getBanEndTime() { + return banEndTime; + } + + public void setBanEndTime(int banEndTime) { + this.banEndTime = banEndTime; + } + + public int getBanStartTime() { + return banStartTime; + } + + public void setBanStartTime(int banStartTime) { + this.banStartTime = banStartTime; + } + + public boolean isBanned() { + if (banEndTime > 0 && banEndTime < System.currentTimeMillis() / 1000) { + this.isBanned = false; + this.banEndTime = 0; + this.banStartTime = 0; + this.banReason = null; + save(); + } + + return isBanned; + } + + public void setBanned(boolean isBanned) { + this.isBanned = isBanned; + } + + /** The collection of a player's permissions. */ + public List getPermissions() { + return this.permissions; + } + + public boolean addPermission(String permission) { + if (this.permissions.contains(permission)) return false; + this.permissions.add(permission); + return true; + } + + public boolean hasPermission(String permission) { + if (permission.isEmpty()) return true; + if (this.permissions.contains("*") && this.permissions.size() == 1) return true; + + // Add default permissions if it doesn't exist + List permissions = + Stream.of(this.permissions, Arrays.asList(ACCOUNT.defaultPermissions)) + .flatMap(Collection::stream) + .distinct() + .toList(); + + if (permissions.contains(permission)) return true; + + String[] permissionParts = permission.split("\\."); + for (String p : permissions) { + if (p.startsWith("-") && permissionMatchesWildcard(p.substring(1), permissionParts)) + return false; + if (permissionMatchesWildcard(p, permissionParts)) return true; + } + + return permissions.contains("*"); + } + + public boolean removePermission(String permission) { + return this.permissions.remove(permission); + } + + public void clearPermission() { + this.permissions.clear(); + } + + // TODO make unique + public String generateLoginToken() { + this.token = Utils.bytesToHex(Crypto.createSessionKey(32)); + this.save(); + return this.token; + } + + public void save() { + DatabaseHelper.saveAccount(this); + } + + @PreLoad + public void onLoad(Document document) { + // Grant the superuser permissions to accounts created before the permissions update + if (!document.containsKey("permissions")) { + this.addPermission("*"); + } + + // Set account default language as server default language + if (!document.containsKey("locale")) { + this.locale = LANGUAGE; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/CoopRequest.java b/src/main/java/emu/grasscutter/game/CoopRequest.java index f1caf0f8b..69bbb1cc8 100644 --- a/src/main/java/emu/grasscutter/game/CoopRequest.java +++ b/src/main/java/emu/grasscutter/game/CoopRequest.java @@ -1,31 +1,31 @@ -package emu.grasscutter.game; - -import emu.grasscutter.game.player.Player; - -public class CoopRequest { - private final Player requester; - private final long requestTime; - private final long expireTime; - - public CoopRequest(Player requester) { - this.requester = requester; - this.requestTime = System.currentTimeMillis(); - this.expireTime = this.requestTime + 10000; - } - - public Player getRequester() { - return requester; - } - - public long getRequestTime() { - return requestTime; - } - - public long getExpireTime() { - return expireTime; - } - - public boolean isExpired() { - return System.currentTimeMillis() > getExpireTime(); - } -} +package emu.grasscutter.game; + +import emu.grasscutter.game.player.Player; + +public class CoopRequest { + private final Player requester; + private final long requestTime; + private final long expireTime; + + public CoopRequest(Player requester) { + this.requester = requester; + this.requestTime = System.currentTimeMillis(); + this.expireTime = this.requestTime + 10000; + } + + public Player getRequester() { + return requester; + } + + public long getRequestTime() { + return requestTime; + } + + public long getExpireTime() { + return expireTime; + } + + public boolean isExpired() { + return System.currentTimeMillis() > getExpireTime(); + } +} diff --git a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java index 2232bd8d8..570a00095 100644 --- a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java +++ b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java @@ -1,222 +1,228 @@ -package emu.grasscutter.game.ability; - -import com.google.protobuf.InvalidProtocolBufferException; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; -import emu.grasscutter.data.binout.AbilityModifierEntry; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.entity.gadget.GadgetGatherObject; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.AbilityInvokeEntryHeadOuterClass.AbilityInvokeEntryHead; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange; -import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap; -import emu.grasscutter.net.proto.AbilityMixinCostStaminaOuterClass.AbilityMixinCostStamina; -import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry; -import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction; -import lombok.Getter; - -public final class AbilityManager extends BasePlayerManager { - HealAbilityManager healAbilityManager; - - @Getter - private boolean abilityInvulnerable = false; - - public AbilityManager(Player player) { - super(player); - this.healAbilityManager = new HealAbilityManager(player); - } - - public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception { - this.healAbilityManager.healHandler(invoke); - - //Grasscutter.getLogger().info(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray())); - switch (invoke.getArgumentType()) { - case ABILITY_INVOKE_ARGUMENT_META_OVERRIDE_PARAM -> this.handleOverrideParam(invoke); - case ABILITY_INVOKE_ARGUMENT_META_REINIT_OVERRIDEMAP -> this.handleReinitOverrideMap(invoke); - case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE -> this.handleModifierChange(invoke); - case ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA -> this.handleMixinCostStamina(invoke); - case ABILITY_INVOKE_ARGUMENT_ACTION_GENERATE_ELEM_BALL -> this.handleGenerateElemBall(invoke); - default -> { - } - } - } - - /** - * Invoked when a player starts a skill. - * - * @param player The player who started the skill. - * @param skillId The skill ID. - * @param casterId The caster ID. - */ - public void onSkillStart(Player player, int skillId, int casterId) { - // Check if the player matches this player. - if (player.getUid() != this.player.getUid()) { - return; - } - - // Check if the caster matches the player. - if (player.getTeamManager().getCurrentAvatarEntity().getId() != casterId) { - return; - } - - var skillData = GameData.getAvatarSkillDataMap().get(skillId); - if (skillData == null) { - return; - } - - // Check if the skill is an elemental burst. - if (skillData.getCostElemVal() <= 0) { - return; - } - - // Set the player as invulnerable. - this.abilityInvulnerable = true; - } - - /** - * Invoked when a player ends a skill. - * - * @param player The player who started the skill. - */ - public void onSkillEnd(Player player) { - // Check if the player matches this player. - if (player.getUid() != this.player.getUid()) { - return; - } - - // Check if the player is invulnerable. - if (!this.abilityInvulnerable) { - return; - } - - // Set the player as not invulnerable. - this.abilityInvulnerable = false; - } - - private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception { - GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId()); - - if (entity == null) { - return; - } - - AbilityScalarValueEntry entry = AbilityScalarValueEntry.parseFrom(invoke.getAbilityData()); - - entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); - } - - private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception { - GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId()); - - if (entity == null) { - return; - } - - AbilityMetaReInitOverrideMap map = AbilityMetaReInitOverrideMap.parseFrom(invoke.getAbilityData()); - - for (AbilityScalarValueEntry entry : map.getOverrideMapList()) { - entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); - } - } - - private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception { - // Sanity checks - GameEntity target = this.player.getScene().getEntityById(invoke.getEntityId()); - if (target == null) { - return; - } - - AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData()); - if (data == null) { - return; - } - - // Destroying rocks - if (target instanceof EntityGadget targetGadget && targetGadget.getContent() instanceof GadgetGatherObject gatherObject) { - if (data.getAction() == ModifierAction.MODIFIER_ACTION_REMOVED) { - gatherObject.dropItems(this.getPlayer()); - return; - } - } - - // Sanity checks - AbilityInvokeEntryHead head = invoke.getHead(); - if (head == null) { - return; - } - - GameEntity sourceEntity = this.player.getScene().getEntityById(data.getApplyEntityId()); - if (sourceEntity == null) { - return; - } - - // This is not how it works but we will keep it for now since healing abilities dont work properly anyways - if (data.getAction() == ModifierAction.MODIFIER_ACTION_ADDED && data.getParentAbilityName() != null) { - // Handle add modifier here - String modifierString = data.getParentAbilityName().getStr(); - AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); - - if (modifier != null && modifier.getOnAdded().size() > 0) { - for (AbilityModifierAction action : modifier.getOnAdded()) { - this.invokeAction(action, target, sourceEntity); - } - } - - // Add to meta modifier list - target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString); - } else if (data.getAction() == ModifierAction.MODIFIER_ACTION_REMOVED) { - // Handle remove modifier - String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId()); - - if (modifierString != null) { - // Get modifier and call on remove event - AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); - - if (modifier != null && modifier.getOnRemoved().size() > 0) { - for (AbilityModifierAction action : modifier.getOnRemoved()) { - this.invokeAction(action, target, sourceEntity); - } - } - - // Remove from meta modifiers - target.getMetaModifiers().remove(head.getInstancedModifierId()); - } - } - } - - private void handleMixinCostStamina(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { - AbilityMixinCostStamina costStamina = AbilityMixinCostStamina.parseFrom((invoke.getAbilityData())); - this.getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim()); - } - - private void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { - this.player.getEnergyManager().handleGenerateElemBall(invoke); - } - - private void invokeAction(AbilityModifierAction action, GameEntity target, GameEntity sourceEntity) { - switch (action.type) { - case HealHP -> { - } - case LoseHP -> { - if (action.amountByTargetCurrentHPRatio == null) { - return; - } - - float damageAmount = action.amount.get(); - - // if (action.amount.isDynamic && action.amount.dynamicKey != null) { - // damageAmount = sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f); - // } - - if (damageAmount > 0) { - target.damage(damageAmount); - } - } - default -> { - } - } - } -} +package emu.grasscutter.game.ability; + +import com.google.protobuf.InvalidProtocolBufferException; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.data.binout.AbilityModifierEntry; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.entity.gadget.GadgetGatherObject; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.AbilityInvokeEntryHeadOuterClass.AbilityInvokeEntryHead; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange; +import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap; +import emu.grasscutter.net.proto.AbilityMixinCostStaminaOuterClass.AbilityMixinCostStamina; +import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry; +import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction; +import lombok.Getter; + +public final class AbilityManager extends BasePlayerManager { + HealAbilityManager healAbilityManager; + + @Getter private boolean abilityInvulnerable = false; + + public AbilityManager(Player player) { + super(player); + this.healAbilityManager = new HealAbilityManager(player); + } + + public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception { + this.healAbilityManager.healHandler(invoke); + + // Grasscutter.getLogger().info(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + // + "): " + Utils.bytesToHex(invoke.toByteArray())); + switch (invoke.getArgumentType()) { + case ABILITY_INVOKE_ARGUMENT_META_OVERRIDE_PARAM -> this.handleOverrideParam(invoke); + case ABILITY_INVOKE_ARGUMENT_META_REINIT_OVERRIDEMAP -> this.handleReinitOverrideMap(invoke); + case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE -> this.handleModifierChange(invoke); + case ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA -> this.handleMixinCostStamina(invoke); + case ABILITY_INVOKE_ARGUMENT_ACTION_GENERATE_ELEM_BALL -> this.handleGenerateElemBall(invoke); + default -> {} + } + } + + /** + * Invoked when a player starts a skill. + * + * @param player The player who started the skill. + * @param skillId The skill ID. + * @param casterId The caster ID. + */ + public void onSkillStart(Player player, int skillId, int casterId) { + // Check if the player matches this player. + if (player.getUid() != this.player.getUid()) { + return; + } + + // Check if the caster matches the player. + if (player.getTeamManager().getCurrentAvatarEntity().getId() != casterId) { + return; + } + + var skillData = GameData.getAvatarSkillDataMap().get(skillId); + if (skillData == null) { + return; + } + + // Check if the skill is an elemental burst. + if (skillData.getCostElemVal() <= 0) { + return; + } + + // Set the player as invulnerable. + this.abilityInvulnerable = true; + } + + /** + * Invoked when a player ends a skill. + * + * @param player The player who started the skill. + */ + public void onSkillEnd(Player player) { + // Check if the player matches this player. + if (player.getUid() != this.player.getUid()) { + return; + } + + // Check if the player is invulnerable. + if (!this.abilityInvulnerable) { + return; + } + + // Set the player as not invulnerable. + this.abilityInvulnerable = false; + } + + private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception { + GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId()); + + if (entity == null) { + return; + } + + AbilityScalarValueEntry entry = AbilityScalarValueEntry.parseFrom(invoke.getAbilityData()); + + entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); + } + + private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception { + GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId()); + + if (entity == null) { + return; + } + + AbilityMetaReInitOverrideMap map = + AbilityMetaReInitOverrideMap.parseFrom(invoke.getAbilityData()); + + for (AbilityScalarValueEntry entry : map.getOverrideMapList()) { + entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); + } + } + + private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception { + // Sanity checks + GameEntity target = this.player.getScene().getEntityById(invoke.getEntityId()); + if (target == null) { + return; + } + + AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData()); + if (data == null) { + return; + } + + // Destroying rocks + if (target instanceof EntityGadget targetGadget + && targetGadget.getContent() instanceof GadgetGatherObject gatherObject) { + if (data.getAction() == ModifierAction.MODIFIER_ACTION_REMOVED) { + gatherObject.dropItems(this.getPlayer()); + return; + } + } + + // Sanity checks + AbilityInvokeEntryHead head = invoke.getHead(); + if (head == null) { + return; + } + + GameEntity sourceEntity = this.player.getScene().getEntityById(data.getApplyEntityId()); + if (sourceEntity == null) { + return; + } + + // This is not how it works but we will keep it for now since healing abilities dont work + // properly anyways + if (data.getAction() == ModifierAction.MODIFIER_ACTION_ADDED + && data.getParentAbilityName() != null) { + // Handle add modifier here + String modifierString = data.getParentAbilityName().getStr(); + AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); + + if (modifier != null && modifier.getOnAdded().size() > 0) { + for (AbilityModifierAction action : modifier.getOnAdded()) { + this.invokeAction(action, target, sourceEntity); + } + } + + // Add to meta modifier list + target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString); + } else if (data.getAction() == ModifierAction.MODIFIER_ACTION_REMOVED) { + // Handle remove modifier + String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId()); + + if (modifierString != null) { + // Get modifier and call on remove event + AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); + + if (modifier != null && modifier.getOnRemoved().size() > 0) { + for (AbilityModifierAction action : modifier.getOnRemoved()) { + this.invokeAction(action, target, sourceEntity); + } + } + + // Remove from meta modifiers + target.getMetaModifiers().remove(head.getInstancedModifierId()); + } + } + } + + private void handleMixinCostStamina(AbilityInvokeEntry invoke) + throws InvalidProtocolBufferException { + AbilityMixinCostStamina costStamina = + AbilityMixinCostStamina.parseFrom((invoke.getAbilityData())); + this.getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim()); + } + + private void handleGenerateElemBall(AbilityInvokeEntry invoke) + throws InvalidProtocolBufferException { + this.player.getEnergyManager().handleGenerateElemBall(invoke); + } + + private void invokeAction( + AbilityModifierAction action, GameEntity target, GameEntity sourceEntity) { + switch (action.type) { + case HealHP -> {} + case LoseHP -> { + if (action.amountByTargetCurrentHPRatio == null) { + return; + } + + float damageAmount = action.amount.get(); + + // if (action.amount.isDynamic && action.amount.dynamicKey != null) { + // damageAmount = + // sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f); + // } + + if (damageAmount > 0) { + target.damage(damageAmount); + } + } + default -> {} + } + } +} diff --git a/src/main/java/emu/grasscutter/game/ability/HealAbilityManager.java b/src/main/java/emu/grasscutter/game/ability/HealAbilityManager.java index de6b50b90..6db6b3995 100644 --- a/src/main/java/emu/grasscutter/game/ability/HealAbilityManager.java +++ b/src/main/java/emu/grasscutter/game/ability/HealAbilityManager.java @@ -1,185 +1,214 @@ -package emu.grasscutter.game.ability; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class HealAbilityManager { - ArrayList healDataAvatarList; - private final Player player; - - public HealAbilityManager(Player player) { - this.player = player; - healDataAvatarList = new ArrayList(); - healDataAvatarList.add(new HealDataAvatar(10000054, "Kokomi", 0).addHealData("E", "ElementalArt_Heal_MaxHP_Base_Percentage", "ElementalArt_Heal_Base_Amount", false).addHealData("Q", "Avatar_Kokomi_ElementalBurst_Heal", 0.0172f, 212f, false)); - healDataAvatarList.add(new HealDataAvatar(10000003, "Qin", 1).addHealData("Q", "Heal", "BurstHealConst", true)); - healDataAvatarList.add(new HealDataAvatar(10000034, "Noel", 2).addHealData("E", "OnAttack_HealthRate", 0.452f, 282f, true)); - healDataAvatarList.add(new HealDataAvatar(10000032, "Bennett", 0).addHealData("Q", "HealMaxHpRatio", "HealConst", false)); - healDataAvatarList.add(new HealDataAvatar(10000039, "Diona", 0).addHealData("Q", "HealHPRatio", "HealHP_Const", false)); - healDataAvatarList.add(new HealDataAvatar(10000053, "Sayu", 1).addHealData("Q", "Constellation_6_Damage", "Heal_BaseAmount", true).addHealData("Q", "Heal_AttackRatio", "Constellation_6_Heal", true)); - healDataAvatarList.add(new HealDataAvatar(10000014, "Barbara", 0).addHealData("E", "HealHPOnAdded", "HealHPOnAdded_Const", true).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true).addHealData("Q", "Avatar_Barbara_IdolHeal", 0.374f, 4660f, true)); - healDataAvatarList.add(new HealDataAvatar(10000065, "Shinobu", 0).addHealData("E", "ElementalArt_Heal_MaxHP_Percentage", 0.064f, 795f, false)); - healDataAvatarList.add(new HealDataAvatar(10000035, "Qiqi", 1).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true).addHealData("E", "ElementalArt_HealHp_Ratio", "ElementalArt_HealHp_Const", true).addHealData("Q", "Avatar_Qiqi_ElementalBurst_ApplyModifier", 0.0191f, 1588f, false)); - healDataAvatarList.add(new HealDataAvatar(10000046, "Hutao", 0).addHealData("Q", "Avatar_Hutao_VermilionBite_BakeMesh", 0.1166f, 0f, false)); - } - - public Player getPlayer() { - return this.player; - } - - public void healHandler(AbilityInvokeEntry invoke) throws Exception { - AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData()); - - if (data == null) { - return; - } - - GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId()); - - String modifierString = ""; - if (data.getParentAbilityName() != null) - modifierString = data.getParentAbilityName().getStr(); - - if (sourceEntity != null) - checkAndHeal(sourceEntity, modifierString); - } - - public void checkAndHeal(GameEntity sourceEntity, String modifierString) { - int fightPropertyType = 0; - float healAmount = 0; - float ratio = 0, base = 0; - float maxHP, curHP, curAttack, curDefense; - Map map = sourceEntity.getMetaOverrideMap(); - - for (int i = 0; i < healDataAvatarList.size(); i++) { - HealDataAvatar healDataAvatar = healDataAvatarList.get(i); - if (modifierString.contains(healDataAvatar.avatarName)) { - fightPropertyType = healDataAvatar.fightPropertyType; - ArrayList healDataList = healDataAvatar.healDataList; - - for (int j = 0; j < healDataList.size(); j++) { - HealData healData = healDataList.get(j); - if (map.containsKey(healData.sRatio) || modifierString.equals(healData.sRatio)) { - if (healData.isString) { - ratio = map.get(healData.sRatio); - base = map.get(healData.sBase); - } else { - ratio = healData.fRatio; - base = healData.fBase; - } - } - - List activeTeam = player.getTeamManager().getActiveTeam(); - List needHealAvatars = new ArrayList(); - int currentIndex = player.getTeamManager().getCurrentCharacterIndex(); - EntityAvatar currentAvatar = activeTeam.get(currentIndex); - if (healData.healAll) { - needHealAvatars = activeTeam; - } else { - needHealAvatars.add(currentAvatar); - } - - EntityAvatar healActionAvatar = null; - for (int k = 0; k < activeTeam.size(); k++) { - EntityAvatar avatar = activeTeam.get(k); - int avatarId = avatar.getAvatar().getAvatarId(); - if (avatarId == healDataAvatar.avatarId) { - healActionAvatar = avatar; - break; - } - } - - if (healActionAvatar != null) { - maxHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - curHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - curAttack = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK); - curDefense = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE); - - //Special case for Hu Tao: - if (healDataAvatar.avatarName.equals("Hutao") && curHP <= maxHP * 0.5 && ratio != 0) { - ratio = 0.1555f; - } - - switch (fightPropertyType) { - case 0: - healAmount = ratio * maxHP + base; - break; - case 1: - healAmount = ratio * curAttack + base; - break; - case 2: - healAmount = ratio * curDefense + base; - break; - } - } - - for (int k = 0; k < needHealAvatars.size(); k++) { - EntityAvatar avatar = needHealAvatars.get(k); - avatar.heal(healAmount); - } - } - break; - } - } - } - - private class HealData { - public boolean isString = true; - public String abilityType = ""; //"E" or "Q" - public String sRatio = ""; - public String sBase = ""; - public float fRatio = 0; - public float fBase = 0; - public boolean healAll = false; - - public HealData(String _abilityType, String _sRatio, String _sBase, boolean _healAll) { - abilityType = _abilityType; - isString = true; - sRatio = _sRatio; - sBase = _sBase; - healAll = _healAll; - } - - public HealData(String _abilityType, String _sRatio, float _fRatio, float _fBase, boolean _healAll) { - abilityType = _abilityType; - isString = false; - sRatio = _sRatio; - fRatio = _fRatio; - fBase = _fBase; - healAll = _healAll; - } - } - - private class HealDataAvatar { - public int avatarId = 0; - public String avatarName = ""; - public int fightPropertyType = 0; //0: maxHP, 1: curAttack, 2: curDefense - public ArrayList healDataList; - - public HealDataAvatar(int _avatarId, String _avatarName, int _fightPropertyType) { - avatarId = _avatarId; - avatarName = _avatarName; - fightPropertyType = _fightPropertyType; - healDataList = new ArrayList(); - } - - public HealDataAvatar addHealData(String abilityType, String sRatio, String sBase, boolean healAll) { - HealData healData = new HealData(abilityType, sRatio, sBase, healAll); - healDataList.add(healData); - return this; - } - - public HealDataAvatar addHealData(String abilityType, String sRatio, float fRatio, float fBase, boolean healAll) { - HealData healData = new HealData(abilityType, sRatio, fRatio, fBase, healAll); - healDataList.add(healData); - return this; - } - } -} +package emu.grasscutter.game.ability; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HealAbilityManager { + ArrayList healDataAvatarList; + private final Player player; + + public HealAbilityManager(Player player) { + this.player = player; + healDataAvatarList = new ArrayList(); + healDataAvatarList.add( + new HealDataAvatar(10000054, "Kokomi", 0) + .addHealData( + "E", + "ElementalArt_Heal_MaxHP_Base_Percentage", + "ElementalArt_Heal_Base_Amount", + false) + .addHealData("Q", "Avatar_Kokomi_ElementalBurst_Heal", 0.0172f, 212f, false)); + healDataAvatarList.add( + new HealDataAvatar(10000003, "Qin", 1).addHealData("Q", "Heal", "BurstHealConst", true)); + healDataAvatarList.add( + new HealDataAvatar(10000034, "Noel", 2) + .addHealData("E", "OnAttack_HealthRate", 0.452f, 282f, true)); + healDataAvatarList.add( + new HealDataAvatar(10000032, "Bennett", 0) + .addHealData("Q", "HealMaxHpRatio", "HealConst", false)); + healDataAvatarList.add( + new HealDataAvatar(10000039, "Diona", 0) + .addHealData("Q", "HealHPRatio", "HealHP_Const", false)); + healDataAvatarList.add( + new HealDataAvatar(10000053, "Sayu", 1) + .addHealData("Q", "Constellation_6_Damage", "Heal_BaseAmount", true) + .addHealData("Q", "Heal_AttackRatio", "Constellation_6_Heal", true)); + healDataAvatarList.add( + new HealDataAvatar(10000014, "Barbara", 0) + .addHealData("E", "HealHPOnAdded", "HealHPOnAdded_Const", true) + .addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true) + .addHealData("Q", "Avatar_Barbara_IdolHeal", 0.374f, 4660f, true)); + healDataAvatarList.add( + new HealDataAvatar(10000065, "Shinobu", 0) + .addHealData("E", "ElementalArt_Heal_MaxHP_Percentage", 0.064f, 795f, false)); + healDataAvatarList.add( + new HealDataAvatar(10000035, "Qiqi", 1) + .addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true) + .addHealData("E", "ElementalArt_HealHp_Ratio", "ElementalArt_HealHp_Const", true) + .addHealData("Q", "Avatar_Qiqi_ElementalBurst_ApplyModifier", 0.0191f, 1588f, false)); + healDataAvatarList.add( + new HealDataAvatar(10000046, "Hutao", 0) + .addHealData("Q", "Avatar_Hutao_VermilionBite_BakeMesh", 0.1166f, 0f, false)); + } + + public Player getPlayer() { + return this.player; + } + + public void healHandler(AbilityInvokeEntry invoke) throws Exception { + AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData()); + + if (data == null) { + return; + } + + GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId()); + + String modifierString = ""; + if (data.getParentAbilityName() != null) modifierString = data.getParentAbilityName().getStr(); + + if (sourceEntity != null) checkAndHeal(sourceEntity, modifierString); + } + + public void checkAndHeal(GameEntity sourceEntity, String modifierString) { + int fightPropertyType = 0; + float healAmount = 0; + float ratio = 0, base = 0; + float maxHP, curHP, curAttack, curDefense; + Map map = sourceEntity.getMetaOverrideMap(); + + for (int i = 0; i < healDataAvatarList.size(); i++) { + HealDataAvatar healDataAvatar = healDataAvatarList.get(i); + if (modifierString.contains(healDataAvatar.avatarName)) { + fightPropertyType = healDataAvatar.fightPropertyType; + ArrayList healDataList = healDataAvatar.healDataList; + + for (int j = 0; j < healDataList.size(); j++) { + HealData healData = healDataList.get(j); + if (map.containsKey(healData.sRatio) || modifierString.equals(healData.sRatio)) { + if (healData.isString) { + ratio = map.get(healData.sRatio); + base = map.get(healData.sBase); + } else { + ratio = healData.fRatio; + base = healData.fBase; + } + } + + List activeTeam = player.getTeamManager().getActiveTeam(); + List needHealAvatars = new ArrayList(); + int currentIndex = player.getTeamManager().getCurrentCharacterIndex(); + EntityAvatar currentAvatar = activeTeam.get(currentIndex); + if (healData.healAll) { + needHealAvatars = activeTeam; + } else { + needHealAvatars.add(currentAvatar); + } + + EntityAvatar healActionAvatar = null; + for (int k = 0; k < activeTeam.size(); k++) { + EntityAvatar avatar = activeTeam.get(k); + int avatarId = avatar.getAvatar().getAvatarId(); + if (avatarId == healDataAvatar.avatarId) { + healActionAvatar = avatar; + break; + } + } + + if (healActionAvatar != null) { + maxHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + curHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + curAttack = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK); + curDefense = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE); + + // Special case for Hu Tao: + if (healDataAvatar.avatarName.equals("Hutao") && curHP <= maxHP * 0.5 && ratio != 0) { + ratio = 0.1555f; + } + + switch (fightPropertyType) { + case 0: + healAmount = ratio * maxHP + base; + break; + case 1: + healAmount = ratio * curAttack + base; + break; + case 2: + healAmount = ratio * curDefense + base; + break; + } + } + + for (int k = 0; k < needHealAvatars.size(); k++) { + EntityAvatar avatar = needHealAvatars.get(k); + avatar.heal(healAmount); + } + } + break; + } + } + } + + private class HealData { + public boolean isString = true; + public String abilityType = ""; // "E" or "Q" + public String sRatio = ""; + public String sBase = ""; + public float fRatio = 0; + public float fBase = 0; + public boolean healAll = false; + + public HealData(String _abilityType, String _sRatio, String _sBase, boolean _healAll) { + abilityType = _abilityType; + isString = true; + sRatio = _sRatio; + sBase = _sBase; + healAll = _healAll; + } + + public HealData( + String _abilityType, String _sRatio, float _fRatio, float _fBase, boolean _healAll) { + abilityType = _abilityType; + isString = false; + sRatio = _sRatio; + fRatio = _fRatio; + fBase = _fBase; + healAll = _healAll; + } + } + + private class HealDataAvatar { + public int avatarId = 0; + public String avatarName = ""; + public int fightPropertyType = 0; // 0: maxHP, 1: curAttack, 2: curDefense + public ArrayList healDataList; + + public HealDataAvatar(int _avatarId, String _avatarName, int _fightPropertyType) { + avatarId = _avatarId; + avatarName = _avatarName; + fightPropertyType = _fightPropertyType; + healDataList = new ArrayList(); + } + + public HealDataAvatar addHealData( + String abilityType, String sRatio, String sBase, boolean healAll) { + HealData healData = new HealData(abilityType, sRatio, sBase, healAll); + healDataList.add(healData); + return this; + } + + public HealDataAvatar addHealData( + String abilityType, String sRatio, float fRatio, float fBase, boolean healAll) { + HealData healData = new HealData(abilityType, sRatio, fRatio, fBase, healAll); + healDataList.add(healData); + return this; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/achievement/Achievement.java b/src/main/java/emu/grasscutter/game/achievement/Achievement.java index a0c872d1f..dac91e063 100644 --- a/src/main/java/emu/grasscutter/game/achievement/Achievement.java +++ b/src/main/java/emu/grasscutter/game/achievement/Achievement.java @@ -1,38 +1,40 @@ -package emu.grasscutter.game.achievement; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.AchievementOuterClass; -import emu.grasscutter.net.proto.StatusOuterClass; -import lombok.Getter; -import lombok.Setter; - -@Entity -@Getter -public class Achievement { - @Setter - private StatusOuterClass.Status status; - private final int id; - private final int totalProgress; - @Setter - private int curProgress; - @Setter - private int finishTimestampSec; - - public Achievement(StatusOuterClass.Status status, int id, int totalProgress, int curProgress, int finishTimestampSec) { - this.status = status; - this.id = id; - this.totalProgress = totalProgress; - this.curProgress = curProgress; - this.finishTimestampSec = finishTimestampSec; - } - - public AchievementOuterClass.Achievement toProto() { - return AchievementOuterClass.Achievement.newBuilder() - .setStatus(this.getStatus()) - .setId(this.getId()) - .setTotalProgress(this.getTotalProgress()) - .setCurProgress(this.getCurProgress()) - .setFinishTimestamp(this.getFinishTimestampSec()) - .build(); - } -} +package emu.grasscutter.game.achievement; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.AchievementOuterClass; +import emu.grasscutter.net.proto.StatusOuterClass; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +public class Achievement { + @Setter private StatusOuterClass.Status status; + private final int id; + private final int totalProgress; + @Setter private int curProgress; + @Setter private int finishTimestampSec; + + public Achievement( + StatusOuterClass.Status status, + int id, + int totalProgress, + int curProgress, + int finishTimestampSec) { + this.status = status; + this.id = id; + this.totalProgress = totalProgress; + this.curProgress = curProgress; + this.finishTimestampSec = finishTimestampSec; + } + + public AchievementOuterClass.Achievement toProto() { + return AchievementOuterClass.Achievement.newBuilder() + .setStatus(this.getStatus()) + .setId(this.getId()) + .setTotalProgress(this.getTotalProgress()) + .setCurProgress(this.getCurProgress()) + .setFinishTimestamp(this.getFinishTimestampSec()) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/achievement/AchievementControlReturns.java b/src/main/java/emu/grasscutter/game/achievement/AchievementControlReturns.java index fecbb7c77..63e79aa92 100644 --- a/src/main/java/emu/grasscutter/game/achievement/AchievementControlReturns.java +++ b/src/main/java/emu/grasscutter/game/achievement/AchievementControlReturns.java @@ -1,48 +1,47 @@ -package emu.grasscutter.game.achievement; - -import lombok.Getter; - -@Getter -public class AchievementControlReturns { - private final Return ret; - private final int changedAchievementStatusNum; - - private AchievementControlReturns(Return ret) { - this(ret, 0); - } - - private AchievementControlReturns(Return ret, int changedAchievementStatusNum) { - this.ret = ret; - this.changedAchievementStatusNum = changedAchievementStatusNum; - } - - public static AchievementControlReturns success(int changedAchievementStatusNum) { - return new AchievementControlReturns(Return.SUCCESS, changedAchievementStatusNum); - } - - public static AchievementControlReturns achievementNotFound() { - return new AchievementControlReturns(Return.ACHIEVEMENT_NOT_FOUND); - } - - public static AchievementControlReturns alreadyAchieved() { - return new AchievementControlReturns(Return.ALREADY_ACHIEVED); - } - - public static AchievementControlReturns notYetAchieved() { - return new AchievementControlReturns(Return.NOT_YET_ACHIEVED); - } - - public enum Return { - SUCCESS("commands.achievement.success."), - ACHIEVEMENT_NOT_FOUND("commands.achievement.fail.achievement_not_found"), - ALREADY_ACHIEVED("commands.achievement.fail.already_achieved"), - NOT_YET_ACHIEVED("commands.achievement.fail.not_yet_achieved"); - - @Getter - private final String key; - - Return(String key) { - this.key = key; - } - } -} +package emu.grasscutter.game.achievement; + +import lombok.Getter; + +@Getter +public class AchievementControlReturns { + private final Return ret; + private final int changedAchievementStatusNum; + + private AchievementControlReturns(Return ret) { + this(ret, 0); + } + + private AchievementControlReturns(Return ret, int changedAchievementStatusNum) { + this.ret = ret; + this.changedAchievementStatusNum = changedAchievementStatusNum; + } + + public static AchievementControlReturns success(int changedAchievementStatusNum) { + return new AchievementControlReturns(Return.SUCCESS, changedAchievementStatusNum); + } + + public static AchievementControlReturns achievementNotFound() { + return new AchievementControlReturns(Return.ACHIEVEMENT_NOT_FOUND); + } + + public static AchievementControlReturns alreadyAchieved() { + return new AchievementControlReturns(Return.ALREADY_ACHIEVED); + } + + public static AchievementControlReturns notYetAchieved() { + return new AchievementControlReturns(Return.NOT_YET_ACHIEVED); + } + + public enum Return { + SUCCESS("commands.achievement.success."), + ACHIEVEMENT_NOT_FOUND("commands.achievement.fail.achievement_not_found"), + ALREADY_ACHIEVED("commands.achievement.fail.already_achieved"), + NOT_YET_ACHIEVED("commands.achievement.fail.not_yet_achieved"); + + @Getter private final String key; + + Return(String key) { + this.key = key; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/achievement/Achievements.java b/src/main/java/emu/grasscutter/game/achievement/Achievements.java index 49bf93a80..f11c6ac5d 100644 --- a/src/main/java/emu/grasscutter/game/achievement/Achievements.java +++ b/src/main/java/emu/grasscutter/game/achievement/Achievements.java @@ -1,293 +1,323 @@ -package emu.grasscutter.game.achievement; - -import com.github.davidmoten.guavamini.Lists; -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Transient; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AchievementData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.StatusOuterClass; -import emu.grasscutter.server.packet.send.PacketAchievementAllDataNotify; -import emu.grasscutter.server.packet.send.PacketAchievementUpdateNotify; -import emu.grasscutter.server.packet.send.PacketTakeAchievementGoalRewardRsp; -import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardRsp; -import lombok.Builder; -import lombok.Data; -import lombok.Getter; -import org.bson.types.ObjectId; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.IntSupplier; - -@Entity("achievements") -@Data -@Builder(builderMethodName = "of") -public class Achievements { - private static final IntSupplier currentTimeSecs = () -> (int) (System.currentTimeMillis() / 1000L); - private static final Achievement INVALID = new Achievement(StatusOuterClass.Status.STATUS_INVALID, -1, 0, 0, 0); - @Id - private ObjectId id; - private int uid; - @Transient - private Player player; - private Map achievementList; - @Getter - private int finishedAchievementNum; - private List takenGoalRewardIdList; - - public static Achievements getByPlayer(Player player) { - var achievements = player.getAchievements() == null ? DatabaseHelper.getAchievementData(player.getUid()) : player.getAchievements(); - if (achievements == null) { - achievements = create(player.getUid()); - } - return achievements; - } - - public static Achievements create(int uid) { - var newAchievement = Achievements.of() - .uid(uid) - .achievementList(init()) - .finishedAchievementNum(0) - .takenGoalRewardIdList(Lists.newArrayList()) - .build(); - newAchievement.save(); - return newAchievement; - } - - private static Map init() { - Map map = new HashMap<>(); - GameData.getAchievementDataMap().values().stream() - .filter(AchievementData::isUsed) - .forEach(a -> { - map.put(a.getId(), new Achievement(StatusOuterClass.Status.STATUS_UNFINISHED, a.getId(), a.getProgress(), 0, 0)); - }); - return map; - } - - public AchievementControlReturns grant(int achievementId) { - var a = this.getAchievement(achievementId); - - if (a == null || this.isFinished(achievementId)) { - return a == null ? AchievementControlReturns.achievementNotFound() : AchievementControlReturns.alreadyAchieved(); - } - - return this.progress(achievementId, a.getTotalProgress()); - } - - public AchievementControlReturns revoke(int achievementId) { - var a = this.getAchievement(achievementId); - - if (a == null || !this.isFinished(achievementId)) { - return a == null ? AchievementControlReturns.achievementNotFound() : AchievementControlReturns.notYetAchieved(); - } - - return this.progress(achievementId, 0); - } - - public AchievementControlReturns progress(int achievementId, int progress) { - var a = this.getAchievement(achievementId); - if (a == null) { - return AchievementControlReturns.achievementNotFound(); - } - - a.setCurProgress(progress); - return AchievementControlReturns.success(this.notifyOtherAchievements(a)); - } - - private int notifyOtherAchievements(Achievement a) { - var changedNum = new AtomicInteger(); - - changedNum.addAndGet(this.update(a) ? 1 : 0); - - GameData.getAchievementDataMap().get(a.getId()) - .getExcludedGroupAchievementIdList().stream() - .map(this::getAchievement) - .filter(Objects::nonNull) - .forEach(other -> { - other.setCurProgress(a.getCurProgress()); - changedNum.addAndGet(this.update(other) ? 1 : 0); - }); - - this.computeFinishedAchievementNum(); - this.save(); - this.sendUpdatePacket(a); - return changedNum.intValue(); - } - - private boolean update(Achievement a) { - if (a.getStatus() == StatusOuterClass.Status.STATUS_UNFINISHED && a.getCurProgress() >= a.getTotalProgress()) { - a.setStatus(StatusOuterClass.Status.STATUS_FINISHED); - a.setFinishTimestampSec(currentTimeSecs.getAsInt()); - return true; - } else if (this.isFinished(a.getId()) && a.getCurProgress() < a.getTotalProgress()) { - a.setStatus(StatusOuterClass.Status.STATUS_UNFINISHED); - a.setFinishTimestampSec(0); - return true; - } - - return false; - } - - private void computeFinishedAchievementNum() { - this.finishedAchievementNum = GameData.getAchievementDataMap().values().stream() - .filter(a -> this.isFinished(a.getId())) - .mapToInt(value -> 1) - .sum(); - } - - private void sendUpdatePacket(Achievement achievement) { - List achievements = Lists.newArrayList(achievement); - achievements.addAll(GameData.getAchievementDataMap().get(achievement.getId()) - .getExcludedGroupAchievementIdList() - .stream().map(this::getAchievement) - .filter(Objects::nonNull) - .toList() - ); - - this.sendUpdatePacket(achievements); - } - - private void sendUpdatePacket(List achievement) { - if (this.isPacketSendable()) { - this.player.sendPacket(new PacketAchievementUpdateNotify(achievement)); - } - } - - @Nullable - public Achievement getAchievement(int achievementId) { - if (this.isInvalid(achievementId)) { - return null; - } - - return this.getAchievementList().computeIfAbsent(achievementId, id -> { - return new Achievement(StatusOuterClass.Status.STATUS_UNFINISHED, id, GameData.getAchievementDataMap().get(id.intValue()).getProgress(), 0, 0); - }); - } - - public boolean isInvalid(int achievementId) { - var data = GameData.getAchievementDataMap().get(achievementId); - return data == null || data.isDisuse(); - } - - public StatusOuterClass.Status getStatus(int achievementId) { - return this.getAchievementList().getOrDefault(achievementId, INVALID).getStatus(); - } - - public boolean isFinished(int achievementId) { - var status = this.getStatus(achievementId); - return status == StatusOuterClass.Status.STATUS_FINISHED || status == StatusOuterClass.Status.STATUS_REWARD_TAKEN; - } - - public void takeReward(List ids) { - List rewards = Lists.newArrayList(); - - for (int i : ids) { - var target = GameData.getAchievementDataMap().get(i); - if (target == null) { - Grasscutter.getLogger().warn("null returned while taking reward!"); - return; - } - - if (this.isRewardTaken(i)) { - this.player.sendPacket(new PacketTakeAchievementRewardRsp()); - return; - } - - var data = GameData.getRewardDataMap().get(target.getFinishRewardId()); - if (data == null) { - Grasscutter.getLogger().warn("null returned while getting reward data!"); - continue; - } - - data.getRewardItemList().forEach(itemParamData -> { - var itemData = GameData.getItemDataMap().get(itemParamData.getId()); - if (itemData == null) { - Grasscutter.getLogger().warn("itemData == null!"); - return; - } - - rewards.add(new GameItem(itemData, itemParamData.getCount())); - }); - - var a = this.getAchievement(i); - a.setStatus(StatusOuterClass.Status.STATUS_REWARD_TAKEN); - this.save(); - this.sendUpdatePacket(a); - } - - this.player.getInventory().addItems(rewards, ActionReason.AchievementReward); - this.player.sendPacket(new PacketTakeAchievementRewardRsp(ids, rewards.stream().map(GameItem::toItemParam).toList())); - } - - public void takeGoalReward(List ids) { - List rewards = Lists.newArrayList(); - - for (int i : ids) { - if (this.takenGoalRewardIdList.contains(i)) { - this.player.sendPacket(new PacketTakeAchievementGoalRewardRsp()); - } - - var goalData = GameData.getAchievementGoalDataMap().get(i); - if (goalData == null) { - Grasscutter.getLogger().warn("null returned while getting goal reward data!"); - continue; - } - - var data = GameData.getRewardDataMap().get(goalData.getFinishRewardId()); - if (data == null) { - Grasscutter.getLogger().warn("null returned while getting reward data!"); - continue; - } - - data.getRewardItemList().forEach(itemParamData -> { - var itemData = GameData.getItemDataMap().get(itemParamData.getId()); - if (itemData == null) { - Grasscutter.getLogger().warn("itemData == null!"); - return; - } - - rewards.add(new GameItem(itemData, itemParamData.getCount())); - }); - - this.takenGoalRewardIdList.add(i); - this.save(); - } - - this.player.getInventory().addItems(rewards, ActionReason.AchievementGoalReward); - this.player.sendPacket(new PacketTakeAchievementGoalRewardRsp(ids, rewards.stream().map(GameItem::toItemParam).toList())); - } - - public boolean isRewardTaken(int achievementId) { - return this.getStatus(achievementId) == StatusOuterClass.Status.STATUS_REWARD_TAKEN; - } - - public boolean isRewardLeft(int achievementId) { - return this.getStatus(achievementId) == StatusOuterClass.Status.STATUS_FINISHED; - } - - private boolean isPacketSendable() { - return this.player != null; - } - - public void save() { - DatabaseHelper.saveAchievementData(this); - } - - public void onLogin(Player player) { - if (this.player == null) { - this.player = player; - } - - this.player.sendPacket(new PacketAchievementAllDataNotify(this.player)); - } -} +package emu.grasscutter.game.achievement; + +import com.github.davidmoten.guavamini.Lists; +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AchievementData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.StatusOuterClass; +import emu.grasscutter.server.packet.send.PacketAchievementAllDataNotify; +import emu.grasscutter.server.packet.send.PacketAchievementUpdateNotify; +import emu.grasscutter.server.packet.send.PacketTakeAchievementGoalRewardRsp; +import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardRsp; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.IntSupplier; +import javax.annotation.Nullable; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import org.bson.types.ObjectId; + +@Entity("achievements") +@Data +@Builder(builderMethodName = "of") +public class Achievements { + private static final IntSupplier currentTimeSecs = + () -> (int) (System.currentTimeMillis() / 1000L); + private static final Achievement INVALID = + new Achievement(StatusOuterClass.Status.STATUS_INVALID, -1, 0, 0, 0); + @Id private ObjectId id; + private int uid; + @Transient private Player player; + private Map achievementList; + @Getter private int finishedAchievementNum; + private List takenGoalRewardIdList; + + public static Achievements getByPlayer(Player player) { + var achievements = + player.getAchievements() == null + ? DatabaseHelper.getAchievementData(player.getUid()) + : player.getAchievements(); + if (achievements == null) { + achievements = create(player.getUid()); + } + return achievements; + } + + public static Achievements create(int uid) { + var newAchievement = + Achievements.of() + .uid(uid) + .achievementList(init()) + .finishedAchievementNum(0) + .takenGoalRewardIdList(Lists.newArrayList()) + .build(); + newAchievement.save(); + return newAchievement; + } + + private static Map init() { + Map map = new HashMap<>(); + GameData.getAchievementDataMap().values().stream() + .filter(AchievementData::isUsed) + .forEach( + a -> { + map.put( + a.getId(), + new Achievement( + StatusOuterClass.Status.STATUS_UNFINISHED, a.getId(), a.getProgress(), 0, 0)); + }); + return map; + } + + public AchievementControlReturns grant(int achievementId) { + var a = this.getAchievement(achievementId); + + if (a == null || this.isFinished(achievementId)) { + return a == null + ? AchievementControlReturns.achievementNotFound() + : AchievementControlReturns.alreadyAchieved(); + } + + return this.progress(achievementId, a.getTotalProgress()); + } + + public AchievementControlReturns revoke(int achievementId) { + var a = this.getAchievement(achievementId); + + if (a == null || !this.isFinished(achievementId)) { + return a == null + ? AchievementControlReturns.achievementNotFound() + : AchievementControlReturns.notYetAchieved(); + } + + return this.progress(achievementId, 0); + } + + public AchievementControlReturns progress(int achievementId, int progress) { + var a = this.getAchievement(achievementId); + if (a == null) { + return AchievementControlReturns.achievementNotFound(); + } + + a.setCurProgress(progress); + return AchievementControlReturns.success(this.notifyOtherAchievements(a)); + } + + private int notifyOtherAchievements(Achievement a) { + var changedNum = new AtomicInteger(); + + changedNum.addAndGet(this.update(a) ? 1 : 0); + + GameData.getAchievementDataMap().get(a.getId()).getExcludedGroupAchievementIdList().stream() + .map(this::getAchievement) + .filter(Objects::nonNull) + .forEach( + other -> { + other.setCurProgress(a.getCurProgress()); + changedNum.addAndGet(this.update(other) ? 1 : 0); + }); + + this.computeFinishedAchievementNum(); + this.save(); + this.sendUpdatePacket(a); + return changedNum.intValue(); + } + + private boolean update(Achievement a) { + if (a.getStatus() == StatusOuterClass.Status.STATUS_UNFINISHED + && a.getCurProgress() >= a.getTotalProgress()) { + a.setStatus(StatusOuterClass.Status.STATUS_FINISHED); + a.setFinishTimestampSec(currentTimeSecs.getAsInt()); + return true; + } else if (this.isFinished(a.getId()) && a.getCurProgress() < a.getTotalProgress()) { + a.setStatus(StatusOuterClass.Status.STATUS_UNFINISHED); + a.setFinishTimestampSec(0); + return true; + } + + return false; + } + + private void computeFinishedAchievementNum() { + this.finishedAchievementNum = + GameData.getAchievementDataMap().values().stream() + .filter(a -> this.isFinished(a.getId())) + .mapToInt(value -> 1) + .sum(); + } + + private void sendUpdatePacket(Achievement achievement) { + List achievements = Lists.newArrayList(achievement); + achievements.addAll( + GameData.getAchievementDataMap() + .get(achievement.getId()) + .getExcludedGroupAchievementIdList() + .stream() + .map(this::getAchievement) + .filter(Objects::nonNull) + .toList()); + + this.sendUpdatePacket(achievements); + } + + private void sendUpdatePacket(List achievement) { + if (this.isPacketSendable()) { + this.player.sendPacket(new PacketAchievementUpdateNotify(achievement)); + } + } + + @Nullable public Achievement getAchievement(int achievementId) { + if (this.isInvalid(achievementId)) { + return null; + } + + return this.getAchievementList() + .computeIfAbsent( + achievementId, + id -> { + return new Achievement( + StatusOuterClass.Status.STATUS_UNFINISHED, + id, + GameData.getAchievementDataMap().get(id.intValue()).getProgress(), + 0, + 0); + }); + } + + public boolean isInvalid(int achievementId) { + var data = GameData.getAchievementDataMap().get(achievementId); + return data == null || data.isDisuse(); + } + + public StatusOuterClass.Status getStatus(int achievementId) { + return this.getAchievementList().getOrDefault(achievementId, INVALID).getStatus(); + } + + public boolean isFinished(int achievementId) { + var status = this.getStatus(achievementId); + return status == StatusOuterClass.Status.STATUS_FINISHED + || status == StatusOuterClass.Status.STATUS_REWARD_TAKEN; + } + + public void takeReward(List ids) { + List rewards = Lists.newArrayList(); + + for (int i : ids) { + var target = GameData.getAchievementDataMap().get(i); + if (target == null) { + Grasscutter.getLogger().warn("null returned while taking reward!"); + return; + } + + if (this.isRewardTaken(i)) { + this.player.sendPacket(new PacketTakeAchievementRewardRsp()); + return; + } + + var data = GameData.getRewardDataMap().get(target.getFinishRewardId()); + if (data == null) { + Grasscutter.getLogger().warn("null returned while getting reward data!"); + continue; + } + + data.getRewardItemList() + .forEach( + itemParamData -> { + var itemData = GameData.getItemDataMap().get(itemParamData.getId()); + if (itemData == null) { + Grasscutter.getLogger().warn("itemData == null!"); + return; + } + + rewards.add(new GameItem(itemData, itemParamData.getCount())); + }); + + var a = this.getAchievement(i); + a.setStatus(StatusOuterClass.Status.STATUS_REWARD_TAKEN); + this.save(); + this.sendUpdatePacket(a); + } + + this.player.getInventory().addItems(rewards, ActionReason.AchievementReward); + this.player.sendPacket( + new PacketTakeAchievementRewardRsp( + ids, rewards.stream().map(GameItem::toItemParam).toList())); + } + + public void takeGoalReward(List ids) { + List rewards = Lists.newArrayList(); + + for (int i : ids) { + if (this.takenGoalRewardIdList.contains(i)) { + this.player.sendPacket(new PacketTakeAchievementGoalRewardRsp()); + } + + var goalData = GameData.getAchievementGoalDataMap().get(i); + if (goalData == null) { + Grasscutter.getLogger().warn("null returned while getting goal reward data!"); + continue; + } + + var data = GameData.getRewardDataMap().get(goalData.getFinishRewardId()); + if (data == null) { + Grasscutter.getLogger().warn("null returned while getting reward data!"); + continue; + } + + data.getRewardItemList() + .forEach( + itemParamData -> { + var itemData = GameData.getItemDataMap().get(itemParamData.getId()); + if (itemData == null) { + Grasscutter.getLogger().warn("itemData == null!"); + return; + } + + rewards.add(new GameItem(itemData, itemParamData.getCount())); + }); + + this.takenGoalRewardIdList.add(i); + this.save(); + } + + this.player.getInventory().addItems(rewards, ActionReason.AchievementGoalReward); + this.player.sendPacket( + new PacketTakeAchievementGoalRewardRsp( + ids, rewards.stream().map(GameItem::toItemParam).toList())); + } + + public boolean isRewardTaken(int achievementId) { + return this.getStatus(achievementId) == StatusOuterClass.Status.STATUS_REWARD_TAKEN; + } + + public boolean isRewardLeft(int achievementId) { + return this.getStatus(achievementId) == StatusOuterClass.Status.STATUS_FINISHED; + } + + private boolean isPacketSendable() { + return this.player != null; + } + + public void save() { + DatabaseHelper.saveAchievementData(this); + } + + public void onLogin(Player player) { + if (this.player == null) { + this.player = player; + } + + this.player.sendPacket(new PacketAchievementAllDataNotify(this.player)); + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityConfigItem.java b/src/main/java/emu/grasscutter/game/activity/ActivityConfigItem.java index a8f17cdc8..88232bfab 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityConfigItem.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityConfigItem.java @@ -1,21 +1,20 @@ -package emu.grasscutter.game.activity; - -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.Date; -import java.util.List; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ActivityConfigItem { - int activityId; - int activityType; - int scheduleId; - List meetCondList; - Date beginTime; - Date endTime; - - transient ActivityHandler activityHandler; -} +package emu.grasscutter.game.activity; + +import java.util.Date; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ActivityConfigItem { + int activityId; + int activityType; + int scheduleId; + List meetCondList; + Date beginTime; + Date endTime; + + transient ActivityHandler activityHandler; +} diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityHandler.java b/src/main/java/emu/grasscutter/game/activity/ActivityHandler.java index a5993d065..993d0189c 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityHandler.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityHandler.java @@ -1,91 +1,98 @@ -package emu.grasscutter.game.activity; - -import com.esotericsoftware.reflectasm.ConstructorAccess; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.ActivityData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.ActivityInfoOuterClass; -import emu.grasscutter.utils.DateHelper; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -import java.util.*; -import java.util.stream.Collectors; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public abstract class ActivityHandler { - /** - * Must set before initWatchers - */ - ActivityConfigItem activityConfigItem; - ActivityData activityData; - Map> watchersMap = new HashMap<>(); - - abstract public void onProtoBuild(PlayerActivityData playerActivityData, ActivityInfoOuterClass.ActivityInfo.Builder activityInfo); - - abstract public void onInitPlayerActivityData(PlayerActivityData playerActivityData); - - public void initWatchers(Map> activityWatcherTypeMap) { - activityData = GameData.getActivityDataMap().get(activityConfigItem.getActivityId()); - - // add watcher to map by id - activityData.getWatcherDataList().forEach(watcherData -> { - var watcherType = activityWatcherTypeMap.get(watcherData.getTriggerConfig().getWatcherTriggerType()); - ActivityWatcher watcher; - if (watcherType != null) { - watcher = (ActivityWatcher) watcherType.newInstance(); - } else { - watcher = new DefaultWatcher(); - } - - watcher.setWatcherId(watcherData.getId()); - watcher.setActivityHandler(this); - watcher.setActivityWatcherData(watcherData); - watchersMap.computeIfAbsent(watcherData.getTriggerConfig().getWatcherTriggerType(), k -> new ArrayList<>()); - watchersMap.get(watcherData.getTriggerConfig().getWatcherTriggerType()).add(watcher); - }); - } - - private Map initWatchersDataForPlayer() { - return watchersMap.values().stream() - .flatMap(Collection::stream) - .map(PlayerActivityData.WatcherInfo::init) - .collect(Collectors.toMap(PlayerActivityData.WatcherInfo::getWatcherId, y -> y)); - } - - public PlayerActivityData initPlayerActivityData(Player player) { - PlayerActivityData playerActivityData = PlayerActivityData.of() - .activityId(activityConfigItem.getActivityId()) - .uid(player.getUid()) - .watcherInfoMap(initWatchersDataForPlayer()) - .build(); - - onInitPlayerActivityData(playerActivityData); - return playerActivityData; - } - - public ActivityInfoOuterClass.ActivityInfo toProto(PlayerActivityData playerActivityData) { - var proto = ActivityInfoOuterClass.ActivityInfo.newBuilder(); - proto.setActivityId(activityConfigItem.getActivityId()) - .setActivityType(activityConfigItem.getActivityType()) - .setScheduleId(activityConfigItem.getScheduleId()) - .setBeginTime(DateHelper.getUnixTime(activityConfigItem.getBeginTime())) - .setFirstDayStartTime(DateHelper.getUnixTime(activityConfigItem.getBeginTime())) - .setEndTime(DateHelper.getUnixTime(activityConfigItem.getEndTime())) - .addAllMeetCondList(activityConfigItem.getMeetCondList()); - - if (playerActivityData != null) { - proto.addAllWatcherInfoList(playerActivityData.getAllWatcherInfoList()); - } - - onProtoBuild(playerActivityData, proto); - - return proto.build(); - } - -} +package emu.grasscutter.game.activity; + +import com.esotericsoftware.reflectasm.ConstructorAccess; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.ActivityData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.ActivityInfoOuterClass; +import emu.grasscutter.utils.DateHelper; +import java.util.*; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; + +@Getter +@Setter +@FieldDefaults(level = AccessLevel.PRIVATE) +public abstract class ActivityHandler { + /** Must set before initWatchers */ + ActivityConfigItem activityConfigItem; + + ActivityData activityData; + Map> watchersMap = new HashMap<>(); + + public abstract void onProtoBuild( + PlayerActivityData playerActivityData, + ActivityInfoOuterClass.ActivityInfo.Builder activityInfo); + + public abstract void onInitPlayerActivityData(PlayerActivityData playerActivityData); + + public void initWatchers(Map> activityWatcherTypeMap) { + activityData = GameData.getActivityDataMap().get(activityConfigItem.getActivityId()); + + // add watcher to map by id + activityData + .getWatcherDataList() + .forEach( + watcherData -> { + var watcherType = + activityWatcherTypeMap.get( + watcherData.getTriggerConfig().getWatcherTriggerType()); + ActivityWatcher watcher; + if (watcherType != null) { + watcher = (ActivityWatcher) watcherType.newInstance(); + } else { + watcher = new DefaultWatcher(); + } + + watcher.setWatcherId(watcherData.getId()); + watcher.setActivityHandler(this); + watcher.setActivityWatcherData(watcherData); + watchersMap.computeIfAbsent( + watcherData.getTriggerConfig().getWatcherTriggerType(), k -> new ArrayList<>()); + watchersMap.get(watcherData.getTriggerConfig().getWatcherTriggerType()).add(watcher); + }); + } + + private Map initWatchersDataForPlayer() { + return watchersMap.values().stream() + .flatMap(Collection::stream) + .map(PlayerActivityData.WatcherInfo::init) + .collect(Collectors.toMap(PlayerActivityData.WatcherInfo::getWatcherId, y -> y)); + } + + public PlayerActivityData initPlayerActivityData(Player player) { + PlayerActivityData playerActivityData = + PlayerActivityData.of() + .activityId(activityConfigItem.getActivityId()) + .uid(player.getUid()) + .watcherInfoMap(initWatchersDataForPlayer()) + .build(); + + onInitPlayerActivityData(playerActivityData); + return playerActivityData; + } + + public ActivityInfoOuterClass.ActivityInfo toProto(PlayerActivityData playerActivityData) { + var proto = ActivityInfoOuterClass.ActivityInfo.newBuilder(); + proto + .setActivityId(activityConfigItem.getActivityId()) + .setActivityType(activityConfigItem.getActivityType()) + .setScheduleId(activityConfigItem.getScheduleId()) + .setBeginTime(DateHelper.getUnixTime(activityConfigItem.getBeginTime())) + .setFirstDayStartTime(DateHelper.getUnixTime(activityConfigItem.getBeginTime())) + .setEndTime(DateHelper.getUnixTime(activityConfigItem.getEndTime())) + .addAllMeetCondList(activityConfigItem.getMeetCondList()); + + if (playerActivityData != null) { + proto.addAllWatcherInfoList(playerActivityData.getAllWatcherInfoList()); + } + + onProtoBuild(playerActivityData, proto); + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java index 8592dc60a..6a7c8c8be 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java @@ -1,150 +1,161 @@ -package emu.grasscutter.game.activity; - -import com.esotericsoftware.reflectasm.ConstructorAccess; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActivityType; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.ActivityInfoOuterClass; -import emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify; -import lombok.Getter; -import org.reflections.Reflections; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -@Getter -public class ActivityManager extends BasePlayerManager { - private static final Map activityConfigItemMap; - @Getter - private static final Map scheduleActivityConfigMap; - - static { - activityConfigItemMap = new HashMap<>(); - scheduleActivityConfigMap = new HashMap<>(); - loadActivityConfigData(); - } - - private final Map playerActivityDataMap; - - public ActivityManager(Player player) { - super(player); - - playerActivityDataMap = new ConcurrentHashMap<>(); - // load data for player - activityConfigItemMap.values().forEach(item -> { - var data = PlayerActivityData.getByPlayer(player, item.getActivityId()); - if (data == null) { - data = item.getActivityHandler().initPlayerActivityData(player); - data.save(); - } - data.setPlayer(player); - data.setActivityHandler(item.getActivityHandler()); - playerActivityDataMap.put(item.getActivityId(), data); - }); - - player.sendPacket(new PacketActivityScheduleInfoNotify(activityConfigItemMap.values())); - } - - private static void loadActivityConfigData() { - // scan activity type handler & watcher type - var activityHandlerTypeMap = new HashMap>(); - var activityWatcherTypeMap = new HashMap>(); - var reflections = new Reflections(ActivityManager.class.getPackage().getName()); - - reflections.getSubTypesOf(ActivityHandler.class).forEach(item -> { - var typeName = item.getAnnotation(GameActivity.class); - activityHandlerTypeMap.put(typeName.value(), ConstructorAccess.get(item)); - }); - reflections.getSubTypesOf(ActivityWatcher.class).forEach(item -> { - var typeName = item.getAnnotation(ActivityWatcherType.class); - activityWatcherTypeMap.put(typeName.value(), ConstructorAccess.get(item)); - }); - - try { - DataLoader.loadList("ActivityConfig.json", ActivityConfigItem.class).forEach(item -> { - var activityData = GameData.getActivityDataMap().get(item.getActivityId()); - if (activityData == null) { - Grasscutter.getLogger().warn("activity {} not exist.", item.getActivityId()); - return; - } - var activityHandlerType = activityHandlerTypeMap.get(ActivityType.getTypeByName(activityData.getActivityType())); - ActivityHandler activityHandler; - - if (activityHandlerType != null) { - activityHandler = (ActivityHandler) activityHandlerType.newInstance(); - } else { - activityHandler = new DefaultActivityHandler(); - } - activityHandler.setActivityConfigItem(item); - activityHandler.initWatchers(activityWatcherTypeMap); - item.setActivityHandler(activityHandler); - - activityConfigItemMap.putIfAbsent(item.getActivityId(), item); - scheduleActivityConfigMap.putIfAbsent(item.getScheduleId(), item); - }); - - Grasscutter.getLogger().info("Enable {} activities.", activityConfigItemMap.size()); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load activities config.", e); - } - - } - - /** - * trigger activity watcher - */ - public void triggerWatcher(WatcherTriggerType watcherTriggerType, String... params) { - var watchers = activityConfigItemMap.values().stream() - .map(ActivityConfigItem::getActivityHandler) - .filter(Objects::nonNull) - .map(ActivityHandler::getWatchersMap) - .map(map -> map.get(watcherTriggerType)) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .toList(); - - watchers.forEach(watcher -> watcher.trigger( - playerActivityDataMap.get(watcher.getActivityHandler().getActivityConfigItem().getActivityId()), - params)); - } - - public ActivityInfoOuterClass.ActivityInfo getInfoProtoByActivityId(int activityId) { - var activityHandler = activityConfigItemMap.get(activityId).getActivityHandler(); - var activityData = playerActivityDataMap.get(activityId); - - return activityHandler.toProto(activityData); - } - - public Optional getActivityHandler(ActivityType type) { - return activityConfigItemMap.values().stream() - .map(ActivityConfigItem::getActivityHandler) - .filter(x -> type == x.getClass().getAnnotation(GameActivity.class).value()) - .findFirst(); - } - - @SuppressWarnings("unchecked") - public Optional getActivityHandlerAs(ActivityType type, Class clazz) { - return getActivityHandler(type).map(x -> (T) x); - } - - public Optional getActivityIdByActivityType(ActivityType type) { - return getActivityHandler(type) - .map(ActivityHandler::getActivityConfigItem) - .map(ActivityConfigItem::getActivityId); - } - - public Optional getPlayerActivityDataByActivityType(ActivityType type) { - return getActivityIdByActivityType(type) - .map(playerActivityDataMap::get); - } - - public Optional getInfoProtoByActivityType(ActivityType type) { - return getActivityIdByActivityType(type) - .map(this::getInfoProtoByActivityId); - } - -} +package emu.grasscutter.game.activity; + +import com.esotericsoftware.reflectasm.ConstructorAccess; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActivityType; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.ActivityInfoOuterClass; +import emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import lombok.Getter; +import org.reflections.Reflections; + +@Getter +public class ActivityManager extends BasePlayerManager { + private static final Map activityConfigItemMap; + @Getter private static final Map scheduleActivityConfigMap; + + static { + activityConfigItemMap = new HashMap<>(); + scheduleActivityConfigMap = new HashMap<>(); + loadActivityConfigData(); + } + + private final Map playerActivityDataMap; + + public ActivityManager(Player player) { + super(player); + + playerActivityDataMap = new ConcurrentHashMap<>(); + // load data for player + activityConfigItemMap + .values() + .forEach( + item -> { + var data = PlayerActivityData.getByPlayer(player, item.getActivityId()); + if (data == null) { + data = item.getActivityHandler().initPlayerActivityData(player); + data.save(); + } + data.setPlayer(player); + data.setActivityHandler(item.getActivityHandler()); + playerActivityDataMap.put(item.getActivityId(), data); + }); + + player.sendPacket(new PacketActivityScheduleInfoNotify(activityConfigItemMap.values())); + } + + private static void loadActivityConfigData() { + // scan activity type handler & watcher type + var activityHandlerTypeMap = new HashMap>(); + var activityWatcherTypeMap = new HashMap>(); + var reflections = new Reflections(ActivityManager.class.getPackage().getName()); + + reflections + .getSubTypesOf(ActivityHandler.class) + .forEach( + item -> { + var typeName = item.getAnnotation(GameActivity.class); + activityHandlerTypeMap.put(typeName.value(), ConstructorAccess.get(item)); + }); + reflections + .getSubTypesOf(ActivityWatcher.class) + .forEach( + item -> { + var typeName = item.getAnnotation(ActivityWatcherType.class); + activityWatcherTypeMap.put(typeName.value(), ConstructorAccess.get(item)); + }); + + try { + DataLoader.loadList("ActivityConfig.json", ActivityConfigItem.class) + .forEach( + item -> { + var activityData = GameData.getActivityDataMap().get(item.getActivityId()); + if (activityData == null) { + Grasscutter.getLogger().warn("activity {} not exist.", item.getActivityId()); + return; + } + var activityHandlerType = + activityHandlerTypeMap.get( + ActivityType.getTypeByName(activityData.getActivityType())); + ActivityHandler activityHandler; + + if (activityHandlerType != null) { + activityHandler = (ActivityHandler) activityHandlerType.newInstance(); + } else { + activityHandler = new DefaultActivityHandler(); + } + activityHandler.setActivityConfigItem(item); + activityHandler.initWatchers(activityWatcherTypeMap); + item.setActivityHandler(activityHandler); + + activityConfigItemMap.putIfAbsent(item.getActivityId(), item); + scheduleActivityConfigMap.putIfAbsent(item.getScheduleId(), item); + }); + + Grasscutter.getLogger().info("Enable {} activities.", activityConfigItemMap.size()); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load activities config.", e); + } + } + + /** trigger activity watcher */ + public void triggerWatcher(WatcherTriggerType watcherTriggerType, String... params) { + var watchers = + activityConfigItemMap.values().stream() + .map(ActivityConfigItem::getActivityHandler) + .filter(Objects::nonNull) + .map(ActivityHandler::getWatchersMap) + .map(map -> map.get(watcherTriggerType)) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .toList(); + + watchers.forEach( + watcher -> + watcher.trigger( + playerActivityDataMap.get( + watcher.getActivityHandler().getActivityConfigItem().getActivityId()), + params)); + } + + public ActivityInfoOuterClass.ActivityInfo getInfoProtoByActivityId(int activityId) { + var activityHandler = activityConfigItemMap.get(activityId).getActivityHandler(); + var activityData = playerActivityDataMap.get(activityId); + + return activityHandler.toProto(activityData); + } + + public Optional getActivityHandler(ActivityType type) { + return activityConfigItemMap.values().stream() + .map(ActivityConfigItem::getActivityHandler) + .filter(x -> type == x.getClass().getAnnotation(GameActivity.class).value()) + .findFirst(); + } + + @SuppressWarnings("unchecked") + public Optional getActivityHandlerAs( + ActivityType type, Class clazz) { + return getActivityHandler(type).map(x -> (T) x); + } + + public Optional getActivityIdByActivityType(ActivityType type) { + return getActivityHandler(type) + .map(ActivityHandler::getActivityConfigItem) + .map(ActivityConfigItem::getActivityId); + } + + public Optional getPlayerActivityDataByActivityType(ActivityType type) { + return getActivityIdByActivityType(type).map(playerActivityDataMap::get); + } + + public Optional getInfoProtoByActivityType( + ActivityType type) { + return getActivityIdByActivityType(type).map(this::getInfoProtoByActivityId); + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityWatcher.java b/src/main/java/emu/grasscutter/game/activity/ActivityWatcher.java index 105792724..ec5fca27f 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityWatcher.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityWatcher.java @@ -1,26 +1,25 @@ -package emu.grasscutter.game.activity; - -import emu.grasscutter.data.excels.ActivityWatcherData; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.FieldDefaults; - -@Getter -@Setter -@FieldDefaults(level = AccessLevel.PRIVATE) -public abstract class ActivityWatcher { - int watcherId; - ActivityWatcherData activityWatcherData; - ActivityHandler activityHandler; - - protected abstract boolean isMeet(String... param); - - public void trigger(PlayerActivityData playerActivityData, String... param) { - if (isMeet(param)) { - playerActivityData.addWatcherProgress(watcherId); - playerActivityData.save(); - } - } - -} +package emu.grasscutter.game.activity; + +import emu.grasscutter.data.excels.ActivityWatcherData; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; + +@Getter +@Setter +@FieldDefaults(level = AccessLevel.PRIVATE) +public abstract class ActivityWatcher { + int watcherId; + ActivityWatcherData activityWatcherData; + ActivityHandler activityHandler; + + protected abstract boolean isMeet(String... param); + + public void trigger(PlayerActivityData playerActivityData, String... param) { + if (isMeet(param)) { + playerActivityData.addWatcherProgress(watcherId); + playerActivityData.save(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityWatcherType.java b/src/main/java/emu/grasscutter/game/activity/ActivityWatcherType.java index 4c68e11f5..6b70d3b3d 100644 --- a/src/main/java/emu/grasscutter/game/activity/ActivityWatcherType.java +++ b/src/main/java/emu/grasscutter/game/activity/ActivityWatcherType.java @@ -1,14 +1,13 @@ -package emu.grasscutter.game.activity; - -import emu.grasscutter.game.props.WatcherTriggerType; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ActivityWatcherType { - WatcherTriggerType value(); -} +package emu.grasscutter.game.activity; + +import emu.grasscutter.game.props.WatcherTriggerType; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ActivityWatcherType { + WatcherTriggerType value(); +} diff --git a/src/main/java/emu/grasscutter/game/activity/DefaultActivityHandler.java b/src/main/java/emu/grasscutter/game/activity/DefaultActivityHandler.java index 98956c6b4..bca08ed10 100644 --- a/src/main/java/emu/grasscutter/game/activity/DefaultActivityHandler.java +++ b/src/main/java/emu/grasscutter/game/activity/DefaultActivityHandler.java @@ -1,17 +1,15 @@ -package emu.grasscutter.game.activity; - -import emu.grasscutter.game.props.ActivityType; -import emu.grasscutter.net.proto.ActivityInfoOuterClass; - -@GameActivity(ActivityType.NONE) -public class DefaultActivityHandler extends ActivityHandler { - @Override - public void onProtoBuild(PlayerActivityData playerActivityData, ActivityInfoOuterClass.ActivityInfo.Builder activityInfo) { - - } - - @Override - public void onInitPlayerActivityData(PlayerActivityData playerActivityData) { - - } -} +package emu.grasscutter.game.activity; + +import emu.grasscutter.game.props.ActivityType; +import emu.grasscutter.net.proto.ActivityInfoOuterClass; + +@GameActivity(ActivityType.NONE) +public class DefaultActivityHandler extends ActivityHandler { + @Override + public void onProtoBuild( + PlayerActivityData playerActivityData, + ActivityInfoOuterClass.ActivityInfo.Builder activityInfo) {} + + @Override + public void onInitPlayerActivityData(PlayerActivityData playerActivityData) {} +} diff --git a/src/main/java/emu/grasscutter/game/activity/DefaultWatcher.java b/src/main/java/emu/grasscutter/game/activity/DefaultWatcher.java index 0a2e6142b..7a9a29e35 100644 --- a/src/main/java/emu/grasscutter/game/activity/DefaultWatcher.java +++ b/src/main/java/emu/grasscutter/game/activity/DefaultWatcher.java @@ -1,11 +1,11 @@ -package emu.grasscutter.game.activity; - -import emu.grasscutter.game.props.WatcherTriggerType; - -@ActivityWatcherType(WatcherTriggerType.TRIGGER_NONE) -public class DefaultWatcher extends ActivityWatcher { - @Override - protected boolean isMeet(String... param) { - return false; - } -} +package emu.grasscutter.game.activity; + +import emu.grasscutter.game.props.WatcherTriggerType; + +@ActivityWatcherType(WatcherTriggerType.TRIGGER_NONE) +public class DefaultWatcher extends ActivityWatcher { + @Override + protected boolean isMeet(String... param) { + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/GameActivity.java b/src/main/java/emu/grasscutter/game/activity/GameActivity.java index 7d70a653d..4332d20a4 100644 --- a/src/main/java/emu/grasscutter/game/activity/GameActivity.java +++ b/src/main/java/emu/grasscutter/game/activity/GameActivity.java @@ -1,14 +1,13 @@ -package emu.grasscutter.game.activity; - -import emu.grasscutter.game.props.ActivityType; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface GameActivity { - ActivityType value(); -} +package emu.grasscutter.game.activity; + +import emu.grasscutter.game.props.ActivityType; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface GameActivity { + ActivityType value(); +} diff --git a/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java b/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java index 7770a04d0..b97a94533 100644 --- a/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java +++ b/src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java @@ -1,133 +1,127 @@ -package emu.grasscutter.game.activity; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Transient; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ActivityWatcherData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass; -import emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify; -import emu.grasscutter.utils.JsonUtils; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -@Entity("activities") -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class PlayerActivityData { - @Id - String id; - int uid; - int activityId; - Map watcherInfoMap; - /** - * the detail data of each type of activity (Json format) - */ - String detail; - @Transient - Player player; - @Transient - ActivityHandler activityHandler; - - public static PlayerActivityData getByPlayer(Player player, int activityId) { - return DatabaseHelper.getPlayerActivityData(player.getUid(), activityId); - } - - public void save() { - DatabaseHelper.savePlayerActivityData(this); - } - - public synchronized void addWatcherProgress(int watcherId) { - var watcherInfo = watcherInfoMap.get(watcherId); - if (watcherInfo == null) { - return; - } - - if (watcherInfo.curProgress >= watcherInfo.totalProgress) { - return; - } - - watcherInfo.curProgress++; - getPlayer().sendPacket(new PacketActivityUpdateWatcherNotify(activityId, watcherInfo)); - } - - public List getAllWatcherInfoList() { - return watcherInfoMap.values().stream() - .map(WatcherInfo::toProto) - .toList(); - } - - public void setDetail(Object detail) { - this.detail = JsonUtils.encode(detail); - } - - public void takeWatcherReward(int watcherId) { - var watcher = watcherInfoMap.get(watcherId); - if (watcher == null || watcher.isTakenReward()) { - return; - } - - var reward = Optional.of(watcher) - .map(WatcherInfo::getMetadata) - .map(ActivityWatcherData::getRewardID) - .map(id -> GameData.getRewardDataMap().get(id.intValue())); - - if (reward.isEmpty()) { - return; - } - - List rewards = new ArrayList<>(); - for (ItemParamData param : reward.get().getRewardItemList()) { - rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); - } - - player.getInventory().addItems(rewards, ActionReason.ActivityWatcher); - watcher.setTakenReward(true); - save(); - } - - @Entity - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - @Builder(builderMethodName = "of") - public static class WatcherInfo { - int watcherId; - int totalProgress; - int curProgress; - boolean isTakenReward; - - public static WatcherInfo init(ActivityWatcher watcher) { - return WatcherInfo.of() - .watcherId(watcher.getWatcherId()) - .totalProgress(watcher.getActivityWatcherData().getProgress()) - .isTakenReward(false) - .build(); - } - - public ActivityWatcherData getMetadata() { - return GameData.getActivityWatcherDataMap().get(watcherId); - } - - public ActivityWatcherInfoOuterClass.ActivityWatcherInfo toProto() { - return ActivityWatcherInfoOuterClass.ActivityWatcherInfo.newBuilder() - .setWatcherId(watcherId) - .setCurProgress(curProgress) - .setTotalProgress(totalProgress) - .setIsTakenReward(isTakenReward) - .build(); - } - } -} +package emu.grasscutter.game.activity; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ActivityWatcherData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass; +import emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify; +import emu.grasscutter.utils.JsonUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity("activities") +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class PlayerActivityData { + @Id String id; + int uid; + int activityId; + Map watcherInfoMap; + /** the detail data of each type of activity (Json format) */ + String detail; + + @Transient Player player; + @Transient ActivityHandler activityHandler; + + public static PlayerActivityData getByPlayer(Player player, int activityId) { + return DatabaseHelper.getPlayerActivityData(player.getUid(), activityId); + } + + public void save() { + DatabaseHelper.savePlayerActivityData(this); + } + + public synchronized void addWatcherProgress(int watcherId) { + var watcherInfo = watcherInfoMap.get(watcherId); + if (watcherInfo == null) { + return; + } + + if (watcherInfo.curProgress >= watcherInfo.totalProgress) { + return; + } + + watcherInfo.curProgress++; + getPlayer().sendPacket(new PacketActivityUpdateWatcherNotify(activityId, watcherInfo)); + } + + public List getAllWatcherInfoList() { + return watcherInfoMap.values().stream().map(WatcherInfo::toProto).toList(); + } + + public void setDetail(Object detail) { + this.detail = JsonUtils.encode(detail); + } + + public void takeWatcherReward(int watcherId) { + var watcher = watcherInfoMap.get(watcherId); + if (watcher == null || watcher.isTakenReward()) { + return; + } + + var reward = + Optional.of(watcher) + .map(WatcherInfo::getMetadata) + .map(ActivityWatcherData::getRewardID) + .map(id -> GameData.getRewardDataMap().get(id.intValue())); + + if (reward.isEmpty()) { + return; + } + + List rewards = new ArrayList<>(); + for (ItemParamData param : reward.get().getRewardItemList()) { + rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); + } + + player.getInventory().addItems(rewards, ActionReason.ActivityWatcher); + watcher.setTakenReward(true); + save(); + } + + @Entity + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + @Builder(builderMethodName = "of") + public static class WatcherInfo { + int watcherId; + int totalProgress; + int curProgress; + boolean isTakenReward; + + public static WatcherInfo init(ActivityWatcher watcher) { + return WatcherInfo.of() + .watcherId(watcher.getWatcherId()) + .totalProgress(watcher.getActivityWatcherData().getProgress()) + .isTakenReward(false) + .build(); + } + + public ActivityWatcherData getMetadata() { + return GameData.getActivityWatcherDataMap().get(watcherId); + } + + public ActivityWatcherInfoOuterClass.ActivityWatcherInfo toProto() { + return ActivityWatcherInfoOuterClass.ActivityWatcherInfo.newBuilder() + .setWatcherId(watcherId) + .setCurProgress(curProgress) + .setTotalProgress(totalProgress) + .setIsTakenReward(isTakenReward) + .build(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java index bbb670d08..da2737172 100644 --- a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java +++ b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java @@ -1,91 +1,105 @@ -package emu.grasscutter.game.activity.musicgame; - -import emu.grasscutter.game.activity.ActivityHandler; -import emu.grasscutter.game.activity.GameActivity; -import emu.grasscutter.game.activity.PlayerActivityData; -import emu.grasscutter.game.props.ActivityType; -import emu.grasscutter.net.proto.ActivityInfoOuterClass; -import emu.grasscutter.net.proto.MusicGameActivityDetailInfoOuterClass; -import emu.grasscutter.utils.JsonUtils; - -import java.util.stream.Collectors; - -@GameActivity(ActivityType.NEW_ACTIVITY_MUSIC_GAME) -public class MusicGameActivityHandler extends ActivityHandler { - - @Override - public void onInitPlayerActivityData(PlayerActivityData playerActivityData) { - var musicGamePlayerData = MusicGamePlayerData.create(); - - playerActivityData.setDetail(musicGamePlayerData); - } - - @Override - public void onProtoBuild(PlayerActivityData playerActivityData, ActivityInfoOuterClass.ActivityInfo.Builder activityInfo) { - MusicGamePlayerData musicGamePlayerData = getMusicGamePlayerData(playerActivityData); - - activityInfo.setMusicGameInfo(MusicGameActivityDetailInfoOuterClass.MusicGameActivityDetailInfo.newBuilder() - .putAllMusicGameRecordMap( - musicGamePlayerData.getMusicGameRecord().values().stream() - .collect(Collectors.toMap(MusicGamePlayerData.MusicGameRecord::getMusicId, MusicGamePlayerData.MusicGameRecord::toProto))) -// .addAllPersonCustomBeatmap(musicGamePlayerData.getPersonalCustomBeatmapRecord().values().stream() -// .map(MusicGamePlayerData.CustomBeatmapRecord::toPersonalBriefProto) -// .map(UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder::build) -// .toList()) -// -// .addAllOthersCustomBeatmap(musicGamePlayerData.getOthersCustomBeatmapRecord().values().stream() -// .map(MusicGamePlayerData.CustomBeatmapRecord::toOthersBriefProto) -// .map(UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder::build) -// .toList()) - .build()); - } - - public MusicGamePlayerData getMusicGamePlayerData(PlayerActivityData playerActivityData) { - if (playerActivityData.getDetail() == null || playerActivityData.getDetail().isBlank()) { - onInitPlayerActivityData(playerActivityData); - playerActivityData.save(); - } - - return JsonUtils.decode(playerActivityData.getDetail(), MusicGamePlayerData.class); - } - - public boolean setMusicGameRecord(PlayerActivityData playerActivityData, MusicGamePlayerData.MusicGameRecord newRecord) { - var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); - var saveRecord = musicGamePlayerData.getMusicGameRecord().get(newRecord.getMusicId()); - - saveRecord.setMaxCombo(Math.max(newRecord.getMaxCombo(), saveRecord.getMaxCombo())); - saveRecord.setMaxScore(Math.max(newRecord.getMaxScore(), saveRecord.getMaxScore())); - - playerActivityData.setDetail(musicGamePlayerData); - playerActivityData.save(); - - return newRecord.getMaxScore() > saveRecord.getMaxScore(); - } - - public void setMusicGameCustomBeatmapRecord(PlayerActivityData playerActivityData, MusicGamePlayerData.CustomBeatmapRecord newRecord) { - var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); - musicGamePlayerData.getOthersCustomBeatmapRecord().put(newRecord.getMusicShareId(), newRecord); - - playerActivityData.setDetail(musicGamePlayerData); - playerActivityData.save(); - } - - public void addPersonalBeatmap(PlayerActivityData playerActivityData, MusicGameBeatmap musicGameBeatmap) { - var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); - musicGamePlayerData.getPersonalCustomBeatmapRecord().put(musicGameBeatmap.getMusicShareId(), - MusicGamePlayerData.CustomBeatmapRecord.of() - .musicShareId(musicGameBeatmap.getMusicShareId()) - .build()); - - playerActivityData.setDetail(musicGamePlayerData); - playerActivityData.save(); - } - - public void removePersonalBeatmap(PlayerActivityData playerActivityData, MusicGameBeatmap musicGameBeatmap) { - var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); - musicGamePlayerData.getPersonalCustomBeatmapRecord().remove(musicGameBeatmap.getMusicShareId()); - - playerActivityData.setDetail(musicGamePlayerData); - playerActivityData.save(); - } -} +package emu.grasscutter.game.activity.musicgame; + +import emu.grasscutter.game.activity.ActivityHandler; +import emu.grasscutter.game.activity.GameActivity; +import emu.grasscutter.game.activity.PlayerActivityData; +import emu.grasscutter.game.props.ActivityType; +import emu.grasscutter.net.proto.ActivityInfoOuterClass; +import emu.grasscutter.net.proto.MusicGameActivityDetailInfoOuterClass; +import emu.grasscutter.utils.JsonUtils; +import java.util.stream.Collectors; + +@GameActivity(ActivityType.NEW_ACTIVITY_MUSIC_GAME) +public class MusicGameActivityHandler extends ActivityHandler { + + @Override + public void onInitPlayerActivityData(PlayerActivityData playerActivityData) { + var musicGamePlayerData = MusicGamePlayerData.create(); + + playerActivityData.setDetail(musicGamePlayerData); + } + + @Override + public void onProtoBuild( + PlayerActivityData playerActivityData, + ActivityInfoOuterClass.ActivityInfo.Builder activityInfo) { + MusicGamePlayerData musicGamePlayerData = getMusicGamePlayerData(playerActivityData); + + activityInfo.setMusicGameInfo( + MusicGameActivityDetailInfoOuterClass.MusicGameActivityDetailInfo.newBuilder() + .putAllMusicGameRecordMap( + musicGamePlayerData.getMusicGameRecord().values().stream() + .collect( + Collectors.toMap( + MusicGamePlayerData.MusicGameRecord::getMusicId, + MusicGamePlayerData.MusicGameRecord::toProto))) + // + // .addAllPersonCustomBeatmap(musicGamePlayerData.getPersonalCustomBeatmapRecord().values().stream() + // .map(MusicGamePlayerData.CustomBeatmapRecord::toPersonalBriefProto) + // .map(UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder::build) + // .toList()) + // + // + // .addAllOthersCustomBeatmap(musicGamePlayerData.getOthersCustomBeatmapRecord().values().stream() + // .map(MusicGamePlayerData.CustomBeatmapRecord::toOthersBriefProto) + // .map(UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder::build) + // .toList()) + .build()); + } + + public MusicGamePlayerData getMusicGamePlayerData(PlayerActivityData playerActivityData) { + if (playerActivityData.getDetail() == null || playerActivityData.getDetail().isBlank()) { + onInitPlayerActivityData(playerActivityData); + playerActivityData.save(); + } + + return JsonUtils.decode(playerActivityData.getDetail(), MusicGamePlayerData.class); + } + + public boolean setMusicGameRecord( + PlayerActivityData playerActivityData, MusicGamePlayerData.MusicGameRecord newRecord) { + var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); + var saveRecord = musicGamePlayerData.getMusicGameRecord().get(newRecord.getMusicId()); + + saveRecord.setMaxCombo(Math.max(newRecord.getMaxCombo(), saveRecord.getMaxCombo())); + saveRecord.setMaxScore(Math.max(newRecord.getMaxScore(), saveRecord.getMaxScore())); + + playerActivityData.setDetail(musicGamePlayerData); + playerActivityData.save(); + + return newRecord.getMaxScore() > saveRecord.getMaxScore(); + } + + public void setMusicGameCustomBeatmapRecord( + PlayerActivityData playerActivityData, MusicGamePlayerData.CustomBeatmapRecord newRecord) { + var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); + musicGamePlayerData.getOthersCustomBeatmapRecord().put(newRecord.getMusicShareId(), newRecord); + + playerActivityData.setDetail(musicGamePlayerData); + playerActivityData.save(); + } + + public void addPersonalBeatmap( + PlayerActivityData playerActivityData, MusicGameBeatmap musicGameBeatmap) { + var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); + musicGamePlayerData + .getPersonalCustomBeatmapRecord() + .put( + musicGameBeatmap.getMusicShareId(), + MusicGamePlayerData.CustomBeatmapRecord.of() + .musicShareId(musicGameBeatmap.getMusicShareId()) + .build()); + + playerActivityData.setDetail(musicGamePlayerData); + playerActivityData.save(); + } + + public void removePersonalBeatmap( + PlayerActivityData playerActivityData, MusicGameBeatmap musicGameBeatmap) { + var musicGamePlayerData = getMusicGamePlayerData(playerActivityData); + musicGamePlayerData.getPersonalCustomBeatmapRecord().remove(musicGameBeatmap.getMusicShareId()); + + playerActivityData.setDetail(musicGamePlayerData); + playerActivityData.save(); + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameBeatmap.java b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameBeatmap.java index 6f2f88335..93ba98cf1 100644 --- a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameBeatmap.java +++ b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameBeatmap.java @@ -1,106 +1,97 @@ -package emu.grasscutter.game.activity.musicgame; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.net.proto.UgcMusicBriefInfoOuterClass; -import emu.grasscutter.net.proto.UgcMusicNoteOuterClass; -import emu.grasscutter.net.proto.UgcMusicRecordOuterClass; -import emu.grasscutter.net.proto.UgcMusicTrackOuterClass; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; -import java.util.Random; - -@Entity("music_game_beatmaps") -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class MusicGameBeatmap { - - @Id - long musicShareId; - int authorUid; - int musicId; - int musicNoteCount; - int savePosition; - int maxScore; - int createTime; - - List> beatmap; - - public static MusicGameBeatmap getByShareId(long musicShareId) { - return DatabaseHelper.getMusicGameBeatmap(musicShareId); - } - - public static List> parse(List beatmapItemListList) { - return beatmapItemListList.stream() - .map(item -> item.getMusicNoteListList().stream() - .map(BeatmapNote::parse) - .toList()) - .toList(); - } - - public void save() { - if (musicShareId == 0) { - musicShareId = new Random().nextLong(100000000000000L, 999999999999999L); - } - DatabaseHelper.saveMusicGameBeatmap(this); - } - - public UgcMusicRecordOuterClass.UgcMusicRecord toProto() { - return UgcMusicRecordOuterClass.UgcMusicRecord.newBuilder() - .setMusicId(musicId) - .addAllMusicTrackList(beatmap.stream() - .map(this::musicBeatmapListToProto) - .toList()) - .build(); - } - - public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toBriefProto() { - var player = DatabaseHelper.getPlayerByUid(authorUid); - - return UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.newBuilder() - .setMusicId(musicId) -// .setMusicNoteCount(musicNoteCount) - .setUgcGuid(musicShareId) - .setMaxScore(maxScore) -// .setShareTime(createTime) - .setCreatorNickname(player.getNickname()) - .setVersion(1); - } - - private UgcMusicTrackOuterClass.UgcMusicTrack musicBeatmapListToProto(List beatmapNoteList) { - return UgcMusicTrackOuterClass.UgcMusicTrack.newBuilder() - .addAllMusicNoteList(beatmapNoteList.stream() - .map(BeatmapNote::toProto) - .toList()) - .build(); - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - @Builder(builderMethodName = "of") - @Entity - public static class BeatmapNote { - int startTime; - int endTime; - - public static BeatmapNote parse(UgcMusicNoteOuterClass.UgcMusicNote note) { - return BeatmapNote.of() - .startTime(note.getStartTime()) - .endTime(note.getEndTime()) - .build(); - } - - public UgcMusicNoteOuterClass.UgcMusicNote toProto() { - return UgcMusicNoteOuterClass.UgcMusicNote.newBuilder() - .setStartTime(startTime) - .setEndTime(endTime) - .build(); - } - } -} +package emu.grasscutter.game.activity.musicgame; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.net.proto.UgcMusicBriefInfoOuterClass; +import emu.grasscutter.net.proto.UgcMusicNoteOuterClass; +import emu.grasscutter.net.proto.UgcMusicRecordOuterClass; +import emu.grasscutter.net.proto.UgcMusicTrackOuterClass; +import java.util.List; +import java.util.Random; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity("music_game_beatmaps") +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class MusicGameBeatmap { + + @Id long musicShareId; + int authorUid; + int musicId; + int musicNoteCount; + int savePosition; + int maxScore; + int createTime; + + List> beatmap; + + public static MusicGameBeatmap getByShareId(long musicShareId) { + return DatabaseHelper.getMusicGameBeatmap(musicShareId); + } + + public static List> parse( + List beatmapItemListList) { + return beatmapItemListList.stream() + .map(item -> item.getMusicNoteListList().stream().map(BeatmapNote::parse).toList()) + .toList(); + } + + public void save() { + if (musicShareId == 0) { + musicShareId = new Random().nextLong(100000000000000L, 999999999999999L); + } + DatabaseHelper.saveMusicGameBeatmap(this); + } + + public UgcMusicRecordOuterClass.UgcMusicRecord toProto() { + return UgcMusicRecordOuterClass.UgcMusicRecord.newBuilder() + .setMusicId(musicId) + .addAllMusicTrackList(beatmap.stream().map(this::musicBeatmapListToProto).toList()) + .build(); + } + + public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toBriefProto() { + var player = DatabaseHelper.getPlayerByUid(authorUid); + + return UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.newBuilder() + .setMusicId(musicId) + // .setMusicNoteCount(musicNoteCount) + .setUgcGuid(musicShareId) + .setMaxScore(maxScore) + // .setShareTime(createTime) + .setCreatorNickname(player.getNickname()) + .setVersion(1); + } + + private UgcMusicTrackOuterClass.UgcMusicTrack musicBeatmapListToProto( + List beatmapNoteList) { + return UgcMusicTrackOuterClass.UgcMusicTrack.newBuilder() + .addAllMusicNoteList(beatmapNoteList.stream().map(BeatmapNote::toProto).toList()) + .build(); + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + @Builder(builderMethodName = "of") + @Entity + public static class BeatmapNote { + int startTime; + int endTime; + + public static BeatmapNote parse(UgcMusicNoteOuterClass.UgcMusicNote note) { + return BeatmapNote.of().startTime(note.getStartTime()).endTime(note.getEndTime()).build(); + } + + public UgcMusicNoteOuterClass.UgcMusicNote toProto() { + return UgcMusicNoteOuterClass.UgcMusicNote.newBuilder() + .setStartTime(startTime) + .setEndTime(endTime) + .build(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGamePlayerData.java b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGamePlayerData.java index 1d454b88e..3ae062230 100644 --- a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGamePlayerData.java +++ b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGamePlayerData.java @@ -1,87 +1,86 @@ -package emu.grasscutter.game.activity.musicgame; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.MusicGameBasicData; -import emu.grasscutter.net.proto.MusicGameRecordOuterClass; -import emu.grasscutter.net.proto.UgcMusicBriefInfoOuterClass; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class MusicGamePlayerData { - Map musicGameRecord; - Map personalCustomBeatmapRecord; - Map othersCustomBeatmapRecord; - - public static MusicGamePlayerData create() { - return MusicGamePlayerData.of() - .musicGameRecord(GameData.getMusicGameBasicDataMap().values().stream() - .collect(Collectors.toMap(MusicGameBasicData::getId, MusicGamePlayerData.MusicGameRecord::create))) - .personalCustomBeatmapRecord(new HashMap<>()) - .othersCustomBeatmapRecord(new HashMap<>()) - .build(); - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - @Builder(builderMethodName = "of") - public static class MusicGameRecord { - int musicId; - int maxCombo; - int maxScore; - - public static MusicGameRecord create(MusicGameBasicData musicGameBasicData) { - return MusicGameRecord.of() - .musicId(musicGameBasicData.getId()) - .build(); - } - - public MusicGameRecordOuterClass.MusicGameRecord toProto() { - return MusicGameRecordOuterClass.MusicGameRecord.newBuilder() - .setIsUnlock(true) - .setMaxCombo(maxCombo) - .setMaxScore(maxScore) - .build(); - } - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - @Builder(builderMethodName = "of") - public static class CustomBeatmapRecord { - long musicShareId; - int score; - boolean settle; - - public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toPersonalBriefProto() { - var musicGameBeatmap = MusicGameBeatmap.getByShareId(musicShareId); - - return UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.newBuilder() -// .setCanShare(true) -// .setCreateTime(musicGameBeatmap.getCreateTime()) - .setMusicId(musicGameBeatmap.getMusicId()) - .setMaxScore(musicGameBeatmap.getMaxScore()) -// .setPosition(musicGameBeatmap.getSavePosition()) -// .setMusicNoteCount(musicGameBeatmap.getMusicNoteCount()) - .setUgcGuid(musicShareId); - } - - public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toOthersBriefProto() { - var musicGameBeatmap = MusicGameBeatmap.getByShareId(musicShareId); - - return musicGameBeatmap.toBriefProto() -// .setScore(score) -// .setSettle(settle) - ; - } - - } -} +package emu.grasscutter.game.activity.musicgame; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.MusicGameBasicData; +import emu.grasscutter.net.proto.MusicGameRecordOuterClass; +import emu.grasscutter.net.proto.UgcMusicBriefInfoOuterClass; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class MusicGamePlayerData { + Map musicGameRecord; + Map personalCustomBeatmapRecord; + Map othersCustomBeatmapRecord; + + public static MusicGamePlayerData create() { + return MusicGamePlayerData.of() + .musicGameRecord( + GameData.getMusicGameBasicDataMap().values().stream() + .collect( + Collectors.toMap( + MusicGameBasicData::getId, MusicGamePlayerData.MusicGameRecord::create))) + .personalCustomBeatmapRecord(new HashMap<>()) + .othersCustomBeatmapRecord(new HashMap<>()) + .build(); + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + @Builder(builderMethodName = "of") + public static class MusicGameRecord { + int musicId; + int maxCombo; + int maxScore; + + public static MusicGameRecord create(MusicGameBasicData musicGameBasicData) { + return MusicGameRecord.of().musicId(musicGameBasicData.getId()).build(); + } + + public MusicGameRecordOuterClass.MusicGameRecord toProto() { + return MusicGameRecordOuterClass.MusicGameRecord.newBuilder() + .setIsUnlock(true) + .setMaxCombo(maxCombo) + .setMaxScore(maxScore) + .build(); + } + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + @Builder(builderMethodName = "of") + public static class CustomBeatmapRecord { + long musicShareId; + int score; + boolean settle; + + public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toPersonalBriefProto() { + var musicGameBeatmap = MusicGameBeatmap.getByShareId(musicShareId); + + return UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.newBuilder() + // .setCanShare(true) + // .setCreateTime(musicGameBeatmap.getCreateTime()) + .setMusicId(musicGameBeatmap.getMusicId()) + .setMaxScore(musicGameBeatmap.getMaxScore()) + // .setPosition(musicGameBeatmap.getSavePosition()) + // .setMusicNoteCount(musicGameBeatmap.getMusicNoteCount()) + .setUgcGuid(musicShareId); + } + + public UgcMusicBriefInfoOuterClass.UgcMusicBriefInfo.Builder toOthersBriefProto() { + var musicGameBeatmap = MusicGameBeatmap.getByShareId(musicShareId); + + return musicGameBeatmap.toBriefProto() + // .setScore(score) + // .setSettle(settle) + ; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameScoreTrigger.java b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameScoreTrigger.java index fcf4a4edf..350eb40f2 100644 --- a/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameScoreTrigger.java +++ b/src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameScoreTrigger.java @@ -1,23 +1,23 @@ -package emu.grasscutter.game.activity.musicgame; - -import emu.grasscutter.game.activity.ActivityWatcher; -import emu.grasscutter.game.activity.ActivityWatcherType; -import emu.grasscutter.game.props.WatcherTriggerType; - -@ActivityWatcherType(WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE) -public class MusicGameScoreTrigger extends ActivityWatcher { - @Override - protected boolean isMeet(String... param) { - if (param.length != 2) { - return false; - } - var paramList = getActivityWatcherData().getTriggerConfig().getParamList(); - if (!paramList.get(0).equals(param[0])) { - return false; - } - - var score = Integer.parseInt(param[1]); - var target = Integer.parseInt(paramList.get(1)); - return score >= target; - } -} +package emu.grasscutter.game.activity.musicgame; + +import emu.grasscutter.game.activity.ActivityWatcher; +import emu.grasscutter.game.activity.ActivityWatcherType; +import emu.grasscutter.game.props.WatcherTriggerType; + +@ActivityWatcherType(WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE) +public class MusicGameScoreTrigger extends ActivityWatcher { + @Override + protected boolean isMeet(String... param) { + if (param.length != 2) { + return false; + } + var paramList = getActivityWatcherData().getTriggerConfig().getParamList(); + if (!paramList.get(0).equals(param[0])) { + return false; + } + + var score = Integer.parseInt(param[1]); + var target = Integer.parseInt(paramList.get(1)); + return score >= target; + } +} diff --git a/src/main/java/emu/grasscutter/game/avatar/Avatar.java b/src/main/java/emu/grasscutter/game/avatar/Avatar.java index 3db674b6c..bfe84a0ed 100644 --- a/src/main/java/emu/grasscutter/game/avatar/Avatar.java +++ b/src/main/java/emu/grasscutter/game/avatar/Avatar.java @@ -1,968 +1,1011 @@ -package emu.grasscutter.game.avatar; - -import dev.morphia.annotations.*; -import emu.grasscutter.GameConstants; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.OpenConfigEntry; -import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier; -import emu.grasscutter.data.common.FightPropData; -import emu.grasscutter.data.excels.*; -import emu.grasscutter.data.excels.AvatarSkillDepotData.InherentProudSkillOpens; -import emu.grasscutter.data.excels.ItemData.WeaponProperty; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.inventory.EquipType; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.*; -import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; -import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo; -import emu.grasscutter.net.proto.AvatarSkillInfoOuterClass.AvatarSkillInfo; -import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData; -import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass; -import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo; -import emu.grasscutter.net.proto.ShowEquipOuterClass.ShowEquip; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.*; -import lombok.Getter; -import lombok.Setter; -import lombok.val; -import org.bson.types.ObjectId; - -import java.util.*; -import java.util.stream.Stream; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -@Entity(value = "avatars", useDiscriminator = false) -public class Avatar { - @Transient - @Getter - private final Int2ObjectMap equips; - @Transient - @Getter - private final Int2FloatOpenHashMap fightProperties; - @Transient - @Getter - private final Int2FloatOpenHashMap fightPropOverrides; - @Id - private ObjectId id; - @Indexed - @Getter - private int ownerId; // Id of player that this avatar belongs to - @Transient - private Player owner; - @Transient - @Getter - private AvatarData data; - @Transient - @Getter - private AvatarSkillDepotData skillDepot; - @Transient - @Getter - private long guid; // Player unique id - @Getter - private int avatarId; // Id of avatar - @Getter - @Setter - private int level = 1; - @Getter - @Setter - private int exp; - @Getter - @Setter - private int promoteLevel; - @Getter - @Setter - private int satiation; // Fullness - @Getter - @Setter - private int satiationPenalty; // When eating too much - @Getter - @Setter - private float currentHp; - private float currentEnergy; - @Transient - @Getter - private Set extraAbilityEmbryos; - - private List fetters; - - private final Map skillLevelMap = new Int2IntArrayMap(7); // Talent levels - @Transient - @Getter - private final Map skillExtraChargeMap = new Int2IntArrayMap(2); // Charges - @Transient - private final Map proudSkillBonusMap = new Int2IntArrayMap(2); // Talent bonus levels (from const) - @Getter - private int skillDepotId; - private Set talentIdList; // Constellation id list - @Getter - private Set proudSkillList; // Character passives - - @Getter - @Setter - private int flyCloak; - @Getter - @Setter - private int costume; - @Getter - private int bornTime; - - @Getter - @Setter - private int fetterLevel = 1; - @Getter - @Setter - private int fetterExp; - - @Getter - @Setter - private int nameCardRewardId; - @Getter - @Setter - private int nameCardId; - - @Deprecated // Do not use. Morhpia only! - public Avatar() { - this.equips = new Int2ObjectOpenHashMap<>(); - this.fightProperties = new Int2FloatOpenHashMap(); - this.fightPropOverrides = new Int2FloatOpenHashMap(); - this.extraAbilityEmbryos = new HashSet<>(); - this.fetters = new ArrayList<>(); // TODO Move to avatar - } - - // On creation - public Avatar(int avatarId) { - this(GameData.getAvatarDataMap().get(avatarId)); - } - - public Avatar(AvatarData data) { - this(); - this.avatarId = data.getId(); - this.nameCardRewardId = data.getNameCardRewardId(); - this.nameCardId = data.getNameCardId(); - this.data = data; - this.bornTime = (int) (System.currentTimeMillis() / 1000); - this.flyCloak = 140001; - - this.talentIdList = new HashSet<>(); - this.proudSkillList = new HashSet<>(); - - // Combat properties - Stream.of(FightProperty.values()) - .map(FightProperty::getId) - .filter(id -> (id > 0) && (id < 3000)) - .forEach(id -> this.setFightProperty(id, 0f)); - - // Skill depot - this.setSkillDepotData(switch (this.avatarId) { - case GameConstants.MAIN_CHARACTER_MALE -> - GameData.getAvatarSkillDepotDataMap().get(504); // Hack to start with anemo skills - case GameConstants.MAIN_CHARACTER_FEMALE -> GameData.getAvatarSkillDepotDataMap().get(704); - default -> data.getSkillDepot(); - }); - - // Set stats - this.recalcStats(); - this.currentHp = getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.currentHp); - this.currentEnergy = 0f; - // Load handler - this.onLoad(); - } - - static public int getMinPromoteLevel(int level) { - if (level > 80) { - return 6; - } else if (level > 70) { - return 5; - } else if (level > 60) { - return 4; - } else if (level > 50) { - return 3; - } else if (level > 40) { - return 2; - } else if (level > 20) { - return 1; - } - return 0; - } - - public Player getPlayer() { - return this.owner; - } - - public ObjectId getObjectId() { - return id; - } - - public AvatarData getAvatarData() { - return data; - } - - protected void setAvatarData(AvatarData data) { - if (this.data != null) return; - this.data = data; // Used while loading this from the database - } - - public void setOwner(Player player) { - this.owner = player; - this.ownerId = player.getUid(); - this.guid = player.getNextGameGuid(); - } - - public boolean addSatiation(int value) { - if (this.satiation >= 10000) return false; - this.satiation += value; - return true; - } - - public float reduceSatiation(int value) { - if (this.satiation == 0) return 0; - this.satiation -= value; - if (this.satiation < 0) { - this.satiation = 0; - } - return this.satiation; - } - - public float reduceSatiationPenalty(int value) { - if (this.satiationPenalty == 0) return 0; - this.satiationPenalty -= value; - if (this.satiationPenalty < 0) { - this.satiationPenalty = 0; - } - return this.satiationPenalty; - } - - public GameItem getEquipBySlot(EquipType slot) { - return this.getEquips().get(slot.getValue()); - } - - private GameItem getEquipBySlot(int slotId) { - return this.getEquips().get(slotId); - } - - public GameItem getWeapon() { - return this.getEquipBySlot(EquipType.EQUIP_WEAPON); - } - - protected void setSkillDepot(AvatarSkillDepotData skillDepot) { - if (this.skillDepot != null) return; - this.skillDepot = skillDepot; // Used while loading this from the database - } - - public void setSkillDepotData(AvatarSkillDepotData skillDepot) { - // Set id and depot - this.skillDepotId = skillDepot.getId(); - this.skillDepot = skillDepot; - // Add any missing skills - this.skillDepot.getSkillsAndEnergySkill() - .forEach(skillId -> this.skillLevelMap.putIfAbsent(skillId, 1)); - // Add proud skills - this.proudSkillList.clear(); - skillDepot.getInherentProudSkillOpens().stream() - .filter(openData -> openData.getProudSkillGroupId() > 0) - .filter(openData -> openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) - .mapToInt(openData -> (openData.getProudSkillGroupId() * 100) + 1) - .filter(proudSkillId -> GameData.getProudSkillDataMap().containsKey(proudSkillId)) - .forEach(proudSkillId -> this.proudSkillList.add(proudSkillId)); - this.recalcStats(); - } - - public List getFetterList() { - return fetters; - } - - public void setFetterList(List fetterList) { - this.fetters = fetterList; - } - - public void setCurrentEnergy() { - if (GAME_OPTIONS.energyUsage) { - this.setCurrentEnergy(this.currentEnergy); - } - } - - public void setCurrentEnergy(float currentEnergy) { - var depot = this.skillDepot; - if (depot != null && depot.getEnergySkillData() != null) { - ElementType element = depot.getElementType(); - var maxEnergy = depot.getEnergySkillData().getCostElemVal(); - this.setFightProperty(element.getMaxEnergyProp(), maxEnergy); - this.setFightProperty(element.getCurEnergyProp(), GAME_OPTIONS.energyUsage ? currentEnergy : maxEnergy); - } - } - - public void setCurrentEnergy(FightProperty curEnergyProp, float currentEnergy) { - if (GAME_OPTIONS.energyUsage) { - this.setFightProperty(curEnergyProp, currentEnergy); - this.currentEnergy = currentEnergy; - this.save(); - } - } - - public void setFightProperty(FightProperty prop, float value) { - this.getFightProperties().put(prop.getId(), value); - } - - private void setFightProperty(int id, float value) { - this.getFightProperties().put(id, value); - } - - public void addFightProperty(FightProperty prop, float value) { - this.getFightProperties().put(prop.getId(), getFightProperty(prop) + value); - } - - public float getFightProperty(FightProperty prop) { - return getFightProperties().getOrDefault(prop.getId(), 0f); - } - - public Map getSkillLevelMap() { // Returns a copy of the skill levels for the current skillDepot. - var map = new Int2IntOpenHashMap(); - this.skillDepot.getSkillsAndEnergySkill().forEach(skillId -> - map.put(skillId, this.skillLevelMap.putIfAbsent(skillId, 1).intValue())); - return map; - } - - // Returns a copy of the skill bonus levels for the current skillDepot, capped to avoid invalid levels. - public Map getProudSkillBonusMap() { - var map = new Int2IntArrayMap(); - this.skillDepot.getSkillsAndEnergySkill().forEach(skillId -> { - val skillData = GameData.getAvatarSkillDataMap().get(skillId); - if (skillData == null) return; - int proudSkillGroupId = skillData.getProudSkillGroupId(); - int bonus = this.proudSkillBonusMap.getOrDefault(proudSkillGroupId, 0); - int maxLevel = GameData.getProudSkillGroupMaxLevel(proudSkillGroupId); - int curLevel = this.skillLevelMap.getOrDefault(skillId, 0); - if (maxLevel > 0) { - bonus = Math.min(bonus, maxLevel - curLevel); - } - map.put(proudSkillGroupId, bonus); - }); - return map; - } - - public IntSet getTalentIdList() { // Returns a copy of the unlocked constellations for the current skillDepot. - var talents = new IntOpenHashSet(this.getSkillDepot().getTalents()); - talents.removeIf(id -> !this.talentIdList.contains(id)); - return talents; - } - - public int getCoreProudSkillLevel() { - var lockedTalents = new IntOpenHashSet(this.getSkillDepot().getTalents()); - lockedTalents.removeAll(this.getTalentIdList()); - // One below the lowest locked talent, or 6 if there are no locked talents. - return lockedTalents.intStream().map(i -> i % 10).min().orElse(7) - 1; - } - - public boolean equipItem(GameItem item, boolean shouldRecalc) { - // Sanity check equip type - EquipType itemEquipType = item.getItemData().getEquipType(); - if (itemEquipType == EquipType.EQUIP_NONE) { - return false; - } - - // Check if other avatars have this item equipped - Avatar otherAvatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter()); - if (otherAvatar != null) { - // Unequip other avatar's item - if (otherAvatar.unequipItem(item.getItemData().getEquipType())) { - getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(otherAvatar, item.getItemData().getEquipType())); - } - // Swap with other avatar - if (getEquips().containsKey(itemEquipType.getValue())) { - GameItem toSwap = this.getEquipBySlot(itemEquipType); - otherAvatar.equipItem(toSwap, false); - } - // Recalc - otherAvatar.recalcStats(); - } else if (getEquips().containsKey(itemEquipType.getValue())) { - // Unequip item in current slot if it exists - unequipItem(itemEquipType); - } - - // Set equip - getEquips().put(itemEquipType.getValue(), item); - - if (itemEquipType == EquipType.EQUIP_WEAPON && getPlayer().getWorld() != null) { - item.setWeaponEntityId(this.getPlayer().getWorld().getNextEntityId(EntityIdType.WEAPON)); - } - - item.setEquipCharacter(this.getAvatarId()); - item.save(); - - if (this.getPlayer().hasSentLoginPackets()) { - this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item)); - } - - if (shouldRecalc) { - this.recalcStats(); - } - - return true; - } - - public boolean unequipItem(EquipType slot) { - GameItem item = getEquips().remove(slot.getValue()); - - if (item != null) { - item.setEquipCharacter(0); - item.save(); - return true; - } - - return false; - } - - public void recalcStats() { - recalcStats(false); - } - - public void recalcStats(boolean forceSendAbilityChange) { - // Setup - var data = this.getAvatarData(); - var promoteData = GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel()); - var setMap = new Int2IntOpenHashMap(); - - // Extra ability embryos - Set prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos(); - this.extraAbilityEmbryos = new HashSet<>(); - - // Fetters - this.setFetterList(data.getFetters()); - this.setNameCardRewardId(data.getNameCardRewardId()); - this.setNameCardId(data.getNameCardId()); - - // Get hp percent, set to 100% if none - float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - - // Store current energy value for later - float currentEnergy = (this.getSkillDepot() != null) ? this.getFightProperty(this.getSkillDepot().getElementType().getCurEnergyProp()) : 0f; - - // Clear properties - this.getFightProperties().clear(); - - // Base stats - this.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, data.getBaseHp(this.getLevel())); - this.setFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, data.getBaseAttack(this.getLevel())); - this.setFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE, data.getBaseDefense(this.getLevel())); - this.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL, data.getBaseCritical()); - this.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL_HURT, data.getBaseCriticalHurt()); - this.setFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 1f); - - if (promoteData != null) { - for (FightPropData fightPropData : promoteData.getAddProps()) { - this.addFightProperty(fightPropData.getProp(), fightPropData.getValue()); - } - } - - // Set energy usage - setCurrentEnergy(currentEnergy); - - // Artifacts - for (int slotId = 1; slotId <= 5; slotId++) { - // Get artifact - GameItem equip = this.getEquipBySlot(slotId); - if (equip == null) { - continue; - } - // Artifact main stat - ReliquaryMainPropData mainPropData = GameData.getReliquaryMainPropDataMap().get(equip.getMainPropId()); - if (mainPropData != null) { - ReliquaryLevelData levelData = GameData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel()); - if (levelData != null) { - this.addFightProperty(mainPropData.getFightProp(), levelData.getPropValue(mainPropData.getFightProp())); - } - } - // Artifact sub stats - for (int appendPropId : equip.getAppendPropIdList()) { - ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId); - if (affixData != null) { - this.addFightProperty(affixData.getFightProp(), affixData.getPropValue()); - } - } - // Set bonus - if (equip.getItemData().getSetId() > 0) { - setMap.addTo(equip.getItemData().getSetId(), 1); - } - } - - // Set stuff - setMap.forEach((setId, amount) -> { - ReliquarySetData setData = GameData.getReliquarySetDataMap().get((int) setId); - if (setData == null) return; - - // Calculate how many items are from the set - // Add affix data from set bonus - val setNeedNum = setData.getSetNeedNum(); - for (int setIndex = 0; setIndex < setNeedNum.length; setIndex++) { - if (amount < setNeedNum[setIndex]) break; - - int affixId = (setData.getEquipAffixId() * 10) + setIndex; - EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId); - if (affix == null) { - continue; - } - - // Add properties from this affix to our avatar - for (FightPropData prop : affix.getAddProps()) { - this.addFightProperty(prop.getProp(), prop.getValue()); - } - - // Add any skill strings from this affix - this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true); - } - }); - - // Weapon - GameItem weapon = this.getWeapon(); - if (weapon != null) { - // Add stats - WeaponCurveData curveData = GameData.getWeaponCurveDataMap().get(weapon.getLevel()); - if (curveData != null) { - for (WeaponProperty weaponProperty : weapon.getItemData().getWeaponProperties()) { - this.addFightProperty(weaponProperty.getPropType(), weaponProperty.getInitValue() * curveData.getMultByProp(weaponProperty.getType())); - } - } - // Weapon promotion stats - WeaponPromoteData wepPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); - if (wepPromoteData != null) { - for (FightPropData prop : wepPromoteData.getAddProps()) { - if (prop.getValue() == 0f || prop.getProp() == null) { - continue; - } - this.addFightProperty(prop.getProp(), prop.getValue()); - } - } - // Add weapon skill from affixes - if (weapon.getAffixes() != null && weapon.getAffixes().size() > 0) { - // Weapons usually dont have more than one affix but just in case... - for (int af : weapon.getAffixes()) { - if (af == 0) { - continue; - } - // Calculate affix id - int affixId = (af * 10) + weapon.getRefinement(); - EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId); - if (affix == null) { - continue; - } - - // Add properties from this affix to our avatar - for (FightPropData prop : affix.getAddProps()) { - this.addFightProperty(prop.getProp(), prop.getValue()); - } - - // Add any skill strings from this affix - this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true); - } - } - } - - // Add proud skills and unlock them if needed - AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getSkillDepotId()); - this.getProudSkillList().clear(); - for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) { - if (openData.getProudSkillGroupId() == 0) { - continue; - } - if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) { - int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; - if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) { - this.getProudSkillList().add(proudSkillId); - } - } - } - - // Proud skills - for (int proudSkillId : this.getProudSkillList()) { - ProudSkillData proudSkillData = GameData.getProudSkillDataMap().get(proudSkillId); - if (proudSkillData == null) { - continue; - } - - // Add properties from this proud skill to our avatar - for (FightPropData prop : proudSkillData.getAddProps()) { - this.addFightProperty(prop.getProp(), prop.getValue()); - } - - // Add any embryos from this proud skill - this.addToExtraAbilityEmbryos(proudSkillData.getOpenConfig()); - } - - // Constellations - this.getTalentIdList().intStream() - .mapToObj(GameData.getAvatarTalentDataMap()::get) - .filter(Objects::nonNull) - .map(AvatarTalentData::getOpenConfig) - .filter(Objects::nonNull) - .forEach(this::addToExtraAbilityEmbryos); - // Add any skill strings from this constellation - - // Set % stats - FightProperty.forEachCompoundProperty(c -> this.setFightProperty(c.getResult(), - this.getFightProperty(c.getFlat()) + (this.getFightProperty(c.getBase()) * (1f + this.getFightProperty(c.getPercent()))))); - - // Reapply all overrides - this.fightProperties.putAll(this.fightPropOverrides); - - // Set current hp - this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent); - - // Packet - if (getPlayer() != null && getPlayer().hasSentLoginPackets()) { - // Update stats for client - getPlayer().sendPacket(new PacketAvatarFightPropNotify(this)); - // Update client abilities - EntityAvatar entity = this.getAsEntity(); - if (entity != null && (!this.getExtraAbilityEmbryos().equals(prevExtraAbilityEmbryos) || forceSendAbilityChange)) { - getPlayer().sendPacket(new PacketAbilityChangeNotify(entity)); - } - } - } - - public void addToExtraAbilityEmbryos(String openConfig) { - this.addToExtraAbilityEmbryos(openConfig, false); - } - - public void addToExtraAbilityEmbryos(String openConfig, boolean forceAdd) { - if (openConfig == null || openConfig.length() == 0) { - return; - } - - OpenConfigEntry entry = GameData.getOpenConfigEntries().get(openConfig); - if (entry == null) { - if (forceAdd) { - // Add config string to ability skill list anyways - this.getExtraAbilityEmbryos().add(openConfig); - } - return; - } - - if (entry.getAddAbilities() != null) { - for (String ability : entry.getAddAbilities()) { - this.getExtraAbilityEmbryos().add(ability); - } - } - } - - public void calcConstellation(OpenConfigEntry entry, boolean notifyClient) { - if (entry == null) return; - if (this.getPlayer() == null) - notifyClient = false; - - // Check if new constellation adds +3 to a skill level - if (this.calcConstellationExtraLevels(entry) && notifyClient) { - // Packet - this.getPlayer().sendPacket(new PacketProudSkillExtraLevelNotify(this, entry.getExtraTalentIndex())); - } - // Check if new constellation adds skill charges - if (this.calcConstellationExtraCharges(entry) && notifyClient) { - // Packet - Stream.of(entry.getSkillPointModifiers()) - .mapToInt(SkillPointModifier::getSkillId) - .forEach(skillId -> { - this.getPlayer().sendPacket( - new PacketAvatarSkillMaxChargeCountNotify(this, skillId, this.getSkillExtraChargeMap().getOrDefault(skillId, 0)) - ); - }); - } - } - - public void recalcConstellations() { - // Clear first - this.proudSkillBonusMap.clear(); - this.skillExtraChargeMap.clear(); - - // Sanity checks - if (this.data == null || this.skillDepot == null) { - return; - } - - this.getTalentIdList().intStream() - .mapToObj(GameData.getAvatarTalentDataMap()::get) - .filter(Objects::nonNull) - .map(AvatarTalentData::getOpenConfig) - .filter(Objects::nonNull) - .filter(openConfig -> openConfig.length() > 0) - .map(GameData.getOpenConfigEntries()::get) - .filter(Objects::nonNull) - .forEach(e -> this.calcConstellation(e, false)); - } - - private boolean calcConstellationExtraCharges(OpenConfigEntry entry) { - var skillPointModifiers = entry.getSkillPointModifiers(); - if (skillPointModifiers == null) return false; - - for (var mod : skillPointModifiers) { - AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(mod.getSkillId()); - - if (skillData == null) continue; - - int charges = skillData.getMaxChargeNum() + mod.getDelta(); - - this.getSkillExtraChargeMap().put(mod.getSkillId(), charges); - } - return true; - } - - private boolean calcConstellationExtraLevels(OpenConfigEntry entry) { - int skillId = switch (entry.getExtraTalentIndex()) { - case 9 -> this.skillDepot.getEnergySkill(); // Ult skill - case 2 -> (this.skillDepot.getSkills().size() >= 2) ? this.skillDepot.getSkills().get(1) : 0; // E skill - default -> 0; - }; - // Sanity check - if (skillId == 0) { - return false; - } - - // Get proud skill group id - AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId); - - if (skillData == null) { - return false; - } - - // Add to bonus list - this.addProudSkillLevelBonus(skillData.getProudSkillGroupId(), 3); - return true; - } - - private int addProudSkillLevelBonus(int proudSkillGroupId, int bonus) { - return this.proudSkillBonusMap.compute(proudSkillGroupId, (k, v) -> (v == null) ? bonus : v + bonus); - } - - public boolean upgradeSkill(int skillId) { - AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId); - if (skillData == null) return false; - - // Get data for next skill level - int newLevel = this.skillLevelMap.getOrDefault(skillId, 0) + 1; - if (newLevel > 10) return false; - - // Proud skill data - int proudSkillId = (skillData.getProudSkillGroupId() * 100) + newLevel; - ProudSkillData proudSkill = GameData.getProudSkillDataMap().get(proudSkillId); - if (proudSkill == null) return false; - - // Make sure break level is correct - if (this.getPromoteLevel() < proudSkill.getBreakLevel()) return false; - - // Pay materials and mora if possible - if (!this.getPlayer().getInventory().payItems(proudSkill.getTotalCostItems())) return false; - - // Upgrade skill - this.setSkillLevel(skillId, newLevel); - return true; - } - - public boolean setSkillLevel(int skillId, int level) { - if (level < 0 || level > 15) return false; - var validLevels = GameData.getAvatarSkillLevels(skillId); - if (validLevels != null && !validLevels.contains(level)) return false; - int oldLevel = this.skillLevelMap.getOrDefault(skillId, 0); // just taking the return value of put would have null concerns - this.skillLevelMap.put(skillId, level); - this.save(); - - // Packet - val player = this.getPlayer(); - if (player != null) { - player.sendPacket(new PacketAvatarSkillChangeNotify(this, skillId, oldLevel, level)); - player.sendPacket(new PacketAvatarSkillUpgradeRsp(this, skillId, oldLevel, level)); - } - return true; - } - - public boolean unlockConstellation() { - return this.unlockConstellation(false); - } - - public boolean unlockConstellation(boolean skipPayment) { - int currentTalentLevel = this.getCoreProudSkillLevel(); - int talentId = this.skillDepot.getTalents().get(currentTalentLevel); - return this.unlockConstellation(talentId, skipPayment); - } - - public boolean unlockConstellation(int talentId) { - return unlockConstellation(talentId, false); - } - - public boolean unlockConstellation(int talentId, boolean skipPayment) { - // Get talent - AvatarTalentData talentData = GameData.getAvatarTalentDataMap().get(talentId); - if (talentData == null) return false; - var player = this.getPlayer(); - - // Pay constellation item if possible - if (!skipPayment && (player != null) && !player.getInventory().payItem(talentData.getMainCostItemId(), 1)) { - return false; - } - - // Apply + recalc - this.talentIdList.add(talentData.getId()); - - // Packet - if (player != null) { - player.sendPacket(new PacketAvatarUnlockTalentNotify(this, talentId)); - player.sendPacket(new PacketUnlockAvatarTalentRsp(this, talentId)); - } - - // Proud skill bonus map (Extra skills) - this.calcConstellation(GameData.getOpenConfigEntries().get(talentData.getOpenConfig()), true); - - // Recalc + save avatar - this.recalcStats(true); - this.save(); - return true; - } - - public void forceConstellationLevel(int level) { - if (level > 6) return; // Sanity check - - if (level < 0) { // Special case for resetConst to remove inactive depots too - this.talentIdList.clear(); - this.recalcStats(); - this.save(); - return; - } - this.talentIdList.removeAll(this.getTalentIdList()); // Only remove constellations from active depot - for (int i = 0; i < level; i++) - this.unlockConstellation(true); - this.recalcStats(); - this.save(); - } - - public boolean sendSkillExtraChargeMap() { - val map = this.getSkillExtraChargeMap(); - if (map.isEmpty()) return false; - this.getPlayer().sendPacket(new PacketAvatarSkillInfoNotify(this.guid, new Int2IntArrayMap(map))); // TODO: Remove this allocation when updating interfaces to FastUtils later - return true; - } - - public EntityAvatar getAsEntity() { - for (EntityAvatar entity : getPlayer().getTeamManager().getActiveTeam()) { - if (entity.getAvatar() == this) { - return entity; - } - } - return null; - } - - public int getEntityId() { - EntityAvatar entity = getAsEntity(); - return entity != null ? entity.getId() : 0; - } - - public void save() { - DatabaseHelper.saveAvatar(this); - } - - public AvatarInfo toProto() { - int fetterLevel = this.getFetterLevel(); - AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder() - .setExpLevel(fetterLevel); - - if (fetterLevel != 10) { - avatarFetter.setExpNumber(this.getFetterExp()); - } - - - if (this.fetters != null) { - this.fetters.forEach(fetterId -> avatarFetter.addFetterList( - FetterData.newBuilder() - .setFetterId(fetterId) - .setFetterState(FetterState.FINISH.getValue()))); - } - - int cardId = this.getNameCardId(); - - if (this.getPlayer().getNameCardList().contains(cardId)) { - avatarFetter.addRewardedFetterLevelList(10); - } - - AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder() - .setAvatarId(this.getAvatarId()) - .setGuid(this.getGuid()) - .setLifeState(1) - .addAllTalentIdList(this.getTalentIdList()) - .putAllFightPropMap(this.getFightProperties()) - .setSkillDepotId(this.getSkillDepotId()) - .setCoreProudSkillLevel(this.getCoreProudSkillLevel()) - .putAllSkillLevelMap(this.getSkillLevelMap()) - .addAllInherentProudSkillList(this.getProudSkillList()) - .putAllProudSkillExtraLevelMap(this.getProudSkillBonusMap()) - .setAvatarType(1) - .setBornTime(this.getBornTime()) - .setFetterInfo(avatarFetter) - .setWearingFlycloakId(this.getFlyCloak()) - .setCostumeId(this.getCostume()); - - this.getSkillExtraChargeMap().forEach((skillId, count) -> - avatarInfo.putSkillMap(skillId, AvatarSkillInfo.newBuilder().setMaxChargeCount(count).build())); - - this.getEquips().forEach((k, item) -> avatarInfo.addEquipGuidList(item.getGuid())); - - avatarInfo.putPropMap(PlayerProperty.PROP_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel())); - avatarInfo.putPropMap(PlayerProperty.PROP_EXP.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_EXP, this.getExp())); - avatarInfo.putPropMap(PlayerProperty.PROP_BREAK_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_BREAK_LEVEL, this.getPromoteLevel())); - avatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_VAL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiation())); - avatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_PENALTY_TIME, this.getSatiationPenalty())); - - return avatarInfo.build(); - } - - // used only in character showcase - public ShowAvatarInfo toShowAvatarInfoProto() { - AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder() - .setExpLevel(this.getFetterLevel()); - - ShowAvatarInfo.Builder showAvatarInfo = ShowAvatarInfoOuterClass.ShowAvatarInfo.newBuilder() - .setAvatarId(avatarId) - .addAllTalentIdList(this.getTalentIdList()) - .putAllFightPropMap(this.getFightProperties()) - .setSkillDepotId(this.getSkillDepotId()) - .setCoreProudSkillLevel(this.getCoreProudSkillLevel()) - .addAllInherentProudSkillList(this.getProudSkillList()) - .putAllSkillLevelMap(this.getSkillLevelMap()) - .putAllProudSkillExtraLevelMap(this.getProudSkillBonusMap()) - .setFetterInfo(avatarFetter) - .setCostumeId(this.getCostume()); - - showAvatarInfo.putPropMap(PlayerProperty.PROP_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel())); - showAvatarInfo.putPropMap(PlayerProperty.PROP_EXP.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_EXP, this.getExp())); - showAvatarInfo.putPropMap(PlayerProperty.PROP_BREAK_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_BREAK_LEVEL, this.getPromoteLevel())); - showAvatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_VAL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiation())); - showAvatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_PENALTY_TIME, this.getSatiationPenalty())); - int maxStamina = this.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA); - showAvatarInfo.putPropMap(PlayerProperty.PROP_MAX_STAMINA.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_MAX_STAMINA, maxStamina)); - - for (GameItem item : this.getEquips().values()) { - if (item.getItemType() == ItemType.ITEM_RELIQUARY) { - showAvatarInfo.addEquipList(ShowEquip.newBuilder() - .setItemId(item.getItemId()) - .setReliquary(item.toReliquaryProto())); - } else if (item.getItemType() == ItemType.ITEM_WEAPON) { - showAvatarInfo.addEquipList(ShowEquip.newBuilder() - .setItemId(item.getItemId()) - .setWeapon(item.toWeaponProto())); - } - } - - return showAvatarInfo.build(); - } - - @PostLoad - private void onLoad() { - - } - - @PrePersist - private void prePersist() { - this.currentHp = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - } -} +package emu.grasscutter.game.avatar; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import dev.morphia.annotations.*; +import emu.grasscutter.GameConstants; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.OpenConfigEntry; +import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier; +import emu.grasscutter.data.common.FightPropData; +import emu.grasscutter.data.excels.*; +import emu.grasscutter.data.excels.AvatarSkillDepotData.InherentProudSkillOpens; +import emu.grasscutter.data.excels.ItemData.WeaponProperty; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.inventory.EquipType; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.*; +import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; +import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo; +import emu.grasscutter.net.proto.AvatarSkillInfoOuterClass.AvatarSkillInfo; +import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData; +import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass; +import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo; +import emu.grasscutter.net.proto.ShowEquipOuterClass.ShowEquip; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.*; +import java.util.*; +import java.util.stream.Stream; +import lombok.Getter; +import lombok.Setter; +import lombok.val; +import org.bson.types.ObjectId; + +@Entity(value = "avatars", useDiscriminator = false) +public class Avatar { + @Transient @Getter private final Int2ObjectMap equips; + @Transient @Getter private final Int2FloatOpenHashMap fightProperties; + @Transient @Getter private final Int2FloatOpenHashMap fightPropOverrides; + @Id private ObjectId id; + @Indexed @Getter private int ownerId; // Id of player that this avatar belongs to + @Transient private Player owner; + @Transient @Getter private AvatarData data; + @Transient @Getter private AvatarSkillDepotData skillDepot; + @Transient @Getter private long guid; // Player unique id + @Getter private int avatarId; // Id of avatar + @Getter @Setter private int level = 1; + @Getter @Setter private int exp; + @Getter @Setter private int promoteLevel; + @Getter @Setter private int satiation; // Fullness + @Getter @Setter private int satiationPenalty; // When eating too much + @Getter @Setter private float currentHp; + private float currentEnergy; + @Transient @Getter private Set extraAbilityEmbryos; + + private List fetters; + + private final Map skillLevelMap = new Int2IntArrayMap(7); // Talent levels + + @Transient @Getter + private final Map skillExtraChargeMap = new Int2IntArrayMap(2); // Charges + + @Transient + private final Map proudSkillBonusMap = + new Int2IntArrayMap(2); // Talent bonus levels (from const) + + @Getter private int skillDepotId; + private Set talentIdList; // Constellation id list + @Getter private Set proudSkillList; // Character passives + + @Getter @Setter private int flyCloak; + @Getter @Setter private int costume; + @Getter private int bornTime; + + @Getter @Setter private int fetterLevel = 1; + @Getter @Setter private int fetterExp; + + @Getter @Setter private int nameCardRewardId; + @Getter @Setter private int nameCardId; + + @Deprecated // Do not use. Morhpia only! + public Avatar() { + this.equips = new Int2ObjectOpenHashMap<>(); + this.fightProperties = new Int2FloatOpenHashMap(); + this.fightPropOverrides = new Int2FloatOpenHashMap(); + this.extraAbilityEmbryos = new HashSet<>(); + this.fetters = new ArrayList<>(); // TODO Move to avatar + } + + // On creation + public Avatar(int avatarId) { + this(GameData.getAvatarDataMap().get(avatarId)); + } + + public Avatar(AvatarData data) { + this(); + this.avatarId = data.getId(); + this.nameCardRewardId = data.getNameCardRewardId(); + this.nameCardId = data.getNameCardId(); + this.data = data; + this.bornTime = (int) (System.currentTimeMillis() / 1000); + this.flyCloak = 140001; + + this.talentIdList = new HashSet<>(); + this.proudSkillList = new HashSet<>(); + + // Combat properties + Stream.of(FightProperty.values()) + .map(FightProperty::getId) + .filter(id -> (id > 0) && (id < 3000)) + .forEach(id -> this.setFightProperty(id, 0f)); + + // Skill depot + this.setSkillDepotData( + switch (this.avatarId) { + case GameConstants.MAIN_CHARACTER_MALE -> GameData.getAvatarSkillDepotDataMap() + .get(504); // Hack to start with anemo skills + case GameConstants.MAIN_CHARACTER_FEMALE -> GameData.getAvatarSkillDepotDataMap() + .get(704); + default -> data.getSkillDepot(); + }); + + // Set stats + this.recalcStats(); + this.currentHp = getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.currentHp); + this.currentEnergy = 0f; + // Load handler + this.onLoad(); + } + + public static int getMinPromoteLevel(int level) { + if (level > 80) { + return 6; + } else if (level > 70) { + return 5; + } else if (level > 60) { + return 4; + } else if (level > 50) { + return 3; + } else if (level > 40) { + return 2; + } else if (level > 20) { + return 1; + } + return 0; + } + + public Player getPlayer() { + return this.owner; + } + + public ObjectId getObjectId() { + return id; + } + + public AvatarData getAvatarData() { + return data; + } + + protected void setAvatarData(AvatarData data) { + if (this.data != null) return; + this.data = data; // Used while loading this from the database + } + + public void setOwner(Player player) { + this.owner = player; + this.ownerId = player.getUid(); + this.guid = player.getNextGameGuid(); + } + + public boolean addSatiation(int value) { + if (this.satiation >= 10000) return false; + this.satiation += value; + return true; + } + + public float reduceSatiation(int value) { + if (this.satiation == 0) return 0; + this.satiation -= value; + if (this.satiation < 0) { + this.satiation = 0; + } + return this.satiation; + } + + public float reduceSatiationPenalty(int value) { + if (this.satiationPenalty == 0) return 0; + this.satiationPenalty -= value; + if (this.satiationPenalty < 0) { + this.satiationPenalty = 0; + } + return this.satiationPenalty; + } + + public GameItem getEquipBySlot(EquipType slot) { + return this.getEquips().get(slot.getValue()); + } + + private GameItem getEquipBySlot(int slotId) { + return this.getEquips().get(slotId); + } + + public GameItem getWeapon() { + return this.getEquipBySlot(EquipType.EQUIP_WEAPON); + } + + protected void setSkillDepot(AvatarSkillDepotData skillDepot) { + if (this.skillDepot != null) return; + this.skillDepot = skillDepot; // Used while loading this from the database + } + + public void setSkillDepotData(AvatarSkillDepotData skillDepot) { + // Set id and depot + this.skillDepotId = skillDepot.getId(); + this.skillDepot = skillDepot; + // Add any missing skills + this.skillDepot + .getSkillsAndEnergySkill() + .forEach(skillId -> this.skillLevelMap.putIfAbsent(skillId, 1)); + // Add proud skills + this.proudSkillList.clear(); + skillDepot.getInherentProudSkillOpens().stream() + .filter(openData -> openData.getProudSkillGroupId() > 0) + .filter(openData -> openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) + .mapToInt(openData -> (openData.getProudSkillGroupId() * 100) + 1) + .filter(proudSkillId -> GameData.getProudSkillDataMap().containsKey(proudSkillId)) + .forEach(proudSkillId -> this.proudSkillList.add(proudSkillId)); + this.recalcStats(); + } + + public List getFetterList() { + return fetters; + } + + public void setFetterList(List fetterList) { + this.fetters = fetterList; + } + + public void setCurrentEnergy() { + if (GAME_OPTIONS.energyUsage) { + this.setCurrentEnergy(this.currentEnergy); + } + } + + public void setCurrentEnergy(float currentEnergy) { + var depot = this.skillDepot; + if (depot != null && depot.getEnergySkillData() != null) { + ElementType element = depot.getElementType(); + var maxEnergy = depot.getEnergySkillData().getCostElemVal(); + this.setFightProperty(element.getMaxEnergyProp(), maxEnergy); + this.setFightProperty( + element.getCurEnergyProp(), GAME_OPTIONS.energyUsage ? currentEnergy : maxEnergy); + } + } + + public void setCurrentEnergy(FightProperty curEnergyProp, float currentEnergy) { + if (GAME_OPTIONS.energyUsage) { + this.setFightProperty(curEnergyProp, currentEnergy); + this.currentEnergy = currentEnergy; + this.save(); + } + } + + public void setFightProperty(FightProperty prop, float value) { + this.getFightProperties().put(prop.getId(), value); + } + + private void setFightProperty(int id, float value) { + this.getFightProperties().put(id, value); + } + + public void addFightProperty(FightProperty prop, float value) { + this.getFightProperties().put(prop.getId(), getFightProperty(prop) + value); + } + + public float getFightProperty(FightProperty prop) { + return getFightProperties().getOrDefault(prop.getId(), 0f); + } + + public Map + getSkillLevelMap() { // Returns a copy of the skill levels for the current skillDepot. + var map = new Int2IntOpenHashMap(); + this.skillDepot + .getSkillsAndEnergySkill() + .forEach( + skillId -> map.put(skillId, this.skillLevelMap.putIfAbsent(skillId, 1).intValue())); + return map; + } + + // Returns a copy of the skill bonus levels for the current skillDepot, capped to avoid invalid + // levels. + public Map getProudSkillBonusMap() { + var map = new Int2IntArrayMap(); + this.skillDepot + .getSkillsAndEnergySkill() + .forEach( + skillId -> { + val skillData = GameData.getAvatarSkillDataMap().get(skillId); + if (skillData == null) return; + int proudSkillGroupId = skillData.getProudSkillGroupId(); + int bonus = this.proudSkillBonusMap.getOrDefault(proudSkillGroupId, 0); + int maxLevel = GameData.getProudSkillGroupMaxLevel(proudSkillGroupId); + int curLevel = this.skillLevelMap.getOrDefault(skillId, 0); + if (maxLevel > 0) { + bonus = Math.min(bonus, maxLevel - curLevel); + } + map.put(proudSkillGroupId, bonus); + }); + return map; + } + + public IntSet getTalentIdList() { // Returns a copy of the unlocked constellations for the current + // skillDepot. + var talents = new IntOpenHashSet(this.getSkillDepot().getTalents()); + talents.removeIf(id -> !this.talentIdList.contains(id)); + return talents; + } + + public int getCoreProudSkillLevel() { + var lockedTalents = new IntOpenHashSet(this.getSkillDepot().getTalents()); + lockedTalents.removeAll(this.getTalentIdList()); + // One below the lowest locked talent, or 6 if there are no locked talents. + return lockedTalents.intStream().map(i -> i % 10).min().orElse(7) - 1; + } + + public boolean equipItem(GameItem item, boolean shouldRecalc) { + // Sanity check equip type + EquipType itemEquipType = item.getItemData().getEquipType(); + if (itemEquipType == EquipType.EQUIP_NONE) { + return false; + } + + // Check if other avatars have this item equipped + Avatar otherAvatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter()); + if (otherAvatar != null) { + // Unequip other avatar's item + if (otherAvatar.unequipItem(item.getItemData().getEquipType())) { + getPlayer() + .sendPacket( + new PacketAvatarEquipChangeNotify(otherAvatar, item.getItemData().getEquipType())); + } + // Swap with other avatar + if (getEquips().containsKey(itemEquipType.getValue())) { + GameItem toSwap = this.getEquipBySlot(itemEquipType); + otherAvatar.equipItem(toSwap, false); + } + // Recalc + otherAvatar.recalcStats(); + } else if (getEquips().containsKey(itemEquipType.getValue())) { + // Unequip item in current slot if it exists + unequipItem(itemEquipType); + } + + // Set equip + getEquips().put(itemEquipType.getValue(), item); + + if (itemEquipType == EquipType.EQUIP_WEAPON && getPlayer().getWorld() != null) { + item.setWeaponEntityId(this.getPlayer().getWorld().getNextEntityId(EntityIdType.WEAPON)); + } + + item.setEquipCharacter(this.getAvatarId()); + item.save(); + + if (this.getPlayer().hasSentLoginPackets()) { + this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item)); + } + + if (shouldRecalc) { + this.recalcStats(); + } + + return true; + } + + public boolean unequipItem(EquipType slot) { + GameItem item = getEquips().remove(slot.getValue()); + + if (item != null) { + item.setEquipCharacter(0); + item.save(); + return true; + } + + return false; + } + + public void recalcStats() { + recalcStats(false); + } + + public void recalcStats(boolean forceSendAbilityChange) { + // Setup + var data = this.getAvatarData(); + var promoteData = + GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel()); + var setMap = new Int2IntOpenHashMap(); + + // Extra ability embryos + Set prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos(); + this.extraAbilityEmbryos = new HashSet<>(); + + // Fetters + this.setFetterList(data.getFetters()); + this.setNameCardRewardId(data.getNameCardRewardId()); + this.setNameCardId(data.getNameCardId()); + + // Get hp percent, set to 100% if none + float hpPercent = + this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 + ? 1f + : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) + / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + + // Store current energy value for later + float currentEnergy = + (this.getSkillDepot() != null) + ? this.getFightProperty(this.getSkillDepot().getElementType().getCurEnergyProp()) + : 0f; + + // Clear properties + this.getFightProperties().clear(); + + // Base stats + this.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, data.getBaseHp(this.getLevel())); + this.setFightProperty( + FightProperty.FIGHT_PROP_BASE_ATTACK, data.getBaseAttack(this.getLevel())); + this.setFightProperty( + FightProperty.FIGHT_PROP_BASE_DEFENSE, data.getBaseDefense(this.getLevel())); + this.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL, data.getBaseCritical()); + this.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL_HURT, data.getBaseCriticalHurt()); + this.setFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 1f); + + if (promoteData != null) { + for (FightPropData fightPropData : promoteData.getAddProps()) { + this.addFightProperty(fightPropData.getProp(), fightPropData.getValue()); + } + } + + // Set energy usage + setCurrentEnergy(currentEnergy); + + // Artifacts + for (int slotId = 1; slotId <= 5; slotId++) { + // Get artifact + GameItem equip = this.getEquipBySlot(slotId); + if (equip == null) { + continue; + } + // Artifact main stat + ReliquaryMainPropData mainPropData = + GameData.getReliquaryMainPropDataMap().get(equip.getMainPropId()); + if (mainPropData != null) { + ReliquaryLevelData levelData = + GameData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel()); + if (levelData != null) { + this.addFightProperty( + mainPropData.getFightProp(), levelData.getPropValue(mainPropData.getFightProp())); + } + } + // Artifact sub stats + for (int appendPropId : equip.getAppendPropIdList()) { + ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId); + if (affixData != null) { + this.addFightProperty(affixData.getFightProp(), affixData.getPropValue()); + } + } + // Set bonus + if (equip.getItemData().getSetId() > 0) { + setMap.addTo(equip.getItemData().getSetId(), 1); + } + } + + // Set stuff + setMap.forEach( + (setId, amount) -> { + ReliquarySetData setData = GameData.getReliquarySetDataMap().get((int) setId); + if (setData == null) return; + + // Calculate how many items are from the set + // Add affix data from set bonus + val setNeedNum = setData.getSetNeedNum(); + for (int setIndex = 0; setIndex < setNeedNum.length; setIndex++) { + if (amount < setNeedNum[setIndex]) break; + + int affixId = (setData.getEquipAffixId() * 10) + setIndex; + EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId); + if (affix == null) { + continue; + } + + // Add properties from this affix to our avatar + for (FightPropData prop : affix.getAddProps()) { + this.addFightProperty(prop.getProp(), prop.getValue()); + } + + // Add any skill strings from this affix + this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true); + } + }); + + // Weapon + GameItem weapon = this.getWeapon(); + if (weapon != null) { + // Add stats + WeaponCurveData curveData = GameData.getWeaponCurveDataMap().get(weapon.getLevel()); + if (curveData != null) { + for (WeaponProperty weaponProperty : weapon.getItemData().getWeaponProperties()) { + this.addFightProperty( + weaponProperty.getPropType(), + weaponProperty.getInitValue() * curveData.getMultByProp(weaponProperty.getType())); + } + } + // Weapon promotion stats + WeaponPromoteData wepPromoteData = + GameData.getWeaponPromoteData( + weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); + if (wepPromoteData != null) { + for (FightPropData prop : wepPromoteData.getAddProps()) { + if (prop.getValue() == 0f || prop.getProp() == null) { + continue; + } + this.addFightProperty(prop.getProp(), prop.getValue()); + } + } + // Add weapon skill from affixes + if (weapon.getAffixes() != null && weapon.getAffixes().size() > 0) { + // Weapons usually dont have more than one affix but just in case... + for (int af : weapon.getAffixes()) { + if (af == 0) { + continue; + } + // Calculate affix id + int affixId = (af * 10) + weapon.getRefinement(); + EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId); + if (affix == null) { + continue; + } + + // Add properties from this affix to our avatar + for (FightPropData prop : affix.getAddProps()) { + this.addFightProperty(prop.getProp(), prop.getValue()); + } + + // Add any skill strings from this affix + this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true); + } + } + } + + // Add proud skills and unlock them if needed + AvatarSkillDepotData skillDepot = + GameData.getAvatarSkillDepotDataMap().get(this.getSkillDepotId()); + this.getProudSkillList().clear(); + for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) { + if (openData.getProudSkillGroupId() == 0) { + continue; + } + if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) { + int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; + if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) { + this.getProudSkillList().add(proudSkillId); + } + } + } + + // Proud skills + for (int proudSkillId : this.getProudSkillList()) { + ProudSkillData proudSkillData = GameData.getProudSkillDataMap().get(proudSkillId); + if (proudSkillData == null) { + continue; + } + + // Add properties from this proud skill to our avatar + for (FightPropData prop : proudSkillData.getAddProps()) { + this.addFightProperty(prop.getProp(), prop.getValue()); + } + + // Add any embryos from this proud skill + this.addToExtraAbilityEmbryos(proudSkillData.getOpenConfig()); + } + + // Constellations + this.getTalentIdList() + .intStream() + .mapToObj(GameData.getAvatarTalentDataMap()::get) + .filter(Objects::nonNull) + .map(AvatarTalentData::getOpenConfig) + .filter(Objects::nonNull) + .forEach(this::addToExtraAbilityEmbryos); + // Add any skill strings from this constellation + + // Set % stats + FightProperty.forEachCompoundProperty( + c -> + this.setFightProperty( + c.getResult(), + this.getFightProperty(c.getFlat()) + + (this.getFightProperty(c.getBase()) + * (1f + this.getFightProperty(c.getPercent()))))); + + // Reapply all overrides + this.fightProperties.putAll(this.fightPropOverrides); + + // Set current hp + this.setFightProperty( + FightProperty.FIGHT_PROP_CUR_HP, + this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent); + + // Packet + if (getPlayer() != null && getPlayer().hasSentLoginPackets()) { + // Update stats for client + getPlayer().sendPacket(new PacketAvatarFightPropNotify(this)); + // Update client abilities + EntityAvatar entity = this.getAsEntity(); + if (entity != null + && (!this.getExtraAbilityEmbryos().equals(prevExtraAbilityEmbryos) + || forceSendAbilityChange)) { + getPlayer().sendPacket(new PacketAbilityChangeNotify(entity)); + } + } + } + + public void addToExtraAbilityEmbryos(String openConfig) { + this.addToExtraAbilityEmbryos(openConfig, false); + } + + public void addToExtraAbilityEmbryos(String openConfig, boolean forceAdd) { + if (openConfig == null || openConfig.length() == 0) { + return; + } + + OpenConfigEntry entry = GameData.getOpenConfigEntries().get(openConfig); + if (entry == null) { + if (forceAdd) { + // Add config string to ability skill list anyways + this.getExtraAbilityEmbryos().add(openConfig); + } + return; + } + + if (entry.getAddAbilities() != null) { + for (String ability : entry.getAddAbilities()) { + this.getExtraAbilityEmbryos().add(ability); + } + } + } + + public void calcConstellation(OpenConfigEntry entry, boolean notifyClient) { + if (entry == null) return; + if (this.getPlayer() == null) notifyClient = false; + + // Check if new constellation adds +3 to a skill level + if (this.calcConstellationExtraLevels(entry) && notifyClient) { + // Packet + this.getPlayer() + .sendPacket(new PacketProudSkillExtraLevelNotify(this, entry.getExtraTalentIndex())); + } + // Check if new constellation adds skill charges + if (this.calcConstellationExtraCharges(entry) && notifyClient) { + // Packet + Stream.of(entry.getSkillPointModifiers()) + .mapToInt(SkillPointModifier::getSkillId) + .forEach( + skillId -> { + this.getPlayer() + .sendPacket( + new PacketAvatarSkillMaxChargeCountNotify( + this, skillId, this.getSkillExtraChargeMap().getOrDefault(skillId, 0))); + }); + } + } + + public void recalcConstellations() { + // Clear first + this.proudSkillBonusMap.clear(); + this.skillExtraChargeMap.clear(); + + // Sanity checks + if (this.data == null || this.skillDepot == null) { + return; + } + + this.getTalentIdList() + .intStream() + .mapToObj(GameData.getAvatarTalentDataMap()::get) + .filter(Objects::nonNull) + .map(AvatarTalentData::getOpenConfig) + .filter(Objects::nonNull) + .filter(openConfig -> openConfig.length() > 0) + .map(GameData.getOpenConfigEntries()::get) + .filter(Objects::nonNull) + .forEach(e -> this.calcConstellation(e, false)); + } + + private boolean calcConstellationExtraCharges(OpenConfigEntry entry) { + var skillPointModifiers = entry.getSkillPointModifiers(); + if (skillPointModifiers == null) return false; + + for (var mod : skillPointModifiers) { + AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(mod.getSkillId()); + + if (skillData == null) continue; + + int charges = skillData.getMaxChargeNum() + mod.getDelta(); + + this.getSkillExtraChargeMap().put(mod.getSkillId(), charges); + } + return true; + } + + private boolean calcConstellationExtraLevels(OpenConfigEntry entry) { + int skillId = + switch (entry.getExtraTalentIndex()) { + case 9 -> this.skillDepot.getEnergySkill(); // Ult skill + case 2 -> (this.skillDepot.getSkills().size() >= 2) + ? this.skillDepot.getSkills().get(1) + : 0; // E skill + default -> 0; + }; + // Sanity check + if (skillId == 0) { + return false; + } + + // Get proud skill group id + AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId); + + if (skillData == null) { + return false; + } + + // Add to bonus list + this.addProudSkillLevelBonus(skillData.getProudSkillGroupId(), 3); + return true; + } + + private int addProudSkillLevelBonus(int proudSkillGroupId, int bonus) { + return this.proudSkillBonusMap.compute( + proudSkillGroupId, (k, v) -> (v == null) ? bonus : v + bonus); + } + + public boolean upgradeSkill(int skillId) { + AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId); + if (skillData == null) return false; + + // Get data for next skill level + int newLevel = this.skillLevelMap.getOrDefault(skillId, 0) + 1; + if (newLevel > 10) return false; + + // Proud skill data + int proudSkillId = (skillData.getProudSkillGroupId() * 100) + newLevel; + ProudSkillData proudSkill = GameData.getProudSkillDataMap().get(proudSkillId); + if (proudSkill == null) return false; + + // Make sure break level is correct + if (this.getPromoteLevel() < proudSkill.getBreakLevel()) return false; + + // Pay materials and mora if possible + if (!this.getPlayer().getInventory().payItems(proudSkill.getTotalCostItems())) return false; + + // Upgrade skill + this.setSkillLevel(skillId, newLevel); + return true; + } + + public boolean setSkillLevel(int skillId, int level) { + if (level < 0 || level > 15) return false; + var validLevels = GameData.getAvatarSkillLevels(skillId); + if (validLevels != null && !validLevels.contains(level)) return false; + int oldLevel = + this.skillLevelMap.getOrDefault( + skillId, 0); // just taking the return value of put would have null concerns + this.skillLevelMap.put(skillId, level); + this.save(); + + // Packet + val player = this.getPlayer(); + if (player != null) { + player.sendPacket(new PacketAvatarSkillChangeNotify(this, skillId, oldLevel, level)); + player.sendPacket(new PacketAvatarSkillUpgradeRsp(this, skillId, oldLevel, level)); + } + return true; + } + + public boolean unlockConstellation() { + return this.unlockConstellation(false); + } + + public boolean unlockConstellation(boolean skipPayment) { + int currentTalentLevel = this.getCoreProudSkillLevel(); + int talentId = this.skillDepot.getTalents().get(currentTalentLevel); + return this.unlockConstellation(talentId, skipPayment); + } + + public boolean unlockConstellation(int talentId) { + return unlockConstellation(talentId, false); + } + + public boolean unlockConstellation(int talentId, boolean skipPayment) { + // Get talent + AvatarTalentData talentData = GameData.getAvatarTalentDataMap().get(talentId); + if (talentData == null) return false; + var player = this.getPlayer(); + + // Pay constellation item if possible + if (!skipPayment + && (player != null) + && !player.getInventory().payItem(talentData.getMainCostItemId(), 1)) { + return false; + } + + // Apply + recalc + this.talentIdList.add(talentData.getId()); + + // Packet + if (player != null) { + player.sendPacket(new PacketAvatarUnlockTalentNotify(this, talentId)); + player.sendPacket(new PacketUnlockAvatarTalentRsp(this, talentId)); + } + + // Proud skill bonus map (Extra skills) + this.calcConstellation(GameData.getOpenConfigEntries().get(talentData.getOpenConfig()), true); + + // Recalc + save avatar + this.recalcStats(true); + this.save(); + return true; + } + + public void forceConstellationLevel(int level) { + if (level > 6) return; // Sanity check + + if (level < 0) { // Special case for resetConst to remove inactive depots too + this.talentIdList.clear(); + this.recalcStats(); + this.save(); + return; + } + this.talentIdList.removeAll( + this.getTalentIdList()); // Only remove constellations from active depot + for (int i = 0; i < level; i++) this.unlockConstellation(true); + this.recalcStats(); + this.save(); + } + + public boolean sendSkillExtraChargeMap() { + val map = this.getSkillExtraChargeMap(); + if (map.isEmpty()) return false; + this.getPlayer() + .sendPacket( + new PacketAvatarSkillInfoNotify( + this.guid, + new Int2IntArrayMap( + map))); // TODO: Remove this allocation when updating interfaces to FastUtils + // later + return true; + } + + public EntityAvatar getAsEntity() { + for (EntityAvatar entity : getPlayer().getTeamManager().getActiveTeam()) { + if (entity.getAvatar() == this) { + return entity; + } + } + return null; + } + + public int getEntityId() { + EntityAvatar entity = getAsEntity(); + return entity != null ? entity.getId() : 0; + } + + public void save() { + DatabaseHelper.saveAvatar(this); + } + + public AvatarInfo toProto() { + int fetterLevel = this.getFetterLevel(); + AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder().setExpLevel(fetterLevel); + + if (fetterLevel != 10) { + avatarFetter.setExpNumber(this.getFetterExp()); + } + + if (this.fetters != null) { + this.fetters.forEach( + fetterId -> + avatarFetter.addFetterList( + FetterData.newBuilder() + .setFetterId(fetterId) + .setFetterState(FetterState.FINISH.getValue()))); + } + + int cardId = this.getNameCardId(); + + if (this.getPlayer().getNameCardList().contains(cardId)) { + avatarFetter.addRewardedFetterLevelList(10); + } + + AvatarInfo.Builder avatarInfo = + AvatarInfo.newBuilder() + .setAvatarId(this.getAvatarId()) + .setGuid(this.getGuid()) + .setLifeState(1) + .addAllTalentIdList(this.getTalentIdList()) + .putAllFightPropMap(this.getFightProperties()) + .setSkillDepotId(this.getSkillDepotId()) + .setCoreProudSkillLevel(this.getCoreProudSkillLevel()) + .putAllSkillLevelMap(this.getSkillLevelMap()) + .addAllInherentProudSkillList(this.getProudSkillList()) + .putAllProudSkillExtraLevelMap(this.getProudSkillBonusMap()) + .setAvatarType(1) + .setBornTime(this.getBornTime()) + .setFetterInfo(avatarFetter) + .setWearingFlycloakId(this.getFlyCloak()) + .setCostumeId(this.getCostume()); + + this.getSkillExtraChargeMap() + .forEach( + (skillId, count) -> + avatarInfo.putSkillMap( + skillId, AvatarSkillInfo.newBuilder().setMaxChargeCount(count).build())); + + this.getEquips().forEach((k, item) -> avatarInfo.addEquipGuidList(item.getGuid())); + + avatarInfo.putPropMap( + PlayerProperty.PROP_LEVEL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel())); + avatarInfo.putPropMap( + PlayerProperty.PROP_EXP.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_EXP, this.getExp())); + avatarInfo.putPropMap( + PlayerProperty.PROP_BREAK_LEVEL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_BREAK_LEVEL, this.getPromoteLevel())); + avatarInfo.putPropMap( + PlayerProperty.PROP_SATIATION_VAL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiation())); + avatarInfo.putPropMap( + PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), + ProtoHelper.newPropValue( + PlayerProperty.PROP_SATIATION_PENALTY_TIME, this.getSatiationPenalty())); + + return avatarInfo.build(); + } + + // used only in character showcase + public ShowAvatarInfo toShowAvatarInfoProto() { + AvatarFetterInfo.Builder avatarFetter = + AvatarFetterInfo.newBuilder().setExpLevel(this.getFetterLevel()); + + ShowAvatarInfo.Builder showAvatarInfo = + ShowAvatarInfoOuterClass.ShowAvatarInfo.newBuilder() + .setAvatarId(avatarId) + .addAllTalentIdList(this.getTalentIdList()) + .putAllFightPropMap(this.getFightProperties()) + .setSkillDepotId(this.getSkillDepotId()) + .setCoreProudSkillLevel(this.getCoreProudSkillLevel()) + .addAllInherentProudSkillList(this.getProudSkillList()) + .putAllSkillLevelMap(this.getSkillLevelMap()) + .putAllProudSkillExtraLevelMap(this.getProudSkillBonusMap()) + .setFetterInfo(avatarFetter) + .setCostumeId(this.getCostume()); + + showAvatarInfo.putPropMap( + PlayerProperty.PROP_LEVEL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel())); + showAvatarInfo.putPropMap( + PlayerProperty.PROP_EXP.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_EXP, this.getExp())); + showAvatarInfo.putPropMap( + PlayerProperty.PROP_BREAK_LEVEL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_BREAK_LEVEL, this.getPromoteLevel())); + showAvatarInfo.putPropMap( + PlayerProperty.PROP_SATIATION_VAL.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiation())); + showAvatarInfo.putPropMap( + PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), + ProtoHelper.newPropValue( + PlayerProperty.PROP_SATIATION_PENALTY_TIME, this.getSatiationPenalty())); + int maxStamina = this.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA); + showAvatarInfo.putPropMap( + PlayerProperty.PROP_MAX_STAMINA.getId(), + ProtoHelper.newPropValue(PlayerProperty.PROP_MAX_STAMINA, maxStamina)); + + for (GameItem item : this.getEquips().values()) { + if (item.getItemType() == ItemType.ITEM_RELIQUARY) { + showAvatarInfo.addEquipList( + ShowEquip.newBuilder() + .setItemId(item.getItemId()) + .setReliquary(item.toReliquaryProto())); + } else if (item.getItemType() == ItemType.ITEM_WEAPON) { + showAvatarInfo.addEquipList( + ShowEquip.newBuilder().setItemId(item.getItemId()).setWeapon(item.toWeaponProto())); + } + } + + return showAvatarInfo.build(); + } + + @PostLoad + private void onLoad() {} + + @PrePersist + private void prePersist() { + this.currentHp = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + } +} diff --git a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java index fcb69faf3..abe0c11d8 100644 --- a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java +++ b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java @@ -1,173 +1,173 @@ -package emu.grasscutter.game.avatar; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeNotify; -import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - -import java.util.Iterator; -import java.util.List; - -public class AvatarStorage extends BasePlayerManager implements Iterable { - private final Int2ObjectMap avatars; - private final Long2ObjectMap avatarsGuid; - - public AvatarStorage(Player player) { - super(player); - this.avatars = new Int2ObjectOpenHashMap<>(); - this.avatarsGuid = new Long2ObjectOpenHashMap<>(); - } - - public Int2ObjectMap getAvatars() { - return avatars; - } - - public int getAvatarCount() { - return this.avatars.size(); - } - - public Avatar getAvatarById(int id) { - return getAvatars().get(id); - } - - public Avatar getAvatarByGuid(long id) { - return avatarsGuid.get(id); - } - - public boolean hasAvatar(int id) { - return getAvatars().containsKey(id); - } - - public boolean addAvatar(Avatar avatar) { - if (avatar.getAvatarData() == null || this.hasAvatar(avatar.getAvatarId())) { - return false; - } - - // Set owner first - avatar.setOwner(getPlayer()); - - // Put into maps - this.avatars.put(avatar.getAvatarId(), avatar); - this.avatarsGuid.put(avatar.getGuid(), avatar); - - avatar.save(); - - return true; - } - - public void addStartingWeapon(Avatar avatar) { - // Make sure avatar owner is this player - if (avatar.getPlayer() != this.getPlayer()) { - return; - } - - // Create weapon - GameItem weapon = new GameItem(avatar.getAvatarData().getInitialWeapon()); - - if (weapon.getItemData() != null) { - this.getPlayer().getInventory().addItem(weapon); - - avatar.equipItem(weapon, true); - } - } - - public boolean wearFlycloak(long avatarGuid, int flycloakId) { - Avatar avatar = this.getAvatarByGuid(avatarGuid); - - if (avatar == null || !getPlayer().getFlyCloakList().contains(flycloakId)) { - return false; - } - - avatar.setFlyCloak(flycloakId); - avatar.save(); - - // Update - getPlayer().sendPacket(new PacketAvatarFlycloakChangeNotify(avatar)); - - return true; - } - - public boolean changeCostume(long avatarGuid, int costumeId) { - Avatar avatar = this.getAvatarByGuid(avatarGuid); - - if (avatar == null) { - return false; - } - - if (costumeId != 0 && !getPlayer().getCostumeList().contains(costumeId)) { - return false; - } - - // TODO make sure avatar can wear costume - - avatar.setCostume(costumeId); - avatar.save(); - - // Update entity - EntityAvatar entity = avatar.getAsEntity(); - if (entity == null) { - entity = new EntityAvatar(avatar); - getPlayer().sendPacket(new PacketAvatarChangeCostumeNotify(entity)); - } else { - getPlayer().getScene().broadcastPacket(new PacketAvatarChangeCostumeNotify(entity)); - } - - // Done - return true; - } - - public void loadFromDatabase() { - List avatars = DatabaseHelper.getAvatars(getPlayer()); - - for (Avatar avatar : avatars) { - // Should never happen - if (avatar.getObjectId() == null) { - continue; - } - - AvatarData avatarData = GameData.getAvatarDataMap().get(avatar.getAvatarId()); - AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId()); - if (avatarData == null || skillDepot == null) { - continue; - } - - // Set ownerships - avatar.setAvatarData(avatarData); - avatar.setSkillDepot(skillDepot); - avatar.setOwner(getPlayer()); - - // Force recalc of const boosted skills - avatar.recalcConstellations(); - - // Add to avatar storage - this.avatars.put(avatar.getAvatarId(), avatar); - this.avatarsGuid.put(avatar.getGuid(), avatar); - } - } - - public void postLoad() { - for (Avatar avatar : this) { - // Weapon check - if (avatar.getWeapon() == null) { - this.addStartingWeapon(avatar); - } - // Recalc stats - avatar.recalcStats(); - } - } - - @Override - public Iterator iterator() { - return getAvatars().values().iterator(); - } -} +package emu.grasscutter.game.avatar; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeNotify; +import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import java.util.Iterator; +import java.util.List; + +public class AvatarStorage extends BasePlayerManager implements Iterable { + private final Int2ObjectMap avatars; + private final Long2ObjectMap avatarsGuid; + + public AvatarStorage(Player player) { + super(player); + this.avatars = new Int2ObjectOpenHashMap<>(); + this.avatarsGuid = new Long2ObjectOpenHashMap<>(); + } + + public Int2ObjectMap getAvatars() { + return avatars; + } + + public int getAvatarCount() { + return this.avatars.size(); + } + + public Avatar getAvatarById(int id) { + return getAvatars().get(id); + } + + public Avatar getAvatarByGuid(long id) { + return avatarsGuid.get(id); + } + + public boolean hasAvatar(int id) { + return getAvatars().containsKey(id); + } + + public boolean addAvatar(Avatar avatar) { + if (avatar.getAvatarData() == null || this.hasAvatar(avatar.getAvatarId())) { + return false; + } + + // Set owner first + avatar.setOwner(getPlayer()); + + // Put into maps + this.avatars.put(avatar.getAvatarId(), avatar); + this.avatarsGuid.put(avatar.getGuid(), avatar); + + avatar.save(); + + return true; + } + + public void addStartingWeapon(Avatar avatar) { + // Make sure avatar owner is this player + if (avatar.getPlayer() != this.getPlayer()) { + return; + } + + // Create weapon + GameItem weapon = new GameItem(avatar.getAvatarData().getInitialWeapon()); + + if (weapon.getItemData() != null) { + this.getPlayer().getInventory().addItem(weapon); + + avatar.equipItem(weapon, true); + } + } + + public boolean wearFlycloak(long avatarGuid, int flycloakId) { + Avatar avatar = this.getAvatarByGuid(avatarGuid); + + if (avatar == null || !getPlayer().getFlyCloakList().contains(flycloakId)) { + return false; + } + + avatar.setFlyCloak(flycloakId); + avatar.save(); + + // Update + getPlayer().sendPacket(new PacketAvatarFlycloakChangeNotify(avatar)); + + return true; + } + + public boolean changeCostume(long avatarGuid, int costumeId) { + Avatar avatar = this.getAvatarByGuid(avatarGuid); + + if (avatar == null) { + return false; + } + + if (costumeId != 0 && !getPlayer().getCostumeList().contains(costumeId)) { + return false; + } + + // TODO make sure avatar can wear costume + + avatar.setCostume(costumeId); + avatar.save(); + + // Update entity + EntityAvatar entity = avatar.getAsEntity(); + if (entity == null) { + entity = new EntityAvatar(avatar); + getPlayer().sendPacket(new PacketAvatarChangeCostumeNotify(entity)); + } else { + getPlayer().getScene().broadcastPacket(new PacketAvatarChangeCostumeNotify(entity)); + } + + // Done + return true; + } + + public void loadFromDatabase() { + List avatars = DatabaseHelper.getAvatars(getPlayer()); + + for (Avatar avatar : avatars) { + // Should never happen + if (avatar.getObjectId() == null) { + continue; + } + + AvatarData avatarData = GameData.getAvatarDataMap().get(avatar.getAvatarId()); + AvatarSkillDepotData skillDepot = + GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId()); + if (avatarData == null || skillDepot == null) { + continue; + } + + // Set ownerships + avatar.setAvatarData(avatarData); + avatar.setSkillDepot(skillDepot); + avatar.setOwner(getPlayer()); + + // Force recalc of const boosted skills + avatar.recalcConstellations(); + + // Add to avatar storage + this.avatars.put(avatar.getAvatarId(), avatar); + this.avatarsGuid.put(avatar.getGuid(), avatar); + } + } + + public void postLoad() { + for (Avatar avatar : this) { + // Weapon check + if (avatar.getWeapon() == null) { + this.addStartingWeapon(avatar); + } + // Recalc stats + avatar.recalcStats(); + } + } + + @Override + public Iterator iterator() { + return getAvatars().values().iterator(); + } +} diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java index 9ac60c578..bef222be8 100644 --- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java +++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java @@ -1,392 +1,415 @@ -package emu.grasscutter.game.battlepass; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Indexed; -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.BattlePassRewardData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.data.excels.RewardData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.MaterialType; -import emu.grasscutter.game.player.BasePlayerDataManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.BattlePassMissionRefreshType; -import emu.grasscutter.game.props.BattlePassMissionStatus; -import emu.grasscutter.game.props.ItemUseOp; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.BattlePassCycleOuterClass.BattlePassCycle; -import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; -import emu.grasscutter.net.proto.BattlePassScheduleOuterClass.BattlePassSchedule; -import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus; -import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify; -import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify; -import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp; -import lombok.Getter; -import org.bson.types.ObjectId; - -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.temporal.TemporalAdjusters; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Entity(value = "battlepass", useDiscriminator = false) -public class BattlePassManager extends BasePlayerDataManager { - @Id - @Getter - private ObjectId id; - - @Indexed - private int ownerUid; - @Getter - private int point; - @Getter - private int cyclePoints; // Weekly maximum cap - @Getter - private int level; - - @Getter - private boolean viewed; - private boolean paid; - - private Map missions; - private Map takenRewards; - - @Deprecated // Morphia only - public BattlePassManager() { - } - - public BattlePassManager(Player player) { - super(player); - this.ownerUid = player.getUid(); - } - - public void setPlayer(Player player) { - this.player = player; - this.ownerUid = player.getUid(); - } - - public void updateViewed() { - this.viewed = true; - } - - public boolean setLevel(int level) { - if (level >= 0 && level <= GameConstants.BATTLE_PASS_MAX_LEVEL) { - this.level = level; - this.point = 0; - this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.player)); - return true; - } - return false; - } - - public void addPoints(int points) { - this.addPointsDirectly(points, false); - - this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(player)); - this.save(); - } - - public void addPointsDirectly(int points, boolean isWeekly) { - int amount = points; - - if (isWeekly) { - amount = Math.min(amount, GameConstants.BATTLE_PASS_POINT_PER_WEEK - this.cyclePoints); - } - - if (amount <= 0) { - return; - } - - this.point += amount; - this.cyclePoints += amount; - - if (this.point >= GameConstants.BATTLE_PASS_POINT_PER_LEVEL && this.getLevel() < GameConstants.BATTLE_PASS_MAX_LEVEL) { - int levelups = Math.floorDiv(this.point, GameConstants.BATTLE_PASS_POINT_PER_LEVEL); - - // Make sure player cant go above max BP level - levelups = Math.min(levelups, GameConstants.BATTLE_PASS_MAX_LEVEL - levelups); - - // Set new points after level up - this.point = this.point - (levelups * GameConstants.BATTLE_PASS_POINT_PER_LEVEL); - this.level += levelups; - } - } - - public Map getMissions() { - if (this.missions == null) this.missions = new HashMap<>(); - return this.missions; - } - - // Will return a new empty mission if the mission id is not found - public BattlePassMission loadMissionById(int id) { - return getMissions().computeIfAbsent(id, i -> new BattlePassMission(i)); - } - - public boolean hasMission(int id) { - return getMissions().containsKey(id); - } - - public boolean isPaid() { - // ToDo: Change this when we actually support unlocking "paid" BP. - return true; - } - - public Map getTakenRewards() { - if (this.takenRewards == null) this.takenRewards = new HashMap<>(); - return this.takenRewards; - } - - // Mission triggers - public void triggerMission(WatcherTriggerType triggerType) { - getPlayer().getServer().getBattlePassSystem().triggerMission(getPlayer(), triggerType); - } - - public void triggerMission(WatcherTriggerType triggerType, int param, int progress) { - getPlayer().getServer().getBattlePassSystem().triggerMission(getPlayer(), triggerType, param, progress); - } - - // Handlers - public void takeMissionPoint(List missionIdList) { - // Obvious exploit check - if (missionIdList.size() > GameData.getBattlePassMissionDataMap().size()) { - return; - } - - List updatedMissions = new ArrayList<>(missionIdList.size()); - - for (int id : missionIdList) { - // Skip if we dont have this mission - if (!this.hasMission(id)) { - continue; - } - - BattlePassMission mission = this.loadMissionById(id); - - if (mission.getData() == null) { - this.getMissions().remove(mission.getId()); - continue; - } - - // Take reward - if (mission.getStatus() == BattlePassMissionStatus.MISSION_STATUS_FINISHED) { - this.addPointsDirectly(mission.getData().getAddPoint(), mission.getData().isCycleRefresh()); - mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_POINT_TAKEN); - - updatedMissions.add(mission); - } - } - - if (updatedMissions.size() > 0) { - // Save to db - this.save(); - - // Packet - getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(updatedMissions)); - getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); - } - } - - private void takeRewardsFromSelectChest(ItemData rewardItemData, int index, ItemParamData entry, List rewardItems) { - // Sanity checks. - if (rewardItemData.getItemUse().size() < 1) { - return; - } - - // Get possible item choices. - String[] choices = rewardItemData.getItemUse().get(0).getUseParam()[0].split(","); - if (choices.length < index) { - return; - } - - // Get data for the selected item. - // This depends on the type of chest. - int chosenId = Integer.parseInt(choices[index - 1]); - - // For ITEM_USE_ADD_SELECT_ITEM chests, we can directly add the item specified in the chest's data. - if (rewardItemData.getItemUse().get(0).getUseOp() == ItemUseOp.ITEM_USE_ADD_SELECT_ITEM) { - GameItem rewardItem = new GameItem(GameData.getItemDataMap().get(chosenId), entry.getItemCount()); - rewardItems.add(rewardItem); - } - // For ITEM_USE_GRANT_SELECT_REWARD chests, we have to again look up reward data. - else if (rewardItemData.getItemUse().get(0).getUseOp() == ItemUseOp.ITEM_USE_GRANT_SELECT_REWARD) { - RewardData selectedReward = GameData.getRewardDataMap().get(chosenId); - - for (var r : selectedReward.getRewardItemList()) { - GameItem rewardItem = new GameItem(GameData.getItemDataMap().get(r.getItemId()), r.getItemCount()); - rewardItems.add(rewardItem); - } - } else { - Grasscutter.getLogger().error("Invalid chest type for BP reward."); - } - } - - public void takeReward(List takeOptionList) { - List rewardList = new ArrayList<>(); - - for (BattlePassRewardTakeOption option : takeOptionList) { - // Duplicate check - if (option.getTag().getRewardId() == 0 || getTakenRewards().containsKey(option.getTag().getRewardId())) { - continue; - } - - // Level check - if (option.getTag().getLevel() > this.getLevel()) { - continue; - } - - BattlePassRewardData rewardData = GameData.getBattlePassRewardDataMap().get(GameConstants.BATTLE_PASS_CURRENT_INDEX * 100 + option.getTag().getLevel()); - - // Sanity check with excel data - if (rewardData.getFreeRewardIdList().contains(option.getTag().getRewardId())) { - rewardList.add(option); - } else if (this.isPaid() && rewardData.getPaidRewardIdList().contains(option.getTag().getRewardId())) { - rewardList.add(option); - } else { - Grasscutter.getLogger().info("Not in rewards list: {}", option.getTag().getRewardId()); - } - } - - // Get rewards - List rewardItems = null; - - if (rewardList.size() > 0) { - - rewardItems = new ArrayList<>(); - - for (var option : rewardList) { - var tag = option.getTag(); - int index = option.getOptionIdx(); - - // Make sure we have reward data. - RewardData reward = GameData.getRewardDataMap().get(tag.getRewardId()); - if (reward == null) { - continue; - } - - // Add reward items. - for (var entry : reward.getRewardItemList()) { - ItemData rewardItemData = GameData.getItemDataMap().get(entry.getItemId()); - - // Some rewards are chests where the user can select the item they want. - if (rewardItemData.getMaterialType() == MaterialType.MATERIAL_SELECTABLE_CHEST) { - this.takeRewardsFromSelectChest(rewardItemData, index, entry, rewardItems); - } - // All other rewards directly give us the right item. - else { - GameItem rewardItem = new GameItem(rewardItemData, entry.getItemCount()); - rewardItems.add(rewardItem); - } - } - - // Construct the reward and set as taken. - BattlePassReward bpReward = new BattlePassReward(tag.getLevel(), tag.getRewardId(), tag.getUnlockStatus() == BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID); - this.getTakenRewards().put(bpReward.getRewardId(), bpReward); - } - - // Save to db - this.save(); - - // Add items and send battle pass schedule packet - getPlayer().getInventory().addItems(rewardItems); - getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); - } - - getPlayer().sendPacket(new PacketTakeBattlePassRewardRsp(takeOptionList, rewardItems)); - } - - public int buyLevels(int buyLevel) { - int boughtLevels = Math.min(buyLevel, GameConstants.BATTLE_PASS_MAX_LEVEL - buyLevel); - - if (boughtLevels > 0) { - int price = GameConstants.BATTLE_PASS_LEVEL_PRICE * boughtLevels; - - if (getPlayer().getPrimogems() < price) { - return 0; - } - - this.level += boughtLevels; - this.save(); - - getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); - } - - return boughtLevels; - } - - public void resetDailyMissions() { - var resetMissions = new ArrayList(); - - for (var mission : this.missions.values()) { - if (mission.getData().getRefreshType() == null || mission.getData().getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_DAILY) { - mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED); - mission.setProgress(0); - - resetMissions.add(mission); - } - } - - this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions)); - this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer())); - } - - public void resetWeeklyMissions() { - var resetMissions = new ArrayList(); - - for (var mission : this.missions.values()) { - if (mission.getData().getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE) { - mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED); - mission.setProgress(0); - - resetMissions.add(mission); - } - } - - this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions)); - this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer())); - } - - // - public BattlePassSchedule getScheduleProto() { - var currentDate = LocalDate.now(); - var nextSundayDate = (currentDate.getDayOfWeek() == DayOfWeek.SUNDAY) - ? currentDate - : LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); - var nextSundayTime = LocalDateTime.of(nextSundayDate.getYear(), nextSundayDate.getMonthValue(), nextSundayDate.getDayOfMonth(), 23, 59, 59); - - BattlePassSchedule.Builder schedule = BattlePassSchedule.newBuilder() - .setScheduleId(2700) - .setLevel(this.getLevel()) - .setPoint(this.getPoint()) - .setBeginTime(0) - .setEndTime(2059483200) - .setIsViewed(this.isViewed()) - .setUnlockStatus(this.isPaid() ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE) - .setPaidPlatformFlags(2) // Not bought on Playstation. - .setCurCyclePoints(this.getCyclePoints()) - .setCurCycle(BattlePassCycle.newBuilder() - .setBeginTime(0) - .setEndTime((int) nextSundayTime.atZone(ZoneId.systemDefault()).toEpochSecond()) - .setCycleIdx(3) - ); - - for (BattlePassReward reward : getTakenRewards().values()) { - schedule.addRewardTakenList(reward.toProto()); - } - - return schedule.build(); - } - - public void save() { - DatabaseHelper.saveBattlePass(this); - } -} +package emu.grasscutter.game.battlepass; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.BattlePassRewardData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.RewardData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.MaterialType; +import emu.grasscutter.game.player.BasePlayerDataManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.BattlePassMissionRefreshType; +import emu.grasscutter.game.props.BattlePassMissionStatus; +import emu.grasscutter.game.props.ItemUseOp; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.BattlePassCycleOuterClass.BattlePassCycle; +import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; +import emu.grasscutter.net.proto.BattlePassScheduleOuterClass.BattlePassSchedule; +import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus; +import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify; +import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify; +import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import org.bson.types.ObjectId; + +@Entity(value = "battlepass", useDiscriminator = false) +public class BattlePassManager extends BasePlayerDataManager { + @Id @Getter private ObjectId id; + + @Indexed private int ownerUid; + @Getter private int point; + @Getter private int cyclePoints; // Weekly maximum cap + @Getter private int level; + + @Getter private boolean viewed; + private boolean paid; + + private Map missions; + private Map takenRewards; + + @Deprecated // Morphia only + public BattlePassManager() {} + + public BattlePassManager(Player player) { + super(player); + this.ownerUid = player.getUid(); + } + + public void setPlayer(Player player) { + this.player = player; + this.ownerUid = player.getUid(); + } + + public void updateViewed() { + this.viewed = true; + } + + public boolean setLevel(int level) { + if (level >= 0 && level <= GameConstants.BATTLE_PASS_MAX_LEVEL) { + this.level = level; + this.point = 0; + this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.player)); + return true; + } + return false; + } + + public void addPoints(int points) { + this.addPointsDirectly(points, false); + + this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(player)); + this.save(); + } + + public void addPointsDirectly(int points, boolean isWeekly) { + int amount = points; + + if (isWeekly) { + amount = Math.min(amount, GameConstants.BATTLE_PASS_POINT_PER_WEEK - this.cyclePoints); + } + + if (amount <= 0) { + return; + } + + this.point += amount; + this.cyclePoints += amount; + + if (this.point >= GameConstants.BATTLE_PASS_POINT_PER_LEVEL + && this.getLevel() < GameConstants.BATTLE_PASS_MAX_LEVEL) { + int levelups = Math.floorDiv(this.point, GameConstants.BATTLE_PASS_POINT_PER_LEVEL); + + // Make sure player cant go above max BP level + levelups = Math.min(levelups, GameConstants.BATTLE_PASS_MAX_LEVEL - levelups); + + // Set new points after level up + this.point = this.point - (levelups * GameConstants.BATTLE_PASS_POINT_PER_LEVEL); + this.level += levelups; + } + } + + public Map getMissions() { + if (this.missions == null) this.missions = new HashMap<>(); + return this.missions; + } + + // Will return a new empty mission if the mission id is not found + public BattlePassMission loadMissionById(int id) { + return getMissions().computeIfAbsent(id, i -> new BattlePassMission(i)); + } + + public boolean hasMission(int id) { + return getMissions().containsKey(id); + } + + public boolean isPaid() { + // ToDo: Change this when we actually support unlocking "paid" BP. + return true; + } + + public Map getTakenRewards() { + if (this.takenRewards == null) this.takenRewards = new HashMap<>(); + return this.takenRewards; + } + + // Mission triggers + public void triggerMission(WatcherTriggerType triggerType) { + getPlayer().getServer().getBattlePassSystem().triggerMission(getPlayer(), triggerType); + } + + public void triggerMission(WatcherTriggerType triggerType, int param, int progress) { + getPlayer() + .getServer() + .getBattlePassSystem() + .triggerMission(getPlayer(), triggerType, param, progress); + } + + // Handlers + public void takeMissionPoint(List missionIdList) { + // Obvious exploit check + if (missionIdList.size() > GameData.getBattlePassMissionDataMap().size()) { + return; + } + + List updatedMissions = new ArrayList<>(missionIdList.size()); + + for (int id : missionIdList) { + // Skip if we dont have this mission + if (!this.hasMission(id)) { + continue; + } + + BattlePassMission mission = this.loadMissionById(id); + + if (mission.getData() == null) { + this.getMissions().remove(mission.getId()); + continue; + } + + // Take reward + if (mission.getStatus() == BattlePassMissionStatus.MISSION_STATUS_FINISHED) { + this.addPointsDirectly(mission.getData().getAddPoint(), mission.getData().isCycleRefresh()); + mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_POINT_TAKEN); + + updatedMissions.add(mission); + } + } + + if (updatedMissions.size() > 0) { + // Save to db + this.save(); + + // Packet + getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(updatedMissions)); + getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); + } + } + + private void takeRewardsFromSelectChest( + ItemData rewardItemData, int index, ItemParamData entry, List rewardItems) { + // Sanity checks. + if (rewardItemData.getItemUse().size() < 1) { + return; + } + + // Get possible item choices. + String[] choices = rewardItemData.getItemUse().get(0).getUseParam()[0].split(","); + if (choices.length < index) { + return; + } + + // Get data for the selected item. + // This depends on the type of chest. + int chosenId = Integer.parseInt(choices[index - 1]); + + // For ITEM_USE_ADD_SELECT_ITEM chests, we can directly add the item specified in the chest's + // data. + if (rewardItemData.getItemUse().get(0).getUseOp() == ItemUseOp.ITEM_USE_ADD_SELECT_ITEM) { + GameItem rewardItem = + new GameItem(GameData.getItemDataMap().get(chosenId), entry.getItemCount()); + rewardItems.add(rewardItem); + } + // For ITEM_USE_GRANT_SELECT_REWARD chests, we have to again look up reward data. + else if (rewardItemData.getItemUse().get(0).getUseOp() + == ItemUseOp.ITEM_USE_GRANT_SELECT_REWARD) { + RewardData selectedReward = GameData.getRewardDataMap().get(chosenId); + + for (var r : selectedReward.getRewardItemList()) { + GameItem rewardItem = + new GameItem(GameData.getItemDataMap().get(r.getItemId()), r.getItemCount()); + rewardItems.add(rewardItem); + } + } else { + Grasscutter.getLogger().error("Invalid chest type for BP reward."); + } + } + + public void takeReward(List takeOptionList) { + List rewardList = new ArrayList<>(); + + for (BattlePassRewardTakeOption option : takeOptionList) { + // Duplicate check + if (option.getTag().getRewardId() == 0 + || getTakenRewards().containsKey(option.getTag().getRewardId())) { + continue; + } + + // Level check + if (option.getTag().getLevel() > this.getLevel()) { + continue; + } + + BattlePassRewardData rewardData = + GameData.getBattlePassRewardDataMap() + .get(GameConstants.BATTLE_PASS_CURRENT_INDEX * 100 + option.getTag().getLevel()); + + // Sanity check with excel data + if (rewardData.getFreeRewardIdList().contains(option.getTag().getRewardId())) { + rewardList.add(option); + } else if (this.isPaid() + && rewardData.getPaidRewardIdList().contains(option.getTag().getRewardId())) { + rewardList.add(option); + } else { + Grasscutter.getLogger().info("Not in rewards list: {}", option.getTag().getRewardId()); + } + } + + // Get rewards + List rewardItems = null; + + if (rewardList.size() > 0) { + + rewardItems = new ArrayList<>(); + + for (var option : rewardList) { + var tag = option.getTag(); + int index = option.getOptionIdx(); + + // Make sure we have reward data. + RewardData reward = GameData.getRewardDataMap().get(tag.getRewardId()); + if (reward == null) { + continue; + } + + // Add reward items. + for (var entry : reward.getRewardItemList()) { + ItemData rewardItemData = GameData.getItemDataMap().get(entry.getItemId()); + + // Some rewards are chests where the user can select the item they want. + if (rewardItemData.getMaterialType() == MaterialType.MATERIAL_SELECTABLE_CHEST) { + this.takeRewardsFromSelectChest(rewardItemData, index, entry, rewardItems); + } + // All other rewards directly give us the right item. + else { + GameItem rewardItem = new GameItem(rewardItemData, entry.getItemCount()); + rewardItems.add(rewardItem); + } + } + + // Construct the reward and set as taken. + BattlePassReward bpReward = + new BattlePassReward( + tag.getLevel(), + tag.getRewardId(), + tag.getUnlockStatus() == BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID); + this.getTakenRewards().put(bpReward.getRewardId(), bpReward); + } + + // Save to db + this.save(); + + // Add items and send battle pass schedule packet + getPlayer().getInventory().addItems(rewardItems); + getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); + } + + getPlayer().sendPacket(new PacketTakeBattlePassRewardRsp(takeOptionList, rewardItems)); + } + + public int buyLevels(int buyLevel) { + int boughtLevels = Math.min(buyLevel, GameConstants.BATTLE_PASS_MAX_LEVEL - buyLevel); + + if (boughtLevels > 0) { + int price = GameConstants.BATTLE_PASS_LEVEL_PRICE * boughtLevels; + + if (getPlayer().getPrimogems() < price) { + return 0; + } + + this.level += boughtLevels; + this.save(); + + getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); + } + + return boughtLevels; + } + + public void resetDailyMissions() { + var resetMissions = new ArrayList(); + + for (var mission : this.missions.values()) { + if (mission.getData().getRefreshType() == null + || mission.getData().getRefreshType() + == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_DAILY) { + mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED); + mission.setProgress(0); + + resetMissions.add(mission); + } + } + + this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions)); + this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer())); + } + + public void resetWeeklyMissions() { + var resetMissions = new ArrayList(); + + for (var mission : this.missions.values()) { + if (mission.getData().getRefreshType() + == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE) { + mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED); + mission.setProgress(0); + + resetMissions.add(mission); + } + } + + this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions)); + this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer())); + } + + // + public BattlePassSchedule getScheduleProto() { + var currentDate = LocalDate.now(); + var nextSundayDate = + (currentDate.getDayOfWeek() == DayOfWeek.SUNDAY) + ? currentDate + : LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); + var nextSundayTime = + LocalDateTime.of( + nextSundayDate.getYear(), + nextSundayDate.getMonthValue(), + nextSundayDate.getDayOfMonth(), + 23, + 59, + 59); + + BattlePassSchedule.Builder schedule = + BattlePassSchedule.newBuilder() + .setScheduleId(2700) + .setLevel(this.getLevel()) + .setPoint(this.getPoint()) + .setBeginTime(0) + .setEndTime(2059483200) + .setIsViewed(this.isViewed()) + .setUnlockStatus( + this.isPaid() + ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID + : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE) + .setPaidPlatformFlags(2) // Not bought on Playstation. + .setCurCyclePoints(this.getCyclePoints()) + .setCurCycle( + BattlePassCycle.newBuilder() + .setBeginTime(0) + .setEndTime((int) nextSundayTime.atZone(ZoneId.systemDefault()).toEpochSecond()) + .setCycleIdx(3)); + + for (BattlePassReward reward : getTakenRewards().values()) { + schedule.addRewardTakenList(reward.toProto()); + } + + return schedule.build(); + } + + public void save() { + DatabaseHelper.saveBattlePass(this); + } +} diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassMission.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassMission.java index 98948acdc..1270988ba 100644 --- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassMission.java +++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassMission.java @@ -1,75 +1,75 @@ -package emu.grasscutter.game.battlepass; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.BattlePassMissionData; -import emu.grasscutter.game.props.BattlePassMissionStatus; - -@Entity -public class BattlePassMission { - private int id; - private int progress; - private BattlePassMissionStatus status; - - @Transient - private BattlePassMissionData data; - - @Deprecated // Morphia only - public BattlePassMission() { - } - - public BattlePassMission(int id) { - this.id = id; - } - - public int getId() { - return id; - } - - public BattlePassMissionData getData() { - if (this.data == null) { - this.data = GameData.getBattlePassMissionDataMap().get(getId()); - } - return this.data; - } - - public int getProgress() { - return progress; - } - - public void setProgress(int value) { - this.progress = value; - } - - public void addProgress(int addProgress, int maxProgress) { - this.progress = Math.min(addProgress + this.progress, maxProgress); - } - - public BattlePassMissionStatus getStatus() { - if (status == null) status = BattlePassMissionStatus.MISSION_STATUS_UNFINISHED; - return status; - } - - public void setStatus(BattlePassMissionStatus status) { - this.status = status; - } - - public boolean isFinshed() { - return getStatus().getValue() >= 2; - } - - public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() { - var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder(); - - protoBuilder - .setMissionId(getId()) - .setCurProgress(getProgress()) - .setTotalProgress(getData().getProgress()) - .setRewardBattlePassPoint(getData().getAddPoint()) - .setMissionStatus(getStatus().getMissionStatus()) - .setMissionType(getData().getRefreshType() == null ? 0 : getData().getRefreshType().getValue()); - - return protoBuilder.build(); - } -} +package emu.grasscutter.game.battlepass; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.BattlePassMissionData; +import emu.grasscutter.game.props.BattlePassMissionStatus; + +@Entity +public class BattlePassMission { + private int id; + private int progress; + private BattlePassMissionStatus status; + + @Transient private BattlePassMissionData data; + + @Deprecated // Morphia only + public BattlePassMission() {} + + public BattlePassMission(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public BattlePassMissionData getData() { + if (this.data == null) { + this.data = GameData.getBattlePassMissionDataMap().get(getId()); + } + return this.data; + } + + public int getProgress() { + return progress; + } + + public void setProgress(int value) { + this.progress = value; + } + + public void addProgress(int addProgress, int maxProgress) { + this.progress = Math.min(addProgress + this.progress, maxProgress); + } + + public BattlePassMissionStatus getStatus() { + if (status == null) status = BattlePassMissionStatus.MISSION_STATUS_UNFINISHED; + return status; + } + + public void setStatus(BattlePassMissionStatus status) { + this.status = status; + } + + public boolean isFinshed() { + return getStatus().getValue() >= 2; + } + + public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() { + var protoBuilder = + emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder(); + + protoBuilder + .setMissionId(getId()) + .setCurProgress(getProgress()) + .setTotalProgress(getData().getProgress()) + .setRewardBattlePassPoint(getData().getAddPoint()) + .setMissionStatus(getStatus().getMissionStatus()) + .setMissionType( + getData().getRefreshType() == null ? 0 : getData().getRefreshType().getValue()); + + return protoBuilder.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassReward.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassReward.java index 903af8f7c..524c5b5eb 100644 --- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassReward.java +++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassReward.java @@ -1,50 +1,51 @@ -package emu.grasscutter.game.battlepass; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.data.excels.BattlePassMissionData; -import emu.grasscutter.net.proto.BattlePassRewardTagOuterClass.BattlePassRewardTag; -import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus; - -@Entity -public class BattlePassReward { - private int level; - private int rewardId; - private boolean paid; - - @Transient - private BattlePassMissionData data; - - @Deprecated // Morphia only - public BattlePassReward() { - } - - public BattlePassReward(int level, int rewardId, boolean paid) { - this.level = level; - this.rewardId = rewardId; - this.paid = paid; - } - - public int getLevel() { - return level; - } - - public int getRewardId() { - return rewardId; - } - - public boolean isPaid() { - return paid; - } - - public BattlePassRewardTag toProto() { - var protoBuilder = BattlePassRewardTag.newBuilder(); - - protoBuilder - .setLevel(this.getLevel()) - .setRewardId(this.getRewardId()) - .setUnlockStatus(this.isPaid() ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE); - - return protoBuilder.build(); - } -} +package emu.grasscutter.game.battlepass; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.excels.BattlePassMissionData; +import emu.grasscutter.net.proto.BattlePassRewardTagOuterClass.BattlePassRewardTag; +import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus; + +@Entity +public class BattlePassReward { + private int level; + private int rewardId; + private boolean paid; + + @Transient private BattlePassMissionData data; + + @Deprecated // Morphia only + public BattlePassReward() {} + + public BattlePassReward(int level, int rewardId, boolean paid) { + this.level = level; + this.rewardId = rewardId; + this.paid = paid; + } + + public int getLevel() { + return level; + } + + public int getRewardId() { + return rewardId; + } + + public boolean isPaid() { + return paid; + } + + public BattlePassRewardTag toProto() { + var protoBuilder = BattlePassRewardTag.newBuilder(); + + protoBuilder + .setLevel(this.getLevel()) + .setRewardId(this.getRewardId()) + .setUnlockStatus( + this.isPaid() + ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID + : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE); + + return protoBuilder.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassSystem.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassSystem.java index c91029d45..9d7fbbb0b 100644 --- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassSystem.java +++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassSystem.java @@ -1,78 +1,80 @@ -package emu.grasscutter.game.battlepass; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.BattlePassMissionData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.BattlePassMissionStatus; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class BattlePassSystem extends BaseGameSystem { - private final Map> cachedTriggers; - - // BP Mission manager for the server, contains cached triggers so we dont have to load it for each player - public BattlePassSystem(GameServer server) { - super(server); - - this.cachedTriggers = new HashMap<>(); - - for (BattlePassMissionData missionData : GameData.getBattlePassMissionDataMap().values()) { - if (missionData.isValidRefreshType()) { - List triggerList = getTriggers().computeIfAbsent(missionData.getTriggerType(), e -> new ArrayList<>()); - triggerList.add(missionData); - } - } - } - - public GameServer getServer() { - return server; - } - - private Map> getTriggers() { - return cachedTriggers; - } - - public void triggerMission(Player player, WatcherTriggerType triggerType) { - triggerMission(player, triggerType, 0, 1); - } - - public void triggerMission(Player player, WatcherTriggerType triggerType, int param, int progress) { - List triggerList = getTriggers().get(triggerType); - - if (triggerList == null || triggerList.isEmpty()) return; - - for (BattlePassMissionData data : triggerList) { - // Skip params check if param == 0 - if (param != 0) { - if (!data.getMainParams().contains(param)) { - continue; - } - } - - // Get mission from player, if it doesnt exist, then we make one - BattlePassMission mission = player.getBattlePassManager().loadMissionById(data.getId()); - - if (mission.isFinshed()) continue; - - // Add progress - mission.addProgress(progress, data.getProgress()); - - if (mission.getProgress() >= data.getProgress()) { - mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_FINISHED); - } - - // Save to db - player.getBattlePassManager().save(); - - // Packet - player.sendPacket(new PacketBattlePassMissionUpdateNotify(mission)); - } - } -} +package emu.grasscutter.game.battlepass; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.BattlePassMissionData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.BattlePassMissionStatus; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BattlePassSystem extends BaseGameSystem { + private final Map> cachedTriggers; + + // BP Mission manager for the server, contains cached triggers so we dont have to load it for each + // player + public BattlePassSystem(GameServer server) { + super(server); + + this.cachedTriggers = new HashMap<>(); + + for (BattlePassMissionData missionData : GameData.getBattlePassMissionDataMap().values()) { + if (missionData.isValidRefreshType()) { + List triggerList = + getTriggers().computeIfAbsent(missionData.getTriggerType(), e -> new ArrayList<>()); + triggerList.add(missionData); + } + } + } + + public GameServer getServer() { + return server; + } + + private Map> getTriggers() { + return cachedTriggers; + } + + public void triggerMission(Player player, WatcherTriggerType triggerType) { + triggerMission(player, triggerType, 0, 1); + } + + public void triggerMission( + Player player, WatcherTriggerType triggerType, int param, int progress) { + List triggerList = getTriggers().get(triggerType); + + if (triggerList == null || triggerList.isEmpty()) return; + + for (BattlePassMissionData data : triggerList) { + // Skip params check if param == 0 + if (param != 0) { + if (!data.getMainParams().contains(param)) { + continue; + } + } + + // Get mission from player, if it doesnt exist, then we make one + BattlePassMission mission = player.getBattlePassManager().loadMissionById(data.getId()); + + if (mission.isFinshed()) continue; + + // Add progress + mission.addProgress(progress, data.getProgress()); + + if (mission.getProgress() >= data.getProgress()) { + mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_FINISHED); + } + + // Save to db + player.getBattlePassManager().save(); + + // Packet + player.sendPacket(new PacketBattlePassMissionUpdateNotify(mission)); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/chat/ChatSystem.java b/src/main/java/emu/grasscutter/game/chat/ChatSystem.java index 70ff53a87..2c9cbfa01 100644 --- a/src/main/java/emu/grasscutter/game/chat/ChatSystem.java +++ b/src/main/java/emu/grasscutter/game/chat/ChatSystem.java @@ -1,204 +1,215 @@ -package emu.grasscutter.game.chat; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.PacketPlayerChatNotify; -import emu.grasscutter.server.packet.send.PacketPrivateChatNotify; -import emu.grasscutter.server.packet.send.PacketPullPrivateChatRsp; -import emu.grasscutter.server.packet.send.PacketPullRecentChatRsp; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import static emu.grasscutter.config.Configuration.GAME_INFO; - -public class ChatSystem implements ChatSystemHandler { - static final String PREFIXES = "[/!]"; - static final Pattern RE_PREFIXES = Pattern.compile(PREFIXES); - static final Pattern RE_COMMANDS = Pattern.compile("\n" + PREFIXES); - - // We store the chat history for ongoing sessions in the form - // user id -> chat partner id -> [messages] - private final Map>> history = new HashMap<>(); - - private final GameServer server; - - public ChatSystem(GameServer server) { - this.server = server; - } - - public GameServer getServer() { - return server; - } - - private boolean tryInvokeCommand(Player sender, Player target, String rawMessage) { - if (!RE_PREFIXES.matcher(rawMessage.substring(0, 1)).matches()) - return false; - for (String line : rawMessage.substring(1).split("\n[/!]")) - CommandMap.getInstance().invoke(sender, target, line); - return true; - } - - /******************** - * Chat history handling - ********************/ - private void putInHistory(int uid, int partnerId, ChatInfo info) { - this.history.computeIfAbsent(uid, x -> new HashMap<>()) - .computeIfAbsent(partnerId, x -> new ArrayList<>()) - .add(info); - } - - public void clearHistoryOnLogout(Player player) { - this.history.remove(player.getUid()); - } - - public void handlePullPrivateChatReq(Player player, int partnerId) { - var chatHistory = this.history.computeIfAbsent(player.getUid(), x -> new HashMap<>()) - .computeIfAbsent(partnerId, x -> new ArrayList<>()); - player.sendPacket(new PacketPullPrivateChatRsp(chatHistory)); - } - - public void handlePullRecentChatReq(Player player) { - // If this user has no chat history yet, create it by sending the server welcome messages. - if (!this.history.computeIfAbsent(player.getUid(), x -> new HashMap<>()).containsKey(GameConstants.SERVER_CONSOLE_UID)) { - this.sendServerWelcomeMessages(player); - } - - // For now, we send the list three messages from the server for the recent chat history. - // This matches the previous behavior, but ultimately, we should probably keep track of the last chat partner - // for every given player and return the last messages exchanged with that partner. - int historyLength = this.history.get(player.getUid()).get(GameConstants.SERVER_CONSOLE_UID).size(); - var messages = this.history.get(player.getUid()).get(GameConstants.SERVER_CONSOLE_UID).subList(Math.max(historyLength - 3, 0), historyLength); - player.sendPacket(new PacketPullRecentChatRsp(messages)); - } - - /******************** - * Sending messages - ********************/ - public void sendPrivateMessageFromServer(int targetUid, String message) { - // Sanity checks. - if (message == null || message.length() == 0) { - return; - } - - // Get target. - Player target = getServer().getPlayerByUid(targetUid); - if (target == null) { - return; - } - - // Create chat packet and put in history. - var packet = new PacketPrivateChatNotify(GameConstants.SERVER_CONSOLE_UID, targetUid, message); - putInHistory(targetUid, GameConstants.SERVER_CONSOLE_UID, packet.getChatInfo()); - - // Send. - target.sendPacket(packet); - } - - public void sendPrivateMessageFromServer(int targetUid, int emote) { - // Get target. - Player target = getServer().getPlayerByUid(targetUid); - if (target == null) { - return; - } - - // Create chat packet and put in history. - var packet = new PacketPrivateChatNotify(GameConstants.SERVER_CONSOLE_UID, targetUid, emote); - putInHistory(targetUid, GameConstants.SERVER_CONSOLE_UID, packet.getChatInfo()); - - // Send. - target.sendPacket(packet); - } - - public void sendPrivateMessage(Player player, int targetUid, String message) { - // Sanity checks. - if (message == null || message.length() == 0) { - return; - } - - // Get target. - Player target = getServer().getPlayerByUid(targetUid); - - if (target == null && targetUid != GameConstants.SERVER_CONSOLE_UID) { - return; - } - - // Create chat packet. - var packet = new PacketPrivateChatNotify(player.getUid(), targetUid, message); - - // Send and put in history. - player.sendPacket(packet); - putInHistory(player.getUid(), targetUid, packet.getChatInfo()); - - // Check if command - boolean isCommand = tryInvokeCommand(player, target, message); - - if ((target != null) && (!isCommand)) { - target.sendPacket(packet); - putInHistory(targetUid, player.getUid(), packet.getChatInfo()); - } - } - - public void sendPrivateMessage(Player player, int targetUid, int emote) { - // Get target. - Player target = getServer().getPlayerByUid(targetUid); - - if (target == null && targetUid != GameConstants.SERVER_CONSOLE_UID) { - return; - } - - // Create chat packet. - var packet = new PacketPrivateChatNotify(player.getUid(), target.getUid(), emote); - - // Send and put is history. - player.sendPacket(packet); - putInHistory(player.getUid(), targetUid, packet.getChatInfo()); - - if (target != null) { - target.sendPacket(packet); - putInHistory(targetUid, player.getUid(), packet.getChatInfo()); - } - } - - public void sendTeamMessage(Player player, int channel, String message) { - // Sanity checks - if (message == null || message.length() == 0) { - return; - } - - // Check if command - if (tryInvokeCommand(player, null, message)) { - return; - } - - // Create and send chat packet - player.getWorld().broadcastPacket(new PacketPlayerChatNotify(player, channel, message)); - } - - public void sendTeamMessage(Player player, int channel, int icon) { - // Create and send chat packet - player.getWorld().broadcastPacket(new PacketPlayerChatNotify(player, channel, icon)); - } - - /******************** - * Welcome messages - ********************/ - private void sendServerWelcomeMessages(Player player) { - var joinOptions = GAME_INFO.joinOptions; - - if (joinOptions.welcomeEmotes != null && joinOptions.welcomeEmotes.length > 0) { - this.sendPrivateMessageFromServer(player.getUid(), joinOptions.welcomeEmotes[Utils.randomRange(0, joinOptions.welcomeEmotes.length - 1)]); - } - - if (joinOptions.welcomeMessage != null && joinOptions.welcomeMessage.length() > 0) { - this.sendPrivateMessageFromServer(player.getUid(), joinOptions.welcomeMessage); - } - } -} +package emu.grasscutter.game.chat; + +import static emu.grasscutter.config.Configuration.GAME_INFO; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.PacketPlayerChatNotify; +import emu.grasscutter.server.packet.send.PacketPrivateChatNotify; +import emu.grasscutter.server.packet.send.PacketPullPrivateChatRsp; +import emu.grasscutter.server.packet.send.PacketPullRecentChatRsp; +import emu.grasscutter.utils.Utils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +public class ChatSystem implements ChatSystemHandler { + static final String PREFIXES = "[/!]"; + static final Pattern RE_PREFIXES = Pattern.compile(PREFIXES); + static final Pattern RE_COMMANDS = Pattern.compile("\n" + PREFIXES); + + // We store the chat history for ongoing sessions in the form + // user id -> chat partner id -> [messages] + private final Map>> history = new HashMap<>(); + + private final GameServer server; + + public ChatSystem(GameServer server) { + this.server = server; + } + + public GameServer getServer() { + return server; + } + + private boolean tryInvokeCommand(Player sender, Player target, String rawMessage) { + if (!RE_PREFIXES.matcher(rawMessage.substring(0, 1)).matches()) return false; + for (String line : rawMessage.substring(1).split("\n[/!]")) + CommandMap.getInstance().invoke(sender, target, line); + return true; + } + + /******************** + * Chat history handling + ********************/ + private void putInHistory(int uid, int partnerId, ChatInfo info) { + this.history + .computeIfAbsent(uid, x -> new HashMap<>()) + .computeIfAbsent(partnerId, x -> new ArrayList<>()) + .add(info); + } + + public void clearHistoryOnLogout(Player player) { + this.history.remove(player.getUid()); + } + + public void handlePullPrivateChatReq(Player player, int partnerId) { + var chatHistory = + this.history + .computeIfAbsent(player.getUid(), x -> new HashMap<>()) + .computeIfAbsent(partnerId, x -> new ArrayList<>()); + player.sendPacket(new PacketPullPrivateChatRsp(chatHistory)); + } + + public void handlePullRecentChatReq(Player player) { + // If this user has no chat history yet, create it by sending the server welcome messages. + if (!this.history + .computeIfAbsent(player.getUid(), x -> new HashMap<>()) + .containsKey(GameConstants.SERVER_CONSOLE_UID)) { + this.sendServerWelcomeMessages(player); + } + + // For now, we send the list three messages from the server for the recent chat history. + // This matches the previous behavior, but ultimately, we should probably keep track of the last + // chat partner + // for every given player and return the last messages exchanged with that partner. + int historyLength = + this.history.get(player.getUid()).get(GameConstants.SERVER_CONSOLE_UID).size(); + var messages = + this.history + .get(player.getUid()) + .get(GameConstants.SERVER_CONSOLE_UID) + .subList(Math.max(historyLength - 3, 0), historyLength); + player.sendPacket(new PacketPullRecentChatRsp(messages)); + } + + /******************** + * Sending messages + ********************/ + public void sendPrivateMessageFromServer(int targetUid, String message) { + // Sanity checks. + if (message == null || message.length() == 0) { + return; + } + + // Get target. + Player target = getServer().getPlayerByUid(targetUid); + if (target == null) { + return; + } + + // Create chat packet and put in history. + var packet = new PacketPrivateChatNotify(GameConstants.SERVER_CONSOLE_UID, targetUid, message); + putInHistory(targetUid, GameConstants.SERVER_CONSOLE_UID, packet.getChatInfo()); + + // Send. + target.sendPacket(packet); + } + + public void sendPrivateMessageFromServer(int targetUid, int emote) { + // Get target. + Player target = getServer().getPlayerByUid(targetUid); + if (target == null) { + return; + } + + // Create chat packet and put in history. + var packet = new PacketPrivateChatNotify(GameConstants.SERVER_CONSOLE_UID, targetUid, emote); + putInHistory(targetUid, GameConstants.SERVER_CONSOLE_UID, packet.getChatInfo()); + + // Send. + target.sendPacket(packet); + } + + public void sendPrivateMessage(Player player, int targetUid, String message) { + // Sanity checks. + if (message == null || message.length() == 0) { + return; + } + + // Get target. + Player target = getServer().getPlayerByUid(targetUid); + + if (target == null && targetUid != GameConstants.SERVER_CONSOLE_UID) { + return; + } + + // Create chat packet. + var packet = new PacketPrivateChatNotify(player.getUid(), targetUid, message); + + // Send and put in history. + player.sendPacket(packet); + putInHistory(player.getUid(), targetUid, packet.getChatInfo()); + + // Check if command + boolean isCommand = tryInvokeCommand(player, target, message); + + if ((target != null) && (!isCommand)) { + target.sendPacket(packet); + putInHistory(targetUid, player.getUid(), packet.getChatInfo()); + } + } + + public void sendPrivateMessage(Player player, int targetUid, int emote) { + // Get target. + Player target = getServer().getPlayerByUid(targetUid); + + if (target == null && targetUid != GameConstants.SERVER_CONSOLE_UID) { + return; + } + + // Create chat packet. + var packet = new PacketPrivateChatNotify(player.getUid(), target.getUid(), emote); + + // Send and put is history. + player.sendPacket(packet); + putInHistory(player.getUid(), targetUid, packet.getChatInfo()); + + if (target != null) { + target.sendPacket(packet); + putInHistory(targetUid, player.getUid(), packet.getChatInfo()); + } + } + + public void sendTeamMessage(Player player, int channel, String message) { + // Sanity checks + if (message == null || message.length() == 0) { + return; + } + + // Check if command + if (tryInvokeCommand(player, null, message)) { + return; + } + + // Create and send chat packet + player.getWorld().broadcastPacket(new PacketPlayerChatNotify(player, channel, message)); + } + + public void sendTeamMessage(Player player, int channel, int icon) { + // Create and send chat packet + player.getWorld().broadcastPacket(new PacketPlayerChatNotify(player, channel, icon)); + } + + /******************** + * Welcome messages + ********************/ + private void sendServerWelcomeMessages(Player player) { + var joinOptions = GAME_INFO.joinOptions; + + if (joinOptions.welcomeEmotes != null && joinOptions.welcomeEmotes.length > 0) { + this.sendPrivateMessageFromServer( + player.getUid(), + joinOptions.welcomeEmotes[Utils.randomRange(0, joinOptions.welcomeEmotes.length - 1)]); + } + + if (joinOptions.welcomeMessage != null && joinOptions.welcomeMessage.length() > 0) { + this.sendPrivateMessageFromServer(player.getUid(), joinOptions.welcomeMessage); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/chat/ChatSystemHandler.java b/src/main/java/emu/grasscutter/game/chat/ChatSystemHandler.java index 89f5f973b..a9fe93905 100644 --- a/src/main/java/emu/grasscutter/game/chat/ChatSystemHandler.java +++ b/src/main/java/emu/grasscutter/game/chat/ChatSystemHandler.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.chat; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.game.GameServer; - -public interface ChatSystemHandler { - GameServer getServer(); - - void sendPrivateMessage(Player player, int targetUid, String message); - - void sendPrivateMessage(Player player, int targetUid, int emote); - - void sendTeamMessage(Player player, int channel, String message); - - void sendTeamMessage(Player player, int channel, int icon); - - void sendPrivateMessageFromServer(int targetUid, String message); - - void sendPrivateMessageFromServer(int targetUid, int emote); - - void handlePullPrivateChatReq(Player player, int targetUid); - - void clearHistoryOnLogout(Player player); - - void handlePullRecentChatReq(Player player); -} +package emu.grasscutter.game.chat; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.game.GameServer; + +public interface ChatSystemHandler { + GameServer getServer(); + + void sendPrivateMessage(Player player, int targetUid, String message); + + void sendPrivateMessage(Player player, int targetUid, int emote); + + void sendTeamMessage(Player player, int channel, String message); + + void sendTeamMessage(Player player, int channel, int icon); + + void sendPrivateMessageFromServer(int targetUid, String message); + + void sendPrivateMessageFromServer(int targetUid, int emote); + + void handlePullPrivateChatReq(Player player, int targetUid); + + void clearHistoryOnLogout(Player player); + + void handlePullRecentChatReq(Player player); +} diff --git a/src/main/java/emu/grasscutter/game/combine/CombineManger.java b/src/main/java/emu/grasscutter/game/combine/CombineManger.java index 9f9c55cbe..0167e27f8 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineManger.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineManger.java @@ -1,132 +1,143 @@ -package emu.grasscutter.game.combine; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.CombineData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify; -import emu.grasscutter.server.packet.send.PacketCombineRsp; -import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.ArrayList; -import java.util.List; - -public class CombineManger extends BaseGameSystem { - private final static Int2ObjectMap> reliquaryDecomposeData = new Int2ObjectOpenHashMap<>(); - - public CombineManger(GameServer server) { - super(server); - } - - public static void initialize() { - // Read the data we need for strongbox. - try { - DataLoader.loadList("ReliquaryDecompose.json", ReliquaryDecomposeEntry.class).forEach(entry -> { - reliquaryDecomposeData.put(entry.getConfigId(), entry.getItems()); - }); - Grasscutter.getLogger().debug("Loaded {} reliquary decompose entries.", reliquaryDecomposeData.size()); - } catch (Exception ex) { - Grasscutter.getLogger().error("Unable to load reliquary decompose data.", ex); - } - } - - public boolean unlockCombineDiagram(Player player, int combineId) { - if (!player.getUnlockedCombines().add(combineId)) { - return false; // Already unlocked - } - // Tell the client that this diagram is now unlocked and add the unlocked item to the player. - player.sendPacket(new PacketCombineFormulaDataNotify(combineId)); - return true; - } - - public CombineResult combineItem(Player player, int cid, int count) { - // check config exist - if (!GameData.getCombineDataMap().containsKey(cid)) { - player.getWorld().getHost().sendPacket(new PacketCombineRsp()); - return null; - } - - CombineData combineData = GameData.getCombineDataMap().get(cid); - - if (combineData.getPlayerLevel() > player.getLevel()) { - return null; - } - - // consume items - List material = new ArrayList<>(combineData.getMaterialItems()); - material.add(new ItemParamData(202, combineData.getScoinCost())); - - boolean success = player.getInventory().payItems(material, count, ActionReason.Combine); - - // abort if not enough material - if (!success) { - player.sendPacket(new PacketCombineRsp(RetcodeOuterClass.Retcode.RET_ITEM_COMBINE_COUNT_NOT_ENOUGH_VALUE)); - } - - // make the result - player.getInventory().addItem(combineData.getResultItemId(), - combineData.getResultItemCount() * count); - - CombineResult result = new CombineResult(); - result.setMaterial(List.of()); - result.setResult(List.of(new ItemParamData(combineData.getResultItemId(), - combineData.getResultItemCount() * count))); - // TODO lucky characters - result.setExtra(List.of()); - result.setBack(List.of()); - - return result; - } - - public synchronized void decomposeReliquaries(Player player, int configId, int count, List input) { - // Check if the configId is legal. - List possibleDrops = reliquaryDecomposeData.get(configId); - if (possibleDrops == null) { - player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); - return; - } - - // Check if the number of input items matches the output count. - if (input.size() != count * 3) { - player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); - return; - } - - // Check if all the input reliquaries actually are in the player's inventory. - for (long guid : input) { - if (player.getInventory().getItemByGuid(guid) == null) { - player.sendPacket(new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); - return; - } - } - - // Delete the input reliquaries. - for (long guid : input) { - player.getInventory().removeItem(guid); - } - - // Generate outoput reliquaries. - List resultItems = new ArrayList<>(); - for (int i = 0; i < count; i++) { - int itemId = Utils.drawRandomListElement(possibleDrops); - GameItem newReliquary = new GameItem(itemId, 1); - - player.getInventory().addItem(newReliquary); - resultItems.add(newReliquary.getGuid()); - } - - // Send packet. - player.sendPacket(new PacketReliquaryDecomposeRsp(resultItems)); - } -} +package emu.grasscutter.game.combine; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CombineData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify; +import emu.grasscutter.server.packet.send.PacketCombineRsp; +import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.List; + +public class CombineManger extends BaseGameSystem { + private static final Int2ObjectMap> reliquaryDecomposeData = + new Int2ObjectOpenHashMap<>(); + + public CombineManger(GameServer server) { + super(server); + } + + public static void initialize() { + // Read the data we need for strongbox. + try { + DataLoader.loadList("ReliquaryDecompose.json", ReliquaryDecomposeEntry.class) + .forEach( + entry -> { + reliquaryDecomposeData.put(entry.getConfigId(), entry.getItems()); + }); + Grasscutter.getLogger() + .debug("Loaded {} reliquary decompose entries.", reliquaryDecomposeData.size()); + } catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load reliquary decompose data.", ex); + } + } + + public boolean unlockCombineDiagram(Player player, int combineId) { + if (!player.getUnlockedCombines().add(combineId)) { + return false; // Already unlocked + } + // Tell the client that this diagram is now unlocked and add the unlocked item to the player. + player.sendPacket(new PacketCombineFormulaDataNotify(combineId)); + return true; + } + + public CombineResult combineItem(Player player, int cid, int count) { + // check config exist + if (!GameData.getCombineDataMap().containsKey(cid)) { + player.getWorld().getHost().sendPacket(new PacketCombineRsp()); + return null; + } + + CombineData combineData = GameData.getCombineDataMap().get(cid); + + if (combineData.getPlayerLevel() > player.getLevel()) { + return null; + } + + // consume items + List material = new ArrayList<>(combineData.getMaterialItems()); + material.add(new ItemParamData(202, combineData.getScoinCost())); + + boolean success = player.getInventory().payItems(material, count, ActionReason.Combine); + + // abort if not enough material + if (!success) { + player.sendPacket( + new PacketCombineRsp(RetcodeOuterClass.Retcode.RET_ITEM_COMBINE_COUNT_NOT_ENOUGH_VALUE)); + } + + // make the result + player + .getInventory() + .addItem(combineData.getResultItemId(), combineData.getResultItemCount() * count); + + CombineResult result = new CombineResult(); + result.setMaterial(List.of()); + result.setResult( + List.of( + new ItemParamData( + combineData.getResultItemId(), combineData.getResultItemCount() * count))); + // TODO lucky characters + result.setExtra(List.of()); + result.setBack(List.of()); + + return result; + } + + public synchronized void decomposeReliquaries( + Player player, int configId, int count, List input) { + // Check if the configId is legal. + List possibleDrops = reliquaryDecomposeData.get(configId); + if (possibleDrops == null) { + player.sendPacket( + new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); + return; + } + + // Check if the number of input items matches the output count. + if (input.size() != count * 3) { + player.sendPacket( + new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); + return; + } + + // Check if all the input reliquaries actually are in the player's inventory. + for (long guid : input) { + if (player.getInventory().getItemByGuid(guid) == null) { + player.sendPacket( + new PacketReliquaryDecomposeRsp(Retcode.RET_RELIQUARY_DECOMPOSE_PARAM_ERROR)); + return; + } + } + + // Delete the input reliquaries. + for (long guid : input) { + player.getInventory().removeItem(guid); + } + + // Generate outoput reliquaries. + List resultItems = new ArrayList<>(); + for (int i = 0; i < count; i++) { + int itemId = Utils.drawRandomListElement(possibleDrops); + GameItem newReliquary = new GameItem(itemId, 1); + + player.getInventory().addItem(newReliquary); + resultItems.add(newReliquary.getGuid()); + } + + // Send packet. + player.sendPacket(new PacketReliquaryDecomposeRsp(resultItems)); + } +} diff --git a/src/main/java/emu/grasscutter/game/combine/CombineResult.java b/src/main/java/emu/grasscutter/game/combine/CombineResult.java index 75a78e0cf..6ac92bdd0 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineResult.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineResult.java @@ -1,45 +1,43 @@ -package emu.grasscutter.game.combine; - -import emu.grasscutter.data.common.ItemParamData; - -import java.util.List; - -public class CombineResult { - private List material; - private List result; - private List extra; - private List back; - - public List getMaterial() { - return material; - } - - public void setMaterial(List material) { - this.material = material; - } - - public List getResult() { - return result; - } - - public void setResult(List result) { - this.result = result; - } - - public List getExtra() { - return extra; - } - - public void setExtra(List extra) { - this.extra = extra; - } - - public List getBack() { - return back; - } - - public void setBack(List back) { - this.back = back; - } - -} +package emu.grasscutter.game.combine; + +import emu.grasscutter.data.common.ItemParamData; +import java.util.List; + +public class CombineResult { + private List material; + private List result; + private List extra; + private List back; + + public List getMaterial() { + return material; + } + + public void setMaterial(List material) { + this.material = material; + } + + public List getResult() { + return result; + } + + public void setResult(List result) { + this.result = result; + } + + public List getExtra() { + return extra; + } + + public void setExtra(List extra) { + this.extra = extra; + } + + public List getBack() { + return back; + } + + public void setBack(List back) { + this.back = back; + } +} diff --git a/src/main/java/emu/grasscutter/game/combine/ReliquaryDecomposeEntry.java b/src/main/java/emu/grasscutter/game/combine/ReliquaryDecomposeEntry.java index 856278535..34c7eaa96 100644 --- a/src/main/java/emu/grasscutter/game/combine/ReliquaryDecomposeEntry.java +++ b/src/main/java/emu/grasscutter/game/combine/ReliquaryDecomposeEntry.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.combine; - -import java.util.List; - -public class ReliquaryDecomposeEntry { - private int configId; - private List items; - - public int getConfigId() { - return configId; - } - - public void setConfigId(int configId) { - this.configId = configId; - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} +package emu.grasscutter.game.combine; + +import java.util.List; + +public class ReliquaryDecomposeEntry { + private int configId; + private List items; + + public int getConfigId() { + return configId; + } + + public void setConfigId(int configId) { + this.configId = configId; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +} diff --git a/src/main/java/emu/grasscutter/game/drop/DropData.java b/src/main/java/emu/grasscutter/game/drop/DropData.java index 601ae0487..f1b99a8aa 100644 --- a/src/main/java/emu/grasscutter/game/drop/DropData.java +++ b/src/main/java/emu/grasscutter/game/drop/DropData.java @@ -1,55 +1,51 @@ -package emu.grasscutter.game.drop; - -public class DropData { - private int minWeight; - private int maxWeight; - private int itemId; - private int minCount; - private int maxCount; - private boolean share = false; - private boolean give = false; - - public boolean isGive() { - return give; - } - - public void setGive(boolean give) { - this.give = give; - } - - public int getItemId() { - return itemId; - } - - public void setItemId(int itemId) { - this.itemId = itemId; - } - - public int getMinCount() { - return minCount; - } - - - public int getMaxCount() { - return maxCount; - } - - - public int getMinWeight() { - return minWeight; - } - - public int getMaxWeight() { - return maxWeight; - } - - - public boolean isShare() { - return share; - } - - public void setIsShare(boolean share) { - this.share = share; - } - -} +package emu.grasscutter.game.drop; + +public class DropData { + private int minWeight; + private int maxWeight; + private int itemId; + private int minCount; + private int maxCount; + private boolean share = false; + private boolean give = false; + + public boolean isGive() { + return give; + } + + public void setGive(boolean give) { + this.give = give; + } + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public int getMinCount() { + return minCount; + } + + public int getMaxCount() { + return maxCount; + } + + public int getMinWeight() { + return minWeight; + } + + public int getMaxWeight() { + return maxWeight; + } + + public boolean isShare() { + return share; + } + + public void setIsShare(boolean share) { + this.share = share; + } +} diff --git a/src/main/java/emu/grasscutter/game/drop/DropInfo.java b/src/main/java/emu/grasscutter/game/drop/DropInfo.java index 8ba401eaf..54a0ab8ad 100644 --- a/src/main/java/emu/grasscutter/game/drop/DropInfo.java +++ b/src/main/java/emu/grasscutter/game/drop/DropInfo.java @@ -1,16 +1,16 @@ -package emu.grasscutter.game.drop; - -import java.util.List; - -public class DropInfo { - private int monsterId; - private List dropDataList; - - public int getMonsterId() { - return monsterId; - } - - public List getDropDataList() { - return dropDataList; - } -} +package emu.grasscutter.game.drop; + +import java.util.List; + +public class DropInfo { + private int monsterId; + private List dropDataList; + + public int getMonsterId() { + return monsterId; + } + + public List getDropDataList() { + return dropDataList; + } +} diff --git a/src/main/java/emu/grasscutter/game/drop/DropSystem.java b/src/main/java/emu/grasscutter/game/drop/DropSystem.java index 874507d2c..e04dd0cd2 100644 --- a/src/main/java/emu/grasscutter/game/drop/DropSystem.java +++ b/src/main/java/emu/grasscutter/game/drop/DropSystem.java @@ -1,107 +1,111 @@ -package emu.grasscutter.game.drop; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.entity.EntityItem; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.List; - -public class DropSystem extends BaseGameSystem { - private final Int2ObjectMap> dropData; - - public DropSystem(GameServer server) { - super(server); - this.dropData = new Int2ObjectOpenHashMap<>(); - this.load(); - } - - public Int2ObjectMap> getDropData() { - return dropData; - } - - public synchronized void load() { - getDropData().clear(); - try { - List banners = DataLoader.loadList("Drop.json", DropInfo.class); - if (banners.size() > 0) { - for (DropInfo di : banners) { - getDropData().put(di.getMonsterId(), di.getDropDataList()); - } - Grasscutter.getLogger().debug("Drop data successfully loaded."); - } else { - Grasscutter.getLogger().error("Unable to load drop data. Drop data size is 0."); - } - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load drop data.", e); - } - } - - private void addDropEntity(DropData dd, Scene dropScene, ItemData itemData, Position pos, int num, Player target) { - if (!dd.isGive() && (itemData.getItemType() != ItemType.ITEM_VIRTUAL || itemData.getGadgetId() != 0)) { - EntityItem entity = new EntityItem(dropScene, target, itemData, pos, num, dd.isShare()); - if (!dd.isShare()) - dropScene.addEntityToSingleClient(target, entity); - else - dropScene.addEntity(entity); - } else { - if (target != null) { - target.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true); - } else { - // target is null if items will be added are shared. no one could pick it up because of the combination(give + shared) - // so it will be sent to all players' inventories directly. - dropScene.getPlayers().forEach(x -> x.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true)); - } - } - } - - private void processDrop(DropData dd, EntityMonster em, Player gp) { - int target = Utils.randomRange(1, 10000); - if (target >= dd.getMinWeight() && target < dd.getMaxWeight()) { - ItemData itemData = GameData.getItemDataMap().get(dd.getItemId()); - int num = Utils.randomRange(dd.getMinCount(), dd.getMaxCount()); - - if (itemData == null) { - return; - } - if (itemData.isEquip()) { - for (int i = 0; i < num; i++) { - float range = (2.5f + (.05f * num)); - Position pos = em.getPosition().nearby2d(range).addY(3f); - addDropEntity(dd, em.getScene(), itemData, pos, num, gp); - } - } else { - Position pos = em.getPosition().clone().addY(3f); - addDropEntity(dd, em.getScene(), itemData, pos, num, gp); - } - } - } - - public void callDrop(EntityMonster em) { - int id = em.getMonsterData().getId(); - if (getDropData().containsKey(id)) { - for (DropData dd : getDropData().get(id)) { - if (dd.isShare()) - processDrop(dd, em, null); - else { - for (Player gp : em.getScene().getPlayers()) { - processDrop(dd, em, gp); - } - } - } - } - } -} +package emu.grasscutter.game.drop; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.List; + +public class DropSystem extends BaseGameSystem { + private final Int2ObjectMap> dropData; + + public DropSystem(GameServer server) { + super(server); + this.dropData = new Int2ObjectOpenHashMap<>(); + this.load(); + } + + public Int2ObjectMap> getDropData() { + return dropData; + } + + public synchronized void load() { + getDropData().clear(); + try { + List banners = DataLoader.loadList("Drop.json", DropInfo.class); + if (banners.size() > 0) { + for (DropInfo di : banners) { + getDropData().put(di.getMonsterId(), di.getDropDataList()); + } + Grasscutter.getLogger().debug("Drop data successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load drop data. Drop data size is 0."); + } + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load drop data.", e); + } + } + + private void addDropEntity( + DropData dd, Scene dropScene, ItemData itemData, Position pos, int num, Player target) { + if (!dd.isGive() + && (itemData.getItemType() != ItemType.ITEM_VIRTUAL || itemData.getGadgetId() != 0)) { + EntityItem entity = new EntityItem(dropScene, target, itemData, pos, num, dd.isShare()); + if (!dd.isShare()) dropScene.addEntityToSingleClient(target, entity); + else dropScene.addEntity(entity); + } else { + if (target != null) { + target.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true); + } else { + // target is null if items will be added are shared. no one could pick it up because of the + // combination(give + shared) + // so it will be sent to all players' inventories directly. + dropScene + .getPlayers() + .forEach( + x -> + x.getInventory() + .addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true)); + } + } + } + + private void processDrop(DropData dd, EntityMonster em, Player gp) { + int target = Utils.randomRange(1, 10000); + if (target >= dd.getMinWeight() && target < dd.getMaxWeight()) { + ItemData itemData = GameData.getItemDataMap().get(dd.getItemId()); + int num = Utils.randomRange(dd.getMinCount(), dd.getMaxCount()); + + if (itemData == null) { + return; + } + if (itemData.isEquip()) { + for (int i = 0; i < num; i++) { + float range = (2.5f + (.05f * num)); + Position pos = em.getPosition().nearby2d(range).addY(3f); + addDropEntity(dd, em.getScene(), itemData, pos, num, gp); + } + } else { + Position pos = em.getPosition().clone().addY(3f); + addDropEntity(dd, em.getScene(), itemData, pos, num, gp); + } + } + } + + public void callDrop(EntityMonster em) { + int id = em.getMonsterData().getId(); + if (getDropData().containsKey(id)) { + for (DropData dd : getDropData().get(id)) { + if (dd.isShare()) processDrop(dd, em, null); + else { + for (Player gp : em.getScene().getPlayers()) { + processDrop(dd, em, gp); + } + } + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonDrop.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonDrop.java index f329eab9c..84e435544 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonDrop.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonDrop.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.dungeons; - -import java.util.List; - -public class DungeonDrop { - private int dungeonId; - private List drops; - - public int getDungeonId() { - return dungeonId; - } - - public void setDungeonId(int dungeonId) { - this.dungeonId = dungeonId; - } - - public List getDrops() { - return drops; - } - - public void setDrops(List drops) { - this.drops = drops; - } -} +package emu.grasscutter.game.dungeons; + +import java.util.List; + +public class DungeonDrop { + private int dungeonId; + private List drops; + + public int getDungeonId() { + return dungeonId; + } + + public void setDungeonId(int dungeonId) { + this.dungeonId = dungeonId; + } + + public List getDrops() { + return drops; + } + + public void setDrops(List drops) { + this.drops = drops; + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonDropEntry.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonDropEntry.java index 80e7b80af..b20554ba4 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonDropEntry.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonDropEntry.java @@ -1,51 +1,51 @@ -package emu.grasscutter.game.dungeons; - -import java.util.List; - -public class DungeonDropEntry { - private List counts; - private List items; - private List probabilities; - private List itemProbabilities; - private boolean mpDouble; - - public List getCounts() { - return counts; - } - - public void setCounts(List counts) { - this.counts = counts; - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - - public List getProbabilities() { - return probabilities; - } - - public void setProbabilities(List probabilities) { - this.probabilities = probabilities; - } - - public List getItemProbabilities() { - return itemProbabilities; - } - - public void setItemProbabilities(List itemProbabilities) { - this.itemProbabilities = itemProbabilities; - } - - public boolean isMpDouble() { - return mpDouble; - } - - public void setMpDouble(boolean mpDouble) { - this.mpDouble = mpDouble; - } -} +package emu.grasscutter.game.dungeons; + +import java.util.List; + +public class DungeonDropEntry { + private List counts; + private List items; + private List probabilities; + private List itemProbabilities; + private boolean mpDouble; + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public List getProbabilities() { + return probabilities; + } + + public void setProbabilities(List probabilities) { + this.probabilities = probabilities; + } + + public List getItemProbabilities() { + return itemProbabilities; + } + + public void setItemProbabilities(List itemProbabilities) { + this.itemProbabilities = itemProbabilities; + } + + public boolean isMpDouble() { + return mpDouble; + } + + public void setMpDouble(boolean mpDouble) { + this.mpDouble = mpDouble; + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonSystem.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonSystem.java index 502af561e..30cf583da 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonSystem.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonSystem.java @@ -1,112 +1,122 @@ -package emu.grasscutter.game.dungeons; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ScenePointEntry; -import emu.grasscutter.data.excels.DungeonData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp; -import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp; -import emu.grasscutter.utils.Position; - -import java.util.List; - -public class DungeonSystem extends BaseGameSystem { - private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener(); - - public DungeonSystem(GameServer server) { - super(server); - } - - public void getEntryInfo(Player player, int pointId) { - ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId); - - if (entry == null) { - // Error - player.sendPacket(new PacketDungeonEntryInfoRsp()); - return; - } - - player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData())); - } - - public boolean enterDungeon(Player player, int pointId, int dungeonId) { - DungeonData data = GameData.getDungeonDataMap().get(dungeonId); - - if (data == null) { - return false; - } - Grasscutter.getLogger().info("{}({}) is trying to enter dungeon {}", player.getNickname(), player.getUid(), dungeonId); - - int sceneId = data.getSceneId(); - player.getScene().setPrevScene(sceneId); - - if (player.getWorld().transferPlayerToScene(player, sceneId, data)) { - player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); - player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId()); - } - - player.getScene().setPrevScenePoint(pointId); - player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId)); - return true; - } - - /** - * used in tower dungeons handoff - */ - public boolean handoffDungeon(Player player, int dungeonId, List dungeonSettleListeners) { - DungeonData data = GameData.getDungeonDataMap().get(dungeonId); - - if (data == null) { - return false; - } - Grasscutter.getLogger().info("{}({}) is trying to enter tower dungeon {}", player.getNickname(), player.getUid(), dungeonId); - - if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) { - dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver); - } - return true; - } - - public void exitDungeon(Player player) { - Scene scene = player.getScene(); - - if (scene == null || scene.getSceneType() != SceneType.SCENE_DUNGEON) { - return; - } - - // Get previous scene - int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3; - - // Get previous position - DungeonData dungeonData = scene.getDungeonData(); - Position prevPos = new Position(GameConstants.START_POSITION); - - if (dungeonData != null) { - ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint()); - - if (entry != null) { - prevPos.set(entry.getPointData().getTranPos()); - } - } - // clean temp team if it has - player.getTeamManager().cleanTemporaryTeam(); - player.getTowerManager().clearEntry(); - - // Transfer player back to world - player.getWorld().transferPlayerToScene(player, prevScene, prevPos); - player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp)); - } - - public void updateDailyDungeons() { - GameData.getScenePointEntries().forEach((id, entry) -> entry.getPointData().updateDailyDungeon()); - } -} +package emu.grasscutter.game.dungeons; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.data.excels.DungeonData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp; +import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp; +import emu.grasscutter.utils.Position; +import java.util.List; + +public class DungeonSystem extends BaseGameSystem { + private static final BasicDungeonSettleListener basicDungeonSettleObserver = + new BasicDungeonSettleListener(); + + public DungeonSystem(GameServer server) { + super(server); + } + + public void getEntryInfo(Player player, int pointId) { + ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId); + + if (entry == null) { + // Error + player.sendPacket(new PacketDungeonEntryInfoRsp()); + return; + } + + player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData())); + } + + public boolean enterDungeon(Player player, int pointId, int dungeonId) { + DungeonData data = GameData.getDungeonDataMap().get(dungeonId); + + if (data == null) { + return false; + } + Grasscutter.getLogger() + .info( + "{}({}) is trying to enter dungeon {}", + player.getNickname(), + player.getUid(), + dungeonId); + + int sceneId = data.getSceneId(); + player.getScene().setPrevScene(sceneId); + + if (player.getWorld().transferPlayerToScene(player, sceneId, data)) { + player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); + player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId()); + } + + player.getScene().setPrevScenePoint(pointId); + player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId)); + return true; + } + + /** used in tower dungeons handoff */ + public boolean handoffDungeon( + Player player, int dungeonId, List dungeonSettleListeners) { + DungeonData data = GameData.getDungeonDataMap().get(dungeonId); + + if (data == null) { + return false; + } + Grasscutter.getLogger() + .info( + "{}({}) is trying to enter tower dungeon {}", + player.getNickname(), + player.getUid(), + dungeonId); + + if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) { + dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver); + } + return true; + } + + public void exitDungeon(Player player) { + Scene scene = player.getScene(); + + if (scene == null || scene.getSceneType() != SceneType.SCENE_DUNGEON) { + return; + } + + // Get previous scene + int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3; + + // Get previous position + DungeonData dungeonData = scene.getDungeonData(); + Position prevPos = new Position(GameConstants.START_POSITION); + + if (dungeonData != null) { + ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint()); + + if (entry != null) { + prevPos.set(entry.getPointData().getTranPos()); + } + } + // clean temp team if it has + player.getTeamManager().cleanTemporaryTeam(); + player.getTowerManager().clearEntry(); + + // Transfer player back to world + player.getWorld().transferPlayerToScene(player, prevScene, prevPos); + player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp)); + } + + public void updateDailyDungeons() { + GameData.getScenePointEntries() + .forEach((id, entry) -> entry.getPointData().updateDailyDungeon()); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java index c45c079d5..7005608dc 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java +++ b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java @@ -1,34 +1,31 @@ -package emu.grasscutter.game.dungeons; - -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; -import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify; -import emu.grasscutter.utils.Utils; - -public class TowerDungeonSettleListener implements DungeonSettleListener { - - @Override - public void onDungeonSettle(Scene scene) { - if (scene.getScriptManager().getVariables().containsKey("stage") - && scene.getScriptManager().getVariables().get("stage") == 1) { - return; - } - scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000); - var towerManager = scene.getPlayers().get(0).getTowerManager(); - - towerManager.notifyCurLevelRecordChangeWhenDone(3); - scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify( - towerManager.getCurrentFloorId(), - 3, - towerManager.canEnterScheduleFloor() - )); - - scene.broadcastPacket(new PacketDungeonSettleNotify( - scene.getChallenge(), - towerManager.hasNextFloor(), - towerManager.hasNextLevel(), - towerManager.hasNextLevel() ? 0 : towerManager.getNextFloorId() - )); - - } -} +package emu.grasscutter.game.dungeons; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; +import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify; +import emu.grasscutter.utils.Utils; + +public class TowerDungeonSettleListener implements DungeonSettleListener { + + @Override + public void onDungeonSettle(Scene scene) { + if (scene.getScriptManager().getVariables().containsKey("stage") + && scene.getScriptManager().getVariables().get("stage") == 1) { + return; + } + scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000); + var towerManager = scene.getPlayers().get(0).getTowerManager(); + + towerManager.notifyCurLevelRecordChangeWhenDone(3); + scene.broadcastPacket( + new PacketTowerFloorRecordChangeNotify( + towerManager.getCurrentFloorId(), 3, towerManager.canEnterScheduleFloor())); + + scene.broadcastPacket( + new PacketDungeonSettleNotify( + scene.getChallenge(), + towerManager.hasNextFloor(), + towerManager.hasNextLevel(), + towerManager.hasNextLevel() ? 0 : towerManager.getNextFloorId())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java index 5702a7a1d..8be5ca139 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/DungeonChallenge.java @@ -1,194 +1,213 @@ -package emu.grasscutter.game.dungeons.challenge; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.DungeonData; -import emu.grasscutter.game.dungeons.DungeonDrop; -import emu.grasscutter.game.dungeons.DungeonDropEntry; -import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.ResinCostTypeOuterClass; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify; -import emu.grasscutter.utils.Utils; -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 java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class DungeonChallenge extends WorldChallenge { - - private final static Int2ObjectMap> dungeonDropData = new Int2ObjectOpenHashMap<>(); - /** - * has more challenge - */ - private boolean stage; - private IntSet rewardedPlayers; - - public DungeonChallenge(Scene scene, SceneGroup group, - int challengeId, int challengeIndex, - List paramList, - int timeLimit, int goal, - List challengeTriggers) { - super(scene, group, challengeId, challengeIndex, paramList, timeLimit, goal, challengeTriggers); - this.setRewardedPlayers(new IntOpenHashSet()); - } - - public static void initialize() { - // Read the data we need for dungeon rewards drops. - try { - DataLoader.loadList("DungeonDrop.json", DungeonDrop.class).forEach(entry -> { - dungeonDropData.put(entry.getDungeonId(), entry.getDrops()); - }); - Grasscutter.getLogger().debug("Loaded {} dungeon drop data entries.", dungeonDropData.size()); - } catch (Exception ex) { - Grasscutter.getLogger().error("Unable to load dungeon drop data.", ex); - } - } - - public boolean isStage() { - return stage; - } - - public void setStage(boolean stage) { - this.stage = stage; - } - - public IntSet getRewardedPlayers() { - return rewardedPlayers; - } - - public void setRewardedPlayers(IntSet rewardedPlayers) { - this.rewardedPlayers = rewardedPlayers; - } - - @Override - public void done() { - super.done(); - if (this.isSuccess()) { - // Settle - settle(); - } - } - - private void settle() { - if (!stage) { - var scene = this.getScene(); - scene.getDungeonSettleListeners().forEach(o -> o.onDungeonSettle(getScene())); - scene.getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, - new ScriptArgs(this.isSuccess() ? 1 : 0)); - // Battle pass trigger - scene.getPlayers().forEach(p -> p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON)); - } - } - - private List rollRewards(boolean useCondensed) { - List rewards = new ArrayList<>(); - int dungeonId = this.getScene().getDungeonData().getId(); - // If we have specific drop data for this dungeon, we use it. - if (dungeonDropData.containsKey(dungeonId)) { - List dropEntries = dungeonDropData.get(dungeonId); - - // Roll for each drop group. - for (var entry : dropEntries) { - // Determine the number of drops we get for this entry. - int start = entry.getCounts().get(0); - int end = entry.getCounts().get(entry.getCounts().size() - 1); - var candidateAmounts = IntStream.range(start, end + 1).boxed().collect(Collectors.toList()); - - int amount = Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities()); - - if (useCondensed) { - amount += Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities()); - } - - // Double rewards in multiplay mode, if specified. - if (entry.isMpDouble() && this.getScene().getPlayerCount() > 1) { - amount *= 2; - } - - // Roll items for this group. - // Here, we have to handle stacking, or the client will not display results correctly. - // For now, we use the following logic: If the possible drop item are a list of multiple items, - // we roll them separately. If not, we stack them. This should work out in practice, at least - // for the currently existing set of dungeons. - if (entry.getItems().size() == 1) { - rewards.add(new GameItem(entry.getItems().get(0), amount)); - } else { - for (int i = 0; i < amount; i++) { - // int itemIndex = ThreadLocalRandom.current().nextInt(0, entry.getItems().size()); - // int itemId = entry.getItems().get(itemIndex); - int itemId = Utils.drawRandomListElement(entry.getItems(), entry.getItemProbabilities()); - rewards.add(new GameItem(itemId, 1)); - } - } - } - } - // Otherwise, we fall back to the preview data. - else { - Grasscutter.getLogger().info("No drop data found or dungeon {}, falling back to preview data ...", dungeonId); - for (ItemParamData param : getScene().getDungeonData().getRewardPreview().getPreviewItems()) { - rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); - } - } - - return rewards; - } - - public void getStatueDrops(Player player, GadgetInteractReq request) { - DungeonData dungeonData = getScene().getDungeonData(); - int resinCost = dungeonData.getStatueCostCount() != 0 ? dungeonData.getStatueCostCount() : 20; - - if (!isSuccess() || dungeonData == null || dungeonData.getRewardPreview() == null || dungeonData.getRewardPreview().getPreviewItems().length == 0) { - return; - } - - // Already rewarded - if (getRewardedPlayers().contains(player.getUid())) { - return; - } - - // Get rewards. - List rewards = new ArrayList<>(); - - if (request.getResinCostType() == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE) { - // Check if condensed resin is usable here. - // For this, we use the following logic for now: - // The normal resin cost of the dungeon has to be 20. - if (resinCost != 20) { - return; - } - - // Spend the condensed resin and only proceed if the transaction succeeds. - if (!player.getResinManager().useCondensedResin(1)) return; - - // Roll rewards. - rewards.addAll(this.rollRewards(true)); - } else { - // Spend the resin and only proceed if the transaction succeeds. - if (!player.getResinManager().useResin(resinCost)) return; - - // Roll rewards. - rewards.addAll(this.rollRewards(false)); - } - - // Add rewards to player and send notification. - player.getInventory().addItems(rewards, ActionReason.DungeonStatueDrop); - player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards)); - - getRewardedPlayers().add(player.getUid()); - } -} +package emu.grasscutter.game.dungeons.challenge; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.DungeonData; +import emu.grasscutter.game.dungeons.DungeonDrop; +import emu.grasscutter.game.dungeons.DungeonDropEntry; +import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.ResinCostTypeOuterClass; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify; +import emu.grasscutter.utils.Utils; +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 java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class DungeonChallenge extends WorldChallenge { + + private static final Int2ObjectMap> dungeonDropData = + new Int2ObjectOpenHashMap<>(); + /** has more challenge */ + private boolean stage; + + private IntSet rewardedPlayers; + + public DungeonChallenge( + Scene scene, + SceneGroup group, + int challengeId, + int challengeIndex, + List paramList, + int timeLimit, + int goal, + List challengeTriggers) { + super(scene, group, challengeId, challengeIndex, paramList, timeLimit, goal, challengeTriggers); + this.setRewardedPlayers(new IntOpenHashSet()); + } + + public static void initialize() { + // Read the data we need for dungeon rewards drops. + try { + DataLoader.loadList("DungeonDrop.json", DungeonDrop.class) + .forEach( + entry -> { + dungeonDropData.put(entry.getDungeonId(), entry.getDrops()); + }); + Grasscutter.getLogger().debug("Loaded {} dungeon drop data entries.", dungeonDropData.size()); + } catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load dungeon drop data.", ex); + } + } + + public boolean isStage() { + return stage; + } + + public void setStage(boolean stage) { + this.stage = stage; + } + + public IntSet getRewardedPlayers() { + return rewardedPlayers; + } + + public void setRewardedPlayers(IntSet rewardedPlayers) { + this.rewardedPlayers = rewardedPlayers; + } + + @Override + public void done() { + super.done(); + if (this.isSuccess()) { + // Settle + settle(); + } + } + + private void settle() { + if (!stage) { + var scene = this.getScene(); + scene.getDungeonSettleListeners().forEach(o -> o.onDungeonSettle(getScene())); + scene + .getScriptManager() + .callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); + // Battle pass trigger + scene + .getPlayers() + .forEach( + p -> + p.getBattlePassManager() + .triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON)); + } + } + + private List rollRewards(boolean useCondensed) { + List rewards = new ArrayList<>(); + int dungeonId = this.getScene().getDungeonData().getId(); + // If we have specific drop data for this dungeon, we use it. + if (dungeonDropData.containsKey(dungeonId)) { + List dropEntries = dungeonDropData.get(dungeonId); + + // Roll for each drop group. + for (var entry : dropEntries) { + // Determine the number of drops we get for this entry. + int start = entry.getCounts().get(0); + int end = entry.getCounts().get(entry.getCounts().size() - 1); + var candidateAmounts = IntStream.range(start, end + 1).boxed().collect(Collectors.toList()); + + int amount = Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities()); + + if (useCondensed) { + amount += Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities()); + } + + // Double rewards in multiplay mode, if specified. + if (entry.isMpDouble() && this.getScene().getPlayerCount() > 1) { + amount *= 2; + } + + // Roll items for this group. + // Here, we have to handle stacking, or the client will not display results correctly. + // For now, we use the following logic: If the possible drop item are a list of multiple + // items, + // we roll them separately. If not, we stack them. This should work out in practice, at + // least + // for the currently existing set of dungeons. + if (entry.getItems().size() == 1) { + rewards.add(new GameItem(entry.getItems().get(0), amount)); + } else { + for (int i = 0; i < amount; i++) { + // int itemIndex = ThreadLocalRandom.current().nextInt(0, entry.getItems().size()); + // int itemId = entry.getItems().get(itemIndex); + int itemId = + Utils.drawRandomListElement(entry.getItems(), entry.getItemProbabilities()); + rewards.add(new GameItem(itemId, 1)); + } + } + } + } + // Otherwise, we fall back to the preview data. + else { + Grasscutter.getLogger() + .info("No drop data found or dungeon {}, falling back to preview data ...", dungeonId); + for (ItemParamData param : getScene().getDungeonData().getRewardPreview().getPreviewItems()) { + rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); + } + } + + return rewards; + } + + public void getStatueDrops(Player player, GadgetInteractReq request) { + DungeonData dungeonData = getScene().getDungeonData(); + int resinCost = dungeonData.getStatueCostCount() != 0 ? dungeonData.getStatueCostCount() : 20; + + if (!isSuccess() + || dungeonData == null + || dungeonData.getRewardPreview() == null + || dungeonData.getRewardPreview().getPreviewItems().length == 0) { + return; + } + + // Already rewarded + if (getRewardedPlayers().contains(player.getUid())) { + return; + } + + // Get rewards. + List rewards = new ArrayList<>(); + + if (request.getResinCostType() + == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE) { + // Check if condensed resin is usable here. + // For this, we use the following logic for now: + // The normal resin cost of the dungeon has to be 20. + if (resinCost != 20) { + return; + } + + // Spend the condensed resin and only proceed if the transaction succeeds. + if (!player.getResinManager().useCondensedResin(1)) return; + + // Roll rewards. + rewards.addAll(this.rollRewards(true)); + } else { + // Spend the resin and only proceed if the transaction succeeds. + if (!player.getResinManager().useResin(resinCost)) return; + + // Roll rewards. + rewards.addAll(this.rollRewards(false)); + } + + // Add rewards to player and send notification. + player.getInventory().addItems(rewards, ActionReason.DungeonStatueDrop); + player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards)); + + getRewardedPlayers().add(player.getUid()); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/WorldChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/WorldChallenge.java index 127b0e9bc..4e304e3d0 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/WorldChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/WorldChallenge.java @@ -1,137 +1,144 @@ -package emu.grasscutter.game.dungeons.challenge; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify; -import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -@Getter -@Setter -public class WorldChallenge { - private final Scene scene; - private final SceneGroup group; - private final int challengeId; - private final int challengeIndex; - private final List paramList; - private final int timeLimit; - private final List challengeTriggers; - private final int goal; - private final AtomicInteger score; - private boolean progress; - private boolean success; - private long startedAt; - private int finishedTime; - - public WorldChallenge(Scene scene, SceneGroup group, - int challengeId, int challengeIndex, List paramList, - int timeLimit, int goal, - List challengeTriggers) { - this.scene = scene; - this.group = group; - this.challengeId = challengeId; - this.challengeIndex = challengeIndex; - this.paramList = paramList; - this.timeLimit = timeLimit; - this.challengeTriggers = challengeTriggers; - this.goal = goal; - this.score = new AtomicInteger(0); - } - - public boolean inProgress() { - return this.progress; - } - - public void onCheckTimeOut() { - if (!inProgress()) { - return; - } - if (timeLimit <= 0) { - return; - } - challengeTriggers.forEach(t -> t.onCheckTimeout(this)); - } - - public void start() { - if (inProgress()) { - Grasscutter.getLogger().info("Could not start a in progress challenge."); - return; - } - this.progress = true; - this.startedAt = System.currentTimeMillis(); - getScene().broadcastPacket(new PacketDungeonChallengeBeginNotify(this)); - challengeTriggers.forEach(t -> t.onBegin(this)); - } - - public void done() { - if (!inProgress()) { - return; - } - finish(true); - this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, - // TODO record the time in PARAM2 and used in action - new ScriptArgs().setParam2(finishedTime)); - - challengeTriggers.forEach(t -> t.onFinish(this)); - } - - public void fail() { - if (!inProgress()) { - return; - } - finish(false); - this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_FAIL, null); - challengeTriggers.forEach(t -> t.onFinish(this)); - } - - private void finish(boolean success) { - this.progress = false; - this.success = success; - this.finishedTime = (int) ((System.currentTimeMillis() - this.startedAt) / 1000L); - getScene().broadcastPacket(new PacketDungeonChallengeFinishNotify(this)); - } - - public int increaseScore() { - return score.incrementAndGet(); - } - - public void onMonsterDeath(EntityMonster monster) { - if (!inProgress()) { - return; - } - if (monster.getGroupId() != getGroup().id) { - return; - } - this.challengeTriggers.forEach(t -> t.onMonsterDeath(this, monster)); - } - - public void onGadgetDeath(EntityGadget gadget) { - if (!inProgress()) { - return; - } - if (gadget.getGroupId() != getGroup().id) { - return; - } - this.challengeTriggers.forEach(t -> t.onGadgetDeath(this, gadget)); - } - - public void onGadgetDamage(EntityGadget gadget) { - if (!inProgress()) { - return; - } - if (gadget.getGroupId() != getGroup().id) { - return; - } - this.challengeTriggers.forEach(t -> t.onGadgetDamage(this, gadget)); - } -} +package emu.grasscutter.game.dungeons.challenge; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify; +import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class WorldChallenge { + private final Scene scene; + private final SceneGroup group; + private final int challengeId; + private final int challengeIndex; + private final List paramList; + private final int timeLimit; + private final List challengeTriggers; + private final int goal; + private final AtomicInteger score; + private boolean progress; + private boolean success; + private long startedAt; + private int finishedTime; + + public WorldChallenge( + Scene scene, + SceneGroup group, + int challengeId, + int challengeIndex, + List paramList, + int timeLimit, + int goal, + List challengeTriggers) { + this.scene = scene; + this.group = group; + this.challengeId = challengeId; + this.challengeIndex = challengeIndex; + this.paramList = paramList; + this.timeLimit = timeLimit; + this.challengeTriggers = challengeTriggers; + this.goal = goal; + this.score = new AtomicInteger(0); + } + + public boolean inProgress() { + return this.progress; + } + + public void onCheckTimeOut() { + if (!inProgress()) { + return; + } + if (timeLimit <= 0) { + return; + } + challengeTriggers.forEach(t -> t.onCheckTimeout(this)); + } + + public void start() { + if (inProgress()) { + Grasscutter.getLogger().info("Could not start a in progress challenge."); + return; + } + this.progress = true; + this.startedAt = System.currentTimeMillis(); + getScene().broadcastPacket(new PacketDungeonChallengeBeginNotify(this)); + challengeTriggers.forEach(t -> t.onBegin(this)); + } + + public void done() { + if (!inProgress()) { + return; + } + finish(true); + this.getScene() + .getScriptManager() + .callEvent( + EventType.EVENT_CHALLENGE_SUCCESS, + // TODO record the time in PARAM2 and used in action + new ScriptArgs().setParam2(finishedTime)); + + challengeTriggers.forEach(t -> t.onFinish(this)); + } + + public void fail() { + if (!inProgress()) { + return; + } + finish(false); + this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_FAIL, null); + challengeTriggers.forEach(t -> t.onFinish(this)); + } + + private void finish(boolean success) { + this.progress = false; + this.success = success; + this.finishedTime = (int) ((System.currentTimeMillis() - this.startedAt) / 1000L); + getScene().broadcastPacket(new PacketDungeonChallengeFinishNotify(this)); + } + + public int increaseScore() { + return score.incrementAndGet(); + } + + public void onMonsterDeath(EntityMonster monster) { + if (!inProgress()) { + return; + } + if (monster.getGroupId() != getGroup().id) { + return; + } + this.challengeTriggers.forEach(t -> t.onMonsterDeath(this, monster)); + } + + public void onGadgetDeath(EntityGadget gadget) { + if (!inProgress()) { + return; + } + if (gadget.getGroupId() != getGroup().id) { + return; + } + this.challengeTriggers.forEach(t -> t.onGadgetDeath(this, gadget)); + } + + public void onGadgetDamage(EntityGadget gadget) { + if (!inProgress()) { + return; + } + if (gadget.getGroupId() != getGroup().id) { + return; + } + this.challengeTriggers.forEach(t -> t.onGadgetDamage(this, gadget)); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactory.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactory.java index a99b6d472..8ac893f6a 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactory.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactory.java @@ -1,30 +1,37 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -import java.util.ArrayList; -import java.util.List; - -public class ChallengeFactory { - - private static final List challengeFactoryHandlers = new ArrayList<>(); - - static { - challengeFactoryHandlers.add(new DungeonChallengeFactoryHandler()); - challengeFactoryHandlers.add(new DungeonGuardChallengeFactoryHandler()); - challengeFactoryHandlers.add(new KillGadgetChallengeFactoryHandler()); - challengeFactoryHandlers.add(new KillMonsterChallengeFactoryHandler()); - } - - public static WorldChallenge getChallenge(int param1, int param2, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - for (var handler : challengeFactoryHandlers) { - if (!handler.isThisType(param1, param2, param3, param4, param5, param6, scene, group)) { - continue; - } - return handler.build(param1, param2, param3, param4, param5, param6, scene, group); - } - return null; - } -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.ArrayList; +import java.util.List; + +public class ChallengeFactory { + + private static final List challengeFactoryHandlers = new ArrayList<>(); + + static { + challengeFactoryHandlers.add(new DungeonChallengeFactoryHandler()); + challengeFactoryHandlers.add(new DungeonGuardChallengeFactoryHandler()); + challengeFactoryHandlers.add(new KillGadgetChallengeFactoryHandler()); + challengeFactoryHandlers.add(new KillMonsterChallengeFactoryHandler()); + } + + public static WorldChallenge getChallenge( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + for (var handler : challengeFactoryHandlers) { + if (!handler.isThisType(param1, param2, param3, param4, param5, param6, scene, group)) { + continue; + } + return handler.build(param1, param2, param3, param4, param5, param6, scene, group); + } + return null; + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactoryHandler.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactoryHandler.java index 0c30e95f9..cdf3c6820 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactoryHandler.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/ChallengeFactoryHandler.java @@ -1,11 +1,27 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -public interface ChallengeFactoryHandler { - boolean isThisType(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group); - - WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group); -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; + +public interface ChallengeFactoryHandler { + boolean isThisType( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group); + + WorldChallenge build( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group); +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonChallengeFactoryHandler.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonChallengeFactoryHandler.java index e5cee82fa..72108f3ba 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonChallengeFactoryHandler.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonChallengeFactoryHandler.java @@ -1,33 +1,48 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; -import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -import java.util.List; - -public class DungeonChallengeFactoryHandler implements ChallengeFactoryHandler { - @Override - public boolean isThisType(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - // ActiveChallenge with 1,1000,300,233101003,15,0 - return scene.getSceneType() == SceneType.SCENE_DUNGEON - && param4 == group.id; - } - - @Override - public WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - var realGroup = scene.getScriptManager().getGroupById(param4); - return new DungeonChallenge( - scene, realGroup, - challengeId, // Id - challengeIndex, // Index - List.of(param5, param3), - param3, // Limit - param5, // Goal - List.of(new InTimeTrigger(), new KillMonsterTrigger())); - } -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; +import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.List; + +public class DungeonChallengeFactoryHandler implements ChallengeFactoryHandler { + @Override + public boolean isThisType( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + // ActiveChallenge with 1,1000,300,233101003,15,0 + return scene.getSceneType() == SceneType.SCENE_DUNGEON && param4 == group.id; + } + + @Override + public WorldChallenge build( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + var realGroup = scene.getScriptManager().getGroupById(param4); + return new DungeonChallenge( + scene, + realGroup, + challengeId, // Id + challengeIndex, // Index + List.of(param5, param3), + param3, // Limit + param5, // Goal + List.of(new InTimeTrigger(), new KillMonsterTrigger())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonGuardChallengeFactoryHandler.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonGuardChallengeFactoryHandler.java index 96fa48cac..4456ab759 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonGuardChallengeFactoryHandler.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/DungeonGuardChallengeFactoryHandler.java @@ -1,32 +1,47 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger; -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -import java.util.List; - -public class DungeonGuardChallengeFactoryHandler implements ChallengeFactoryHandler { - @Override - public boolean isThisType(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - // ActiveChallenge with 1,188,234101003,12,3030,0 - return scene.getSceneType() == SceneType.SCENE_DUNGEON - && param3 == group.id; - } - - @Override - public WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - var realGroup = scene.getScriptManager().getGroupById(param3); - return new DungeonChallenge( - scene, realGroup, - challengeId, // Id - challengeIndex, // Index - List.of(param4, 0), - 0, // Limit - param4, // Goal - List.of(new GuardTrigger())); - } -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger; +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.List; + +public class DungeonGuardChallengeFactoryHandler implements ChallengeFactoryHandler { + @Override + public boolean isThisType( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + // ActiveChallenge with 1,188,234101003,12,3030,0 + return scene.getSceneType() == SceneType.SCENE_DUNGEON && param3 == group.id; + } + + @Override + public WorldChallenge build( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + var realGroup = scene.getScriptManager().getGroupById(param3); + return new DungeonChallenge( + scene, + realGroup, + challengeId, // Id + challengeIndex, // Index + List.of(param4, 0), + 0, // Limit + param4, // Goal + List.of(new GuardTrigger())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillGadgetChallengeFactoryHandler.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillGadgetChallengeFactoryHandler.java index 71ccecc33..60f1fa07d 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillGadgetChallengeFactoryHandler.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillGadgetChallengeFactoryHandler.java @@ -1,33 +1,48 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; -import emu.grasscutter.game.dungeons.challenge.trigger.KillGadgetTrigger; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -import java.util.List; - -public class KillGadgetChallengeFactoryHandler implements ChallengeFactoryHandler { - @Override - public boolean isThisType(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - // kill gadgets(explosive barrel) in time - // ActiveChallenge with 56,201,20,2,201,4 - // open chest in time - // ActiveChallenge with 666,202,30,7,202,1 - return challengeId == 201 || challengeId == 202; - } - - @Override - public WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - return new WorldChallenge( - scene, group, - challengeId, // Id - challengeIndex, // Index - List.of(param3, param6, 0), - param3, // Limit - param6, // Goal - List.of(new InTimeTrigger(), new KillGadgetTrigger()) - ); - } -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; +import emu.grasscutter.game.dungeons.challenge.trigger.KillGadgetTrigger; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.List; + +public class KillGadgetChallengeFactoryHandler implements ChallengeFactoryHandler { + @Override + public boolean isThisType( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + // kill gadgets(explosive barrel) in time + // ActiveChallenge with 56,201,20,2,201,4 + // open chest in time + // ActiveChallenge with 666,202,30,7,202,1 + return challengeId == 201 || challengeId == 202; + } + + @Override + public WorldChallenge build( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + return new WorldChallenge( + scene, + group, + challengeId, // Id + challengeIndex, // Index + List.of(param3, param6, 0), + param3, // Limit + param6, // Goal + List.of(new InTimeTrigger(), new KillGadgetTrigger())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillMonsterChallengeFactoryHandler.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillMonsterChallengeFactoryHandler.java index 72bd4b75b..98f708e30 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillMonsterChallengeFactoryHandler.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/factory/KillMonsterChallengeFactoryHandler.java @@ -1,31 +1,46 @@ -package emu.grasscutter.game.dungeons.challenge.factory; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; -import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneGroup; - -import java.util.List; - -public class KillMonsterChallengeFactoryHandler implements ChallengeFactoryHandler { - @Override - public boolean isThisType(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - // ActiveChallenge with 180,180,45,133108061,1,0 - return challengeId == 180; - } - - @Override - public WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group) { - var realGroup = scene.getScriptManager().getGroupById(param4); - return new WorldChallenge( - scene, realGroup, - challengeId, // Id - challengeIndex, // Index - List.of(param5, param3), - param3, // Limit - param5, // Goal - List.of(new KillMonsterTrigger(), new InTimeTrigger()) - ); - } -} +package emu.grasscutter.game.dungeons.challenge.factory; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; +import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneGroup; +import java.util.List; + +public class KillMonsterChallengeFactoryHandler implements ChallengeFactoryHandler { + @Override + public boolean isThisType( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + // ActiveChallenge with 180,180,45,133108061,1,0 + return challengeId == 180; + } + + @Override + public WorldChallenge build( + int challengeIndex, + int challengeId, + int param3, + int param4, + int param5, + int param6, + Scene scene, + SceneGroup group) { + var realGroup = scene.getScriptManager().getGroupById(param4); + return new WorldChallenge( + scene, + realGroup, + challengeId, // Id + challengeIndex, // Index + List.of(param5, param3), + param3, // Limit + param5, // Goal + List.of(new KillMonsterTrigger(), new InTimeTrigger())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/ChallengeTrigger.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/ChallengeTrigger.java index ebb0f48ee..1608cf144 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/ChallengeTrigger.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/ChallengeTrigger.java @@ -1,25 +1,19 @@ -package emu.grasscutter.game.dungeons.challenge.trigger; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityMonster; - -public abstract class ChallengeTrigger { - public void onBegin(WorldChallenge challenge) { - } - - public void onFinish(WorldChallenge challenge) { - } - - public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) { - } - - public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) { - } - - public void onCheckTimeout(WorldChallenge challenge) { - } - - public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) { - } -} +package emu.grasscutter.game.dungeons.challenge.trigger; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityMonster; + +public abstract class ChallengeTrigger { + public void onBegin(WorldChallenge challenge) {} + + public void onFinish(WorldChallenge challenge) {} + + public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) {} + + public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) {} + + public void onCheckTimeout(WorldChallenge challenge) {} + + public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) {} +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/GuardTrigger.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/GuardTrigger.java index c1588a974..8104931ef 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/GuardTrigger.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/GuardTrigger.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.dungeons.challenge.trigger; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; - -public class GuardTrigger extends KillMonsterTrigger { - @Override - public void onBegin(WorldChallenge challenge) { - super.onBegin(challenge); - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, 100)); - } - - @Override - public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) { - var curHp = gadget.getFightProperties().get(FightProperty.FIGHT_PROP_CUR_HP.getId()); - var maxHp = gadget.getFightProperties().get(FightProperty.FIGHT_PROP_BASE_HP.getId()); - int percent = (int) (curHp / maxHp); - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, percent)); - - if (percent <= 0) { - challenge.fail(); - } - } -} +package emu.grasscutter.game.dungeons.challenge.trigger; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; + +public class GuardTrigger extends KillMonsterTrigger { + @Override + public void onBegin(WorldChallenge challenge) { + super.onBegin(challenge); + challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, 100)); + } + + @Override + public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) { + var curHp = gadget.getFightProperties().get(FightProperty.FIGHT_PROP_CUR_HP.getId()); + var maxHp = gadget.getFightProperties().get(FightProperty.FIGHT_PROP_BASE_HP.getId()); + int percent = (int) (curHp / maxHp); + challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, percent)); + + if (percent <= 0) { + challenge.fail(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/InTimeTrigger.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/InTimeTrigger.java index 5aeb01ee3..649a8665a 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/InTimeTrigger.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/InTimeTrigger.java @@ -1,13 +1,13 @@ -package emu.grasscutter.game.dungeons.challenge.trigger; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; - -public class InTimeTrigger extends ChallengeTrigger { - @Override - public void onCheckTimeout(WorldChallenge challenge) { - var current = System.currentTimeMillis(); - if (current - challenge.getStartedAt() > challenge.getTimeLimit() * 1000L) { - challenge.fail(); - } - } -} +package emu.grasscutter.game.dungeons.challenge.trigger; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; + +public class InTimeTrigger extends ChallengeTrigger { + @Override + public void onCheckTimeout(WorldChallenge challenge) { + var current = System.currentTimeMillis(); + if (current - challenge.getStartedAt() > challenge.getTimeLimit() * 1000L) { + challenge.fail(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillGadgetTrigger.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillGadgetTrigger.java index 9f8b87ce8..520184462 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillGadgetTrigger.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillGadgetTrigger.java @@ -1,23 +1,24 @@ -package emu.grasscutter.game.dungeons.challenge.trigger; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; - -public class KillGadgetTrigger extends ChallengeTrigger { - @Override - public void onBegin(WorldChallenge challenge) { - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, challenge.getScore().get())); - } - - @Override - public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) { - var newScore = challenge.increaseScore(); - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, newScore)); - - if (newScore >= challenge.getGoal()) { - challenge.done(); - } - - } -} +package emu.grasscutter.game.dungeons.challenge.trigger; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; + +public class KillGadgetTrigger extends ChallengeTrigger { + @Override + public void onBegin(WorldChallenge challenge) { + challenge + .getScene() + .broadcastPacket(new PacketChallengeDataNotify(challenge, 2, challenge.getScore().get())); + } + + @Override + public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) { + var newScore = challenge.increaseScore(); + challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 2, newScore)); + + if (newScore >= challenge.getGoal()) { + challenge.done(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillMonsterTrigger.java b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillMonsterTrigger.java index e3cce9d2c..e41b1f0d7 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillMonsterTrigger.java +++ b/src/main/java/emu/grasscutter/game/dungeons/challenge/trigger/KillMonsterTrigger.java @@ -1,23 +1,24 @@ -package emu.grasscutter.game.dungeons.challenge.trigger; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; - -public class KillMonsterTrigger extends ChallengeTrigger { - @Override - public void onBegin(WorldChallenge challenge) { - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, challenge.getScore().get())); - } - - @Override - public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) { - var newScore = challenge.increaseScore(); - challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, newScore)); - - if (newScore >= challenge.getGoal()) { - challenge.done(); - } - - } -} +package emu.grasscutter.game.dungeons.challenge.trigger; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; + +public class KillMonsterTrigger extends ChallengeTrigger { + @Override + public void onBegin(WorldChallenge challenge) { + challenge + .getScene() + .broadcastPacket(new PacketChallengeDataNotify(challenge, 1, challenge.getScore().get())); + } + + @Override + public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) { + var newScore = challenge.increaseScore(); + challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, newScore)); + + if (newScore >= challenge.getGoal()) { + challenge.done(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java index 4dade5362..49c21bd90 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java @@ -1,330 +1,347 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.inventory.EquipType; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock; -import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.server.event.player.PlayerMoveEvent; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import lombok.Getter; -import lombok.val; - -public class EntityAvatar extends GameEntity { - @Getter - private final Avatar avatar; - - @Getter - private PlayerDieType killedType; - @Getter - private int killedBy; - - public EntityAvatar(Avatar avatar) { - this(null, avatar); - } - - public EntityAvatar(Scene scene, Avatar avatar) { - super(scene); - this.avatar = avatar; - this.avatar.setCurrentEnergy(); - if (getScene() != null) { - this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR); - - GameItem weapon = getAvatar().getWeapon(); - if (weapon != null) { - weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON)); - } - } - } - - public Player getPlayer() { - return this.avatar.getPlayer(); - } - - @Override - public Position getPosition() { - return getPlayer().getPosition(); - } - - @Override - public Position getRotation() { - return getPlayer().getRotation(); - } - - @Override - public boolean isAlive() { - return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f; - } - - @Override - public Int2FloatMap getFightProperties() { - return getAvatar().getFightProperties(); - } - - public int getWeaponEntityId() { - if (getAvatar().getWeapon() != null) { - return getAvatar().getWeapon().getWeaponEntityId(); - } - return 0; - } - - @Override - public void onDeath(int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - - this.killedType = PlayerDieType.PLAYER_DIE_TYPE_KILL_BY_MONSTER; - this.killedBy = killerId; - clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE); - } - - public void onDeath(PlayerDieType dieType, int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - - this.killedType = dieType; - this.killedBy = killerId; - clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE); - } - - @Override - public float heal(float amount) { - // Do not heal character if they are dead - if (!this.isAlive()) { - return 0f; - } - - float healed = super.heal(amount); - - if (healed > 0f) { - getScene().broadcastPacket( - new PacketEntityFightPropChangeReasonNotify(this, FightProperty.FIGHT_PROP_CUR_HP, healed, PropChangeReason.PROP_CHANGE_REASON_ABILITY, ChangeHpReason.CHANGE_HP_REASON_ADD_ABILITY) - ); - } - - return healed; - } - - public void clearEnergy(ChangeEnergyReason reason) { - // Fight props. - val curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); - float curEnergy = this.getFightProperty(curEnergyProp); - - // Set energy to zero. - this.avatar.setCurrentEnergy(curEnergyProp, 0); - - // Send packets. - this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp)); - - if (reason == ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START) { - this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -curEnergy, reason)); - } - } - - public void addEnergy(float amount, PropChangeReason reason) { - this.addEnergy(amount, reason, false); - } - - public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) { - // Get current and maximum energy for this avatar. - val elementType = this.getAvatar().getSkillDepot().getElementType(); - val curEnergyProp = elementType.getCurEnergyProp(); - val maxEnergyProp = elementType.getMaxEnergyProp(); - - float curEnergy = this.getFightProperty(curEnergyProp); - float maxEnergy = this.getFightProperty(maxEnergyProp); - - // Scale amount by energy recharge, if the amount is not flat. - if (!isFlat) { - amount *= this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY); - } - - // Determine the new energy value. - float newEnergy = Math.min(curEnergy + amount, maxEnergy); - - // Set energy and notify. - if (newEnergy != curEnergy) { - this.avatar.setCurrentEnergy(curEnergyProp, newEnergy); - - this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); - this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason)); - } - } - - public SceneAvatarInfo getSceneAvatarInfo() { - val avatar = this.getAvatar(); - val player = this.getPlayer(); - SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder() - .setUid(player.getUid()) - .setAvatarId(avatar.getAvatarId()) - .setGuid(avatar.getGuid()) - .setPeerId(player.getPeerId()) - .addAllTalentIdList(avatar.getTalentIdList()) - .setCoreProudSkillLevel(avatar.getCoreProudSkillLevel()) - .putAllSkillLevelMap(avatar.getSkillLevelMap()) - .setSkillDepotId(avatar.getSkillDepotId()) - .addAllInherentProudSkillList(avatar.getProudSkillList()) - .putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap()) - .addAllTeamResonanceList(player.getTeamManager().getTeamResonances()) - .setWearingFlycloakId(avatar.getFlyCloak()) - .setCostumeId(avatar.getCostume()) - .setBornTime(avatar.getBornTime()); - - for (GameItem item : avatar.getEquips().values()) { - if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) { - avatarInfo.setWeapon(item.createSceneWeaponInfo()); - } else { - avatarInfo.addReliquaryList(item.createSceneReliquaryInfo()); - } - avatarInfo.addEquipIdList(item.getItemId()); - } - - return avatarInfo.build(); - } - - @Override - public SceneEntityInfo toProto() { - EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) - .setBornPos(Vector.newBuilder()) - .build(); - - SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs()) - .setLastMoveReliableSeq(this.getLastMoveReliableSeq()) - .setLifeState(this.getLifeState().getValue()); - - if (this.getScene() != null) { - entityInfo.setMotionInfo(this.getMotionInfo()); - } - - this.addAllFightPropsToEntityInfo(entityInfo); - - PropPair pair = PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel())) - .build(); - entityInfo.addPropList(pair); - - entityInfo.setAvatar(this.getSceneAvatarInfo()); - - return entityInfo.build(); - } - - public AbilityControlBlock getAbilityControlBlock() { - AvatarData data = this.getAvatar().getAvatarData(); - AbilityControlBlock.Builder abilityControlBlock = AbilityControlBlock.newBuilder(); - int embryoId = 0; - - // Add avatar abilities - if (data.getAbilities() != null) { - for (int id : data.getAbilities()) { - AbilityEmbryo emb = AbilityEmbryo.newBuilder() - .setAbilityId(++embryoId) - .setAbilityNameHash(id) - .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) - .build(); - abilityControlBlock.addAbilityEmbryoList(emb); - } - } - // Add default abilities - for (int id : GameConstants.DEFAULT_ABILITY_HASHES) { - AbilityEmbryo emb = AbilityEmbryo.newBuilder() - .setAbilityId(++embryoId) - .setAbilityNameHash(id) - .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) - .build(); - abilityControlBlock.addAbilityEmbryoList(emb); - } - // Add team resonances - for (int id : this.getPlayer().getTeamManager().getTeamResonancesConfig()) { - AbilityEmbryo emb = AbilityEmbryo.newBuilder() - .setAbilityId(++embryoId) - .setAbilityNameHash(id) - .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) - .build(); - abilityControlBlock.addAbilityEmbryoList(emb); - } - // Add skill depot abilities - AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId()); - if (skillDepot != null && skillDepot.getAbilities() != null) { - for (int id : skillDepot.getAbilities()) { - AbilityEmbryo emb = AbilityEmbryo.newBuilder() - .setAbilityId(++embryoId) - .setAbilityNameHash(id) - .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) - .build(); - abilityControlBlock.addAbilityEmbryoList(emb); - } - } - // Add equip abilities - if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) { - for (String skill : this.getAvatar().getExtraAbilityEmbryos()) { - AbilityEmbryo emb = AbilityEmbryo.newBuilder() - .setAbilityId(++embryoId) - .setAbilityNameHash(Utils.abilityHash(skill)) - .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) - .build(); - abilityControlBlock.addAbilityEmbryoList(emb); - } - } - - // - return abilityControlBlock.build(); - } - - /** - * Move this entity to a new position. - * Additionally invoke player move event. - * - * @param newPosition The new position. - * @param rotation The new rotation. - */ - @Override - public void move(Position newPosition, Position rotation) { - // Invoke player move event. - PlayerMoveEvent event = new PlayerMoveEvent( - this.getPlayer(), PlayerMoveEvent.MoveType.PLAYER, - this.getPosition(), newPosition - ); - event.call(); - - // Set position and rotation. - super.move(event.getDestination(), rotation); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.inventory.EquipType; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock; +import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.server.event.player.PlayerMoveEvent; +import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import lombok.Getter; +import lombok.val; + +public class EntityAvatar extends GameEntity { + @Getter private final Avatar avatar; + + @Getter private PlayerDieType killedType; + @Getter private int killedBy; + + public EntityAvatar(Avatar avatar) { + this(null, avatar); + } + + public EntityAvatar(Scene scene, Avatar avatar) { + super(scene); + this.avatar = avatar; + this.avatar.setCurrentEnergy(); + if (getScene() != null) { + this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR); + + GameItem weapon = getAvatar().getWeapon(); + if (weapon != null) { + weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON)); + } + } + } + + public Player getPlayer() { + return this.avatar.getPlayer(); + } + + @Override + public Position getPosition() { + return getPlayer().getPosition(); + } + + @Override + public Position getRotation() { + return getPlayer().getRotation(); + } + + @Override + public boolean isAlive() { + return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f; + } + + @Override + public Int2FloatMap getFightProperties() { + return getAvatar().getFightProperties(); + } + + public int getWeaponEntityId() { + if (getAvatar().getWeapon() != null) { + return getAvatar().getWeapon().getWeaponEntityId(); + } + return 0; + } + + @Override + public void onDeath(int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + + this.killedType = PlayerDieType.PLAYER_DIE_TYPE_KILL_BY_MONSTER; + this.killedBy = killerId; + clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE); + } + + public void onDeath(PlayerDieType dieType, int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + + this.killedType = dieType; + this.killedBy = killerId; + clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE); + } + + @Override + public float heal(float amount) { + // Do not heal character if they are dead + if (!this.isAlive()) { + return 0f; + } + + float healed = super.heal(amount); + + if (healed > 0f) { + getScene() + .broadcastPacket( + new PacketEntityFightPropChangeReasonNotify( + this, + FightProperty.FIGHT_PROP_CUR_HP, + healed, + PropChangeReason.PROP_CHANGE_REASON_ABILITY, + ChangeHpReason.CHANGE_HP_REASON_ADD_ABILITY)); + } + + return healed; + } + + public void clearEnergy(ChangeEnergyReason reason) { + // Fight props. + val curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); + float curEnergy = this.getFightProperty(curEnergyProp); + + // Set energy to zero. + this.avatar.setCurrentEnergy(curEnergyProp, 0); + + // Send packets. + this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp)); + + if (reason == ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START) { + this.getScene() + .broadcastPacket( + new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -curEnergy, reason)); + } + } + + public void addEnergy(float amount, PropChangeReason reason) { + this.addEnergy(amount, reason, false); + } + + public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) { + // Get current and maximum energy for this avatar. + val elementType = this.getAvatar().getSkillDepot().getElementType(); + val curEnergyProp = elementType.getCurEnergyProp(); + val maxEnergyProp = elementType.getMaxEnergyProp(); + + float curEnergy = this.getFightProperty(curEnergyProp); + float maxEnergy = this.getFightProperty(maxEnergyProp); + + // Scale amount by energy recharge, if the amount is not flat. + if (!isFlat) { + amount *= this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY); + } + + // Determine the new energy value. + float newEnergy = Math.min(curEnergy + amount, maxEnergy); + + // Set energy and notify. + if (newEnergy != curEnergy) { + this.avatar.setCurrentEnergy(curEnergyProp, newEnergy); + + this.getScene() + .broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); + this.getScene() + .broadcastPacket( + new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason)); + } + } + + public SceneAvatarInfo getSceneAvatarInfo() { + val avatar = this.getAvatar(); + val player = this.getPlayer(); + SceneAvatarInfo.Builder avatarInfo = + SceneAvatarInfo.newBuilder() + .setUid(player.getUid()) + .setAvatarId(avatar.getAvatarId()) + .setGuid(avatar.getGuid()) + .setPeerId(player.getPeerId()) + .addAllTalentIdList(avatar.getTalentIdList()) + .setCoreProudSkillLevel(avatar.getCoreProudSkillLevel()) + .putAllSkillLevelMap(avatar.getSkillLevelMap()) + .setSkillDepotId(avatar.getSkillDepotId()) + .addAllInherentProudSkillList(avatar.getProudSkillList()) + .putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap()) + .addAllTeamResonanceList(player.getTeamManager().getTeamResonances()) + .setWearingFlycloakId(avatar.getFlyCloak()) + .setCostumeId(avatar.getCostume()) + .setBornTime(avatar.getBornTime()); + + for (GameItem item : avatar.getEquips().values()) { + if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) { + avatarInfo.setWeapon(item.createSceneWeaponInfo()); + } else { + avatarInfo.addReliquaryList(item.createSceneReliquaryInfo()); + } + avatarInfo.addEquipIdList(item.getItemId()); + } + + return avatarInfo.build(); + } + + @Override + public SceneEntityInfo toProto() { + EntityAuthorityInfo authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) + .setBornPos(Vector.newBuilder()) + .build(); + + SceneEntityInfo.Builder entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setEntityClientData(EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs()) + .setLastMoveReliableSeq(this.getLastMoveReliableSeq()) + .setLifeState(this.getLifeState().getValue()); + + if (this.getScene() != null) { + entityInfo.setMotionInfo(this.getMotionInfo()); + } + + this.addAllFightPropsToEntityInfo(entityInfo); + + PropPair pair = + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue( + ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel())) + .build(); + entityInfo.addPropList(pair); + + entityInfo.setAvatar(this.getSceneAvatarInfo()); + + return entityInfo.build(); + } + + public AbilityControlBlock getAbilityControlBlock() { + AvatarData data = this.getAvatar().getAvatarData(); + AbilityControlBlock.Builder abilityControlBlock = AbilityControlBlock.newBuilder(); + int embryoId = 0; + + // Add avatar abilities + if (data.getAbilities() != null) { + for (int id : data.getAbilities()) { + AbilityEmbryo emb = + AbilityEmbryo.newBuilder() + .setAbilityId(++embryoId) + .setAbilityNameHash(id) + .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) + .build(); + abilityControlBlock.addAbilityEmbryoList(emb); + } + } + // Add default abilities + for (int id : GameConstants.DEFAULT_ABILITY_HASHES) { + AbilityEmbryo emb = + AbilityEmbryo.newBuilder() + .setAbilityId(++embryoId) + .setAbilityNameHash(id) + .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) + .build(); + abilityControlBlock.addAbilityEmbryoList(emb); + } + // Add team resonances + for (int id : this.getPlayer().getTeamManager().getTeamResonancesConfig()) { + AbilityEmbryo emb = + AbilityEmbryo.newBuilder() + .setAbilityId(++embryoId) + .setAbilityNameHash(id) + .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) + .build(); + abilityControlBlock.addAbilityEmbryoList(emb); + } + // Add skill depot abilities + AvatarSkillDepotData skillDepot = + GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId()); + if (skillDepot != null && skillDepot.getAbilities() != null) { + for (int id : skillDepot.getAbilities()) { + AbilityEmbryo emb = + AbilityEmbryo.newBuilder() + .setAbilityId(++embryoId) + .setAbilityNameHash(id) + .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) + .build(); + abilityControlBlock.addAbilityEmbryoList(emb); + } + } + // Add equip abilities + if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) { + for (String skill : this.getAvatar().getExtraAbilityEmbryos()) { + AbilityEmbryo emb = + AbilityEmbryo.newBuilder() + .setAbilityId(++embryoId) + .setAbilityNameHash(Utils.abilityHash(skill)) + .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME) + .build(); + abilityControlBlock.addAbilityEmbryoList(emb); + } + } + + // + return abilityControlBlock.build(); + } + + /** + * Move this entity to a new position. Additionally invoke player move event. + * + * @param newPosition The new position. + * @param rotation The new rotation. + */ + @Override + public void move(Position newPosition, Position rotation) { + // Invoke player move event. + PlayerMoveEvent event = + new PlayerMoveEvent( + this.getPlayer(), PlayerMoveEvent.MoveType.PLAYER, this.getPosition(), newPosition); + event.call(); + + // Set position and rotation. + super.move(event.getDestination(), rotation); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityBaseGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityBaseGadget.java index b28e99480..5d262b461 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityBaseGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityBaseGadget.java @@ -1,57 +1,58 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.data.binout.ConfigGadget; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.utils.Position; -import lombok.Getter; - -public abstract class EntityBaseGadget extends GameEntity { - @Getter(onMethod_ = @Override) - protected final Position position; - @Getter(onMethod_ = @Override) - protected final Position rotation; - - public EntityBaseGadget(Scene scene) { - this(scene, null, null); - } - - public EntityBaseGadget(Scene scene, Position position, Position rotation) { - super(scene); - this.position = position != null ? position.clone() : new Position(); - this.rotation = rotation != null ? rotation.clone() : new Position(); - } - - public abstract int getGadgetId(); - - @Override - public void onDeath(int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - } - - protected void fillFightProps(ConfigGadget configGadget) { - if (configGadget == null || configGadget.getCombat() == null) { - return; - } - var combatData = configGadget.getCombat(); - var combatProperties = combatData.getProperty(); - - var targetHp = combatProperties.getHP(); - setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, targetHp); - setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, targetHp); - if (combatProperties.isInvincible()) { - targetHp = Float.POSITIVE_INFINITY; - } - setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, targetHp); - - var atk = combatProperties.getAttack(); - setFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, atk); - setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, atk); - - var def = combatProperties.getDefence(); - setFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE, def); - setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, def); - - setLockHP(combatProperties.isLockHP()); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.binout.ConfigGadget; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.utils.Position; +import lombok.Getter; + +public abstract class EntityBaseGadget extends GameEntity { + @Getter(onMethod_ = @Override) + protected final Position position; + + @Getter(onMethod_ = @Override) + protected final Position rotation; + + public EntityBaseGadget(Scene scene) { + this(scene, null, null); + } + + public EntityBaseGadget(Scene scene, Position position, Position rotation) { + super(scene); + this.position = position != null ? position.clone() : new Position(); + this.rotation = rotation != null ? rotation.clone() : new Position(); + } + + public abstract int getGadgetId(); + + @Override + public void onDeath(int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + } + + protected void fillFightProps(ConfigGadget configGadget) { + if (configGadget == null || configGadget.getCombat() == null) { + return; + } + var combatData = configGadget.getCombat(); + var combatProperties = combatData.getProperty(); + + var targetHp = combatProperties.getHP(); + setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, targetHp); + setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, targetHp); + if (combatProperties.isInvincible()) { + targetHp = Float.POSITIVE_INFINITY; + } + setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, targetHp); + + var atk = combatProperties.getAttack(); + setFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, atk); + setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, atk); + + var def = combatProperties.getDefence(); + setFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE, def); + setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, def); + + setLockHP(combatProperties.isLockHP()); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java index fcb933531..24e172f50 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java @@ -1,119 +1,122 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import lombok.Getter; - -public class EntityClientGadget extends EntityBaseGadget { - @Getter - private final Player owner; - - @Getter(onMethod_ = @Override) - private final int gadgetId; - - @Getter - private final int campId; - @Getter - private final int campType; - @Getter - private final int ownerEntityId; - @Getter - private final int targetEntityId; - @Getter - private final boolean asyncLoad; - - @Getter - private final int originalOwnerEntityId; - - public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) { - super(scene, new Position(notify.getInitPos()), new Position(notify.getInitEulerAngles())); - this.owner = player; - this.id = notify.getEntityId(); - this.gadgetId = notify.getConfigId(); - this.campId = notify.getCampId(); - this.campType = notify.getCampType(); - this.ownerEntityId = notify.getPropOwnerEntityId(); - this.targetEntityId = notify.getTargetEntityId(); - this.asyncLoad = notify.getIsAsyncLoad(); - - GameEntity owner = scene.getEntityById(this.ownerEntityId); - if (owner instanceof EntityClientGadget ownerGadget) { - this.originalOwnerEntityId = ownerGadget.getOriginalOwnerEntityId(); - } else { - this.originalOwnerEntityId = this.ownerEntityId; - } - } - - @Override - public void onDeath(int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - } - - @Override - public Int2FloatMap getFightProperties() { - return null; - } - - @Override - public SceneEntityInfo toProto() { - EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) - .setBornPos(Vector.newBuilder()) - .build(); - - SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLifeState(1); - - PropPair pair = PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) - .build(); - entityInfo.addPropList(pair); - - ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder() - .setCampId(this.getCampId()) - .setCampType(this.getCampType()) - .setOwnerEntityId(this.getOwnerEntityId()) - .setTargetEntityId(this.getTargetEntityId()) - .setAsyncLoad(this.isAsyncLoad()) - .build(); - - SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() - .setGadgetId(this.getGadgetId()) - .setOwnerEntityId(this.getOwnerEntityId()) - .setIsEnableInteract(true) - .setClientGadget(clientGadget) - .setPropOwnerEntityId(this.getOwnerEntityId()) - .setAuthorityPeerId(this.getOwner().getPeerId()); - - entityInfo.setGadget(gadgetInfo); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import lombok.Getter; + +public class EntityClientGadget extends EntityBaseGadget { + @Getter private final Player owner; + + @Getter(onMethod_ = @Override) + private final int gadgetId; + + @Getter private final int campId; + @Getter private final int campType; + @Getter private final int ownerEntityId; + @Getter private final int targetEntityId; + @Getter private final boolean asyncLoad; + + @Getter private final int originalOwnerEntityId; + + public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) { + super(scene, new Position(notify.getInitPos()), new Position(notify.getInitEulerAngles())); + this.owner = player; + this.id = notify.getEntityId(); + this.gadgetId = notify.getConfigId(); + this.campId = notify.getCampId(); + this.campType = notify.getCampType(); + this.ownerEntityId = notify.getPropOwnerEntityId(); + this.targetEntityId = notify.getTargetEntityId(); + this.asyncLoad = notify.getIsAsyncLoad(); + + GameEntity owner = scene.getEntityById(this.ownerEntityId); + if (owner instanceof EntityClientGadget ownerGadget) { + this.originalOwnerEntityId = ownerGadget.getOriginalOwnerEntityId(); + } else { + this.originalOwnerEntityId = this.ownerEntityId; + } + } + + @Override + public void onDeath(int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + } + + @Override + public Int2FloatMap getFightProperties() { + return null; + } + + @Override + public SceneEntityInfo toProto() { + EntityAuthorityInfo authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) + .setBornPos(Vector.newBuilder()) + .build(); + + SceneEntityInfo.Builder entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setMotionInfo( + MotionInfo.newBuilder() + .setPos(getPosition().toProto()) + .setRot(getRotation().toProto()) + .setSpeed(Vector.newBuilder())) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setEntityClientData(EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLifeState(1); + + PropPair pair = + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) + .build(); + entityInfo.addPropList(pair); + + ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = + ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder() + .setCampId(this.getCampId()) + .setCampType(this.getCampType()) + .setOwnerEntityId(this.getOwnerEntityId()) + .setTargetEntityId(this.getTargetEntityId()) + .setAsyncLoad(this.isAsyncLoad()) + .build(); + + SceneGadgetInfo.Builder gadgetInfo = + SceneGadgetInfo.newBuilder() + .setGadgetId(this.getGadgetId()) + .setOwnerEntityId(this.getOwnerEntityId()) + .setIsEnableInteract(true) + .setClientGadget(clientGadget) + .setPropOwnerEntityId(this.getOwnerEntityId()) + .setAuthorityPeerId(this.getOwner().getPeerId()); + + entityInfo.setGadget(gadgetInfo); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java index 9ab2c85d6..e8cb0aceb 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java @@ -1,190 +1,206 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ConfigGadget; -import emu.grasscutter.data.excels.GadgetData; -import emu.grasscutter.game.entity.gadget.*; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.SceneGadget; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -import javax.annotation.Nullable; -import java.util.Optional; - -@ToString(callSuper = true) -public class EntityGadget extends EntityBaseGadget { - @Getter - private final GadgetData gadgetData; - @Getter(onMethod_ = @Override, lazy = true) - private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap(); - @Getter(onMethod_ = @Override) - @Setter - private int gadgetId; - @Getter - @Setter - private int state; - @Getter - @Setter - private int pointType; - @Getter - private GadgetContent content; - @Getter - @Setter - private SceneGadget metaGadget; - @Nullable - @Getter - private final ConfigGadget configGadget; - - public EntityGadget(Scene scene, int gadgetId, Position pos) { - this(scene, gadgetId, pos, null, null); - } - - public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) { - this(scene, gadgetId, pos, rot, null); - } - - public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) { - super(scene, pos, rot); - this.gadgetData = GameData.getGadgetDataMap().get(gadgetId); - this.configGadget = Optional.ofNullable(this.gadgetData).map(GadgetData::getJsonName).map(GameData.getGadgetConfigData()::get).orElse(null); - this.id = this.getScene().getWorld().getNextEntityId(EntityIdType.GADGET); - this.gadgetId = gadgetId; - this.content = content; - fillFightProps(configGadget); - } - - public void updateState(int state) { - this.setState(state); - this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state)); - getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_STATE_CHANGE, new ScriptArgs(state, this.getConfigId())); - } - - @Deprecated(forRemoval = true) // Dont use! - public void setContent(GadgetContent content) { - this.content = this.content == null ? content : this.content; - } - - // TODO refactor - public void buildContent() { - if (this.getContent() != null || this.getGadgetData() == null || this.getGadgetData().getType() == null) { - return; - } - - this.content = switch (this.getGadgetData().getType()) { - case GatherPoint -> new GadgetGatherPoint(this); - case GatherObject -> new GadgetGatherObject(this); - case Worktop -> new GadgetWorktop(this); - case RewardStatue -> new GadgetRewardStatue(this); - case Chest -> new GadgetChest(this); - case Gadget -> new GadgetObject(this); - default -> null; - }; - } - - @Override - public void onInteract(Player player, GadgetInteractReq interactReq) { - if (this.getContent() == null) { - return; - } - - boolean shouldDelete = this.getContent().onInteract(player, interactReq); - - if (shouldDelete) { - this.getScene().killEntity(this); - } - } - - @Override - public void onCreate() { - // Lua event - getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_CREATE, new ScriptArgs(this.getConfigId())); - } - - @Override - public void onDeath(int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - - if (this.getSpawnEntry() != null) { - this.getScene().getDeadSpawnedEntities().add(getSpawnEntry()); - } - if (getScene().getChallenge() != null) { - getScene().getChallenge().onGadgetDeath(this); - } - getScene().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId())); - } - - @Override - public SceneEntityInfo toProto() { - EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) - .setBornPos(Vector.newBuilder()) - .build(); - - SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLifeState(1); - - PropPair pair = PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) - .build(); - entityInfo.addPropList(pair); - - // We do not use the getter to null check because the getter will create a fight prop map if it is null - if (this.fightProperties != null) { - addAllFightPropsToEntityInfo(entityInfo); - } - - SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() - .setGadgetId(this.getGadgetId()) - .setGroupId(this.getGroupId()) - .setConfigId(this.getConfigId()) - .setGadgetState(this.getState()) - .setIsEnableInteract(true) - .setAuthorityPeerId(this.getScene().getWorld().getHostPeerId()); - - if (this.metaGadget != null) { - gadgetInfo.setDraftId(this.metaGadget.draft_id); - } - - if (this.getContent() != null) { - this.getContent().onBuildProto(gadgetInfo); - } - - entityInfo.setGadget(gadgetInfo); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ConfigGadget; +import emu.grasscutter.data.excels.GadgetData; +import emu.grasscutter.game.entity.gadget.*; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGadget; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import java.util.Optional; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@ToString(callSuper = true) +public class EntityGadget extends EntityBaseGadget { + @Getter private final GadgetData gadgetData; + + @Getter(onMethod_ = @Override, lazy = true) + private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap(); + + @Getter(onMethod_ = @Override) + @Setter + private int gadgetId; + + @Getter @Setter private int state; + @Getter @Setter private int pointType; + @Getter private GadgetContent content; + @Getter @Setter private SceneGadget metaGadget; + @Nullable @Getter private final ConfigGadget configGadget; + + public EntityGadget(Scene scene, int gadgetId, Position pos) { + this(scene, gadgetId, pos, null, null); + } + + public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) { + this(scene, gadgetId, pos, rot, null); + } + + public EntityGadget( + Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) { + super(scene, pos, rot); + this.gadgetData = GameData.getGadgetDataMap().get(gadgetId); + this.configGadget = + Optional.ofNullable(this.gadgetData) + .map(GadgetData::getJsonName) + .map(GameData.getGadgetConfigData()::get) + .orElse(null); + this.id = this.getScene().getWorld().getNextEntityId(EntityIdType.GADGET); + this.gadgetId = gadgetId; + this.content = content; + fillFightProps(configGadget); + } + + public void updateState(int state) { + this.setState(state); + this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state)); + getScene() + .getScriptManager() + .callEvent(EventType.EVENT_GADGET_STATE_CHANGE, new ScriptArgs(state, this.getConfigId())); + } + + @Deprecated(forRemoval = true) // Dont use! + public void setContent(GadgetContent content) { + this.content = this.content == null ? content : this.content; + } + + // TODO refactor + public void buildContent() { + if (this.getContent() != null + || this.getGadgetData() == null + || this.getGadgetData().getType() == null) { + return; + } + + this.content = + switch (this.getGadgetData().getType()) { + case GatherPoint -> new GadgetGatherPoint(this); + case GatherObject -> new GadgetGatherObject(this); + case Worktop -> new GadgetWorktop(this); + case RewardStatue -> new GadgetRewardStatue(this); + case Chest -> new GadgetChest(this); + case Gadget -> new GadgetObject(this); + default -> null; + }; + } + + @Override + public void onInteract(Player player, GadgetInteractReq interactReq) { + if (this.getContent() == null) { + return; + } + + boolean shouldDelete = this.getContent().onInteract(player, interactReq); + + if (shouldDelete) { + this.getScene().killEntity(this); + } + } + + @Override + public void onCreate() { + // Lua event + getScene() + .getScriptManager() + .callEvent(EventType.EVENT_GADGET_CREATE, new ScriptArgs(this.getConfigId())); + } + + @Override + public void onDeath(int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + + if (this.getSpawnEntry() != null) { + this.getScene().getDeadSpawnedEntities().add(getSpawnEntry()); + } + if (getScene().getChallenge() != null) { + getScene().getChallenge().onGadgetDeath(this); + } + getScene() + .getScriptManager() + .callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId())); + } + + @Override + public SceneEntityInfo toProto() { + EntityAuthorityInfo authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) + .setBornPos(Vector.newBuilder()) + .build(); + + SceneEntityInfo.Builder entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setMotionInfo( + MotionInfo.newBuilder() + .setPos(getPosition().toProto()) + .setRot(getRotation().toProto()) + .setSpeed(Vector.newBuilder())) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setEntityClientData(EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLifeState(1); + + PropPair pair = + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) + .build(); + entityInfo.addPropList(pair); + + // We do not use the getter to null check because the getter will create a fight prop map if it + // is null + if (this.fightProperties != null) { + addAllFightPropsToEntityInfo(entityInfo); + } + + SceneGadgetInfo.Builder gadgetInfo = + SceneGadgetInfo.newBuilder() + .setGadgetId(this.getGadgetId()) + .setGroupId(this.getGroupId()) + .setConfigId(this.getConfigId()) + .setGadgetState(this.getState()) + .setIsEnableInteract(true) + .setAuthorityPeerId(this.getScene().getWorld().getHostPeerId()); + + if (this.metaGadget != null) { + gadgetInfo.setDraftId(this.metaGadget.draft_id); + } + + if (this.getContent() != null) { + this.getContent().onBuildProto(gadgetInfo); + } + + entityInfo.setGadget(gadgetInfo); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityItem.java b/src/main/java/emu/grasscutter/game/entity/EntityItem.java index 4c403adcd..6cc8cb12c 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityItem.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityItem.java @@ -1,131 +1,143 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.GadgetBornTypeOuterClass.GadgetBornType; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import lombok.Getter; - -public class EntityItem extends EntityBaseGadget { - @Getter - private final GameItem item; - @Getter - private final long guid; - @Getter - private final boolean share; - - public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count) { - this(scene, player, itemData, pos, count, true); - } - - // In official game, some drop items are shared to all players, and some other items are independent to all players - // For example, if you killed a monster in MP mode, all players could get drops but rarity and number of them are different - // but if you broke regional mine, when someone picked up the drop then it disappeared - public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) { - super(scene, pos, null); - this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); - this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid(); - this.item = new GameItem(itemData, count); - this.share = share; - } - - public ItemData getItemData() { - return this.getItem().getItemData(); - } - - public int getCount() { - return this.getItem().getCount(); - } - - @Override - public int getGadgetId() { - return this.getItemData().getGadgetId(); - } - - @Override - public Int2FloatMap getFightProperties() { - return null; - } - - @Override - public void onInteract(Player player, GadgetInteractReq interactReq) { - // check drop owner to avoid someone picked up item in others' world - if (!this.isShare()) { - int dropOwner = (int) (this.getGuid() >> 32); - if (dropOwner != player.getUid()) { - return; - } - } - - this.getScene().removeEntity(this); - GameItem item = new GameItem(this.getItemData(), this.getCount()); - - // Add to inventory - boolean success = player.getInventory().addItem(item, ActionReason.SubfieldDrop); - if (success) { - if (!this.isShare()) { // not shared drop - player.sendPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM)); - } else { - this.getScene().broadcastPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM)); - } - } - } - - @Override - public SceneEntityInfo toProto() { - EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) - .setBornPos(Vector.newBuilder()) - .build(); - - SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLifeState(1); - - PropPair pair = PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) - .build(); - entityInfo.addPropList(pair); - - SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() - .setGadgetId(this.getItemData().getGadgetId()) - .setTrifleItem(this.getItem().toProto()) - .setBornType(GadgetBornType.GADGET_BORN_TYPE_IN_AIR) - .setAuthorityPeerId(this.getWorld().getHostPeerId()) - .setIsEnableInteract(true); - - entityInfo.setGadget(gadgetInfo); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.GadgetBornTypeOuterClass.GadgetBornType; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import lombok.Getter; + +public class EntityItem extends EntityBaseGadget { + @Getter private final GameItem item; + @Getter private final long guid; + @Getter private final boolean share; + + public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count) { + this(scene, player, itemData, pos, count, true); + } + + // In official game, some drop items are shared to all players, and some other items are + // independent to all players + // For example, if you killed a monster in MP mode, all players could get drops but rarity and + // number of them are different + // but if you broke regional mine, when someone picked up the drop then it disappeared + public EntityItem( + Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) { + super(scene, pos, null); + this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); + this.guid = + player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid(); + this.item = new GameItem(itemData, count); + this.share = share; + } + + public ItemData getItemData() { + return this.getItem().getItemData(); + } + + public int getCount() { + return this.getItem().getCount(); + } + + @Override + public int getGadgetId() { + return this.getItemData().getGadgetId(); + } + + @Override + public Int2FloatMap getFightProperties() { + return null; + } + + @Override + public void onInteract(Player player, GadgetInteractReq interactReq) { + // check drop owner to avoid someone picked up item in others' world + if (!this.isShare()) { + int dropOwner = (int) (this.getGuid() >> 32); + if (dropOwner != player.getUid()) { + return; + } + } + + this.getScene().removeEntity(this); + GameItem item = new GameItem(this.getItemData(), this.getCount()); + + // Add to inventory + boolean success = player.getInventory().addItem(item, ActionReason.SubfieldDrop); + if (success) { + if (!this.isShare()) { // not shared drop + player.sendPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM)); + } else { + this.getScene() + .broadcastPacket( + new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM)); + } + } + } + + @Override + public SceneEntityInfo toProto() { + EntityAuthorityInfo authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder())) + .setBornPos(Vector.newBuilder()) + .build(); + + SceneEntityInfo.Builder entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setMotionInfo( + MotionInfo.newBuilder() + .setPos(getPosition().toProto()) + .setRot(getRotation().toProto()) + .setSpeed(Vector.newBuilder())) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setEntityClientData(EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLifeState(1); + + PropPair pair = + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) + .build(); + entityInfo.addPropList(pair); + + SceneGadgetInfo.Builder gadgetInfo = + SceneGadgetInfo.newBuilder() + .setGadgetId(this.getItemData().getGadgetId()) + .setTrifleItem(this.getItem().toProto()) + .setBornType(GadgetBornType.GADGET_BORN_TYPE_IN_AIR) + .setAuthorityPeerId(this.getWorld().getHostPeerId()) + .setIsEnableInteract(true); + + entityInfo.setGadget(gadgetInfo); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java index d87823432..830490413 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java @@ -1,233 +1,260 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.PropGrowCurve; -import emu.grasscutter.data.excels.EnvAnimalGatherConfigData; -import emu.grasscutter.data.excels.MonsterCurveData; -import emu.grasscutter.data.excels.MonsterData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.*; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.MonsterBornTypeOuterClass.MonsterBornType; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo; -import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -import java.util.Optional; - -public class EntityMonster extends GameEntity { - @Getter - private final MonsterData monsterData; - @Getter(onMethod_ = @Override) - private final Int2FloatOpenHashMap fightProperties; - - @Getter(onMethod_ = @Override) - private final Position position; - @Getter(onMethod_ = @Override) - private final Position rotation; - @Getter - private final Position bornPos; - @Getter - private final int level; - private int weaponEntityId; - @Getter - @Setter - private int poseId; - @Getter - @Setter - private int aiId = -1; - - public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) { - super(scene); - this.id = getWorld().getNextEntityId(EntityIdType.MONSTER); - this.monsterData = monsterData; - this.fightProperties = new Int2FloatOpenHashMap(); - this.position = new Position(pos); - this.rotation = new Position(); - this.bornPos = getPosition().clone(); - this.level = level; - - // Monster weapon - if (getMonsterWeaponId() > 0) { - this.weaponEntityId = getWorld().getNextEntityId(EntityIdType.WEAPON); - } - - this.recalcStats(); - } - - public int getMonsterWeaponId() { - return this.getMonsterData().getWeaponId(); - } - - private int getMonsterId() { - return this.getMonsterData().getId(); - } - - @Override - public boolean isAlive() { - return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f; - } - - @Override - public void onInteract(Player player, GadgetInteractReq interactReq) { - EnvAnimalGatherConfigData gatherData = GameData.getEnvAnimalGatherConfigDataMap().get(this.getMonsterData().getId()); - - if (gatherData == null) { - return; - } - - player.getInventory().addItem(gatherData.getGatherItem(), ActionReason.SubfieldDrop); - - this.getScene().killEntity(this); - } - - @Override - public void onCreate() { - // Lua event - getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(this.getConfigId())); - } - - @Override - public void damage(float amount, int killerId) { - // Get HP before damage. - float hpBeforeDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - - // Apply damage. - super.damage(amount, killerId); - - // Get HP after damage. - float hpAfterDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - - // Invoke energy drop logic. - for (Player player : this.getScene().getPlayers()) { - player.getEnergyManager().handleMonsterEnergyDrop(this, hpBeforeDamage, hpAfterDamage); - } - } - - @Override - public void onDeath(int killerId) { - super.onDeath(killerId); // Invoke super class's onDeath() method. - var scene = this.getScene(); - var challenge = Optional.ofNullable(scene.getChallenge()); - var scriptManager = scene.getScriptManager(); - - Optional.ofNullable(this.getSpawnEntry()).ifPresent(scene.getDeadSpawnedEntities()::add); - - // first set the challenge data - challenge.ifPresent(c -> c.onMonsterDeath(this)); - - if (scriptManager.isInit() && this.getGroupId() > 0) { - Optional.ofNullable(scriptManager.getScriptMonsterSpawnService()).ifPresent(s -> s.onMonsterDead(this)); - - // prevent spawn monster after success - if (challenge.map(c -> c.inProgress()).orElse(true)) - scriptManager.callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId())); - } - // Battle Pass trigger - scene.getPlayers().forEach(p -> p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_MONSTER_DIE, this.getMonsterId(), 1)); - } - - public void recalcStats() { - // Monster data - MonsterData data = this.getMonsterData(); - - // Get hp percent, set to 100% if none - float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - - // Clear properties - this.getFightProperties().clear(); - - // Base stats - MonsterData.definedFightProperties.forEach(prop -> this.setFightProperty(prop, data.getFightProperty(prop))); - - // Level curve - MonsterCurveData curve = GameData.getMonsterCurveDataMap().get(this.getLevel()); - if (curve != null) { - for (PropGrowCurve growCurve : data.getPropGrowCurves()) { - FightProperty prop = FightProperty.getPropByName(growCurve.getType()); - this.setFightProperty(prop, this.getFightProperty(prop) * curve.getMultByProp(growCurve.getGrowCurve())); - } - } - - // Set % stats - FightProperty.forEachCompoundProperty(c -> this.setFightProperty(c.getResult(), - this.getFightProperty(c.getFlat()) + (this.getFightProperty(c.getBase()) * (1f + this.getFightProperty(c.getPercent()))))); - - // Set current hp - this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent); - } - - @Override - public SceneEntityInfo toProto() { - var authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(this.getBornPos().toProto())) - .setBornPos(this.getBornPos().toProto()) - .build(); - - var entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER) - .setMotionInfo(this.getMotionInfo()) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLifeState(this.getLifeState().getValue()); - - this.addAllFightPropsToEntityInfo(entityInfo); - - entityInfo.addPropList(PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel())) - .build()); - - var monsterInfo = SceneMonsterInfo.newBuilder() - .setMonsterId(getMonsterId()) - .setGroupId(this.getGroupId()) - .setConfigId(this.getConfigId()) - .addAllAffixList(getMonsterData().getAffix()) - .setAuthorityPeerId(getWorld().getHostPeerId()) - .setPoseId(this.getPoseId()) - .setBlockId(3001) - .setBornType(MonsterBornType.MONSTER_BORN_TYPE_DEFAULT) - .setSpecialNameId(40); - - if (getMonsterData().getDescribeData() != null) { - monsterInfo.setTitleId(getMonsterData().getDescribeData().getTitleID()); - } - - if (this.getMonsterWeaponId() > 0) { - SceneWeaponInfo weaponInfo = SceneWeaponInfo.newBuilder() - .setEntityId(this.weaponEntityId) - .setGadgetId(this.getMonsterWeaponId()) - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .build(); - - monsterInfo.addWeaponList(weaponInfo); - } - if (this.aiId != -1) { - monsterInfo.setAiConfigId(aiId); - } - - entityInfo.setMonster(monsterInfo); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.PropGrowCurve; +import emu.grasscutter.data.excels.EnvAnimalGatherConfigData; +import emu.grasscutter.data.excels.MonsterCurveData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.*; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.MonsterBornTypeOuterClass.MonsterBornType; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo; +import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import java.util.Optional; +import lombok.Getter; +import lombok.Setter; + +public class EntityMonster extends GameEntity { + @Getter private final MonsterData monsterData; + + @Getter(onMethod_ = @Override) + private final Int2FloatOpenHashMap fightProperties; + + @Getter(onMethod_ = @Override) + private final Position position; + + @Getter(onMethod_ = @Override) + private final Position rotation; + + @Getter private final Position bornPos; + @Getter private final int level; + private int weaponEntityId; + @Getter @Setter private int poseId; + @Getter @Setter private int aiId = -1; + + public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) { + super(scene); + this.id = getWorld().getNextEntityId(EntityIdType.MONSTER); + this.monsterData = monsterData; + this.fightProperties = new Int2FloatOpenHashMap(); + this.position = new Position(pos); + this.rotation = new Position(); + this.bornPos = getPosition().clone(); + this.level = level; + + // Monster weapon + if (getMonsterWeaponId() > 0) { + this.weaponEntityId = getWorld().getNextEntityId(EntityIdType.WEAPON); + } + + this.recalcStats(); + } + + public int getMonsterWeaponId() { + return this.getMonsterData().getWeaponId(); + } + + private int getMonsterId() { + return this.getMonsterData().getId(); + } + + @Override + public boolean isAlive() { + return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f; + } + + @Override + public void onInteract(Player player, GadgetInteractReq interactReq) { + EnvAnimalGatherConfigData gatherData = + GameData.getEnvAnimalGatherConfigDataMap().get(this.getMonsterData().getId()); + + if (gatherData == null) { + return; + } + + player.getInventory().addItem(gatherData.getGatherItem(), ActionReason.SubfieldDrop); + + this.getScene().killEntity(this); + } + + @Override + public void onCreate() { + // Lua event + getScene() + .getScriptManager() + .callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(this.getConfigId())); + } + + @Override + public void damage(float amount, int killerId) { + // Get HP before damage. + float hpBeforeDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + + // Apply damage. + super.damage(amount, killerId); + + // Get HP after damage. + float hpAfterDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + + // Invoke energy drop logic. + for (Player player : this.getScene().getPlayers()) { + player.getEnergyManager().handleMonsterEnergyDrop(this, hpBeforeDamage, hpAfterDamage); + } + } + + @Override + public void onDeath(int killerId) { + super.onDeath(killerId); // Invoke super class's onDeath() method. + var scene = this.getScene(); + var challenge = Optional.ofNullable(scene.getChallenge()); + var scriptManager = scene.getScriptManager(); + + Optional.ofNullable(this.getSpawnEntry()).ifPresent(scene.getDeadSpawnedEntities()::add); + + // first set the challenge data + challenge.ifPresent(c -> c.onMonsterDeath(this)); + + if (scriptManager.isInit() && this.getGroupId() > 0) { + Optional.ofNullable(scriptManager.getScriptMonsterSpawnService()) + .ifPresent(s -> s.onMonsterDead(this)); + + // prevent spawn monster after success + if (challenge.map(c -> c.inProgress()).orElse(true)) + scriptManager.callEvent( + EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId())); + } + // Battle Pass trigger + scene + .getPlayers() + .forEach( + p -> + p.getBattlePassManager() + .triggerMission( + WatcherTriggerType.TRIGGER_MONSTER_DIE, this.getMonsterId(), 1)); + } + + public void recalcStats() { + // Monster data + MonsterData data = this.getMonsterData(); + + // Get hp percent, set to 100% if none + float hpPercent = + this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 + ? 1f + : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) + / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + + // Clear properties + this.getFightProperties().clear(); + + // Base stats + MonsterData.definedFightProperties.forEach( + prop -> this.setFightProperty(prop, data.getFightProperty(prop))); + + // Level curve + MonsterCurveData curve = GameData.getMonsterCurveDataMap().get(this.getLevel()); + if (curve != null) { + for (PropGrowCurve growCurve : data.getPropGrowCurves()) { + FightProperty prop = FightProperty.getPropByName(growCurve.getType()); + this.setFightProperty( + prop, this.getFightProperty(prop) * curve.getMultByProp(growCurve.getGrowCurve())); + } + } + + // Set % stats + FightProperty.forEachCompoundProperty( + c -> + this.setFightProperty( + c.getResult(), + this.getFightProperty(c.getFlat()) + + (this.getFightProperty(c.getBase()) + * (1f + this.getFightProperty(c.getPercent()))))); + + // Set current hp + this.setFightProperty( + FightProperty.FIGHT_PROP_CUR_HP, + this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent); + } + + @Override + public SceneEntityInfo toProto() { + var authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder() + .setIsAiOpen(true) + .setBornPos(this.getBornPos().toProto())) + .setBornPos(this.getBornPos().toProto()) + .build(); + + var entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER) + .setMotionInfo(this.getMotionInfo()) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setEntityClientData(EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLifeState(this.getLifeState().getValue()); + + this.addAllFightPropsToEntityInfo(entityInfo); + + entityInfo.addPropList( + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel())) + .build()); + + var monsterInfo = + SceneMonsterInfo.newBuilder() + .setMonsterId(getMonsterId()) + .setGroupId(this.getGroupId()) + .setConfigId(this.getConfigId()) + .addAllAffixList(getMonsterData().getAffix()) + .setAuthorityPeerId(getWorld().getHostPeerId()) + .setPoseId(this.getPoseId()) + .setBlockId(3001) + .setBornType(MonsterBornType.MONSTER_BORN_TYPE_DEFAULT) + .setSpecialNameId(40); + + if (getMonsterData().getDescribeData() != null) { + monsterInfo.setTitleId(getMonsterData().getDescribeData().getTitleID()); + } + + if (this.getMonsterWeaponId() > 0) { + SceneWeaponInfo weaponInfo = + SceneWeaponInfo.newBuilder() + .setEntityId(this.weaponEntityId) + .setGadgetId(this.getMonsterWeaponId()) + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .build(); + + monsterInfo.addWeaponList(weaponInfo); + } + if (this.aiId != -1) { + monsterInfo.setAiConfigId(aiId); + } + + entityInfo.setMonster(monsterInfo); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityNPC.java b/src/main/java/emu/grasscutter/game/entity/EntityNPC.java index 315d5c6c6..3356f8025 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityNPC.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityNPC.java @@ -1,70 +1,77 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.*; -import emu.grasscutter.scripts.data.SceneNPC; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import lombok.Getter; - -public class EntityNPC extends GameEntity { - @Getter(onMethod_ = @Override) - private final Position position; - @Getter(onMethod_ = @Override) - private final Position rotation; - private final SceneNPC metaNpc; - @Getter - private final int suiteId; - - public EntityNPC(Scene scene, SceneNPC metaNPC, int blockId, int suiteId) { - super(scene); - this.id = getScene().getWorld().getNextEntityId(EntityIdType.NPC); - setConfigId(metaNPC.config_id); - setGroupId(metaNPC.group.id); - setBlockId(blockId); - this.suiteId = suiteId; - this.position = metaNPC.pos.clone(); - this.rotation = metaNPC.rot.clone(); - this.metaNpc = metaNPC; - - } - - @Override - public Int2FloatMap getFightProperties() { - return null; - } - - @Override - public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { - - EntityAuthorityInfoOuterClass.EntityAuthorityInfo authority = EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder() - .setIsAiOpen(true) - .setBornPos(getPosition().toProto())) - .setBornPos(getPosition().toProto()) - .build(); - - SceneEntityInfoOuterClass.SceneEntityInfo.Builder entityInfo = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_NPC) - .setMotionInfo(MotionInfoOuterClass.MotionInfo.newBuilder() - .setPos(getPosition().toProto()) - .setRot(getRotation().toProto()) - .setSpeed(VectorOuterClass.Vector.newBuilder())) - .addAnimatorParaList(AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair.newBuilder()) - .setEntityClientData(EntityClientDataOuterClass.EntityClientData.newBuilder()) - .setEntityAuthorityInfo(authority) - .setLifeState(1); - - - entityInfo.setNpc(SceneNpcInfoOuterClass.SceneNpcInfo.newBuilder() - .setNpcId(metaNpc.npc_id) - .setBlockId(getBlockId()) - .build()); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.*; +import emu.grasscutter.scripts.data.SceneNPC; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import lombok.Getter; + +public class EntityNPC extends GameEntity { + @Getter(onMethod_ = @Override) + private final Position position; + + @Getter(onMethod_ = @Override) + private final Position rotation; + + private final SceneNPC metaNpc; + @Getter private final int suiteId; + + public EntityNPC(Scene scene, SceneNPC metaNPC, int blockId, int suiteId) { + super(scene); + this.id = getScene().getWorld().getNextEntityId(EntityIdType.NPC); + setConfigId(metaNPC.config_id); + setGroupId(metaNPC.group.id); + setBlockId(blockId); + this.suiteId = suiteId; + this.position = metaNPC.pos.clone(); + this.rotation = metaNPC.rot.clone(); + this.metaNpc = metaNPC; + } + + @Override + public Int2FloatMap getFightProperties() { + return null; + } + + @Override + public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { + + EntityAuthorityInfoOuterClass.EntityAuthorityInfo authority = + EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo( + EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder() + .setIsAiOpen(true) + .setBornPos(getPosition().toProto())) + .setBornPos(getPosition().toProto()) + .build(); + + SceneEntityInfoOuterClass.SceneEntityInfo.Builder entityInfo = + SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_NPC) + .setMotionInfo( + MotionInfoOuterClass.MotionInfo.newBuilder() + .setPos(getPosition().toProto()) + .setRot(getRotation().toProto()) + .setSpeed(VectorOuterClass.Vector.newBuilder())) + .addAnimatorParaList( + AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair + .newBuilder()) + .setEntityClientData(EntityClientDataOuterClass.EntityClientData.newBuilder()) + .setEntityAuthorityInfo(authority) + .setLifeState(1); + + entityInfo.setNpc( + SceneNpcInfoOuterClass.SceneNpcInfo.newBuilder() + .setNpcId(metaNpc.npc_id) + .setBlockId(getBlockId()) + .build()); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityRegion.java b/src/main/java/emu/grasscutter/game/entity/EntityRegion.java index ef4e55bdd..cccb5b41f 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityRegion.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityRegion.java @@ -1,93 +1,90 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass; -import emu.grasscutter.scripts.data.SceneRegion; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import lombok.Getter; - -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -@Getter -public class EntityRegion extends GameEntity { - private final Position position; - private final Set entities; // Ids of entities inside this region - private final SceneRegion metaRegion; - private boolean hasNewEntities; - private boolean entityLeave; - - public EntityRegion(Scene scene, SceneRegion region) { - super(scene); - this.id = getScene().getWorld().getNextEntityId(EntityIdType.REGION); - setGroupId(region.group.id); - setBlockId(region.group.block_id); - setConfigId(region.config_id); - this.position = region.pos.clone(); - this.entities = ConcurrentHashMap.newKeySet(); - this.metaRegion = region; - } - - public void addEntity(GameEntity entity) { - if (this.getEntities().contains(entity.getId())) { - return; - } - this.getEntities().add(entity.getId()); - this.hasNewEntities = true; - } - - public boolean hasNewEntities() { - return hasNewEntities; - } - - public void resetNewEntities() { - hasNewEntities = false; - } - - public void removeEntity(int entityId) { - this.getEntities().remove(entityId); - this.entityLeave = true; - } - - public void removeEntity(GameEntity entity) { - this.getEntities().remove(entity.getId()); - this.entityLeave = true; - } - - public boolean entityLeave() { - return this.entityLeave; - } - - public void resetEntityLeave() { - this.entityLeave = false; - } - - @Override - public Int2FloatMap getFightProperties() { - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public Position getRotation() { - return null; - } - - @Override - public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { - /** - * The Region Entity would not be sent to client. - */ - return null; - } - - public int getFirstEntityId() { - return entities.stream().findFirst().orElse(0); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass; +import emu.grasscutter.scripts.data.SceneRegion; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import lombok.Getter; + +@Getter +public class EntityRegion extends GameEntity { + private final Position position; + private final Set entities; // Ids of entities inside this region + private final SceneRegion metaRegion; + private boolean hasNewEntities; + private boolean entityLeave; + + public EntityRegion(Scene scene, SceneRegion region) { + super(scene); + this.id = getScene().getWorld().getNextEntityId(EntityIdType.REGION); + setGroupId(region.group.id); + setBlockId(region.group.block_id); + setConfigId(region.config_id); + this.position = region.pos.clone(); + this.entities = ConcurrentHashMap.newKeySet(); + this.metaRegion = region; + } + + public void addEntity(GameEntity entity) { + if (this.getEntities().contains(entity.getId())) { + return; + } + this.getEntities().add(entity.getId()); + this.hasNewEntities = true; + } + + public boolean hasNewEntities() { + return hasNewEntities; + } + + public void resetNewEntities() { + hasNewEntities = false; + } + + public void removeEntity(int entityId) { + this.getEntities().remove(entityId); + this.entityLeave = true; + } + + public void removeEntity(GameEntity entity) { + this.getEntities().remove(entity.getId()); + this.entityLeave = true; + } + + public boolean entityLeave() { + return this.entityLeave; + } + + public void resetEntityLeave() { + this.entityLeave = false; + } + + @Override + public Int2FloatMap getFightProperties() { + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public Position getRotation() { + return null; + } + + @Override + public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { + /** The Region Entity would not be sent to client. */ + return null; + } + + public int getFirstEntityId() { + return entities.stream().findFirst().orElse(0); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntitySolarIsotomaClientGadget.java b/src/main/java/emu/grasscutter/game/entity/EntitySolarIsotomaClientGadget.java index bc039a6a3..29007b8b4 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntitySolarIsotomaClientGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntitySolarIsotomaClientGadget.java @@ -1,32 +1,34 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.game.entity.platform.EntityPlatform; -import emu.grasscutter.game.entity.platform.EntitySolarIsotomaElevatorPlatform; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass; -import lombok.Getter; - -public class EntitySolarIsotomaClientGadget extends EntityClientGadget { - public static final int GADGET_ID = 41038001; - public static final int ELEVATOR_GADGET_ID = 41038002; - @Getter - private EntityPlatform platformGadget; - - public EntitySolarIsotomaClientGadget(Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) { - super(scene, player, notify); - } - - @Override - public void onCreate() { - //Create solar isotoma elevator and send to all. - this.platformGadget = new EntitySolarIsotomaElevatorPlatform(this, getScene(), getOwner(), ELEVATOR_GADGET_ID, getPosition(), getRotation()); - getScene().addEntity(this.platformGadget); - } - - @Override - public void onRemoved() { - //Remove solar isotoma elevator entity. - getScene().removeEntity(this.platformGadget); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.entity.platform.EntityPlatform; +import emu.grasscutter.game.entity.platform.EntitySolarIsotomaElevatorPlatform; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass; +import lombok.Getter; + +public class EntitySolarIsotomaClientGadget extends EntityClientGadget { + public static final int GADGET_ID = 41038001; + public static final int ELEVATOR_GADGET_ID = 41038002; + @Getter private EntityPlatform platformGadget; + + public EntitySolarIsotomaClientGadget( + Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) { + super(scene, player, notify); + } + + @Override + public void onCreate() { + // Create solar isotoma elevator and send to all. + this.platformGadget = + new EntitySolarIsotomaElevatorPlatform( + this, getScene(), getOwner(), ELEVATOR_GADGET_ID, getPosition(), getRotation()); + getScene().addEntity(this.platformGadget); + } + + @Override + public void onRemoved() { + // Remove solar isotoma elevator entity. + getScene().removeEntity(this.platformGadget); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java index 07bd4a79b..fe783ac8d 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java @@ -1,120 +1,125 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ConfigGadget; -import emu.grasscutter.data.excels.GadgetData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; -import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; -import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; -import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; -import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.net.proto.VehicleInfoOuterClass.VehicleInfo; -import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -public class EntityVehicle extends EntityBaseGadget { - - @Getter - private final Player owner; - @Getter(onMethod_ = @Override) - private final Int2FloatMap fightProperties; - - @Getter - private final int pointId; - @Getter - private final int gadgetId; - - @Getter - @Setter - private float curStamina; - @Getter - private final List vehicleMembers; - @Nullable - @Getter - private ConfigGadget configGadget; - - public EntityVehicle(Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) { - super(scene, pos, rot); - this.owner = player; - this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); - this.fightProperties = new Int2FloatOpenHashMap(); - this.gadgetId = gadgetId; - this.pointId = pointId; - this.curStamina = 240; // might be in configGadget.GCALKECLLLP.JBAKBEFIMBN.ANBMPHPOALP - this.vehicleMembers = new ArrayList<>(); - GadgetData data = GameData.getGadgetDataMap().get(gadgetId); - if (data != null && data.getJsonName() != null) { - this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName()); - } - - fillFightProps(configGadget); - } - - @Override - protected void fillFightProps(ConfigGadget configGadget) { - super.fillFightProps(configGadget); - this.addFightProperty(FightProperty.FIGHT_PROP_CUR_SPEED, 0); - this.addFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 0); - } - - @Override - public SceneEntityInfo toProto() { - - VehicleInfo vehicle = VehicleInfo.newBuilder() - .setOwnerUid(this.owner.getUid()) - .setCurStamina(getCurStamina()) - .build(); - - EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() - .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) - .setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(getPosition().toProto())) - .setBornPos(getPosition().toProto()) - .build(); - - SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() - .setGadgetId(this.getGadgetId()) - .setAuthorityPeerId(this.getOwner().getPeerId()) - .setIsEnableInteract(true) - .setVehicleInfo(vehicle); - - SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) - .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) - .setGadget(gadgetInfo) - .setEntityAuthorityInfo(authority) - .setLifeState(1); - - PropPair pair = PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47)) - .build(); - - this.addAllFightPropsToEntityInfo(entityInfo); - entityInfo.addPropList(pair); - - return entityInfo.build(); - } -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ConfigGadget; +import emu.grasscutter.data.excels.GadgetData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; +import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; +import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; +import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.net.proto.VehicleInfoOuterClass.VehicleInfo; +import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; + +public class EntityVehicle extends EntityBaseGadget { + + @Getter private final Player owner; + + @Getter(onMethod_ = @Override) + private final Int2FloatMap fightProperties; + + @Getter private final int pointId; + @Getter private final int gadgetId; + + @Getter @Setter private float curStamina; + @Getter private final List vehicleMembers; + @Nullable @Getter private ConfigGadget configGadget; + + public EntityVehicle( + Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) { + super(scene, pos, rot); + this.owner = player; + this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); + this.fightProperties = new Int2FloatOpenHashMap(); + this.gadgetId = gadgetId; + this.pointId = pointId; + this.curStamina = 240; // might be in configGadget.GCALKECLLLP.JBAKBEFIMBN.ANBMPHPOALP + this.vehicleMembers = new ArrayList<>(); + GadgetData data = GameData.getGadgetDataMap().get(gadgetId); + if (data != null && data.getJsonName() != null) { + this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName()); + } + + fillFightProps(configGadget); + } + + @Override + protected void fillFightProps(ConfigGadget configGadget) { + super.fillFightProps(configGadget); + this.addFightProperty(FightProperty.FIGHT_PROP_CUR_SPEED, 0); + this.addFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 0); + } + + @Override + public SceneEntityInfo toProto() { + + VehicleInfo vehicle = + VehicleInfo.newBuilder() + .setOwnerUid(this.owner.getUid()) + .setCurStamina(getCurStamina()) + .build(); + + EntityAuthorityInfo authority = + EntityAuthorityInfo.newBuilder() + .setAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) + .setAiInfo( + SceneEntityAiInfo.newBuilder() + .setIsAiOpen(true) + .setBornPos(getPosition().toProto())) + .setBornPos(getPosition().toProto()) + .build(); + + SceneGadgetInfo.Builder gadgetInfo = + SceneGadgetInfo.newBuilder() + .setGadgetId(this.getGadgetId()) + .setAuthorityPeerId(this.getOwner().getPeerId()) + .setIsEnableInteract(true) + .setVehicleInfo(vehicle); + + SceneEntityInfo.Builder entityInfo = + SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setMotionInfo( + MotionInfo.newBuilder() + .setPos(getPosition().toProto()) + .setRot(getRotation().toProto()) + .setSpeed(Vector.newBuilder())) + .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) + .setGadget(gadgetInfo) + .setEntityAuthorityInfo(authority) + .setLifeState(1); + + PropPair pair = + PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47)) + .build(); + + this.addAllFightPropsToEntityInfo(entityInfo); + entityInfo.addPropList(pair); + + return entityInfo.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/GameEntity.java b/src/main/java/emu/grasscutter/game/entity/GameEntity.java index 11aecd754..9ea393a52 100644 --- a/src/main/java/emu/grasscutter/game/entity/GameEntity.java +++ b/src/main/java/emu/grasscutter/game/entity/GameEntity.java @@ -1,247 +1,230 @@ -package emu.grasscutter.game.entity; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.LifeState; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.game.world.SpawnDataEntry; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; -import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import emu.grasscutter.server.event.entity.EntityDamageEvent; -import emu.grasscutter.server.event.entity.EntityDeathEvent; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2FloatMap; -import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -public abstract class GameEntity { - @Getter - private final Scene scene; - @Getter - protected int id; - @Getter - @Setter - private SpawnDataEntry spawnEntry; - - @Getter - @Setter - private int blockId; - @Getter - @Setter - private int configId; - @Getter - @Setter - private int groupId; - - @Getter - @Setter - private MotionState motionState; - @Getter - @Setter - private int lastMoveSceneTimeMs; - @Getter - @Setter - private int lastMoveReliableSeq; - - @Getter - @Setter - private boolean lockHP; - - // Abilities - private Object2FloatMap metaOverrideMap; - private Int2ObjectMap metaModifiers; - - public GameEntity(Scene scene) { - this.scene = scene; - this.motionState = MotionState.MOTION_STATE_NONE; - } - - public int getEntityType() { - return this.getId() >> 24; - } - - public World getWorld() { - return this.getScene().getWorld(); - } - - public boolean isAlive() { - return true; - } - - public LifeState getLifeState() { - return this.isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD; - } - - public Object2FloatMap getMetaOverrideMap() { - if (this.metaOverrideMap == null) { - this.metaOverrideMap = new Object2FloatOpenHashMap<>(); - } - return this.metaOverrideMap; - } - - public Int2ObjectMap getMetaModifiers() { - if (this.metaModifiers == null) { - this.metaModifiers = new Int2ObjectOpenHashMap<>(); - } - return this.metaModifiers; - } - - public abstract Int2FloatMap getFightProperties(); - - public abstract Position getPosition(); - - public abstract Position getRotation(); - - public void setFightProperty(FightProperty prop, float value) { - this.getFightProperties().put(prop.getId(), value); - } - - public void setFightProperty(int id, float value) { - this.getFightProperties().put(id, value); - } - - public void addFightProperty(FightProperty prop, float value) { - this.getFightProperties().put(prop.getId(), this.getFightProperty(prop) + value); - } - - public float getFightProperty(FightProperty prop) { - return this.getFightProperties().getOrDefault(prop.getId(), 0f); - } - - public boolean hasFightProperty(FightProperty prop) { - return this.getFightProperties().containsKey(prop.getId()); - } - - public void addAllFightPropsToEntityInfo(SceneEntityInfo.Builder entityInfo) { - this.getFightProperties().forEach((key, value) -> { - if (key == 0) return; - entityInfo.addFightPropList(FightPropPair.newBuilder().setPropType(key).setPropValue(value).build()); - }); - } - - protected MotionInfo getMotionInfo() { - MotionInfo proto = MotionInfo.newBuilder() - .setPos(this.getPosition().toProto()) - .setRot(this.getRotation().toProto()) - .setSpeed(Vector.newBuilder()) - .setState(this.getMotionState()) - .build(); - - return proto; - } - - public float heal(float amount) { - if (this.getFightProperties() == null) { - return 0f; - } - - float curHp = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - float maxHp = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - - if (curHp >= maxHp) { - return 0f; - } - - float healed = Math.min(maxHp - curHp, amount); - this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed); - - this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); - - return healed; - } - - public void damage(float amount) { - this.damage(amount, 0); - } - - public void damage(float amount, int killerId) { - // Check if the entity has properties. - if (this.getFightProperties() == null || !hasFightProperty(FightProperty.FIGHT_PROP_CUR_HP)) { - return; - } - - // Invoke entity damage event. - EntityDamageEvent event = new EntityDamageEvent(this, amount, this.getScene().getEntityById(killerId)); - event.call(); - if (event.isCanceled()) { - return; // If the event is canceled, do not damage the entity. - } - - float curHp = getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - if (curHp != Float.POSITIVE_INFINITY && !lockHP || lockHP && curHp <= event.getDamage()) { - // Add negative HP to the current HP property. - this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -(event.getDamage())); - } - - // Check if dead - boolean isDead = false; - if (this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) { - this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f); - isDead = true; - } - - // Packets - this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); - - // Check if dead. - if (isDead) { - this.getScene().killEntity(this, killerId); - } - } - - /** - * Move this entity to a new position. - * - * @param position The new position. - * @param rotation The new rotation. - */ - public void move(Position position, Position rotation) { - // Set the position and rotation. - this.getPosition().set(position); - this.getRotation().set(rotation); - } - - /** - * Called when a player interacts with this entity - * - * @param player Player that is interacting with this entity - * @param interactReq Interact request protobuf data - */ - public void onInteract(Player player, GadgetInteractReq interactReq) { - - } - - /** - * Called when this entity is added to the world - */ - public void onCreate() { - - } - - public void onRemoved() { - - } - - /** - * Called when this entity dies - * - * @param killerId Entity id of the entity that killed this entity - */ - public void onDeath(int killerId) { - // Invoke entity death event. - EntityDeathEvent event = new EntityDeathEvent(this, killerId); - event.call(); - } - - public abstract SceneEntityInfo toProto(); -} +package emu.grasscutter.game.entity; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.game.world.SpawnDataEntry; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.server.event.entity.EntityDamageEvent; +import emu.grasscutter.server.event.entity.EntityDeathEvent; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2FloatMap; +import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; +import lombok.Getter; +import lombok.Setter; + +public abstract class GameEntity { + @Getter private final Scene scene; + @Getter protected int id; + @Getter @Setter private SpawnDataEntry spawnEntry; + + @Getter @Setter private int blockId; + @Getter @Setter private int configId; + @Getter @Setter private int groupId; + + @Getter @Setter private MotionState motionState; + @Getter @Setter private int lastMoveSceneTimeMs; + @Getter @Setter private int lastMoveReliableSeq; + + @Getter @Setter private boolean lockHP; + + // Abilities + private Object2FloatMap metaOverrideMap; + private Int2ObjectMap metaModifiers; + + public GameEntity(Scene scene) { + this.scene = scene; + this.motionState = MotionState.MOTION_STATE_NONE; + } + + public int getEntityType() { + return this.getId() >> 24; + } + + public World getWorld() { + return this.getScene().getWorld(); + } + + public boolean isAlive() { + return true; + } + + public LifeState getLifeState() { + return this.isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD; + } + + public Object2FloatMap getMetaOverrideMap() { + if (this.metaOverrideMap == null) { + this.metaOverrideMap = new Object2FloatOpenHashMap<>(); + } + return this.metaOverrideMap; + } + + public Int2ObjectMap getMetaModifiers() { + if (this.metaModifiers == null) { + this.metaModifiers = new Int2ObjectOpenHashMap<>(); + } + return this.metaModifiers; + } + + public abstract Int2FloatMap getFightProperties(); + + public abstract Position getPosition(); + + public abstract Position getRotation(); + + public void setFightProperty(FightProperty prop, float value) { + this.getFightProperties().put(prop.getId(), value); + } + + public void setFightProperty(int id, float value) { + this.getFightProperties().put(id, value); + } + + public void addFightProperty(FightProperty prop, float value) { + this.getFightProperties().put(prop.getId(), this.getFightProperty(prop) + value); + } + + public float getFightProperty(FightProperty prop) { + return this.getFightProperties().getOrDefault(prop.getId(), 0f); + } + + public boolean hasFightProperty(FightProperty prop) { + return this.getFightProperties().containsKey(prop.getId()); + } + + public void addAllFightPropsToEntityInfo(SceneEntityInfo.Builder entityInfo) { + this.getFightProperties() + .forEach( + (key, value) -> { + if (key == 0) return; + entityInfo.addFightPropList( + FightPropPair.newBuilder().setPropType(key).setPropValue(value).build()); + }); + } + + protected MotionInfo getMotionInfo() { + MotionInfo proto = + MotionInfo.newBuilder() + .setPos(this.getPosition().toProto()) + .setRot(this.getRotation().toProto()) + .setSpeed(Vector.newBuilder()) + .setState(this.getMotionState()) + .build(); + + return proto; + } + + public float heal(float amount) { + if (this.getFightProperties() == null) { + return 0f; + } + + float curHp = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + float maxHp = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + + if (curHp >= maxHp) { + return 0f; + } + + float healed = Math.min(maxHp - curHp, amount); + this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed); + + this.getScene() + .broadcastPacket( + new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); + + return healed; + } + + public void damage(float amount) { + this.damage(amount, 0); + } + + public void damage(float amount, int killerId) { + // Check if the entity has properties. + if (this.getFightProperties() == null || !hasFightProperty(FightProperty.FIGHT_PROP_CUR_HP)) { + return; + } + + // Invoke entity damage event. + EntityDamageEvent event = + new EntityDamageEvent(this, amount, this.getScene().getEntityById(killerId)); + event.call(); + if (event.isCanceled()) { + return; // If the event is canceled, do not damage the entity. + } + + float curHp = getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + if (curHp != Float.POSITIVE_INFINITY && !lockHP || lockHP && curHp <= event.getDamage()) { + // Add negative HP to the current HP property. + this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -(event.getDamage())); + } + + // Check if dead + boolean isDead = false; + if (this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) { + this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f); + isDead = true; + } + + // Packets + this.getScene() + .broadcastPacket( + new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); + + // Check if dead. + if (isDead) { + this.getScene().killEntity(this, killerId); + } + } + + /** + * Move this entity to a new position. + * + * @param position The new position. + * @param rotation The new rotation. + */ + public void move(Position position, Position rotation) { + // Set the position and rotation. + this.getPosition().set(position); + this.getRotation().set(rotation); + } + + /** + * Called when a player interacts with this entity + * + * @param player Player that is interacting with this entity + * @param interactReq Interact request protobuf data + */ + public void onInteract(Player player, GadgetInteractReq interactReq) {} + + /** Called when this entity is added to the world */ + public void onCreate() {} + + public void onRemoved() {} + + /** + * Called when this entity dies + * + * @param killerId Entity id of the entity that killed this entity + */ + public void onDeath(int killerId) { + // Invoke entity death event. + EntityDeathEvent event = new EntityDeathEvent(this, killerId); + event.call(); + } + + public abstract SceneEntityInfo toProto(); +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java index ca016f0d9..033ebb308 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetChest.java @@ -1,71 +1,88 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType; -import emu.grasscutter.net.proto.InteractTypeOuterClass; -import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; -import emu.grasscutter.net.proto.ResinCostTypeOuterClass; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.scripts.constants.ScriptGadgetState; -import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; - -public class GadgetChest extends GadgetContent { - - public GadgetChest(EntityGadget gadget) { - super(gadget); - } - - public boolean onInteract(Player player, GadgetInteractReq req) { - var chestInteractHandlerMap = getGadget().getScene().getWorld().getServer().getWorldDataSystem().getChestInteractHandlerMap(); - var handler = chestInteractHandlerMap.get(getGadget().getGadgetData().getJsonName()); - if (handler == null) { - Grasscutter.getLogger().warn("Could not found the handler of this type of Chests {}", getGadget().getGadgetData().getJsonName()); - return false; - } - - if (req.getOpType() == InterOpType.INTER_OP_TYPE_START && handler.isTwoStep()) { - player.sendPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_CHEST, InterOpType.INTER_OP_TYPE_START)); - return false; - } else { - boolean success; - if (handler instanceof BossChestInteractHandler bossChestInteractHandler) { - success = bossChestInteractHandler.onInteract(this, player, - req.getResinCostType() == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE); - } else { - success = handler.onInteract(this, player); - } - if (!success) { - return false; - } - - getGadget().updateState(ScriptGadgetState.ChestOpened); - player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST)); - - return true; - } - } - - public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { - if (getGadget().getMetaGadget() == null) { - return; - } - - var bossChest = getGadget().getMetaGadget().boss_chest; - if (bossChest != null) { - var players = getGadget().getScene().getPlayers().stream().map(Player::getUid).toList(); - - gadgetInfo.setBossChest(BossChestInfo.newBuilder() - .setMonsterConfigId(bossChest.monster_config_id) - .setResin(bossChest.resin) - .addAllQualifyUidList(players) - .addAllRemainUidList(players) - .build()); - } - - } -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType; +import emu.grasscutter.net.proto.InteractTypeOuterClass; +import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; +import emu.grasscutter.net.proto.ResinCostTypeOuterClass; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.scripts.constants.ScriptGadgetState; +import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; + +public class GadgetChest extends GadgetContent { + + public GadgetChest(EntityGadget gadget) { + super(gadget); + } + + public boolean onInteract(Player player, GadgetInteractReq req) { + var chestInteractHandlerMap = + getGadget() + .getScene() + .getWorld() + .getServer() + .getWorldDataSystem() + .getChestInteractHandlerMap(); + var handler = chestInteractHandlerMap.get(getGadget().getGadgetData().getJsonName()); + if (handler == null) { + Grasscutter.getLogger() + .warn( + "Could not found the handler of this type of Chests {}", + getGadget().getGadgetData().getJsonName()); + return false; + } + + if (req.getOpType() == InterOpType.INTER_OP_TYPE_START && handler.isTwoStep()) { + player.sendPacket( + new PacketGadgetInteractRsp( + getGadget(), InteractType.INTERACT_TYPE_OPEN_CHEST, InterOpType.INTER_OP_TYPE_START)); + return false; + } else { + boolean success; + if (handler instanceof BossChestInteractHandler bossChestInteractHandler) { + success = + bossChestInteractHandler.onInteract( + this, + player, + req.getResinCostType() + == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE); + } else { + success = handler.onInteract(this, player); + } + if (!success) { + return false; + } + + getGadget().updateState(ScriptGadgetState.ChestOpened); + player.sendPacket( + new PacketGadgetInteractRsp( + this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST)); + + return true; + } + } + + public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { + if (getGadget().getMetaGadget() == null) { + return; + } + + var bossChest = getGadget().getMetaGadget().boss_chest; + if (bossChest != null) { + var players = getGadget().getScene().getPlayers().stream().map(Player::getUid).toList(); + + gadgetInfo.setBossChest( + BossChestInfo.newBuilder() + .setMonsterConfigId(bossChest.monster_config_id) + .setResin(bossChest.resin) + .addAllQualifyUidList(players) + .addAllRemainUidList(players) + .build()); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetContent.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetContent.java index 091957832..811fccc47 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetContent.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetContent.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; - -public abstract class GadgetContent { - private final EntityGadget gadget; - - public GadgetContent(EntityGadget gadget) { - this.gadget = gadget; - } - - public EntityGadget getGadget() { - return gadget; - } - - public abstract boolean onInteract(Player player, GadgetInteractReq req); - - public abstract void onBuildProto(SceneGadgetInfo.Builder gadgetInfo); -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; + +public abstract class GadgetContent { + private final EntityGadget gadget; + + public GadgetContent(EntityGadget gadget) { + this.gadget = gadget; + } + + public EntityGadget getGadget() { + return gadget; + } + + public abstract boolean onInteract(Player player, GadgetInteractReq req); + + public abstract void onBuildProto(SceneGadgetInfo.Builder gadgetInfo); +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherObject.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherObject.java index 82dc14efc..a37fd8125 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherObject.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherObject.java @@ -1,81 +1,86 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityItem; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo; -import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; -import emu.grasscutter.utils.Utils; - -public class GadgetGatherObject extends GadgetContent { - private int itemId; - private boolean isForbidGuest; - - public GadgetGatherObject(EntityGadget gadget) { - super(gadget); - - if (gadget.getSpawnEntry() != null) { - this.itemId = gadget.getSpawnEntry().getGatherItemId(); - } - } - - public int getItemId() { - return this.itemId; - } - - public boolean isForbidGuest() { - return isForbidGuest; - } - - public boolean onInteract(Player player, GadgetInteractReq req) { - // Sanity check - ItemData itemData = GameData.getItemDataMap().get(getItemId()); - if (itemData == null) { - return false; - } - - GameItem item = new GameItem(itemData, 1); - player.getInventory().addItem(item, ActionReason.Gather); - - getGadget().getScene().broadcastPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_GATHER)); - - return true; - } - - public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { - GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder() - .setItemId(this.getItemId()) - .setIsForbidGuest(this.isForbidGuest()) - .build(); - - gadgetInfo.setGatherGadget(gatherGadgetInfo); - } - - public void dropItems(Player player) { - Scene scene = getGadget().getScene(); - int times = Utils.randomRange(1, 2); - - for (int i = 0; i < times; i++) { - EntityItem item = new EntityItem( - scene, - player, - GameData.getItemDataMap().get(itemId), - getGadget().getPosition().nearby2d(1f).addY(2f), - 1, - true); - - scene.addEntity(item); - } - - scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId()); - // Todo: add record - } -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo; +import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; +import emu.grasscutter.utils.Utils; + +public class GadgetGatherObject extends GadgetContent { + private int itemId; + private boolean isForbidGuest; + + public GadgetGatherObject(EntityGadget gadget) { + super(gadget); + + if (gadget.getSpawnEntry() != null) { + this.itemId = gadget.getSpawnEntry().getGatherItemId(); + } + } + + public int getItemId() { + return this.itemId; + } + + public boolean isForbidGuest() { + return isForbidGuest; + } + + public boolean onInteract(Player player, GadgetInteractReq req) { + // Sanity check + ItemData itemData = GameData.getItemDataMap().get(getItemId()); + if (itemData == null) { + return false; + } + + GameItem item = new GameItem(itemData, 1); + player.getInventory().addItem(item, ActionReason.Gather); + + getGadget() + .getScene() + .broadcastPacket( + new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_GATHER)); + + return true; + } + + public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { + GatherGadgetInfo gatherGadgetInfo = + GatherGadgetInfo.newBuilder() + .setItemId(this.getItemId()) + .setIsForbidGuest(this.isForbidGuest()) + .build(); + + gadgetInfo.setGatherGadget(gatherGadgetInfo); + } + + public void dropItems(Player player) { + Scene scene = getGadget().getScene(); + int times = Utils.randomRange(1, 2); + + for (int i = 0; i < times; i++) { + EntityItem item = + new EntityItem( + scene, + player, + GameData.getItemDataMap().get(itemId), + getGadget().getPosition().nearby2d(1f).addY(2f), + 1, + true); + + scene.addEntity(item); + } + + scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId()); + // Todo: add record + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherPoint.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherPoint.java index dd4c14b98..b5f44152c 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherPoint.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetGatherPoint.java @@ -1,79 +1,83 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.GatherData; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityItem; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.utils.Utils; - -public class GadgetGatherPoint extends GadgetContent { - private final int itemId; - private boolean isForbidGuest; - - public GadgetGatherPoint(EntityGadget gadget) { - super(gadget); - - if (gadget.getSpawnEntry() != null) { - this.itemId = gadget.getSpawnEntry().getGatherItemId(); - } else { - GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType()); - this.itemId = gatherData.getItemId(); - this.isForbidGuest = gatherData.isForbidGuest(); - } - } - - public int getItemId() { - return this.itemId; - } - - public boolean isForbidGuest() { - return isForbidGuest; - } - - public boolean onInteract(Player player, GadgetInteractReq req) { - GameItem item = new GameItem(getItemId(), 1); - - player.getInventory().addItem(item, ActionReason.Gather); - - return true; - } - - public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { - GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder() - .setItemId(this.getItemId()) - .setIsForbidGuest(this.isForbidGuest()) - .build(); - - gadgetInfo.setGatherGadget(gatherGadgetInfo); - } - - public void dropItems(Player player) { - Scene scene = getGadget().getScene(); - int times = Utils.randomRange(1, 2); - - for (int i = 0; i < times; i++) { - EntityItem item = new EntityItem( - scene, - player, - GameData.getItemDataMap().get(itemId), - getGadget().getPosition().clone() - .addY(2f) - .addX(Utils.randomFloatRange(-1f, 1f)) - .addZ(Utils.randomFloatRange(-1f, 1f)), - 1, - true); - - scene.addEntity(item); - } - - scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId()); - // Todo: add record - } -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.GatherData; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.utils.Utils; + +public class GadgetGatherPoint extends GadgetContent { + private final int itemId; + private boolean isForbidGuest; + + public GadgetGatherPoint(EntityGadget gadget) { + super(gadget); + + if (gadget.getSpawnEntry() != null) { + this.itemId = gadget.getSpawnEntry().getGatherItemId(); + } else { + GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType()); + this.itemId = gatherData.getItemId(); + this.isForbidGuest = gatherData.isForbidGuest(); + } + } + + public int getItemId() { + return this.itemId; + } + + public boolean isForbidGuest() { + return isForbidGuest; + } + + public boolean onInteract(Player player, GadgetInteractReq req) { + GameItem item = new GameItem(getItemId(), 1); + + player.getInventory().addItem(item, ActionReason.Gather); + + return true; + } + + public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { + GatherGadgetInfo gatherGadgetInfo = + GatherGadgetInfo.newBuilder() + .setItemId(this.getItemId()) + .setIsForbidGuest(this.isForbidGuest()) + .build(); + + gadgetInfo.setGatherGadget(gatherGadgetInfo); + } + + public void dropItems(Player player) { + Scene scene = getGadget().getScene(); + int times = Utils.randomRange(1, 2); + + for (int i = 0; i < times; i++) { + EntityItem item = + new EntityItem( + scene, + player, + GameData.getItemDataMap().get(itemId), + getGadget() + .getPosition() + .clone() + .addY(2f) + .addX(Utils.randomFloatRange(-1f, 1f)) + .addZ(Utils.randomFloatRange(-1f, 1f)), + 1, + true); + + scene.addEntity(item); + } + + scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId()); + // Todo: add record + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetObject.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetObject.java index 0f190a34c..583eb23b3 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetObject.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetObject.java @@ -1,22 +1,20 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass; - -public class GadgetObject extends GadgetContent { - public GadgetObject(EntityGadget gadget) { - super(gadget); - } - - @Override - public boolean onInteract(Player player, GadgetInteractReqOuterClass.GadgetInteractReq req) { - return false; - } - - @Override - public void onBuildProto(SceneGadgetInfoOuterClass.SceneGadgetInfo.Builder gadgetInfo) { - - } -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass; + +public class GadgetObject extends GadgetContent { + public GadgetObject(EntityGadget gadget) { + super(gadget); + } + + @Override + public boolean onInteract(Player player, GadgetInteractReqOuterClass.GadgetInteractReq req) { + return false; + } + + @Override + public void onBuildProto(SceneGadgetInfoOuterClass.SceneGadgetInfo.Builder gadgetInfo) {} +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetRewardStatue.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetRewardStatue.java index e1f15b2ee..b327b77e4 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetRewardStatue.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetRewardStatue.java @@ -1,30 +1,30 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; - -public class GadgetRewardStatue extends GadgetContent { - - public GadgetRewardStatue(EntityGadget gadget) { - super(gadget); - } - - public boolean onInteract(Player player, GadgetInteractReq req) { - if (player.getScene().getChallenge() != null && player.getScene().getChallenge() instanceof DungeonChallenge dungeonChallenge) { - dungeonChallenge.getStatueDrops(player, req); - } - - player.sendPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_STATUE)); - - return false; - } - - public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { - - } -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp; + +public class GadgetRewardStatue extends GadgetContent { + + public GadgetRewardStatue(EntityGadget gadget) { + super(gadget); + } + + public boolean onInteract(Player player, GadgetInteractReq req) { + if (player.getScene().getChallenge() != null + && player.getScene().getChallenge() instanceof DungeonChallenge dungeonChallenge) { + dungeonChallenge.getStatueDrops(player, req); + } + + player.sendPacket( + new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_STATUE)); + + return false; + } + + public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {} +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetWorktop.java b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetWorktop.java index c83813ff5..3a5976b9b 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/GadgetWorktop.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/GadgetWorktop.java @@ -1,68 +1,65 @@ -package emu.grasscutter.game.entity.gadget; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.gadget.worktop.WorktopWorktopOptionHandler; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; -import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq; -import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; - -import java.util.Arrays; - -public class GadgetWorktop extends GadgetContent { - private IntSet worktopOptions; - private WorktopWorktopOptionHandler handler; - - public GadgetWorktop(EntityGadget gadget) { - super(gadget); - } - - public IntSet getWorktopOptions() { - return worktopOptions; - } - - public void addWorktopOptions(int[] options) { - if (this.worktopOptions == null) { - this.worktopOptions = new IntOpenHashSet(); - } - Arrays.stream(options).forEach(this.worktopOptions::add); - } - - public void removeWorktopOption(int option) { - if (this.worktopOptions == null) { - return; - } - this.worktopOptions.remove(option); - } - - public boolean onInteract(Player player, GadgetInteractReq req) { - return false; - } - - public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { - if (this.worktopOptions == null) { - return; - } - - WorktopInfo worktop = WorktopInfo.newBuilder() - .addAllOptionList(this.getWorktopOptions()) - .build(); - - gadgetInfo.setWorktop(worktop); - } - - public void setOnSelectWorktopOptionEvent(WorktopWorktopOptionHandler handler) { - this.handler = handler; - } - - public boolean onSelectWorktopOption(SelectWorktopOptionReq req) { - if (this.handler != null) { - this.handler.onSelectWorktopOption(this, req.getOptionId()); - } - return false; - } - -} +package emu.grasscutter.game.entity.gadget; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.gadget.worktop.WorktopWorktopOptionHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo; +import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq; +import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import java.util.Arrays; + +public class GadgetWorktop extends GadgetContent { + private IntSet worktopOptions; + private WorktopWorktopOptionHandler handler; + + public GadgetWorktop(EntityGadget gadget) { + super(gadget); + } + + public IntSet getWorktopOptions() { + return worktopOptions; + } + + public void addWorktopOptions(int[] options) { + if (this.worktopOptions == null) { + this.worktopOptions = new IntOpenHashSet(); + } + Arrays.stream(options).forEach(this.worktopOptions::add); + } + + public void removeWorktopOption(int option) { + if (this.worktopOptions == null) { + return; + } + this.worktopOptions.remove(option); + } + + public boolean onInteract(Player player, GadgetInteractReq req) { + return false; + } + + public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) { + if (this.worktopOptions == null) { + return; + } + + WorktopInfo worktop = + WorktopInfo.newBuilder().addAllOptionList(this.getWorktopOptions()).build(); + + gadgetInfo.setWorktop(worktop); + } + + public void setOnSelectWorktopOptionEvent(WorktopWorktopOptionHandler handler) { + this.handler = handler; + } + + public boolean onSelectWorktopOption(SelectWorktopOptionReq req) { + if (this.handler != null) { + this.handler.onSelectWorktopOption(this, req.getOptionId()); + } + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/chest/BossChestInteractHandler.java b/src/main/java/emu/grasscutter/game/entity/gadget/chest/BossChestInteractHandler.java index 31cf7815c..b931bf514 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/chest/BossChestInteractHandler.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/chest/BossChestInteractHandler.java @@ -1,51 +1,61 @@ -package emu.grasscutter.game.entity.gadget.chest; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.entity.gadget.GadgetChest; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify; - -import java.util.ArrayList; -import java.util.List; - -public class BossChestInteractHandler implements ChestInteractHandler { - @Override - public boolean isTwoStep() { - return true; - } - - @Override - public boolean onInteract(GadgetChest chest, Player player) { - return this.onInteract(chest, player, false); - } - - public boolean onInteract(GadgetChest chest, Player player, boolean useCondensedResin) { - var blossomRewards = player.getScene().getBlossomManager().onReward(player, chest.getGadget(), useCondensedResin); - if (blossomRewards != null) { - player.getInventory().addItems(blossomRewards, ActionReason.OpenWorldBossChest); - player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(blossomRewards)); - return true; - } - - var worldDataManager = chest.getGadget().getScene().getWorld().getServer().getWorldDataSystem(); - var monster = chest.getGadget().getMetaGadget().group.monsters.get(chest.getGadget().getMetaGadget().boss_chest.monster_config_id); - var reward = worldDataManager.getRewardByBossId(monster.monster_id); - - if (reward == null) { - Grasscutter.getLogger().warn("Could not found the reward of boss monster {}", monster.monster_id); - return false; - } - List rewards = new ArrayList<>(); - for (ItemParamData param : reward.getPreviewItems()) { - rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); - } - - player.getInventory().addItems(rewards, ActionReason.OpenWorldBossChest); - player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards)); - - return true; - } -} +package emu.grasscutter.game.entity.gadget.chest; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.entity.gadget.GadgetChest; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify; +import java.util.ArrayList; +import java.util.List; + +public class BossChestInteractHandler implements ChestInteractHandler { + @Override + public boolean isTwoStep() { + return true; + } + + @Override + public boolean onInteract(GadgetChest chest, Player player) { + return this.onInteract(chest, player, false); + } + + public boolean onInteract(GadgetChest chest, Player player, boolean useCondensedResin) { + var blossomRewards = + player + .getScene() + .getBlossomManager() + .onReward(player, chest.getGadget(), useCondensedResin); + if (blossomRewards != null) { + player.getInventory().addItems(blossomRewards, ActionReason.OpenWorldBossChest); + player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(blossomRewards)); + return true; + } + + var worldDataManager = chest.getGadget().getScene().getWorld().getServer().getWorldDataSystem(); + var monster = + chest + .getGadget() + .getMetaGadget() + .group + .monsters + .get(chest.getGadget().getMetaGadget().boss_chest.monster_config_id); + var reward = worldDataManager.getRewardByBossId(monster.monster_id); + + if (reward == null) { + Grasscutter.getLogger() + .warn("Could not found the reward of boss monster {}", monster.monster_id); + return false; + } + List rewards = new ArrayList<>(); + for (ItemParamData param : reward.getPreviewItems()) { + rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); + } + + player.getInventory().addItems(rewards, ActionReason.OpenWorldBossChest); + player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards)); + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java b/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java index dff206b09..ebab73b24 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/chest/NormalChestInteractHandler.java @@ -1,42 +1,50 @@ -package emu.grasscutter.game.entity.gadget.chest; - -import emu.grasscutter.game.entity.gadget.GadgetChest; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.ChestReward; - -import java.util.Random; - -public class NormalChestInteractHandler implements ChestInteractHandler { - private final ChestReward chestReward; - - public NormalChestInteractHandler(ChestReward rewardData) { - this.chestReward = rewardData; - } - - @Override - public boolean isTwoStep() { - return false; - } - - @Override - public boolean onInteract(GadgetChest chest, Player player) { - player.earnExp(chestReward.getAdvExp()); - player.getInventory().addItem(201, chestReward.getResin()); - - var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5); - player.getInventory().addItem(202, (int) mora); - - for (int i = 0; i < chestReward.getContent().size(); i++) { - chest.getGadget().getScene().addItemEntity(chestReward.getContent().get(i).getItemId(), chestReward.getContent().get(i).getCount(), chest.getGadget()); - } - - var random = new Random(System.currentTimeMillis()); - for (int i = 0; i < chestReward.getRandomCount(); i++) { - var index = random.nextInt(chestReward.getRandomContent().size()); - var item = chestReward.getRandomContent().get(index); - chest.getGadget().getScene().addItemEntity(item.getItemId(), item.getCount(), chest.getGadget()); - } - - return true; - } -} +package emu.grasscutter.game.entity.gadget.chest; + +import emu.grasscutter.game.entity.gadget.GadgetChest; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.ChestReward; +import java.util.Random; + +public class NormalChestInteractHandler implements ChestInteractHandler { + private final ChestReward chestReward; + + public NormalChestInteractHandler(ChestReward rewardData) { + this.chestReward = rewardData; + } + + @Override + public boolean isTwoStep() { + return false; + } + + @Override + public boolean onInteract(GadgetChest chest, Player player) { + player.earnExp(chestReward.getAdvExp()); + player.getInventory().addItem(201, chestReward.getResin()); + + var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5); + player.getInventory().addItem(202, (int) mora); + + for (int i = 0; i < chestReward.getContent().size(); i++) { + chest + .getGadget() + .getScene() + .addItemEntity( + chestReward.getContent().get(i).getItemId(), + chestReward.getContent().get(i).getCount(), + chest.getGadget()); + } + + var random = new Random(System.currentTimeMillis()); + for (int i = 0; i < chestReward.getRandomCount(); i++) { + var index = random.nextInt(chestReward.getRandomContent().size()); + var item = chestReward.getRandomContent().get(index); + chest + .getGadget() + .getScene() + .addItemEntity(item.getItemId(), item.getCount(), chest.getGadget()); + } + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/worktop/WorktopWorktopOptionHandler.java b/src/main/java/emu/grasscutter/game/entity/gadget/worktop/WorktopWorktopOptionHandler.java index 7efb19bf7..86268af41 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/worktop/WorktopWorktopOptionHandler.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/worktop/WorktopWorktopOptionHandler.java @@ -1,7 +1,7 @@ -package emu.grasscutter.game.entity.gadget.worktop; - -import emu.grasscutter.game.entity.gadget.GadgetWorktop; - -public interface WorktopWorktopOptionHandler { - boolean onSelectWorktopOption(GadgetWorktop gadgetWorktop, int option); -} +package emu.grasscutter.game.entity.gadget.worktop; + +import emu.grasscutter.game.entity.gadget.GadgetWorktop; + +public interface WorktopWorktopOptionHandler { + boolean onSelectWorktopOption(GadgetWorktop gadgetWorktop, int option); +} diff --git a/src/main/java/emu/grasscutter/game/entity/platform/EntityPlatform.java b/src/main/java/emu/grasscutter/game/entity/platform/EntityPlatform.java index 03428691b..0dc55b548 100644 --- a/src/main/java/emu/grasscutter/game/entity/platform/EntityPlatform.java +++ b/src/main/java/emu/grasscutter/game/entity/platform/EntityPlatform.java @@ -1,97 +1,101 @@ -package emu.grasscutter.game.entity.platform; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ConfigGadget; -import emu.grasscutter.data.excels.GadgetData; -import emu.grasscutter.game.entity.EntityBaseGadget; -import emu.grasscutter.game.entity.EntityClientGadget; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.*; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2FloatMap; -import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -import javax.annotation.Nullable; - -public class EntityPlatform extends EntityBaseGadget { - @Getter - private final Player owner; - @Getter(onMethod_ = @Override) - private final int gadgetId; - @Getter - private final EntityClientGadget gadget; - @Getter(onMethod_ = @Override) - private final Int2FloatMap fightProperties; - @Getter - private final MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType; - @Nullable - @Getter - private ConfigGadget configGadget; - @Getter - @Setter - private boolean isStarted; - @Getter - @Setter - private boolean isActive; - - public EntityPlatform(EntityClientGadget gadget, Scene scene, Player player, int gadgetId, Position pos, Position rot, MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType) { - super(scene, pos, rot); - this.gadget = gadget; - this.owner = player; - this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); - this.fightProperties = new Int2FloatOpenHashMap(); - this.movingPlatformType = movingPlatformType; - this.gadgetId = gadgetId; - GadgetData data = GameData.getGadgetDataMap().get(gadgetId); - if (data != null && data.getJsonName() != null) { - this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName()); - } - - fillFightProps(configGadget); - } - - @Override - public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { - var platform = PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setMovingPlatformType(movingPlatformType) - .build(); - - var gadgetInfo = SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder() - .setGadgetId(getGadgetId()) - .setAuthorityPeerId(getOwner().getPeerId()) - .setPlatform(platform); - - var entityInfo = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() - .setEntityId(getId()) - .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setGadget(gadgetInfo) - .setLifeState(1); - - this.addAllFightPropsToEntityInfo(entityInfo); - return entityInfo.build(); - } - - public PlatformInfoOuterClass.PlatformInfo onStartRoute() { - return PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setStartSceneTime(getScene().getSceneTime()) - .setIsStarted(true) - .setPosOffset(getPosition().toProto()) - .setMovingPlatformType(getMovingPlatformType()) - .setIsActive(true) - .build(); - } - - public PlatformInfoOuterClass.PlatformInfo onStopRoute() { - var sceneTime = getScene().getSceneTime(); - return PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setStartSceneTime(sceneTime) - .setStopSceneTime(sceneTime) - .setPosOffset(getPosition().toProto()) - .setMovingPlatformType(getMovingPlatformType()) - .build(); - } -} +package emu.grasscutter.game.entity.platform; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ConfigGadget; +import emu.grasscutter.data.excels.GadgetData; +import emu.grasscutter.game.entity.EntityBaseGadget; +import emu.grasscutter.game.entity.EntityClientGadget; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.*; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2FloatMap; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; + +public class EntityPlatform extends EntityBaseGadget { + @Getter private final Player owner; + + @Getter(onMethod_ = @Override) + private final int gadgetId; + + @Getter private final EntityClientGadget gadget; + + @Getter(onMethod_ = @Override) + private final Int2FloatMap fightProperties; + + @Getter private final MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType; + @Nullable @Getter private ConfigGadget configGadget; + @Getter @Setter private boolean isStarted; + @Getter @Setter private boolean isActive; + + public EntityPlatform( + EntityClientGadget gadget, + Scene scene, + Player player, + int gadgetId, + Position pos, + Position rot, + MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType) { + super(scene, pos, rot); + this.gadget = gadget; + this.owner = player; + this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); + this.fightProperties = new Int2FloatOpenHashMap(); + this.movingPlatformType = movingPlatformType; + this.gadgetId = gadgetId; + GadgetData data = GameData.getGadgetDataMap().get(gadgetId); + if (data != null && data.getJsonName() != null) { + this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName()); + } + + fillFightProps(configGadget); + } + + @Override + public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { + var platform = + PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setMovingPlatformType(movingPlatformType) + .build(); + + var gadgetInfo = + SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder() + .setGadgetId(getGadgetId()) + .setAuthorityPeerId(getOwner().getPeerId()) + .setPlatform(platform); + + var entityInfo = + SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() + .setEntityId(getId()) + .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setGadget(gadgetInfo) + .setLifeState(1); + + this.addAllFightPropsToEntityInfo(entityInfo); + return entityInfo.build(); + } + + public PlatformInfoOuterClass.PlatformInfo onStartRoute() { + return PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setStartSceneTime(getScene().getSceneTime()) + .setIsStarted(true) + .setPosOffset(getPosition().toProto()) + .setMovingPlatformType(getMovingPlatformType()) + .setIsActive(true) + .build(); + } + + public PlatformInfoOuterClass.PlatformInfo onStopRoute() { + var sceneTime = getScene().getSceneTime(); + return PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setStartSceneTime(sceneTime) + .setStopSceneTime(sceneTime) + .setPosOffset(getPosition().toProto()) + .setMovingPlatformType(getMovingPlatformType()) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/entity/platform/EntitySolarIsotomaElevatorPlatform.java b/src/main/java/emu/grasscutter/game/entity/platform/EntitySolarIsotomaElevatorPlatform.java index 3bdedd4b0..fda82ed73 100644 --- a/src/main/java/emu/grasscutter/game/entity/platform/EntitySolarIsotomaElevatorPlatform.java +++ b/src/main/java/emu/grasscutter/game/entity/platform/EntitySolarIsotomaElevatorPlatform.java @@ -1,136 +1,153 @@ -package emu.grasscutter.game.entity.platform; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.binout.ConfigGadget; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.EntitySolarIsotomaClientGadget; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.*; -import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.ProtoHelper; - -public class EntitySolarIsotomaElevatorPlatform extends EntityPlatform { - public EntitySolarIsotomaElevatorPlatform(EntitySolarIsotomaClientGadget isotoma, Scene scene, Player player, int gadgetId, Position pos, Position rot) { - super(isotoma, scene, player, gadgetId, pos, rot, MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY); - } - - @Override - protected void fillFightProps(ConfigGadget configGadget) { - if (configGadget == null || configGadget.getCombat() == null) { - return; - } - var combatData = configGadget.getCombat(); - var combatProperties = combatData.getProperty(); - - if (combatProperties.isUseCreatorProperty()) { - //If useCreatorProperty == true, use owner's property; - GameEntity ownerAvatar = getScene().getEntityById(getGadget().getOwnerEntityId()); - if (ownerAvatar != null) { - getFightProperties().putAll(ownerAvatar.getFightProperties()); - return; - } else { - Grasscutter.getLogger().warn("Why gadget owner is null?"); - } - } - - super.fillFightProps(configGadget); - } - - @Override - public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { - var gadget = SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder() - .setGadgetId(getGadgetId()) - .setOwnerEntityId(getGadget().getId()) - .setAuthorityPeerId(getOwner().getPeerId()) - .setIsEnableInteract(true) - .setAbilityGadget(AbilityGadgetInfoOuterClass.AbilityGadgetInfo.newBuilder() - .setCampId(getGadget().getCampId()) - .setCampTargetType(getGadget().getCampType()) - .setTargetEntityId(getGadget().getId()) - .build()) - .setPlatform(PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setStartRot(MathQuaternionOuterClass.MathQuaternion.newBuilder() - .setW(1.0F) - .build()) - .setPosOffset(getGadget().getPosition().toProto()) - .setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder() - .setW(1.0F) - .build()) - .setMovingPlatformType(MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY) - .build()) - .build(); - - var authority = EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder() - .setAiInfo(SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder() - .setIsAiOpen(true) - .setBornPos(getGadget().getPosition().toProto())) - .setBornPos(getGadget().getPosition().toProto()) - .build(); - - var info = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() - .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET) - .setEntityId(getId()) - .setMotionInfo(MotionInfoOuterClass.MotionInfo.newBuilder() - .setPos(getGadget().getPosition().toProto()) - .setRot(getGadget().getRotation().toProto()) - .build()); - - GameEntity entity = getScene().getEntityById(getGadget().getOwnerEntityId()); - if (entity instanceof EntityAvatar avatar) { - info.addPropList(PropPairOuterClass.PropPair.newBuilder() - .setType(PlayerProperty.PROP_LEVEL.getId()) - .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, avatar.getAvatar().getLevel())) - .build()); - } else { - Grasscutter.getLogger().warn("Why gadget owner doesn't exist?"); - } - - this.addAllFightPropsToEntityInfo(info); - - info.setLifeState(1) - .setGadget(gadget) - .setEntityAuthorityInfo(authority); - - return info.build(); - } - - @Override - public PlatformInfoOuterClass.PlatformInfo onStartRoute() { - setStarted(true); - setActive(true); - - var sceneTime = getScene().getSceneTime(); - getOwner().sendPacket(new PacketSceneTimeNotify(getOwner())); - - return PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setStartSceneTime(sceneTime + 300) - .setIsStarted(true) - .setPosOffset(getPosition().toProto()) - .setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder() - .setW(1.0F) - .build()) - .setMovingPlatformType(getMovingPlatformType()) - .setIsActive(true) - .build(); - } - - @Override - public PlatformInfoOuterClass.PlatformInfo onStopRoute() { - setStarted(false); - setActive(false); - - return PlatformInfoOuterClass.PlatformInfo.newBuilder() - .setStartSceneTime(getScene().getSceneTime()) - .setStopSceneTime(getScene().getSceneTime()) - .setPosOffset(getPosition().toProto()) - .setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder() - .setW(1.0F) - .build()) - .setMovingPlatformType(getMovingPlatformType()) - .build(); - } -} +package emu.grasscutter.game.entity.platform; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.ConfigGadget; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntitySolarIsotomaClientGadget; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.*; +import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.ProtoHelper; + +public class EntitySolarIsotomaElevatorPlatform extends EntityPlatform { + public EntitySolarIsotomaElevatorPlatform( + EntitySolarIsotomaClientGadget isotoma, + Scene scene, + Player player, + int gadgetId, + Position pos, + Position rot) { + super( + isotoma, + scene, + player, + gadgetId, + pos, + rot, + MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY); + } + + @Override + protected void fillFightProps(ConfigGadget configGadget) { + if (configGadget == null || configGadget.getCombat() == null) { + return; + } + var combatData = configGadget.getCombat(); + var combatProperties = combatData.getProperty(); + + if (combatProperties.isUseCreatorProperty()) { + // If useCreatorProperty == true, use owner's property; + GameEntity ownerAvatar = getScene().getEntityById(getGadget().getOwnerEntityId()); + if (ownerAvatar != null) { + getFightProperties().putAll(ownerAvatar.getFightProperties()); + return; + } else { + Grasscutter.getLogger().warn("Why gadget owner is null?"); + } + } + + super.fillFightProps(configGadget); + } + + @Override + public SceneEntityInfoOuterClass.SceneEntityInfo toProto() { + var gadget = + SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder() + .setGadgetId(getGadgetId()) + .setOwnerEntityId(getGadget().getId()) + .setAuthorityPeerId(getOwner().getPeerId()) + .setIsEnableInteract(true) + .setAbilityGadget( + AbilityGadgetInfoOuterClass.AbilityGadgetInfo.newBuilder() + .setCampId(getGadget().getCampId()) + .setCampTargetType(getGadget().getCampType()) + .setTargetEntityId(getGadget().getId()) + .build()) + .setPlatform( + PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setStartRot( + MathQuaternionOuterClass.MathQuaternion.newBuilder().setW(1.0F).build()) + .setPosOffset(getGadget().getPosition().toProto()) + .setRotOffset( + MathQuaternionOuterClass.MathQuaternion.newBuilder().setW(1.0F).build()) + .setMovingPlatformType( + MovingPlatformTypeOuterClass.MovingPlatformType + .MOVING_PLATFORM_TYPE_ABILITY) + .build()) + .build(); + + var authority = + EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder() + .setAiInfo( + SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder() + .setIsAiOpen(true) + .setBornPos(getGadget().getPosition().toProto())) + .setBornPos(getGadget().getPosition().toProto()) + .build(); + + var info = + SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder() + .setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET) + .setEntityId(getId()) + .setMotionInfo( + MotionInfoOuterClass.MotionInfo.newBuilder() + .setPos(getGadget().getPosition().toProto()) + .setRot(getGadget().getRotation().toProto()) + .build()); + + GameEntity entity = getScene().getEntityById(getGadget().getOwnerEntityId()); + if (entity instanceof EntityAvatar avatar) { + info.addPropList( + PropPairOuterClass.PropPair.newBuilder() + .setType(PlayerProperty.PROP_LEVEL.getId()) + .setPropValue( + ProtoHelper.newPropValue( + PlayerProperty.PROP_LEVEL, avatar.getAvatar().getLevel())) + .build()); + } else { + Grasscutter.getLogger().warn("Why gadget owner doesn't exist?"); + } + + this.addAllFightPropsToEntityInfo(info); + + info.setLifeState(1).setGadget(gadget).setEntityAuthorityInfo(authority); + + return info.build(); + } + + @Override + public PlatformInfoOuterClass.PlatformInfo onStartRoute() { + setStarted(true); + setActive(true); + + var sceneTime = getScene().getSceneTime(); + getOwner().sendPacket(new PacketSceneTimeNotify(getOwner())); + + return PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setStartSceneTime(sceneTime + 300) + .setIsStarted(true) + .setPosOffset(getPosition().toProto()) + .setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder().setW(1.0F).build()) + .setMovingPlatformType(getMovingPlatformType()) + .setIsActive(true) + .build(); + } + + @Override + public PlatformInfoOuterClass.PlatformInfo onStopRoute() { + setStarted(false); + setActive(false); + + return PlatformInfoOuterClass.PlatformInfo.newBuilder() + .setStartSceneTime(getScene().getSceneTime()) + .setStopSceneTime(getScene().getSceneTime()) + .setPosOffset(getPosition().toProto()) + .setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder().setW(1.0F).build()) + .setMovingPlatformType(getMovingPlatformType()) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionInfo.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionInfo.java index 4cbeebd97..2f603d354 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionInfo.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionInfo.java @@ -1,25 +1,25 @@ -package emu.grasscutter.game.expedition; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.AvatarExpeditionInfoOuterClass.AvatarExpeditionInfo; -import lombok.Getter; -import lombok.Setter; - -@Entity -@Getter -@Setter -public class ExpeditionInfo { - private int state; - private int expId; - private int hourTime; - private int startTime; - - public AvatarExpeditionInfo toProto() { - return AvatarExpeditionInfo.newBuilder() - .setStateValue(this.getState()) - .setExpId(this.getExpId()) - .setHourTime(this.getHourTime()) - .setStartTime(this.getStartTime()) - .build(); - } -} +package emu.grasscutter.game.expedition; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.AvatarExpeditionInfoOuterClass.AvatarExpeditionInfo; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class ExpeditionInfo { + private int state; + private int expId; + private int hourTime; + private int startTime; + + public AvatarExpeditionInfo toProto() { + return AvatarExpeditionInfo.newBuilder() + .setStateValue(this.getState()) + .setExpId(this.getExpId()) + .setHourTime(this.getHourTime()) + .setStartTime(this.getStartTime()) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardData.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardData.java index e5ffa7bb9..ddf17330e 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardData.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardData.java @@ -1,18 +1,15 @@ -package emu.grasscutter.game.expedition; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.utils.Utils; -import lombok.Getter; - -public class ExpeditionRewardData { - @Getter - private int itemId; - @Getter - private int minCount; - @Getter - private int maxCount; - - public GameItem getReward() { - return new GameItem(itemId, Utils.randomRange(minCount, maxCount)); - } -} +package emu.grasscutter.game.expedition; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.utils.Utils; +import lombok.Getter; + +public class ExpeditionRewardData { + @Getter private int itemId; + @Getter private int minCount; + @Getter private int maxCount; + + public GameItem getReward() { + return new GameItem(itemId, Utils.randomRange(minCount, maxCount)); + } +} diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardDataList.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardDataList.java index 61dc5e4b1..945ec3abb 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardDataList.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardDataList.java @@ -1,22 +1,19 @@ -package emu.grasscutter.game.expedition; - -import emu.grasscutter.game.inventory.GameItem; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.List; - -public class ExpeditionRewardDataList { - @Getter - private int hourTime; - @Getter - private List expeditionRewardData; - - public List getRewards() { - List rewards = new ArrayList<>(); - if (expeditionRewardData != null) { - expeditionRewardData.forEach(data -> rewards.add(data.getReward())); - } - return rewards; - } -} +package emu.grasscutter.game.expedition; + +import emu.grasscutter.game.inventory.GameItem; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; + +public class ExpeditionRewardDataList { + @Getter private int hourTime; + @Getter private List expeditionRewardData; + + public List getRewards() { + List rewards = new ArrayList<>(); + if (expeditionRewardData != null) { + expeditionRewardData.forEach(data -> rewards.add(data.getReward())); + } + return rewards; + } +} diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardInfo.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardInfo.java index 1087a4ecb..8b83ab970 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardInfo.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionRewardInfo.java @@ -1,12 +1,9 @@ -package emu.grasscutter.game.expedition; - -import lombok.Getter; - -import java.util.List; - -public class ExpeditionRewardInfo { - @Getter - private int expId; - @Getter - private List expeditionRewardDataList; -} +package emu.grasscutter.game.expedition; + +import java.util.List; +import lombok.Getter; + +public class ExpeditionRewardInfo { + @Getter private int expId; + @Getter private List expeditionRewardDataList; +} diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java index 351b81b31..e4e144076 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionSystem.java @@ -1,41 +1,42 @@ -package emu.grasscutter.game.expedition; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.List; - -public class ExpeditionSystem extends BaseGameSystem { - private final Int2ObjectMap> expeditionRewardData; - - public ExpeditionSystem(GameServer server) { - super(server); - this.expeditionRewardData = new Int2ObjectOpenHashMap<>(); - this.load(); - } - - public Int2ObjectMap> getExpeditionRewardDataList() { - return expeditionRewardData; - } - - public synchronized void load() { - getExpeditionRewardDataList().clear(); - try { - List banners = DataLoader.loadList("ExpeditionReward.json", ExpeditionRewardInfo.class); - if (banners.size() > 0) { - for (ExpeditionRewardInfo di : banners) { - getExpeditionRewardDataList().put(di.getExpId(), di.getExpeditionRewardDataList()); - } - Grasscutter.getLogger().debug("Expedition reward successfully loaded."); - } else { - Grasscutter.getLogger().error("Unable to load expedition reward. Expedition reward size is 0."); - } - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load expedition reward.", e); - } - } -} +package emu.grasscutter.game.expedition; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.List; + +public class ExpeditionSystem extends BaseGameSystem { + private final Int2ObjectMap> expeditionRewardData; + + public ExpeditionSystem(GameServer server) { + super(server); + this.expeditionRewardData = new Int2ObjectOpenHashMap<>(); + this.load(); + } + + public Int2ObjectMap> getExpeditionRewardDataList() { + return expeditionRewardData; + } + + public synchronized void load() { + getExpeditionRewardDataList().clear(); + try { + List banners = + DataLoader.loadList("ExpeditionReward.json", ExpeditionRewardInfo.class); + if (banners.size() > 0) { + for (ExpeditionRewardInfo di : banners) { + getExpeditionRewardDataList().put(di.getExpId(), di.getExpeditionRewardDataList()); + } + Grasscutter.getLogger().debug("Expedition reward successfully loaded."); + } else { + Grasscutter.getLogger() + .error("Unable to load expedition reward. Expedition reward size is 0."); + } + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load expedition reward.", e); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/friends/FriendsList.java b/src/main/java/emu/grasscutter/game/friends/FriendsList.java index 6c04f6889..97905c467 100644 --- a/src/main/java/emu/grasscutter/game/friends/FriendsList.java +++ b/src/main/java/emu/grasscutter/game/friends/FriendsList.java @@ -1,254 +1,254 @@ -package emu.grasscutter.game.friends; - -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType; -import emu.grasscutter.server.packet.send.*; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.List; - -public class FriendsList extends BasePlayerManager { - private final Int2ObjectMap friends; - private final Int2ObjectMap pendingFriends; - - private boolean loaded = false; - - public FriendsList(Player player) { - super(player); - this.friends = new Int2ObjectOpenHashMap(); - this.pendingFriends = new Int2ObjectOpenHashMap(); - } - - public boolean hasLoaded() { - return loaded; - } - - public synchronized Int2ObjectMap getFriends() { - return friends; - } - - public synchronized Int2ObjectMap getPendingFriends() { - return this.pendingFriends; - } - - public synchronized boolean isFriendsWith(int uid) { - return this.getFriends().containsKey(uid); - } - - private synchronized Friendship getFriendshipById(int id) { - Friendship friendship = this.getFriends().get(id); - if (friendship == null) { - friendship = this.getPendingFriendById(id); - } - return friendship; - } - - private synchronized Friendship getFriendById(int id) { - return this.getFriends().get(id); - } - - private synchronized Friendship getPendingFriendById(int id) { - return this.getPendingFriends().get(id); - } - - public void addFriend(Friendship friendship) { - getFriends().put(friendship.getFriendId(), friendship); - } - - public void addPendingFriend(Friendship friendship) { - getPendingFriends().put(friendship.getFriendId(), friendship); - } - - public synchronized void handleFriendRequest(int targetUid, DealAddFriendResultType result) { - // Check if player has sent friend request - Friendship myFriendship = this.getPendingFriendById(targetUid); - if (myFriendship == null) { - return; - } - - // Make sure asker cant do anything - if (myFriendship.getAskerId() == this.getPlayer().getUid()) { - return; - } - - Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true); - if (target == null) { - return; // Should never happen - } - - // Get target's friendship - Friendship theirFriendship = null; - if (target.isOnline()) { - theirFriendship = target.getFriendsList().getPendingFriendById(this.getPlayer().getUid()); - } else { - theirFriendship = DatabaseHelper.getReverseFriendship(myFriendship); - } - - if (theirFriendship == null) { - // They dont have us on their friends list anymore, rip - this.getPendingFriends().remove(myFriendship.getOwnerId()); - myFriendship.delete(); - return; - } - - // Handle - if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT) { // Request accepted - myFriendship.setIsFriend(true); - theirFriendship.setIsFriend(true); - - this.getPendingFriends().remove(myFriendship.getOwnerId()); - this.addFriend(myFriendship); - - if (target.isOnline()) { - target.getFriendsList().getPendingFriends().remove(this.getPlayer().getUid()); - target.getFriendsList().addFriend(theirFriendship); - } - - myFriendship.save(); - theirFriendship.save(); - } else { // Request declined - // Delete from my pending friends - this.getPendingFriends().remove(myFriendship.getOwnerId()); - myFriendship.delete(); - // Delete from target uid - if (target.isOnline()) { - theirFriendship = target.getFriendsList().getPendingFriendById(this.getPlayer().getUid()); - } - theirFriendship.delete(); - } - - // Packet - this.getPlayer().sendPacket(new PacketDealAddFriendRsp(targetUid, result)); - } - - public synchronized void deleteFriend(int targetUid) { - Friendship myFriendship = this.getFriendById(targetUid); - if (myFriendship == null) { - return; - } - - this.getFriends().remove(targetUid); - myFriendship.delete(); - - Friendship theirFriendship = null; - Player friend = myFriendship.getFriendProfile().getPlayer(); - if (friend != null) { - // Friend online - theirFriendship = friend.getFriendsList().getFriendById(this.getPlayer().getUid()); - if (theirFriendship != null) { - friend.getFriendsList().getFriends().remove(theirFriendship.getFriendId()); - theirFriendship.delete(); - friend.sendPacket(new PacketDeleteFriendNotify(theirFriendship.getFriendId())); - } - } else { - // Friend offline - theirFriendship = DatabaseHelper.getReverseFriendship(myFriendship); - if (theirFriendship != null) { - theirFriendship.delete(); - } - } - - // Packet - this.getPlayer().sendPacket(new PacketDeleteFriendRsp(targetUid)); - } - - public synchronized void sendFriendRequest(int targetUid) { - Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true); - - if (target == null || target == this.getPlayer()) { - return; - } - - // Check if friend already exists - if (this.getPendingFriends().containsKey(targetUid) || this.getFriends().containsKey(targetUid)) { - return; - } - - // Create friendships - Friendship myFriendship = new Friendship(getPlayer(), target, getPlayer()); - Friendship theirFriendship = new Friendship(target, getPlayer(), getPlayer()); - - // Add pending lists - this.addPendingFriend(myFriendship); - - if (target.isOnline() && target.getFriendsList().hasLoaded()) { - target.getFriendsList().addPendingFriend(theirFriendship); - target.sendPacket(new PacketAskAddFriendNotify(theirFriendship)); - } - - // Save - myFriendship.save(); - theirFriendship.save(); - - // Packets - this.getPlayer().sendPacket(new PacketAskAddFriendRsp(targetUid)); - } - - /** - * Gets total amount of potential friends - */ - public int getFullFriendCount() { - return this.getPendingFriends().size() + this.getFriends().size(); - } - - public synchronized void loadFromDatabase() { - if (this.hasLoaded()) { - return; - } - - // Get friendships from the db - List friendships = DatabaseHelper.getFriends(player); - friendships.forEach(this::loadFriendFromDatabase); - - // Set loaded flag - this.loaded = true; - } - - private void loadFriendFromDatabase(Friendship friendship) { - // Set friendship owner - friendship.setOwner(getPlayer()); - - // Check if friend is online - Player friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid()); - if (friend != null) { - // Set friend to online mode - friendship.setFriendProfile(friend); - - // Update our status on friend's client if theyre online - if (friend.getFriendsList().hasLoaded()) { - Friendship theirFriendship = friend.getFriendsList().getFriendshipById(getPlayer().getUid()); - if (theirFriendship != null) { - // Update friend profile - theirFriendship.setFriendProfile(getPlayer()); - } else { - // They dont have us on their friends list anymore, rip - friendship.delete(); - return; - } - } - } - - // Finally, load to our friends list - if (friendship.isFriend()) { - getFriends().put(friendship.getFriendId(), friendship); - } else { - getPendingFriends().put(friendship.getFriendId(), friendship); - // TODO - Hacky fix to force client to see a notification for a friendship - if (getPendingFriends().size() == 1) { - getPlayer().getSession().send(new PacketAskAddFriendNotify(friendship)); - } - } - } - - public void save() { - // Update all our friends - List friendships = DatabaseHelper.getReverseFriends(getPlayer()); - for (Friendship friend : friendships) { - friend.setFriendProfile(this.getPlayer()); - friend.save(); - } - } -} +package emu.grasscutter.game.friends; + +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType; +import emu.grasscutter.server.packet.send.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.List; + +public class FriendsList extends BasePlayerManager { + private final Int2ObjectMap friends; + private final Int2ObjectMap pendingFriends; + + private boolean loaded = false; + + public FriendsList(Player player) { + super(player); + this.friends = new Int2ObjectOpenHashMap(); + this.pendingFriends = new Int2ObjectOpenHashMap(); + } + + public boolean hasLoaded() { + return loaded; + } + + public synchronized Int2ObjectMap getFriends() { + return friends; + } + + public synchronized Int2ObjectMap getPendingFriends() { + return this.pendingFriends; + } + + public synchronized boolean isFriendsWith(int uid) { + return this.getFriends().containsKey(uid); + } + + private synchronized Friendship getFriendshipById(int id) { + Friendship friendship = this.getFriends().get(id); + if (friendship == null) { + friendship = this.getPendingFriendById(id); + } + return friendship; + } + + private synchronized Friendship getFriendById(int id) { + return this.getFriends().get(id); + } + + private synchronized Friendship getPendingFriendById(int id) { + return this.getPendingFriends().get(id); + } + + public void addFriend(Friendship friendship) { + getFriends().put(friendship.getFriendId(), friendship); + } + + public void addPendingFriend(Friendship friendship) { + getPendingFriends().put(friendship.getFriendId(), friendship); + } + + public synchronized void handleFriendRequest(int targetUid, DealAddFriendResultType result) { + // Check if player has sent friend request + Friendship myFriendship = this.getPendingFriendById(targetUid); + if (myFriendship == null) { + return; + } + + // Make sure asker cant do anything + if (myFriendship.getAskerId() == this.getPlayer().getUid()) { + return; + } + + Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true); + if (target == null) { + return; // Should never happen + } + + // Get target's friendship + Friendship theirFriendship = null; + if (target.isOnline()) { + theirFriendship = target.getFriendsList().getPendingFriendById(this.getPlayer().getUid()); + } else { + theirFriendship = DatabaseHelper.getReverseFriendship(myFriendship); + } + + if (theirFriendship == null) { + // They dont have us on their friends list anymore, rip + this.getPendingFriends().remove(myFriendship.getOwnerId()); + myFriendship.delete(); + return; + } + + // Handle + if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT) { // Request accepted + myFriendship.setIsFriend(true); + theirFriendship.setIsFriend(true); + + this.getPendingFriends().remove(myFriendship.getOwnerId()); + this.addFriend(myFriendship); + + if (target.isOnline()) { + target.getFriendsList().getPendingFriends().remove(this.getPlayer().getUid()); + target.getFriendsList().addFriend(theirFriendship); + } + + myFriendship.save(); + theirFriendship.save(); + } else { // Request declined + // Delete from my pending friends + this.getPendingFriends().remove(myFriendship.getOwnerId()); + myFriendship.delete(); + // Delete from target uid + if (target.isOnline()) { + theirFriendship = target.getFriendsList().getPendingFriendById(this.getPlayer().getUid()); + } + theirFriendship.delete(); + } + + // Packet + this.getPlayer().sendPacket(new PacketDealAddFriendRsp(targetUid, result)); + } + + public synchronized void deleteFriend(int targetUid) { + Friendship myFriendship = this.getFriendById(targetUid); + if (myFriendship == null) { + return; + } + + this.getFriends().remove(targetUid); + myFriendship.delete(); + + Friendship theirFriendship = null; + Player friend = myFriendship.getFriendProfile().getPlayer(); + if (friend != null) { + // Friend online + theirFriendship = friend.getFriendsList().getFriendById(this.getPlayer().getUid()); + if (theirFriendship != null) { + friend.getFriendsList().getFriends().remove(theirFriendship.getFriendId()); + theirFriendship.delete(); + friend.sendPacket(new PacketDeleteFriendNotify(theirFriendship.getFriendId())); + } + } else { + // Friend offline + theirFriendship = DatabaseHelper.getReverseFriendship(myFriendship); + if (theirFriendship != null) { + theirFriendship.delete(); + } + } + + // Packet + this.getPlayer().sendPacket(new PacketDeleteFriendRsp(targetUid)); + } + + public synchronized void sendFriendRequest(int targetUid) { + Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true); + + if (target == null || target == this.getPlayer()) { + return; + } + + // Check if friend already exists + if (this.getPendingFriends().containsKey(targetUid) + || this.getFriends().containsKey(targetUid)) { + return; + } + + // Create friendships + Friendship myFriendship = new Friendship(getPlayer(), target, getPlayer()); + Friendship theirFriendship = new Friendship(target, getPlayer(), getPlayer()); + + // Add pending lists + this.addPendingFriend(myFriendship); + + if (target.isOnline() && target.getFriendsList().hasLoaded()) { + target.getFriendsList().addPendingFriend(theirFriendship); + target.sendPacket(new PacketAskAddFriendNotify(theirFriendship)); + } + + // Save + myFriendship.save(); + theirFriendship.save(); + + // Packets + this.getPlayer().sendPacket(new PacketAskAddFriendRsp(targetUid)); + } + + /** Gets total amount of potential friends */ + public int getFullFriendCount() { + return this.getPendingFriends().size() + this.getFriends().size(); + } + + public synchronized void loadFromDatabase() { + if (this.hasLoaded()) { + return; + } + + // Get friendships from the db + List friendships = DatabaseHelper.getFriends(player); + friendships.forEach(this::loadFriendFromDatabase); + + // Set loaded flag + this.loaded = true; + } + + private void loadFriendFromDatabase(Friendship friendship) { + // Set friendship owner + friendship.setOwner(getPlayer()); + + // Check if friend is online + Player friend = + getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid()); + if (friend != null) { + // Set friend to online mode + friendship.setFriendProfile(friend); + + // Update our status on friend's client if theyre online + if (friend.getFriendsList().hasLoaded()) { + Friendship theirFriendship = + friend.getFriendsList().getFriendshipById(getPlayer().getUid()); + if (theirFriendship != null) { + // Update friend profile + theirFriendship.setFriendProfile(getPlayer()); + } else { + // They dont have us on their friends list anymore, rip + friendship.delete(); + return; + } + } + } + + // Finally, load to our friends list + if (friendship.isFriend()) { + getFriends().put(friendship.getFriendId(), friendship); + } else { + getPendingFriends().put(friendship.getFriendId(), friendship); + // TODO - Hacky fix to force client to see a notification for a friendship + if (getPendingFriends().size() == 1) { + getPlayer().getSession().send(new PacketAskAddFriendNotify(friendship)); + } + } + } + + public void save() { + // Update all our friends + List friendships = DatabaseHelper.getReverseFriends(getPlayer()); + for (Friendship friend : friendships) { + friend.setFriendProfile(this.getPlayer()); + friend.save(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/friends/Friendship.java b/src/main/java/emu/grasscutter/game/friends/Friendship.java index 713c7ddf5..5507a3ddd 100644 --- a/src/main/java/emu/grasscutter/game/friends/Friendship.java +++ b/src/main/java/emu/grasscutter/game/friends/Friendship.java @@ -1,116 +1,116 @@ -package emu.grasscutter.game.friends; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Indexed; -import dev.morphia.annotations.Transient; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief; -import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState; -import emu.grasscutter.net.proto.PlatformTypeOuterClass; -import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; -import org.bson.types.ObjectId; - -@Entity(value = "friendships", useDiscriminator = false) -public class Friendship { - @Id - private ObjectId id; - - @Transient - private Player owner; - - @Indexed - private int ownerId; - @Indexed - private int friendId; - private boolean isFriend; - private int askerId; - - private PlayerProfile profile; - - @Deprecated // Morphia use only - public Friendship() { - } - - public Friendship(Player owner, Player friend, Player asker) { - this.setOwner(owner); - this.ownerId = owner.getUid(); - this.friendId = friend.getUid(); - this.profile = friend.getProfile(); - this.askerId = asker.getUid(); - } - - public Player getOwner() { - return owner; - } - - public void setOwner(Player owner) { - this.owner = owner; - } - - public boolean isFriend() { - return isFriend; - } - - public void setIsFriend(boolean b) { - this.isFriend = b; - } - - public int getOwnerId() { - return ownerId; - } - - public int getFriendId() { - return friendId; - } - - public int getAskerId() { - return askerId; - } - - public void setAskerId(int askerId) { - this.askerId = askerId; - } - - public PlayerProfile getFriendProfile() { - return profile; - } - - public void setFriendProfile(Player character) { - if (character == null || this.friendId != character.getUid()) return; - this.profile = character.getProfile(); - } - - public boolean isOnline() { - return getFriendProfile().getPlayer() != null; - } - - public void save() { - DatabaseHelper.saveFriendship(this); - } - - public void delete() { - DatabaseHelper.deleteFriendship(this); - } - - public FriendBrief toProto() { - FriendBrief proto = FriendBrief.newBuilder() - .setUid(getFriendProfile().getUid()) - .setNickname(getFriendProfile().getName()) - .setLevel(getFriendProfile().getPlayerLevel()) - .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId())) - .setWorldLevel(getFriendProfile().getWorldLevel()) - .setSignature(getFriendProfile().getSignature()) - .setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE : FriendOnlineState.FRIEND_ONLINE_STATE_DISCONNECT) - .setIsMpModeAvailable(true) - .setLastActiveTime(getFriendProfile().getLastActiveTime()) - .setNameCardId(getFriendProfile().getNameCard()) - .setParam(getFriendProfile().getDaysSinceLogin()) - .setIsGameSource(true) - .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) - .build(); - - return proto; - } -} +package emu.grasscutter.game.friends; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.Transient; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief; +import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState; +import emu.grasscutter.net.proto.PlatformTypeOuterClass; +import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; +import org.bson.types.ObjectId; + +@Entity(value = "friendships", useDiscriminator = false) +public class Friendship { + @Id private ObjectId id; + + @Transient private Player owner; + + @Indexed private int ownerId; + @Indexed private int friendId; + private boolean isFriend; + private int askerId; + + private PlayerProfile profile; + + @Deprecated // Morphia use only + public Friendship() {} + + public Friendship(Player owner, Player friend, Player asker) { + this.setOwner(owner); + this.ownerId = owner.getUid(); + this.friendId = friend.getUid(); + this.profile = friend.getProfile(); + this.askerId = asker.getUid(); + } + + public Player getOwner() { + return owner; + } + + public void setOwner(Player owner) { + this.owner = owner; + } + + public boolean isFriend() { + return isFriend; + } + + public void setIsFriend(boolean b) { + this.isFriend = b; + } + + public int getOwnerId() { + return ownerId; + } + + public int getFriendId() { + return friendId; + } + + public int getAskerId() { + return askerId; + } + + public void setAskerId(int askerId) { + this.askerId = askerId; + } + + public PlayerProfile getFriendProfile() { + return profile; + } + + public void setFriendProfile(Player character) { + if (character == null || this.friendId != character.getUid()) return; + this.profile = character.getProfile(); + } + + public boolean isOnline() { + return getFriendProfile().getPlayer() != null; + } + + public void save() { + DatabaseHelper.saveFriendship(this); + } + + public void delete() { + DatabaseHelper.deleteFriendship(this); + } + + public FriendBrief toProto() { + FriendBrief proto = + FriendBrief.newBuilder() + .setUid(getFriendProfile().getUid()) + .setNickname(getFriendProfile().getName()) + .setLevel(getFriendProfile().getPlayerLevel()) + .setProfilePicture( + ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId())) + .setWorldLevel(getFriendProfile().getWorldLevel()) + .setSignature(getFriendProfile().getSignature()) + .setOnlineState( + getFriendProfile().isOnline() + ? FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE + : FriendOnlineState.FRIEND_ONLINE_STATE_DISCONNECT) + .setIsMpModeAvailable(true) + .setLastActiveTime(getFriendProfile().getLastActiveTime()) + .setNameCardId(getFriendProfile().getNameCard()) + .setParam(getFriendProfile().getDaysSinceLogin()) + .setIsGameSource(true) + .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) + .build(); + + return proto; + } +} diff --git a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java index 120a8f9e7..44acc40d0 100644 --- a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java +++ b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java @@ -1,106 +1,105 @@ -package emu.grasscutter.game.friends; - -import dev.morphia.annotations.AlsoLoad; -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.utils.Utils; - -@Entity -public class PlayerProfile { - @Transient - private Player player; - - @AlsoLoad("id") - private int uid; - private int nameCard; - private int avatarId; - private String name; - private String signature; - private int achievements; - - private int playerLevel; - private int worldLevel; - private int lastActiveTime; - - @Deprecated // Morphia only - public PlayerProfile() { - } - - public PlayerProfile(Player player) { - this.uid = player.getUid(); - this.syncWithCharacter(player); - } - - public int getUid() { - return uid; - } - - public Player getPlayer() { - return player; - } - - public synchronized void setPlayer(Player player) { - this.player = player; - } - - public String getName() { - return name; - } - - public int getNameCard() { - return nameCard; - } - - public int getAvatarId() { - return avatarId; - } - - public String getSignature() { - return signature; - } - - public int getAchievements() { - return achievements; - } - - public int getPlayerLevel() { - return playerLevel; - } - - public int getWorldLevel() { - return worldLevel; - } - - public int getLastActiveTime() { - return lastActiveTime; - } - - public void updateLastActiveTime() { - this.lastActiveTime = Utils.getCurrentSeconds(); - } - - public int getDaysSinceLogin() { - return (int) Math.floor((Utils.getCurrentSeconds() - getLastActiveTime()) / 86400.0); - } - - public boolean isOnline() { - return this.getPlayer() != null; - } - - public void syncWithCharacter(Player player) { - if (player == null) { - return; - } - - this.uid = player.getUid(); - this.name = player.getNickname(); - this.avatarId = player.getHeadImage(); - this.signature = player.getSignature(); - this.nameCard = player.getNameCardId(); - this.playerLevel = player.getLevel(); - this.worldLevel = player.getWorldLevel(); - //this.achievements = 0; - this.updateLastActiveTime(); - } -} +package emu.grasscutter.game.friends; + +import dev.morphia.annotations.AlsoLoad; +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.utils.Utils; + +@Entity +public class PlayerProfile { + @Transient private Player player; + + @AlsoLoad("id") + private int uid; + + private int nameCard; + private int avatarId; + private String name; + private String signature; + private int achievements; + + private int playerLevel; + private int worldLevel; + private int lastActiveTime; + + @Deprecated // Morphia only + public PlayerProfile() {} + + public PlayerProfile(Player player) { + this.uid = player.getUid(); + this.syncWithCharacter(player); + } + + public int getUid() { + return uid; + } + + public Player getPlayer() { + return player; + } + + public synchronized void setPlayer(Player player) { + this.player = player; + } + + public String getName() { + return name; + } + + public int getNameCard() { + return nameCard; + } + + public int getAvatarId() { + return avatarId; + } + + public String getSignature() { + return signature; + } + + public int getAchievements() { + return achievements; + } + + public int getPlayerLevel() { + return playerLevel; + } + + public int getWorldLevel() { + return worldLevel; + } + + public int getLastActiveTime() { + return lastActiveTime; + } + + public void updateLastActiveTime() { + this.lastActiveTime = Utils.getCurrentSeconds(); + } + + public int getDaysSinceLogin() { + return (int) Math.floor((Utils.getCurrentSeconds() - getLastActiveTime()) / 86400.0); + } + + public boolean isOnline() { + return this.getPlayer() != null; + } + + public void syncWithCharacter(Player player) { + if (player == null) { + return; + } + + this.uid = player.getUid(); + this.name = player.getNickname(); + this.avatarId = player.getHeadImage(); + this.signature = player.getSignature(); + this.nameCard = player.getNameCardId(); + this.playerLevel = player.getLevel(); + this.worldLevel = player.getWorldLevel(); + // this.achievements = 0; + this.updateLastActiveTime(); + } +} diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java index 512543428..24e2f49db 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java @@ -1,292 +1,352 @@ -package emu.grasscutter.game.gacha; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.GachaInfoOuterClass.GachaInfo; -import emu.grasscutter.net.proto.GachaUpInfoOuterClass.GachaUpInfo; -import emu.grasscutter.utils.Utils; -import lombok.Getter; - -import static emu.grasscutter.config.Configuration.*; - -public class GachaBanner { - // Constants used by the BannerType enum - static final int[][] DEFAULT_WEIGHTS_4 = {{1, 510}, {8, 510}, {10, 10000}}; - static final int[][] DEFAULT_WEIGHTS_4_WEAPON = {{1, 600}, {7, 600}, {8, 6600}, {10, 12600}}; - static final int[][] DEFAULT_WEIGHTS_5 = {{1, 75}, {73, 150}, {90, 10000}}; - static final int[][] DEFAULT_WEIGHTS_5_CHARACTER = {{1, 80}, {73, 80}, {90, 10000}}; - static final int[][] DEFAULT_WEIGHTS_5_WEAPON = {{1, 100}, {62, 100}, {73, 7800}, {80, 10000}}; - static final int[] DEFAULT_FALLBACK_ITEMS_4_POOL_1 = {1014, 1020, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1059, 1064, 1065, 1067, 1068, 1072}; // Default avatars - static final int[] DEFAULT_FALLBACK_ITEMS_4_POOL_2 = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405}; // Default weapons - static final int[] DEFAULT_FALLBACK_ITEMS_5_POOL_1 = {1003, 1016, 1042, 1035, 1041, 1069}; // Default avatars - static final int[] DEFAULT_FALLBACK_ITEMS_5_POOL_2 = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; // Default weapons - static final int[] EMPTY_POOL = {}; // Used to remove a type of fallback - @Getter - int scheduleId = -1; - @Getter - int sortId = -1; - @Getter - private int gachaType = -1; - @Getter - private String prefabPath; - @Getter - private String previewPrefabPath; - @Getter - private String titlePath; - private int costItemId = 0; - private final int costItemAmount = 1; - private int costItemId10 = 0; - private final int costItemAmount10 = 10; - @Getter - private final int beginTime = 0; - @Getter - private final int endTime = 1924992000; - @Getter - private final int gachaTimesLimit = Integer.MAX_VALUE; - @Getter - private final int[] rateUpItems4 = {}; - @Getter - private final int[] rateUpItems5 = {}; - // This now handles default values for the fields below - @Getter - private final BannerType bannerType = BannerType.STANDARD; - // These don't change between banner types (apart from Standard having three extra 4star avatars) - @Getter - private final int[] fallbackItems3 = {11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304}; - @Getter - private final int[] fallbackItems4Pool1 = DEFAULT_FALLBACK_ITEMS_4_POOL_1; - @Getter - private final int[] fallbackItems4Pool2 = DEFAULT_FALLBACK_ITEMS_4_POOL_2; - // Different banner types have different defaults, see above for default values and the enum for which are used where. - @Getter - private int[] fallbackItems5Pool1; - @Getter - private int[] fallbackItems5Pool2; - private int[][] weights4; - private int[][] weights5; - private int eventChance4 = -1; // Chance to win a featured event item - private int eventChance5 = -1; // Chance to win a featured event item - // - @Getter - private final boolean removeC6FromPool = false; - @Getter - private final boolean autoStripRateUpFromFallback = true; // Ensures that featured items won't "double dip" into the losing pool - private final int[][] poolBalanceWeights4 = {{1, 255}, {17, 255}, {21, 10455}}; // Used to ensure that players won't go too many rolls without getting something from pool 1 (avatar) or pool 2 (weapon) - private final int[][] poolBalanceWeights5 = {{1, 30}, {147, 150}, {181, 10230}}; - @Getter - private final int wishMaxProgress = 2; - - // Deprecated fields that were tolerated in early May 2022 but have apparently still being circulating in new custom configs - // For now, throw up big scary errors on load telling people that they will be banned outright in a future version - @Deprecated - private final int[] rateUpItems1 = {}; - @Deprecated - private final int[] rateUpItems2 = {}; - @Deprecated - private final int eventChance = -1; - @Deprecated - private final int costItem = 0; - @Deprecated - private final int softPity = -1; - @Deprecated - private final int hardPity = -1; - @Deprecated - private final int minItemType = -1; - @Deprecated - private final int maxItemType = -1; - @Getter - private boolean deprecated = false; - @Getter - private final boolean disabled = false; - - private void warnDeprecated(String name, String replacement) { - Grasscutter.getLogger().error("Deprecated field found in Banners config: " + name + " was replaced back in early May 2022, use " + replacement + " instead. You MUST remove this field from your config."); - this.deprecated = true; - } - - public void onLoad() { - // Handle deprecated configs - if (eventChance != -1) - warnDeprecated("eventChance", "eventChance4 & eventChance5"); - if (costItem != 0) - warnDeprecated("costItem", "costItemId"); - if (softPity != -1) - warnDeprecated("softPity", "weights5"); - if (hardPity != -1) - warnDeprecated("hardPity", "weights5"); - if (minItemType != -1) - warnDeprecated("minItemType", "fallbackItems[4,5]Pool[1,2]"); - if (maxItemType != -1) - warnDeprecated("maxItemType", "fallbackItems[4,5]Pool[1,2]"); - if (rateUpItems1.length > 0) - warnDeprecated("rateUpItems1", "rateUpItems5"); - if (rateUpItems2.length > 0) - warnDeprecated("rateUpItems2", "rateUpItems4"); - - // Handle default values - if (this.previewPrefabPath != null && this.previewPrefabPath.equals("UI_Tab_" + this.prefabPath)) - Grasscutter.getLogger().error("Redundant field found in Banners config: previewPrefabPath does not need to be specified if it is identical to prefabPath prefixed with \"UI_Tab_\"."); - if (this.previewPrefabPath == null || this.previewPrefabPath.isEmpty()) - this.previewPrefabPath = "UI_Tab_" + this.prefabPath; - if (this.gachaType < 0) - this.gachaType = this.bannerType.gachaType; - if (this.costItemId == 0) - this.costItemId = this.bannerType.costItemId; - if (this.costItemId10 == 0) - this.costItemId10 = this.costItemId; - if (this.weights4 == null) - this.weights4 = this.bannerType.weights4; - if (this.weights5 == null) - this.weights5 = this.bannerType.weights5; - if (this.eventChance4 < 0) - this.eventChance4 = this.bannerType.eventChance4; - if (this.eventChance5 < 0) - this.eventChance5 = this.bannerType.eventChance5; - if (this.fallbackItems5Pool1 == null) - this.fallbackItems5Pool1 = this.bannerType.fallbackItems5Pool1; - if (this.fallbackItems5Pool2 == null) - this.fallbackItems5Pool2 = this.bannerType.fallbackItems5Pool2; - } - - public ItemParamData getCost(int numRolls) { - return switch (numRolls) { - case 10 -> new ItemParamData(costItemId10, costItemAmount10); - default -> new ItemParamData(costItemId, costItemAmount * numRolls); - }; - } - - @Deprecated - public int getCostItem() { - return costItemId; - } - - public boolean hasEpitomized() { - return bannerType.equals(BannerType.WEAPON); - } - - public int getWeight(int rarity, int pity) { - return switch (rarity) { - case 4 -> Utils.lerp(pity, weights4); - default -> Utils.lerp(pity, weights5); - }; - } - - public int getPoolBalanceWeight(int rarity, int pity) { - return switch (rarity) { - case 4 -> Utils.lerp(pity, poolBalanceWeights4); - default -> Utils.lerp(pity, poolBalanceWeights5); - }; - } - - public int getEventChance(int rarity) { - return switch (rarity) { - case 4 -> eventChance4; - default -> eventChance5; - }; - } - - public GachaInfo toProto(Player player) { - // TODO: use other Nonce/key insteadof session key to ensure the overall security for the player - String sessionKey = player.getAccount().getSessionKey(); - - String record = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" - + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" - + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) - + "/gacha?s=" + sessionKey + "&gachaType=" + gachaType; - String details = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" - + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" - + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) - + "/gacha/details?s=" + sessionKey + "&scheduleId=" + scheduleId; - - // Grasscutter.getLogger().info("record = " + record); - PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(this); - int leftGachaTimes = switch (gachaTimesLimit) { - case Integer.MAX_VALUE -> Integer.MAX_VALUE; - default -> Math.max(gachaTimesLimit - gachaInfo.getTotalPulls(), 0); - }; - GachaInfo.Builder info = GachaInfo.newBuilder() - .setGachaType(this.getGachaType()) - .setScheduleId(this.getScheduleId()) - .setBeginTime(this.getBeginTime()) - .setEndTime(this.getEndTime()) - .setCostItemId(this.costItemId) - .setCostItemNum(this.costItemAmount) - .setTenCostItemId(this.costItemId10) - .setTenCostItemNum(this.costItemAmount10) - .setGachaPrefabPath(this.getPrefabPath()) - .setGachaPreviewPrefabPath(this.getPreviewPrefabPath()) - .setGachaProbUrl(details) - .setGachaProbUrlOversea(details) - .setGachaRecordUrl(record) - .setGachaRecordUrlOversea(record) - .setLeftGachaTimes(leftGachaTimes) - .setGachaTimesLimit(gachaTimesLimit) - .setGachaSortId(this.getSortId()); - - if (hasEpitomized()) { - info.setWishItemId(gachaInfo.getWishItemId()) - .setWishProgress(gachaInfo.getFailedChosenItemPulls()) - .setWishMaxProgress(this.getWishMaxProgress()); - } - - if (this.getTitlePath() != null) { - info.setTitleTextmap(this.getTitlePath()); - } - - if (this.getRateUpItems5().length > 0) { - GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(1); - - for (int id : getRateUpItems5()) { - upInfo.addItemIdList(id); - info.addDisplayUp5ItemList(id); - } - - info.addGachaUpInfoList(upInfo); - } - - if (this.getRateUpItems4().length > 0) { - GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(2); - - for (int id : getRateUpItems4()) { - upInfo.addItemIdList(id); - if (info.getDisplayUp4ItemListCount() == 0) { - info.addDisplayUp4ItemList(id); - } - } - - info.addGachaUpInfoList(upInfo); - } - - return info.build(); - } - - public enum BannerType { - STANDARD(200, 224, DEFAULT_WEIGHTS_4, DEFAULT_WEIGHTS_5, 50, 50, DEFAULT_FALLBACK_ITEMS_5_POOL_1, DEFAULT_FALLBACK_ITEMS_5_POOL_2), - BEGINNER(100, 224, DEFAULT_WEIGHTS_4, DEFAULT_WEIGHTS_5, 50, 50, DEFAULT_FALLBACK_ITEMS_5_POOL_1, DEFAULT_FALLBACK_ITEMS_5_POOL_2), - EVENT(301, 223, DEFAULT_WEIGHTS_4, DEFAULT_WEIGHTS_5_CHARACTER, 50, 50, DEFAULT_FALLBACK_ITEMS_5_POOL_1, DEFAULT_FALLBACK_ITEMS_5_POOL_2), // Legacy value for CHARACTER - CHARACTER(301, 223, DEFAULT_WEIGHTS_4, DEFAULT_WEIGHTS_5_CHARACTER, 50, 50, DEFAULT_FALLBACK_ITEMS_5_POOL_1, EMPTY_POOL), - CHARACTER2(400, 223, DEFAULT_WEIGHTS_4, DEFAULT_WEIGHTS_5_CHARACTER, 50, 50, DEFAULT_FALLBACK_ITEMS_5_POOL_1, EMPTY_POOL), - WEAPON(302, 223, DEFAULT_WEIGHTS_4_WEAPON, DEFAULT_WEIGHTS_5_WEAPON, 75, 75, EMPTY_POOL, DEFAULT_FALLBACK_ITEMS_5_POOL_2); - - public final int gachaType; - public final int costItemId; - public final int[][] weights4; - public final int[][] weights5; - public final int eventChance4; - public final int eventChance5; - public final int[] fallbackItems5Pool1; - public final int[] fallbackItems5Pool2; - - BannerType(int gachaType, int costItemId, int[][] weights4, int[][] weights5, int eventChance4, int eventChance5, int[] fallbackItems5Pool1, int[] fallbackItems5Pool2) { - this.gachaType = gachaType; - this.costItemId = costItemId; - this.weights4 = weights4; - this.weights5 = weights5; - this.eventChance4 = eventChance4; - this.eventChance5 = eventChance5; - this.fallbackItems5Pool1 = fallbackItems5Pool1; - this.fallbackItems5Pool2 = fallbackItems5Pool2; - } - } -} +package emu.grasscutter.game.gacha; + +import static emu.grasscutter.config.Configuration.*; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.GachaInfoOuterClass.GachaInfo; +import emu.grasscutter.net.proto.GachaUpInfoOuterClass.GachaUpInfo; +import emu.grasscutter.utils.Utils; +import lombok.Getter; + +public class GachaBanner { + // Constants used by the BannerType enum + static final int[][] DEFAULT_WEIGHTS_4 = {{1, 510}, {8, 510}, {10, 10000}}; + static final int[][] DEFAULT_WEIGHTS_4_WEAPON = {{1, 600}, {7, 600}, {8, 6600}, {10, 12600}}; + static final int[][] DEFAULT_WEIGHTS_5 = {{1, 75}, {73, 150}, {90, 10000}}; + static final int[][] DEFAULT_WEIGHTS_5_CHARACTER = {{1, 80}, {73, 80}, {90, 10000}}; + static final int[][] DEFAULT_WEIGHTS_5_WEAPON = {{1, 100}, {62, 100}, {73, 7800}, {80, 10000}}; + static final int[] DEFAULT_FALLBACK_ITEMS_4_POOL_1 = { + 1014, 1020, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, + 1055, 1056, 1059, 1064, 1065, 1067, 1068, 1072 + }; // Default avatars + static final int[] DEFAULT_FALLBACK_ITEMS_4_POOL_2 = { + 11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, + 14409, 15401, 15402, 15403, 15405 + }; // Default weapons + static final int[] DEFAULT_FALLBACK_ITEMS_5_POOL_1 = { + 1003, 1016, 1042, 1035, 1041, 1069 + }; // Default avatars + static final int[] DEFAULT_FALLBACK_ITEMS_5_POOL_2 = { + 11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502 + }; // Default weapons + static final int[] EMPTY_POOL = {}; // Used to remove a type of fallback + @Getter int scheduleId = -1; + @Getter int sortId = -1; + @Getter private int gachaType = -1; + @Getter private String prefabPath; + @Getter private String previewPrefabPath; + @Getter private String titlePath; + private int costItemId = 0; + private final int costItemAmount = 1; + private int costItemId10 = 0; + private final int costItemAmount10 = 10; + @Getter private final int beginTime = 0; + @Getter private final int endTime = 1924992000; + @Getter private final int gachaTimesLimit = Integer.MAX_VALUE; + @Getter private final int[] rateUpItems4 = {}; + @Getter private final int[] rateUpItems5 = {}; + // This now handles default values for the fields below + @Getter private final BannerType bannerType = BannerType.STANDARD; + // These don't change between banner types (apart from Standard having three extra 4star avatars) + @Getter + private final int[] fallbackItems3 = { + 11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304 + }; + + @Getter private final int[] fallbackItems4Pool1 = DEFAULT_FALLBACK_ITEMS_4_POOL_1; + @Getter private final int[] fallbackItems4Pool2 = DEFAULT_FALLBACK_ITEMS_4_POOL_2; + // Different banner types have different defaults, see above for default values and the enum for + // which are used where. + @Getter private int[] fallbackItems5Pool1; + @Getter private int[] fallbackItems5Pool2; + private int[][] weights4; + private int[][] weights5; + private int eventChance4 = -1; // Chance to win a featured event item + private int eventChance5 = -1; // Chance to win a featured event item + // + @Getter private final boolean removeC6FromPool = false; + + @Getter + private final boolean autoStripRateUpFromFallback = + true; // Ensures that featured items won't "double dip" into the losing pool + + private final int[][] poolBalanceWeights4 = { + {1, 255}, {17, 255}, {21, 10455} + }; // Used to ensure that players won't go too many rolls without getting something from pool 1 + // (avatar) or pool 2 (weapon) + private final int[][] poolBalanceWeights5 = {{1, 30}, {147, 150}, {181, 10230}}; + @Getter private final int wishMaxProgress = 2; + + // Deprecated fields that were tolerated in early May 2022 but have apparently still being + // circulating in new custom configs + // For now, throw up big scary errors on load telling people that they will be banned outright in + // a future version + @Deprecated private final int[] rateUpItems1 = {}; + @Deprecated private final int[] rateUpItems2 = {}; + @Deprecated private final int eventChance = -1; + @Deprecated private final int costItem = 0; + @Deprecated private final int softPity = -1; + @Deprecated private final int hardPity = -1; + @Deprecated private final int minItemType = -1; + @Deprecated private final int maxItemType = -1; + @Getter private boolean deprecated = false; + @Getter private final boolean disabled = false; + + private void warnDeprecated(String name, String replacement) { + Grasscutter.getLogger() + .error( + "Deprecated field found in Banners config: " + + name + + " was replaced back in early May 2022, use " + + replacement + + " instead. You MUST remove this field from your config."); + this.deprecated = true; + } + + public void onLoad() { + // Handle deprecated configs + if (eventChance != -1) warnDeprecated("eventChance", "eventChance4 & eventChance5"); + if (costItem != 0) warnDeprecated("costItem", "costItemId"); + if (softPity != -1) warnDeprecated("softPity", "weights5"); + if (hardPity != -1) warnDeprecated("hardPity", "weights5"); + if (minItemType != -1) warnDeprecated("minItemType", "fallbackItems[4,5]Pool[1,2]"); + if (maxItemType != -1) warnDeprecated("maxItemType", "fallbackItems[4,5]Pool[1,2]"); + if (rateUpItems1.length > 0) warnDeprecated("rateUpItems1", "rateUpItems5"); + if (rateUpItems2.length > 0) warnDeprecated("rateUpItems2", "rateUpItems4"); + + // Handle default values + if (this.previewPrefabPath != null + && this.previewPrefabPath.equals("UI_Tab_" + this.prefabPath)) + Grasscutter.getLogger() + .error( + "Redundant field found in Banners config: previewPrefabPath does not need to be specified if it is identical to prefabPath prefixed with \"UI_Tab_\"."); + if (this.previewPrefabPath == null || this.previewPrefabPath.isEmpty()) + this.previewPrefabPath = "UI_Tab_" + this.prefabPath; + if (this.gachaType < 0) this.gachaType = this.bannerType.gachaType; + if (this.costItemId == 0) this.costItemId = this.bannerType.costItemId; + if (this.costItemId10 == 0) this.costItemId10 = this.costItemId; + if (this.weights4 == null) this.weights4 = this.bannerType.weights4; + if (this.weights5 == null) this.weights5 = this.bannerType.weights5; + if (this.eventChance4 < 0) this.eventChance4 = this.bannerType.eventChance4; + if (this.eventChance5 < 0) this.eventChance5 = this.bannerType.eventChance5; + if (this.fallbackItems5Pool1 == null) + this.fallbackItems5Pool1 = this.bannerType.fallbackItems5Pool1; + if (this.fallbackItems5Pool2 == null) + this.fallbackItems5Pool2 = this.bannerType.fallbackItems5Pool2; + } + + public ItemParamData getCost(int numRolls) { + return switch (numRolls) { + case 10 -> new ItemParamData(costItemId10, costItemAmount10); + default -> new ItemParamData(costItemId, costItemAmount * numRolls); + }; + } + + @Deprecated + public int getCostItem() { + return costItemId; + } + + public boolean hasEpitomized() { + return bannerType.equals(BannerType.WEAPON); + } + + public int getWeight(int rarity, int pity) { + return switch (rarity) { + case 4 -> Utils.lerp(pity, weights4); + default -> Utils.lerp(pity, weights5); + }; + } + + public int getPoolBalanceWeight(int rarity, int pity) { + return switch (rarity) { + case 4 -> Utils.lerp(pity, poolBalanceWeights4); + default -> Utils.lerp(pity, poolBalanceWeights5); + }; + } + + public int getEventChance(int rarity) { + return switch (rarity) { + case 4 -> eventChance4; + default -> eventChance5; + }; + } + + public GachaInfo toProto(Player player) { + // TODO: use other Nonce/key insteadof session key to ensure the overall security for the player + String sessionKey = player.getAccount().getSessionKey(); + + String record = + "http" + + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) + + "/gacha?s=" + + sessionKey + + "&gachaType=" + + gachaType; + String details = + "http" + + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) + + "/gacha/details?s=" + + sessionKey + + "&scheduleId=" + + scheduleId; + + // Grasscutter.getLogger().info("record = " + record); + PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(this); + int leftGachaTimes = + switch (gachaTimesLimit) { + case Integer.MAX_VALUE -> Integer.MAX_VALUE; + default -> Math.max(gachaTimesLimit - gachaInfo.getTotalPulls(), 0); + }; + GachaInfo.Builder info = + GachaInfo.newBuilder() + .setGachaType(this.getGachaType()) + .setScheduleId(this.getScheduleId()) + .setBeginTime(this.getBeginTime()) + .setEndTime(this.getEndTime()) + .setCostItemId(this.costItemId) + .setCostItemNum(this.costItemAmount) + .setTenCostItemId(this.costItemId10) + .setTenCostItemNum(this.costItemAmount10) + .setGachaPrefabPath(this.getPrefabPath()) + .setGachaPreviewPrefabPath(this.getPreviewPrefabPath()) + .setGachaProbUrl(details) + .setGachaProbUrlOversea(details) + .setGachaRecordUrl(record) + .setGachaRecordUrlOversea(record) + .setLeftGachaTimes(leftGachaTimes) + .setGachaTimesLimit(gachaTimesLimit) + .setGachaSortId(this.getSortId()); + + if (hasEpitomized()) { + info.setWishItemId(gachaInfo.getWishItemId()) + .setWishProgress(gachaInfo.getFailedChosenItemPulls()) + .setWishMaxProgress(this.getWishMaxProgress()); + } + + if (this.getTitlePath() != null) { + info.setTitleTextmap(this.getTitlePath()); + } + + if (this.getRateUpItems5().length > 0) { + GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(1); + + for (int id : getRateUpItems5()) { + upInfo.addItemIdList(id); + info.addDisplayUp5ItemList(id); + } + + info.addGachaUpInfoList(upInfo); + } + + if (this.getRateUpItems4().length > 0) { + GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(2); + + for (int id : getRateUpItems4()) { + upInfo.addItemIdList(id); + if (info.getDisplayUp4ItemListCount() == 0) { + info.addDisplayUp4ItemList(id); + } + } + + info.addGachaUpInfoList(upInfo); + } + + return info.build(); + } + + public enum BannerType { + STANDARD( + 200, + 224, + DEFAULT_WEIGHTS_4, + DEFAULT_WEIGHTS_5, + 50, + 50, + DEFAULT_FALLBACK_ITEMS_5_POOL_1, + DEFAULT_FALLBACK_ITEMS_5_POOL_2), + BEGINNER( + 100, + 224, + DEFAULT_WEIGHTS_4, + DEFAULT_WEIGHTS_5, + 50, + 50, + DEFAULT_FALLBACK_ITEMS_5_POOL_1, + DEFAULT_FALLBACK_ITEMS_5_POOL_2), + EVENT( + 301, + 223, + DEFAULT_WEIGHTS_4, + DEFAULT_WEIGHTS_5_CHARACTER, + 50, + 50, + DEFAULT_FALLBACK_ITEMS_5_POOL_1, + DEFAULT_FALLBACK_ITEMS_5_POOL_2), // Legacy value for CHARACTER + CHARACTER( + 301, + 223, + DEFAULT_WEIGHTS_4, + DEFAULT_WEIGHTS_5_CHARACTER, + 50, + 50, + DEFAULT_FALLBACK_ITEMS_5_POOL_1, + EMPTY_POOL), + CHARACTER2( + 400, + 223, + DEFAULT_WEIGHTS_4, + DEFAULT_WEIGHTS_5_CHARACTER, + 50, + 50, + DEFAULT_FALLBACK_ITEMS_5_POOL_1, + EMPTY_POOL), + WEAPON( + 302, + 223, + DEFAULT_WEIGHTS_4_WEAPON, + DEFAULT_WEIGHTS_5_WEAPON, + 75, + 75, + EMPTY_POOL, + DEFAULT_FALLBACK_ITEMS_5_POOL_2); + + public final int gachaType; + public final int costItemId; + public final int[][] weights4; + public final int[][] weights5; + public final int eventChance4; + public final int eventChance5; + public final int[] fallbackItems5Pool1; + public final int[] fallbackItems5Pool2; + + BannerType( + int gachaType, + int costItemId, + int[][] weights4, + int[][] weights5, + int eventChance4, + int eventChance5, + int[] fallbackItems5Pool1, + int[] fallbackItems5Pool2) { + this.gachaType = gachaType; + this.costItemId = costItemId; + this.weights4 = weights4; + this.weights5 = weights5; + this.eventChance4 = eventChance4; + this.eventChance5 = eventChance5; + this.fallbackItems5Pool1 = fallbackItems5Pool1; + this.fallbackItems5Pool2 = fallbackItems5Pool2; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaRecord.java b/src/main/java/emu/grasscutter/game/gacha/GachaRecord.java index ceda9cde2..571b22b1f 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaRecord.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaRecord.java @@ -1,81 +1,75 @@ -package emu.grasscutter.game.gacha; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Indexed; -import org.bson.types.ObjectId; - -import java.util.Date; - -@Entity(value = "gachas", useDiscriminator = false) -public class GachaRecord { - @Id - private ObjectId id; - - @Indexed - private int ownerId; - - private Date transactionDate; - private int itemID; - @Indexed - private int gachaType; - - public GachaRecord() { - } - - public GachaRecord(int itemId, int ownerId, int gachaType) { - this.transactionDate = new Date(); - this.itemID = itemId; - this.ownerId = ownerId; - this.gachaType = gachaType; - } - - public int getOwnerId() { - return ownerId; - } - - public void setOwnerId(int ownerId) { - this.ownerId = ownerId; - } - - public int getGachaType() { - return gachaType; - } - - public void setGachaType(int type) { - this.gachaType = type; - } - - public Date getTransactionDate() { - return transactionDate; - } - - public void setTransactionDate(Date transactionDate) { - this.transactionDate = transactionDate; - } - - public int getItemID() { - return itemID; - } - - public void setItemID(int itemID) { - this.itemID = itemID; - } - - public ObjectId getId() { - return id; - } - - public void setId(ObjectId id) { - this.id = id; - } - - public String toString() { - return toJsonString(); - } - - public String toJsonString() { - return "{\"time\": " + this.transactionDate.getTime() + ",\"item\":" + this.itemID + "}"; - } - -} +package emu.grasscutter.game.gacha; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import java.util.Date; +import org.bson.types.ObjectId; + +@Entity(value = "gachas", useDiscriminator = false) +public class GachaRecord { + @Id private ObjectId id; + + @Indexed private int ownerId; + + private Date transactionDate; + private int itemID; + @Indexed private int gachaType; + + public GachaRecord() {} + + public GachaRecord(int itemId, int ownerId, int gachaType) { + this.transactionDate = new Date(); + this.itemID = itemId; + this.ownerId = ownerId; + this.gachaType = gachaType; + } + + public int getOwnerId() { + return ownerId; + } + + public void setOwnerId(int ownerId) { + this.ownerId = ownerId; + } + + public int getGachaType() { + return gachaType; + } + + public void setGachaType(int type) { + this.gachaType = type; + } + + public Date getTransactionDate() { + return transactionDate; + } + + public void setTransactionDate(Date transactionDate) { + this.transactionDate = transactionDate; + } + + public int getItemID() { + return itemID; + } + + public void setItemID(int itemID) { + this.itemID = itemID; + } + + public ObjectId getId() { + return id; + } + + public void setId(ObjectId id) { + this.id = id; + } + + public String toString() { + return toJsonString(); + } + + public String toJsonString() { + return "{\"time\": " + this.transactionDate.getTime() + ",\"item\":" + this.itemID + "}"; + } +} diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java b/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java index b11a36607..081829ace 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaSystem.java @@ -1,429 +1,491 @@ -package emu.grasscutter.game.gacha; - -import com.sun.nio.file.SensitivityWatchEventModifier; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.gacha.GachaBanner.BannerType; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.Inventory; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.game.systems.InventorySystem; -import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem; -import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem; -import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.game.GameServerTickEvent; -import emu.grasscutter.server.packet.send.PacketDoGachaRsp; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import org.greenrobot.eventbus.Subscribe; - -import java.nio.file.*; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -public class GachaSystem extends BaseGameSystem { - private static final int starglitterId = 221; - private static final int stardustId = 222; - private final Int2ObjectMap gachaBanners; - private WatchService watchService; - - public GachaSystem(GameServer server) { - super(server); - this.gachaBanners = new Int2ObjectOpenHashMap<>(); - this.load(); - this.startWatcher(server); - } - - public Int2ObjectMap getGachaBanners() { - return gachaBanners; - } - - public int randomRange(int min, int max) { // Both are inclusive - return ThreadLocalRandom.current().nextInt(max - min + 1) + min; - } - - public int getRandom(int[] array) { - return array[randomRange(0, array.length - 1)]; - } - - public synchronized void load() { - getGachaBanners().clear(); - int autoScheduleId = 1000; - int autoSortId = 9000; - try { - List banners = DataLoader.loadTableToList("Banners", GachaBanner.class); - if (banners.size() > 0) { - for (GachaBanner banner : banners) { - banner.onLoad(); - if (banner.isDeprecated()) { - Grasscutter.getLogger().error("A Banner has not been loaded because it contains one or more deprecated fields. Remove the fields mentioned above and reload."); - } else if (banner.isDisabled()) { - Grasscutter.getLogger().debug("A Banner has not been loaded because it is disabled."); - } else { - if (banner.scheduleId < 0) - banner.scheduleId = autoScheduleId++; - if (banner.sortId < 0) - banner.sortId = autoSortId--; - getGachaBanners().put(banner.scheduleId, banner); - } - } - Grasscutter.getLogger().debug("Banners successfully loaded."); - } else { - Grasscutter.getLogger().error("Unable to load banners. Banners size is 0."); - } - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private synchronized int[] removeC6FromPool(int[] itemPool, Player player) { - IntList temp = new IntArrayList(); - for (int itemId : itemPool) { - if (InventorySystem.checkPlayerAvatarConstellationLevel(player, itemId) < 6) { - temp.add(itemId); - } - } - return temp.toIntArray(); - } - - private synchronized int drawRoulette(int[] weights, int cutoff) { - // This follows the logic laid out in issue #183 - // Simple weighted selection with an upper bound for the roll that cuts off trailing entries - // All weights must be >= 0 - int total = 0; - for (int weight : weights) { - if (weight < 0) { - throw new IllegalArgumentException("Weights must be non-negative!"); - } - total += weight; - } - int roll = ThreadLocalRandom.current().nextInt((total < cutoff) ? total : cutoff); - int subTotal = 0; - for (int i = 0; i < weights.length; i++) { - subTotal += weights[i]; - if (roll < subTotal) { - return i; - } - } - // throw new IllegalStateException(); - return 0; // This should only be reachable if total==0 - } - - private synchronized int doFallbackRarePull(int[] fallback1, int[] fallback2, int rarity, GachaBanner banner, PlayerGachaBannerInfo gachaInfo) { - if (fallback1.length < 1) { - if (fallback2.length < 1) { - return getRandom((rarity == 5) ? GachaBanner.DEFAULT_FALLBACK_ITEMS_5_POOL_2 : GachaBanner.DEFAULT_FALLBACK_ITEMS_4_POOL_2); - } else { - return getRandom(fallback2); - } - } else if (fallback2.length < 1) { - return getRandom(fallback1); - } else { // Both pools are possible, use the pool balancer - int pityPool1 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 1)); - int pityPool2 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 2)); - int chosenPool = switch ((pityPool1 >= pityPool2) ? 1 : 0) { // Larger weight must come first for the hard cutoff to function correctly - case 1 -> 1 + drawRoulette(new int[]{pityPool1, pityPool2}, 10000); - default -> 2 - drawRoulette(new int[]{pityPool2, pityPool1}, 10000); - }; - return switch (chosenPool) { - case 1: - gachaInfo.setPityPool(rarity, 1, 0); - yield getRandom(fallback1); - default: - gachaInfo.setPityPool(rarity, 2, 0); - yield getRandom(fallback2); - }; - } - } - - private synchronized int doRarePull(int[] featured, int[] fallback1, int[] fallback2, int rarity, GachaBanner banner, PlayerGachaBannerInfo gachaInfo) { - int itemId = 0; - boolean epitomized = (banner.hasEpitomized()) && (rarity == 5) && (gachaInfo.getWishItemId() != 0); - boolean pityEpitomized = (gachaInfo.getFailedChosenItemPulls() >= banner.getWishMaxProgress()); // Maximum fate points reached - boolean pityFeatured = (gachaInfo.getFailedFeaturedItemPulls(rarity) >= 1); // Lost previous coinflip - boolean rollFeatured = (this.randomRange(1, 100) <= banner.getEventChance(rarity)); // Won this coinflip - boolean pullFeatured = pityFeatured || rollFeatured; - - if (epitomized && pityEpitomized) { // Auto pick item when epitomized points reached - gachaInfo.setFailedFeaturedItemPulls(rarity, 0); // Epitomized item will always be a featured one - itemId = gachaInfo.getWishItemId(); - } else { - if (pullFeatured && (featured.length > 0)) { - gachaInfo.setFailedFeaturedItemPulls(rarity, 0); - itemId = getRandom(featured); - } else { - gachaInfo.addFailedFeaturedItemPulls(rarity, 1); // This could be moved into doFallbackRarePull but having it here makes it clearer - itemId = doFallbackRarePull(fallback1, fallback2, rarity, banner, gachaInfo); - } - } - - if (epitomized) { - if (itemId == gachaInfo.getWishItemId()) { // Reset epitomized points when got wished item - gachaInfo.setFailedChosenItemPulls(0); - } else { // Add epitomized points if not get wished item - gachaInfo.addFailedChosenItemPulls(1); - } - } - return itemId; - } - - private synchronized int doPull(GachaBanner banner, PlayerGachaBannerInfo gachaInfo, BannerPools pools) { - // Pre-increment all pity pools (yes this makes all calculations assume 1-indexed pity) - gachaInfo.incPityAll(); - - int[] weights = {banner.getWeight(5, gachaInfo.getPity5()), banner.getWeight(4, gachaInfo.getPity4()), 10000}; - int levelWon = 5 - drawRoulette(weights, 10000); - - return switch (levelWon) { - case 5: - gachaInfo.setPity5(0); - yield doRarePull(pools.rateUpItems5, pools.fallbackItems5Pool1, pools.fallbackItems5Pool2, 5, banner, gachaInfo); - case 4: - gachaInfo.setPity4(0); - yield doRarePull(pools.rateUpItems4, pools.fallbackItems4Pool1, pools.fallbackItems4Pool2, 4, banner, gachaInfo); - default: - yield getRandom(banner.getFallbackItems3()); - }; - } - - public synchronized void doPulls(Player player, int scheduleId, int times) { - // Sanity check - if (times != 10 && times != 1) { - player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_INVALID_TIMES)); - return; - } - Inventory inventory = player.getInventory(); - if (inventory.getInventoryTab(ItemType.ITEM_WEAPON).getSize() + times > inventory.getInventoryTab(ItemType.ITEM_WEAPON).getMaxCapacity()) { - player.sendPacket(new PacketDoGachaRsp(Retcode.RET_ITEM_EXCEED_LIMIT)); - return; - } - - // Get banner - GachaBanner banner = this.getGachaBanners().get(scheduleId); - if (banner == null) { - player.sendPacket(new PacketDoGachaRsp()); - return; - } - - // Check against total limit - PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(banner); - int gachaTimesLimit = banner.getGachaTimesLimit(); - if (gachaTimesLimit != Integer.MAX_VALUE && (gachaInfo.getTotalPulls() + times) > gachaTimesLimit) { - player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_TIMES_LIMIT)); - return; - } - - // Spend currency - ItemParamData cost = banner.getCost(times); - if (cost.getCount() > 0 && !inventory.payItem(cost)) { - player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_COST_ITEM_NOT_ENOUGH)); - return; - } - - // Add to character - gachaInfo.addTotalPulls(times); - BannerPools pools = new BannerPools(banner); - List list = new ArrayList<>(); - int stardust = 0, starglitter = 0; - - if (banner.isRemoveC6FromPool()) { // The ultimate form of pity (non-vanilla) - pools.rateUpItems4 = removeC6FromPool(pools.rateUpItems4, player); - pools.rateUpItems5 = removeC6FromPool(pools.rateUpItems5, player); - pools.fallbackItems4Pool1 = removeC6FromPool(pools.fallbackItems4Pool1, player); - pools.fallbackItems4Pool2 = removeC6FromPool(pools.fallbackItems4Pool2, player); - pools.fallbackItems5Pool1 = removeC6FromPool(pools.fallbackItems5Pool1, player); - pools.fallbackItems5Pool2 = removeC6FromPool(pools.fallbackItems5Pool2, player); - } - - for (int i = 0; i < times; i++) { - // Roll - int itemId = doPull(banner, gachaInfo, pools); - ItemData itemData = GameData.getItemDataMap().get(itemId); - if (itemData == null) { - continue; // Maybe we should bail out if an item fails instead of rolling the rest? - } - - // Write gacha record - GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), banner.getGachaType()); - DatabaseHelper.saveGachaRecord(gachaRecord); - - // Create gacha item - GachaItem.Builder gachaItem = GachaItem.newBuilder(); - int addStardust = 0, addStarglitter = 0; - boolean isTransferItem = false; - - // Const check - int constellation = InventorySystem.checkPlayerAvatarConstellationLevel(player, itemId); - switch (constellation) { - case -2: // Is weapon - switch (itemData.getRankLevel()) { - case 5 -> addStarglitter = 10; - case 4 -> addStarglitter = 2; - default -> addStardust = 15; - } - break; - case -1: // New character - gachaItem.setIsGachaItemNew(true); - break; - default: - if (constellation >= 6) { // C6, give consolation starglitter - addStarglitter = (itemData.getRankLevel() == 5) ? 25 : 5; - } else { // C0-C5, give constellation item - if (banner.isRemoveC6FromPool() && constellation == 5) { // New C6, remove it from the pools so we don't get C7 in a 10pull - pools.removeFromAllPools(new int[]{itemId}); - } - addStarglitter = (itemData.getRankLevel() == 5) ? 10 : 2; - int constItemId = itemId + 100; // This may not hold true for future characters. Examples of strictly correct constellation item lookup are elsewhere for now. - boolean haveConstItem = inventory.getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId) == null; - gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(haveConstItem)); - //inventory.addItem(constItemId, 1); // This is now managed by the avatar card item itself - } - isTransferItem = true; - break; - } - - // Create item - GameItem item = new GameItem(itemData); - gachaItem.setGachaItem(item.toItemParam()); - inventory.addItem(item); - - stardust += addStardust; - starglitter += addStarglitter; - - if (addStardust > 0) { - gachaItem.addTokenItemList(ItemParam.newBuilder().setItemId(stardustId).setCount(addStardust)); - } - if (addStarglitter > 0) { - ItemParam starglitterParam = ItemParam.newBuilder().setItemId(starglitterId).setCount(addStarglitter).build(); - if (isTransferItem) { - gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(starglitterParam)); - } - gachaItem.addTokenItemList(starglitterParam); - } - - list.add(gachaItem.build()); - } - - // Add stardust/starglitter - if (stardust > 0) { - inventory.addItem(stardustId, stardust); - } - if (starglitter > 0) { - inventory.addItem(starglitterId, starglitter); - } - - // Packets - player.sendPacket(new PacketDoGachaRsp(banner, list, gachaInfo)); - - // Battle Pass trigger - player.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_GACHA_NUM, 0, times); - } - - private synchronized void startWatcher(GameServer server) { - if (this.watchService == null) { - try { - this.watchService = FileSystems.getDefault().newWatchService(); - FileUtils.getDataUserPath("").register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"); - e.printStackTrace(); - } - } else { - Grasscutter.getLogger().error("Cannot reinitialise watcher "); - } - } - - @Subscribe - public synchronized void watchBannerJson(GameServerTickEvent tickEvent) { - if (GAME_OPTIONS.watchGachaConfig) { - try { - WatchKey watchKey = watchService.take(); - - for (WatchEvent event : watchKey.pollEvents()) { - final Path changed = (Path) event.context(); - if (changed.endsWith("Banners.json")) { - Grasscutter.getLogger().info("Change detected with banners.json. Reloading gacha config"); - this.load(); - } - } - - boolean valid = watchKey.reset(); - if (!valid) { - Grasscutter.getLogger().error("Unable to reset Gacha Manager Watch Key. Auto-reload of banners.json will no longer work."); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private synchronized GetGachaInfoRsp createProto(Player player) { - GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345); - - long currentTime = System.currentTimeMillis() / 1000L; - - for (GachaBanner banner : getGachaBanners().values()) { - if ((banner.getEndTime() >= currentTime && banner.getBeginTime() <= currentTime) || (banner.getBannerType() == BannerType.STANDARD)) { - proto.addGachaInfoList(banner.toProto(player)); - } - } - - return proto.build(); - } - - public GetGachaInfoRsp toProto(Player player) { - return createProto(player); - } - - private class BannerPools { - public int[] rateUpItems4; - public int[] rateUpItems5; - public int[] fallbackItems4Pool1; - public int[] fallbackItems4Pool2; - public int[] fallbackItems5Pool1; - public int[] fallbackItems5Pool2; - - public BannerPools(GachaBanner banner) { - rateUpItems4 = banner.getRateUpItems4(); - rateUpItems5 = banner.getRateUpItems5(); - fallbackItems4Pool1 = banner.getFallbackItems4Pool1(); - fallbackItems4Pool2 = banner.getFallbackItems4Pool2(); - fallbackItems5Pool1 = banner.getFallbackItems5Pool1(); - fallbackItems5Pool2 = banner.getFallbackItems5Pool2(); - - if (banner.isAutoStripRateUpFromFallback()) { - fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, rateUpItems4); - fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, rateUpItems4); - fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, rateUpItems5); - fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, rateUpItems5); - } - } - - public void removeFromAllPools(int[] itemIds) { - rateUpItems4 = Utils.setSubtract(rateUpItems4, itemIds); - rateUpItems5 = Utils.setSubtract(rateUpItems5, itemIds); - fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, itemIds); - fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, itemIds); - fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, itemIds); - fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, itemIds); - } - } -} +package emu.grasscutter.game.gacha; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import com.sun.nio.file.SensitivityWatchEventModifier; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.gacha.GachaBanner.BannerType; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.Inventory; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.game.systems.InventorySystem; +import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem; +import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem; +import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.game.GameServerTickEvent; +import emu.grasscutter.server.packet.send.PacketDoGachaRsp; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import org.greenrobot.eventbus.Subscribe; + +public class GachaSystem extends BaseGameSystem { + private static final int starglitterId = 221; + private static final int stardustId = 222; + private final Int2ObjectMap gachaBanners; + private WatchService watchService; + + public GachaSystem(GameServer server) { + super(server); + this.gachaBanners = new Int2ObjectOpenHashMap<>(); + this.load(); + this.startWatcher(server); + } + + public Int2ObjectMap getGachaBanners() { + return gachaBanners; + } + + public int randomRange(int min, int max) { // Both are inclusive + return ThreadLocalRandom.current().nextInt(max - min + 1) + min; + } + + public int getRandom(int[] array) { + return array[randomRange(0, array.length - 1)]; + } + + public synchronized void load() { + getGachaBanners().clear(); + int autoScheduleId = 1000; + int autoSortId = 9000; + try { + List banners = DataLoader.loadTableToList("Banners", GachaBanner.class); + if (banners.size() > 0) { + for (GachaBanner banner : banners) { + banner.onLoad(); + if (banner.isDeprecated()) { + Grasscutter.getLogger() + .error( + "A Banner has not been loaded because it contains one or more deprecated fields. Remove the fields mentioned above and reload."); + } else if (banner.isDisabled()) { + Grasscutter.getLogger().debug("A Banner has not been loaded because it is disabled."); + } else { + if (banner.scheduleId < 0) banner.scheduleId = autoScheduleId++; + if (banner.sortId < 0) banner.sortId = autoSortId--; + getGachaBanners().put(banner.scheduleId, banner); + } + } + Grasscutter.getLogger().debug("Banners successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load banners. Banners size is 0."); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private synchronized int[] removeC6FromPool(int[] itemPool, Player player) { + IntList temp = new IntArrayList(); + for (int itemId : itemPool) { + if (InventorySystem.checkPlayerAvatarConstellationLevel(player, itemId) < 6) { + temp.add(itemId); + } + } + return temp.toIntArray(); + } + + private synchronized int drawRoulette(int[] weights, int cutoff) { + // This follows the logic laid out in issue #183 + // Simple weighted selection with an upper bound for the roll that cuts off trailing entries + // All weights must be >= 0 + int total = 0; + for (int weight : weights) { + if (weight < 0) { + throw new IllegalArgumentException("Weights must be non-negative!"); + } + total += weight; + } + int roll = ThreadLocalRandom.current().nextInt((total < cutoff) ? total : cutoff); + int subTotal = 0; + for (int i = 0; i < weights.length; i++) { + subTotal += weights[i]; + if (roll < subTotal) { + return i; + } + } + // throw new IllegalStateException(); + return 0; // This should only be reachable if total==0 + } + + private synchronized int doFallbackRarePull( + int[] fallback1, + int[] fallback2, + int rarity, + GachaBanner banner, + PlayerGachaBannerInfo gachaInfo) { + if (fallback1.length < 1) { + if (fallback2.length < 1) { + return getRandom( + (rarity == 5) + ? GachaBanner.DEFAULT_FALLBACK_ITEMS_5_POOL_2 + : GachaBanner.DEFAULT_FALLBACK_ITEMS_4_POOL_2); + } else { + return getRandom(fallback2); + } + } else if (fallback2.length < 1) { + return getRandom(fallback1); + } else { // Both pools are possible, use the pool balancer + int pityPool1 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 1)); + int pityPool2 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 2)); + int chosenPool = + switch ((pityPool1 >= pityPool2) + ? 1 + : 0) { // Larger weight must come first for the hard cutoff to function correctly + case 1 -> 1 + drawRoulette(new int[] {pityPool1, pityPool2}, 10000); + default -> 2 - drawRoulette(new int[] {pityPool2, pityPool1}, 10000); + }; + return switch (chosenPool) { + case 1: + gachaInfo.setPityPool(rarity, 1, 0); + yield getRandom(fallback1); + default: + gachaInfo.setPityPool(rarity, 2, 0); + yield getRandom(fallback2); + }; + } + } + + private synchronized int doRarePull( + int[] featured, + int[] fallback1, + int[] fallback2, + int rarity, + GachaBanner banner, + PlayerGachaBannerInfo gachaInfo) { + int itemId = 0; + boolean epitomized = + (banner.hasEpitomized()) && (rarity == 5) && (gachaInfo.getWishItemId() != 0); + boolean pityEpitomized = + (gachaInfo.getFailedChosenItemPulls() + >= banner.getWishMaxProgress()); // Maximum fate points reached + boolean pityFeatured = + (gachaInfo.getFailedFeaturedItemPulls(rarity) >= 1); // Lost previous coinflip + boolean rollFeatured = + (this.randomRange(1, 100) <= banner.getEventChance(rarity)); // Won this coinflip + boolean pullFeatured = pityFeatured || rollFeatured; + + if (epitomized && pityEpitomized) { // Auto pick item when epitomized points reached + gachaInfo.setFailedFeaturedItemPulls( + rarity, 0); // Epitomized item will always be a featured one + itemId = gachaInfo.getWishItemId(); + } else { + if (pullFeatured && (featured.length > 0)) { + gachaInfo.setFailedFeaturedItemPulls(rarity, 0); + itemId = getRandom(featured); + } else { + gachaInfo.addFailedFeaturedItemPulls( + rarity, + 1); // This could be moved into doFallbackRarePull but having it here makes it clearer + itemId = doFallbackRarePull(fallback1, fallback2, rarity, banner, gachaInfo); + } + } + + if (epitomized) { + if (itemId == gachaInfo.getWishItemId()) { // Reset epitomized points when got wished item + gachaInfo.setFailedChosenItemPulls(0); + } else { // Add epitomized points if not get wished item + gachaInfo.addFailedChosenItemPulls(1); + } + } + return itemId; + } + + private synchronized int doPull( + GachaBanner banner, PlayerGachaBannerInfo gachaInfo, BannerPools pools) { + // Pre-increment all pity pools (yes this makes all calculations assume 1-indexed pity) + gachaInfo.incPityAll(); + + int[] weights = { + banner.getWeight(5, gachaInfo.getPity5()), banner.getWeight(4, gachaInfo.getPity4()), 10000 + }; + int levelWon = 5 - drawRoulette(weights, 10000); + + return switch (levelWon) { + case 5: + gachaInfo.setPity5(0); + yield doRarePull( + pools.rateUpItems5, + pools.fallbackItems5Pool1, + pools.fallbackItems5Pool2, + 5, + banner, + gachaInfo); + case 4: + gachaInfo.setPity4(0); + yield doRarePull( + pools.rateUpItems4, + pools.fallbackItems4Pool1, + pools.fallbackItems4Pool2, + 4, + banner, + gachaInfo); + default: + yield getRandom(banner.getFallbackItems3()); + }; + } + + public synchronized void doPulls(Player player, int scheduleId, int times) { + // Sanity check + if (times != 10 && times != 1) { + player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_INVALID_TIMES)); + return; + } + Inventory inventory = player.getInventory(); + if (inventory.getInventoryTab(ItemType.ITEM_WEAPON).getSize() + times + > inventory.getInventoryTab(ItemType.ITEM_WEAPON).getMaxCapacity()) { + player.sendPacket(new PacketDoGachaRsp(Retcode.RET_ITEM_EXCEED_LIMIT)); + return; + } + + // Get banner + GachaBanner banner = this.getGachaBanners().get(scheduleId); + if (banner == null) { + player.sendPacket(new PacketDoGachaRsp()); + return; + } + + // Check against total limit + PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(banner); + int gachaTimesLimit = banner.getGachaTimesLimit(); + if (gachaTimesLimit != Integer.MAX_VALUE + && (gachaInfo.getTotalPulls() + times) > gachaTimesLimit) { + player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_TIMES_LIMIT)); + return; + } + + // Spend currency + ItemParamData cost = banner.getCost(times); + if (cost.getCount() > 0 && !inventory.payItem(cost)) { + player.sendPacket(new PacketDoGachaRsp(Retcode.RET_GACHA_COST_ITEM_NOT_ENOUGH)); + return; + } + + // Add to character + gachaInfo.addTotalPulls(times); + BannerPools pools = new BannerPools(banner); + List list = new ArrayList<>(); + int stardust = 0, starglitter = 0; + + if (banner.isRemoveC6FromPool()) { // The ultimate form of pity (non-vanilla) + pools.rateUpItems4 = removeC6FromPool(pools.rateUpItems4, player); + pools.rateUpItems5 = removeC6FromPool(pools.rateUpItems5, player); + pools.fallbackItems4Pool1 = removeC6FromPool(pools.fallbackItems4Pool1, player); + pools.fallbackItems4Pool2 = removeC6FromPool(pools.fallbackItems4Pool2, player); + pools.fallbackItems5Pool1 = removeC6FromPool(pools.fallbackItems5Pool1, player); + pools.fallbackItems5Pool2 = removeC6FromPool(pools.fallbackItems5Pool2, player); + } + + for (int i = 0; i < times; i++) { + // Roll + int itemId = doPull(banner, gachaInfo, pools); + ItemData itemData = GameData.getItemDataMap().get(itemId); + if (itemData == null) { + continue; // Maybe we should bail out if an item fails instead of rolling the rest? + } + + // Write gacha record + GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), banner.getGachaType()); + DatabaseHelper.saveGachaRecord(gachaRecord); + + // Create gacha item + GachaItem.Builder gachaItem = GachaItem.newBuilder(); + int addStardust = 0, addStarglitter = 0; + boolean isTransferItem = false; + + // Const check + int constellation = InventorySystem.checkPlayerAvatarConstellationLevel(player, itemId); + switch (constellation) { + case -2: // Is weapon + switch (itemData.getRankLevel()) { + case 5 -> addStarglitter = 10; + case 4 -> addStarglitter = 2; + default -> addStardust = 15; + } + break; + case -1: // New character + gachaItem.setIsGachaItemNew(true); + break; + default: + if (constellation >= 6) { // C6, give consolation starglitter + addStarglitter = (itemData.getRankLevel() == 5) ? 25 : 5; + } else { // C0-C5, give constellation item + if (banner.isRemoveC6FromPool() + && constellation + == 5) { // New C6, remove it from the pools so we don't get C7 in a 10pull + pools.removeFromAllPools(new int[] {itemId}); + } + addStarglitter = (itemData.getRankLevel() == 5) ? 10 : 2; + int constItemId = + itemId + 100; // This may not hold true for future characters. Examples of strictly + // correct constellation item lookup are elsewhere for now. + boolean haveConstItem = + inventory.getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId) == null; + gachaItem.addTransferItems( + GachaTransferItem.newBuilder() + .setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)) + .setIsTransferItemNew(haveConstItem)); + // inventory.addItem(constItemId, 1); // This is now managed by the avatar card item + // itself + } + isTransferItem = true; + break; + } + + // Create item + GameItem item = new GameItem(itemData); + gachaItem.setGachaItem(item.toItemParam()); + inventory.addItem(item); + + stardust += addStardust; + starglitter += addStarglitter; + + if (addStardust > 0) { + gachaItem.addTokenItemList( + ItemParam.newBuilder().setItemId(stardustId).setCount(addStardust)); + } + if (addStarglitter > 0) { + ItemParam starglitterParam = + ItemParam.newBuilder().setItemId(starglitterId).setCount(addStarglitter).build(); + if (isTransferItem) { + gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(starglitterParam)); + } + gachaItem.addTokenItemList(starglitterParam); + } + + list.add(gachaItem.build()); + } + + // Add stardust/starglitter + if (stardust > 0) { + inventory.addItem(stardustId, stardust); + } + if (starglitter > 0) { + inventory.addItem(starglitterId, starglitter); + } + + // Packets + player.sendPacket(new PacketDoGachaRsp(banner, list, gachaInfo)); + + // Battle Pass trigger + player.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_GACHA_NUM, 0, times); + } + + private synchronized void startWatcher(GameServer server) { + if (this.watchService == null) { + try { + this.watchService = FileSystems.getDefault().newWatchService(); + FileUtils.getDataUserPath("") + .register( + watchService, + new WatchEvent.Kind[] {StandardWatchEventKinds.ENTRY_MODIFY}, + SensitivityWatchEventModifier.HIGH); + } catch (Exception e) { + Grasscutter.getLogger() + .error( + "Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"); + e.printStackTrace(); + } + } else { + Grasscutter.getLogger().error("Cannot reinitialise watcher "); + } + } + + @Subscribe + public synchronized void watchBannerJson(GameServerTickEvent tickEvent) { + if (GAME_OPTIONS.watchGachaConfig) { + try { + WatchKey watchKey = watchService.take(); + + for (WatchEvent event : watchKey.pollEvents()) { + final Path changed = (Path) event.context(); + if (changed.endsWith("Banners.json")) { + Grasscutter.getLogger() + .info("Change detected with banners.json. Reloading gacha config"); + this.load(); + } + } + + boolean valid = watchKey.reset(); + if (!valid) { + Grasscutter.getLogger() + .error( + "Unable to reset Gacha Manager Watch Key. Auto-reload of banners.json will no longer work."); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private synchronized GetGachaInfoRsp createProto(Player player) { + GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345); + + long currentTime = System.currentTimeMillis() / 1000L; + + for (GachaBanner banner : getGachaBanners().values()) { + if ((banner.getEndTime() >= currentTime && banner.getBeginTime() <= currentTime) + || (banner.getBannerType() == BannerType.STANDARD)) { + proto.addGachaInfoList(banner.toProto(player)); + } + } + + return proto.build(); + } + + public GetGachaInfoRsp toProto(Player player) { + return createProto(player); + } + + private class BannerPools { + public int[] rateUpItems4; + public int[] rateUpItems5; + public int[] fallbackItems4Pool1; + public int[] fallbackItems4Pool2; + public int[] fallbackItems5Pool1; + public int[] fallbackItems5Pool2; + + public BannerPools(GachaBanner banner) { + rateUpItems4 = banner.getRateUpItems4(); + rateUpItems5 = banner.getRateUpItems5(); + fallbackItems4Pool1 = banner.getFallbackItems4Pool1(); + fallbackItems4Pool2 = banner.getFallbackItems4Pool2(); + fallbackItems5Pool1 = banner.getFallbackItems5Pool1(); + fallbackItems5Pool2 = banner.getFallbackItems5Pool2(); + + if (banner.isAutoStripRateUpFromFallback()) { + fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, rateUpItems4); + fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, rateUpItems4); + fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, rateUpItems5); + fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, rateUpItems5); + } + } + + public void removeFromAllPools(int[] itemIds) { + rateUpItems4 = Utils.setSubtract(rateUpItems4, itemIds); + rateUpItems5 = Utils.setSubtract(rateUpItems5, itemIds); + fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, itemIds); + fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, itemIds); + fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, itemIds); + fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, itemIds); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java b/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java index 1c0477546..5fd93a05d 100644 --- a/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java +++ b/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java @@ -1,132 +1,122 @@ -package emu.grasscutter.game.gacha; - -import dev.morphia.annotations.Entity; -import lombok.Getter; -import lombok.Setter; - -@Entity -public class PlayerGachaBannerInfo { - @Getter - @Setter - private int totalPulls = 0; - @Getter - @Setter - private int pity5 = 0; - @Getter - @Setter - private int pity4 = 0; - private int failedFeaturedItemPulls = 0; - private int failedFeatured4ItemPulls = 0; - private int pity5Pool1 = 0; - private int pity5Pool2 = 0; - private int pity4Pool1 = 0; - private int pity4Pool2 = 0; - - @Getter - @Setter - private int failedChosenItemPulls = 0; - @Getter - @Setter - private int wishItemId = 0; - - public void addTotalPulls(int amount) { - this.totalPulls += amount; - } - - public void addPity5(int amount) { - this.pity5 += amount; - } - - public void addPity4(int amount) { - this.pity4 += amount; - } - - public void addFailedChosenItemPulls(int amount) { - failedChosenItemPulls += amount; - } - - public int getFailedFeaturedItemPulls(int rarity) { - return switch (rarity) { - case 4 -> failedFeatured4ItemPulls; - default -> failedFeaturedItemPulls; // 5 - }; - } - - public void setFailedFeaturedItemPulls(int rarity, int amount) { - if (rarity == 4) { - failedFeatured4ItemPulls = amount; - } else { - failedFeaturedItemPulls = amount; // 5 - } - } - - public void addFailedFeaturedItemPulls(int rarity, int amount) { - if (rarity == 4) { - failedFeatured4ItemPulls += amount; - } else { - failedFeaturedItemPulls += amount; // 5 - } - } - - public int getPityPool(int rarity, int pool) { - return switch (rarity) { - case 4 -> switch (pool) { - case 1 -> pity4Pool1; - default -> pity4Pool2; - }; - default -> switch (pool) { - case 1 -> pity5Pool1; - default -> pity5Pool2; - }; - }; - } - - public void setPityPool(int rarity, int pool, int amount) { - switch (rarity) { - case 4: - if (pool == 1) { - pity4Pool1 = amount; - } else { - pity4Pool2 = amount; - } - break; - case 5: - default: - if (pool == 1) { - pity5Pool1 = amount; - } else { - pity5Pool2 = amount; - } - break; - } - } - - public void addPityPool(int rarity, int pool, int amount) { - switch (rarity) { - case 4: - if (pool == 1) { - pity4Pool1 += amount; - } else { - pity4Pool2 += amount; - } - break; - case 5: - default: - if (pool == 1) { - pity5Pool1 += amount; - } else { - pity5Pool2 += amount; - } - break; - } - } - - public void incPityAll() { - pity4++; - pity5++; - pity4Pool1++; - pity4Pool2++; - pity5Pool1++; - pity5Pool2++; - } -} +package emu.grasscutter.game.gacha; + +import dev.morphia.annotations.Entity; +import lombok.Getter; +import lombok.Setter; + +@Entity +public class PlayerGachaBannerInfo { + @Getter @Setter private int totalPulls = 0; + @Getter @Setter private int pity5 = 0; + @Getter @Setter private int pity4 = 0; + private int failedFeaturedItemPulls = 0; + private int failedFeatured4ItemPulls = 0; + private int pity5Pool1 = 0; + private int pity5Pool2 = 0; + private int pity4Pool1 = 0; + private int pity4Pool2 = 0; + + @Getter @Setter private int failedChosenItemPulls = 0; + @Getter @Setter private int wishItemId = 0; + + public void addTotalPulls(int amount) { + this.totalPulls += amount; + } + + public void addPity5(int amount) { + this.pity5 += amount; + } + + public void addPity4(int amount) { + this.pity4 += amount; + } + + public void addFailedChosenItemPulls(int amount) { + failedChosenItemPulls += amount; + } + + public int getFailedFeaturedItemPulls(int rarity) { + return switch (rarity) { + case 4 -> failedFeatured4ItemPulls; + default -> failedFeaturedItemPulls; // 5 + }; + } + + public void setFailedFeaturedItemPulls(int rarity, int amount) { + if (rarity == 4) { + failedFeatured4ItemPulls = amount; + } else { + failedFeaturedItemPulls = amount; // 5 + } + } + + public void addFailedFeaturedItemPulls(int rarity, int amount) { + if (rarity == 4) { + failedFeatured4ItemPulls += amount; + } else { + failedFeaturedItemPulls += amount; // 5 + } + } + + public int getPityPool(int rarity, int pool) { + return switch (rarity) { + case 4 -> switch (pool) { + case 1 -> pity4Pool1; + default -> pity4Pool2; + }; + default -> switch (pool) { + case 1 -> pity5Pool1; + default -> pity5Pool2; + }; + }; + } + + public void setPityPool(int rarity, int pool, int amount) { + switch (rarity) { + case 4: + if (pool == 1) { + pity4Pool1 = amount; + } else { + pity4Pool2 = amount; + } + break; + case 5: + default: + if (pool == 1) { + pity5Pool1 = amount; + } else { + pity5Pool2 = amount; + } + break; + } + } + + public void addPityPool(int rarity, int pool, int amount) { + switch (rarity) { + case 4: + if (pool == 1) { + pity4Pool1 += amount; + } else { + pity4Pool2 += amount; + } + break; + case 5: + default: + if (pool == 1) { + pity5Pool1 += amount; + } else { + pity5Pool2 += amount; + } + break; + } + } + + public void incPityAll() { + pity4++; + pity5++; + pity4Pool1++; + pity4Pool2++; + pity5Pool1++; + pity5Pool2++; + } +} diff --git a/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java b/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java index 4fbf2c208..107195e3a 100644 --- a/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java +++ b/src/main/java/emu/grasscutter/game/home/FurnitureMakeSlotItem.java @@ -1,32 +1,31 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -@Entity -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class FurnitureMakeSlotItem { - @Id - int index; - int makeId; - int avatarId; - int beginTime; - int durTime; - - public FurnitureMakeDataOuterClass.FurnitureMakeData toProto() { - return FurnitureMakeDataOuterClass.FurnitureMakeData.newBuilder() - .setIndex(index) - .setAvatarId(avatarId) - .setMakeId(makeId) - .setBeginTime(beginTime) - .setDurTime(durTime) - .build(); - } -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class FurnitureMakeSlotItem { + @Id int index; + int makeId; + int avatarId; + int beginTime; + int durTime; + + public FurnitureMakeDataOuterClass.FurnitureMakeData toProto() { + return FurnitureMakeDataOuterClass.FurnitureMakeData.newBuilder() + .setIndex(index) + .setAvatarId(avatarId) + .setMakeId(makeId) + .setBeginTime(beginTime) + .setDurTime(durTime) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/GameHome.java b/src/main/java/emu/grasscutter/game/home/GameHome.java index 8f6787fb4..14ed2256d 100644 --- a/src/main/java/emu/grasscutter/game/home/GameHome.java +++ b/src/main/java/emu/grasscutter/game/home/GameHome.java @@ -1,341 +1,358 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.*; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.HomeWorldLevelData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.*; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -@Entity(value = "homes", useDiscriminator = false) -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class GameHome { - @Id - String id; - - @Indexed(options = @IndexOptions(unique = true)) - long ownerUid; - @Transient - Player player; - - int level; - int exp; - int lastUpdatedTime; - int nextUpdateTime; - int storedCoin; - int storedFetterExp; - List furnitureMakeSlotItemList; - ConcurrentHashMap sceneMap; - Set unlockedHomeBgmList; - int enterHomeOption; - - public static GameHome getByUid(Integer uid) { - var home = DatabaseHelper.getHomeByUid(uid); - if (home == null) { - home = GameHome.create(uid); - } - return home; - } - - public static GameHome create(Integer uid) { - return GameHome.of() - .ownerUid(uid) - .level(1) - .sceneMap(new ConcurrentHashMap<>()) - .unlockedHomeBgmList(new HashSet<>()) - .build(); - } - - public void save() { - DatabaseHelper.saveHome(this); - } - - public HomeSceneItem getHomeSceneItem(int sceneId) { - return sceneMap.computeIfAbsent(sceneId, e -> { - var defaultItem = GameData.getHomeworldDefaultSaveData().get(sceneId); - if (defaultItem != null) { - Grasscutter.getLogger().info("Set player {} home {} to initial setting", ownerUid, sceneId); - return HomeSceneItem.parseFrom(defaultItem, sceneId); - } else { - // Realm res missing bricks account, use default realm data to allow main house - defaultItem = GameData.getHomeworldDefaultSaveData().get(2001); - return HomeSceneItem.parseFrom(defaultItem, sceneId); - } - }); - } - - public void onOwnerLogin(Player player) { - if (this.player == null) - this.player = player; - player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); - player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); - player.getSession().send(new PacketHomeComfortInfoNotify(player)); - player.getSession().send(new PacketFurnitureCurModuleArrangeCountNotify()); - player.getSession().send(new PacketHomeMarkPointNotify(player)); - player.getSession().send(new PacketHomeAllUnlockedBgmIdListNotify(player)); - checkAccumulatedResources(player); - player.getSession().send(new PacketHomeResourceNotify(player)); - } - - // Tell the client the reward is claimed or realm unlocked - public void onClaimReward(Player player) { - player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); - } - - public Player getPlayer() { - if (this.player == null) - this.player = Grasscutter.getGameServer().getPlayerByUid((int) this.ownerUid, true); - return this.player; - } - - public HomeWorldLevelData getLevelData() { - return GameData.getHomeWorldLevelDataMap().get(level); - } - - public boolean addUnlockedHomeBgm(int homeBgmId) { - if (!getUnlockedHomeBgmList().add(homeBgmId)) return false; - - var player = this.getPlayer(); - player.sendPacket(new PacketHomeNewUnlockedBgmIdListNotify(homeBgmId)); - player.sendPacket(new PacketHomeAllUnlockedBgmIdListNotify(player)); - save(); - return true; - } - - public Set getUnlockedHomeBgmList() { - if (this.unlockedHomeBgmList == null) { - this.unlockedHomeBgmList = new HashSet<>(); - } - - if (this.unlockedHomeBgmList.addAll(getDefaultUnlockedHomeBgmIds())) { - save(); - } - - return this.unlockedHomeBgmList; - } - - private Set getDefaultUnlockedHomeBgmIds() { - return GameData.getHomeWorldBgmDataMap().int2ObjectEntrySet().stream() - .filter(e -> e.getValue().isDefaultUnlock()) - .map(Int2ObjectMap.Entry::getIntKey) - .collect(Collectors.toUnmodifiableSet()); - } - - // Same as Player.java addExpDirectly - public void addExp(Player player, int count) { - exp += count; - int reqExp = getExpRequired(level); - - while (exp >= reqExp && reqExp > 0) { - exp -= reqExp; - level += 1; - reqExp = getExpRequired(level); - - // Update client level and exp - player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); - } - - // Update client home - onOwnerLogin(player); - } - - private void checkAccumulatedResources(Player player) { - int clientTime = (int) ZonedDateTime.now().toEpochSecond(); - int owedRewards = 0; - - // Don't owe if previous update hasn't passed - if (nextUpdateTime > clientTime) { - return; - } - - if (lastUpdatedTime == 0) { - lastUpdatedTime = clientTime; - } - - // Calculate number of owed rewards - owedRewards = 1 + ((clientTime - nextUpdateTime) / 3600); - - // Ensure next update is at top of the hour - nextUpdateTime = (int) ZonedDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS).toEpochSecond(); - - // Get resources - var hourlyResources = getComfortResources(player); - var owedCoin = hourlyResources.get(0) * owedRewards; - var owedFetter = hourlyResources.get(1) * owedRewards; - - // Update stored amounts - storeResources(player, owedCoin, owedFetter); - } - - public void takeHomeCoin(Player player) { - player.getInventory().addItem(204, storedCoin); - storedCoin = 0; - save(); - player.getSession().send(new PacketHomeResourceNotify(player)); - } - - public void takeHomeFetter(Player player) { - List invitedAvatars = new ArrayList<>(); - - // Outdoors avatars - sceneMap.get(player.getCurrentRealmId() + 2000).getBlockItems().forEach((i, e) -> { - e.getDeployNPCList().forEach(id -> { - invitedAvatars.add(id.getAvatarId()); - }); - }); - - // Check as realm 5 inside is not in defaults and will be null - if (Objects.nonNull(sceneMap.get(player.getCurrentRealmId() + 2200))) { - // Indoors avatars - sceneMap.get(player.getCurrentRealmId() + 2200).getBlockItems().forEach((i, e) -> { - e.getDeployNPCList().forEach(id -> { - invitedAvatars.add(id.getAvatarId()); - }); - }); - } - - // Add exp to all avatars - invitedAvatars.forEach(id -> { - var avatar = player.getAvatars().getAvatarById(id); - player.getServer().getInventorySystem().upgradeAvatarFetterLevel(player, avatar, storedFetterExp); - }); - - storedFetterExp = 0; - save(); - player.getSession().send(new PacketHomeResourceNotify(player)); - } - - public void updateHourlyResources(Player player) { - int clientTime = (int) ZonedDateTime.now().toEpochSecond(); - - // Check if resources can update - if (nextUpdateTime > clientTime) { - return; - } - - // If no update has occurred before - if (lastUpdatedTime == 0) { - lastUpdatedTime = clientTime; - } - - // Update stored resources - storeResources(player, 0, 0); - lastUpdatedTime = clientTime; - nextUpdateTime = (int) ZonedDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS).toEpochSecond(); - save(); - - // Send packet - player.getSession().send(new PacketHomeResourceNotify(player)); - } - - public void storeResources(Player player, int owedCoin, int owedFetter) { - // Get max values - var maxCoin = getMaxCoin(level); - var maxFetter = getMaxFetter(level); - int newCoin = 0; - int newFetter = 0; - - // Check if resources are already max - if (storedCoin >= maxCoin && storedFetterExp >= maxFetter) { - return; - } - - // Get resources - var hourlyResources = getComfortResources(player); - - // Update home coin - if (storedCoin < maxCoin) { - // Check if owed or hourly - if (owedCoin == 0) { - newCoin = storedCoin + hourlyResources.get(0); - } else { - newCoin = storedCoin + owedCoin; - } - // Ensure max is not exceeded - storedCoin = (maxCoin >= newCoin) ? newCoin : maxCoin; - } - - // Update fetter exp - if (storedFetterExp < maxFetter) { - // Check if owed or hourly - if (owedFetter == 0) { - newFetter = storedFetterExp + hourlyResources.get(1); - } else { - newFetter = storedFetterExp + owedFetter; - } - // Ensure max is not exceeded - storedFetterExp = (maxFetter >= newFetter) ? newFetter : maxFetter; - } - - save(); - } - - public List getComfortResources(Player player) { - List allHomesComfort = new ArrayList<>(); - int highestComfort = 0; - // Use HomeComfortInfoNotify data since comfort value isn't stored - if (player.getRealmList() == null) { - return List.of(0, 0); - } - - // Calculate comfort value for each home - for (int moduleId : player.getRealmList()) { - var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); - allHomesComfort.add(homeScene.calComfort()); - } - - // Get highest comfort value - highestComfort = Collections.max(allHomesComfort); - - // Determine hourly resources - if (highestComfort >= 20000) { - return List.of(30, 5); - } else if (highestComfort >= 15000) { - return List.of(28, 5); - } else if (highestComfort >= 12000) { - return List.of(26, 5); - } else if (highestComfort >= 10000) { - return List.of(24, 4); - } else if (highestComfort >= 8000) { - return List.of(22, 4); - } else if (highestComfort >= 6000) { - return List.of(20, 4); - } else if (highestComfort >= 4500) { - return List.of(16, 3); - } else if (highestComfort >= 3000) { - return List.of(12, 3); - } else if (highestComfort >= 2000) { - return List.of(8, 2); - } else - return List.of(4, 2); - } - - private int getExpRequired(int level) { - HomeWorldLevelData levelData = GameData.getHomeWorldLevelDataMap().get(level); - return levelData != null ? levelData.getExp() : 0; - } - - public int getMaxCoin(int level) { - var levelData = GameData.getHomeWorldLevelDataMap().get(level); - return levelData != null ? levelData.getHomeCoinStoreLimit() : 0; - } - - public int getMaxFetter(int level) { - var levelData = GameData.getHomeWorldLevelDataMap().get(level); - return levelData != null ? levelData.getHomeFetterExpStoreLimit() : 0; - } -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.*; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.HomeWorldLevelData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity(value = "homes", useDiscriminator = false) +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class GameHome { + @Id String id; + + @Indexed(options = @IndexOptions(unique = true)) + long ownerUid; + + @Transient Player player; + + int level; + int exp; + int lastUpdatedTime; + int nextUpdateTime; + int storedCoin; + int storedFetterExp; + List furnitureMakeSlotItemList; + ConcurrentHashMap sceneMap; + Set unlockedHomeBgmList; + int enterHomeOption; + + public static GameHome getByUid(Integer uid) { + var home = DatabaseHelper.getHomeByUid(uid); + if (home == null) { + home = GameHome.create(uid); + } + return home; + } + + public static GameHome create(Integer uid) { + return GameHome.of() + .ownerUid(uid) + .level(1) + .sceneMap(new ConcurrentHashMap<>()) + .unlockedHomeBgmList(new HashSet<>()) + .build(); + } + + public void save() { + DatabaseHelper.saveHome(this); + } + + public HomeSceneItem getHomeSceneItem(int sceneId) { + return sceneMap.computeIfAbsent( + sceneId, + e -> { + var defaultItem = GameData.getHomeworldDefaultSaveData().get(sceneId); + if (defaultItem != null) { + Grasscutter.getLogger() + .info("Set player {} home {} to initial setting", ownerUid, sceneId); + return HomeSceneItem.parseFrom(defaultItem, sceneId); + } else { + // Realm res missing bricks account, use default realm data to allow main house + defaultItem = GameData.getHomeworldDefaultSaveData().get(2001); + return HomeSceneItem.parseFrom(defaultItem, sceneId); + } + }); + } + + public void onOwnerLogin(Player player) { + if (this.player == null) this.player = player; + player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); + player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); + player.getSession().send(new PacketHomeComfortInfoNotify(player)); + player.getSession().send(new PacketFurnitureCurModuleArrangeCountNotify()); + player.getSession().send(new PacketHomeMarkPointNotify(player)); + player.getSession().send(new PacketHomeAllUnlockedBgmIdListNotify(player)); + checkAccumulatedResources(player); + player.getSession().send(new PacketHomeResourceNotify(player)); + } + + // Tell the client the reward is claimed or realm unlocked + public void onClaimReward(Player player) { + player.getSession().send(new PacketPlayerHomeCompInfoNotify(player)); + } + + public Player getPlayer() { + if (this.player == null) + this.player = Grasscutter.getGameServer().getPlayerByUid((int) this.ownerUid, true); + return this.player; + } + + public HomeWorldLevelData getLevelData() { + return GameData.getHomeWorldLevelDataMap().get(level); + } + + public boolean addUnlockedHomeBgm(int homeBgmId) { + if (!getUnlockedHomeBgmList().add(homeBgmId)) return false; + + var player = this.getPlayer(); + player.sendPacket(new PacketHomeNewUnlockedBgmIdListNotify(homeBgmId)); + player.sendPacket(new PacketHomeAllUnlockedBgmIdListNotify(player)); + save(); + return true; + } + + public Set getUnlockedHomeBgmList() { + if (this.unlockedHomeBgmList == null) { + this.unlockedHomeBgmList = new HashSet<>(); + } + + if (this.unlockedHomeBgmList.addAll(getDefaultUnlockedHomeBgmIds())) { + save(); + } + + return this.unlockedHomeBgmList; + } + + private Set getDefaultUnlockedHomeBgmIds() { + return GameData.getHomeWorldBgmDataMap().int2ObjectEntrySet().stream() + .filter(e -> e.getValue().isDefaultUnlock()) + .map(Int2ObjectMap.Entry::getIntKey) + .collect(Collectors.toUnmodifiableSet()); + } + + // Same as Player.java addExpDirectly + public void addExp(Player player, int count) { + exp += count; + int reqExp = getExpRequired(level); + + while (exp >= reqExp && reqExp > 0) { + exp -= reqExp; + level += 1; + reqExp = getExpRequired(level); + + // Update client level and exp + player.getSession().send(new PacketHomeBasicInfoNotify(player, false)); + } + + // Update client home + onOwnerLogin(player); + } + + private void checkAccumulatedResources(Player player) { + int clientTime = (int) ZonedDateTime.now().toEpochSecond(); + int owedRewards = 0; + + // Don't owe if previous update hasn't passed + if (nextUpdateTime > clientTime) { + return; + } + + if (lastUpdatedTime == 0) { + lastUpdatedTime = clientTime; + } + + // Calculate number of owed rewards + owedRewards = 1 + ((clientTime - nextUpdateTime) / 3600); + + // Ensure next update is at top of the hour + nextUpdateTime = + (int) ZonedDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS).toEpochSecond(); + + // Get resources + var hourlyResources = getComfortResources(player); + var owedCoin = hourlyResources.get(0) * owedRewards; + var owedFetter = hourlyResources.get(1) * owedRewards; + + // Update stored amounts + storeResources(player, owedCoin, owedFetter); + } + + public void takeHomeCoin(Player player) { + player.getInventory().addItem(204, storedCoin); + storedCoin = 0; + save(); + player.getSession().send(new PacketHomeResourceNotify(player)); + } + + public void takeHomeFetter(Player player) { + List invitedAvatars = new ArrayList<>(); + + // Outdoors avatars + sceneMap + .get(player.getCurrentRealmId() + 2000) + .getBlockItems() + .forEach( + (i, e) -> { + e.getDeployNPCList() + .forEach( + id -> { + invitedAvatars.add(id.getAvatarId()); + }); + }); + + // Check as realm 5 inside is not in defaults and will be null + if (Objects.nonNull(sceneMap.get(player.getCurrentRealmId() + 2200))) { + // Indoors avatars + sceneMap + .get(player.getCurrentRealmId() + 2200) + .getBlockItems() + .forEach( + (i, e) -> { + e.getDeployNPCList() + .forEach( + id -> { + invitedAvatars.add(id.getAvatarId()); + }); + }); + } + + // Add exp to all avatars + invitedAvatars.forEach( + id -> { + var avatar = player.getAvatars().getAvatarById(id); + player + .getServer() + .getInventorySystem() + .upgradeAvatarFetterLevel(player, avatar, storedFetterExp); + }); + + storedFetterExp = 0; + save(); + player.getSession().send(new PacketHomeResourceNotify(player)); + } + + public void updateHourlyResources(Player player) { + int clientTime = (int) ZonedDateTime.now().toEpochSecond(); + + // Check if resources can update + if (nextUpdateTime > clientTime) { + return; + } + + // If no update has occurred before + if (lastUpdatedTime == 0) { + lastUpdatedTime = clientTime; + } + + // Update stored resources + storeResources(player, 0, 0); + lastUpdatedTime = clientTime; + nextUpdateTime = + (int) ZonedDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS).toEpochSecond(); + save(); + + // Send packet + player.getSession().send(new PacketHomeResourceNotify(player)); + } + + public void storeResources(Player player, int owedCoin, int owedFetter) { + // Get max values + var maxCoin = getMaxCoin(level); + var maxFetter = getMaxFetter(level); + int newCoin = 0; + int newFetter = 0; + + // Check if resources are already max + if (storedCoin >= maxCoin && storedFetterExp >= maxFetter) { + return; + } + + // Get resources + var hourlyResources = getComfortResources(player); + + // Update home coin + if (storedCoin < maxCoin) { + // Check if owed or hourly + if (owedCoin == 0) { + newCoin = storedCoin + hourlyResources.get(0); + } else { + newCoin = storedCoin + owedCoin; + } + // Ensure max is not exceeded + storedCoin = (maxCoin >= newCoin) ? newCoin : maxCoin; + } + + // Update fetter exp + if (storedFetterExp < maxFetter) { + // Check if owed or hourly + if (owedFetter == 0) { + newFetter = storedFetterExp + hourlyResources.get(1); + } else { + newFetter = storedFetterExp + owedFetter; + } + // Ensure max is not exceeded + storedFetterExp = (maxFetter >= newFetter) ? newFetter : maxFetter; + } + + save(); + } + + public List getComfortResources(Player player) { + List allHomesComfort = new ArrayList<>(); + int highestComfort = 0; + // Use HomeComfortInfoNotify data since comfort value isn't stored + if (player.getRealmList() == null) { + return List.of(0, 0); + } + + // Calculate comfort value for each home + for (int moduleId : player.getRealmList()) { + var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); + allHomesComfort.add(homeScene.calComfort()); + } + + // Get highest comfort value + highestComfort = Collections.max(allHomesComfort); + + // Determine hourly resources + if (highestComfort >= 20000) { + return List.of(30, 5); + } else if (highestComfort >= 15000) { + return List.of(28, 5); + } else if (highestComfort >= 12000) { + return List.of(26, 5); + } else if (highestComfort >= 10000) { + return List.of(24, 4); + } else if (highestComfort >= 8000) { + return List.of(22, 4); + } else if (highestComfort >= 6000) { + return List.of(20, 4); + } else if (highestComfort >= 4500) { + return List.of(16, 3); + } else if (highestComfort >= 3000) { + return List.of(12, 3); + } else if (highestComfort >= 2000) { + return List.of(8, 2); + } else return List.of(4, 2); + } + + private int getExpRequired(int level) { + HomeWorldLevelData levelData = GameData.getHomeWorldLevelDataMap().get(level); + return levelData != null ? levelData.getExp() : 0; + } + + public int getMaxCoin(int level) { + var levelData = GameData.getHomeWorldLevelDataMap().get(level); + return levelData != null ? levelData.getHomeCoinStoreLimit() : 0; + } + + public int getMaxFetter(int level) { + var levelData = GameData.getHomeWorldLevelDataMap().get(level); + return levelData != null ? levelData.getHomeFetterExpStoreLimit() : 0; + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeAnimalItem.java b/src/main/java/emu/grasscutter/game/home/HomeAnimalItem.java index 51440c10b..f20d20d95 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeAnimalItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeAnimalItem.java @@ -1,36 +1,35 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.HomeAnimalDataOuterClass; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -@Entity -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class HomeAnimalItem { - int furnitureId; - Position spawnPos; - Position spawnRot; - - public static HomeAnimalItem parseFrom(HomeAnimalDataOuterClass.HomeAnimalData homeAnimalData) { - return HomeAnimalItem.of() - .furnitureId(homeAnimalData.getFurnitureId()) - .spawnPos(new Position(homeAnimalData.getSpawnPos())) - .spawnRot(new Position(homeAnimalData.getSpawnRot())) - .build(); - } - - public HomeAnimalDataOuterClass.HomeAnimalData toProto() { - return HomeAnimalDataOuterClass.HomeAnimalData.newBuilder() - .setFurnitureId(furnitureId) - .setSpawnPos(spawnPos.toProto()) - .setSpawnRot(spawnRot.toProto()) - .build(); - } - -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.HomeAnimalDataOuterClass; +import emu.grasscutter.utils.Position; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class HomeAnimalItem { + int furnitureId; + Position spawnPos; + Position spawnRot; + + public static HomeAnimalItem parseFrom(HomeAnimalDataOuterClass.HomeAnimalData homeAnimalData) { + return HomeAnimalItem.of() + .furnitureId(homeAnimalData.getFurnitureId()) + .spawnPos(new Position(homeAnimalData.getSpawnPos())) + .spawnRot(new Position(homeAnimalData.getSpawnRot())) + .build(); + } + + public HomeAnimalDataOuterClass.HomeAnimalData toProto() { + return HomeAnimalDataOuterClass.HomeAnimalData.newBuilder() + .setFurnitureId(furnitureId) + .setSpawnPos(spawnPos.toProto()) + .setSpawnRot(spawnRot.toProto()) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeBlockItem.java b/src/main/java/emu/grasscutter/game/home/HomeBlockItem.java index 32c3b058f..0f7600d23 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeBlockItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeBlockItem.java @@ -1,86 +1,87 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import emu.grasscutter.data.binout.HomeworldDefaultSaveData; -import emu.grasscutter.net.proto.HomeBlockArrangementInfoOuterClass.HomeBlockArrangementInfo; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Entity -@Data -@Builder(builderMethodName = "of") -@FieldDefaults(level = AccessLevel.PRIVATE) -public class HomeBlockItem { - @Id - int blockId; - boolean unlocked; - List deployFurnitureList; - List persistentFurnitureList; - List deployAnimalList; - List deployNPCList; - - public static HomeBlockItem parseFrom(HomeworldDefaultSaveData.HomeBlock homeBlock) { - // create from default setting - return HomeBlockItem.of() - .blockId(homeBlock.getBlockId()) - .unlocked(homeBlock.getFurnitures() != null) - .deployFurnitureList( - homeBlock.getFurnitures() == null ? List.of() : - homeBlock.getFurnitures().stream() - .map(HomeFurnitureItem::parseFrom) - .toList()) - .persistentFurnitureList( - homeBlock.getPersistentFurnitures() == null ? List.of() : - homeBlock.getPersistentFurnitures().stream() - .map(HomeFurnitureItem::parseFrom) - .toList()) - .deployAnimalList(List.of()) - .deployNPCList(List.of()) - .build(); - } - - public void update(HomeBlockArrangementInfo homeBlockArrangementInfo) { - this.blockId = homeBlockArrangementInfo.getBlockId(); - - this.deployFurnitureList = homeBlockArrangementInfo.getDeployFurniureListList().stream() - .map(HomeFurnitureItem::parseFrom) - .toList(); - - this.persistentFurnitureList = homeBlockArrangementInfo.getPersistentFurnitureListList().stream() - .map(HomeFurnitureItem::parseFrom) - .toList(); - - this.deployAnimalList = homeBlockArrangementInfo.getDeployAnimalListList().stream() - .map(HomeAnimalItem::parseFrom) - .toList(); - - this.deployNPCList = homeBlockArrangementInfo.getDeployNpcListList().stream() - .map(HomeNPCItem::parseFrom) - .toList(); - } - - public int calComfort() { - return this.deployFurnitureList.stream() - .mapToInt(HomeFurnitureItem::getComfort) - .sum(); - } - - public HomeBlockArrangementInfo toProto() { - var proto = HomeBlockArrangementInfo.newBuilder() - .setBlockId(blockId) - .setIsUnlocked(unlocked) - .setComfortValue(calComfort()); - - this.deployFurnitureList.forEach(f -> proto.addDeployFurniureList(f.toProto())); - this.persistentFurnitureList.forEach(f -> proto.addPersistentFurnitureList(f.toProto())); - this.deployAnimalList.forEach(f -> proto.addDeployAnimalList(f.toProto())); - this.deployNPCList.forEach(f -> proto.addDeployNpcList(f.toProto())); - - return proto.build(); - } -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.grasscutter.data.binout.HomeworldDefaultSaveData; +import emu.grasscutter.net.proto.HomeBlockArrangementInfoOuterClass.HomeBlockArrangementInfo; +import java.util.List; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@Builder(builderMethodName = "of") +@FieldDefaults(level = AccessLevel.PRIVATE) +public class HomeBlockItem { + @Id int blockId; + boolean unlocked; + List deployFurnitureList; + List persistentFurnitureList; + List deployAnimalList; + List deployNPCList; + + public static HomeBlockItem parseFrom(HomeworldDefaultSaveData.HomeBlock homeBlock) { + // create from default setting + return HomeBlockItem.of() + .blockId(homeBlock.getBlockId()) + .unlocked(homeBlock.getFurnitures() != null) + .deployFurnitureList( + homeBlock.getFurnitures() == null + ? List.of() + : homeBlock.getFurnitures().stream().map(HomeFurnitureItem::parseFrom).toList()) + .persistentFurnitureList( + homeBlock.getPersistentFurnitures() == null + ? List.of() + : homeBlock.getPersistentFurnitures().stream() + .map(HomeFurnitureItem::parseFrom) + .toList()) + .deployAnimalList(List.of()) + .deployNPCList(List.of()) + .build(); + } + + public void update(HomeBlockArrangementInfo homeBlockArrangementInfo) { + this.blockId = homeBlockArrangementInfo.getBlockId(); + + this.deployFurnitureList = + homeBlockArrangementInfo.getDeployFurniureListList().stream() + .map(HomeFurnitureItem::parseFrom) + .toList(); + + this.persistentFurnitureList = + homeBlockArrangementInfo.getPersistentFurnitureListList().stream() + .map(HomeFurnitureItem::parseFrom) + .toList(); + + this.deployAnimalList = + homeBlockArrangementInfo.getDeployAnimalListList().stream() + .map(HomeAnimalItem::parseFrom) + .toList(); + + this.deployNPCList = + homeBlockArrangementInfo.getDeployNpcListList().stream() + .map(HomeNPCItem::parseFrom) + .toList(); + } + + public int calComfort() { + return this.deployFurnitureList.stream().mapToInt(HomeFurnitureItem::getComfort).sum(); + } + + public HomeBlockArrangementInfo toProto() { + var proto = + HomeBlockArrangementInfo.newBuilder() + .setBlockId(blockId) + .setIsUnlocked(unlocked) + .setComfortValue(calComfort()); + + this.deployFurnitureList.forEach(f -> proto.addDeployFurniureList(f.toProto())); + this.persistentFurnitureList.forEach(f -> proto.addPersistentFurnitureList(f.toProto())); + this.deployAnimalList.forEach(f -> proto.addDeployAnimalList(f.toProto())); + this.deployNPCList.forEach(f -> proto.addDeployNpcList(f.toProto())); + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java b/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java index 8ba5768f0..ebb87f0fc 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeFurnitureItem.java @@ -1,80 +1,82 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.HomeworldDefaultSaveData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.net.proto.HomeFurnitureDataOuterClass; -import emu.grasscutter.net.proto.HomeMarkPointFurnitureDataOuterClass; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -@Entity -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class HomeFurnitureItem { - int furnitureId; - int guid; - int parentFurnitureIndex; - Position spawnPos; - Position spawnRot; - int version; - - public static HomeFurnitureItem parseFrom(HomeFurnitureDataOuterClass.HomeFurnitureData homeFurnitureData) { - return HomeFurnitureItem.of() - .furnitureId(homeFurnitureData.getFurnitureId()) - .guid(homeFurnitureData.getGuid()) - .parentFurnitureIndex(homeFurnitureData.getParentFurnitureIndex()) - .spawnPos(new Position(homeFurnitureData.getSpawnPos())) - .spawnRot(new Position(homeFurnitureData.getSpawnRot())) - .version(homeFurnitureData.getVersion()) - .build(); - } - - public static HomeFurnitureItem parseFrom(HomeworldDefaultSaveData.HomeFurniture homeFurniture) { - return HomeFurnitureItem.of() - .furnitureId(homeFurniture.getId()) - .parentFurnitureIndex(1) - .spawnPos(homeFurniture.getPos() == null ? new Position() : homeFurniture.getPos()) - .spawnRot(homeFurniture.getRot() == null ? new Position() : homeFurniture.getRot()) - .build(); - } - - public HomeFurnitureDataOuterClass.HomeFurnitureData toProto() { - return HomeFurnitureDataOuterClass.HomeFurnitureData.newBuilder() - .setFurnitureId(furnitureId) - .setGuid(guid) - .setParentFurnitureIndex(parentFurnitureIndex) - .setSpawnPos(spawnPos.toProto()) - .setSpawnRot(spawnRot.toProto()) - .setVersion(version) - .build(); - } - - public HomeMarkPointFurnitureDataOuterClass.HomeMarkPointFurnitureData toMarkPointProto(int type) { - return HomeMarkPointFurnitureDataOuterClass.HomeMarkPointFurnitureData.newBuilder() - .setFurnitureId(furnitureId) - .setGuid(guid) - .setFurnitureType(type) - .setPos(spawnPos.toProto()) - // TODO NPC and farm - .build(); - } - - public ItemData getAsItem() { - return GameData.getItemDataMap().get(this.furnitureId); - } - - public int getComfort() { - var item = getAsItem(); - - if (item == null) { - return 0; - } - return item.getComfort(); - } -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.HomeworldDefaultSaveData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.net.proto.HomeFurnitureDataOuterClass; +import emu.grasscutter.net.proto.HomeMarkPointFurnitureDataOuterClass; +import emu.grasscutter.utils.Position; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class HomeFurnitureItem { + int furnitureId; + int guid; + int parentFurnitureIndex; + Position spawnPos; + Position spawnRot; + int version; + + public static HomeFurnitureItem parseFrom( + HomeFurnitureDataOuterClass.HomeFurnitureData homeFurnitureData) { + return HomeFurnitureItem.of() + .furnitureId(homeFurnitureData.getFurnitureId()) + .guid(homeFurnitureData.getGuid()) + .parentFurnitureIndex(homeFurnitureData.getParentFurnitureIndex()) + .spawnPos(new Position(homeFurnitureData.getSpawnPos())) + .spawnRot(new Position(homeFurnitureData.getSpawnRot())) + .version(homeFurnitureData.getVersion()) + .build(); + } + + public static HomeFurnitureItem parseFrom(HomeworldDefaultSaveData.HomeFurniture homeFurniture) { + return HomeFurnitureItem.of() + .furnitureId(homeFurniture.getId()) + .parentFurnitureIndex(1) + .spawnPos(homeFurniture.getPos() == null ? new Position() : homeFurniture.getPos()) + .spawnRot(homeFurniture.getRot() == null ? new Position() : homeFurniture.getRot()) + .build(); + } + + public HomeFurnitureDataOuterClass.HomeFurnitureData toProto() { + return HomeFurnitureDataOuterClass.HomeFurnitureData.newBuilder() + .setFurnitureId(furnitureId) + .setGuid(guid) + .setParentFurnitureIndex(parentFurnitureIndex) + .setSpawnPos(spawnPos.toProto()) + .setSpawnRot(spawnRot.toProto()) + .setVersion(version) + .build(); + } + + public HomeMarkPointFurnitureDataOuterClass.HomeMarkPointFurnitureData toMarkPointProto( + int type) { + return HomeMarkPointFurnitureDataOuterClass.HomeMarkPointFurnitureData.newBuilder() + .setFurnitureId(furnitureId) + .setGuid(guid) + .setFurnitureType(type) + .setPos(spawnPos.toProto()) + // TODO NPC and farm + .build(); + } + + public ItemData getAsItem() { + return GameData.getItemDataMap().get(this.furnitureId); + } + + public int getComfort() { + var item = getAsItem(); + + if (item == null) { + return 0; + } + return item.getComfort(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeNPCItem.java b/src/main/java/emu/grasscutter/game/home/HomeNPCItem.java index 8a538cba8..0090d6db4 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeNPCItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeNPCItem.java @@ -1,38 +1,38 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.HomeNpcDataOuterClass; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -@Entity -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -@Builder(builderMethodName = "of") -public class HomeNPCItem { - int avatarId; - Position spawnPos; - Position spawnRot; - int costumeId; - - public static HomeNPCItem parseFrom(HomeNpcDataOuterClass.HomeNpcData homeNpcData) { - return HomeNPCItem.of() - .avatarId(homeNpcData.getAvatarId()) - .spawnPos(new Position(homeNpcData.getSpawnPos())) - .spawnRot(new Position(homeNpcData.getSpawnRot())) - .costumeId(homeNpcData.getCostumeId()) - .build(); - } - - public HomeNpcDataOuterClass.HomeNpcData toProto() { - return HomeNpcDataOuterClass.HomeNpcData.newBuilder() - .setAvatarId(avatarId) - .setSpawnPos(spawnPos.toProto()) - .setSpawnRot(spawnRot.toProto()) - .setCostumeId(costumeId) - .build(); - } -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.HomeNpcDataOuterClass; +import emu.grasscutter.utils.Position; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +@Builder(builderMethodName = "of") +public class HomeNPCItem { + int avatarId; + Position spawnPos; + Position spawnRot; + int costumeId; + + public static HomeNPCItem parseFrom(HomeNpcDataOuterClass.HomeNpcData homeNpcData) { + return HomeNPCItem.of() + .avatarId(homeNpcData.getAvatarId()) + .spawnPos(new Position(homeNpcData.getSpawnPos())) + .spawnRot(new Position(homeNpcData.getSpawnRot())) + .costumeId(homeNpcData.getCostumeId()) + .build(); + } + + public HomeNpcDataOuterClass.HomeNpcData toProto() { + return HomeNpcDataOuterClass.HomeNpcData.newBuilder() + .setAvatarId(avatarId) + .setSpawnPos(spawnPos.toProto()) + .setSpawnRot(spawnRot.toProto()) + .setCostumeId(costumeId) + .build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java index 5be66efd9..86082b6b3 100644 --- a/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java +++ b/src/main/java/emu/grasscutter/game/home/HomeSceneItem.java @@ -1,97 +1,96 @@ -package emu.grasscutter.game.home; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.binout.HomeworldDefaultSaveData; -import emu.grasscutter.net.proto.HomeSceneArrangementInfoOuterClass.HomeSceneArrangementInfo; -import emu.grasscutter.utils.Position; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.Map; -import java.util.stream.Collectors; - -@Entity -@Data -@Builder(builderMethodName = "of") -@FieldDefaults(level = AccessLevel.PRIVATE) -public class HomeSceneItem { - @Id - int sceneId; - Map blockItems; - Position bornPos; - Position bornRot; - Position djinnPos; - int homeBgmId; - HomeFurnitureItem mainHouse; - int tmpVersion; - - public static HomeSceneItem parseFrom(HomeworldDefaultSaveData defaultItem, int sceneId) { - return HomeSceneItem.of() - .sceneId(sceneId) - .blockItems(defaultItem.getHomeBlockLists().stream() - .map(HomeBlockItem::parseFrom) - .collect(Collectors.toMap(HomeBlockItem::getBlockId, y -> y))) - .bornPos(defaultItem.getBornPos()) - .bornRot(defaultItem.getBornRot() == null ? new Position() : defaultItem.getBornRot()) - .djinnPos(defaultItem.getDjinPos() == null ? new Position() : defaultItem.getDjinPos()) - .mainHouse(defaultItem.getMainhouse() == null ? null : - HomeFurnitureItem.parseFrom(defaultItem.getMainhouse())) - .build(); - } - - public void update(HomeSceneArrangementInfo arrangementInfo) { - for (var blockItem : arrangementInfo.getBlockArrangementInfoListList()) { - var block = this.blockItems.get(blockItem.getBlockId()); - if (block == null) { - Grasscutter.getLogger().warn("Could not found the Home Block {}", blockItem.getBlockId()); - continue; - } - block.update(blockItem); - this.blockItems.put(blockItem.getBlockId(), block); - } - - this.bornPos = new Position(arrangementInfo.getBornPos()); - this.bornRot = new Position(arrangementInfo.getBornRot()); - this.djinnPos = new Position(arrangementInfo.getDjinnPos()); - this.homeBgmId = arrangementInfo.getBgmId(); - this.mainHouse = HomeFurnitureItem.parseFrom(arrangementInfo.getMainHouse()); - this.tmpVersion = arrangementInfo.getTmpVersion(); - } - - public int getRoomSceneId() { - if (mainHouse == null || mainHouse.getAsItem() == null) { - return 0; - } - return mainHouse.getAsItem().getRoomSceneId(); - } - - public int calComfort() { - return this.blockItems.values().stream() - .mapToInt(HomeBlockItem::calComfort) - .sum(); - } - - public HomeSceneArrangementInfo toProto() { - var proto = HomeSceneArrangementInfo.newBuilder(); - blockItems.values().forEach(b -> proto.addBlockArrangementInfoList(b.toProto())); - - proto.setComfortValue(calComfort()) - .setBornPos(bornPos.toProto()) - .setBornRot(bornRot.toProto()) - .setDjinnPos(djinnPos.toProto()) - .setIsSetBornPos(true) - .setSceneId(sceneId) - .setBgmId(homeBgmId) - .setTmpVersion(tmpVersion); - - if (mainHouse != null) { - proto.setMainHouse(mainHouse.toProto()); - } - return proto.build(); - } - -} +package emu.grasscutter.game.home; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.HomeworldDefaultSaveData; +import emu.grasscutter.net.proto.HomeSceneArrangementInfoOuterClass.HomeSceneArrangementInfo; +import emu.grasscutter.utils.Position; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Entity +@Data +@Builder(builderMethodName = "of") +@FieldDefaults(level = AccessLevel.PRIVATE) +public class HomeSceneItem { + @Id int sceneId; + Map blockItems; + Position bornPos; + Position bornRot; + Position djinnPos; + int homeBgmId; + HomeFurnitureItem mainHouse; + int tmpVersion; + + public static HomeSceneItem parseFrom(HomeworldDefaultSaveData defaultItem, int sceneId) { + return HomeSceneItem.of() + .sceneId(sceneId) + .blockItems( + defaultItem.getHomeBlockLists().stream() + .map(HomeBlockItem::parseFrom) + .collect(Collectors.toMap(HomeBlockItem::getBlockId, y -> y))) + .bornPos(defaultItem.getBornPos()) + .bornRot(defaultItem.getBornRot() == null ? new Position() : defaultItem.getBornRot()) + .djinnPos(defaultItem.getDjinPos() == null ? new Position() : defaultItem.getDjinPos()) + .mainHouse( + defaultItem.getMainhouse() == null + ? null + : HomeFurnitureItem.parseFrom(defaultItem.getMainhouse())) + .build(); + } + + public void update(HomeSceneArrangementInfo arrangementInfo) { + for (var blockItem : arrangementInfo.getBlockArrangementInfoListList()) { + var block = this.blockItems.get(blockItem.getBlockId()); + if (block == null) { + Grasscutter.getLogger().warn("Could not found the Home Block {}", blockItem.getBlockId()); + continue; + } + block.update(blockItem); + this.blockItems.put(blockItem.getBlockId(), block); + } + + this.bornPos = new Position(arrangementInfo.getBornPos()); + this.bornRot = new Position(arrangementInfo.getBornRot()); + this.djinnPos = new Position(arrangementInfo.getDjinnPos()); + this.homeBgmId = arrangementInfo.getBgmId(); + this.mainHouse = HomeFurnitureItem.parseFrom(arrangementInfo.getMainHouse()); + this.tmpVersion = arrangementInfo.getTmpVersion(); + } + + public int getRoomSceneId() { + if (mainHouse == null || mainHouse.getAsItem() == null) { + return 0; + } + return mainHouse.getAsItem().getRoomSceneId(); + } + + public int calComfort() { + return this.blockItems.values().stream().mapToInt(HomeBlockItem::calComfort).sum(); + } + + public HomeSceneArrangementInfo toProto() { + var proto = HomeSceneArrangementInfo.newBuilder(); + blockItems.values().forEach(b -> proto.addBlockArrangementInfoList(b.toProto())); + + proto + .setComfortValue(calComfort()) + .setBornPos(bornPos.toProto()) + .setBornRot(bornRot.toProto()) + .setDjinnPos(djinnPos.toProto()) + .setIsSetBornPos(true) + .setSceneId(sceneId) + .setBgmId(homeBgmId) + .setTmpVersion(tmpVersion); + + if (mainHouse != null) { + proto.setMainHouse(mainHouse.toProto()); + } + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/EquipInventoryTab.java b/src/main/java/emu/grasscutter/game/inventory/EquipInventoryTab.java index 5082f978e..00f35bd1c 100644 --- a/src/main/java/emu/grasscutter/game/inventory/EquipInventoryTab.java +++ b/src/main/java/emu/grasscutter/game/inventory/EquipInventoryTab.java @@ -1,39 +1,39 @@ -package emu.grasscutter.game.inventory; - -import java.util.HashSet; -import java.util.Set; - -public class EquipInventoryTab implements InventoryTab { - private final Set items; - private final int maxCapacity; - - public EquipInventoryTab(int maxCapacity) { - this.items = new HashSet(); - this.maxCapacity = maxCapacity; - } - - @Override - public GameItem getItemById(int id) { - return null; - } - - @Override - public void onAddItem(GameItem item) { - this.items.add(item); - } - - @Override - public void onRemoveItem(GameItem item) { - this.items.remove(item); - } - - @Override - public int getSize() { - return this.items.size(); - } - - @Override - public int getMaxCapacity() { - return this.maxCapacity; - } -} +package emu.grasscutter.game.inventory; + +import java.util.HashSet; +import java.util.Set; + +public class EquipInventoryTab implements InventoryTab { + private final Set items; + private final int maxCapacity; + + public EquipInventoryTab(int maxCapacity) { + this.items = new HashSet(); + this.maxCapacity = maxCapacity; + } + + @Override + public GameItem getItemById(int id) { + return null; + } + + @Override + public void onAddItem(GameItem item) { + this.items.add(item); + } + + @Override + public void onRemoveItem(GameItem item) { + this.items.remove(item); + } + + @Override + public int getSize() { + return this.items.size(); + } + + @Override + public int getMaxCapacity() { + return this.maxCapacity; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/EquipType.java b/src/main/java/emu/grasscutter/game/inventory/EquipType.java index a80a65a94..128fe6589 100644 --- a/src/main/java/emu/grasscutter/game/inventory/EquipType.java +++ b/src/main/java/emu/grasscutter/game/inventory/EquipType.java @@ -1,46 +1,47 @@ -package emu.grasscutter.game.inventory; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum EquipType { - EQUIP_NONE(0), - EQUIP_BRACER(1), - EQUIP_NECKLACE(2), - EQUIP_SHOES(3), - EQUIP_RING(4), - EQUIP_DRESS(5), - EQUIP_WEAPON(6); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - EquipType(int value) { - this.value = value; - } - - public static EquipType getTypeByValue(int value) { - return map.getOrDefault(value, EQUIP_NONE); - } - - public static EquipType getTypeByName(String name) { - return stringMap.getOrDefault(name, EQUIP_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum EquipType { + EQUIP_NONE(0), + EQUIP_BRACER(1), + EQUIP_NECKLACE(2), + EQUIP_SHOES(3), + EQUIP_RING(4), + EQUIP_DRESS(5), + EQUIP_WEAPON(6); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + EquipType(int value) { + this.value = value; + } + + public static EquipType getTypeByValue(int value) { + return map.getOrDefault(value, EQUIP_NONE); + } + + public static EquipType getTypeByName(String name) { + return stringMap.getOrDefault(name, EQUIP_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/GameItem.java b/src/main/java/emu/grasscutter/game/inventory/GameItem.java index 495ce6c38..58516e6d7 100644 --- a/src/main/java/emu/grasscutter/game/inventory/GameItem.java +++ b/src/main/java/emu/grasscutter/game/inventory/GameItem.java @@ -1,389 +1,363 @@ -package emu.grasscutter.game.inventory; - -import dev.morphia.annotations.*; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameDepot; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.data.excels.ReliquaryAffixData; -import emu.grasscutter.data.excels.ReliquaryMainPropData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.EquipOuterClass.Equip; -import emu.grasscutter.net.proto.FurnitureOuterClass.Furniture; -import emu.grasscutter.net.proto.ItemHintOuterClass.ItemHint; -import emu.grasscutter.net.proto.ItemOuterClass.Item; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.MaterialOuterClass.Material; -import emu.grasscutter.net.proto.ReliquaryOuterClass.Reliquary; -import emu.grasscutter.net.proto.SceneReliquaryInfoOuterClass.SceneReliquaryInfo; -import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo; -import emu.grasscutter.net.proto.WeaponOuterClass.Weapon; -import emu.grasscutter.utils.WeightedList; -import lombok.Getter; -import lombok.Setter; -import org.bson.types.ObjectId; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -@Entity(value = "items", useDiscriminator = false) -public class GameItem { - @Id - private ObjectId id; - @Indexed - private int ownerId; - @Getter - @Setter - private int itemId; - @Getter - @Setter - private int count; - - @Transient - @Getter - private long guid; // Player unique id - @Transient - @Getter - @Setter - private ItemData itemData; - - // Equips - @Getter - @Setter - private int level; - @Getter - @Setter - private int exp; - @Getter - @Setter - private int totalExp; - @Getter - @Setter - private int promoteLevel; - @Getter - @Setter - private boolean locked; - - // Weapon - @Getter - private List affixes; - @Getter - @Setter - private int refinement = 0; - - // Relic - @Getter - @Setter - private int mainPropId; - @Getter - private List appendPropIdList; - - @Getter - @Setter - private int equipCharacter; - @Transient - @Getter - @Setter - private int weaponEntityId; - - public GameItem() { - // Morphia only - } - - public GameItem(int itemId) { - this(GameData.getItemDataMap().get(itemId)); - } - - public GameItem(int itemId, int count) { - this(GameData.getItemDataMap().get(itemId), count); - } - - public GameItem(ItemParamData itemParamData) { - this(itemParamData.getId(), itemParamData.getCount()); - } - - public GameItem(ItemData data) { - this(data, 1); - } - - public GameItem(ItemData data, int count) { - this.itemId = data.getId(); - this.itemData = data; - - switch (data.getItemType()) { - case ITEM_VIRTUAL: - this.count = count; - break; - case ITEM_WEAPON: - this.count = 1; - this.level = Math.max(this.count, 1); // ?????????????????? - this.affixes = new ArrayList<>(2); - if (data.getSkillAffix() != null) { - for (int skillAffix : data.getSkillAffix()) { - if (skillAffix > 0) { - this.affixes.add(skillAffix); - } - } - } - break; - case ITEM_RELIQUARY: - this.count = 1; - this.level = 1; - this.appendPropIdList = new ArrayList<>(); - // Create main property - ReliquaryMainPropData mainPropData = GameDepot.getRandomRelicMainProp(data.getMainPropDepotId()); - if (mainPropData != null) { - this.mainPropId = mainPropData.getId(); - } - // Create extra stats - this.addAppendProps(data.getAppendPropNum()); - break; - default: - this.count = Math.min(count, data.getStackLimit()); - } - } - - public static int getMinPromoteLevel(int level) { - if (level > 80) { - return 6; - } else if (level > 70) { - return 5; - } else if (level > 60) { - return 4; - } else if (level > 50) { - return 3; - } else if (level > 40) { - return 2; - } else if (level > 20) { - return 1; - } - return 0; - } - - public int getOwnerId() { - return ownerId; - } - - public void setOwner(Player player) { - this.ownerId = player.getUid(); - this.guid = player.getNextGameGuid(); - } - - public ObjectId getObjectId() { - return id; - } - - public ItemType getItemType() { - return this.itemData.getItemType(); - } - - public int getEquipSlot() { - return this.getItemData().getEquipType().getValue(); - } - - public boolean isEquipped() { - return this.getEquipCharacter() > 0; - } - - public boolean isDestroyable() { - return !this.isLocked() && !this.isEquipped(); - } - - public void addAppendProp() { - if (this.appendPropIdList == null) { - this.appendPropIdList = new ArrayList<>(); - } - - if (this.appendPropIdList.size() < 4) { - this.addNewAppendProp(); - } else { - this.upgradeRandomAppendProp(); - } - } - - public void addAppendProps(int quantity) { - int num = Math.max(quantity, 0); - for (int i = 0; i < num; i++) { - this.addAppendProp(); - } - } - - private Set getAppendFightProperties() { - Set props = new HashSet<>(); - // Previously this would check no more than the first four affixes, however custom artifacts may not respect this order. - for (int appendPropId : this.appendPropIdList) { - ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId); - if (affixData != null) { - props.add(affixData.getFightProp()); - } - } - return props; - } - - private void addNewAppendProp() { - List affixList = GameDepot.getRelicAffixList(this.itemData.getAppendPropDepotId()); - - if (affixList == null) { - return; - } - - // Build blacklist - Dont add same stat as main/sub stat - Set blacklist = this.getAppendFightProperties(); - ReliquaryMainPropData mainPropData = GameData.getReliquaryMainPropDataMap().get(this.mainPropId); - if (mainPropData != null) { - blacklist.add(mainPropData.getFightProp()); - } - - // Build random list - WeightedList randomList = new WeightedList<>(); - for (ReliquaryAffixData affix : affixList) { - if (!blacklist.contains(affix.getFightProp())) { - randomList.add(affix.getWeight(), affix); - } - } - - if (randomList.size() == 0) { - return; - } - - // Add random stat - ReliquaryAffixData affixData = randomList.next(); - this.appendPropIdList.add(affixData.getId()); - } - - private void upgradeRandomAppendProp() { - List affixList = GameDepot.getRelicAffixList(this.itemData.getAppendPropDepotId()); - - if (affixList == null) { - return; - } - - // Build whitelist - Set whitelist = this.getAppendFightProperties(); - - // Build random list - WeightedList randomList = new WeightedList<>(); - for (ReliquaryAffixData affix : affixList) { - if (whitelist.contains(affix.getFightProp())) { - randomList.add(affix.getUpgradeWeight(), affix); - } - } - - // Add random stat - ReliquaryAffixData affixData = randomList.next(); - this.appendPropIdList.add(affixData.getId()); - } - - @PostLoad - public void onLoad() { - if (this.itemData == null) { - this.itemData = GameData.getItemDataMap().get(getItemId()); - } - } - - public void save() { - if (this.count > 0 && this.ownerId > 0) { - DatabaseHelper.saveItem(this); - } else if (this.getObjectId() != null) { - DatabaseHelper.deleteItem(this); - } - } - - public SceneWeaponInfo createSceneWeaponInfo() { - SceneWeaponInfo.Builder weaponInfo = SceneWeaponInfo.newBuilder() - .setEntityId(this.getWeaponEntityId()) - .setItemId(this.getItemId()) - .setGuid(this.getGuid()) - .setLevel(this.getLevel()) - .setGadgetId(this.getItemData().getGadgetId()) - .setAbilityInfo(AbilitySyncStateInfo.newBuilder().setIsInited(getAffixes().size() > 0)); - - if (this.getAffixes() != null && this.getAffixes().size() > 0) { - for (int affix : this.getAffixes()) { - weaponInfo.putAffixMap(affix, this.getRefinement()); - } - } - - return weaponInfo.build(); - } - - public SceneReliquaryInfo createSceneReliquaryInfo() { - SceneReliquaryInfo relicInfo = SceneReliquaryInfo.newBuilder() - .setItemId(this.getItemId()) - .setGuid(this.getGuid()) - .setLevel(this.getLevel()) - .build(); - - return relicInfo; - } - - public Weapon toWeaponProto() { - Weapon.Builder weapon = Weapon.newBuilder() - .setLevel(this.getLevel()) - .setExp(this.getExp()) - .setPromoteLevel(this.getPromoteLevel()); - - if (this.getAffixes() != null && this.getAffixes().size() > 0) { - for (int affix : this.getAffixes()) { - weapon.putAffixMap(affix, this.getRefinement()); - } - } - - return weapon.build(); - } - - public Reliquary toReliquaryProto() { - Reliquary.Builder relic = Reliquary.newBuilder() - .setLevel(this.getLevel()) - .setExp(this.getExp()) - .setPromoteLevel(this.getPromoteLevel()) - .setMainPropId(this.getMainPropId()) - .addAllAppendPropIdList(this.getAppendPropIdList()); - - return relic.build(); - } - - public Item toProto() { - Item.Builder proto = Item.newBuilder() - .setGuid(this.getGuid()) - .setItemId(this.getItemId()); - - switch (getItemType()) { - case ITEM_WEAPON: - Weapon weapon = this.toWeaponProto(); - proto.setEquip(Equip.newBuilder().setWeapon(weapon).setIsLocked(this.isLocked()).build()); - break; - case ITEM_RELIQUARY: - Reliquary relic = this.toReliquaryProto(); - proto.setEquip(Equip.newBuilder().setReliquary(relic).setIsLocked(this.isLocked()).build()); - break; - case ITEM_FURNITURE: - Furniture furniture = Furniture.newBuilder() - .setCount(getCount()) - .build(); - proto.setFurniture(furniture); - break; - default: - Material material = Material.newBuilder() - .setCount(getCount()) - .build(); - proto.setMaterial(material); - break; - } - - return proto.build(); - } - - public ItemHint toItemHintProto() { - return ItemHint.newBuilder().setItemId(getItemId()).setCount(getCount()).setIsNew(false).build(); - } - - public ItemParam toItemParam() { - return ItemParam.newBuilder().setItemId(this.getItemId()).setCount(this.getCount()).build(); - } -} +package emu.grasscutter.game.inventory; + +import dev.morphia.annotations.*; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.ReliquaryAffixData; +import emu.grasscutter.data.excels.ReliquaryMainPropData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.EquipOuterClass.Equip; +import emu.grasscutter.net.proto.FurnitureOuterClass.Furniture; +import emu.grasscutter.net.proto.ItemHintOuterClass.ItemHint; +import emu.grasscutter.net.proto.ItemOuterClass.Item; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.MaterialOuterClass.Material; +import emu.grasscutter.net.proto.ReliquaryOuterClass.Reliquary; +import emu.grasscutter.net.proto.SceneReliquaryInfoOuterClass.SceneReliquaryInfo; +import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo; +import emu.grasscutter.net.proto.WeaponOuterClass.Weapon; +import emu.grasscutter.utils.WeightedList; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.Getter; +import lombok.Setter; +import org.bson.types.ObjectId; + +@Entity(value = "items", useDiscriminator = false) +public class GameItem { + @Id private ObjectId id; + @Indexed private int ownerId; + @Getter @Setter private int itemId; + @Getter @Setter private int count; + + @Transient @Getter private long guid; // Player unique id + @Transient @Getter @Setter private ItemData itemData; + + // Equips + @Getter @Setter private int level; + @Getter @Setter private int exp; + @Getter @Setter private int totalExp; + @Getter @Setter private int promoteLevel; + @Getter @Setter private boolean locked; + + // Weapon + @Getter private List affixes; + @Getter @Setter private int refinement = 0; + + // Relic + @Getter @Setter private int mainPropId; + @Getter private List appendPropIdList; + + @Getter @Setter private int equipCharacter; + @Transient @Getter @Setter private int weaponEntityId; + + public GameItem() { + // Morphia only + } + + public GameItem(int itemId) { + this(GameData.getItemDataMap().get(itemId)); + } + + public GameItem(int itemId, int count) { + this(GameData.getItemDataMap().get(itemId), count); + } + + public GameItem(ItemParamData itemParamData) { + this(itemParamData.getId(), itemParamData.getCount()); + } + + public GameItem(ItemData data) { + this(data, 1); + } + + public GameItem(ItemData data, int count) { + this.itemId = data.getId(); + this.itemData = data; + + switch (data.getItemType()) { + case ITEM_VIRTUAL: + this.count = count; + break; + case ITEM_WEAPON: + this.count = 1; + this.level = Math.max(this.count, 1); // ?????????????????? + this.affixes = new ArrayList<>(2); + if (data.getSkillAffix() != null) { + for (int skillAffix : data.getSkillAffix()) { + if (skillAffix > 0) { + this.affixes.add(skillAffix); + } + } + } + break; + case ITEM_RELIQUARY: + this.count = 1; + this.level = 1; + this.appendPropIdList = new ArrayList<>(); + // Create main property + ReliquaryMainPropData mainPropData = + GameDepot.getRandomRelicMainProp(data.getMainPropDepotId()); + if (mainPropData != null) { + this.mainPropId = mainPropData.getId(); + } + // Create extra stats + this.addAppendProps(data.getAppendPropNum()); + break; + default: + this.count = Math.min(count, data.getStackLimit()); + } + } + + public static int getMinPromoteLevel(int level) { + if (level > 80) { + return 6; + } else if (level > 70) { + return 5; + } else if (level > 60) { + return 4; + } else if (level > 50) { + return 3; + } else if (level > 40) { + return 2; + } else if (level > 20) { + return 1; + } + return 0; + } + + public int getOwnerId() { + return ownerId; + } + + public void setOwner(Player player) { + this.ownerId = player.getUid(); + this.guid = player.getNextGameGuid(); + } + + public ObjectId getObjectId() { + return id; + } + + public ItemType getItemType() { + return this.itemData.getItemType(); + } + + public int getEquipSlot() { + return this.getItemData().getEquipType().getValue(); + } + + public boolean isEquipped() { + return this.getEquipCharacter() > 0; + } + + public boolean isDestroyable() { + return !this.isLocked() && !this.isEquipped(); + } + + public void addAppendProp() { + if (this.appendPropIdList == null) { + this.appendPropIdList = new ArrayList<>(); + } + + if (this.appendPropIdList.size() < 4) { + this.addNewAppendProp(); + } else { + this.upgradeRandomAppendProp(); + } + } + + public void addAppendProps(int quantity) { + int num = Math.max(quantity, 0); + for (int i = 0; i < num; i++) { + this.addAppendProp(); + } + } + + private Set getAppendFightProperties() { + Set props = new HashSet<>(); + // Previously this would check no more than the first four affixes, however custom artifacts may + // not respect this order. + for (int appendPropId : this.appendPropIdList) { + ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId); + if (affixData != null) { + props.add(affixData.getFightProp()); + } + } + return props; + } + + private void addNewAppendProp() { + List affixList = + GameDepot.getRelicAffixList(this.itemData.getAppendPropDepotId()); + + if (affixList == null) { + return; + } + + // Build blacklist - Dont add same stat as main/sub stat + Set blacklist = this.getAppendFightProperties(); + ReliquaryMainPropData mainPropData = + GameData.getReliquaryMainPropDataMap().get(this.mainPropId); + if (mainPropData != null) { + blacklist.add(mainPropData.getFightProp()); + } + + // Build random list + WeightedList randomList = new WeightedList<>(); + for (ReliquaryAffixData affix : affixList) { + if (!blacklist.contains(affix.getFightProp())) { + randomList.add(affix.getWeight(), affix); + } + } + + if (randomList.size() == 0) { + return; + } + + // Add random stat + ReliquaryAffixData affixData = randomList.next(); + this.appendPropIdList.add(affixData.getId()); + } + + private void upgradeRandomAppendProp() { + List affixList = + GameDepot.getRelicAffixList(this.itemData.getAppendPropDepotId()); + + if (affixList == null) { + return; + } + + // Build whitelist + Set whitelist = this.getAppendFightProperties(); + + // Build random list + WeightedList randomList = new WeightedList<>(); + for (ReliquaryAffixData affix : affixList) { + if (whitelist.contains(affix.getFightProp())) { + randomList.add(affix.getUpgradeWeight(), affix); + } + } + + // Add random stat + ReliquaryAffixData affixData = randomList.next(); + this.appendPropIdList.add(affixData.getId()); + } + + @PostLoad + public void onLoad() { + if (this.itemData == null) { + this.itemData = GameData.getItemDataMap().get(getItemId()); + } + } + + public void save() { + if (this.count > 0 && this.ownerId > 0) { + DatabaseHelper.saveItem(this); + } else if (this.getObjectId() != null) { + DatabaseHelper.deleteItem(this); + } + } + + public SceneWeaponInfo createSceneWeaponInfo() { + SceneWeaponInfo.Builder weaponInfo = + SceneWeaponInfo.newBuilder() + .setEntityId(this.getWeaponEntityId()) + .setItemId(this.getItemId()) + .setGuid(this.getGuid()) + .setLevel(this.getLevel()) + .setGadgetId(this.getItemData().getGadgetId()) + .setAbilityInfo(AbilitySyncStateInfo.newBuilder().setIsInited(getAffixes().size() > 0)); + + if (this.getAffixes() != null && this.getAffixes().size() > 0) { + for (int affix : this.getAffixes()) { + weaponInfo.putAffixMap(affix, this.getRefinement()); + } + } + + return weaponInfo.build(); + } + + public SceneReliquaryInfo createSceneReliquaryInfo() { + SceneReliquaryInfo relicInfo = + SceneReliquaryInfo.newBuilder() + .setItemId(this.getItemId()) + .setGuid(this.getGuid()) + .setLevel(this.getLevel()) + .build(); + + return relicInfo; + } + + public Weapon toWeaponProto() { + Weapon.Builder weapon = + Weapon.newBuilder() + .setLevel(this.getLevel()) + .setExp(this.getExp()) + .setPromoteLevel(this.getPromoteLevel()); + + if (this.getAffixes() != null && this.getAffixes().size() > 0) { + for (int affix : this.getAffixes()) { + weapon.putAffixMap(affix, this.getRefinement()); + } + } + + return weapon.build(); + } + + public Reliquary toReliquaryProto() { + Reliquary.Builder relic = + Reliquary.newBuilder() + .setLevel(this.getLevel()) + .setExp(this.getExp()) + .setPromoteLevel(this.getPromoteLevel()) + .setMainPropId(this.getMainPropId()) + .addAllAppendPropIdList(this.getAppendPropIdList()); + + return relic.build(); + } + + public Item toProto() { + Item.Builder proto = Item.newBuilder().setGuid(this.getGuid()).setItemId(this.getItemId()); + + switch (getItemType()) { + case ITEM_WEAPON: + Weapon weapon = this.toWeaponProto(); + proto.setEquip(Equip.newBuilder().setWeapon(weapon).setIsLocked(this.isLocked()).build()); + break; + case ITEM_RELIQUARY: + Reliquary relic = this.toReliquaryProto(); + proto.setEquip(Equip.newBuilder().setReliquary(relic).setIsLocked(this.isLocked()).build()); + break; + case ITEM_FURNITURE: + Furniture furniture = Furniture.newBuilder().setCount(getCount()).build(); + proto.setFurniture(furniture); + break; + default: + Material material = Material.newBuilder().setCount(getCount()).build(); + proto.setMaterial(material); + break; + } + + return proto.build(); + } + + public ItemHint toItemHintProto() { + return ItemHint.newBuilder() + .setItemId(getItemId()) + .setCount(getCount()) + .setIsNew(false) + .build(); + } + + public ItemParam toItemParam() { + return ItemParam.newBuilder().setItemId(this.getItemId()).setCount(this.getCount()).build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index ed275838a..2b813b408 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -1,520 +1,558 @@ -package emu.grasscutter.game.inventory; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.avatar.AvatarStorage; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.props.ItemUseAction.UseItemParams; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify; -import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; -import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify; -import emu.grasscutter.server.packet.send.PacketStoreItemDelNotify; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; - -public class Inventory extends BasePlayerManager implements Iterable { - private final Long2ObjectMap store; - private final Int2ObjectMap inventoryTypes; - - public Inventory(Player player) { - super(player); - - this.store = new Long2ObjectOpenHashMap<>(); - this.inventoryTypes = new Int2ObjectOpenHashMap<>(); - - this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(INVENTORY_LIMITS.weapons)); - this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(INVENTORY_LIMITS.relics)); - this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(INVENTORY_LIMITS.materials)); - this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(INVENTORY_LIMITS.furniture)); - } - - public AvatarStorage getAvatarStorage() { - return this.getPlayer().getAvatars(); - } - - public Long2ObjectMap getItems() { - return store; - } - - public Int2ObjectMap getInventoryTypes() { - return inventoryTypes; - } - - public InventoryTab getInventoryTab(ItemType type) { - return getInventoryTypes().get(type.getValue()); - } - - public void createInventoryTab(ItemType type, InventoryTab tab) { - this.getInventoryTypes().put(type.getValue(), tab); - } - - public GameItem getItemByGuid(long id) { - return this.getItems().get(id); - } - - public boolean addItem(int itemId) { - return addItem(itemId, 1); - } - - public boolean addItem(int itemId, int count) { - return addItem(itemId, count, null); - } - - public boolean addItem(int itemId, int count, ActionReason reason) { - ItemData itemData = GameData.getItemDataMap().get(itemId); - - if (itemData == null) { - return false; - } - - GameItem item = new GameItem(itemData, count); - - return addItem(item, reason); - } - - public boolean addItem(GameItem item) { - GameItem result = putItem(item); - - if (result != null) { - getPlayer().getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, result.getItemId(), result.getCount()); - getPlayer().sendPacket(new PacketStoreItemChangeNotify(result)); - return true; - } - - return false; - } - - public boolean addItem(GameItem item, ActionReason reason) { - boolean result = addItem(item); - - if (result && reason != null) { - getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason)); - } - - return result; - } - - public boolean addItem(GameItem item, ActionReason reason, boolean forceNotify) { - boolean result = addItem(item); - - if (reason != null && (forceNotify || result)) { - getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason)); - } - - return result; - } - - public boolean addItem(ItemParamData itemParam) { - return addItem(itemParam, null); - } - - public boolean addItem(ItemParamData itemParam, ActionReason reason) { - if (itemParam == null) return false; - return addItem(itemParam.getId(), itemParam.getCount(), reason); - } - - public void addItems(Collection items) { - this.addItems(items, null); - } - - - public void addItems(Collection items, ActionReason reason) { - List changedItems = new ArrayList<>(); - for (var item : items) { - if (item.getItemId() == 0) continue; - GameItem result = null; - try { - // putItem might throws exception - // ignore that exception and continue - result = putItem(item); - } catch (Exception e) { - e.printStackTrace(); - } - if (result != null) { - getPlayer().getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, result.getItemId(), result.getCount()); - changedItems.add(result); - } - } - if (changedItems.size() == 0) { - return; - } - if (reason != null) { - getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason)); - } - getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); - } - - public void addItemParams(Collection items) { - addItems(items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), null); - } - - public void addItemParamDatas(Collection items) { - addItemParamDatas(items, null); - } - - public void addItemParamDatas(Collection items, ActionReason reason) { - addItems(items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), reason); - } - - private synchronized GameItem putItem(GameItem item) { - // Dont add items that dont have a valid item definition. - var data = item.getItemData(); - if (data == null) return null; - - if (data.isUseOnGain()) { - var params = new UseItemParams(this.player, data.getUseTarget()); - params.usedItemId = data.getId(); - this.player.getServer().getInventorySystem().useItemDirect(data, params); - return null; - } - - // Add item to inventory store - ItemType type = item.getItemData().getItemType(); - InventoryTab tab = getInventoryTab(type); - - // Add - switch (type) { - case ITEM_WEAPON: - case ITEM_RELIQUARY: - if (tab.getSize() >= tab.getMaxCapacity()) { - return null; - } - // Duplicates cause problems - item.setCount(Math.max(item.getCount(), 1)); - // Adds to inventory - this.putItem(item, tab); - // Set ownership and save to db - item.save(); - return item; - case ITEM_VIRTUAL: - // Handle - this.addVirtualItem(item.getItemId(), item.getCount()); - return item; - default: - switch (item.getItemData().getMaterialType()) { - case MATERIAL_AVATAR: - case MATERIAL_FLYCLOAK: - case MATERIAL_COSTUME: - case MATERIAL_NAMECARD: - Grasscutter.getLogger().warn("Attempted to add a " + item.getItemData().getMaterialType().name() + " to inventory, but item definition lacks isUseOnGain. This indicates a Resources error."); - return null; - default: - if (tab == null) { - return null; - } - GameItem existingItem = tab.getItemById(item.getItemId()); - if (existingItem == null) { - // Item type didnt exist before, we will add it to main inventory map if there is enough space - if (tab.getSize() >= tab.getMaxCapacity()) { - return null; - } - this.putItem(item, tab); - // Set ownership and save to db - item.save(); - return item; - } else { - // Add count - existingItem.setCount(Math.min(existingItem.getCount() + item.getCount(), item.getItemData().getStackLimit())); - existingItem.save(); - return existingItem; - } - } - } - } - - private synchronized void putItem(GameItem item, InventoryTab tab) { - this.player.getCodex().checkAddedItem(item); - // Set owner and guid FIRST! - item.setOwner(this.player); - // Put in item store - getItems().put(item.getGuid(), item); - if (tab != null) { - tab.onAddItem(item); - } - } - - private void addVirtualItem(int itemId, int count) { - switch (itemId) { - case 101 -> // Character exp - this.player.getTeamManager().getActiveTeam().stream().map(e -> e.getAvatar()).forEach( - avatar -> this.player.getServer().getInventorySystem().upgradeAvatar(this.player, avatar, count) - ); - case 102 -> // Adventure exp - this.player.addExpDirectly(count); - case 105 -> // Companionship exp - this.player.getTeamManager().getActiveTeam().stream().map(e -> e.getAvatar()).forEach( - avatar -> this.player.getServer().getInventorySystem().upgradeAvatarFetterLevel(this.player, avatar, count * (this.player.isInMultiplayer() ? 2 : 1)) - ); - case 106 -> // Resin - this.player.getResinManager().addResin(count); - case 107 -> // Legendary Key - this.player.addLegendaryKey(count); - case 121 -> // Home exp - this.player.getHome().addExp(this.player, count); - case 201 -> // Primogem - this.player.setPrimogems(this.player.getPrimogems() + count); - case 202 -> // Mora - this.player.setMora(this.player.getMora() + count); - case 203 -> // Genesis Crystals - this.player.setCrystals(this.player.getCrystals() + count); - case 204 -> // Home Coin - this.player.setHomeCoin(this.player.getHomeCoin() + count); - } - } - - private GameItem payVirtualItem(int itemId, int count) { - switch (itemId) { - case 201 -> // Primogem - player.setPrimogems(player.getPrimogems() - count); - case 202 -> // Mora - player.setMora(player.getMora() - count); - case 203 -> // Genesis Crystals - player.setCrystals(player.getCrystals() - count); - case 106 -> // Resin - player.getResinManager().useResin(count); - case 107 -> // LegendaryKey - player.useLegendaryKey(count); - case 204 -> // Home Coin - player.setHomeCoin(player.getHomeCoin() - count); - default -> { - var gameItem = getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); - removeItem(gameItem, count); - return gameItem; - } - } - return null; - } - - private int getVirtualItemCount(int itemId) { - switch (itemId) { - case 201: // Primogem - return this.player.getPrimogems(); - case 202: // Mora - return this.player.getMora(); - case 203: // Genesis Crystals - return this.player.getCrystals(); - case 106: // Resin - return this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); - case 107: // Legendary Key - return this.player.getProperty(PlayerProperty.PROP_PLAYER_LEGENDARY_KEY); - case 204: // Home Coin - return this.player.getHomeCoin(); - default: - GameItem item = getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); // What if we ever want to operate on weapons/relics/furniture? :S - return (item == null) ? 0 : item.getCount(); - } - } - - public synchronized boolean payItem(int id, int count) { - if (this.getVirtualItemCount(id) < count) - return false; - this.payVirtualItem(id, count); - return true; - } - - public boolean payItem(ItemParamData costItem) { - return this.payItem(costItem.getId(), costItem.getCount()); - } - - public boolean payItems(ItemParamData[] costItems) { - return this.payItems(costItems, 1, null); - } - - public boolean payItems(ItemParamData[] costItems, int quantity) { - return this.payItems(costItems, quantity, null); - } - - public synchronized boolean payItems(ItemParamData[] costItems, int quantity, ActionReason reason) { - // Make sure player has requisite items - for (ItemParamData cost : costItems) - if (this.getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) - return false; - // All costs are satisfied, now remove them all - for (ItemParamData cost : costItems) { - this.payVirtualItem(cost.getId(), cost.getCount() * quantity); - } - - if (reason != null) { // Do we need these? - // getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason)); - } - // getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); - return true; - } - - public boolean payItems(Iterable costItems) { - return this.payItems(costItems, 1, null); - } - - public boolean payItems(Iterable costItems, int quantity) { - return this.payItems(costItems, quantity, null); - } - - public synchronized boolean payItems(Iterable costItems, int quantity, ActionReason reason) { - // Make sure player has requisite items - for (ItemParamData cost : costItems) - if (getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) - return false; - // All costs are satisfied, now remove them all - costItems.forEach(cost -> this.payVirtualItem(cost.getId(), cost.getCount() * quantity)); - //TODO:handle the reason(need to send certain package) - return true; - } - - public void removeItems(List items) { - // TODO Bulk delete - for (GameItem item : items) { - this.removeItem(item, item.getCount()); - } - } - - public boolean removeItem(long guid) { - return removeItem(guid, 1); - } - - public synchronized boolean removeItem(long guid, int count) { - GameItem item = this.getItemByGuid(guid); - - if (item == null) { - return false; - } - - return removeItem(item, count); - } - - public synchronized boolean removeItem(GameItem item) { - return removeItem(item, item.getCount()); - } - - public synchronized boolean removeItem(GameItem item, int count) { - // Sanity check - if (count <= 0 || item == null) { - return false; - } - - if (item.getItemData().isEquip()) { - item.setCount(0); - } else { - item.setCount(item.getCount() - count); - } - - if (item.getCount() <= 0) { - // Remove from inventory tab too - InventoryTab tab = null; - if (item.getItemData() != null) { - tab = getInventoryTab(item.getItemData().getItemType()); - } - // Remove if less than 0 - deleteItem(item, tab); - // - getPlayer().sendPacket(new PacketStoreItemDelNotify(item)); - } else { - getPlayer().sendPacket(new PacketStoreItemChangeNotify(item)); - } - - // Battle pass trigger - int removeCount = Math.min(count, item.getCount()); - getPlayer().getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_COST_MATERIAL, item.getItemId(), removeCount); - - // Update in db - item.save(); - - // Returns true on success - return true; - } - - private void deleteItem(GameItem item, InventoryTab tab) { - getItems().remove(item.getGuid()); - if (tab != null) { - tab.onRemoveItem(item); - } - } - - public boolean equipItem(long avatarGuid, long equipGuid) { - Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid); - GameItem item = this.getItemByGuid(equipGuid); - - if (avatar != null && item != null) { - return avatar.equipItem(item, true); - } - - return false; - } - - public boolean unequipItem(long avatarGuid, int slot) { - Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid); - EquipType equipType = EquipType.getTypeByValue(slot); - - if (avatar != null && equipType != EquipType.EQUIP_WEAPON) { - if (avatar.unequipItem(equipType)) { - getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(avatar, equipType)); - avatar.recalcStats(); - return true; - } - } - - return false; - } - - public void loadFromDatabase() { - List items = DatabaseHelper.getInventoryItems(getPlayer()); - - for (GameItem item : items) { - // Should never happen - if (item.getObjectId() == null) { - continue; - } - - ItemData itemData = GameData.getItemDataMap().get(item.getItemId()); - if (itemData == null) { - continue; - } - - item.setItemData(itemData); - - InventoryTab tab = null; - if (item.getItemData() != null) { - tab = getInventoryTab(item.getItemData().getItemType()); - } - - putItem(item, tab); - - // Equip to a character if possible - if (item.isEquipped()) { - Avatar avatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter()); - boolean hasEquipped = false; - - if (avatar != null) { - hasEquipped = avatar.equipItem(item, false); - } - - if (!hasEquipped) { - item.setEquipCharacter(0); - item.save(); - } - } - } - } - - @Override - public Iterator iterator() { - return this.getItems().values().iterator(); - } -} +package emu.grasscutter.game.inventory; + +import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.avatar.AvatarStorage; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.ItemUseAction.UseItemParams; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify; +import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; +import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify; +import emu.grasscutter.server.packet.send.PacketStoreItemDelNotify; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +public class Inventory extends BasePlayerManager implements Iterable { + private final Long2ObjectMap store; + private final Int2ObjectMap inventoryTypes; + + public Inventory(Player player) { + super(player); + + this.store = new Long2ObjectOpenHashMap<>(); + this.inventoryTypes = new Int2ObjectOpenHashMap<>(); + + this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(INVENTORY_LIMITS.weapons)); + this.createInventoryTab( + ItemType.ITEM_RELIQUARY, new EquipInventoryTab(INVENTORY_LIMITS.relics)); + this.createInventoryTab( + ItemType.ITEM_MATERIAL, new MaterialInventoryTab(INVENTORY_LIMITS.materials)); + this.createInventoryTab( + ItemType.ITEM_FURNITURE, new MaterialInventoryTab(INVENTORY_LIMITS.furniture)); + } + + public AvatarStorage getAvatarStorage() { + return this.getPlayer().getAvatars(); + } + + public Long2ObjectMap getItems() { + return store; + } + + public Int2ObjectMap getInventoryTypes() { + return inventoryTypes; + } + + public InventoryTab getInventoryTab(ItemType type) { + return getInventoryTypes().get(type.getValue()); + } + + public void createInventoryTab(ItemType type, InventoryTab tab) { + this.getInventoryTypes().put(type.getValue(), tab); + } + + public GameItem getItemByGuid(long id) { + return this.getItems().get(id); + } + + public boolean addItem(int itemId) { + return addItem(itemId, 1); + } + + public boolean addItem(int itemId, int count) { + return addItem(itemId, count, null); + } + + public boolean addItem(int itemId, int count, ActionReason reason) { + ItemData itemData = GameData.getItemDataMap().get(itemId); + + if (itemData == null) { + return false; + } + + GameItem item = new GameItem(itemData, count); + + return addItem(item, reason); + } + + public boolean addItem(GameItem item) { + GameItem result = putItem(item); + + if (result != null) { + getPlayer() + .getBattlePassManager() + .triggerMission( + WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, + result.getItemId(), + result.getCount()); + getPlayer().sendPacket(new PacketStoreItemChangeNotify(result)); + return true; + } + + return false; + } + + public boolean addItem(GameItem item, ActionReason reason) { + boolean result = addItem(item); + + if (result && reason != null) { + getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason)); + } + + return result; + } + + public boolean addItem(GameItem item, ActionReason reason, boolean forceNotify) { + boolean result = addItem(item); + + if (reason != null && (forceNotify || result)) { + getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason)); + } + + return result; + } + + public boolean addItem(ItemParamData itemParam) { + return addItem(itemParam, null); + } + + public boolean addItem(ItemParamData itemParam, ActionReason reason) { + if (itemParam == null) return false; + return addItem(itemParam.getId(), itemParam.getCount(), reason); + } + + public void addItems(Collection items) { + this.addItems(items, null); + } + + public void addItems(Collection items, ActionReason reason) { + List changedItems = new ArrayList<>(); + for (var item : items) { + if (item.getItemId() == 0) continue; + GameItem result = null; + try { + // putItem might throws exception + // ignore that exception and continue + result = putItem(item); + } catch (Exception e) { + e.printStackTrace(); + } + if (result != null) { + getPlayer() + .getBattlePassManager() + .triggerMission( + WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, + result.getItemId(), + result.getCount()); + changedItems.add(result); + } + } + if (changedItems.size() == 0) { + return; + } + if (reason != null) { + getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason)); + } + getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); + } + + public void addItemParams(Collection items) { + addItems( + items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), + null); + } + + public void addItemParamDatas(Collection items) { + addItemParamDatas(items, null); + } + + public void addItemParamDatas(Collection items, ActionReason reason) { + addItems( + items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), + reason); + } + + private synchronized GameItem putItem(GameItem item) { + // Dont add items that dont have a valid item definition. + var data = item.getItemData(); + if (data == null) return null; + + if (data.isUseOnGain()) { + var params = new UseItemParams(this.player, data.getUseTarget()); + params.usedItemId = data.getId(); + this.player.getServer().getInventorySystem().useItemDirect(data, params); + return null; + } + + // Add item to inventory store + ItemType type = item.getItemData().getItemType(); + InventoryTab tab = getInventoryTab(type); + + // Add + switch (type) { + case ITEM_WEAPON: + case ITEM_RELIQUARY: + if (tab.getSize() >= tab.getMaxCapacity()) { + return null; + } + // Duplicates cause problems + item.setCount(Math.max(item.getCount(), 1)); + // Adds to inventory + this.putItem(item, tab); + // Set ownership and save to db + item.save(); + return item; + case ITEM_VIRTUAL: + // Handle + this.addVirtualItem(item.getItemId(), item.getCount()); + return item; + default: + switch (item.getItemData().getMaterialType()) { + case MATERIAL_AVATAR: + case MATERIAL_FLYCLOAK: + case MATERIAL_COSTUME: + case MATERIAL_NAMECARD: + Grasscutter.getLogger() + .warn( + "Attempted to add a " + + item.getItemData().getMaterialType().name() + + " to inventory, but item definition lacks isUseOnGain. This indicates a Resources error."); + return null; + default: + if (tab == null) { + return null; + } + GameItem existingItem = tab.getItemById(item.getItemId()); + if (existingItem == null) { + // Item type didnt exist before, we will add it to main inventory map if there is + // enough space + if (tab.getSize() >= tab.getMaxCapacity()) { + return null; + } + this.putItem(item, tab); + // Set ownership and save to db + item.save(); + return item; + } else { + // Add count + existingItem.setCount( + Math.min( + existingItem.getCount() + item.getCount(), + item.getItemData().getStackLimit())); + existingItem.save(); + return existingItem; + } + } + } + } + + private synchronized void putItem(GameItem item, InventoryTab tab) { + this.player.getCodex().checkAddedItem(item); + // Set owner and guid FIRST! + item.setOwner(this.player); + // Put in item store + getItems().put(item.getGuid(), item); + if (tab != null) { + tab.onAddItem(item); + } + } + + private void addVirtualItem(int itemId, int count) { + switch (itemId) { + case 101 -> // Character exp + this.player.getTeamManager().getActiveTeam().stream() + .map(e -> e.getAvatar()) + .forEach( + avatar -> + this.player + .getServer() + .getInventorySystem() + .upgradeAvatar(this.player, avatar, count)); + case 102 -> // Adventure exp + this.player.addExpDirectly(count); + case 105 -> // Companionship exp + this.player.getTeamManager().getActiveTeam().stream() + .map(e -> e.getAvatar()) + .forEach( + avatar -> + this.player + .getServer() + .getInventorySystem() + .upgradeAvatarFetterLevel( + this.player, avatar, count * (this.player.isInMultiplayer() ? 2 : 1))); + case 106 -> // Resin + this.player.getResinManager().addResin(count); + case 107 -> // Legendary Key + this.player.addLegendaryKey(count); + case 121 -> // Home exp + this.player.getHome().addExp(this.player, count); + case 201 -> // Primogem + this.player.setPrimogems(this.player.getPrimogems() + count); + case 202 -> // Mora + this.player.setMora(this.player.getMora() + count); + case 203 -> // Genesis Crystals + this.player.setCrystals(this.player.getCrystals() + count); + case 204 -> // Home Coin + this.player.setHomeCoin(this.player.getHomeCoin() + count); + } + } + + private GameItem payVirtualItem(int itemId, int count) { + switch (itemId) { + case 201 -> // Primogem + player.setPrimogems(player.getPrimogems() - count); + case 202 -> // Mora + player.setMora(player.getMora() - count); + case 203 -> // Genesis Crystals + player.setCrystals(player.getCrystals() - count); + case 106 -> // Resin + player.getResinManager().useResin(count); + case 107 -> // LegendaryKey + player.useLegendaryKey(count); + case 204 -> // Home Coin + player.setHomeCoin(player.getHomeCoin() - count); + default -> { + var gameItem = getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); + removeItem(gameItem, count); + return gameItem; + } + } + return null; + } + + private int getVirtualItemCount(int itemId) { + switch (itemId) { + case 201: // Primogem + return this.player.getPrimogems(); + case 202: // Mora + return this.player.getMora(); + case 203: // Genesis Crystals + return this.player.getCrystals(); + case 106: // Resin + return this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); + case 107: // Legendary Key + return this.player.getProperty(PlayerProperty.PROP_PLAYER_LEGENDARY_KEY); + case 204: // Home Coin + return this.player.getHomeCoin(); + default: + GameItem item = + getInventoryTab(ItemType.ITEM_MATERIAL) + .getItemById( + itemId); // What if we ever want to operate on weapons/relics/furniture? :S + return (item == null) ? 0 : item.getCount(); + } + } + + public synchronized boolean payItem(int id, int count) { + if (this.getVirtualItemCount(id) < count) return false; + this.payVirtualItem(id, count); + return true; + } + + public boolean payItem(ItemParamData costItem) { + return this.payItem(costItem.getId(), costItem.getCount()); + } + + public boolean payItems(ItemParamData[] costItems) { + return this.payItems(costItems, 1, null); + } + + public boolean payItems(ItemParamData[] costItems, int quantity) { + return this.payItems(costItems, quantity, null); + } + + public synchronized boolean payItems( + ItemParamData[] costItems, int quantity, ActionReason reason) { + // Make sure player has requisite items + for (ItemParamData cost : costItems) + if (this.getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) return false; + // All costs are satisfied, now remove them all + for (ItemParamData cost : costItems) { + this.payVirtualItem(cost.getId(), cost.getCount() * quantity); + } + + if (reason != null) { // Do we need these? + // getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason)); + } + // getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); + return true; + } + + public boolean payItems(Iterable costItems) { + return this.payItems(costItems, 1, null); + } + + public boolean payItems(Iterable costItems, int quantity) { + return this.payItems(costItems, quantity, null); + } + + public synchronized boolean payItems( + Iterable costItems, int quantity, ActionReason reason) { + // Make sure player has requisite items + for (ItemParamData cost : costItems) + if (getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) return false; + // All costs are satisfied, now remove them all + costItems.forEach(cost -> this.payVirtualItem(cost.getId(), cost.getCount() * quantity)); + // TODO:handle the reason(need to send certain package) + return true; + } + + public void removeItems(List items) { + // TODO Bulk delete + for (GameItem item : items) { + this.removeItem(item, item.getCount()); + } + } + + public boolean removeItem(long guid) { + return removeItem(guid, 1); + } + + public synchronized boolean removeItem(long guid, int count) { + GameItem item = this.getItemByGuid(guid); + + if (item == null) { + return false; + } + + return removeItem(item, count); + } + + public synchronized boolean removeItem(GameItem item) { + return removeItem(item, item.getCount()); + } + + public synchronized boolean removeItem(GameItem item, int count) { + // Sanity check + if (count <= 0 || item == null) { + return false; + } + + if (item.getItemData().isEquip()) { + item.setCount(0); + } else { + item.setCount(item.getCount() - count); + } + + if (item.getCount() <= 0) { + // Remove from inventory tab too + InventoryTab tab = null; + if (item.getItemData() != null) { + tab = getInventoryTab(item.getItemData().getItemType()); + } + // Remove if less than 0 + deleteItem(item, tab); + // + getPlayer().sendPacket(new PacketStoreItemDelNotify(item)); + } else { + getPlayer().sendPacket(new PacketStoreItemChangeNotify(item)); + } + + // Battle pass trigger + int removeCount = Math.min(count, item.getCount()); + getPlayer() + .getBattlePassManager() + .triggerMission(WatcherTriggerType.TRIGGER_COST_MATERIAL, item.getItemId(), removeCount); + + // Update in db + item.save(); + + // Returns true on success + return true; + } + + private void deleteItem(GameItem item, InventoryTab tab) { + getItems().remove(item.getGuid()); + if (tab != null) { + tab.onRemoveItem(item); + } + } + + public boolean equipItem(long avatarGuid, long equipGuid) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid); + GameItem item = this.getItemByGuid(equipGuid); + + if (avatar != null && item != null) { + return avatar.equipItem(item, true); + } + + return false; + } + + public boolean unequipItem(long avatarGuid, int slot) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid); + EquipType equipType = EquipType.getTypeByValue(slot); + + if (avatar != null && equipType != EquipType.EQUIP_WEAPON) { + if (avatar.unequipItem(equipType)) { + getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(avatar, equipType)); + avatar.recalcStats(); + return true; + } + } + + return false; + } + + public void loadFromDatabase() { + List items = DatabaseHelper.getInventoryItems(getPlayer()); + + for (GameItem item : items) { + // Should never happen + if (item.getObjectId() == null) { + continue; + } + + ItemData itemData = GameData.getItemDataMap().get(item.getItemId()); + if (itemData == null) { + continue; + } + + item.setItemData(itemData); + + InventoryTab tab = null; + if (item.getItemData() != null) { + tab = getInventoryTab(item.getItemData().getItemType()); + } + + putItem(item, tab); + + // Equip to a character if possible + if (item.isEquipped()) { + Avatar avatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter()); + boolean hasEquipped = false; + + if (avatar != null) { + hasEquipped = avatar.equipItem(item, false); + } + + if (!hasEquipped) { + item.setEquipCharacter(0); + item.save(); + } + } + } + } + + @Override + public Iterator iterator() { + return this.getItems().values().iterator(); + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/InventoryTab.java b/src/main/java/emu/grasscutter/game/inventory/InventoryTab.java index e50f884bf..3612218cc 100644 --- a/src/main/java/emu/grasscutter/game/inventory/InventoryTab.java +++ b/src/main/java/emu/grasscutter/game/inventory/InventoryTab.java @@ -1,13 +1,13 @@ -package emu.grasscutter.game.inventory; - -public interface InventoryTab { - GameItem getItemById(int id); - - void onAddItem(GameItem item); - - void onRemoveItem(GameItem item); - - int getSize(); - - int getMaxCapacity(); -} +package emu.grasscutter.game.inventory; + +public interface InventoryTab { + GameItem getItemById(int id); + + void onAddItem(GameItem item); + + void onRemoveItem(GameItem item); + + int getSize(); + + int getMaxCapacity(); +} diff --git a/src/main/java/emu/grasscutter/game/inventory/ItemDef.java b/src/main/java/emu/grasscutter/game/inventory/ItemDef.java index 0dde8fd05..4e014cae2 100644 --- a/src/main/java/emu/grasscutter/game/inventory/ItemDef.java +++ b/src/main/java/emu/grasscutter/game/inventory/ItemDef.java @@ -1,27 +1,27 @@ -package emu.grasscutter.game.inventory; - -public class ItemDef { - private int itemId; - private int count; - - public ItemDef(int itemId, int count) { - this.itemId = itemId; - this.count = count; - } - - public int getItemId() { - return itemId; - } - - public void setItemId(int itemId) { - this.itemId = itemId; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } -} +package emu.grasscutter.game.inventory; + +public class ItemDef { + private int itemId; + private int count; + + public ItemDef(int itemId, int count) { + this.itemId = itemId; + this.count = count; + } + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/ItemQuality.java b/src/main/java/emu/grasscutter/game/inventory/ItemQuality.java index a3486e291..d3c5ec061 100644 --- a/src/main/java/emu/grasscutter/game/inventory/ItemQuality.java +++ b/src/main/java/emu/grasscutter/game/inventory/ItemQuality.java @@ -1,46 +1,47 @@ -package emu.grasscutter.game.inventory; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum ItemQuality { - QUALITY_NONE(0), - QUALITY_WHITE(1), - QUALITY_GREEN(2), - QUALITY_BLUE(3), - QUALITY_PURPLE(4), - QUALITY_ORANGE(5), - QUALITY_ORANGE_SP(105); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - ItemQuality(int value) { - this.value = value; - } - - public static ItemQuality getTypeByValue(int value) { - return map.getOrDefault(value, QUALITY_NONE); - } - - public static ItemQuality getTypeByName(String name) { - return stringMap.getOrDefault(name, QUALITY_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum ItemQuality { + QUALITY_NONE(0), + QUALITY_WHITE(1), + QUALITY_GREEN(2), + QUALITY_BLUE(3), + QUALITY_PURPLE(4), + QUALITY_ORANGE(5), + QUALITY_ORANGE_SP(105); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + ItemQuality(int value) { + this.value = value; + } + + public static ItemQuality getTypeByValue(int value) { + return map.getOrDefault(value, QUALITY_NONE); + } + + public static ItemQuality getTypeByName(String name) { + return stringMap.getOrDefault(name, QUALITY_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/ItemType.java b/src/main/java/emu/grasscutter/game/inventory/ItemType.java index 7f6d64e8f..7cf351fd8 100644 --- a/src/main/java/emu/grasscutter/game/inventory/ItemType.java +++ b/src/main/java/emu/grasscutter/game/inventory/ItemType.java @@ -1,46 +1,47 @@ -package emu.grasscutter.game.inventory; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum ItemType { - ITEM_NONE(0), - ITEM_VIRTUAL(1), - ITEM_MATERIAL(2), - ITEM_RELIQUARY(3), - ITEM_WEAPON(4), - ITEM_DISPLAY(5), - ITEM_FURNITURE(6); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - ItemType(int value) { - this.value = value; - } - - public static ItemType getTypeByValue(int value) { - return map.getOrDefault(value, ITEM_NONE); - } - - public static ItemType getTypeByName(String name) { - return stringMap.getOrDefault(name, ITEM_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum ItemType { + ITEM_NONE(0), + ITEM_VIRTUAL(1), + ITEM_MATERIAL(2), + ITEM_RELIQUARY(3), + ITEM_WEAPON(4), + ITEM_DISPLAY(5), + ITEM_FURNITURE(6); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + ItemType(int value) { + this.value = value; + } + + public static ItemType getTypeByValue(int value) { + return map.getOrDefault(value, ITEM_NONE); + } + + public static ItemType getTypeByName(String name) { + return stringMap.getOrDefault(name, ITEM_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/MaterialInventoryTab.java b/src/main/java/emu/grasscutter/game/inventory/MaterialInventoryTab.java index 9ebf0d7f1..80ba76b2c 100644 --- a/src/main/java/emu/grasscutter/game/inventory/MaterialInventoryTab.java +++ b/src/main/java/emu/grasscutter/game/inventory/MaterialInventoryTab.java @@ -1,39 +1,39 @@ -package emu.grasscutter.game.inventory; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -public class MaterialInventoryTab implements InventoryTab { - private final Int2ObjectMap items; - private final int maxCapacity; - - public MaterialInventoryTab(int maxCapacity) { - this.items = new Int2ObjectOpenHashMap<>(); - this.maxCapacity = maxCapacity; - } - - @Override - public GameItem getItemById(int id) { - return this.items.get(id); - } - - @Override - public void onAddItem(GameItem item) { - this.items.put(item.getItemId(), item); - } - - @Override - public void onRemoveItem(GameItem item) { - this.items.remove(item.getItemId()); - } - - @Override - public int getSize() { - return this.items.size(); - } - - @Override - public int getMaxCapacity() { - return this.maxCapacity; - } -} +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public class MaterialInventoryTab implements InventoryTab { + private final Int2ObjectMap items; + private final int maxCapacity; + + public MaterialInventoryTab(int maxCapacity) { + this.items = new Int2ObjectOpenHashMap<>(); + this.maxCapacity = maxCapacity; + } + + @Override + public GameItem getItemById(int id) { + return this.items.get(id); + } + + @Override + public void onAddItem(GameItem item) { + this.items.put(item.getItemId(), item); + } + + @Override + public void onRemoveItem(GameItem item) { + this.items.remove(item.getItemId()); + } + + @Override + public int getSize() { + return this.items.size(); + } + + @Override + public int getMaxCapacity() { + return this.maxCapacity; + } +} diff --git a/src/main/java/emu/grasscutter/game/inventory/MaterialType.java b/src/main/java/emu/grasscutter/game/inventory/MaterialType.java index 486435d29..58fbe98ac 100644 --- a/src/main/java/emu/grasscutter/game/inventory/MaterialType.java +++ b/src/main/java/emu/grasscutter/game/inventory/MaterialType.java @@ -1,80 +1,81 @@ -package emu.grasscutter.game.inventory; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum MaterialType { - MATERIAL_NONE(0), - MATERIAL_FOOD(1), - MATERIAL_QUEST(2), - MATERIAL_EXCHANGE(4), - MATERIAL_CONSUME(5), - MATERIAL_EXP_FRUIT(6), - MATERIAL_AVATAR(7), - MATERIAL_ADSORBATE(8), - MATERIAL_CRICKET(9), - MATERIAL_ELEM_CRYSTAL(10), - MATERIAL_WEAPON_EXP_STONE(11), - MATERIAL_CHEST(12), - MATERIAL_RELIQUARY_MATERIAL(13), - MATERIAL_AVATAR_MATERIAL(14), - MATERIAL_NOTICE_ADD_HP(15), - MATERIAL_SEA_LAMP(16), - MATERIAL_SELECTABLE_CHEST(17), - MATERIAL_FLYCLOAK(18), - MATERIAL_NAMECARD(19), - MATERIAL_TALENT(20), - MATERIAL_WIDGET(21), - MATERIAL_CHEST_BATCH_USE(22), - MATERIAL_FAKE_ABSORBATE(23), - MATERIAL_CONSUME_BATCH_USE(24), - MATERIAL_WOOD(25), - MATERIAL_FURNITURE_FORMULA(27), - MATERIAL_CHANNELLER_SLAB_BUFF(28), - MATERIAL_FURNITURE_SUITE_FORMULA(29), - MATERIAL_COSTUME(30), - MATERIAL_HOME_SEED(31), - MATERIAL_FISH_BAIT(32), - MATERIAL_FISH_ROD(33), - MATERIAL_SUMO_BUFF(34), - MATERIAL_FIREWORKS(35), - MATERIAL_BGM(36), - MATERIAL_SPICE_FOOD(37), - MATERIAL_ACTIVITY_ROBOT(38), - MATERIAL_ACTIVITY_GEAR(39), - MATERIAL_ACTIVITY_JIGSAW(40), - MATERIAL_ARANARA(41), - MATERIAL_DESHRET_MANUAL(46); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - MaterialType(int value) { - this.value = value; - } - - public static MaterialType getTypeByValue(int value) { - return map.getOrDefault(value, MATERIAL_NONE); - } - - public static MaterialType getTypeByName(String name) { - return stringMap.getOrDefault(name, MATERIAL_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.inventory; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum MaterialType { + MATERIAL_NONE(0), + MATERIAL_FOOD(1), + MATERIAL_QUEST(2), + MATERIAL_EXCHANGE(4), + MATERIAL_CONSUME(5), + MATERIAL_EXP_FRUIT(6), + MATERIAL_AVATAR(7), + MATERIAL_ADSORBATE(8), + MATERIAL_CRICKET(9), + MATERIAL_ELEM_CRYSTAL(10), + MATERIAL_WEAPON_EXP_STONE(11), + MATERIAL_CHEST(12), + MATERIAL_RELIQUARY_MATERIAL(13), + MATERIAL_AVATAR_MATERIAL(14), + MATERIAL_NOTICE_ADD_HP(15), + MATERIAL_SEA_LAMP(16), + MATERIAL_SELECTABLE_CHEST(17), + MATERIAL_FLYCLOAK(18), + MATERIAL_NAMECARD(19), + MATERIAL_TALENT(20), + MATERIAL_WIDGET(21), + MATERIAL_CHEST_BATCH_USE(22), + MATERIAL_FAKE_ABSORBATE(23), + MATERIAL_CONSUME_BATCH_USE(24), + MATERIAL_WOOD(25), + MATERIAL_FURNITURE_FORMULA(27), + MATERIAL_CHANNELLER_SLAB_BUFF(28), + MATERIAL_FURNITURE_SUITE_FORMULA(29), + MATERIAL_COSTUME(30), + MATERIAL_HOME_SEED(31), + MATERIAL_FISH_BAIT(32), + MATERIAL_FISH_ROD(33), + MATERIAL_SUMO_BUFF(34), + MATERIAL_FIREWORKS(35), + MATERIAL_BGM(36), + MATERIAL_SPICE_FOOD(37), + MATERIAL_ACTIVITY_ROBOT(38), + MATERIAL_ACTIVITY_GEAR(39), + MATERIAL_ACTIVITY_JIGSAW(40), + MATERIAL_ARANARA(41), + MATERIAL_DESHRET_MANUAL(46); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + MaterialType(int value) { + this.value = value; + } + + public static MaterialType getTypeByValue(int value) { + return map.getOrDefault(value, MATERIAL_NONE); + } + + public static MaterialType getTypeByName(String name) { + return stringMap.getOrDefault(name, MATERIAL_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/mail/Mail.java b/src/main/java/emu/grasscutter/game/mail/Mail.java index 98b44ecd1..2283fac98 100644 --- a/src/main/java/emu/grasscutter/game/mail/Mail.java +++ b/src/main/java/emu/grasscutter/game/mail/Mail.java @@ -1,128 +1,133 @@ -package emu.grasscutter.game.mail; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Indexed; -import dev.morphia.annotations.Transient; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import org.bson.types.ObjectId; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; - -@Entity(value = "mail", useDiscriminator = false) -public class Mail { - public MailContent mailContent; - public List itemList; - public long sendTime; - public long expireTime; - public int importance; - public boolean isRead; - public boolean isAttachmentGot; - public int stateValue; - @Id - private ObjectId id; - @Indexed - private int ownerUid; - @Transient - private boolean shouldDelete; - - public Mail() { - this(new MailContent(), new ArrayList(), (int) Instant.now().getEpochSecond() + 604800); // TODO: add expire time to send mail command - } - - public Mail(MailContent mailContent, List itemList, long expireTime) { - this(mailContent, itemList, expireTime, 0); - } - - public Mail(MailContent mailContent, List itemList, long expireTime, int importance) { - this(mailContent, itemList, expireTime, importance, 1); - } - - public Mail(MailContent mailContent, List itemList, long expireTime, int importance, int state) { - this.mailContent = mailContent; - this.itemList = itemList; - this.sendTime = (int) Instant.now().getEpochSecond(); - this.expireTime = expireTime; - this.importance = importance; // Starred mail, 0 = No star, 1 = Star. - this.isRead = false; - this.isAttachmentGot = false; - this.stateValue = state; // Different mailboxes, 1 = Default, 3 = Gift-box. - } - - public ObjectId getId() { - return id; - } - - public int getOwnerUid() { - return ownerUid; - } - - public void setOwnerUid(int ownerUid) { - this.ownerUid = ownerUid; - } - - public void save() { - if (this.expireTime * 1000 < System.currentTimeMillis()) { - DatabaseHelper.deleteMail(this); - } else { - DatabaseHelper.saveMail(this); - } - } - - @Entity - public static class MailContent { - public String title; - public String content; - public String sender; - - public MailContent() { - this.title = ""; - this.content = "loading..."; - this.sender = "loading"; - } - - public MailContent(String title, String content) { - this(title, content, "Server"); - } - - public MailContent(String title, String content, Player sender) { - this(title, content, sender.getNickname()); - } - - public MailContent(String title, String content, String sender) { - this.title = title; - this.content = content; - this.sender = sender; - } - } - - @Entity - public static class MailItem { - public int itemId; - public int itemCount; - public int itemLevel; - - public MailItem() { - this.itemId = 11101; - this.itemCount = 1; - this.itemLevel = 1; - } - - public MailItem(int itemId) { - this(itemId, 1); - } - - public MailItem(int itemId, int itemCount) { - this(itemId, itemCount, 1); - } - - public MailItem(int itemId, int itemCount, int itemLevel) { - this.itemId = itemId; - this.itemCount = itemCount; - this.itemLevel = itemLevel; - } - } -} +package emu.grasscutter.game.mail; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.Transient; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import org.bson.types.ObjectId; + +@Entity(value = "mail", useDiscriminator = false) +public class Mail { + public MailContent mailContent; + public List itemList; + public long sendTime; + public long expireTime; + public int importance; + public boolean isRead; + public boolean isAttachmentGot; + public int stateValue; + @Id private ObjectId id; + @Indexed private int ownerUid; + @Transient private boolean shouldDelete; + + public Mail() { + this( + new MailContent(), + new ArrayList(), + (int) Instant.now().getEpochSecond() + + 604800); // TODO: add expire time to send mail command + } + + public Mail(MailContent mailContent, List itemList, long expireTime) { + this(mailContent, itemList, expireTime, 0); + } + + public Mail(MailContent mailContent, List itemList, long expireTime, int importance) { + this(mailContent, itemList, expireTime, importance, 1); + } + + public Mail( + MailContent mailContent, + List itemList, + long expireTime, + int importance, + int state) { + this.mailContent = mailContent; + this.itemList = itemList; + this.sendTime = (int) Instant.now().getEpochSecond(); + this.expireTime = expireTime; + this.importance = importance; // Starred mail, 0 = No star, 1 = Star. + this.isRead = false; + this.isAttachmentGot = false; + this.stateValue = state; // Different mailboxes, 1 = Default, 3 = Gift-box. + } + + public ObjectId getId() { + return id; + } + + public int getOwnerUid() { + return ownerUid; + } + + public void setOwnerUid(int ownerUid) { + this.ownerUid = ownerUid; + } + + public void save() { + if (this.expireTime * 1000 < System.currentTimeMillis()) { + DatabaseHelper.deleteMail(this); + } else { + DatabaseHelper.saveMail(this); + } + } + + @Entity + public static class MailContent { + public String title; + public String content; + public String sender; + + public MailContent() { + this.title = ""; + this.content = "loading..."; + this.sender = "loading"; + } + + public MailContent(String title, String content) { + this(title, content, "Server"); + } + + public MailContent(String title, String content, Player sender) { + this(title, content, sender.getNickname()); + } + + public MailContent(String title, String content, String sender) { + this.title = title; + this.content = content; + this.sender = sender; + } + } + + @Entity + public static class MailItem { + public int itemId; + public int itemCount; + public int itemLevel; + + public MailItem() { + this.itemId = 11101; + this.itemCount = 1; + this.itemLevel = 1; + } + + public MailItem(int itemId) { + this(itemId, 1); + } + + public MailItem(int itemId, int itemCount) { + this(itemId, itemCount, 1); + } + + public MailItem(int itemId, int itemCount, int itemLevel) { + this.itemId = itemId; + this.itemCount = itemCount; + this.itemLevel = itemLevel; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/mail/MailHandler.java b/src/main/java/emu/grasscutter/game/mail/MailHandler.java index 4b1390d14..fbb3cc6b3 100644 --- a/src/main/java/emu/grasscutter/game/mail/MailHandler.java +++ b/src/main/java/emu/grasscutter/game/mail/MailHandler.java @@ -1,105 +1,111 @@ -package emu.grasscutter.game.mail; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.player.PlayerReceiveMailEvent; -import emu.grasscutter.server.packet.send.PacketDelMailRsp; -import emu.grasscutter.server.packet.send.PacketMailChangeNotify; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class MailHandler extends BasePlayerManager { - private final List mail; - - public MailHandler(Player player) { - super(player); - - this.mail = new ArrayList<>(); - } - - public List getMail() { - return mail; - } - - // ---------------------MAIL------------------------ - - public void sendMail(Mail message) { - // Call mail receive event. - PlayerReceiveMailEvent event = new PlayerReceiveMailEvent(this.getPlayer(), message); - event.call(); - if (event.isCanceled()) return; - message = event.getMessage(); - - message.setOwnerUid(this.getPlayer().getUid()); - message.save(); - - this.mail.add(message); - - Grasscutter.getLogger().debug("Mail sent to user [" + this.getPlayer().getUid() + ":" + this.getPlayer().getNickname() + "]!"); - - if (this.getPlayer().isOnline()) { - this.getPlayer().sendPacket(new PacketMailChangeNotify(this.getPlayer(), message)); - } // TODO: setup a way for the mail notification to show up when someone receives mail when they were offline - } - - public boolean deleteMail(int mailId) { - Mail message = getMailById(mailId); - - if (message != null) { - this.getMail().remove(mailId); - message.expireTime = 0; - message.save(); - - return true; - } - - return false; - } - - public void deleteMail(List mailList) { - List sortedMailList = new ArrayList<>(); - sortedMailList.addAll(mailList); - Collections.sort(sortedMailList, Collections.reverseOrder()); - - List deleted = new ArrayList<>(); - - for (int id : sortedMailList) { - if (this.deleteMail(id)) { - deleted.add(id); - } - } - - player.getSession().send(new PacketDelMailRsp(player, deleted)); - player.getSession().send(new PacketMailChangeNotify(player, null, deleted)); - } - - public Mail getMailById(int index) { - return this.mail.get(index); - } - - public int getMailIndex(Mail message) { - return this.mail.indexOf(message); - } - - public boolean replaceMailByIndex(int index, Mail message) { - if (getMailById(index) != null) { - this.mail.set(index, message); - message.save(); - return true; - } else { - return false; - } - } - - public void loadFromDatabase() { - List mailList = DatabaseHelper.getAllMail(this.getPlayer()); - - for (Mail mail : mailList) { - this.getMail().add(mail); - } - } -} +package emu.grasscutter.game.mail; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.player.PlayerReceiveMailEvent; +import emu.grasscutter.server.packet.send.PacketDelMailRsp; +import emu.grasscutter.server.packet.send.PacketMailChangeNotify; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MailHandler extends BasePlayerManager { + private final List mail; + + public MailHandler(Player player) { + super(player); + + this.mail = new ArrayList<>(); + } + + public List getMail() { + return mail; + } + + // ---------------------MAIL------------------------ + + public void sendMail(Mail message) { + // Call mail receive event. + PlayerReceiveMailEvent event = new PlayerReceiveMailEvent(this.getPlayer(), message); + event.call(); + if (event.isCanceled()) return; + message = event.getMessage(); + + message.setOwnerUid(this.getPlayer().getUid()); + message.save(); + + this.mail.add(message); + + Grasscutter.getLogger() + .debug( + "Mail sent to user [" + + this.getPlayer().getUid() + + ":" + + this.getPlayer().getNickname() + + "]!"); + + if (this.getPlayer().isOnline()) { + this.getPlayer().sendPacket(new PacketMailChangeNotify(this.getPlayer(), message)); + } // TODO: setup a way for the mail notification to show up when someone receives mail when they + // were offline + } + + public boolean deleteMail(int mailId) { + Mail message = getMailById(mailId); + + if (message != null) { + this.getMail().remove(mailId); + message.expireTime = 0; + message.save(); + + return true; + } + + return false; + } + + public void deleteMail(List mailList) { + List sortedMailList = new ArrayList<>(); + sortedMailList.addAll(mailList); + Collections.sort(sortedMailList, Collections.reverseOrder()); + + List deleted = new ArrayList<>(); + + for (int id : sortedMailList) { + if (this.deleteMail(id)) { + deleted.add(id); + } + } + + player.getSession().send(new PacketDelMailRsp(player, deleted)); + player.getSession().send(new PacketMailChangeNotify(player, null, deleted)); + } + + public Mail getMailById(int index) { + return this.mail.get(index); + } + + public int getMailIndex(Mail message) { + return this.mail.indexOf(message); + } + + public boolean replaceMailByIndex(int index, Mail message) { + if (getMailById(index) != null) { + this.mail.set(index, message); + message.save(); + return true; + } else { + return false; + } + } + + public void loadFromDatabase() { + List mailList = DatabaseHelper.getAllMail(this.getPlayer()); + + for (Mail mail : mailList) { + this.getMail().add(mail); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java index 3e3801432..00851f790 100644 --- a/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java +++ b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java @@ -1,142 +1,178 @@ -package emu.grasscutter.game.managers; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.home.FurnitureMakeSlotItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayList; -import java.util.List; - -public class FurnitureManager extends BasePlayerManager { - - public FurnitureManager(Player player) { - super(player); - } - - public void onLogin() { - notifyUnlockFurniture(); - notifyUnlockFurnitureSuite(); - } - - public void notifyUnlockFurniture() { - player.getSession().send(new PacketUnlockedFurnitureFormulaDataNotify(player.getUnlockedFurniture())); - } - - public void notifyUnlockFurnitureSuite() { - player.getSession().send(new PacketUnlockedFurnitureSuiteDataNotify(player.getUnlockedFurnitureSuite())); - } - - public boolean unlockFurnitureFormula(int id) { - if (!player.getUnlockedFurniture().add(id)) { - return false; // Already unlocked! - } - notifyUnlockFurniture(); - return true; - } - - public boolean unlockFurnitureSuite(int id) { - if (!player.getUnlockedFurnitureSuite().add(id)) { - return false; // Already unlocked! - } - notifyUnlockFurnitureSuite(); - return true; - } - - public void startMake(int makeId, int avatarId) { - var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); - if (makeData == null) { - player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, null)); - return; - } - - // check slot count - if (player.getHome().getLevelData().getFurnitureMakeSlotCount() <= player.getHome().getFurnitureMakeSlotItemList().size()) { - player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_SLOT_FULL_VALUE, null)); - return; - } - - // pay items first - if (!player.getInventory().payItems(makeData.getMaterialItems())) { - player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_HOME_FURNITURE_COUNT_NOT_ENOUGH_VALUE, null)); - return; - } - - var furnitureSlot = FurnitureMakeSlotItem.of() - .avatarId(avatarId) - .makeId(makeId) - .beginTime(Utils.getCurrentSeconds()) - .durTime(makeData.getMakeTime()) - .build(); - - // add furniture make task - player.getHome().getFurnitureMakeSlotItemList().add(furnitureSlot); - player.getSession().send(new PacketFurnitureMakeStartRsp(Retcode.RET_SUCC_VALUE, - player.getHome().getFurnitureMakeSlotItemList().stream() - .map(FurnitureMakeSlotItem::toProto) - .toList() - )); - - player.getHome().save(); - } - - public void queryStatus() { - if (player.getHome().getFurnitureMakeSlotItemList() == null) { - player.getHome().setFurnitureMakeSlotItemList(new ArrayList<>()); - } - - player.sendPacket(new PacketFurnitureMakeRsp(player.getHome())); - } - - - public void take(int index, int makeId, boolean isFastFinish) { - var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); - if (makeData == null) { - player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, makeId, null, null)); - return; - } - - var slotItem = player.getHome().getFurnitureMakeSlotItemList().stream() - .filter(x -> x.getIndex() == index && x.getMakeId() == makeId) - .findFirst(); - - if (slotItem.isEmpty()) { - player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_NO_MAKE_DATA_VALUE, makeId, null, null)); - return; - } - - // pay the speedup item - if (isFastFinish && !player.getInventory().payItem(107013, 1)) { - player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); - return; - } - - // check if player can take -// if (slotItem.get().getBeginTime() + slotItem.get().getDurTime() >= Utils.getCurrentSeconds() && !isFastFinish) { -// player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); -// return; -// } - - player.getInventory().addItem(makeData.getFurnitureItemID(), makeData.getCount()); - player.getHome().getFurnitureMakeSlotItemList().remove(slotItem.get()); - - // Should be for first craft, but until first craft check exists add exp for each item crafted - player.getInventory().addItem(121, makeData.getExp(), ActionReason.FurnitureMakeTake); - - player.getSession().send(new PacketTakeFurnitureMakeRsp(Retcode.RET_SUCC_VALUE, makeId, - List.of(ItemParamOuterClass.ItemParam.newBuilder() - .setItemId(makeData.getFurnitureItemID()) - .setCount(makeData.getCount()) - .build()), - player.getHome().getFurnitureMakeSlotItemList().stream() - .map(FurnitureMakeSlotItem::toProto) - .toList() - )); - player.getHome().save(); - } -} +package emu.grasscutter.game.managers; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.home.FurnitureMakeSlotItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Utils; +import java.util.ArrayList; +import java.util.List; + +public class FurnitureManager extends BasePlayerManager { + + public FurnitureManager(Player player) { + super(player); + } + + public void onLogin() { + notifyUnlockFurniture(); + notifyUnlockFurnitureSuite(); + } + + public void notifyUnlockFurniture() { + player + .getSession() + .send(new PacketUnlockedFurnitureFormulaDataNotify(player.getUnlockedFurniture())); + } + + public void notifyUnlockFurnitureSuite() { + player + .getSession() + .send(new PacketUnlockedFurnitureSuiteDataNotify(player.getUnlockedFurnitureSuite())); + } + + public boolean unlockFurnitureFormula(int id) { + if (!player.getUnlockedFurniture().add(id)) { + return false; // Already unlocked! + } + notifyUnlockFurniture(); + return true; + } + + public boolean unlockFurnitureSuite(int id) { + if (!player.getUnlockedFurnitureSuite().add(id)) { + return false; // Already unlocked! + } + notifyUnlockFurnitureSuite(); + return true; + } + + public void startMake(int makeId, int avatarId) { + var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); + if (makeData == null) { + player + .getSession() + .send( + new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, null)); + return; + } + + // check slot count + if (player.getHome().getLevelData().getFurnitureMakeSlotCount() + <= player.getHome().getFurnitureMakeSlotItemList().size()) { + player + .getSession() + .send(new PacketFurnitureMakeStartRsp(Retcode.RET_FURNITURE_MAKE_SLOT_FULL_VALUE, null)); + return; + } + + // pay items first + if (!player.getInventory().payItems(makeData.getMaterialItems())) { + player + .getSession() + .send( + new PacketFurnitureMakeStartRsp( + Retcode.RET_HOME_FURNITURE_COUNT_NOT_ENOUGH_VALUE, null)); + return; + } + + var furnitureSlot = + FurnitureMakeSlotItem.of() + .avatarId(avatarId) + .makeId(makeId) + .beginTime(Utils.getCurrentSeconds()) + .durTime(makeData.getMakeTime()) + .build(); + + // add furniture make task + player.getHome().getFurnitureMakeSlotItemList().add(furnitureSlot); + player + .getSession() + .send( + new PacketFurnitureMakeStartRsp( + Retcode.RET_SUCC_VALUE, + player.getHome().getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList())); + + player.getHome().save(); + } + + public void queryStatus() { + if (player.getHome().getFurnitureMakeSlotItemList() == null) { + player.getHome().setFurnitureMakeSlotItemList(new ArrayList<>()); + } + + player.sendPacket(new PacketFurnitureMakeRsp(player.getHome())); + } + + public void take(int index, int makeId, boolean isFastFinish) { + var makeData = GameData.getFurnitureMakeConfigDataMap().get(makeId); + if (makeData == null) { + player + .getSession() + .send( + new PacketTakeFurnitureMakeRsp( + Retcode.RET_FURNITURE_MAKE_CONFIG_ERROR_VALUE, makeId, null, null)); + return; + } + + var slotItem = + player.getHome().getFurnitureMakeSlotItemList().stream() + .filter(x -> x.getIndex() == index && x.getMakeId() == makeId) + .findFirst(); + + if (slotItem.isEmpty()) { + player + .getSession() + .send( + new PacketTakeFurnitureMakeRsp( + Retcode.RET_FURNITURE_MAKE_NO_MAKE_DATA_VALUE, makeId, null, null)); + return; + } + + // pay the speedup item + if (isFastFinish && !player.getInventory().payItem(107013, 1)) { + player + .getSession() + .send( + new PacketTakeFurnitureMakeRsp( + Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); + return; + } + + // check if player can take + // if (slotItem.get().getBeginTime() + slotItem.get().getDurTime() >= + // Utils.getCurrentSeconds() && !isFastFinish) { + // player.getSession().send(new + // PacketTakeFurnitureMakeRsp(Retcode.RET_FURNITURE_MAKE_UNFINISH_VALUE, makeId, null, null)); + // return; + // } + + player.getInventory().addItem(makeData.getFurnitureItemID(), makeData.getCount()); + player.getHome().getFurnitureMakeSlotItemList().remove(slotItem.get()); + + // Should be for first craft, but until first craft check exists add exp for each item crafted + player.getInventory().addItem(121, makeData.getExp(), ActionReason.FurnitureMakeTake); + + player + .getSession() + .send( + new PacketTakeFurnitureMakeRsp( + Retcode.RET_SUCC_VALUE, + makeId, + List.of( + ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(makeData.getFurnitureItemID()) + .setCount(makeData.getCount()) + .build()), + player.getHome().getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList())); + player.getHome().save(); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/ResinManager.java b/src/main/java/emu/grasscutter/game/managers/ResinManager.java index a86427dfa..2ee0be666 100644 --- a/src/main/java/emu/grasscutter/game/managers/ResinManager.java +++ b/src/main/java/emu/grasscutter/game/managers/ResinManager.java @@ -1,147 +1,154 @@ -package emu.grasscutter.game.managers; - -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.server.packet.send.PacketResinChangeNotify; -import emu.grasscutter.utils.Utils; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -public class ResinManager extends BasePlayerManager { - - public ResinManager(Player player) { - super(player); - } - - /******************** - * Change resin. - ********************/ - public synchronized boolean useResin(int amount) { - // Check if resin enabled. - if (!GAME_OPTIONS.resinOptions.resinUsage) { - return true; - } - - int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); - - // Check if the player has sufficient resin. - if (currentResin < amount) { - return false; - } - - // Deduct the resin from the player. - int newResin = currentResin - amount; - this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); - - // Check if this has taken the player under the recharge cap, - // starting the recharging process. - if (this.player.getNextResinRefresh() == 0 && newResin < GAME_OPTIONS.resinOptions.cap) { - int currentTime = Utils.getCurrentSeconds(); - this.player.setNextResinRefresh(currentTime + GAME_OPTIONS.resinOptions.rechargeTime); - } - - // Send packets. - this.player.sendPacket(new PacketResinChangeNotify(this.player)); - - // Battle Pass trigger - this.player.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_COST_MATERIAL, 106, amount); // Resin item id = 106 - - return true; - } - - public synchronized boolean useCondensedResin(int amount) { - // Don't deduct if resin disabled. - if (!GAME_OPTIONS.resinOptions.resinUsage) return true; - return this.player.getInventory().payItem(220007, amount); - } - - public synchronized void addResin(int amount) { - // Check if resin enabled. - if (!GAME_OPTIONS.resinOptions.resinUsage) { - return; - } - - // Add resin. - int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); - int newResin = currentResin + amount; - this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); - - // Stop recharging if player is now at or over the cap. - if (newResin >= GAME_OPTIONS.resinOptions.cap) { - this.player.setNextResinRefresh(0); - } - - // Send packets. - this.player.sendPacket(new PacketResinChangeNotify(this.player)); - } - - /******************** - * Recharge resin. - ********************/ - public synchronized void rechargeResin() { - // Check if resin enabled. - if (!GAME_OPTIONS.resinOptions.resinUsage) { - return; - } - - int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); - int currentTime = Utils.getCurrentSeconds(); - - // Make sure we are currently in "recharging mode". - // This is denoted by Player.nextResinRefresh being greater than 0. - if (this.player.getNextResinRefresh() <= 0) { - return; - } - - // Determine if we actually need to recharge yet. - if (currentTime < this.player.getNextResinRefresh()) { - return; - } - - // Calculate how much resin we need to refill and update player. - // Note that this can be more than one in case the player - // logged off with uncapped resin and is now logging in again. - int recharge = 1 + ((currentTime - this.player.getNextResinRefresh()) / GAME_OPTIONS.resinOptions.rechargeTime); - int newResin = Math.min(GAME_OPTIONS.resinOptions.cap, currentResin + recharge); - int resinChange = newResin - currentResin; - - this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); - - // Calculate next recharge time. - // Set to zero to disable recharge (because on/over cap.) - if (newResin >= GAME_OPTIONS.resinOptions.cap) { - this.player.setNextResinRefresh(0); - } else { - int nextRecharge = this.player.getNextResinRefresh() + resinChange * GAME_OPTIONS.resinOptions.rechargeTime; - this.player.setNextResinRefresh(nextRecharge); - } - - // Send packets. - this.player.sendPacket(new PacketResinChangeNotify(this.player)); - } - - /******************** - * Player login. - ********************/ - public synchronized void onPlayerLogin() { - // If resin usage is disabled, set resin to cap. - if (!GAME_OPTIONS.resinOptions.resinUsage) { - this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, GAME_OPTIONS.resinOptions.cap); - this.player.setNextResinRefresh(0); - } - - // In case server administrators change the resin cap while players are capped, - // we need to restart recharging here. - int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); - int currentTime = Utils.getCurrentSeconds(); - - if (currentResin < GAME_OPTIONS.resinOptions.cap && this.player.getNextResinRefresh() == 0) { - this.player.setNextResinRefresh(currentTime + GAME_OPTIONS.resinOptions.rechargeTime); - } - - // Send initial notifications on logon. - this.player.sendPacket(new PacketResinChangeNotify(this.player)); - } -} +package emu.grasscutter.game.managers; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.server.packet.send.PacketResinChangeNotify; +import emu.grasscutter.utils.Utils; + +public class ResinManager extends BasePlayerManager { + + public ResinManager(Player player) { + super(player); + } + + /******************** + * Change resin. + ********************/ + public synchronized boolean useResin(int amount) { + // Check if resin enabled. + if (!GAME_OPTIONS.resinOptions.resinUsage) { + return true; + } + + int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); + + // Check if the player has sufficient resin. + if (currentResin < amount) { + return false; + } + + // Deduct the resin from the player. + int newResin = currentResin - amount; + this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); + + // Check if this has taken the player under the recharge cap, + // starting the recharging process. + if (this.player.getNextResinRefresh() == 0 && newResin < GAME_OPTIONS.resinOptions.cap) { + int currentTime = Utils.getCurrentSeconds(); + this.player.setNextResinRefresh(currentTime + GAME_OPTIONS.resinOptions.rechargeTime); + } + + // Send packets. + this.player.sendPacket(new PacketResinChangeNotify(this.player)); + + // Battle Pass trigger + this.player + .getBattlePassManager() + .triggerMission( + WatcherTriggerType.TRIGGER_COST_MATERIAL, 106, amount); // Resin item id = 106 + + return true; + } + + public synchronized boolean useCondensedResin(int amount) { + // Don't deduct if resin disabled. + if (!GAME_OPTIONS.resinOptions.resinUsage) return true; + return this.player.getInventory().payItem(220007, amount); + } + + public synchronized void addResin(int amount) { + // Check if resin enabled. + if (!GAME_OPTIONS.resinOptions.resinUsage) { + return; + } + + // Add resin. + int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); + int newResin = currentResin + amount; + this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); + + // Stop recharging if player is now at or over the cap. + if (newResin >= GAME_OPTIONS.resinOptions.cap) { + this.player.setNextResinRefresh(0); + } + + // Send packets. + this.player.sendPacket(new PacketResinChangeNotify(this.player)); + } + + /******************** + * Recharge resin. + ********************/ + public synchronized void rechargeResin() { + // Check if resin enabled. + if (!GAME_OPTIONS.resinOptions.resinUsage) { + return; + } + + int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); + int currentTime = Utils.getCurrentSeconds(); + + // Make sure we are currently in "recharging mode". + // This is denoted by Player.nextResinRefresh being greater than 0. + if (this.player.getNextResinRefresh() <= 0) { + return; + } + + // Determine if we actually need to recharge yet. + if (currentTime < this.player.getNextResinRefresh()) { + return; + } + + // Calculate how much resin we need to refill and update player. + // Note that this can be more than one in case the player + // logged off with uncapped resin and is now logging in again. + int recharge = + 1 + + ((currentTime - this.player.getNextResinRefresh()) + / GAME_OPTIONS.resinOptions.rechargeTime); + int newResin = Math.min(GAME_OPTIONS.resinOptions.cap, currentResin + recharge); + int resinChange = newResin - currentResin; + + this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, newResin); + + // Calculate next recharge time. + // Set to zero to disable recharge (because on/over cap.) + if (newResin >= GAME_OPTIONS.resinOptions.cap) { + this.player.setNextResinRefresh(0); + } else { + int nextRecharge = + this.player.getNextResinRefresh() + resinChange * GAME_OPTIONS.resinOptions.rechargeTime; + this.player.setNextResinRefresh(nextRecharge); + } + + // Send packets. + this.player.sendPacket(new PacketResinChangeNotify(this.player)); + } + + /******************** + * Player login. + ********************/ + public synchronized void onPlayerLogin() { + // If resin usage is disabled, set resin to cap. + if (!GAME_OPTIONS.resinOptions.resinUsage) { + this.player.setProperty(PlayerProperty.PROP_PLAYER_RESIN, GAME_OPTIONS.resinOptions.cap); + this.player.setNextResinRefresh(0); + } + + // In case server administrators change the resin cap while players are capped, + // we need to restart recharging here. + int currentResin = this.player.getProperty(PlayerProperty.PROP_PLAYER_RESIN); + int currentTime = Utils.getCurrentSeconds(); + + if (currentResin < GAME_OPTIONS.resinOptions.cap && this.player.getNextResinRefresh() == 0) { + this.player.setNextResinRefresh(currentTime + GAME_OPTIONS.resinOptions.rechargeTime); + } + + // Send initial notifications on logon. + this.player.sendPacket(new PacketResinChangeNotify(this.player)); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/SatiationManager.java b/src/main/java/emu/grasscutter/game/managers/SatiationManager.java index 843244116..2df291c90 100644 --- a/src/main/java/emu/grasscutter/game/managers/SatiationManager.java +++ b/src/main/java/emu/grasscutter/game/managers/SatiationManager.java @@ -1,115 +1,115 @@ -package emu.grasscutter.game.managers; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.server.packet.send.PacketAvatarPropNotify; -import emu.grasscutter.server.packet.send.PacketAvatarSatiationDataNotify; -import emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify; -import emu.grasscutter.server.packet.send.PacketPlayerTimeNotify; - -import java.util.HashMap; -import java.util.Map; - -public class SatiationManager extends BasePlayerManager { - - public SatiationManager(Player player) { - super(player); - } - - /******************** - * Change satiation - ********************/ - public synchronized boolean addSatiation(Avatar avatar, float satiationIncrease, int itemId) { - - // Satiation is max 10000 but can go over in the case of overeating - Map propMap = new HashMap<>(); - int satiation = Math.round(satiationIncrease * 100); - float totalSatiation = ((satiationIncrease * 100) + avatar.getSatiation()); - - // Update client time - updateTime(); - - // Calculate times - var playerTime = (player.getClientTime() / 1000); - float finishTime = playerTime + (totalSatiation / 30); - - // Penalty - long penaltyTime = playerTime; - long penaltyValue = avatar.getSatiationPenalty(); - if (totalSatiation + avatar.getSatiation() > 10000 && penaltyValue == 0) { - // Penalty is always 30sec - penaltyTime += 30; - penaltyValue = 3000; - } - - // Add satiation - if (!addSatiationDirectly(avatar, satiation)) return false; - propMap.put(PlayerProperty.PROP_SATIATION_VAL.getId(), Long.valueOf(satiation)); - propMap.put(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), penaltyValue); - - // Send packets - player.getSession().send(new PacketAvatarPropNotify(avatar, propMap)); - player.getSession().send(new PacketAvatarSatiationDataNotify(avatar, finishTime, penaltyTime)); - return true; - } - - public synchronized boolean addSatiationDirectly(Avatar avatar, int value) { - if (!avatar.addSatiation(value)) - return false; - // Update avatar - avatar.save(); - return true; - } - - public synchronized void removeSatiationDirectly(Avatar avatar, int value) { - avatar.reduceSatiation(value); - avatar.reduceSatiationPenalty(3000); - avatar.save(); - // Update avatar to no satiation - updateSingleAvatar(avatar, 0); - } - - public synchronized void reduceSatiation() { - /* Satiation may not reduce while paused on official but it will here */ - // Get all avatars with satiation - player.getAvatars().forEach(avatar -> { - // Ensure avatar isn't stuck in penalty - if (avatar.getSatiationPenalty() > 0 && avatar.getSatiation() == 0) { - avatar.reduceSatiationPenalty(3000); - } - - // Reduce satiation - if (avatar.getSatiation() > 0) { - // Reduce penalty first - if (avatar.getSatiationPenalty() > 0) { - // Penalty reduction rate is 1/s - avatar.reduceSatiationPenalty(100); - } else { - // Satiation reduction rate is 0.3/s - avatar.reduceSatiation(30); - - // Update all packets every tick else it won't work - // Surely there is a better way to handle this - addSatiation(avatar, 0, 0); - } - } - }); - } - - /******************** - * Player Updates - ********************/ - public synchronized void updateSingleAvatar(Avatar avatar, float givenTime) { - float time = (player.getClientTime() / 1000) + givenTime; - player.getSession().send(new PacketAvatarPropNotify(avatar)); - player.getSession().send(new PacketAvatarSatiationDataNotify(time, avatar)); - } - - private void updateTime() { - player.getSession().send(new PacketPlayerGameTimeNotify(player)); - player.getSession().send(new PacketPlayerTimeNotify(player)); - } - -} +package emu.grasscutter.game.managers; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.server.packet.send.PacketAvatarPropNotify; +import emu.grasscutter.server.packet.send.PacketAvatarSatiationDataNotify; +import emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify; +import emu.grasscutter.server.packet.send.PacketPlayerTimeNotify; +import java.util.HashMap; +import java.util.Map; + +public class SatiationManager extends BasePlayerManager { + + public SatiationManager(Player player) { + super(player); + } + + /******************** + * Change satiation + ********************/ + public synchronized boolean addSatiation(Avatar avatar, float satiationIncrease, int itemId) { + + // Satiation is max 10000 but can go over in the case of overeating + Map propMap = new HashMap<>(); + int satiation = Math.round(satiationIncrease * 100); + float totalSatiation = ((satiationIncrease * 100) + avatar.getSatiation()); + + // Update client time + updateTime(); + + // Calculate times + var playerTime = (player.getClientTime() / 1000); + float finishTime = playerTime + (totalSatiation / 30); + + // Penalty + long penaltyTime = playerTime; + long penaltyValue = avatar.getSatiationPenalty(); + if (totalSatiation + avatar.getSatiation() > 10000 && penaltyValue == 0) { + // Penalty is always 30sec + penaltyTime += 30; + penaltyValue = 3000; + } + + // Add satiation + if (!addSatiationDirectly(avatar, satiation)) return false; + propMap.put(PlayerProperty.PROP_SATIATION_VAL.getId(), Long.valueOf(satiation)); + propMap.put(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), penaltyValue); + + // Send packets + player.getSession().send(new PacketAvatarPropNotify(avatar, propMap)); + player.getSession().send(new PacketAvatarSatiationDataNotify(avatar, finishTime, penaltyTime)); + return true; + } + + public synchronized boolean addSatiationDirectly(Avatar avatar, int value) { + if (!avatar.addSatiation(value)) return false; + // Update avatar + avatar.save(); + return true; + } + + public synchronized void removeSatiationDirectly(Avatar avatar, int value) { + avatar.reduceSatiation(value); + avatar.reduceSatiationPenalty(3000); + avatar.save(); + // Update avatar to no satiation + updateSingleAvatar(avatar, 0); + } + + public synchronized void reduceSatiation() { + /* Satiation may not reduce while paused on official but it will here */ + // Get all avatars with satiation + player + .getAvatars() + .forEach( + avatar -> { + // Ensure avatar isn't stuck in penalty + if (avatar.getSatiationPenalty() > 0 && avatar.getSatiation() == 0) { + avatar.reduceSatiationPenalty(3000); + } + + // Reduce satiation + if (avatar.getSatiation() > 0) { + // Reduce penalty first + if (avatar.getSatiationPenalty() > 0) { + // Penalty reduction rate is 1/s + avatar.reduceSatiationPenalty(100); + } else { + // Satiation reduction rate is 0.3/s + avatar.reduceSatiation(30); + + // Update all packets every tick else it won't work + // Surely there is a better way to handle this + addSatiation(avatar, 0, 0); + } + } + }); + } + + /******************** + * Player Updates + ********************/ + public synchronized void updateSingleAvatar(Avatar avatar, float givenTime) { + float time = (player.getClientTime() / 1000) + givenTime; + player.getSession().send(new PacketAvatarPropNotify(avatar)); + player.getSession().send(new PacketAvatarSatiationDataNotify(time, avatar)); + } + + private void updateTime() { + player.getSession().send(new PacketPlayerGameTimeNotify(player)); + player.getSession().send(new PacketPlayerTimeNotify(player)); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/SotSManager.java b/src/main/java/emu/grasscutter/game/managers/SotSManager.java index f6f71b6dd..552e50472 100644 --- a/src/main/java/emu/grasscutter/game/managers/SotSManager.java +++ b/src/main/java/emu/grasscutter/game/managers/SotSManager.java @@ -1,190 +1,211 @@ -package emu.grasscutter.game.managers; - -import ch.qos.logback.classic.Logger; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; -import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; - -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -// Statue of the Seven Manager -public class SotSManager extends BasePlayerManager { - - // NOTE: Spring volume balance *1 = fight prop HP *100 - - public final static int GlobalMaximumSpringVolume = PlayerProperty.PROP_MAX_SPRING_VOLUME.getMax(); - private final Logger logger = Grasscutter.getLogger(); - private final boolean enablePriorityHealing = false; - private Timer autoRecoverTimer; - - public SotSManager(Player player) { - super(player); - } - - public boolean getIsAutoRecoveryEnabled() { - return player.getProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE) == 1; - } - - public void setIsAutoRecoveryEnabled(boolean enabled) { - player.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, enabled ? 1 : 0); - player.save(); - } - - public int getAutoRecoveryPercentage() { - return player.getProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT); - } - - public void setAutoRecoveryPercentage(int percentage) { - player.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, percentage); - player.save(); - } - - public long getLastUsed() { - return player.getSpringLastUsed(); - } - - public void setLastUsed() { - player.setSpringLastUsed(System.currentTimeMillis() / 1000); - player.save(); - } - - public int getMaxVolume() { - return player.getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); - } - - public void setMaxVolume(int volume) { - player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, volume); - player.save(); - } - - public int getCurrentVolume() { - return player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); - } - - public void setCurrentVolume(int volume) { - player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, volume); - setLastUsed(); - player.save(); - } - - public void handleEnterTransPointRegionNotify() { - logger.trace("Player entered statue region"); - autoRevive(); - if (autoRecoverTimer == null) { - autoRecoverTimer = new Timer(); - autoRecoverTimer.schedule(new AutoRecoverTimerTick(), 2500, 15000); - } - } - - public void handleExitTransPointRegionNotify() { - logger.trace("Player left statue region"); - if (autoRecoverTimer != null) { - autoRecoverTimer.cancel(); - autoRecoverTimer = null; - } - } - - // autoRevive automatically revives all team members. - public void autoRevive() { - player.getTeamManager().getActiveTeam().forEach(entity -> { - boolean isAlive = entity.isAlive(); - if (isAlive) { - return; - } - logger.trace("Reviving avatar " + entity.getAvatar().getAvatarData().getName()); - player.getTeamManager().reviveAvatar(entity.getAvatar()); - player.getTeamManager().healAvatar(entity.getAvatar(), 30, 0); - }); - } - - public void checkAndHealAvatar(EntityAvatar entity) { - int maxHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * 100); - int currentHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) * 100); - if (currentHP == maxHP) { - return; - } - int targetHP = maxHP * getAutoRecoveryPercentage() / 100; - - if (targetHP > currentHP) { - int needHP = targetHP - currentHP; - int currentVolume = getCurrentVolume(); - if (currentVolume >= needHP) { - // sufficient - setCurrentVolume(currentVolume - needHP); - } else { - // insufficient balance - needHP = currentVolume; - setCurrentVolume(0); - } - if (needHP > 0) { - logger.trace("Healing avatar " + entity.getAvatar().getAvatarData().getName() + " +" + needHP); - player.getTeamManager().healAvatar(entity.getAvatar(), 0, needHP); - player.getSession().send(new PacketEntityFightPropChangeReasonNotify(entity, FightProperty.FIGHT_PROP_CUR_HP, - ((float) needHP / 100), List.of(3), PropChangeReason.PROP_CHANGE_REASON_STATUE_RECOVER, - ChangeHpReason.CHANGE_HP_REASON_ADD_STATUE)); - player.getSession().send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); - - } - } - } - - public void refillSpringVolume() { - // Temporary: Max spring volume depends on level of the statues in Mondstadt and Liyue. Override until we have statue level. - // TODO: remove - // https://genshin-impact.fandom.com/wiki/Statue_of_The_Seven#:~:text=region%20of%20Inazuma.-,Statue%20Levels,-Upon%20first%20unlocking - setMaxVolume(8500000); - // Temporary: Auto enable 100% statue recovery until we can adjust statue settings in game - // TODO: remove - setAutoRecoveryPercentage(100); - setIsAutoRecoveryEnabled(true); - - int maxVolume = getMaxVolume(); - int currentVolume = getCurrentVolume(); - if (currentVolume < maxVolume) { - long now = System.currentTimeMillis() / 1000; - int secondsSinceLastUsed = (int) (now - getLastUsed()); - // 15s = 1% max volume - int volumeRefilled = secondsSinceLastUsed * maxVolume / 15 / 100; - logger.trace("Statue has refilled HP volume: " + volumeRefilled); - currentVolume = Math.min(currentVolume + volumeRefilled, maxVolume); - logger.trace("Statue remaining HP volume: " + currentVolume); - setCurrentVolume(currentVolume); - } - } - - private class AutoRecoverTimerTick extends TimerTask { - // autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level. - public void run() { - refillSpringVolume(); - - logger.trace("isAutoRecoveryEnabled: " + getIsAutoRecoveryEnabled() + "\tautoRecoverPercentage: " + getAutoRecoveryPercentage()); - - if (getIsAutoRecoveryEnabled()) { - List activeTeam = player.getTeamManager().getActiveTeam(); - // When the statue does not have enough remaining volume: - // Enhanced experience: Enable priority healing - // The current active character will get healed first, then sequential. - // Vanilla experience: Disable priority healing - // Sequential healing based on character index. - int priorityIndex = enablePriorityHealing ? player.getTeamManager().getCurrentCharacterIndex() : -1; - if (priorityIndex >= 0) { - checkAndHealAvatar(activeTeam.get(priorityIndex)); - } - for (int i = 0; i < activeTeam.size(); i++) { - if (i != priorityIndex) { - checkAndHealAvatar(activeTeam.get(i)); - } - } - } - } - } -} +package emu.grasscutter.game.managers; + +import ch.qos.logback.classic.Logger; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +// Statue of the Seven Manager +public class SotSManager extends BasePlayerManager { + + // NOTE: Spring volume balance *1 = fight prop HP *100 + + public static final int GlobalMaximumSpringVolume = + PlayerProperty.PROP_MAX_SPRING_VOLUME.getMax(); + private final Logger logger = Grasscutter.getLogger(); + private final boolean enablePriorityHealing = false; + private Timer autoRecoverTimer; + + public SotSManager(Player player) { + super(player); + } + + public boolean getIsAutoRecoveryEnabled() { + return player.getProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE) == 1; + } + + public void setIsAutoRecoveryEnabled(boolean enabled) { + player.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, enabled ? 1 : 0); + player.save(); + } + + public int getAutoRecoveryPercentage() { + return player.getProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT); + } + + public void setAutoRecoveryPercentage(int percentage) { + player.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, percentage); + player.save(); + } + + public long getLastUsed() { + return player.getSpringLastUsed(); + } + + public void setLastUsed() { + player.setSpringLastUsed(System.currentTimeMillis() / 1000); + player.save(); + } + + public int getMaxVolume() { + return player.getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); + } + + public void setMaxVolume(int volume) { + player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, volume); + player.save(); + } + + public int getCurrentVolume() { + return player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); + } + + public void setCurrentVolume(int volume) { + player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, volume); + setLastUsed(); + player.save(); + } + + public void handleEnterTransPointRegionNotify() { + logger.trace("Player entered statue region"); + autoRevive(); + if (autoRecoverTimer == null) { + autoRecoverTimer = new Timer(); + autoRecoverTimer.schedule(new AutoRecoverTimerTick(), 2500, 15000); + } + } + + public void handleExitTransPointRegionNotify() { + logger.trace("Player left statue region"); + if (autoRecoverTimer != null) { + autoRecoverTimer.cancel(); + autoRecoverTimer = null; + } + } + + // autoRevive automatically revives all team members. + public void autoRevive() { + player + .getTeamManager() + .getActiveTeam() + .forEach( + entity -> { + boolean isAlive = entity.isAlive(); + if (isAlive) { + return; + } + logger.trace("Reviving avatar " + entity.getAvatar().getAvatarData().getName()); + player.getTeamManager().reviveAvatar(entity.getAvatar()); + player.getTeamManager().healAvatar(entity.getAvatar(), 30, 0); + }); + } + + public void checkAndHealAvatar(EntityAvatar entity) { + int maxHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * 100); + int currentHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) * 100); + if (currentHP == maxHP) { + return; + } + int targetHP = maxHP * getAutoRecoveryPercentage() / 100; + + if (targetHP > currentHP) { + int needHP = targetHP - currentHP; + int currentVolume = getCurrentVolume(); + if (currentVolume >= needHP) { + // sufficient + setCurrentVolume(currentVolume - needHP); + } else { + // insufficient balance + needHP = currentVolume; + setCurrentVolume(0); + } + if (needHP > 0) { + logger.trace( + "Healing avatar " + entity.getAvatar().getAvatarData().getName() + " +" + needHP); + player.getTeamManager().healAvatar(entity.getAvatar(), 0, needHP); + player + .getSession() + .send( + new PacketEntityFightPropChangeReasonNotify( + entity, + FightProperty.FIGHT_PROP_CUR_HP, + ((float) needHP / 100), + List.of(3), + PropChangeReason.PROP_CHANGE_REASON_STATUE_RECOVER, + ChangeHpReason.CHANGE_HP_REASON_ADD_STATUE)); + player + .getSession() + .send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + } + } + } + + public void refillSpringVolume() { + // Temporary: Max spring volume depends on level of the statues in Mondstadt and Liyue. Override + // until we have statue level. + // TODO: remove + // https://genshin-impact.fandom.com/wiki/Statue_of_The_Seven#:~:text=region%20of%20Inazuma.-,Statue%20Levels,-Upon%20first%20unlocking + setMaxVolume(8500000); + // Temporary: Auto enable 100% statue recovery until we can adjust statue settings in game + // TODO: remove + setAutoRecoveryPercentage(100); + setIsAutoRecoveryEnabled(true); + + int maxVolume = getMaxVolume(); + int currentVolume = getCurrentVolume(); + if (currentVolume < maxVolume) { + long now = System.currentTimeMillis() / 1000; + int secondsSinceLastUsed = (int) (now - getLastUsed()); + // 15s = 1% max volume + int volumeRefilled = secondsSinceLastUsed * maxVolume / 15 / 100; + logger.trace("Statue has refilled HP volume: " + volumeRefilled); + currentVolume = Math.min(currentVolume + volumeRefilled, maxVolume); + logger.trace("Statue remaining HP volume: " + currentVolume); + setCurrentVolume(currentVolume); + } + } + + private class AutoRecoverTimerTick extends TimerTask { + // autoRecover checks player setting to see if auto recover is enabled, and refill HP to the + // predefined level. + public void run() { + refillSpringVolume(); + + logger.trace( + "isAutoRecoveryEnabled: " + + getIsAutoRecoveryEnabled() + + "\tautoRecoverPercentage: " + + getAutoRecoveryPercentage()); + + if (getIsAutoRecoveryEnabled()) { + List activeTeam = player.getTeamManager().getActiveTeam(); + // When the statue does not have enough remaining volume: + // Enhanced experience: Enable priority healing + // The current active character will get healed first, then + // sequential. + // Vanilla experience: Disable priority healing + // Sequential healing based on character index. + int priorityIndex = + enablePriorityHealing ? player.getTeamManager().getCurrentCharacterIndex() : -1; + if (priorityIndex >= 0) { + checkAndHealAvatar(activeTeam.get(priorityIndex)); + } + for (int i = 0; i < activeTeam.size(); i++) { + if (i != priorityIndex) { + checkAndHealAvatar(activeTeam.get(i)); + } + } + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomActivity.java b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomActivity.java index 01ffc79ab..55a62f124 100644 --- a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomActivity.java +++ b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomActivity.java @@ -1,144 +1,148 @@ -package emu.grasscutter.game.managers.blossom; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.MonsterData; -import emu.grasscutter.data.excels.WorldLevelData; -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; -import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.scripts.data.SceneBossChest; -import emu.grasscutter.scripts.data.SceneGadget; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; - -public class BlossomActivity { - - private static final int BLOOMING_GADGET_ID = 70210109; - private final SceneGroup tempSceneGroup; - private final WorldChallenge challenge; - private final EntityGadget gadget; - private final int goal; - private final int worldLevel; - private final List activeMonsters = new ArrayList<>(); - private final Queue candidateMonsters = new ArrayDeque<>(); - private EntityGadget chest; - private int step; - private int generatedCount; - private boolean pass = false; - - public BlossomActivity(EntityGadget entityGadget, List monsters, int timeout, int worldLevel) { - this.tempSceneGroup = new SceneGroup(); - this.tempSceneGroup.id = entityGadget.getId(); - this.gadget = entityGadget; - this.step = 0; - this.goal = monsters.size(); - this.candidateMonsters.addAll(monsters); - this.worldLevel = worldLevel; - ArrayList challengeTriggers = new ArrayList<>(); - this.challenge = new WorldChallenge(entityGadget.getScene(), - tempSceneGroup, - 1, - 1, - List.of(goal, timeout), - timeout, - goal, challengeTriggers); - challengeTriggers.add(new KillMonsterTrigger()); - //this.challengeTriggers.add(new InTimeTrigger()); - } - - public WorldChallenge getChallenge() { - return this.challenge; - } - - public void setMonsters(List monsters) { - this.activeMonsters.clear(); - this.activeMonsters.addAll(monsters); - for (EntityMonster monster : monsters) { - monster.setGroupId(this.tempSceneGroup.id); - } - } - - public int getAliveMonstersCount() { - int count = 0; - for (EntityMonster monster : activeMonsters) { - if (monster.isAlive()) { - count++; - } - } - return count; - } - - public boolean getPass() { - return pass; - } - - public void start() { - challenge.start(); - } - - public void onTick() { - Scene scene = gadget.getScene(); - Position pos = gadget.getPosition(); - if (getAliveMonstersCount() <= 2) { - if (generatedCount < goal) { - step++; - - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(worldLevel); - int worldLevelOverride = 0; - if (worldLevelData != null) { - worldLevelOverride = worldLevelData.getMonsterLevel(); - } - - List newMonsters = new ArrayList<>(); - int willSpawn = Utils.randomRange(3, 5); - if (generatedCount + willSpawn > goal) { - willSpawn = goal - generatedCount; - } - generatedCount += willSpawn; - for (int i = 0; i < willSpawn; i++) { - MonsterData monsterData = GameData.getMonsterDataMap().get(candidateMonsters.poll()); - int level = scene.getEntityLevel(1, worldLevelOverride); - EntityMonster entity = new EntityMonster(scene, monsterData, pos.nearby2d(4f), level); - scene.addEntity(entity); - newMonsters.add(entity); - } - setMonsters(newMonsters); - } else { - if (getAliveMonstersCount() == 0) { - this.pass = true; - this.challenge.done(); - } - } - } - } - - public EntityGadget getGadget() { - return gadget; - } - - public EntityGadget getChest() { - if (chest == null) { - EntityGadget rewardGadget = new EntityGadget(gadget.getScene(), BLOOMING_GADGET_ID, gadget.getPosition()); - SceneGadget metaGadget = new SceneGadget(); - metaGadget.boss_chest = new SceneBossChest(); - metaGadget.boss_chest.resin = 20; - rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, Float.POSITIVE_INFINITY); - rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Float.POSITIVE_INFINITY); - rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, Float.POSITIVE_INFINITY); - rewardGadget.setMetaGadget(metaGadget); - rewardGadget.buildContent(); - chest = rewardGadget; - } - return chest; - } -} +package emu.grasscutter.game.managers.blossom; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.WorldLevelData; +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger; +import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.scripts.data.SceneBossChest; +import emu.grasscutter.scripts.data.SceneGadget; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +public class BlossomActivity { + + private static final int BLOOMING_GADGET_ID = 70210109; + private final SceneGroup tempSceneGroup; + private final WorldChallenge challenge; + private final EntityGadget gadget; + private final int goal; + private final int worldLevel; + private final List activeMonsters = new ArrayList<>(); + private final Queue candidateMonsters = new ArrayDeque<>(); + private EntityGadget chest; + private int step; + private int generatedCount; + private boolean pass = false; + + public BlossomActivity( + EntityGadget entityGadget, List monsters, int timeout, int worldLevel) { + this.tempSceneGroup = new SceneGroup(); + this.tempSceneGroup.id = entityGadget.getId(); + this.gadget = entityGadget; + this.step = 0; + this.goal = monsters.size(); + this.candidateMonsters.addAll(monsters); + this.worldLevel = worldLevel; + ArrayList challengeTriggers = new ArrayList<>(); + this.challenge = + new WorldChallenge( + entityGadget.getScene(), + tempSceneGroup, + 1, + 1, + List.of(goal, timeout), + timeout, + goal, + challengeTriggers); + challengeTriggers.add(new KillMonsterTrigger()); + // this.challengeTriggers.add(new InTimeTrigger()); + } + + public WorldChallenge getChallenge() { + return this.challenge; + } + + public void setMonsters(List monsters) { + this.activeMonsters.clear(); + this.activeMonsters.addAll(monsters); + for (EntityMonster monster : monsters) { + monster.setGroupId(this.tempSceneGroup.id); + } + } + + public int getAliveMonstersCount() { + int count = 0; + for (EntityMonster monster : activeMonsters) { + if (monster.isAlive()) { + count++; + } + } + return count; + } + + public boolean getPass() { + return pass; + } + + public void start() { + challenge.start(); + } + + public void onTick() { + Scene scene = gadget.getScene(); + Position pos = gadget.getPosition(); + if (getAliveMonstersCount() <= 2) { + if (generatedCount < goal) { + step++; + + WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(worldLevel); + int worldLevelOverride = 0; + if (worldLevelData != null) { + worldLevelOverride = worldLevelData.getMonsterLevel(); + } + + List newMonsters = new ArrayList<>(); + int willSpawn = Utils.randomRange(3, 5); + if (generatedCount + willSpawn > goal) { + willSpawn = goal - generatedCount; + } + generatedCount += willSpawn; + for (int i = 0; i < willSpawn; i++) { + MonsterData monsterData = GameData.getMonsterDataMap().get(candidateMonsters.poll()); + int level = scene.getEntityLevel(1, worldLevelOverride); + EntityMonster entity = new EntityMonster(scene, monsterData, pos.nearby2d(4f), level); + scene.addEntity(entity); + newMonsters.add(entity); + } + setMonsters(newMonsters); + } else { + if (getAliveMonstersCount() == 0) { + this.pass = true; + this.challenge.done(); + } + } + } + } + + public EntityGadget getGadget() { + return gadget; + } + + public EntityGadget getChest() { + if (chest == null) { + EntityGadget rewardGadget = + new EntityGadget(gadget.getScene(), BLOOMING_GADGET_ID, gadget.getPosition()); + SceneGadget metaGadget = new SceneGadget(); + metaGadget.boss_chest = new SceneBossChest(); + metaGadget.boss_chest.resin = 20; + rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, Float.POSITIVE_INFINITY); + rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Float.POSITIVE_INFINITY); + rewardGadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, Float.POSITIVE_INFINITY); + rewardGadget.setMetaGadget(metaGadget); + rewardGadget.buildContent(); + chest = rewardGadget; + } + return chest; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomConfig.java b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomConfig.java index 7bc512e02..2878be5cb 100644 --- a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomConfig.java +++ b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomConfig.java @@ -1,14 +1,12 @@ -package emu.grasscutter.game.managers.blossom; - -import lombok.Getter; - -import java.util.List; -import java.util.Map; - -public class BlossomConfig { - @Getter - private int monsterFightingVolume; - // @Getter private Int2ObjectMap monsterIdsPerDifficulty; // Need to wrangle Gson for this - @Getter - private Map> monsterIdsPerDifficulty; -} +package emu.grasscutter.game.managers.blossom; + +import java.util.List; +import java.util.Map; +import lombok.Getter; + +public class BlossomConfig { + @Getter private int monsterFightingVolume; + // @Getter private Int2ObjectMap monsterIdsPerDifficulty; // Need to wrangle Gson for + // this + @Getter private Map> monsterIdsPerDifficulty; +} diff --git a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomManager.java b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomManager.java index 7a75c7c1b..a170ab012 100644 --- a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomManager.java +++ b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomManager.java @@ -1,235 +1,243 @@ -package emu.grasscutter.game.managers.blossom; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameDepot; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.RewardPreviewData; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.entity.gadget.GadgetWorktop; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.game.world.SpawnDataEntry; -import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; -import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass; -import emu.grasscutter.net.proto.VisionTypeOuterClass; -import emu.grasscutter.server.packet.send.PacketBlossomBriefInfoNotify; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; - -import java.util.ArrayList; -import java.util.List; - -public class BlossomManager { - private final Scene scene; - private final List blossomActivities = new ArrayList<>(); - private final List activeChests = new ArrayList<>(); - private final List createdEntity = new ArrayList<>(); - private final List blossomConsumed = new ArrayList<>(); - - public BlossomManager(Scene scene) { - this.scene = scene; - } - - private static Integer getPreviewReward(BlossomType type, int worldLevel) { - // TODO: blossoms should be based on their city - if (type == null) { - Grasscutter.getLogger().error("Illegal blossom type {}", type); - return null; - } - - int blossomChestId = type.getBlossomChestId(); - var dataMap = GameData.getBlossomRefreshExcelConfigDataMap(); - for (var data : dataMap.values()) { - if (blossomChestId == data.getBlossomChestId()) { - var dropVecList = data.getDropVec(); - if (worldLevel > dropVecList.length) { - Grasscutter.getLogger().error("Illegal world level {}", worldLevel); - return null; - } - return dropVecList[worldLevel].getPreviewReward(); - } - } - Grasscutter.getLogger().error("Cannot find blossom type {}", type); - return null; - } - - private static RewardPreviewData getRewardList(BlossomType type, int worldLevel) { - Integer previewReward = getPreviewReward(type, worldLevel); - if (previewReward == null) return null; - return GameData.getRewardPreviewDataMap().get((int) previewReward); - } - - public static IntList getRandomMonstersID(int difficulty, int count) { - IntList result = new IntArrayList(); - List monsters = GameDepot.getBlossomConfig().getMonsterIdsPerDifficulty().get(difficulty); - for (int i = 0; i < count; i++) { - result.add((int) monsters.get(Utils.randomRange(0, monsters.size() - 1))); - } - return result; - } - - public void onTick() { - synchronized (blossomActivities) { - var it = blossomActivities.iterator(); - while (it.hasNext()) { - var active = it.next(); - active.onTick(); - if (active.getPass()) { - EntityGadget chest = active.getChest(); - scene.addEntity(chest); - scene.setChallenge(null); - activeChests.add(active); - it.remove(); - } - } - } - } - - public void recycleGadgetEntity(List entities) { - for (var entity : entities) { - if (entity instanceof EntityGadget gadget) { - createdEntity.remove(gadget); - } - } - notifyIcon(); - } - - public void initBlossom(EntityGadget gadget) { - if (createdEntity.contains(gadget)) { - return; - } - if (blossomConsumed.contains(gadget.getSpawnEntry())) { - return; - } - var id = gadget.getGadgetId(); - if (BlossomType.valueOf(id) == null) { - return; - } - gadget.buildContent(); - gadget.setState(204); - int worldLevel = getWorldLevel(); - GadgetWorktop gadgetWorktop = ((GadgetWorktop) gadget.getContent()); - gadgetWorktop.addWorktopOptions(new int[]{187}); - gadgetWorktop.setOnSelectWorktopOptionEvent((GadgetWorktop context, int option) -> { - BlossomActivity activity; - EntityGadget entityGadget = context.getGadget(); - synchronized (blossomActivities) { - for (BlossomActivity i : this.blossomActivities) { - if (i.getGadget() == entityGadget) { - return false; - } - } - - int volume = 0; - IntList monsters = new IntArrayList(); - while (true) { - var remain = GameDepot.getBlossomConfig().getMonsterFightingVolume() - volume; - if (remain <= 0) { - break; - } - var rand = Utils.randomRange(1, 100); - if (rand > 85 && remain >= 50) {//15% ,generate strong monster - monsters.addAll(getRandomMonstersID(2, 1)); - volume += 50; - } else if (rand > 50 && remain >= 20) {//35% ,generate normal monster - monsters.addAll(getRandomMonstersID(1, 1)); - volume += 20; - } else {//50% ,generate weak monster - monsters.addAll(getRandomMonstersID(0, 1)); - volume += 10; - } - } - - Grasscutter.getLogger().info("Blossom Monsters:" + monsters); - - activity = new BlossomActivity(entityGadget, monsters, -1, worldLevel); - blossomActivities.add(activity); - } - entityGadget.updateState(201); - scene.setChallenge(activity.getChallenge()); - scene.removeEntity(entityGadget, VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE); - activity.start(); - return true; - }); - createdEntity.add(gadget); - notifyIcon(); - } - - public void notifyIcon() { - final int wl = getWorldLevel(); - final int worldLevel = (wl < 0) ? 0 : ((wl > 8) ? 8 : wl); - final var worldLevelData = GameData.getWorldLevelDataMap().get(worldLevel); - final int monsterLevel = (worldLevelData != null) ? worldLevelData.getMonsterLevel() : 1; - List blossoms = new ArrayList<>(); - GameDepot.getSpawnLists().forEach((gridBlockId, spawnDataEntryList) -> { - int sceneId = gridBlockId.getSceneId(); - spawnDataEntryList.stream() - .map(SpawnDataEntry::getGroup) - .map(SpawnGroupEntry::getSpawns) - .flatMap(List::stream) - .filter(spawn -> !blossomConsumed.contains(spawn)) - .filter(spawn -> BlossomType.valueOf(spawn.getGadgetId()) != null) - .forEach(spawn -> { - var type = BlossomType.valueOf(spawn.getGadgetId()); - int previewReward = getPreviewReward(type, worldLevel); - blossoms.add(BlossomBriefInfoOuterClass.BlossomBriefInfo.newBuilder() - .setSceneId(sceneId) - .setPos(spawn.getPos().toProto()) - .setResin(20) - .setMonsterLevel(monsterLevel) - .setRewardId(previewReward) - .setCircleCampId(type.getCircleCampId()) - .setRefreshId(type.getBlossomChestId()) // TODO: replace when using actual leylines - .build() - ); - }); - }); - scene.broadcastPacket(new PacketBlossomBriefInfoNotify(blossoms)); - } - - public int getWorldLevel() { - return scene.getWorld().getWorldLevel(); - } - - public List onReward(Player player, EntityGadget chest, boolean useCondensedResin) { - var resinManager = player.getResinManager(); - synchronized (activeChests) { - var it = activeChests.iterator(); - while (it.hasNext()) { - var activeChest = it.next(); - if (activeChest.getChest() == chest) { - boolean pay = useCondensedResin ? resinManager.useCondensedResin(1) : resinManager.useResin(20); - if (pay) { - int worldLevel = getWorldLevel(); - List items = new ArrayList<>(); - var gadget = activeChest.getGadget(); - var type = BlossomType.valueOf(gadget.getGadgetId()); - RewardPreviewData blossomRewards = getRewardList(type, worldLevel); - if (blossomRewards == null) { - Grasscutter.getLogger().error("Blossom could not support world level : " + worldLevel); - return null; - } - var rewards = blossomRewards.getPreviewItems(); - for (ItemParamData blossomReward : rewards) { - int rewardCount = blossomReward.getCount(); - if (useCondensedResin) { - rewardCount += blossomReward.getCount(); // Double! - } - items.add(new GameItem(blossomReward.getItemId(), rewardCount)); - } - it.remove(); - recycleGadgetEntity(List.of(gadget)); - blossomConsumed.add(gadget.getSpawnEntry()); - return items; - } - return null; - } - } - } - return null; - } -} +package emu.grasscutter.game.managers.blossom; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.RewardPreviewData; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.entity.gadget.GadgetWorktop; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.game.world.SpawnDataEntry; +import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; +import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass; +import emu.grasscutter.net.proto.VisionTypeOuterClass; +import emu.grasscutter.server.packet.send.PacketBlossomBriefInfoNotify; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import java.util.ArrayList; +import java.util.List; + +public class BlossomManager { + private final Scene scene; + private final List blossomActivities = new ArrayList<>(); + private final List activeChests = new ArrayList<>(); + private final List createdEntity = new ArrayList<>(); + private final List blossomConsumed = new ArrayList<>(); + + public BlossomManager(Scene scene) { + this.scene = scene; + } + + private static Integer getPreviewReward(BlossomType type, int worldLevel) { + // TODO: blossoms should be based on their city + if (type == null) { + Grasscutter.getLogger().error("Illegal blossom type {}", type); + return null; + } + + int blossomChestId = type.getBlossomChestId(); + var dataMap = GameData.getBlossomRefreshExcelConfigDataMap(); + for (var data : dataMap.values()) { + if (blossomChestId == data.getBlossomChestId()) { + var dropVecList = data.getDropVec(); + if (worldLevel > dropVecList.length) { + Grasscutter.getLogger().error("Illegal world level {}", worldLevel); + return null; + } + return dropVecList[worldLevel].getPreviewReward(); + } + } + Grasscutter.getLogger().error("Cannot find blossom type {}", type); + return null; + } + + private static RewardPreviewData getRewardList(BlossomType type, int worldLevel) { + Integer previewReward = getPreviewReward(type, worldLevel); + if (previewReward == null) return null; + return GameData.getRewardPreviewDataMap().get((int) previewReward); + } + + public static IntList getRandomMonstersID(int difficulty, int count) { + IntList result = new IntArrayList(); + List monsters = + GameDepot.getBlossomConfig().getMonsterIdsPerDifficulty().get(difficulty); + for (int i = 0; i < count; i++) { + result.add((int) monsters.get(Utils.randomRange(0, monsters.size() - 1))); + } + return result; + } + + public void onTick() { + synchronized (blossomActivities) { + var it = blossomActivities.iterator(); + while (it.hasNext()) { + var active = it.next(); + active.onTick(); + if (active.getPass()) { + EntityGadget chest = active.getChest(); + scene.addEntity(chest); + scene.setChallenge(null); + activeChests.add(active); + it.remove(); + } + } + } + } + + public void recycleGadgetEntity(List entities) { + for (var entity : entities) { + if (entity instanceof EntityGadget gadget) { + createdEntity.remove(gadget); + } + } + notifyIcon(); + } + + public void initBlossom(EntityGadget gadget) { + if (createdEntity.contains(gadget)) { + return; + } + if (blossomConsumed.contains(gadget.getSpawnEntry())) { + return; + } + var id = gadget.getGadgetId(); + if (BlossomType.valueOf(id) == null) { + return; + } + gadget.buildContent(); + gadget.setState(204); + int worldLevel = getWorldLevel(); + GadgetWorktop gadgetWorktop = ((GadgetWorktop) gadget.getContent()); + gadgetWorktop.addWorktopOptions(new int[] {187}); + gadgetWorktop.setOnSelectWorktopOptionEvent( + (GadgetWorktop context, int option) -> { + BlossomActivity activity; + EntityGadget entityGadget = context.getGadget(); + synchronized (blossomActivities) { + for (BlossomActivity i : this.blossomActivities) { + if (i.getGadget() == entityGadget) { + return false; + } + } + + int volume = 0; + IntList monsters = new IntArrayList(); + while (true) { + var remain = GameDepot.getBlossomConfig().getMonsterFightingVolume() - volume; + if (remain <= 0) { + break; + } + var rand = Utils.randomRange(1, 100); + if (rand > 85 && remain >= 50) { // 15% ,generate strong monster + monsters.addAll(getRandomMonstersID(2, 1)); + volume += 50; + } else if (rand > 50 && remain >= 20) { // 35% ,generate normal monster + monsters.addAll(getRandomMonstersID(1, 1)); + volume += 20; + } else { // 50% ,generate weak monster + monsters.addAll(getRandomMonstersID(0, 1)); + volume += 10; + } + } + + Grasscutter.getLogger().info("Blossom Monsters:" + monsters); + + activity = new BlossomActivity(entityGadget, monsters, -1, worldLevel); + blossomActivities.add(activity); + } + entityGadget.updateState(201); + scene.setChallenge(activity.getChallenge()); + scene.removeEntity(entityGadget, VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE); + activity.start(); + return true; + }); + createdEntity.add(gadget); + notifyIcon(); + } + + public void notifyIcon() { + final int wl = getWorldLevel(); + final int worldLevel = (wl < 0) ? 0 : ((wl > 8) ? 8 : wl); + final var worldLevelData = GameData.getWorldLevelDataMap().get(worldLevel); + final int monsterLevel = (worldLevelData != null) ? worldLevelData.getMonsterLevel() : 1; + List blossoms = new ArrayList<>(); + GameDepot.getSpawnLists() + .forEach( + (gridBlockId, spawnDataEntryList) -> { + int sceneId = gridBlockId.getSceneId(); + spawnDataEntryList.stream() + .map(SpawnDataEntry::getGroup) + .map(SpawnGroupEntry::getSpawns) + .flatMap(List::stream) + .filter(spawn -> !blossomConsumed.contains(spawn)) + .filter(spawn -> BlossomType.valueOf(spawn.getGadgetId()) != null) + .forEach( + spawn -> { + var type = BlossomType.valueOf(spawn.getGadgetId()); + int previewReward = getPreviewReward(type, worldLevel); + blossoms.add( + BlossomBriefInfoOuterClass.BlossomBriefInfo.newBuilder() + .setSceneId(sceneId) + .setPos(spawn.getPos().toProto()) + .setResin(20) + .setMonsterLevel(monsterLevel) + .setRewardId(previewReward) + .setCircleCampId(type.getCircleCampId()) + .setRefreshId( + type.getBlossomChestId()) // TODO: replace when using actual + // leylines + .build()); + }); + }); + scene.broadcastPacket(new PacketBlossomBriefInfoNotify(blossoms)); + } + + public int getWorldLevel() { + return scene.getWorld().getWorldLevel(); + } + + public List onReward(Player player, EntityGadget chest, boolean useCondensedResin) { + var resinManager = player.getResinManager(); + synchronized (activeChests) { + var it = activeChests.iterator(); + while (it.hasNext()) { + var activeChest = it.next(); + if (activeChest.getChest() == chest) { + boolean pay = + useCondensedResin ? resinManager.useCondensedResin(1) : resinManager.useResin(20); + if (pay) { + int worldLevel = getWorldLevel(); + List items = new ArrayList<>(); + var gadget = activeChest.getGadget(); + var type = BlossomType.valueOf(gadget.getGadgetId()); + RewardPreviewData blossomRewards = getRewardList(type, worldLevel); + if (blossomRewards == null) { + Grasscutter.getLogger() + .error("Blossom could not support world level : " + worldLevel); + return null; + } + var rewards = blossomRewards.getPreviewItems(); + for (ItemParamData blossomReward : rewards) { + int rewardCount = blossomReward.getCount(); + if (useCondensedResin) { + rewardCount += blossomReward.getCount(); // Double! + } + items.add(new GameItem(blossomReward.getItemId(), rewardCount)); + } + it.remove(); + recycleGadgetEntity(List.of(gadget)); + blossomConsumed.add(gadget.getSpawnEntry()); + return items; + } + return null; + } + } + } + return null; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomType.java b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomType.java index 0e63c1e35..ee28bc2a9 100644 --- a/src/main/java/emu/grasscutter/game/managers/blossom/BlossomType.java +++ b/src/main/java/emu/grasscutter/game/managers/blossom/BlossomType.java @@ -1,39 +1,35 @@ -package emu.grasscutter.game.managers.blossom; - -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public enum BlossomType { - GOLD(70360056, 101001001, 1), - BLUE(70360057, 101002003, 2); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>( - Stream.of(values()).collect(Collectors.toMap(x -> x.getGadgetId(), x -> x)) - ); - @Getter - private final int gadgetId; - @Getter - private final int circleCampId; - @Getter - private final int blossomChestId; - - BlossomType(int gadgetId, int circleCampId, int blossomChestId) { - this.gadgetId = gadgetId; - this.circleCampId = circleCampId; - this.blossomChestId = blossomChestId; - } - - public static BlossomType valueOf(int i) { - return map.get(i); - } - - public static BlossomType random() { - BlossomType[] values = values(); - return values[Utils.randomRange(0, values.length)]; - } -} +package emu.grasscutter.game.managers.blossom; + +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lombok.Getter; + +public enum BlossomType { + GOLD(70360056, 101001001, 1), + BLUE(70360057, 101002003, 2); + + private static final Int2ObjectMap map = + new Int2ObjectOpenHashMap<>( + Stream.of(values()).collect(Collectors.toMap(x -> x.getGadgetId(), x -> x))); + @Getter private final int gadgetId; + @Getter private final int circleCampId; + @Getter private final int blossomChestId; + + BlossomType(int gadgetId, int circleCampId, int blossomChestId) { + this.gadgetId = gadgetId; + this.circleCampId = circleCampId; + this.blossomChestId = blossomChestId; + } + + public static BlossomType valueOf(int i) { + return map.get(i); + } + + public static BlossomType random() { + BlossomType[] values = values(); + return values[Utils.randomRange(0, values.length)]; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/cooking/ActiveCookCompoundData.java b/src/main/java/emu/grasscutter/game/managers/cooking/ActiveCookCompoundData.java index 677c27edc..2d91dc899 100644 --- a/src/main/java/emu/grasscutter/game/managers/cooking/ActiveCookCompoundData.java +++ b/src/main/java/emu/grasscutter/game/managers/cooking/ActiveCookCompoundData.java @@ -1,59 +1,53 @@ -package emu.grasscutter.game.managers.cooking; - -import dev.morphia.annotations.Entity; -import lombok.Getter; - - -@Entity -public class ActiveCookCompoundData { - private final int costTime; - @Getter - private final int compoundId; - @Getter - private int totalCount; - private int startTime; - - public ActiveCookCompoundData(int compoundId, int processTime, int count, int startTime) { - this.compoundId = compoundId; - this.costTime = processTime; - this.totalCount = count; - this.startTime = startTime; - } - - public int getOutputCount(int currentTime) { - int cnt = (currentTime - startTime) / costTime; - if (cnt > totalCount) return totalCount; - else return cnt; - } - - public int getWaitCount(int currentTime) { - return totalCount - getOutputCount(currentTime); - } - - /** - * Get the timestamp of next output. - * If all finished,return 0 - */ - public int getOutputTime(int currentTime) { - int cnt = getOutputCount(currentTime); - if (cnt == totalCount) return 0; - else return startTime + (cnt + 1) * costTime; - } - - public void addCompound(int count, int currentTime) { - if (getOutputCount(currentTime) == totalCount) startTime = currentTime - totalCount * costTime; - totalCount += count; - } - - /** - * Take away all finished compound. - * - * @return The number of finished items. - */ - public int takeCompound(int currentTime) { - int count = getOutputCount(currentTime); - startTime += costTime * count; - totalCount -= count; - return count; - } -} +package emu.grasscutter.game.managers.cooking; + +import dev.morphia.annotations.Entity; +import lombok.Getter; + +@Entity +public class ActiveCookCompoundData { + private final int costTime; + @Getter private final int compoundId; + @Getter private int totalCount; + private int startTime; + + public ActiveCookCompoundData(int compoundId, int processTime, int count, int startTime) { + this.compoundId = compoundId; + this.costTime = processTime; + this.totalCount = count; + this.startTime = startTime; + } + + public int getOutputCount(int currentTime) { + int cnt = (currentTime - startTime) / costTime; + if (cnt > totalCount) return totalCount; + else return cnt; + } + + public int getWaitCount(int currentTime) { + return totalCount - getOutputCount(currentTime); + } + + /** Get the timestamp of next output. If all finished,return 0 */ + public int getOutputTime(int currentTime) { + int cnt = getOutputCount(currentTime); + if (cnt == totalCount) return 0; + else return startTime + (cnt + 1) * costTime; + } + + public void addCompound(int count, int currentTime) { + if (getOutputCount(currentTime) == totalCount) startTime = currentTime - totalCount * costTime; + totalCount += count; + } + + /** + * Take away all finished compound. + * + * @return The number of finished items. + */ + public int takeCompound(int currentTime) { + int count = getOutputCount(currentTime); + startTime += costTime * count; + totalCount -= count; + return count; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/cooking/CookingCompoundManager.java b/src/main/java/emu/grasscutter/game/managers/cooking/CookingCompoundManager.java index 093e891e7..604c31443 100644 --- a/src/main/java/emu/grasscutter/game/managers/cooking/CookingCompoundManager.java +++ b/src/main/java/emu/grasscutter/game/managers/cooking/CookingCompoundManager.java @@ -1,135 +1,163 @@ -package emu.grasscutter.game.managers.cooking; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.CompoundData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; -import emu.grasscutter.net.proto.GetCompoundDataReqOuterClass.GetCompoundDataReq; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.PlayerCompoundMaterialReqOuterClass.PlayerCompoundMaterialReq; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.net.proto.TakeCompoundOutputReqOuterClass.TakeCompoundOutputReq; -import emu.grasscutter.server.packet.send.PackageTakeCompoundOutputRsp; -import emu.grasscutter.server.packet.send.PacketCompoundDataNotify; -import emu.grasscutter.server.packet.send.PacketGetCompoundDataRsp; -import emu.grasscutter.server.packet.send.PacketPlayerCompoundMaterialRsp; -import emu.grasscutter.utils.Utils; - -import java.util.*; - -public class CookingCompoundManager extends BasePlayerManager { - private static Set defaultUnlockedCompounds; - private static Map> compoundGroups; - //TODO:bind it to player - private static Set unlocked; - - public CookingCompoundManager(Player player) { - super(player); - } - - public static void initialize() { - defaultUnlockedCompounds = new HashSet<>(); - compoundGroups = new HashMap<>(); - GameData.getCompoundDataMap().forEach((id, compound) -> { - if (compound.isDefaultUnlocked()) { - defaultUnlockedCompounds.add(id); - } - compoundGroups.computeIfAbsent(compound.getGroupID(), gid -> new HashSet<>()).add(id); - }); - //TODO:Because we haven't implemented fishing feature,unlock all compounds related to fish.Besides,it should be bound to player rather than manager. - unlocked = new HashSet<>(defaultUnlockedCompounds); - if (compoundGroups.containsKey(3)) // Avoid NPE from Resources error - unlocked.addAll(compoundGroups.get(3)); - } - - private synchronized List getCompoundQueueData() { - List compoundQueueData = new ArrayList<>(player.getActiveCookCompounds().size()); - int currentTime = Utils.getCurrentSeconds(); - for (var item : player.getActiveCookCompounds().values()) { - var data = CompoundQueueData.newBuilder().setCompoundId(item.getCompoundId()).setOutputCount(item.getOutputCount(currentTime)).setOutputTime(item.getOutputTime(currentTime)).setWaitCount(item.getWaitCount(currentTime)).build(); - compoundQueueData.add(data); - } - return compoundQueueData; - } - - public synchronized void handleGetCompoundDataReq(GetCompoundDataReq req) { - player.sendPacket(new PacketGetCompoundDataRsp(unlocked, getCompoundQueueData())); - } - - public synchronized void handlePlayerCompoundMaterialReq(PlayerCompoundMaterialReq req) { - int id = req.getCompoundId(), count = req.getCount(); - CompoundData compound = GameData.getCompoundDataMap().get(id); - var activeCompounds = player.getActiveCookCompounds(); - - //check whether the compound is available - //TODO:add other compounds,see my pr for detail - if (!unlocked.contains(id)) { - player.sendPacket(new PacketPlayerCompoundMaterialRsp(Retcode.RET_FAIL_VALUE)); - return; - } - //check whether the queue is full - if (activeCompounds.containsKey(id) && activeCompounds.get(id).getTotalCount() + count > compound.getQueueSize()) { - player.sendPacket(new PacketPlayerCompoundMaterialRsp(Retcode.RET_COMPOUND_QUEUE_FULL_VALUE)); - return; - } - //try to consume raw materials - if (!player.getInventory().payItems(compound.getInputVec(), count)) { - //TODO:I'm not sure whether retcode is correct. - player.sendPacket(new PacketPlayerCompoundMaterialRsp(Retcode.RET_ITEM_COUNT_NOT_ENOUGH_VALUE)); - return; - } - ActiveCookCompoundData c; - int currentTime = Utils.getCurrentSeconds(); - if (activeCompounds.containsKey(id)) { - c = activeCompounds.get(id); - c.addCompound(count, currentTime); - } else { - c = new ActiveCookCompoundData(id, compound.getCostTime(), count, currentTime); - activeCompounds.put(id, c); - } - var data = CompoundQueueData.newBuilder().setCompoundId(id).setOutputCount(c.getOutputCount(currentTime)).setOutputTime(c.getOutputTime(currentTime)).setWaitCount(c.getWaitCount(currentTime)).build(); - player.sendPacket(new PacketPlayerCompoundMaterialRsp(data)); - } - - public synchronized void handleTakeCompoundOutputReq(TakeCompoundOutputReq req) { - //Client won't set compound_id and will set group_id instead. - int groupId = req.getCompoundGroupId(); - var activeCompounds = player.getActiveCookCompounds(); - int now = Utils.getCurrentSeconds(); - //check available queues - boolean success = false; - Map allRewards = new HashMap<>(); - for (int id : compoundGroups.get(groupId)) { - if (!activeCompounds.containsKey(id)) continue; - int quantity = activeCompounds.get(id).takeCompound(now); - if (activeCompounds.get(id).getTotalCount() == 0) activeCompounds.remove(id); - if (quantity == 0) continue; - List rewards = GameData.getCompoundDataMap().get(id).getOutputVec(); - for (var i : rewards) { - if (i.getId() == 0) continue; - if (allRewards.containsKey(i.getId())) { - GameItem item = allRewards.get(i.getId()); - item.setCount(item.getCount() + i.getCount() * quantity); - } else { - allRewards.put(i.getId(), new GameItem(i.getId(), i.getCount() * quantity)); - } - } - success = true; - } - //give player the rewards - if (success) { - player.getInventory().addItems(allRewards.values(), ActionReason.Compound); - player.sendPacket(new PackageTakeCompoundOutputRsp(allRewards.values().stream().map(i -> ItemParam.newBuilder().setItemId(i.getItemId()).setCount(i.getCount()).build()).toList(), Retcode.RET_SUCC_VALUE)); - } else { - player.sendPacket(new PackageTakeCompoundOutputRsp(null, Retcode.RET_COMPOUND_NOT_FINISH_VALUE)); - } - } - - public void onPlayerLogin() { - player.sendPacket(new PacketCompoundDataNotify(unlocked, getCompoundQueueData())); - } -} +package emu.grasscutter.game.managers.cooking; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CompoundData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; +import emu.grasscutter.net.proto.GetCompoundDataReqOuterClass.GetCompoundDataReq; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.PlayerCompoundMaterialReqOuterClass.PlayerCompoundMaterialReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.net.proto.TakeCompoundOutputReqOuterClass.TakeCompoundOutputReq; +import emu.grasscutter.server.packet.send.PackageTakeCompoundOutputRsp; +import emu.grasscutter.server.packet.send.PacketCompoundDataNotify; +import emu.grasscutter.server.packet.send.PacketGetCompoundDataRsp; +import emu.grasscutter.server.packet.send.PacketPlayerCompoundMaterialRsp; +import emu.grasscutter.utils.Utils; +import java.util.*; + +public class CookingCompoundManager extends BasePlayerManager { + private static Set defaultUnlockedCompounds; + private static Map> compoundGroups; + // TODO:bind it to player + private static Set unlocked; + + public CookingCompoundManager(Player player) { + super(player); + } + + public static void initialize() { + defaultUnlockedCompounds = new HashSet<>(); + compoundGroups = new HashMap<>(); + GameData.getCompoundDataMap() + .forEach( + (id, compound) -> { + if (compound.isDefaultUnlocked()) { + defaultUnlockedCompounds.add(id); + } + compoundGroups.computeIfAbsent(compound.getGroupID(), gid -> new HashSet<>()).add(id); + }); + // TODO:Because we haven't implemented fishing feature,unlock all compounds related to + // fish.Besides,it should be bound to player rather than manager. + unlocked = new HashSet<>(defaultUnlockedCompounds); + if (compoundGroups.containsKey(3)) // Avoid NPE from Resources error + unlocked.addAll(compoundGroups.get(3)); + } + + private synchronized List getCompoundQueueData() { + List compoundQueueData = + new ArrayList<>(player.getActiveCookCompounds().size()); + int currentTime = Utils.getCurrentSeconds(); + for (var item : player.getActiveCookCompounds().values()) { + var data = + CompoundQueueData.newBuilder() + .setCompoundId(item.getCompoundId()) + .setOutputCount(item.getOutputCount(currentTime)) + .setOutputTime(item.getOutputTime(currentTime)) + .setWaitCount(item.getWaitCount(currentTime)) + .build(); + compoundQueueData.add(data); + } + return compoundQueueData; + } + + public synchronized void handleGetCompoundDataReq(GetCompoundDataReq req) { + player.sendPacket(new PacketGetCompoundDataRsp(unlocked, getCompoundQueueData())); + } + + public synchronized void handlePlayerCompoundMaterialReq(PlayerCompoundMaterialReq req) { + int id = req.getCompoundId(), count = req.getCount(); + CompoundData compound = GameData.getCompoundDataMap().get(id); + var activeCompounds = player.getActiveCookCompounds(); + + // check whether the compound is available + // TODO:add other compounds,see my pr for detail + if (!unlocked.contains(id)) { + player.sendPacket(new PacketPlayerCompoundMaterialRsp(Retcode.RET_FAIL_VALUE)); + return; + } + // check whether the queue is full + if (activeCompounds.containsKey(id) + && activeCompounds.get(id).getTotalCount() + count > compound.getQueueSize()) { + player.sendPacket(new PacketPlayerCompoundMaterialRsp(Retcode.RET_COMPOUND_QUEUE_FULL_VALUE)); + return; + } + // try to consume raw materials + if (!player.getInventory().payItems(compound.getInputVec(), count)) { + // TODO:I'm not sure whether retcode is correct. + player.sendPacket( + new PacketPlayerCompoundMaterialRsp(Retcode.RET_ITEM_COUNT_NOT_ENOUGH_VALUE)); + return; + } + ActiveCookCompoundData c; + int currentTime = Utils.getCurrentSeconds(); + if (activeCompounds.containsKey(id)) { + c = activeCompounds.get(id); + c.addCompound(count, currentTime); + } else { + c = new ActiveCookCompoundData(id, compound.getCostTime(), count, currentTime); + activeCompounds.put(id, c); + } + var data = + CompoundQueueData.newBuilder() + .setCompoundId(id) + .setOutputCount(c.getOutputCount(currentTime)) + .setOutputTime(c.getOutputTime(currentTime)) + .setWaitCount(c.getWaitCount(currentTime)) + .build(); + player.sendPacket(new PacketPlayerCompoundMaterialRsp(data)); + } + + public synchronized void handleTakeCompoundOutputReq(TakeCompoundOutputReq req) { + // Client won't set compound_id and will set group_id instead. + int groupId = req.getCompoundGroupId(); + var activeCompounds = player.getActiveCookCompounds(); + int now = Utils.getCurrentSeconds(); + // check available queues + boolean success = false; + Map allRewards = new HashMap<>(); + for (int id : compoundGroups.get(groupId)) { + if (!activeCompounds.containsKey(id)) continue; + int quantity = activeCompounds.get(id).takeCompound(now); + if (activeCompounds.get(id).getTotalCount() == 0) activeCompounds.remove(id); + if (quantity == 0) continue; + List rewards = GameData.getCompoundDataMap().get(id).getOutputVec(); + for (var i : rewards) { + if (i.getId() == 0) continue; + if (allRewards.containsKey(i.getId())) { + GameItem item = allRewards.get(i.getId()); + item.setCount(item.getCount() + i.getCount() * quantity); + } else { + allRewards.put(i.getId(), new GameItem(i.getId(), i.getCount() * quantity)); + } + } + success = true; + } + // give player the rewards + if (success) { + player.getInventory().addItems(allRewards.values(), ActionReason.Compound); + player.sendPacket( + new PackageTakeCompoundOutputRsp( + allRewards.values().stream() + .map( + i -> + ItemParam.newBuilder() + .setItemId(i.getItemId()) + .setCount(i.getCount()) + .build()) + .toList(), + Retcode.RET_SUCC_VALUE)); + } else { + player.sendPacket( + new PackageTakeCompoundOutputRsp(null, Retcode.RET_COMPOUND_NOT_FINISH_VALUE)); + } + } + + public void onPlayerLogin() { + player.sendPacket(new PacketCompoundDataNotify(unlocked, getCompoundQueueData())); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/cooking/CookingManager.java b/src/main/java/emu/grasscutter/game/managers/cooking/CookingManager.java index a3bf15105..8efd03b86 100644 --- a/src/main/java/emu/grasscutter/game/managers/cooking/CookingManager.java +++ b/src/main/java/emu/grasscutter/game/managers/cooking/CookingManager.java @@ -1,184 +1,185 @@ -package emu.grasscutter.game.managers.cooking; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.proto.CookRecipeDataOuterClass; -import emu.grasscutter.net.proto.PlayerCookArgsReqOuterClass.PlayerCookArgsReq; -import emu.grasscutter.net.proto.PlayerCookReqOuterClass.PlayerCookReq; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.packet.send.PacketCookDataNotify; -import emu.grasscutter.server.packet.send.PacketCookRecipeDataNotify; -import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp; -import emu.grasscutter.server.packet.send.PacketPlayerCookRsp; -import io.netty.util.internal.ThreadLocalRandom; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class CookingManager extends BasePlayerManager { - private static final int MANUAL_PERFECT_COOK_QUALITY = 3; - private static Set defaultUnlockedRecipies; - - public CookingManager(Player player) { - super(player); - } - - public static void initialize() { - // Initialize the set of recipies that are unlocked by default. - defaultUnlockedRecipies = new HashSet<>(); - - for (var recipe : GameData.getCookRecipeDataMap().values()) { - if (recipe.isDefaultUnlocked()) { - defaultUnlockedRecipies.add(recipe.getId()); - } - } - } - - /******************** - * Unlocking for recipies. - ********************/ - public boolean unlockRecipe(int id) { - if (this.player.getUnlockedRecipies().containsKey(id)) { - return false; // Recipe already unlocked - } - // Tell the client that this blueprint is now unlocked and add the unlocked item to the player. - this.player.getUnlockedRecipies().put(id, 0); - this.player.sendPacket(new PacketCookRecipeDataNotify(id)); - - return true; - } - - /******************** - * Perform cooking. - ********************/ - private double getSpecialtyChance(ItemData cookedItem) { - // Chances taken from the Wiki. - return switch (cookedItem.getRankLevel()) { - case 1 -> 0.25; - case 2 -> 0.2; - case 3 -> 0.15; - default -> 0; - }; - } - - public void handlePlayerCookReq(PlayerCookReq req) { - // Get info from the request. - int recipeId = req.getRecipeId(); - int quality = req.getQteQuality(); - int count = req.getCookCount(); - int avatar = req.getAssistAvatar(); - - // Get recipe data. - var recipeData = GameData.getCookRecipeDataMap().get(recipeId); - if (recipeData == null) { - this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); - return; - } - - // Get proficiency for player. - int proficiency = this.player.getUnlockedRecipies().getOrDefault(recipeId, 0); - - // Try consuming materials. - boolean success = player.getInventory().payItems(recipeData.getInputVec(), count, ActionReason.Cook); - if (!success) { - this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); - } - - // Get result item information. - int qualityIndex = - quality == 0 - ? 2 - : quality - 1; - - ItemParamData resultParam = recipeData.getQualityOutputVec().get(qualityIndex); - ItemData resultItemData = GameData.getItemDataMap().get(resultParam.getItemId()); - - // Handle character's specialties. - int specialtyCount = 0; - double specialtyChance = this.getSpecialtyChance(resultItemData); - - var bonusData = GameData.getCookBonusDataMap().get(avatar); - if (bonusData != null && recipeId == bonusData.getRecipeId()) { - // Roll for specialy replacements. - for (int i = 0; i < count; i++) { - if (ThreadLocalRandom.current().nextDouble() <= specialtyChance) { - specialtyCount++; - } - } - } - - // Obtain results. - List cookResults = new ArrayList<>(); - - int normalCount = count - specialtyCount; - GameItem cookResultNormal = new GameItem(resultItemData, resultParam.getCount() * normalCount); - cookResults.add(cookResultNormal); - this.player.getInventory().addItem(cookResultNormal); - - if (specialtyCount > 0) { - ItemData specialtyItemData = GameData.getItemDataMap().get(bonusData.getReplacementItemId()); - GameItem cookResultSpecialty = new GameItem(specialtyItemData, resultParam.getCount() * specialtyCount); - cookResults.add(cookResultSpecialty); - this.player.getInventory().addItem(cookResultSpecialty); - } - - // Increase player proficiency, if this was a manual perfect cook. - if (quality == MANUAL_PERFECT_COOK_QUALITY) { - proficiency = Math.min(proficiency + 1, recipeData.getMaxProficiency()); - this.player.getUnlockedRecipies().put(recipeId, proficiency); - } - - // Send response. - this.player.sendPacket(new PacketPlayerCookRsp(cookResults, quality, count, recipeId, proficiency)); - } - - /******************** - * Cooking arguments. - ********************/ - public void handleCookArgsReq(PlayerCookArgsReq req) { - this.player.sendPacket(new PacketPlayerCookArgsRsp()); - } - - /******************** - * Notify unlocked recipies. - ********************/ - private void addDefaultUnlocked() { - // Get recipies that are already unlocked. - var unlockedRecipies = this.player.getUnlockedRecipies(); - - // Get recipies that should be unlocked by default but aren't. - var additionalRecipies = new HashSet<>(defaultUnlockedRecipies); - additionalRecipies.removeAll(unlockedRecipies.keySet()); - - // Add them to the player. - for (int id : additionalRecipies) { - unlockedRecipies.put(id, 0); - } - } - - public void sendCookDataNotify() { - // Default unlocked recipes to player if they don't have them yet. - this.addDefaultUnlocked(); - - // Get unlocked recipes. - var unlockedRecipes = this.player.getUnlockedRecipies(); - - // Construct CookRecipeData protos. - List data = new ArrayList<>(); - unlockedRecipes.forEach((recipeId, proficiency) -> - data.add(CookRecipeDataOuterClass.CookRecipeData.newBuilder() - .setRecipeId(recipeId) - .setProficiency(proficiency) - .build())); - - // Send packet. - this.player.sendPacket(new PacketCookDataNotify(data)); - } -} +package emu.grasscutter.game.managers.cooking; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.CookRecipeDataOuterClass; +import emu.grasscutter.net.proto.PlayerCookArgsReqOuterClass.PlayerCookArgsReq; +import emu.grasscutter.net.proto.PlayerCookReqOuterClass.PlayerCookReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.packet.send.PacketCookDataNotify; +import emu.grasscutter.server.packet.send.PacketCookRecipeDataNotify; +import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp; +import emu.grasscutter.server.packet.send.PacketPlayerCookRsp; +import io.netty.util.internal.ThreadLocalRandom; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class CookingManager extends BasePlayerManager { + private static final int MANUAL_PERFECT_COOK_QUALITY = 3; + private static Set defaultUnlockedRecipies; + + public CookingManager(Player player) { + super(player); + } + + public static void initialize() { + // Initialize the set of recipies that are unlocked by default. + defaultUnlockedRecipies = new HashSet<>(); + + for (var recipe : GameData.getCookRecipeDataMap().values()) { + if (recipe.isDefaultUnlocked()) { + defaultUnlockedRecipies.add(recipe.getId()); + } + } + } + + /******************** + * Unlocking for recipies. + ********************/ + public boolean unlockRecipe(int id) { + if (this.player.getUnlockedRecipies().containsKey(id)) { + return false; // Recipe already unlocked + } + // Tell the client that this blueprint is now unlocked and add the unlocked item to the player. + this.player.getUnlockedRecipies().put(id, 0); + this.player.sendPacket(new PacketCookRecipeDataNotify(id)); + + return true; + } + + /******************** + * Perform cooking. + ********************/ + private double getSpecialtyChance(ItemData cookedItem) { + // Chances taken from the Wiki. + return switch (cookedItem.getRankLevel()) { + case 1 -> 0.25; + case 2 -> 0.2; + case 3 -> 0.15; + default -> 0; + }; + } + + public void handlePlayerCookReq(PlayerCookReq req) { + // Get info from the request. + int recipeId = req.getRecipeId(); + int quality = req.getQteQuality(); + int count = req.getCookCount(); + int avatar = req.getAssistAvatar(); + + // Get recipe data. + var recipeData = GameData.getCookRecipeDataMap().get(recipeId); + if (recipeData == null) { + this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); + return; + } + + // Get proficiency for player. + int proficiency = this.player.getUnlockedRecipies().getOrDefault(recipeId, 0); + + // Try consuming materials. + boolean success = + player.getInventory().payItems(recipeData.getInputVec(), count, ActionReason.Cook); + if (!success) { + this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); + } + + // Get result item information. + int qualityIndex = quality == 0 ? 2 : quality - 1; + + ItemParamData resultParam = recipeData.getQualityOutputVec().get(qualityIndex); + ItemData resultItemData = GameData.getItemDataMap().get(resultParam.getItemId()); + + // Handle character's specialties. + int specialtyCount = 0; + double specialtyChance = this.getSpecialtyChance(resultItemData); + + var bonusData = GameData.getCookBonusDataMap().get(avatar); + if (bonusData != null && recipeId == bonusData.getRecipeId()) { + // Roll for specialy replacements. + for (int i = 0; i < count; i++) { + if (ThreadLocalRandom.current().nextDouble() <= specialtyChance) { + specialtyCount++; + } + } + } + + // Obtain results. + List cookResults = new ArrayList<>(); + + int normalCount = count - specialtyCount; + GameItem cookResultNormal = new GameItem(resultItemData, resultParam.getCount() * normalCount); + cookResults.add(cookResultNormal); + this.player.getInventory().addItem(cookResultNormal); + + if (specialtyCount > 0) { + ItemData specialtyItemData = GameData.getItemDataMap().get(bonusData.getReplacementItemId()); + GameItem cookResultSpecialty = + new GameItem(specialtyItemData, resultParam.getCount() * specialtyCount); + cookResults.add(cookResultSpecialty); + this.player.getInventory().addItem(cookResultSpecialty); + } + + // Increase player proficiency, if this was a manual perfect cook. + if (quality == MANUAL_PERFECT_COOK_QUALITY) { + proficiency = Math.min(proficiency + 1, recipeData.getMaxProficiency()); + this.player.getUnlockedRecipies().put(recipeId, proficiency); + } + + // Send response. + this.player.sendPacket( + new PacketPlayerCookRsp(cookResults, quality, count, recipeId, proficiency)); + } + + /******************** + * Cooking arguments. + ********************/ + public void handleCookArgsReq(PlayerCookArgsReq req) { + this.player.sendPacket(new PacketPlayerCookArgsRsp()); + } + + /******************** + * Notify unlocked recipies. + ********************/ + private void addDefaultUnlocked() { + // Get recipies that are already unlocked. + var unlockedRecipies = this.player.getUnlockedRecipies(); + + // Get recipies that should be unlocked by default but aren't. + var additionalRecipies = new HashSet<>(defaultUnlockedRecipies); + additionalRecipies.removeAll(unlockedRecipies.keySet()); + + // Add them to the player. + for (int id : additionalRecipies) { + unlockedRecipies.put(id, 0); + } + } + + public void sendCookDataNotify() { + // Default unlocked recipes to player if they don't have them yet. + this.addDefaultUnlocked(); + + // Get unlocked recipes. + var unlockedRecipes = this.player.getUnlockedRecipies(); + + // Construct CookRecipeData protos. + List data = new ArrayList<>(); + unlockedRecipes.forEach( + (recipeId, proficiency) -> + data.add( + CookRecipeDataOuterClass.CookRecipeData.newBuilder() + .setRecipeId(recipeId) + .setProficiency(proficiency) + .build())); + + // Send packet. + this.player.sendPacket(new PacketCookDataNotify(data)); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java b/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java index d3a4b89d9..82757a5e2 100644 --- a/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java +++ b/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java @@ -1,100 +1,101 @@ -package emu.grasscutter.game.managers.deforestation; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.entity.EntityItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.HitTreeNotifyOuterClass; -import emu.grasscutter.net.proto.VectorOuterClass; -import emu.grasscutter.utils.Position; - -import java.util.ArrayList; -import java.util.HashMap; - -public class DeforestationManager extends BasePlayerManager { - final static int RECORD_EXPIRED_SECONDS = 60 * 5; // 5 min - final static int RECORD_MAX_TIMES = 3; // max number of wood - final static int RECORD_MAX_TIMES_OTHER_HIT_TREE = 10; // if hit 10 times other trees, reset wood - private final static HashMap ColliderTypeToWoodItemID = new HashMap<>(); - - static { - /* define wood types which reflected to item id*/ - ColliderTypeToWoodItemID.put(1, 101301); - ColliderTypeToWoodItemID.put(2, 101302); - ColliderTypeToWoodItemID.put(3, 101303); - ColliderTypeToWoodItemID.put(4, 101304); - ColliderTypeToWoodItemID.put(5, 101305); - ColliderTypeToWoodItemID.put(6, 101306); - ColliderTypeToWoodItemID.put(7, 101307); - ColliderTypeToWoodItemID.put(8, 101308); - ColliderTypeToWoodItemID.put(9, 101309); - ColliderTypeToWoodItemID.put(10, 101310); - ColliderTypeToWoodItemID.put(11, 101311); - ColliderTypeToWoodItemID.put(12, 101312); - ColliderTypeToWoodItemID.put(13, 101313); - ColliderTypeToWoodItemID.put(14, 101314); - ColliderTypeToWoodItemID.put(15, 101315); - ColliderTypeToWoodItemID.put(16, 101316); - ColliderTypeToWoodItemID.put(17, 101317); - } - - private final ArrayList currentRecord; - - public DeforestationManager(Player player) { - super(player); - this.currentRecord = new ArrayList<>(); - } - - public void resetWood() { - synchronized (currentRecord) { - currentRecord.clear(); - } - } - - public void onDeforestationInvoke(HitTreeNotifyOuterClass.HitTreeNotify hit) { - synchronized (currentRecord) { - //Grasscutter.getLogger().info("onDeforestationInvoke! Wood records {}", currentRecord); - VectorOuterClass.Vector hitPosition = hit.getTreePos(); - int woodType = hit.getTreeType(); - if (ColliderTypeToWoodItemID.containsKey(woodType)) {// is a available wood type - Scene scene = player.getScene(); - int itemId = ColliderTypeToWoodItemID.get(woodType); - int positionHash = hitPosition.hashCode(); - HitTreeRecord record = searchRecord(positionHash); - if (record == null) { - record = new HitTreeRecord(positionHash); - } else { - currentRecord.remove(record);// move it to last position - } - currentRecord.add(record); - if (currentRecord.size() > RECORD_MAX_TIMES_OTHER_HIT_TREE) { - currentRecord.remove(0); - } - if (record.record()) { - EntityItem entity = new EntityItem(scene, - null, - GameData.getItemDataMap().get(itemId), - new Position(hitPosition.getX(), hitPosition.getY(), hitPosition.getZ()), - 1, - false); - scene.addEntity(entity); - } - //record.record()=false : too many wood they have deforested, no more wood dropped! - } else { - Grasscutter.getLogger().warn("No wood type {} found.", woodType); - } - } - // unknown wood type - } - - private HitTreeRecord searchRecord(int id) { - for (HitTreeRecord record : currentRecord) { - if (record.getUnique() == id) { - return record; - } - } - return null; - } -} +package emu.grasscutter.game.managers.deforestation; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.HitTreeNotifyOuterClass; +import emu.grasscutter.net.proto.VectorOuterClass; +import emu.grasscutter.utils.Position; +import java.util.ArrayList; +import java.util.HashMap; + +public class DeforestationManager extends BasePlayerManager { + static final int RECORD_EXPIRED_SECONDS = 60 * 5; // 5 min + static final int RECORD_MAX_TIMES = 3; // max number of wood + static final int RECORD_MAX_TIMES_OTHER_HIT_TREE = 10; // if hit 10 times other trees, reset wood + private static final HashMap ColliderTypeToWoodItemID = new HashMap<>(); + + static { + /* define wood types which reflected to item id*/ + ColliderTypeToWoodItemID.put(1, 101301); + ColliderTypeToWoodItemID.put(2, 101302); + ColliderTypeToWoodItemID.put(3, 101303); + ColliderTypeToWoodItemID.put(4, 101304); + ColliderTypeToWoodItemID.put(5, 101305); + ColliderTypeToWoodItemID.put(6, 101306); + ColliderTypeToWoodItemID.put(7, 101307); + ColliderTypeToWoodItemID.put(8, 101308); + ColliderTypeToWoodItemID.put(9, 101309); + ColliderTypeToWoodItemID.put(10, 101310); + ColliderTypeToWoodItemID.put(11, 101311); + ColliderTypeToWoodItemID.put(12, 101312); + ColliderTypeToWoodItemID.put(13, 101313); + ColliderTypeToWoodItemID.put(14, 101314); + ColliderTypeToWoodItemID.put(15, 101315); + ColliderTypeToWoodItemID.put(16, 101316); + ColliderTypeToWoodItemID.put(17, 101317); + } + + private final ArrayList currentRecord; + + public DeforestationManager(Player player) { + super(player); + this.currentRecord = new ArrayList<>(); + } + + public void resetWood() { + synchronized (currentRecord) { + currentRecord.clear(); + } + } + + public void onDeforestationInvoke(HitTreeNotifyOuterClass.HitTreeNotify hit) { + synchronized (currentRecord) { + // Grasscutter.getLogger().info("onDeforestationInvoke! Wood records {}", currentRecord); + VectorOuterClass.Vector hitPosition = hit.getTreePos(); + int woodType = hit.getTreeType(); + if (ColliderTypeToWoodItemID.containsKey(woodType)) { // is a available wood type + Scene scene = player.getScene(); + int itemId = ColliderTypeToWoodItemID.get(woodType); + int positionHash = hitPosition.hashCode(); + HitTreeRecord record = searchRecord(positionHash); + if (record == null) { + record = new HitTreeRecord(positionHash); + } else { + currentRecord.remove(record); // move it to last position + } + currentRecord.add(record); + if (currentRecord.size() > RECORD_MAX_TIMES_OTHER_HIT_TREE) { + currentRecord.remove(0); + } + if (record.record()) { + EntityItem entity = + new EntityItem( + scene, + null, + GameData.getItemDataMap().get(itemId), + new Position(hitPosition.getX(), hitPosition.getY(), hitPosition.getZ()), + 1, + false); + scene.addEntity(entity); + } + // record.record()=false : too many wood they have deforested, no more wood dropped! + } else { + Grasscutter.getLogger().warn("No wood type {} found.", woodType); + } + } + // unknown wood type + } + + private HitTreeRecord searchRecord(int id) { + for (HitTreeRecord record : currentRecord) { + if (record.getUnique() == id) { + return record; + } + } + return null; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/deforestation/HitTreeRecord.java b/src/main/java/emu/grasscutter/game/managers/deforestation/HitTreeRecord.java index e59f755fe..19769ff4e 100644 --- a/src/main/java/emu/grasscutter/game/managers/deforestation/HitTreeRecord.java +++ b/src/main/java/emu/grasscutter/game/managers/deforestation/HitTreeRecord.java @@ -1,58 +1,48 @@ -package emu.grasscutter.game.managers.deforestation; - - -public class HitTreeRecord { - private final int unique; - private short count; // hit this tree times - private long time; // last available hitting time - - HitTreeRecord(int unique) { - this.count = 0; - this.time = 0; - this.unique = unique; - } - - /** - * reset hit time - */ - private void resetTime() { - this.time = System.currentTimeMillis(); - } - - - /** - * commit hit behavior - */ - public boolean record() { - if (this.count < DeforestationManager.RECORD_MAX_TIMES) { - this.count++; - resetTime(); - return true; - } - // check expired - boolean isWaiting = System.currentTimeMillis() - this.time < DeforestationManager.RECORD_EXPIRED_SECONDS * 1000L; - if (isWaiting) { - return false; - } else { - this.count = 1; - resetTime(); - return true; - } - } - - /** - * get unique id - */ - public int getUnique() { - return unique; - } - - @Override - public String toString() { - return "HitTreeRecord{" + - "unique=" + unique + - ", count=" + count + - ", time=" + time + - '}'; - } -} +package emu.grasscutter.game.managers.deforestation; + +public class HitTreeRecord { + private final int unique; + private short count; // hit this tree times + private long time; // last available hitting time + + HitTreeRecord(int unique) { + this.count = 0; + this.time = 0; + this.unique = unique; + } + + /** reset hit time */ + private void resetTime() { + this.time = System.currentTimeMillis(); + } + + /** commit hit behavior */ + public boolean record() { + if (this.count < DeforestationManager.RECORD_MAX_TIMES) { + this.count++; + resetTime(); + return true; + } + // check expired + boolean isWaiting = + System.currentTimeMillis() - this.time + < DeforestationManager.RECORD_EXPIRED_SECONDS * 1000L; + if (isWaiting) { + return false; + } else { + this.count = 1; + resetTime(); + return true; + } + } + + /** get unique id */ + public int getUnique() { + return unique; + } + + @Override + public String toString() { + return "HitTreeRecord{" + "unique=" + unique + ", count=" + count + ", time=" + time + '}'; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java index 79a0e8c55..422e7d629 100644 --- a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java +++ b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java @@ -1,380 +1,396 @@ -package emu.grasscutter.game.managers.energy; - -import com.google.protobuf.InvalidProtocolBufferException; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.data.excels.MonsterData.HpDrops; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.*; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.MonsterType; -import emu.grasscutter.game.props.WeaponType; -import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; -import emu.grasscutter.net.proto.AbilityIdentifierOuterClass.AbilityIdentifier; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; -import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; -import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ThreadLocalRandom; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -public class EnergyManager extends BasePlayerManager { - private final static Int2ObjectMap> energyDropData = new Int2ObjectOpenHashMap<>(); - private final static Int2ObjectMap> skillParticleGenerationData = new Int2ObjectOpenHashMap<>(); - private final Object2IntMap avatarNormalProbabilities; - private boolean energyUsage; // Should energy usage be enabled for this player? - - public EnergyManager(Player player) { - super(player); - this.avatarNormalProbabilities = new Object2IntOpenHashMap<>(); - this.energyUsage = GAME_OPTIONS.energyUsage; - } - - public static void initialize() { - // Read the data we need for monster energy drops. - try { - DataLoader.loadList("EnergyDrop.json", EnergyDropEntry.class).forEach(entry -> { - energyDropData.put(entry.getDropId(), entry.getDropList()); - }); - - Grasscutter.getLogger().debug("Energy drop data successfully loaded."); - } catch (Exception ex) { - Grasscutter.getLogger().error("Unable to load energy drop data.", ex); - } - - // Read the data for particle generation from skills - try { - DataLoader.loadList("SkillParticleGeneration.json", SkillParticleGenerationEntry.class).forEach(entry -> { - skillParticleGenerationData.put(entry.getAvatarId(), entry.getAmountList()); - }); - - Grasscutter.getLogger().debug("Skill particle generation data successfully loaded."); - } catch (Exception ex) { - Grasscutter.getLogger().error("Unable to load skill particle generation data data.", ex); - } - } - - /** - * Particle creation for elemental skills. - */ - private int getBallCountForAvatar(int avatarId) { - // We default to two particles. - int count = 2; - - // If we don't have any data for this avatar, stop. - if (!skillParticleGenerationData.containsKey(avatarId)) { - Grasscutter.getLogger().warn("No particle generation data for avatarId {} found.", avatarId); - } - // If we do have data, roll for how many particles we should generate. - else { - int roll = ThreadLocalRandom.current().nextInt(0, 100); - int percentageStack = 0; - for (SkillParticleGenerationInfo info : skillParticleGenerationData.get(avatarId)) { - int chance = info.getChance(); - percentageStack += chance; - if (roll < percentageStack) { - count = info.getValue(); - break; - } - } - } - - // Done. - return count; - } - - private int getBallIdForElement(ElementType element) { - // If we have no element, we default to an element-less particle. - if (element == null) { - return 2024; - } - - // Otherwise, we determine the particle's ID based on the element. - return switch (element) { - case Fire -> 2017; - case Water -> 2018; - case Grass -> 2019; - case Electric -> 2020; - case Wind -> 2021; - case Ice -> 2022; - case Rock -> 2023; - default -> 2024; - }; - } - - public void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { - // ToDo: - // This is also called when a weapon like Favonius Warbow etc. creates energy through its passive. - // We are not handling this correctly at the moment. - - // Get action info. - AbilityActionGenerateElemBall action = AbilityActionGenerateElemBall.parseFrom(invoke.getAbilityData()); - if (action == null) { - return; - } - - // Default to an elementless particle. - int itemId = 2024; - - // Generate 2 particles by default. - int amount = 2; - - // Try to get the casting avatar from the player's party. - Optional avatarEntity = this.getCastingAvatarEntityForEnergy(invoke.getEntityId()); - - // Bug: invokes twice sometimes, Ayato, Keqing - // ToDo: deal with press, hold difference. deal with charge(Beidou, Yunjin) - if (avatarEntity.isPresent()) { - Avatar avatar = avatarEntity.get().getAvatar(); - - if (avatar != null) { - int avatarId = avatar.getAvatarId(); - AvatarSkillDepotData skillDepotData = avatar.getSkillDepot(); - - // Determine how many particles we need to create for this avatar. - amount = this.getBallCountForAvatar(avatarId); - - // Determine the avatar's element, and based on that the ID of the - // particles we have to generate. - if (skillDepotData != null) { - ElementType element = skillDepotData.getElementType(); - itemId = this.getBallIdForElement(element); - } - } - } - - // Generate the particles. - var pos = new Position(action.getPos()); - for (int i = 0; i < amount; i++) { - this.generateElemBall(itemId, pos, 1); - } - } - - /** - * Energy generation for NAs/CAs. - * - * @param avatar The avatar. - */ - private void generateEnergyForNormalAndCharged(EntityAvatar avatar) { - // This logic is based on the descriptions given in - // https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks - // https://library.keqingmains.com/combat-mechanics/energy#auto-attacking - // Those descriptions are lacking in some information, so this implementation most likely - // does not fully replicate the behavior of the official server. Open questions: - // - Does the probability for a character reset after some time? - // - Does the probability for a character reset when switching them out? - // - Does this really count every individual hit separately? - - // Get the avatar's weapon type. - WeaponType weaponType = avatar.getAvatar().getAvatarData().getWeaponType(); - - // Check if we already have probability data for this avatar. If not, insert it. - if (!this.avatarNormalProbabilities.containsKey(avatar)) { - this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); - } - - // Roll for energy. - int currentProbability = this.avatarNormalProbabilities.getInt(avatar); - int roll = ThreadLocalRandom.current().nextInt(0, 100); - - // If the player wins the roll, we increase the avatar's energy and reset the probability. - if (roll < currentProbability) { - avatar.addEnergy(1.0f, PropChangeReason.PROP_CHANGE_REASON_ABILITY, true); - this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); - } - // Otherwise, we increase the probability for the next hit. - else { - this.avatarNormalProbabilities.put(avatar, currentProbability + weaponType.getEnergyGainIncreaseProbability()); - } - } - - public void handleAttackHit(EvtBeingHitInfo hitInfo) { - // Get the attack result. - AttackResult attackRes = hitInfo.getAttackResult(); - - // Make sure the attack was performed by the currently active avatar. If not, we ignore the hit. - Optional attackerEntity = this.getCastingAvatarEntityForEnergy(attackRes.getAttackerId()); - if (attackerEntity.isEmpty() || this.player.getTeamManager().getCurrentAvatarEntity().getId() != attackerEntity.get().getId()) { - return; - } - - // Make sure the target is an actual enemy. - GameEntity targetEntity = this.player.getScene().getEntityById(attackRes.getDefenseId()); - if (!(targetEntity instanceof EntityMonster targetMonster)) { - return; - } - - MonsterType targetType = targetMonster.getMonsterData().getType(); - if (targetType != MonsterType.MONSTER_ORDINARY && targetType != MonsterType.MONSTER_BOSS) { - return; - } - - // Get the ability that caused this hit. - AbilityIdentifier ability = attackRes.getAbilityIdentifier(); - - // Make sure there is no actual "ability" associated with the hit. For now, this is how we - // identify normal and charged attacks. Note that this is not completely accurate: - // - Many character's charged attacks have an ability associated with them. This means that, - // for now, we don't identify charged attacks reliably. - // - There might also be some cases where we incorrectly identify something as a normal or - // charged attack that is not (Diluc's E?). - // - Catalyst normal attacks have an ability, so we don't handle those for now. - // ToDo: Fix all of that. - if (ability != AbilityIdentifier.getDefaultInstance()) { - return; - } - - // Handle the energy generation. - this.generateEnergyForNormalAndCharged(attackerEntity.get()); - } - - /* - * Energy logic related to using skills. - */ - - private void handleBurstCast(Avatar avatar, int skillId) { - // Don't do anything if energy usage is disabled. - if (!GAME_OPTIONS.energyUsage || !this.energyUsage) { - return; - } - - // If the cast skill was a burst, consume energy. - if (avatar.getSkillDepot() != null && skillId == avatar.getSkillDepot().getEnergySkill()) { - avatar.getAsEntity().clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START); - } - } - - public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { - // Determine the entity that has cast the skill. Cancel if we can't find that avatar. - Optional caster = this.player.getTeamManager().getActiveTeam().stream() - .filter(character -> character.getId() == casterId) - .findFirst(); - - if (caster.isEmpty()) { - return; - } - - Avatar avatar = caster.get().getAvatar(); - - // Handle elemental burst. - this.handleBurstCast(avatar, skillId); - } - - /* - * Monster energy drops. - */ - - private void generateElemBallDrops(EntityMonster monster, int dropId) { - // Generate all drops specified for the given drop id. - if (!energyDropData.containsKey(dropId)) { - Grasscutter.getLogger().warn("No drop data for dropId {} found.", dropId); - return; - } - - for (EnergyDropInfo info : energyDropData.get(dropId)) { - this.generateElemBall(info.getBallId(), monster.getPosition(), info.getCount()); - } - } - - public void handleMonsterEnergyDrop(EntityMonster monster, float hpBeforeDamage, float hpAfterDamage) { - // Make sure this is actually a monster. - // Note that some wildlife also has that type, like boars or birds. - MonsterType type = monster.getMonsterData().getType(); - if (type != MonsterType.MONSTER_ORDINARY && type != MonsterType.MONSTER_BOSS) { - return; - } - - // Calculate the HP thresholds for before and after the damage was taken. - float maxHp = monster.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - float thresholdBefore = hpBeforeDamage / maxHp; - float thresholdAfter = hpAfterDamage / maxHp; - - // Determine the thresholds the monster has passed, and generate drops based on that. - for (HpDrops drop : monster.getMonsterData().getHpDrops()) { - if (drop.getDropId() == 0) { - continue; - } - - float threshold = drop.getHpPercent() / 100.0f; - if (threshold < thresholdBefore && threshold >= thresholdAfter) { - this.generateElemBallDrops(monster, drop.getDropId()); - } - } - - // Handle kill drops. - if (hpAfterDamage <= 0 && monster.getMonsterData().getKillDropId() != 0) { - this.generateElemBallDrops(monster, monster.getMonsterData().getKillDropId()); - } - } - - /* - * Utilities. - */ - - private void generateElemBall(int ballId, Position position, int count) { - // Generate a particle/orb with the specified parameters. - ItemData itemData = GameData.getItemDataMap().get(ballId); - if (itemData == null) { - return; - } - - EntityItem energyBall = new EntityItem(this.getPlayer().getScene(), this.getPlayer(), itemData, position, count); - this.getPlayer().getScene().addEntity(energyBall); - } - - private Optional getCastingAvatarEntityForEnergy(int invokeEntityId) { - // To determine the avatar that has cast the skill that caused the energy particle to be generated, - // we have to look at the entity that has invoked the ability. This can either be that avatar directly, - // or it can be an `EntityClientGadget`, owned (some way up the owner hierarchy) by the avatar - // that cast the skill. - - // Try to get the invoking entity from the scene. - GameEntity entity = this.player.getScene().getEntityById(invokeEntityId); - - // Determine the ID of the entity that originally cast this skill. If the scene entity is null, - // or not an `EntityClientGadget`, we assume that we are directly looking at the casting avatar - // (the null case will happen if the avatar was switched out between casting the skill and the - // particle being generated). If the scene entity is an `EntityClientGadget`, we need to find the - // ID of the original owner of that gadget. - int avatarEntityId = - (!(entity instanceof EntityClientGadget)) - ? invokeEntityId - : ((EntityClientGadget) entity).getOriginalOwnerEntityId(); - - // Finally, find the avatar entity in the player's team. - return this.player.getTeamManager().getActiveTeam() - .stream() - .filter(character -> character.getId() == avatarEntityId) - .findFirst(); - } - - public boolean getEnergyUsage() { - return this.energyUsage; - } - - public void setEnergyUsage(boolean energyUsage) { - this.energyUsage = energyUsage; - if (!energyUsage) { // Refill team energy if usage is disabled - for (EntityAvatar entityAvatar : this.player.getTeamManager().getActiveTeam()) { - entityAvatar.addEnergy(1000, PropChangeReason.PROP_CHANGE_REASON_GM, true); - } - } - } -} +package emu.grasscutter.game.managers.energy; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import com.google.protobuf.InvalidProtocolBufferException; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData.HpDrops; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.*; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.MonsterType; +import emu.grasscutter.game.props.WeaponType; +import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; +import emu.grasscutter.net.proto.AbilityIdentifierOuterClass.AbilityIdentifier; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; +import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; +import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; + +public class EnergyManager extends BasePlayerManager { + private static final Int2ObjectMap> energyDropData = + new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap> + skillParticleGenerationData = new Int2ObjectOpenHashMap<>(); + private final Object2IntMap avatarNormalProbabilities; + private boolean energyUsage; // Should energy usage be enabled for this player? + + public EnergyManager(Player player) { + super(player); + this.avatarNormalProbabilities = new Object2IntOpenHashMap<>(); + this.energyUsage = GAME_OPTIONS.energyUsage; + } + + public static void initialize() { + // Read the data we need for monster energy drops. + try { + DataLoader.loadList("EnergyDrop.json", EnergyDropEntry.class) + .forEach( + entry -> { + energyDropData.put(entry.getDropId(), entry.getDropList()); + }); + + Grasscutter.getLogger().debug("Energy drop data successfully loaded."); + } catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load energy drop data.", ex); + } + + // Read the data for particle generation from skills + try { + DataLoader.loadList("SkillParticleGeneration.json", SkillParticleGenerationEntry.class) + .forEach( + entry -> { + skillParticleGenerationData.put(entry.getAvatarId(), entry.getAmountList()); + }); + + Grasscutter.getLogger().debug("Skill particle generation data successfully loaded."); + } catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load skill particle generation data data.", ex); + } + } + + /** Particle creation for elemental skills. */ + private int getBallCountForAvatar(int avatarId) { + // We default to two particles. + int count = 2; + + // If we don't have any data for this avatar, stop. + if (!skillParticleGenerationData.containsKey(avatarId)) { + Grasscutter.getLogger().warn("No particle generation data for avatarId {} found.", avatarId); + } + // If we do have data, roll for how many particles we should generate. + else { + int roll = ThreadLocalRandom.current().nextInt(0, 100); + int percentageStack = 0; + for (SkillParticleGenerationInfo info : skillParticleGenerationData.get(avatarId)) { + int chance = info.getChance(); + percentageStack += chance; + if (roll < percentageStack) { + count = info.getValue(); + break; + } + } + } + + // Done. + return count; + } + + private int getBallIdForElement(ElementType element) { + // If we have no element, we default to an element-less particle. + if (element == null) { + return 2024; + } + + // Otherwise, we determine the particle's ID based on the element. + return switch (element) { + case Fire -> 2017; + case Water -> 2018; + case Grass -> 2019; + case Electric -> 2020; + case Wind -> 2021; + case Ice -> 2022; + case Rock -> 2023; + default -> 2024; + }; + } + + public void handleGenerateElemBall(AbilityInvokeEntry invoke) + throws InvalidProtocolBufferException { + // ToDo: + // This is also called when a weapon like Favonius Warbow etc. creates energy through its + // passive. + // We are not handling this correctly at the moment. + + // Get action info. + AbilityActionGenerateElemBall action = + AbilityActionGenerateElemBall.parseFrom(invoke.getAbilityData()); + if (action == null) { + return; + } + + // Default to an elementless particle. + int itemId = 2024; + + // Generate 2 particles by default. + int amount = 2; + + // Try to get the casting avatar from the player's party. + Optional avatarEntity = + this.getCastingAvatarEntityForEnergy(invoke.getEntityId()); + + // Bug: invokes twice sometimes, Ayato, Keqing + // ToDo: deal with press, hold difference. deal with charge(Beidou, Yunjin) + if (avatarEntity.isPresent()) { + Avatar avatar = avatarEntity.get().getAvatar(); + + if (avatar != null) { + int avatarId = avatar.getAvatarId(); + AvatarSkillDepotData skillDepotData = avatar.getSkillDepot(); + + // Determine how many particles we need to create for this avatar. + amount = this.getBallCountForAvatar(avatarId); + + // Determine the avatar's element, and based on that the ID of the + // particles we have to generate. + if (skillDepotData != null) { + ElementType element = skillDepotData.getElementType(); + itemId = this.getBallIdForElement(element); + } + } + } + + // Generate the particles. + var pos = new Position(action.getPos()); + for (int i = 0; i < amount; i++) { + this.generateElemBall(itemId, pos, 1); + } + } + + /** + * Energy generation for NAs/CAs. + * + * @param avatar The avatar. + */ + private void generateEnergyForNormalAndCharged(EntityAvatar avatar) { + // This logic is based on the descriptions given in + // https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks + // https://library.keqingmains.com/combat-mechanics/energy#auto-attacking + // Those descriptions are lacking in some information, so this implementation most likely + // does not fully replicate the behavior of the official server. Open questions: + // - Does the probability for a character reset after some time? + // - Does the probability for a character reset when switching them out? + // - Does this really count every individual hit separately? + + // Get the avatar's weapon type. + WeaponType weaponType = avatar.getAvatar().getAvatarData().getWeaponType(); + + // Check if we already have probability data for this avatar. If not, insert it. + if (!this.avatarNormalProbabilities.containsKey(avatar)) { + this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); + } + + // Roll for energy. + int currentProbability = this.avatarNormalProbabilities.getInt(avatar); + int roll = ThreadLocalRandom.current().nextInt(0, 100); + + // If the player wins the roll, we increase the avatar's energy and reset the probability. + if (roll < currentProbability) { + avatar.addEnergy(1.0f, PropChangeReason.PROP_CHANGE_REASON_ABILITY, true); + this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); + } + // Otherwise, we increase the probability for the next hit. + else { + this.avatarNormalProbabilities.put( + avatar, currentProbability + weaponType.getEnergyGainIncreaseProbability()); + } + } + + public void handleAttackHit(EvtBeingHitInfo hitInfo) { + // Get the attack result. + AttackResult attackRes = hitInfo.getAttackResult(); + + // Make sure the attack was performed by the currently active avatar. If not, we ignore the hit. + Optional attackerEntity = + this.getCastingAvatarEntityForEnergy(attackRes.getAttackerId()); + if (attackerEntity.isEmpty() + || this.player.getTeamManager().getCurrentAvatarEntity().getId() + != attackerEntity.get().getId()) { + return; + } + + // Make sure the target is an actual enemy. + GameEntity targetEntity = this.player.getScene().getEntityById(attackRes.getDefenseId()); + if (!(targetEntity instanceof EntityMonster targetMonster)) { + return; + } + + MonsterType targetType = targetMonster.getMonsterData().getType(); + if (targetType != MonsterType.MONSTER_ORDINARY && targetType != MonsterType.MONSTER_BOSS) { + return; + } + + // Get the ability that caused this hit. + AbilityIdentifier ability = attackRes.getAbilityIdentifier(); + + // Make sure there is no actual "ability" associated with the hit. For now, this is how we + // identify normal and charged attacks. Note that this is not completely accurate: + // - Many character's charged attacks have an ability associated with them. This means that, + // for now, we don't identify charged attacks reliably. + // - There might also be some cases where we incorrectly identify something as a normal or + // charged attack that is not (Diluc's E?). + // - Catalyst normal attacks have an ability, so we don't handle those for now. + // ToDo: Fix all of that. + if (ability != AbilityIdentifier.getDefaultInstance()) { + return; + } + + // Handle the energy generation. + this.generateEnergyForNormalAndCharged(attackerEntity.get()); + } + + /* + * Energy logic related to using skills. + */ + + private void handleBurstCast(Avatar avatar, int skillId) { + // Don't do anything if energy usage is disabled. + if (!GAME_OPTIONS.energyUsage || !this.energyUsage) { + return; + } + + // If the cast skill was a burst, consume energy. + if (avatar.getSkillDepot() != null && skillId == avatar.getSkillDepot().getEnergySkill()) { + avatar.getAsEntity().clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START); + } + } + + public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { + // Determine the entity that has cast the skill. Cancel if we can't find that avatar. + Optional caster = + this.player.getTeamManager().getActiveTeam().stream() + .filter(character -> character.getId() == casterId) + .findFirst(); + + if (caster.isEmpty()) { + return; + } + + Avatar avatar = caster.get().getAvatar(); + + // Handle elemental burst. + this.handleBurstCast(avatar, skillId); + } + + /* + * Monster energy drops. + */ + + private void generateElemBallDrops(EntityMonster monster, int dropId) { + // Generate all drops specified for the given drop id. + if (!energyDropData.containsKey(dropId)) { + Grasscutter.getLogger().warn("No drop data for dropId {} found.", dropId); + return; + } + + for (EnergyDropInfo info : energyDropData.get(dropId)) { + this.generateElemBall(info.getBallId(), monster.getPosition(), info.getCount()); + } + } + + public void handleMonsterEnergyDrop( + EntityMonster monster, float hpBeforeDamage, float hpAfterDamage) { + // Make sure this is actually a monster. + // Note that some wildlife also has that type, like boars or birds. + MonsterType type = monster.getMonsterData().getType(); + if (type != MonsterType.MONSTER_ORDINARY && type != MonsterType.MONSTER_BOSS) { + return; + } + + // Calculate the HP thresholds for before and after the damage was taken. + float maxHp = monster.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + float thresholdBefore = hpBeforeDamage / maxHp; + float thresholdAfter = hpAfterDamage / maxHp; + + // Determine the thresholds the monster has passed, and generate drops based on that. + for (HpDrops drop : monster.getMonsterData().getHpDrops()) { + if (drop.getDropId() == 0) { + continue; + } + + float threshold = drop.getHpPercent() / 100.0f; + if (threshold < thresholdBefore && threshold >= thresholdAfter) { + this.generateElemBallDrops(monster, drop.getDropId()); + } + } + + // Handle kill drops. + if (hpAfterDamage <= 0 && monster.getMonsterData().getKillDropId() != 0) { + this.generateElemBallDrops(monster, monster.getMonsterData().getKillDropId()); + } + } + + /* + * Utilities. + */ + + private void generateElemBall(int ballId, Position position, int count) { + // Generate a particle/orb with the specified parameters. + ItemData itemData = GameData.getItemDataMap().get(ballId); + if (itemData == null) { + return; + } + + EntityItem energyBall = + new EntityItem(this.getPlayer().getScene(), this.getPlayer(), itemData, position, count); + this.getPlayer().getScene().addEntity(energyBall); + } + + private Optional getCastingAvatarEntityForEnergy(int invokeEntityId) { + // To determine the avatar that has cast the skill that caused the energy particle to be + // generated, + // we have to look at the entity that has invoked the ability. This can either be that avatar + // directly, + // or it can be an `EntityClientGadget`, owned (some way up the owner hierarchy) by the avatar + // that cast the skill. + + // Try to get the invoking entity from the scene. + GameEntity entity = this.player.getScene().getEntityById(invokeEntityId); + + // Determine the ID of the entity that originally cast this skill. If the scene entity is null, + // or not an `EntityClientGadget`, we assume that we are directly looking at the casting avatar + // (the null case will happen if the avatar was switched out between casting the skill and the + // particle being generated). If the scene entity is an `EntityClientGadget`, we need to find + // the + // ID of the original owner of that gadget. + int avatarEntityId = + (!(entity instanceof EntityClientGadget)) + ? invokeEntityId + : ((EntityClientGadget) entity).getOriginalOwnerEntityId(); + + // Finally, find the avatar entity in the player's team. + return this.player.getTeamManager().getActiveTeam().stream() + .filter(character -> character.getId() == avatarEntityId) + .findFirst(); + } + + public boolean getEnergyUsage() { + return this.energyUsage; + } + + public void setEnergyUsage(boolean energyUsage) { + this.energyUsage = energyUsage; + if (!energyUsage) { // Refill team energy if usage is disabled + for (EntityAvatar entityAvatar : this.player.getTeamManager().getActiveTeam()) { + entityAvatar.addEnergy(1000, PropChangeReason.PROP_CHANGE_REASON_GM, true); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationEntry.java b/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationEntry.java index b7047a930..609a5bd1b 100644 --- a/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationEntry.java +++ b/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationEntry.java @@ -1,16 +1,16 @@ -package emu.grasscutter.game.managers.energy; - -import java.util.List; - -public class SkillParticleGenerationEntry { - private int avatarId; - private List amountList; - - public int getAvatarId() { - return this.avatarId; - } - - public List getAmountList() { - return this.amountList; - } -} +package emu.grasscutter.game.managers.energy; + +import java.util.List; + +public class SkillParticleGenerationEntry { + private int avatarId; + private List amountList; + + public int getAvatarId() { + return this.avatarId; + } + + public List getAmountList() { + return this.amountList; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationInfo.java b/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationInfo.java index c9ce4067a..27ccb0562 100644 --- a/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationInfo.java +++ b/src/main/java/emu/grasscutter/game/managers/energy/SkillParticleGenerationInfo.java @@ -1,14 +1,14 @@ -package emu.grasscutter.game.managers.energy; - -public class SkillParticleGenerationInfo { - private int value; - private int chance; - - public int getValue() { - return this.value; - } - - public int getChance() { - return this.chance; - } -} +package emu.grasscutter.game.managers.energy; + +public class SkillParticleGenerationInfo { + private int value; + private int chance; + + public int getValue() { + return this.value; + } + + public int getChance() { + return this.chance; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/forging/ActiveForgeData.java b/src/main/java/emu/grasscutter/game/managers/forging/ActiveForgeData.java index cab430578..1e838080c 100644 --- a/src/main/java/emu/grasscutter/game/managers/forging/ActiveForgeData.java +++ b/src/main/java/emu/grasscutter/game/managers/forging/ActiveForgeData.java @@ -1,97 +1,96 @@ -package emu.grasscutter.game.managers.forging; - -import dev.morphia.annotations.Entity; - -@Entity -public class ActiveForgeData { - private int forgeId; - private int avatarId; - private int count; - - private int startTime; - private int forgeTime; - - private int lastUnfinishedCount; - private boolean changed; - - public int getFinishedCount(int currentTime) { - int timeDelta = currentTime - this.startTime; - int finishedCount = timeDelta / this.forgeTime; - - return Math.min(finishedCount, this.count); - } - - public int getUnfinishedCount(int currentTime) { - return this.count - this.getFinishedCount(currentTime); - } - - public int getNextFinishTimestamp(int currentTime) { - return - (currentTime >= this.getTotalFinishTimestamp()) - ? this.getTotalFinishTimestamp() - : (this.getFinishedCount(currentTime) * this.forgeTime + this.forgeTime + this.startTime); - } - - public int getTotalFinishTimestamp() { - return this.startTime + this.forgeTime * this.count; - } - - public int getForgeId() { - return this.forgeId; - } - - public void setForgeId(int value) { - this.forgeId = value; - } - - public int getAvatarId() { - return this.avatarId; - } - - public void setAvatarId(int value) { - this.avatarId = value; - } - - public int getCount() { - return count; - } - - public void setCount(int value) { - this.count = value; - } - - public int getStartTime() { - return this.startTime; - } - - public void setStartTime(int value) { - this.startTime = value; - } - - public int getForgeTime() { - return this.forgeTime; - } - - public void setForgeTime(int value) { - this.forgeTime = value; - } - - public boolean isChanged() { - return this.changed; - } - - public void setChanged(boolean value) { - this.changed = value; - } - - public boolean updateChanged(int currentTime) { - int currentUnfinished = this.getUnfinishedCount(currentTime); - - if (currentUnfinished != this.lastUnfinishedCount) { - this.changed = true; - this.lastUnfinishedCount = currentUnfinished; - } - - return this.changed; - } -} +package emu.grasscutter.game.managers.forging; + +import dev.morphia.annotations.Entity; + +@Entity +public class ActiveForgeData { + private int forgeId; + private int avatarId; + private int count; + + private int startTime; + private int forgeTime; + + private int lastUnfinishedCount; + private boolean changed; + + public int getFinishedCount(int currentTime) { + int timeDelta = currentTime - this.startTime; + int finishedCount = timeDelta / this.forgeTime; + + return Math.min(finishedCount, this.count); + } + + public int getUnfinishedCount(int currentTime) { + return this.count - this.getFinishedCount(currentTime); + } + + public int getNextFinishTimestamp(int currentTime) { + return (currentTime >= this.getTotalFinishTimestamp()) + ? this.getTotalFinishTimestamp() + : (this.getFinishedCount(currentTime) * this.forgeTime + this.forgeTime + this.startTime); + } + + public int getTotalFinishTimestamp() { + return this.startTime + this.forgeTime * this.count; + } + + public int getForgeId() { + return this.forgeId; + } + + public void setForgeId(int value) { + this.forgeId = value; + } + + public int getAvatarId() { + return this.avatarId; + } + + public void setAvatarId(int value) { + this.avatarId = value; + } + + public int getCount() { + return count; + } + + public void setCount(int value) { + this.count = value; + } + + public int getStartTime() { + return this.startTime; + } + + public void setStartTime(int value) { + this.startTime = value; + } + + public int getForgeTime() { + return this.forgeTime; + } + + public void setForgeTime(int value) { + this.forgeTime = value; + } + + public boolean isChanged() { + return this.changed; + } + + public void setChanged(boolean value) { + this.changed = value; + } + + public boolean updateChanged(int currentTime) { + int currentUnfinished = this.getUnfinishedCount(currentTime); + + if (currentUnfinished != this.lastUnfinishedCount) { + this.changed = true; + this.lastUnfinishedCount = currentUnfinished; + } + + return this.changed; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java b/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java index 020822f2e..9b386e848 100644 --- a/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java +++ b/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java @@ -1,305 +1,318 @@ -package emu.grasscutter.game.managers.forging; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ForgeData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; -import emu.grasscutter.net.proto.ForgeQueueManipulateReqOuterClass.ForgeQueueManipulateReq; -import emu.grasscutter.net.proto.ForgeQueueManipulateTypeOuterClass.ForgeQueueManipulateType; -import emu.grasscutter.net.proto.ForgeStartReqOuterClass.ForgeStartReq; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ForgingManager extends BasePlayerManager { - - public ForgingManager(Player player) { - super(player); - } - - /********** - Blueprint unlocking. - **********/ - public boolean unlockForgingBlueprint(int id) { - // Tell the client that this blueprint is now unlocked and add the unlocked item to the player. - if (!this.player.getUnlockedForgingBlueprints().add(id)) { - return false; // Already unlocked - } - this.player.sendPacket(new PacketForgeFormulaDataNotify(id)); - return true; - } - - /********** - Communicate forging information to the client. - **********/ - private synchronized int determineNumberOfQueues() { - int adventureRank = player.getLevel(); - return - (adventureRank >= 15) ? 4 - : (adventureRank >= 10) ? 3 - : (adventureRank >= 5) ? 2 - : 1; - } - - private synchronized Map determineCurrentForgeQueueData() { - Map res = new HashMap<>(); - int currentTime = Utils.getCurrentSeconds(); - - // Create queue information for all active forges. - for (int i = 0; i < this.player.getActiveForges().size(); i++) { - ActiveForgeData activeForge = this.player.getActiveForges().get(i); - - ForgeQueueData data = ForgeQueueData.newBuilder() - .setQueueId(i + 1) - .setForgeId(activeForge.getForgeId()) - .setFinishCount(activeForge.getFinishedCount(currentTime)) - .setUnfinishCount(activeForge.getUnfinishedCount(currentTime)) - .setTotalFinishTimestamp(activeForge.getTotalFinishTimestamp()) - .setNextFinishTimestamp(activeForge.getNextFinishTimestamp(currentTime)) - .setAvatarId(activeForge.getAvatarId()) - .build(); - - res.put(i + 1, data); - } - - return res; - } - - public synchronized void sendForgeDataNotify() { - // Determine the number of queues and unlocked items. - int numQueues = this.determineNumberOfQueues(); - var unlockedItems = this.player.getUnlockedForgingBlueprints(); - var queueData = this.determineCurrentForgeQueueData(); - - // Send notification. - this.player.sendPacket(new PacketForgeDataNotify(unlockedItems, numQueues, queueData)); - } - - public synchronized void handleForgeGetQueueDataReq() { - // Determine the number of queues. - int numQueues = this.determineNumberOfQueues(); - var queueData = this.determineCurrentForgeQueueData(); - - // Reply. - this.player.sendPacket(new PacketForgeGetQueueDataRsp(Retcode.RET_SUCC, numQueues, queueData)); - } - - /********** - Initiate forging process. - **********/ - private synchronized void sendForgeQueueDataNotify() { - var queueData = this.determineCurrentForgeQueueData(); - this.player.sendPacket(new PacketForgeQueueDataNotify(queueData, List.of())); - } - - private synchronized void sendForgeQueueDataNotify(boolean hasRemoved) { - var queueData = this.determineCurrentForgeQueueData(); - - if (hasRemoved) { - this.player.sendPacket(new PacketForgeQueueDataNotify(Map.of(), List.of(1, 2, 3, 4))); - } - - this.player.sendPacket(new PacketForgeQueueDataNotify(queueData, List.of())); - } - - public synchronized void handleForgeStartReq(ForgeStartReq req) { - // Refuse if all queues are already full. - if (this.player.getActiveForges().size() >= this.determineNumberOfQueues()) { - this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_FORGE_QUEUE_FULL)); - return; - } - - // Get the required forging information for the target item. - if (!GameData.getForgeDataMap().containsKey(req.getForgeId())) { - this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_FAIL)); //ToDo: Probably the wrong return code. - return; - } - - ForgeData forgeData = GameData.getForgeDataMap().get(req.getForgeId()); - - //Check if the player has sufficient forge points. - int requiredPoints = forgeData.getForgePoint() * req.getForgeCount(); - if (requiredPoints > this.player.getForgePoints()) { - this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_FORGE_POINT_NOT_ENOUGH)); - return; - } - - // Check if we have enough of each material and consume. - List material = new ArrayList<>(forgeData.getMaterialItems()); - material.add(new ItemParamData(202, forgeData.getScoinCost())); - - boolean success = player.getInventory().payItems(material, req.getForgeCount(), ActionReason.ForgeCost); - - if (!success) { - //TODO:I'm not sure this one is correct. - this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_ITEM_COUNT_NOT_ENOUGH)); //ToDo: Probably the wrong return code. - } - - // Consume forge points. - this.player.setForgePoints(this.player.getForgePoints() - requiredPoints); - - // Create and add active forge. - ActiveForgeData activeForge = new ActiveForgeData(); - activeForge.setForgeId(req.getForgeId()); - activeForge.setAvatarId(req.getAvatarId()); - activeForge.setCount(req.getForgeCount()); - activeForge.setStartTime(Utils.getCurrentSeconds()); - activeForge.setForgeTime(forgeData.getForgeTime()); - - this.player.getActiveForges().add(activeForge); - - // Done. - this.sendForgeQueueDataNotify(); - this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_SUCC)); - } - - /********** - Forge queue manipulation (obtaining results and cancelling forges). - **********/ - private synchronized void obtainItems(int queueId) { - // Determine how many items are finished. - int currentTime = Utils.getCurrentSeconds(); - ActiveForgeData forge = this.player.getActiveForges().get(queueId - 1); - - int finished = forge.getFinishedCount(currentTime); - int unfinished = forge.getUnfinishedCount(currentTime); - - // Sanity check: Are any items finished? - if (finished <= 0) { - return; - } - - // Give finished items to the player. - ForgeData data = GameData.getForgeDataMap().get(forge.getForgeId()); - - int resultId = data.getResultItemId() > 0 ? data.getResultItemId() : data.getShowItemId(); - ItemData resultItemData = GameData.getItemDataMap().get(resultId); - GameItem addItem = new GameItem(resultItemData, data.getResultItemCount() * finished); - this.player.getInventory().addItem(addItem); - - // Battle pass trigger handler - this.player.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_DO_FORGE, 0, finished); - - // Replace active forge with a new one for the unfinished items, if there are any. - if (unfinished > 0) { - ActiveForgeData remainingForge = new ActiveForgeData(); - - remainingForge.setForgeId(forge.getForgeId()); - remainingForge.setAvatarId(forge.getAvatarId()); - remainingForge.setCount(unfinished); - remainingForge.setForgeTime(forge.getForgeTime()); - remainingForge.setStartTime(forge.getStartTime() + finished * forge.getForgeTime()); - - this.player.getActiveForges().set(queueId - 1, remainingForge); - this.sendForgeQueueDataNotify(); - } - // Otherwise, completely remove it. - else { - this.player.getActiveForges().remove(queueId - 1); - // this.sendForgeQueueDataNotify(queueId); - this.sendForgeQueueDataNotify(true); - } - - // Send response. - this.player.sendPacket(new PacketForgeQueueManipulateRsp(Retcode.RET_SUCC, ForgeQueueManipulateType.FORGE_QUEUE_MANIPULATE_TYPE_RECEIVE_OUTPUT, List.of(addItem), List.of(), List.of())); - } - - private synchronized void cancelForge(int queueId) { - // Make sure there are no unfinished items. - int currentTime = Utils.getCurrentSeconds(); - ActiveForgeData forge = this.player.getActiveForges().get(queueId - 1); - - if (forge.getFinishedCount(currentTime) > 0) { - return; - } - - // Return material items to the player. - ForgeData data = GameData.getForgeDataMap().get(forge.getForgeId()); - - var returnItems = new ArrayList(); - for (var material : data.getMaterialItems()) { - if (material.getItemId() == 0) { - continue; - } - - ItemData resultItemData = GameData.getItemDataMap().get(material.getItemId()); - GameItem returnItem = new GameItem(resultItemData, material.getItemCount() * forge.getCount()); - - this.player.getInventory().addItem(returnItem); - returnItems.add(returnItem); - } - - // Return Mora to the player. - this.player.setMora(this.player.getMora() + data.getScoinCost() * forge.getCount()); - - ItemData moraItem = GameData.getItemDataMap().get(202); - GameItem returnMora = new GameItem(moraItem, data.getScoinCost() * forge.getCount()); - returnItems.add(returnMora); - - // Return forge points to the player. - int requiredPoints = data.getForgePoint() * forge.getCount(); - int newPoints = Math.min(this.player.getForgePoints() + requiredPoints, 300_000); - - this.player.setForgePoints(newPoints); - - // Remove the forge queue. - this.player.getActiveForges().remove(queueId - 1); - this.sendForgeQueueDataNotify(true); - - // Send response. - this.player.sendPacket(new PacketForgeQueueManipulateRsp(Retcode.RET_SUCC, ForgeQueueManipulateType.FORGE_QUEUE_MANIPULATE_TYPE_STOP_FORGE, List.of(), returnItems, List.of())); - } - - public synchronized void handleForgeQueueManipulateReq(ForgeQueueManipulateReq req) { - // Get info from the request. - int queueId = req.getForgeQueueId(); - var manipulateType = req.getManipulateType(); - - // Handle according to the manipulation type. - switch (manipulateType) { - case FORGE_QUEUE_MANIPULATE_TYPE_RECEIVE_OUTPUT -> this.obtainItems(queueId); - case FORGE_QUEUE_MANIPULATE_TYPE_STOP_FORGE -> this.cancelForge(queueId); - default -> { - } //Should never happen. - } - } - - /********** - Periodic forging updates. - **********/ - public synchronized void sendPlayerForgingUpdate() { - int currentTime = Utils.getCurrentSeconds(); - - // Determine if sending an update is necessary. - // We only send an update if there are forges in the forge queue - // that have changed since the last notification. - if (this.player.getActiveForges().size() <= 0) { - return; - } - - boolean hasChanges = this.player.getActiveForges().stream() - .anyMatch(forge -> forge.updateChanged(currentTime)); - - if (!hasChanges) { - return; - } - - // Send notification. - this.sendForgeQueueDataNotify(); - - // Reset changed flags. - this.player.getActiveForges().stream() - .forEach(forge -> forge.setChanged(false)); - } -} +package emu.grasscutter.game.managers.forging; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ForgeData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; +import emu.grasscutter.net.proto.ForgeQueueManipulateReqOuterClass.ForgeQueueManipulateReq; +import emu.grasscutter.net.proto.ForgeQueueManipulateTypeOuterClass.ForgeQueueManipulateType; +import emu.grasscutter.net.proto.ForgeStartReqOuterClass.ForgeStartReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Utils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ForgingManager extends BasePlayerManager { + + public ForgingManager(Player player) { + super(player); + } + + /********** + * Blueprint unlocking. + **********/ + public boolean unlockForgingBlueprint(int id) { + // Tell the client that this blueprint is now unlocked and add the unlocked item to the player. + if (!this.player.getUnlockedForgingBlueprints().add(id)) { + return false; // Already unlocked + } + this.player.sendPacket(new PacketForgeFormulaDataNotify(id)); + return true; + } + + /********** + * Communicate forging information to the client. + **********/ + private synchronized int determineNumberOfQueues() { + int adventureRank = player.getLevel(); + return (adventureRank >= 15) ? 4 : (adventureRank >= 10) ? 3 : (adventureRank >= 5) ? 2 : 1; + } + + private synchronized Map determineCurrentForgeQueueData() { + Map res = new HashMap<>(); + int currentTime = Utils.getCurrentSeconds(); + + // Create queue information for all active forges. + for (int i = 0; i < this.player.getActiveForges().size(); i++) { + ActiveForgeData activeForge = this.player.getActiveForges().get(i); + + ForgeQueueData data = + ForgeQueueData.newBuilder() + .setQueueId(i + 1) + .setForgeId(activeForge.getForgeId()) + .setFinishCount(activeForge.getFinishedCount(currentTime)) + .setUnfinishCount(activeForge.getUnfinishedCount(currentTime)) + .setTotalFinishTimestamp(activeForge.getTotalFinishTimestamp()) + .setNextFinishTimestamp(activeForge.getNextFinishTimestamp(currentTime)) + .setAvatarId(activeForge.getAvatarId()) + .build(); + + res.put(i + 1, data); + } + + return res; + } + + public synchronized void sendForgeDataNotify() { + // Determine the number of queues and unlocked items. + int numQueues = this.determineNumberOfQueues(); + var unlockedItems = this.player.getUnlockedForgingBlueprints(); + var queueData = this.determineCurrentForgeQueueData(); + + // Send notification. + this.player.sendPacket(new PacketForgeDataNotify(unlockedItems, numQueues, queueData)); + } + + public synchronized void handleForgeGetQueueDataReq() { + // Determine the number of queues. + int numQueues = this.determineNumberOfQueues(); + var queueData = this.determineCurrentForgeQueueData(); + + // Reply. + this.player.sendPacket(new PacketForgeGetQueueDataRsp(Retcode.RET_SUCC, numQueues, queueData)); + } + + /********** + * Initiate forging process. + **********/ + private synchronized void sendForgeQueueDataNotify() { + var queueData = this.determineCurrentForgeQueueData(); + this.player.sendPacket(new PacketForgeQueueDataNotify(queueData, List.of())); + } + + private synchronized void sendForgeQueueDataNotify(boolean hasRemoved) { + var queueData = this.determineCurrentForgeQueueData(); + + if (hasRemoved) { + this.player.sendPacket(new PacketForgeQueueDataNotify(Map.of(), List.of(1, 2, 3, 4))); + } + + this.player.sendPacket(new PacketForgeQueueDataNotify(queueData, List.of())); + } + + public synchronized void handleForgeStartReq(ForgeStartReq req) { + // Refuse if all queues are already full. + if (this.player.getActiveForges().size() >= this.determineNumberOfQueues()) { + this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_FORGE_QUEUE_FULL)); + return; + } + + // Get the required forging information for the target item. + if (!GameData.getForgeDataMap().containsKey(req.getForgeId())) { + this.player.sendPacket( + new PacketForgeStartRsp(Retcode.RET_FAIL)); // ToDo: Probably the wrong return code. + return; + } + + ForgeData forgeData = GameData.getForgeDataMap().get(req.getForgeId()); + + // Check if the player has sufficient forge points. + int requiredPoints = forgeData.getForgePoint() * req.getForgeCount(); + if (requiredPoints > this.player.getForgePoints()) { + this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_FORGE_POINT_NOT_ENOUGH)); + return; + } + + // Check if we have enough of each material and consume. + List material = new ArrayList<>(forgeData.getMaterialItems()); + material.add(new ItemParamData(202, forgeData.getScoinCost())); + + boolean success = + player.getInventory().payItems(material, req.getForgeCount(), ActionReason.ForgeCost); + + if (!success) { + // TODO:I'm not sure this one is correct. + this.player.sendPacket( + new PacketForgeStartRsp( + Retcode.RET_ITEM_COUNT_NOT_ENOUGH)); // ToDo: Probably the wrong return code. + } + + // Consume forge points. + this.player.setForgePoints(this.player.getForgePoints() - requiredPoints); + + // Create and add active forge. + ActiveForgeData activeForge = new ActiveForgeData(); + activeForge.setForgeId(req.getForgeId()); + activeForge.setAvatarId(req.getAvatarId()); + activeForge.setCount(req.getForgeCount()); + activeForge.setStartTime(Utils.getCurrentSeconds()); + activeForge.setForgeTime(forgeData.getForgeTime()); + + this.player.getActiveForges().add(activeForge); + + // Done. + this.sendForgeQueueDataNotify(); + this.player.sendPacket(new PacketForgeStartRsp(Retcode.RET_SUCC)); + } + + /********** + * Forge queue manipulation (obtaining results and cancelling forges). + **********/ + private synchronized void obtainItems(int queueId) { + // Determine how many items are finished. + int currentTime = Utils.getCurrentSeconds(); + ActiveForgeData forge = this.player.getActiveForges().get(queueId - 1); + + int finished = forge.getFinishedCount(currentTime); + int unfinished = forge.getUnfinishedCount(currentTime); + + // Sanity check: Are any items finished? + if (finished <= 0) { + return; + } + + // Give finished items to the player. + ForgeData data = GameData.getForgeDataMap().get(forge.getForgeId()); + + int resultId = data.getResultItemId() > 0 ? data.getResultItemId() : data.getShowItemId(); + ItemData resultItemData = GameData.getItemDataMap().get(resultId); + GameItem addItem = new GameItem(resultItemData, data.getResultItemCount() * finished); + this.player.getInventory().addItem(addItem); + + // Battle pass trigger handler + this.player + .getBattlePassManager() + .triggerMission(WatcherTriggerType.TRIGGER_DO_FORGE, 0, finished); + + // Replace active forge with a new one for the unfinished items, if there are any. + if (unfinished > 0) { + ActiveForgeData remainingForge = new ActiveForgeData(); + + remainingForge.setForgeId(forge.getForgeId()); + remainingForge.setAvatarId(forge.getAvatarId()); + remainingForge.setCount(unfinished); + remainingForge.setForgeTime(forge.getForgeTime()); + remainingForge.setStartTime(forge.getStartTime() + finished * forge.getForgeTime()); + + this.player.getActiveForges().set(queueId - 1, remainingForge); + this.sendForgeQueueDataNotify(); + } + // Otherwise, completely remove it. + else { + this.player.getActiveForges().remove(queueId - 1); + // this.sendForgeQueueDataNotify(queueId); + this.sendForgeQueueDataNotify(true); + } + + // Send response. + this.player.sendPacket( + new PacketForgeQueueManipulateRsp( + Retcode.RET_SUCC, + ForgeQueueManipulateType.FORGE_QUEUE_MANIPULATE_TYPE_RECEIVE_OUTPUT, + List.of(addItem), + List.of(), + List.of())); + } + + private synchronized void cancelForge(int queueId) { + // Make sure there are no unfinished items. + int currentTime = Utils.getCurrentSeconds(); + ActiveForgeData forge = this.player.getActiveForges().get(queueId - 1); + + if (forge.getFinishedCount(currentTime) > 0) { + return; + } + + // Return material items to the player. + ForgeData data = GameData.getForgeDataMap().get(forge.getForgeId()); + + var returnItems = new ArrayList(); + for (var material : data.getMaterialItems()) { + if (material.getItemId() == 0) { + continue; + } + + ItemData resultItemData = GameData.getItemDataMap().get(material.getItemId()); + GameItem returnItem = + new GameItem(resultItemData, material.getItemCount() * forge.getCount()); + + this.player.getInventory().addItem(returnItem); + returnItems.add(returnItem); + } + + // Return Mora to the player. + this.player.setMora(this.player.getMora() + data.getScoinCost() * forge.getCount()); + + ItemData moraItem = GameData.getItemDataMap().get(202); + GameItem returnMora = new GameItem(moraItem, data.getScoinCost() * forge.getCount()); + returnItems.add(returnMora); + + // Return forge points to the player. + int requiredPoints = data.getForgePoint() * forge.getCount(); + int newPoints = Math.min(this.player.getForgePoints() + requiredPoints, 300_000); + + this.player.setForgePoints(newPoints); + + // Remove the forge queue. + this.player.getActiveForges().remove(queueId - 1); + this.sendForgeQueueDataNotify(true); + + // Send response. + this.player.sendPacket( + new PacketForgeQueueManipulateRsp( + Retcode.RET_SUCC, + ForgeQueueManipulateType.FORGE_QUEUE_MANIPULATE_TYPE_STOP_FORGE, + List.of(), + returnItems, + List.of())); + } + + public synchronized void handleForgeQueueManipulateReq(ForgeQueueManipulateReq req) { + // Get info from the request. + int queueId = req.getForgeQueueId(); + var manipulateType = req.getManipulateType(); + + // Handle according to the manipulation type. + switch (manipulateType) { + case FORGE_QUEUE_MANIPULATE_TYPE_RECEIVE_OUTPUT -> this.obtainItems(queueId); + case FORGE_QUEUE_MANIPULATE_TYPE_STOP_FORGE -> this.cancelForge(queueId); + default -> {} // Should never happen. + } + } + + /********** + * Periodic forging updates. + **********/ + public synchronized void sendPlayerForgingUpdate() { + int currentTime = Utils.getCurrentSeconds(); + + // Determine if sending an update is necessary. + // We only send an update if there are forges in the forge queue + // that have changed since the last notification. + if (this.player.getActiveForges().size() <= 0) { + return; + } + + boolean hasChanges = + this.player.getActiveForges().stream().anyMatch(forge -> forge.updateChanged(currentTime)); + + if (!hasChanges) { + return; + } + + // Send notification. + this.sendForgeQueueDataNotify(); + + // Reset changed flags. + this.player.getActiveForges().stream().forEach(forge -> forge.setChanged(false)); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMark.java b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMark.java index 9753108a4..75eabbfb8 100644 --- a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMark.java +++ b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMark.java @@ -1,62 +1,62 @@ -package emu.grasscutter.game.managers.mapmark; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.MapMarkFromTypeOuterClass.MapMarkFromType; -import emu.grasscutter.net.proto.MapMarkPointOuterClass.MapMarkPoint; -import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; -import emu.grasscutter.utils.Position; - -@Entity -public class MapMark { - private int sceneId; - private String name; - private Position position; - private final MapMarkPointType mapMarkPointType; - private int monsterId; - private final MapMarkFromType mapMarkFromType; - private int questId; - - @Deprecated // Morhpia - public MapMark() { - this.mapMarkPointType = MapMarkPointType.MAP_MARK_POINT_TYPE_MONSTER; - this.mapMarkFromType = MapMarkFromType.MAP_MARK_FROM_TYPE_MONSTER; - } - - public MapMark(MapMarkPoint mapMarkPoint) { - this.sceneId = mapMarkPoint.getSceneId(); - this.name = mapMarkPoint.getName(); - this.position = new Position(mapMarkPoint.getPos()); - this.mapMarkPointType = mapMarkPoint.getPointType(); - this.monsterId = mapMarkPoint.getMonsterId(); - this.mapMarkFromType = mapMarkPoint.getFromType(); - this.questId = mapMarkPoint.getQuestId(); - } - - public int getSceneId() { - return this.sceneId; - } - - public String getName() { - return this.name; - } - - public Position getPosition() { - return this.position; - } - - public MapMarkPointType getMapMarkPointType() { - return this.mapMarkPointType; - } - - public int getMonsterId() { - return this.monsterId; - } - - public MapMarkFromType getMapMarkFromType() { - return this.mapMarkFromType; - } - - public int getQuestId() { - return this.questId; - } -} +package emu.grasscutter.game.managers.mapmark; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.MapMarkFromTypeOuterClass.MapMarkFromType; +import emu.grasscutter.net.proto.MapMarkPointOuterClass.MapMarkPoint; +import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; +import emu.grasscutter.utils.Position; + +@Entity +public class MapMark { + private int sceneId; + private String name; + private Position position; + private final MapMarkPointType mapMarkPointType; + private int monsterId; + private final MapMarkFromType mapMarkFromType; + private int questId; + + @Deprecated // Morhpia + public MapMark() { + this.mapMarkPointType = MapMarkPointType.MAP_MARK_POINT_TYPE_MONSTER; + this.mapMarkFromType = MapMarkFromType.MAP_MARK_FROM_TYPE_MONSTER; + } + + public MapMark(MapMarkPoint mapMarkPoint) { + this.sceneId = mapMarkPoint.getSceneId(); + this.name = mapMarkPoint.getName(); + this.position = new Position(mapMarkPoint.getPos()); + this.mapMarkPointType = mapMarkPoint.getPointType(); + this.monsterId = mapMarkPoint.getMonsterId(); + this.mapMarkFromType = mapMarkPoint.getFromType(); + this.questId = mapMarkPoint.getQuestId(); + } + + public int getSceneId() { + return this.sceneId; + } + + public String getName() { + return this.name; + } + + public Position getPosition() { + return this.position; + } + + public MapMarkPointType getMapMarkPointType() { + return this.mapMarkPointType; + } + + public int getMonsterId() { + return this.monsterId; + } + + public MapMarkFromType getMapMarkFromType() { + return this.mapMarkFromType; + } + + public int getQuestId() { + return this.questId; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java index fa1048547..52d2329a3 100644 --- a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java +++ b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java @@ -1,82 +1,88 @@ -package emu.grasscutter.game.managers.mapmark; - -import emu.grasscutter.config.Configuration; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; -import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; -import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq.Operation; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.packet.send.PacketMarkMapRsp; -import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; -import emu.grasscutter.utils.Position; - -import java.util.Map; - -public class MapMarksManager extends BasePlayerManager { - public static final int mapMarkMaxCount = 150; - - public MapMarksManager(Player player) { - super(player); - } - - public Map getMapMarks() { - return this.getPlayer().getMapMarks(); - } - - public void handleMapMarkReq(MarkMapReq req) { - Operation op = req.getOp(); - switch (op) { - case OPERATION_ADD -> { - MapMark createMark = new MapMark(req.getMark()); - // keep teleporting functionality on fishhook mark. - if (Configuration.GAME_OPTIONS.fishhookTeleport && createMark.getMapMarkPointType() == MapMarkPointType.MAP_MARK_POINT_TYPE_FISH_POOL) { - this.teleport(player, createMark); - return; - } - this.addMapMark(createMark); - } - case OPERATION_MOD -> { - MapMark oldMark = new MapMark(req.getOld()); - this.removeMapMark(oldMark.getPosition()); - MapMark newMark = new MapMark(req.getMark()); - this.addMapMark(newMark); - } - case OPERATION_DEL -> { - MapMark deleteMark = new MapMark(req.getMark()); - this.removeMapMark(deleteMark.getPosition()); - } - } - if (op != Operation.OPERATION_GET) { - this.save(); - } - player.getSession().send(new PacketMarkMapRsp(this.getMapMarks())); - } - - public String getMapMarkKey(Position position) { - return "x" + (int) position.getX() + "z" + (int) position.getZ(); - } - - public void removeMapMark(Position position) { - this.getMapMarks().remove(this.getMapMarkKey(position)); - } - - public void addMapMark(MapMark mapMark) { - if (this.getMapMarks().size() < mapMarkMaxCount) { - this.getMapMarks().put(this.getMapMarkKey(mapMark.getPosition()), mapMark); - } - } - - private void teleport(Player player, MapMark mapMark) { - float y; - try { - y = Float.parseFloat(mapMark.getName()); - } catch (Exception e) { - y = 300; - } - - Position pos = mapMark.getPosition(); - player.getWorld().transferPlayerToScene(player, mapMark.getSceneId(), TeleportType.MAP, new Position(pos.getX(), y, pos.getZ())); - player.getScene().broadcastPacket(new PacketSceneEntityAppearNotify(player)); - } -} +package emu.grasscutter.game.managers.mapmark; + +import emu.grasscutter.config.Configuration; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; +import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; +import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq.Operation; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.packet.send.PacketMarkMapRsp; +import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; +import emu.grasscutter.utils.Position; +import java.util.Map; + +public class MapMarksManager extends BasePlayerManager { + public static final int mapMarkMaxCount = 150; + + public MapMarksManager(Player player) { + super(player); + } + + public Map getMapMarks() { + return this.getPlayer().getMapMarks(); + } + + public void handleMapMarkReq(MarkMapReq req) { + Operation op = req.getOp(); + switch (op) { + case OPERATION_ADD -> { + MapMark createMark = new MapMark(req.getMark()); + // keep teleporting functionality on fishhook mark. + if (Configuration.GAME_OPTIONS.fishhookTeleport + && createMark.getMapMarkPointType() == MapMarkPointType.MAP_MARK_POINT_TYPE_FISH_POOL) { + this.teleport(player, createMark); + return; + } + this.addMapMark(createMark); + } + case OPERATION_MOD -> { + MapMark oldMark = new MapMark(req.getOld()); + this.removeMapMark(oldMark.getPosition()); + MapMark newMark = new MapMark(req.getMark()); + this.addMapMark(newMark); + } + case OPERATION_DEL -> { + MapMark deleteMark = new MapMark(req.getMark()); + this.removeMapMark(deleteMark.getPosition()); + } + } + if (op != Operation.OPERATION_GET) { + this.save(); + } + player.getSession().send(new PacketMarkMapRsp(this.getMapMarks())); + } + + public String getMapMarkKey(Position position) { + return "x" + (int) position.getX() + "z" + (int) position.getZ(); + } + + public void removeMapMark(Position position) { + this.getMapMarks().remove(this.getMapMarkKey(position)); + } + + public void addMapMark(MapMark mapMark) { + if (this.getMapMarks().size() < mapMarkMaxCount) { + this.getMapMarks().put(this.getMapMarkKey(mapMark.getPosition()), mapMark); + } + } + + private void teleport(Player player, MapMark mapMark) { + float y; + try { + y = Float.parseFloat(mapMark.getName()); + } catch (Exception e) { + y = 300; + } + + Position pos = mapMark.getPosition(); + player + .getWorld() + .transferPlayerToScene( + player, + mapMark.getSceneId(), + TeleportType.MAP, + new Position(pos.getX(), y, pos.getZ())); + player.getScene().broadcastPacket(new PacketSceneEntityAppearNotify(player)); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/stamina/AfterUpdateStaminaListener.java b/src/main/java/emu/grasscutter/game/managers/stamina/AfterUpdateStaminaListener.java index d6e1d5e51..3d55b07cd 100644 --- a/src/main/java/emu/grasscutter/game/managers/stamina/AfterUpdateStaminaListener.java +++ b/src/main/java/emu/grasscutter/game/managers/stamina/AfterUpdateStaminaListener.java @@ -1,12 +1,12 @@ -package emu.grasscutter.game.managers.stamina; - -public interface AfterUpdateStaminaListener { - /** - * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. - * This gives listeners a chance to intercept this update. - * - * @param reason Why updating stamina. - * @param newStamina New Stamina value. - */ - void onAfterUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); -} +package emu.grasscutter.game.managers.stamina; + +public interface AfterUpdateStaminaListener { + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's + * current stamina. This gives listeners a chance to intercept this update. + * + * @param reason Why updating stamina. + * @param newStamina New Stamina value. + */ + void onAfterUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); +} diff --git a/src/main/java/emu/grasscutter/game/managers/stamina/BeforeUpdateStaminaListener.java b/src/main/java/emu/grasscutter/game/managers/stamina/BeforeUpdateStaminaListener.java index 7b069cabf..276d5b35d 100644 --- a/src/main/java/emu/grasscutter/game/managers/stamina/BeforeUpdateStaminaListener.java +++ b/src/main/java/emu/grasscutter/game/managers/stamina/BeforeUpdateStaminaListener.java @@ -1,23 +1,24 @@ -package emu.grasscutter.game.managers.stamina; - -public interface BeforeUpdateStaminaListener { - /** - * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. - * This gives listeners a chance to intercept this update. - * - * @param reason Why updating stamina. - * @param newStamina New ABSOLUTE stamina value. - * @return true if you want to cancel this update, otherwise false. - */ - int onBeforeUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); - - /** - * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. - * This gives listeners a chance to intercept this update. - * - * @param reason Why updating stamina. - * @param consumption ConsumptionType and RELATIVE stamina change amount. - * @return true if you want to cancel this update, otherwise false. - */ - Consumption onBeforeUpdateStamina(String reason, Consumption consumption, boolean isCharacterStamina); -} +package emu.grasscutter.game.managers.stamina; + +public interface BeforeUpdateStaminaListener { + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's + * current stamina. This gives listeners a chance to intercept this update. + * + * @param reason Why updating stamina. + * @param newStamina New ABSOLUTE stamina value. + * @return true if you want to cancel this update, otherwise false. + */ + int onBeforeUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); + + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's + * current stamina. This gives listeners a chance to intercept this update. + * + * @param reason Why updating stamina. + * @param consumption ConsumptionType and RELATIVE stamina change amount. + * @return true if you want to cancel this update, otherwise false. + */ + Consumption onBeforeUpdateStamina( + String reason, Consumption consumption, boolean isCharacterStamina); +} diff --git a/src/main/java/emu/grasscutter/game/managers/stamina/Consumption.java b/src/main/java/emu/grasscutter/game/managers/stamina/Consumption.java index 15d777fc6..53860ae33 100644 --- a/src/main/java/emu/grasscutter/game/managers/stamina/Consumption.java +++ b/src/main/java/emu/grasscutter/game/managers/stamina/Consumption.java @@ -1,18 +1,17 @@ -package emu.grasscutter.game.managers.stamina; - -public class Consumption { - public ConsumptionType type = ConsumptionType.None; - public int amount = 0; - - public Consumption(ConsumptionType type, int amount) { - this.type = type; - this.amount = amount; - } - - public Consumption(ConsumptionType type) { - this(type, type.amount); - } - - public Consumption() { - } -} +package emu.grasscutter.game.managers.stamina; + +public class Consumption { + public ConsumptionType type = ConsumptionType.None; + public int amount = 0; + + public Consumption(ConsumptionType type, int amount) { + this.type = type; + this.amount = amount; + } + + public Consumption(ConsumptionType type) { + this(type, type.amount); + } + + public Consumption() {} +} diff --git a/src/main/java/emu/grasscutter/game/managers/stamina/ConsumptionType.java b/src/main/java/emu/grasscutter/game/managers/stamina/ConsumptionType.java index ddf21b166..c84ab055d 100644 --- a/src/main/java/emu/grasscutter/game/managers/stamina/ConsumptionType.java +++ b/src/main/java/emu/grasscutter/game/managers/stamina/ConsumptionType.java @@ -1,37 +1,37 @@ -package emu.grasscutter.game.managers.stamina; - -public enum ConsumptionType { - None(0), - - // consume - CLIMBING(-150), - CLIMB_START(-500), - CLIMB_JUMP(-2500), - DASH(-360), - FIGHT(0), // See StaminaManager.getFightConsumption() - FLY(-60), - // Slow swimming is handled per movement, not per second. - // Arm movement frequency depends on gender/age/height. - // TODO: Instead of cost -80 per tick, find a proper way to calculate cost. - SKIFF_DASH(-204), - SPRINT(-1800), - SWIM_DASH_START(-2000), - SWIM_DASH(-204), // -10.2 per second, 5Hz = -204 each tick - SWIMMING(-80), - TALENT_DASH(-300), // -1500 per second, 5Hz = -300 each tick - TALENT_DASH_START(-1000), - - // restore - POWERED_FLY(500), - POWERED_SKIFF(500), - RUN(500), - SKIFF(500), - STANDBY(500), - WALK(500); - - public final int amount; - - ConsumptionType(int amount) { - this.amount = amount; - } -} \ No newline at end of file +package emu.grasscutter.game.managers.stamina; + +public enum ConsumptionType { + None(0), + + // consume + CLIMBING(-150), + CLIMB_START(-500), + CLIMB_JUMP(-2500), + DASH(-360), + FIGHT(0), // See StaminaManager.getFightConsumption() + FLY(-60), + // Slow swimming is handled per movement, not per second. + // Arm movement frequency depends on gender/age/height. + // TODO: Instead of cost -80 per tick, find a proper way to calculate cost. + SKIFF_DASH(-204), + SPRINT(-1800), + SWIM_DASH_START(-2000), + SWIM_DASH(-204), // -10.2 per second, 5Hz = -204 each tick + SWIMMING(-80), + TALENT_DASH(-300), // -1500 per second, 5Hz = -300 each tick + TALENT_DASH_START(-1000), + + // restore + POWERED_FLY(500), + POWERED_SKIFF(500), + RUN(500), + SKIFF(500), + STANDBY(500), + WALK(500); + + public final int amount; + + ConsumptionType(int amount) { + this.amount = amount; + } +} diff --git a/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java b/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java index e3de1dfab..410ab9724 100644 --- a/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java +++ b/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java @@ -1,24 +1,23 @@ -package emu.grasscutter.game.player; - -import lombok.NonNull; - -public abstract class BasePlayerDataManager { - protected transient Player player; - - public BasePlayerDataManager() { - } - - public BasePlayerDataManager(@NonNull Player player) { - this.player = player; - } - - public Player getPlayer() { - return this.player; - } - - public void setPlayer(Player player) { - if (this.player == null) { - this.player = player; - } - } -} +package emu.grasscutter.game.player; + +import lombok.NonNull; + +public abstract class BasePlayerDataManager { + protected transient Player player; + + public BasePlayerDataManager() {} + + public BasePlayerDataManager(@NonNull Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } + + public void setPlayer(Player player) { + if (this.player == null) { + this.player = player; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java b/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java index d3cbf9f90..cc877befd 100644 --- a/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java +++ b/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java @@ -1,22 +1,20 @@ -package emu.grasscutter.game.player; - -import lombok.NonNull; - -public abstract class BasePlayerManager { - protected transient final Player player; - - public BasePlayerManager(@NonNull Player player) { - this.player = player; - } - - public Player getPlayer() { - return this.player; - } - - /** - * Saves the player to the database - */ - public void save() { - getPlayer().save(); - } -} +package emu.grasscutter.game.player; + +import lombok.NonNull; + +public abstract class BasePlayerManager { + protected final transient Player player; + + public BasePlayerManager(@NonNull Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } + + /** Saves the player to the database */ + public void save() { + getPlayer().save(); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/InvokeHandler.java b/src/main/java/emu/grasscutter/game/player/InvokeHandler.java index aeaefc211..898e9e200 100644 --- a/src/main/java/emu/grasscutter/game/player/InvokeHandler.java +++ b/src/main/java/emu/grasscutter/game/player/InvokeHandler.java @@ -1,61 +1,64 @@ -package emu.grasscutter.game.player; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.ForwardTypeOuterClass.ForwardType; - -import java.util.ArrayList; -import java.util.List; - -public class InvokeHandler { - private final List entryListForwardAll; - private final List entryListForwardAllExceptCur; - private final List entryListForwardHost; - private final Class packetClass; - - public InvokeHandler(Class packetClass) { - this.entryListForwardAll = new ArrayList<>(); - this.entryListForwardAllExceptCur = new ArrayList<>(); - this.entryListForwardHost = new ArrayList<>(); - this.packetClass = packetClass; - } - - public synchronized void addEntry(ForwardType forward, T entry) { - switch (forward) { - case FORWARD_TYPE_TO_ALL -> entryListForwardAll.add(entry); - case FORWARD_TYPE_TO_ALL_EXCEPT_CUR, FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR -> - entryListForwardAllExceptCur.add(entry); - case FORWARD_TYPE_TO_HOST -> entryListForwardHost.add(entry); - default -> { - } - } - } - - public synchronized void update(Player player) { - if (player.getWorld() == null || player.getScene() == null) { - this.entryListForwardAll.clear(); - this.entryListForwardAllExceptCur.clear(); - this.entryListForwardHost.clear(); - return; - } - - try { - if (entryListForwardAll.size() > 0) { - BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAll); - player.getScene().broadcastPacket(packet); - this.entryListForwardAll.clear(); - } - if (entryListForwardAllExceptCur.size() > 0) { - BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAllExceptCur); - player.getScene().broadcastPacketToOthers(player, packet); - this.entryListForwardAllExceptCur.clear(); - } - if (entryListForwardHost.size() > 0) { - BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardHost); - player.getWorld().getHost().sendPacket(packet); - this.entryListForwardHost.clear(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} +package emu.grasscutter.game.player; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.proto.ForwardTypeOuterClass.ForwardType; +import java.util.ArrayList; +import java.util.List; + +public class InvokeHandler { + private final List entryListForwardAll; + private final List entryListForwardAllExceptCur; + private final List entryListForwardHost; + private final Class packetClass; + + public InvokeHandler(Class packetClass) { + this.entryListForwardAll = new ArrayList<>(); + this.entryListForwardAllExceptCur = new ArrayList<>(); + this.entryListForwardHost = new ArrayList<>(); + this.packetClass = packetClass; + } + + public synchronized void addEntry(ForwardType forward, T entry) { + switch (forward) { + case FORWARD_TYPE_TO_ALL -> entryListForwardAll.add(entry); + case FORWARD_TYPE_TO_ALL_EXCEPT_CUR, + FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR -> entryListForwardAllExceptCur.add(entry); + case FORWARD_TYPE_TO_HOST -> entryListForwardHost.add(entry); + default -> {} + } + } + + public synchronized void update(Player player) { + if (player.getWorld() == null || player.getScene() == null) { + this.entryListForwardAll.clear(); + this.entryListForwardAllExceptCur.clear(); + this.entryListForwardHost.clear(); + return; + } + + try { + if (entryListForwardAll.size() > 0) { + BasePacket packet = + packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAll); + player.getScene().broadcastPacket(packet); + this.entryListForwardAll.clear(); + } + if (entryListForwardAllExceptCur.size() > 0) { + BasePacket packet = + packetClass + .getDeclaredConstructor(List.class) + .newInstance(this.entryListForwardAllExceptCur); + player.getScene().broadcastPacketToOthers(player, packet); + this.entryListForwardAllExceptCur.clear(); + } + if (entryListForwardHost.size() > 0) { + BasePacket packet = + packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardHost); + player.getWorld().getHost().sendPacket(packet); + this.entryListForwardHost.clear(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/player/PlayerBirthday.java b/src/main/java/emu/grasscutter/game/player/PlayerBirthday.java index b9756f4d9..c7f42e771 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerBirthday.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerBirthday.java @@ -1,69 +1,64 @@ -package emu.grasscutter.game.player; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday; - -@Entity -public class PlayerBirthday { - private int day; - private int month; - - public PlayerBirthday() { - this.day = 0; - this.month = 0; - } - - public PlayerBirthday(int day, int month) { - this.day = day; - this.month = month; - } - - public PlayerBirthday set(PlayerBirthday birth) { - this.day = birth.day; - this.month = birth.month; - - return this; - } - - public PlayerBirthday set(int d, int m) { - this.day = d; - this.month = m; - - return this; - } - - public int getDay() { - return this.day; - } - - public PlayerBirthday setDay(int value) { - this.day = value; - return this; - } - - public int getMonth() { - return this.month; - } - - public PlayerBirthday setMonth(int value) { - this.month = value; - return this; - } - - public Birthday toProto() { - return Birthday.newBuilder() - .setDay(this.getDay()) - .setMonth(this.getMonth()) - .build(); - } - - public Birthday.Builder getFilledProtoWhenNotEmpty() { - if (this.getDay() > 0) { - return Birthday.newBuilder() - .setDay(this.getDay()) - .setMonth(this.getMonth()); - } - - return Birthday.newBuilder(); - } -} +package emu.grasscutter.game.player; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday; + +@Entity +public class PlayerBirthday { + private int day; + private int month; + + public PlayerBirthday() { + this.day = 0; + this.month = 0; + } + + public PlayerBirthday(int day, int month) { + this.day = day; + this.month = month; + } + + public PlayerBirthday set(PlayerBirthday birth) { + this.day = birth.day; + this.month = birth.month; + + return this; + } + + public PlayerBirthday set(int d, int m) { + this.day = d; + this.month = m; + + return this; + } + + public int getDay() { + return this.day; + } + + public PlayerBirthday setDay(int value) { + this.day = value; + return this; + } + + public int getMonth() { + return this.month; + } + + public PlayerBirthday setMonth(int value) { + this.month = value; + return this; + } + + public Birthday toProto() { + return Birthday.newBuilder().setDay(this.getDay()).setMonth(this.getMonth()).build(); + } + + public Birthday.Builder getFilledProtoWhenNotEmpty() { + if (this.getDay() > 0) { + return Birthday.newBuilder().setDay(this.getDay()).setMonth(this.getMonth()); + } + + return Birthday.newBuilder(); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java b/src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java index f5af4edcc..9761d3f31 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java @@ -1,214 +1,224 @@ -package emu.grasscutter.game.player; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; -import emu.grasscutter.data.excels.BuffData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType; -import emu.grasscutter.net.proto.ServerBuffOuterClass.ServerBuff; -import emu.grasscutter.server.packet.send.PacketServerBuffChangeNotify; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -public class PlayerBuffManager extends BasePlayerManager { - private final List pendingBuffs; - private final Int2ObjectMap buffs; // Server buffs - private int nextBuffUid; - - public PlayerBuffManager(Player player) { - super(player); - this.buffs = new Int2ObjectOpenHashMap<>(); - this.pendingBuffs = new ArrayList<>(); - } - - /** - * Gets a new uid for a server buff - * - * @return New integer buff uid - */ - private int getNextBuffUid() { - return ++nextBuffUid; - } - - /** - * Returns true if the player has a buff with this group id - * - * @param groupId Buff group id - * @return True if a buff with this group id exists - */ - public synchronized boolean hasBuff(int groupId) { - return this.buffs.containsKey(groupId); - } - - /** - * Clears all player buffs - */ - public synchronized void clearBuffs() { - // Remove from player - getPlayer().sendPacket( - new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.buffs.values()) - ); - - // Clear - this.buffs.clear(); - } - - /** - * Adds a server buff to the player. - * - * @param buffId Server buff id - * @return True if a buff was added - */ - public boolean addBuff(int buffId) { - return addBuff(buffId, -1f); - } - - /** - * Adds a server buff to the player. - * - * @param buffId Server buff id - * @param duration Duration of the buff in seconds. Set to 0 for an infinite buff. - * @return True if a buff was added - */ - public synchronized boolean addBuff(int buffId, float duration) { - return addBuff(buffId, duration, null); - } - - /** - * Adds a server buff to the player. - * - * @param buffId Server buff id - * @param duration Duration of the buff in seconds. Set to 0 for an infinite buff. - * @param target Target avatar - * @return True if a buff was added - */ - public synchronized boolean addBuff(int buffId, float duration, Avatar target) { - // Get buff excel data - BuffData buffData = GameData.getBuffDataMap().get(buffId); - if (buffData == null) return false; - - boolean success = false; - - // Perform onAdded actions - success |= Optional.ofNullable(GameData.getAbilityData(buffData.getAbilityName())) - .map(data -> data.modifiers.get(buffData.getModifierName())) - .map(modifier -> modifier.onAdded) - .map(onAdded -> { - - var s = false; - for (var a : onAdded) { - Grasscutter.getLogger().debug("onAdded exists"); - if (Objects.requireNonNull(a.type) == AbilityModifierAction.Type.HealHP) { - Grasscutter.getLogger().debug("Attempting heal"); - if (target == null) continue; - var maxHp = target.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - var amount = a.amount.get() + a.amountByTargetMaxHPRatio.get() * maxHp; - target.getAsEntity().heal(amount); - s = true; - Grasscutter.getLogger().debug("Healed {}", amount); - } - } - return s; - }) - .orElse(false); - Grasscutter.getLogger().debug("Oh no"); - - // Set duration - if (duration < 0f) { - duration = buffData.getTime(); - } - - // Dont add buff if duration is equal or less than 0 - if (duration <= 0) { - return success; - } - - // Clear previous buff if it exists - this.removeBuff(buffData.getGroupId()); - - // Create and store buff - PlayerBuff buff = new PlayerBuff(getNextBuffUid(), buffData, duration); - this.buffs.put(buff.getGroupId(), buff); - - // Packet - getPlayer().sendPacket(new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_ADD_SERVER_BUFF, buff)); - - return true; - } - - /** - * Removes a buff by its group id - * - * @param buffGroupId Server buff group id - * @return True if a buff was remove - */ - public synchronized boolean removeBuff(int buffGroupId) { - PlayerBuff buff = this.buffs.remove(buffGroupId); - - if (buff != null) { - getPlayer().sendPacket( - new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, buff) - ); - return true; - } - - return false; - } - - public synchronized void onTick() { - // Skip if no buffs - if (this.buffs.isEmpty()) return; - - long currentTime = System.currentTimeMillis(); - - // Add to pending buffs to remove if buff has expired - this.buffs.values().removeIf(buff -> { - if (currentTime <= buff.getEndTime()) - return false; - this.pendingBuffs.add(buff); - return true; - }); - - if (this.pendingBuffs.size() > 0) { - // Send packet - getPlayer().sendPacket( - new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.pendingBuffs) - ); - this.pendingBuffs.clear(); - } - } - - @Getter - public static class PlayerBuff { - private final int uid; - private final BuffData buffData; - private final long endTime; - - public PlayerBuff(int uid, BuffData buffData, float duration) { - this.uid = uid; - this.buffData = buffData; - this.endTime = System.currentTimeMillis() + ((long) duration * 1000); - } - - public int getGroupId() { - return getBuffData().getGroupId(); - } - - public ServerBuff toProto() { - return ServerBuff.newBuilder() - .setServerBuffUid(this.getUid()) - .setServerBuffId(this.getBuffData().getId()) - .setServerBuffType(this.getBuffData().getServerBuffType().getValue()) - .setInstancedModifierId(1) - .build(); - } - } -} +package emu.grasscutter.game.player; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.data.excels.BuffData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType; +import emu.grasscutter.net.proto.ServerBuffOuterClass.ServerBuff; +import emu.grasscutter.server.packet.send.PacketServerBuffChangeNotify; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import lombok.Getter; + +public class PlayerBuffManager extends BasePlayerManager { + private final List pendingBuffs; + private final Int2ObjectMap buffs; // Server buffs + private int nextBuffUid; + + public PlayerBuffManager(Player player) { + super(player); + this.buffs = new Int2ObjectOpenHashMap<>(); + this.pendingBuffs = new ArrayList<>(); + } + + /** + * Gets a new uid for a server buff + * + * @return New integer buff uid + */ + private int getNextBuffUid() { + return ++nextBuffUid; + } + + /** + * Returns true if the player has a buff with this group id + * + * @param groupId Buff group id + * @return True if a buff with this group id exists + */ + public synchronized boolean hasBuff(int groupId) { + return this.buffs.containsKey(groupId); + } + + /** Clears all player buffs */ + public synchronized void clearBuffs() { + // Remove from player + getPlayer() + .sendPacket( + new PacketServerBuffChangeNotify( + getPlayer(), + ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, + this.buffs.values())); + + // Clear + this.buffs.clear(); + } + + /** + * Adds a server buff to the player. + * + * @param buffId Server buff id + * @return True if a buff was added + */ + public boolean addBuff(int buffId) { + return addBuff(buffId, -1f); + } + + /** + * Adds a server buff to the player. + * + * @param buffId Server buff id + * @param duration Duration of the buff in seconds. Set to 0 for an infinite buff. + * @return True if a buff was added + */ + public synchronized boolean addBuff(int buffId, float duration) { + return addBuff(buffId, duration, null); + } + + /** + * Adds a server buff to the player. + * + * @param buffId Server buff id + * @param duration Duration of the buff in seconds. Set to 0 for an infinite buff. + * @param target Target avatar + * @return True if a buff was added + */ + public synchronized boolean addBuff(int buffId, float duration, Avatar target) { + // Get buff excel data + BuffData buffData = GameData.getBuffDataMap().get(buffId); + if (buffData == null) return false; + + boolean success = false; + + // Perform onAdded actions + success |= + Optional.ofNullable(GameData.getAbilityData(buffData.getAbilityName())) + .map(data -> data.modifiers.get(buffData.getModifierName())) + .map(modifier -> modifier.onAdded) + .map( + onAdded -> { + var s = false; + for (var a : onAdded) { + Grasscutter.getLogger().debug("onAdded exists"); + if (Objects.requireNonNull(a.type) == AbilityModifierAction.Type.HealHP) { + Grasscutter.getLogger().debug("Attempting heal"); + if (target == null) continue; + var maxHp = target.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + var amount = a.amount.get() + a.amountByTargetMaxHPRatio.get() * maxHp; + target.getAsEntity().heal(amount); + s = true; + Grasscutter.getLogger().debug("Healed {}", amount); + } + } + return s; + }) + .orElse(false); + Grasscutter.getLogger().debug("Oh no"); + + // Set duration + if (duration < 0f) { + duration = buffData.getTime(); + } + + // Dont add buff if duration is equal or less than 0 + if (duration <= 0) { + return success; + } + + // Clear previous buff if it exists + this.removeBuff(buffData.getGroupId()); + + // Create and store buff + PlayerBuff buff = new PlayerBuff(getNextBuffUid(), buffData, duration); + this.buffs.put(buff.getGroupId(), buff); + + // Packet + getPlayer() + .sendPacket( + new PacketServerBuffChangeNotify( + getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_ADD_SERVER_BUFF, buff)); + + return true; + } + + /** + * Removes a buff by its group id + * + * @param buffGroupId Server buff group id + * @return True if a buff was remove + */ + public synchronized boolean removeBuff(int buffGroupId) { + PlayerBuff buff = this.buffs.remove(buffGroupId); + + if (buff != null) { + getPlayer() + .sendPacket( + new PacketServerBuffChangeNotify( + getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, buff)); + return true; + } + + return false; + } + + public synchronized void onTick() { + // Skip if no buffs + if (this.buffs.isEmpty()) return; + + long currentTime = System.currentTimeMillis(); + + // Add to pending buffs to remove if buff has expired + this.buffs + .values() + .removeIf( + buff -> { + if (currentTime <= buff.getEndTime()) return false; + this.pendingBuffs.add(buff); + return true; + }); + + if (this.pendingBuffs.size() > 0) { + // Send packet + getPlayer() + .sendPacket( + new PacketServerBuffChangeNotify( + getPlayer(), + ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, + this.pendingBuffs)); + this.pendingBuffs.clear(); + } + } + + @Getter + public static class PlayerBuff { + private final int uid; + private final BuffData buffData; + private final long endTime; + + public PlayerBuff(int uid, BuffData buffData, float duration) { + this.uid = uid; + this.buffData = buffData; + this.endTime = System.currentTimeMillis() + ((long) duration * 1000); + } + + public int getGroupId() { + return getBuffData().getGroupId(); + } + + public ServerBuff toProto() { + return ServerBuff.newBuilder() + .setServerBuffUid(this.getUid()) + .setServerBuffId(this.getBuffData().getId()) + .setServerBuffType(this.getBuffData().getServerBuffType().getValue()) + .setInstancedModifierId(1) + .build(); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/player/PlayerCodex.java b/src/main/java/emu/grasscutter/game/player/PlayerCodex.java index 242850498..b3ad08d1e 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerCodex.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerCodex.java @@ -1,141 +1,136 @@ -package emu.grasscutter.game.player; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.CodexAnimalData; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; -import lombok.Getter; -import lombok.val; - -import java.util.*; - -@Entity -public class PlayerCodex { - @Transient - private Player player; - - //itemId is not codexId! - @Getter - private final Set unlockedWeapon; - @Getter - private final Map unlockedAnimal; - @Getter - private final Set unlockedMaterial; - @Getter - private final Set unlockedBook; - @Getter - private final Set unlockedTip; - @Getter - private final Set unlockedView; - @Getter - private Set unlockedReliquary; - @Getter - private final Set unlockedReliquarySuitCodex; - - public PlayerCodex() { - this.unlockedWeapon = new HashSet<>(); - this.unlockedAnimal = new HashMap<>(); - this.unlockedMaterial = new HashSet<>(); - this.unlockedBook = new HashSet<>(); - this.unlockedTip = new HashSet<>(); - this.unlockedView = new HashSet<>(); - this.unlockedReliquary = new HashSet<>(); - this.unlockedReliquarySuitCodex = new HashSet<>(); - } - - public PlayerCodex(Player player) { - this(); - this.player = player; - } - - public void setPlayer(Player player) { - this.player = player; - this.fixReliquaries(); - } - - public void checkAddedItem(GameItem item) { - val itemData = item.getItemData(); - val itemId = item.getItemId(); - switch (itemData.getItemType()) { - case ITEM_WEAPON -> { - Optional.ofNullable(GameData.getCodexWeaponDataIdMap().get(itemId)) - .ifPresent(codexData -> { - if (this.getUnlockedWeapon().add(itemId)) { - this.player.save(); - this.player.sendPacket(new PacketCodexDataUpdateNotify(2, codexData.getId())); - } - }); - } - case ITEM_MATERIAL -> { - switch (itemData.getMaterialType()) { - // Is this check even needed? - case MATERIAL_FOOD, MATERIAL_WIDGET, MATERIAL_EXCHANGE, MATERIAL_AVATAR_MATERIAL, MATERIAL_NOTICE_ADD_HP -> { - Optional.ofNullable(GameData.getCodexMaterialDataIdMap().get(itemId)) - .ifPresent(codexData -> { - if (this.getUnlockedMaterial().add(itemId)) { - this.player.save(); - this.player.sendPacket(new PacketCodexDataUpdateNotify(4, codexData.getId())); - } - }); - } - default -> { - } - } - } - case ITEM_RELIQUARY -> { - val reliquaryId = (itemId / 10) * 10; // Normalize to 0-substat form - if (this.getUnlockedReliquary().add(reliquaryId)) - checkUnlockedSuits(reliquaryId); - } - default -> { - } - } - } - - public void checkAnimal(GameEntity target, CodexAnimalData.CountType countType) { - if (target instanceof EntityMonster) { - val monsterId = ((EntityMonster) target).getMonsterData().getId(); - val codexAnimal = GameData.getCodexAnimalDataMap().get(monsterId); - if (codexAnimal == null) return; - - val animalCountType = codexAnimal.getCountType(); - if (animalCountType != countType && animalCountType != null) return; - - this.getUnlockedAnimal().merge(monsterId, 1, (i, j) -> i + 1); - - player.save(); - this.player.sendPacket(new PacketCodexDataUpdateNotify(3, monsterId)); - } - } - - public void checkUnlockedSuits(int reliquaryId) { - GameData.getCodexReliquaryArrayList().stream() - .filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId())) - .filter(x -> x.containsId(reliquaryId)) - .filter(x -> this.getUnlockedReliquary().containsAll(x.getIds())) - .forEach(x -> { - int id = x.getId(); - this.getUnlockedReliquarySuitCodex().add(id); - this.player.save(); - this.player.sendPacket(new PacketCodexDataUpdateNotify(8, id)); - }); - } - - @Deprecated // Maybe remove this if we ever stop caring about older dbs - private void fixReliquaries() { - // Migrate older database entries which were using non-canonical forms of itemIds - val newReliquaries = new HashSet(); - this.unlockedReliquary.forEach(i -> newReliquaries.add((i / 10) * 10)); - this.unlockedReliquary = newReliquaries; - - GameData.getCodexReliquaryArrayList().stream() - .filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId())) - .filter(x -> this.getUnlockedReliquary().containsAll(x.getIds())) - .forEach(x -> this.getUnlockedReliquarySuitCodex().add(x.getId())); - this.player.save(); - } -} +package emu.grasscutter.game.player; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.CodexAnimalData; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; +import java.util.*; +import lombok.Getter; +import lombok.val; + +@Entity +public class PlayerCodex { + @Transient private Player player; + + // itemId is not codexId! + @Getter private final Set unlockedWeapon; + @Getter private final Map unlockedAnimal; + @Getter private final Set unlockedMaterial; + @Getter private final Set unlockedBook; + @Getter private final Set unlockedTip; + @Getter private final Set unlockedView; + @Getter private Set unlockedReliquary; + @Getter private final Set unlockedReliquarySuitCodex; + + public PlayerCodex() { + this.unlockedWeapon = new HashSet<>(); + this.unlockedAnimal = new HashMap<>(); + this.unlockedMaterial = new HashSet<>(); + this.unlockedBook = new HashSet<>(); + this.unlockedTip = new HashSet<>(); + this.unlockedView = new HashSet<>(); + this.unlockedReliquary = new HashSet<>(); + this.unlockedReliquarySuitCodex = new HashSet<>(); + } + + public PlayerCodex(Player player) { + this(); + this.player = player; + } + + public void setPlayer(Player player) { + this.player = player; + this.fixReliquaries(); + } + + public void checkAddedItem(GameItem item) { + val itemData = item.getItemData(); + val itemId = item.getItemId(); + switch (itemData.getItemType()) { + case ITEM_WEAPON -> { + Optional.ofNullable(GameData.getCodexWeaponDataIdMap().get(itemId)) + .ifPresent( + codexData -> { + if (this.getUnlockedWeapon().add(itemId)) { + this.player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(2, codexData.getId())); + } + }); + } + case ITEM_MATERIAL -> { + switch (itemData.getMaterialType()) { + // Is this check even needed? + case MATERIAL_FOOD, + MATERIAL_WIDGET, + MATERIAL_EXCHANGE, + MATERIAL_AVATAR_MATERIAL, + MATERIAL_NOTICE_ADD_HP -> { + Optional.ofNullable(GameData.getCodexMaterialDataIdMap().get(itemId)) + .ifPresent( + codexData -> { + if (this.getUnlockedMaterial().add(itemId)) { + this.player.save(); + this.player.sendPacket( + new PacketCodexDataUpdateNotify(4, codexData.getId())); + } + }); + } + default -> {} + } + } + case ITEM_RELIQUARY -> { + val reliquaryId = (itemId / 10) * 10; // Normalize to 0-substat form + if (this.getUnlockedReliquary().add(reliquaryId)) checkUnlockedSuits(reliquaryId); + } + default -> {} + } + } + + public void checkAnimal(GameEntity target, CodexAnimalData.CountType countType) { + if (target instanceof EntityMonster) { + val monsterId = ((EntityMonster) target).getMonsterData().getId(); + val codexAnimal = GameData.getCodexAnimalDataMap().get(monsterId); + if (codexAnimal == null) return; + + val animalCountType = codexAnimal.getCountType(); + if (animalCountType != countType && animalCountType != null) return; + + this.getUnlockedAnimal().merge(monsterId, 1, (i, j) -> i + 1); + + player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(3, monsterId)); + } + } + + public void checkUnlockedSuits(int reliquaryId) { + GameData.getCodexReliquaryArrayList().stream() + .filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId())) + .filter(x -> x.containsId(reliquaryId)) + .filter(x -> this.getUnlockedReliquary().containsAll(x.getIds())) + .forEach( + x -> { + int id = x.getId(); + this.getUnlockedReliquarySuitCodex().add(id); + this.player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(8, id)); + }); + } + + @Deprecated // Maybe remove this if we ever stop caring about older dbs + private void fixReliquaries() { + // Migrate older database entries which were using non-canonical forms of itemIds + val newReliquaries = new HashSet(); + this.unlockedReliquary.forEach(i -> newReliquaries.add((i / 10) * 10)); + this.unlockedReliquary = newReliquaries; + + GameData.getCodexReliquaryArrayList().stream() + .filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId())) + .filter(x -> this.getUnlockedReliquary().containsAll(x.getIds())) + .forEach(x -> this.getUnlockedReliquarySuitCodex().add(x.getId())); + this.player.save(); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/PlayerCollectionRecords.java b/src/main/java/emu/grasscutter/game/player/PlayerCollectionRecords.java index a9e22e0ab..e2bc5a796 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerCollectionRecords.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerCollectionRecords.java @@ -1,68 +1,68 @@ -package emu.grasscutter.game.player; - -import dev.morphia.annotations.Entity; - -import java.util.HashMap; -import java.util.Map; - -@Entity(useDiscriminator = false) -public class PlayerCollectionRecords { - private Map records; - - private Map getRecords() { - if (records == null) { - records = new HashMap<>(); - } - return records; - } - - public void addRecord(int configId, long expiredMillisecond) { - Map records; - synchronized (records = getRecords()) { - records.put(configId, new CollectionRecord(configId, expiredMillisecond + System.currentTimeMillis())); - } - } - - public boolean findRecord(int configId) { - Map records; - synchronized (records = getRecords()) { - CollectionRecord record = records.get(configId); - - if (record == null) { - return false; - } - - boolean expired = record.getExpiredTime() < System.currentTimeMillis(); - - if (expired) { - records.remove(configId); - return false; - } - - return true; - } - } - - @Entity - public static class CollectionRecord { - private int configId; - private long expiredTime; - - @Deprecated // Morphia - public CollectionRecord() { - } - - public CollectionRecord(int configId, long expiredTime) { - this.configId = configId; - this.expiredTime = expiredTime; - } - - public int getConfigId() { - return configId; - } - - public long getExpiredTime() { - return expiredTime; - } - } -} +package emu.grasscutter.game.player; + +import dev.morphia.annotations.Entity; +import java.util.HashMap; +import java.util.Map; + +@Entity(useDiscriminator = false) +public class PlayerCollectionRecords { + private Map records; + + private Map getRecords() { + if (records == null) { + records = new HashMap<>(); + } + return records; + } + + public void addRecord(int configId, long expiredMillisecond) { + Map records; + synchronized (records = getRecords()) { + records.put( + configId, + new CollectionRecord(configId, expiredMillisecond + System.currentTimeMillis())); + } + } + + public boolean findRecord(int configId) { + Map records; + synchronized (records = getRecords()) { + CollectionRecord record = records.get(configId); + + if (record == null) { + return false; + } + + boolean expired = record.getExpiredTime() < System.currentTimeMillis(); + + if (expired) { + records.remove(configId); + return false; + } + + return true; + } + } + + @Entity + public static class CollectionRecord { + private int configId; + private long expiredTime; + + @Deprecated // Morphia + public CollectionRecord() {} + + public CollectionRecord(int configId, long expiredTime) { + this.configId = configId; + this.expiredTime = expiredTime; + } + + public int getConfigId() { + return configId; + } + + public long getExpiredTime() { + return expiredTime; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java index 4a853af8a..2fa7f29ba 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java @@ -1,219 +1,239 @@ -package emu.grasscutter.game.player; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ScenePointEntry; -import emu.grasscutter.data.excels.OpenStateData; -import emu.grasscutter.data.excels.OpenStateData.OpenStateCondType; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.packet.send.*; - -import java.util.Set; -import java.util.stream.Collectors; - -// @Entity -public class PlayerProgressManager extends BasePlayerDataManager { - /****************************************************************************************************************** - ****************************************************************************************************************** - * OPEN STATES - ****************************************************************************************************************** - *****************************************************************************************************************/ - - // Set of open states that are never unlocked, whether they fulfill the conditions or not. - public static final Set BLACKLIST_OPEN_STATES = Set.of( - 48 // blacklist OPEN_STATE_LIMIT_REGION_GLOBAL to make Meledy happy. =D Remove this as soon as quest unlocks are fully implemented. - ); - // Set of open states that are set per default for all accounts. Can be overwritten by an entry in `map`. - public static final Set DEFAULT_OPEN_STATES = GameData.getOpenStateList().stream() - .filter(s -> - s.isDefaultState() // Actual default-opened states. - // All states whose unlock we don't handle correctly yet. - || (s.getCond().stream().filter(c -> c.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL).count() == 0) - // Always unlock OPEN_STATE_PAIMON, otherwise the player will not have a working chat. - || s.getId() == 1 - ) - .filter(s -> !BLACKLIST_OPEN_STATES.contains(s.getId())) // Filter out states in the blacklist. - .map(s -> s.getId()) - .collect(Collectors.toSet()); - - public PlayerProgressManager(Player player) { - super(player); - } - - /********** - Handler for player login. - **********/ - public void onPlayerLogin() { - // Try unlocking open states on player login. This handles accounts where unlock conditions were - // already met before certain open state unlocks were implemented. - this.tryUnlockOpenStates(false); - - // Send notify to the client. - player.getSession().send(new PacketOpenStateUpdateNotify(this.player)); - - // Add statue quests if necessary. - this.addStatueQuestsOnLogin(); - - // Auto-unlock the first statue and map area, until we figure out how to make - // that particular statue interactable. - this.player.getUnlockedScenePoints(3).add(7); - this.player.getUnlockedSceneAreas(3).add(1); - - } - - /********** - Direct getters and setters for open states. - **********/ - public int getOpenState(int openState) { - return this.player.getOpenStates().getOrDefault(openState, 0); - } - - private void setOpenState(int openState, int value, boolean sendNotify) { - int previousValue = this.player.getOpenStates().getOrDefault(openState, 0); - - if (value != previousValue) { - this.player.getOpenStates().put(openState, value); - - if (sendNotify) { - player.getSession().send(new PacketOpenStateChangeNotify(openState, value)); - } - } - } - - private void setOpenState(int openState, int value) { - this.setOpenState(openState, value, true); - } - - /********** - Condition checking for setting open states. - **********/ - private boolean areConditionsMet(OpenStateData openState) { - // Check all conditions and test if at least one of them is violated. - for (var condition : openState.getCond()) { - // For level conditions, check if the player has reached the necessary level. - if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL) { - if (this.player.getLevel() < condition.getParam()) { - return false; - } - } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_QUEST) { - // ToDo: Implement. - } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PARENT_QUEST) { - // ToDo: Implement. - } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_OFFERING_LEVEL) { - // ToDo: Implement. - } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_CITY_REPUTATION_LEVEL) { - // ToDo: Implement. - } - } - - // Done. If we didn't find any violations, all conditions are met. - return true; - } - - /********** - Setting open states from the client (via `SetOpenStateReq`). - **********/ - public void setOpenStateFromClient(int openState, int value) { - // Get the data for this open state. - OpenStateData data = GameData.getOpenStateDataMap().get(openState); - if (data == null) { - this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL)); - return; - } - - // Make sure that this is an open state that the client is allowed to set, - // and that it doesn't have any further conditions attached. - if (!data.isAllowClientOpen() || !this.areConditionsMet(data)) { - this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL)); - return; - } - - // Set. - this.setOpenState(openState, value); - this.player.sendPacket(new PacketSetOpenStateRsp(openState, value)); - } - - /********** - Triggered unlocking of open states (unlock states whose conditions have been met.) - **********/ - public void tryUnlockOpenStates(boolean sendNotify) { - // Get list of open states that are not yet unlocked. - var lockedStates = GameData.getOpenStateList().stream().filter(s -> this.player.getOpenStates().getOrDefault(s, 0) == 0).toList(); - - // Try unlocking all of them. - for (var state : lockedStates) { - // To auto-unlock a state, it has to meet three conditions: - // * it can not be a state that is unlocked by the client, - // * it has to meet all its unlock conditions, and - // * it can not be in the blacklist. - if (!state.isAllowClientOpen() && this.areConditionsMet(state) && !BLACKLIST_OPEN_STATES.contains(state.getId())) { - this.setOpenState(state.getId(), 1, sendNotify); - } - } - } - - public void tryUnlockOpenStates() { - this.tryUnlockOpenStates(true); - } - - /****************************************************************************************************************** - ****************************************************************************************************************** - * MAP AREAS AND POINTS - ****************************************************************************************************************** - *****************************************************************************************************************/ - private void addStatueQuestsOnLogin() { - // Get all currently existing subquests for the "unlock all statues" main quest. - var statueMainQuest = GameData.getMainQuestDataMap().get(303); - var statueSubQuests = statueMainQuest.getSubQuests(); - - // Add the main statue quest if it isn't active yet. - var statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303); - if (statueGameMainQuest == null) { - this.player.getQuestManager().addQuest(30302); - statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303); - } - - // Set all subquests to active if they aren't already finished. - for (var subData : statueSubQuests) { - var subGameQuest = statueGameMainQuest.getChildQuestById(subData.getSubId()); - if (subGameQuest != null && subGameQuest.getState() == QuestState.QUEST_STATE_UNSTARTED) { - this.player.getQuestManager().addQuest(subData.getSubId()); - } - } - } - - public boolean unlockTransPoint(int sceneId, int pointId, boolean isStatue) { - // Check whether the unlocked point exists and whether it is still locked. - ScenePointEntry scenePointEntry = GameData.getScenePointEntryById(sceneId, pointId); - - if (scenePointEntry == null || this.player.getUnlockedScenePoints(sceneId).contains(pointId)) { - return false; - } - - // Add the point to the list of unlocked points for its scene. - this.player.getUnlockedScenePoints(sceneId).add(pointId); - - // Give primogems and Adventure EXP for unlocking. - this.player.getInventory().addItem(201, 5, ActionReason.UnlockPointReward); - this.player.getInventory().addItem(102, isStatue ? 50 : 10, ActionReason.UnlockPointReward); - - // this.player.sendPacket(new PacketPlayerPropChangeReasonNotify(this.player.getProperty(PlayerProperty.PROP_PLAYER_EXP), PlayerProperty.PROP_PLAYER_EXP, PropChangeReason.PROP_CHANGE_REASON_PLAYER_ADD_EXP)); - - // Fire quest trigger for trans point unlock. - this.player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT, sceneId, pointId); - - // Send packet. - this.player.sendPacket(new PacketScenePointUnlockNotify(sceneId, pointId)); - return true; - } - - public void unlockSceneArea(int sceneId, int areaId) { - // Add the area to the list of unlocked areas in its scene. - this.player.getUnlockedSceneAreas(sceneId).add(areaId); - - // Send packet. - this.player.sendPacket(new PacketSceneAreaUnlockNotify(sceneId, areaId)); - } -} +package emu.grasscutter.game.player; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.data.excels.OpenStateData; +import emu.grasscutter.data.excels.OpenStateData.OpenStateCondType; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.packet.send.*; +import java.util.Set; +import java.util.stream.Collectors; + +// @Entity +public class PlayerProgressManager extends BasePlayerDataManager { + /****************************************************************************************************************** + ****************************************************************************************************************** + * OPEN STATES + ****************************************************************************************************************** + *****************************************************************************************************************/ + + // Set of open states that are never unlocked, whether they fulfill the conditions or not. + public static final Set BLACKLIST_OPEN_STATES = + Set.of( + 48 // blacklist OPEN_STATE_LIMIT_REGION_GLOBAL to make Meledy happy. =D Remove this as + // soon as quest unlocks are fully implemented. + ); + // Set of open states that are set per default for all accounts. Can be overwritten by an entry in + // `map`. + public static final Set DEFAULT_OPEN_STATES = + GameData.getOpenStateList().stream() + .filter( + s -> + s.isDefaultState() // Actual default-opened states. + // All states whose unlock we don't handle correctly yet. + || (s.getCond().stream() + .filter( + c -> + c.getCondType() + == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL) + .count() + == 0) + // Always unlock OPEN_STATE_PAIMON, otherwise the player will not have a + // working chat. + || s.getId() == 1) + .filter( + s -> + !BLACKLIST_OPEN_STATES.contains(s.getId())) // Filter out states in the blacklist. + .map(s -> s.getId()) + .collect(Collectors.toSet()); + + public PlayerProgressManager(Player player) { + super(player); + } + + /********** + * Handler for player login. + **********/ + public void onPlayerLogin() { + // Try unlocking open states on player login. This handles accounts where unlock conditions were + // already met before certain open state unlocks were implemented. + this.tryUnlockOpenStates(false); + + // Send notify to the client. + player.getSession().send(new PacketOpenStateUpdateNotify(this.player)); + + // Add statue quests if necessary. + this.addStatueQuestsOnLogin(); + + // Auto-unlock the first statue and map area, until we figure out how to make + // that particular statue interactable. + this.player.getUnlockedScenePoints(3).add(7); + this.player.getUnlockedSceneAreas(3).add(1); + } + + /********** + * Direct getters and setters for open states. + **********/ + public int getOpenState(int openState) { + return this.player.getOpenStates().getOrDefault(openState, 0); + } + + private void setOpenState(int openState, int value, boolean sendNotify) { + int previousValue = this.player.getOpenStates().getOrDefault(openState, 0); + + if (value != previousValue) { + this.player.getOpenStates().put(openState, value); + + if (sendNotify) { + player.getSession().send(new PacketOpenStateChangeNotify(openState, value)); + } + } + } + + private void setOpenState(int openState, int value) { + this.setOpenState(openState, value, true); + } + + /********** + * Condition checking for setting open states. + **********/ + private boolean areConditionsMet(OpenStateData openState) { + // Check all conditions and test if at least one of them is violated. + for (var condition : openState.getCond()) { + // For level conditions, check if the player has reached the necessary level. + if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL) { + if (this.player.getLevel() < condition.getParam()) { + return false; + } + } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_QUEST) { + // ToDo: Implement. + } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_COND_PARENT_QUEST) { + // ToDo: Implement. + } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_OFFERING_LEVEL) { + // ToDo: Implement. + } else if (condition.getCondType() == OpenStateCondType.OPEN_STATE_CITY_REPUTATION_LEVEL) { + // ToDo: Implement. + } + } + + // Done. If we didn't find any violations, all conditions are met. + return true; + } + + /********** + * Setting open states from the client (via `SetOpenStateReq`). + **********/ + public void setOpenStateFromClient(int openState, int value) { + // Get the data for this open state. + OpenStateData data = GameData.getOpenStateDataMap().get(openState); + if (data == null) { + this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL)); + return; + } + + // Make sure that this is an open state that the client is allowed to set, + // and that it doesn't have any further conditions attached. + if (!data.isAllowClientOpen() || !this.areConditionsMet(data)) { + this.player.sendPacket(new PacketSetOpenStateRsp(Retcode.RET_FAIL)); + return; + } + + // Set. + this.setOpenState(openState, value); + this.player.sendPacket(new PacketSetOpenStateRsp(openState, value)); + } + + /********** + * Triggered unlocking of open states (unlock states whose conditions have been met.) + **********/ + public void tryUnlockOpenStates(boolean sendNotify) { + // Get list of open states that are not yet unlocked. + var lockedStates = + GameData.getOpenStateList().stream() + .filter(s -> this.player.getOpenStates().getOrDefault(s, 0) == 0) + .toList(); + + // Try unlocking all of them. + for (var state : lockedStates) { + // To auto-unlock a state, it has to meet three conditions: + // * it can not be a state that is unlocked by the client, + // * it has to meet all its unlock conditions, and + // * it can not be in the blacklist. + if (!state.isAllowClientOpen() + && this.areConditionsMet(state) + && !BLACKLIST_OPEN_STATES.contains(state.getId())) { + this.setOpenState(state.getId(), 1, sendNotify); + } + } + } + + public void tryUnlockOpenStates() { + this.tryUnlockOpenStates(true); + } + + /****************************************************************************************************************** + ****************************************************************************************************************** + * MAP AREAS AND POINTS + ****************************************************************************************************************** + *****************************************************************************************************************/ + private void addStatueQuestsOnLogin() { + // Get all currently existing subquests for the "unlock all statues" main quest. + var statueMainQuest = GameData.getMainQuestDataMap().get(303); + var statueSubQuests = statueMainQuest.getSubQuests(); + + // Add the main statue quest if it isn't active yet. + var statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303); + if (statueGameMainQuest == null) { + this.player.getQuestManager().addQuest(30302); + statueGameMainQuest = this.player.getQuestManager().getMainQuestById(303); + } + + // Set all subquests to active if they aren't already finished. + for (var subData : statueSubQuests) { + var subGameQuest = statueGameMainQuest.getChildQuestById(subData.getSubId()); + if (subGameQuest != null && subGameQuest.getState() == QuestState.QUEST_STATE_UNSTARTED) { + this.player.getQuestManager().addQuest(subData.getSubId()); + } + } + } + + public boolean unlockTransPoint(int sceneId, int pointId, boolean isStatue) { + // Check whether the unlocked point exists and whether it is still locked. + ScenePointEntry scenePointEntry = GameData.getScenePointEntryById(sceneId, pointId); + + if (scenePointEntry == null || this.player.getUnlockedScenePoints(sceneId).contains(pointId)) { + return false; + } + + // Add the point to the list of unlocked points for its scene. + this.player.getUnlockedScenePoints(sceneId).add(pointId); + + // Give primogems and Adventure EXP for unlocking. + this.player.getInventory().addItem(201, 5, ActionReason.UnlockPointReward); + this.player.getInventory().addItem(102, isStatue ? 50 : 10, ActionReason.UnlockPointReward); + + // this.player.sendPacket(new + // PacketPlayerPropChangeReasonNotify(this.player.getProperty(PlayerProperty.PROP_PLAYER_EXP), + // PlayerProperty.PROP_PLAYER_EXP, PropChangeReason.PROP_CHANGE_REASON_PLAYER_ADD_EXP)); + + // Fire quest trigger for trans point unlock. + this.player + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT, sceneId, pointId); + + // Send packet. + this.player.sendPacket(new PacketScenePointUnlockNotify(sceneId, pointId)); + return true; + } + + public void unlockSceneArea(int sceneId, int areaId) { + // Add the area to the list of unlocked areas in its scene. + this.player.getUnlockedSceneAreas(sceneId).add(areaId); + + // Send packet. + this.player.sendPacket(new PacketSceneAreaUnlockNotify(sceneId, areaId)); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/TeamInfo.java b/src/main/java/emu/grasscutter/game/player/TeamInfo.java index 3b39f560a..0edd3899a 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamInfo.java +++ b/src/main/java/emu/grasscutter/game/player/TeamInfo.java @@ -1,97 +1,95 @@ -package emu.grasscutter.game.player; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam; - -import java.util.ArrayList; -import java.util.List; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -@Entity -public class TeamInfo { - private String name; - private final List avatars; - - public TeamInfo() { - this.name = ""; - this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam); - } - - public TeamInfo(List avatars) { - this.name = ""; - this.avatars = avatars; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getAvatars() { - return avatars; - } - - public int size() { - return avatars.size(); - } - - public boolean contains(Avatar avatar) { - return getAvatars().contains(avatar.getAvatarId()); - } - - public boolean addAvatar(Avatar avatar) { - if (contains(avatar)) { - return false; - } - - getAvatars().add(avatar.getAvatarId()); - - return true; - } - - public boolean removeAvatar(int slot) { - if (size() <= 1) { - return false; - } - - getAvatars().remove(slot); - - return true; - } - - public void copyFrom(TeamInfo team) { - copyFrom(team, GAME_OPTIONS.avatarLimits.singlePlayerTeam); - } - - public void copyFrom(TeamInfo team, int maxTeamSize) { - // Clone avatar ids from team to copy from - List avatarIds = new ArrayList<>(team.getAvatars()); - - // Clear current avatar list first - this.getAvatars().clear(); - - // Copy from team - int len = Math.min(avatarIds.size(), maxTeamSize); - for (int i = 0; i < len; i++) { - int id = avatarIds.get(i); - this.getAvatars().add(id); - } - } - - public AvatarTeam toProto(Player player) { - AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder() - .setTeamName(this.getName()); - - for (int i = 0; i < this.getAvatars().size(); i++) { - Avatar avatar = player.getAvatars().getAvatarById(this.getAvatars().get(i)); - avatarTeam.addAvatarGuidList(avatar.getGuid()); - } - - return avatarTeam.build(); - } -} +package emu.grasscutter.game.player; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam; +import java.util.ArrayList; +import java.util.List; + +@Entity +public class TeamInfo { + private String name; + private final List avatars; + + public TeamInfo() { + this.name = ""; + this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam); + } + + public TeamInfo(List avatars) { + this.name = ""; + this.avatars = avatars; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getAvatars() { + return avatars; + } + + public int size() { + return avatars.size(); + } + + public boolean contains(Avatar avatar) { + return getAvatars().contains(avatar.getAvatarId()); + } + + public boolean addAvatar(Avatar avatar) { + if (contains(avatar)) { + return false; + } + + getAvatars().add(avatar.getAvatarId()); + + return true; + } + + public boolean removeAvatar(int slot) { + if (size() <= 1) { + return false; + } + + getAvatars().remove(slot); + + return true; + } + + public void copyFrom(TeamInfo team) { + copyFrom(team, GAME_OPTIONS.avatarLimits.singlePlayerTeam); + } + + public void copyFrom(TeamInfo team, int maxTeamSize) { + // Clone avatar ids from team to copy from + List avatarIds = new ArrayList<>(team.getAvatars()); + + // Clear current avatar list first + this.getAvatars().clear(); + + // Copy from team + int len = Math.min(avatarIds.size(), maxTeamSize); + for (int i = 0; i < len; i++) { + int id = avatarIds.get(i); + this.getAvatars().add(id); + } + } + + public AvatarTeam toProto(Player player) { + AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder().setTeamName(this.getName()); + + for (int i = 0; i < this.getAvatars().size(); i++) { + Avatar avatar = player.getAvatars().getAvatarById(this.getAvatars().get(i)); + avatarTeam.addAvatarGuidList(avatar.getGuid()); + } + + return avatarTeam.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index fe559571e..e3d7139ca 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -1,706 +1,728 @@ -package emu.grasscutter.game.player; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.GameConstants; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.EntityBaseGadget; -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.game.props.EnterReason; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; -import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.event.player.PlayerTeamDeathEvent; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.Utils; -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.Object2IntOpenHashMap; -import lombok.Getter; -import lombok.Setter; - -import java.util.*; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -@Entity -public class TeamManager extends BasePlayerDataManager { - @Transient - private final List avatars; - @Transient - @Getter - private final Set gadgets; - @Transient - @Getter - private final IntSet teamResonances; - @Transient - @Getter - private final IntSet teamResonancesConfig; - // This needs to be a LinkedHashMap to guarantee insertion order. - @Getter - private LinkedHashMap teams; - private int currentTeamIndex; - @Getter - @Setter - private int currentCharacterIndex; - @Transient - @Getter - @Setter - private TeamInfo mpTeam; - @Transient - @Getter - @Setter - private int entityId; - @Transient - private int useTemporarilyTeamIndex = -1; - @Transient - private List temporaryTeam; // Temporary Team for tower - - public TeamManager() { - this.mpTeam = new TeamInfo(); - this.avatars = new ArrayList<>(); - this.gadgets = new HashSet<>(); - this.teamResonances = new IntOpenHashSet(); - this.teamResonancesConfig = new IntOpenHashSet(); - } - - public TeamManager(Player player) { - this(); - this.setPlayer(player); - - this.teams = new LinkedHashMap<>(); - this.currentTeamIndex = 1; - for (int i = 1; i <= GameConstants.DEFAULT_TEAMS; i++) { - this.teams.put(i, new TeamInfo()); - } - } - - public World getWorld() { - return this.getPlayer().getWorld(); - } - - /** - * Search through all teams and if the team matches, return that index. - * Otherwise, return -1. - * No match could mean that the team does not currently belong to the player. - */ - public int getTeamId(TeamInfo team) { - for (int i = 1; i <= this.teams.size(); i++) { - if (this.teams.get(i).equals(team)) { - return i; - } - } - return -1; - } - - public int getCurrentTeamId() { - // Starts from 1 - return currentTeamIndex; - } - - private void setCurrentTeamId(int currentTeamIndex) { - this.currentTeamIndex = currentTeamIndex; - } - - public long getCurrentCharacterGuid() { - return this.getCurrentAvatarEntity().getAvatar().getGuid(); - } - - public TeamInfo getCurrentTeamInfo() { - if (useTemporarilyTeamIndex >= 0 && - useTemporarilyTeamIndex < temporaryTeam.size()) { - return temporaryTeam.get(useTemporarilyTeamIndex); - } - if (this.getPlayer().isInMultiplayer()) { - return this.getMpTeam(); - } - return this.getTeams().get(this.currentTeamIndex); - } - - public TeamInfo getCurrentSinglePlayerTeamInfo() { - return this.getTeams().get(this.currentTeamIndex); - } - - public List getActiveTeam() { - return avatars; - } - - public EntityAvatar getCurrentAvatarEntity() { - return this.getActiveTeam().get(currentCharacterIndex); - } - - public boolean isSpawned() { - return this.getPlayer().getScene() != null && this.getPlayer().getScene().getEntities().containsKey(this.getCurrentAvatarEntity().getId()); - } - - public int getMaxTeamSize() { - if (this.getPlayer().isInMultiplayer()) { - int max = GAME_OPTIONS.avatarLimits.multiplayerTeam; - if (this.getPlayer().getWorld().getHost() == this.getPlayer()) { - return Math.max(1, (int) Math.ceil(max / (double) this.getWorld().getPlayerCount())); - } - return Math.max(1, (int) Math.floor(max / (double) this.getWorld().getPlayerCount())); - } - - return GAME_OPTIONS.avatarLimits.singlePlayerTeam; - } - - // Methods - - /** - * Returns true if there is space to add the number of avatars to the team. - */ - public boolean canAddAvatarsToTeam(TeamInfo team, int avatars) { - return team.size() + avatars <= this.getMaxTeamSize(); - } - - /** - * Returns true if there is space to add to the team. - */ - public boolean canAddAvatarToTeam(TeamInfo team) { - return this.canAddAvatarsToTeam(team, 1); - } - - /** - * Returns true if there is space to add the number of avatars to the current team. - * If the current team is temporary, returns false. - */ - public boolean canAddAvatarsToCurrentTeam(int avatars) { - if (this.useTemporarilyTeamIndex != -1) { - return false; - } - return this.canAddAvatarsToTeam(this.getCurrentTeamInfo(), avatars); - } - - /** - * Returns true if there is space to add to the current team. - * If the current team is temporary, returns false. - */ - public boolean canAddAvatarToCurrentTeam() { - return this.canAddAvatarsToCurrentTeam(1); - } - - /** - * Try to add the collection of avatars to the team. - * Returns true if all were successfully added. - * If some can not be added, returns false and does not add any. - */ - public boolean addAvatarsToTeam(TeamInfo team, Collection avatars) { - if (!this.canAddAvatarsToTeam(team, avatars.size())) { - return false; - } - - // Convert avatars into a collection of avatar IDs, then add - team.getAvatars().addAll(avatars.stream().map(a -> a.getAvatarId()).toList()); - - // Update team - if (this.getPlayer().isInMultiplayer()) { - if (team.equals(this.getMpTeam())) { - // MP team Packet - this.updateTeamEntities(new PacketChangeMpTeamAvatarRsp(this.getPlayer(), team)); - } - } else { - // SP team update packet - this.getPlayer().sendPacket(new PacketAvatarTeamUpdateNotify(this.getPlayer())); - - int teamId = this.getTeamId(team); - if (teamId != -1) { - // This is one of the player's teams - // Update entites - if (teamId == this.getCurrentTeamId()) { - this.updateTeamEntities(new PacketSetUpAvatarTeamRsp(this.getPlayer(), teamId, team)); - } else { - this.getPlayer().sendPacket(new PacketSetUpAvatarTeamRsp(this.getPlayer(), teamId, team)); - } - } - } - - return true; - } - - /** - * Try to add an avatar to a team. - * Returns true if successful. - */ - public boolean addAvatarToTeam(TeamInfo team, Avatar avatar) { - return this.addAvatarsToTeam(team, Collections.singleton(avatar)); - } - - /** - * Try to add the collection of avatars to the current team. - * Will not modify a temporary team. - * Returns true if all were successfully added. - * If some can not be added, returns false and does not add any. - */ - public boolean addAvatarsToCurrentTeam(Collection avatars) { - if (this.useTemporarilyTeamIndex != -1) { - return false; - } - return this.addAvatarsToTeam(this.getCurrentTeamInfo(), avatars); - } - - /** - * Try to add an avatar to the current team. - * Will not modify a temporary team. - * Returns true if successful. - */ - public boolean addAvatarToCurrentTeam(Avatar avatar) { - return this.addAvatarsToCurrentTeam(Collections.singleton(avatar)); - } - - private void updateTeamResonances() { - this.getTeamResonances().clear(); - this.getTeamResonancesConfig().clear(); - // Official resonances require a full party - if (this.avatars.size() < 4) return; - - // TODO: make this actually read from TeamResonanceExcelConfigData.json for the real resonances and conditions - // Currently we just hardcode these conditions, but this won't work for modded resources or future changes - var elementCounts = new Object2IntOpenHashMap(); - this.getActiveTeam().stream() - .map(EntityAvatar::getAvatar).filter(Objects::nonNull) - .map(Avatar::getSkillDepot).filter(Objects::nonNull) - .map(AvatarSkillDepotData::getElementType).filter(Objects::nonNull) - .forEach(elementType -> elementCounts.addTo(elementType, 1)); - - // Dual element resonances - elementCounts.object2IntEntrySet().stream() - .filter(e -> e.getIntValue() >= 2) - .map(e -> e.getKey()) - .filter(elementType -> elementType.getTeamResonanceId() != 0) - .forEach(elementType -> { - this.teamResonances.add(elementType.getTeamResonanceId()); - this.teamResonancesConfig.add(elementType.getConfigHash()); - }); - - // Four element resonance - if (elementCounts.size() >= 4) { - this.teamResonances.add(ElementType.Default.getTeamResonanceId()); - this.teamResonancesConfig.add(ElementType.Default.getConfigHash()); - } - } - - public void updateTeamEntities(BasePacket responsePacket) { - // Sanity check - Should never happen - if (this.getCurrentTeamInfo().getAvatars().size() <= 0) { - return; - } - - // If current team has changed - EntityAvatar currentEntity = this.getCurrentAvatarEntity(); - Int2ObjectMap existingAvatars = new Int2ObjectOpenHashMap<>(); - int prevSelectedAvatarIndex = -1; - - for (EntityAvatar entity : this.getActiveTeam()) { - existingAvatars.put(entity.getAvatar().getAvatarId(), entity); - } - - // Clear active team entity list - this.getActiveTeam().clear(); - - // Add back entities into team - for (int i = 0; i < this.getCurrentTeamInfo().getAvatars().size(); i++) { - int avatarId = this.getCurrentTeamInfo().getAvatars().get(i); - EntityAvatar entity; - - if (existingAvatars.containsKey(avatarId)) { - entity = existingAvatars.get(avatarId); - existingAvatars.remove(avatarId); - if (entity == currentEntity) { - prevSelectedAvatarIndex = i; - } - } else { - entity = new EntityAvatar(this.getPlayer().getScene(), this.getPlayer().getAvatars().getAvatarById(avatarId)); - } - - this.getActiveTeam().add(entity); - } - - // Unload removed entities - for (EntityAvatar entity : existingAvatars.values()) { - this.getPlayer().getScene().removeEntity(entity); - entity.getAvatar().save(); - } - - // Set new selected character index - if (prevSelectedAvatarIndex == -1) { - // Previous selected avatar is not in the same spot, we will select the current one in the prev slot - prevSelectedAvatarIndex = Math.min(this.currentCharacterIndex, this.getActiveTeam().size() - 1); - } - this.currentCharacterIndex = prevSelectedAvatarIndex; - - // Update team resonances - this.updateTeamResonances(); - - // Packets - this.getPlayer().getWorld().broadcastPacket(new PacketSceneTeamUpdateNotify(this.getPlayer())); - - // Skill charges packet - Yes, this is official server behavior as of 2.6.0 - this.getActiveTeam().stream().map(EntityAvatar::getAvatar).forEach(Avatar::sendSkillExtraChargeMap); - - // Run callback - if (responsePacket != null) { - this.getPlayer().sendPacket(responsePacket); - } - - // Check if character changed - if (currentEntity != this.getCurrentAvatarEntity()) { - // Remove and Add - this.getPlayer().getScene().replaceEntity(currentEntity, this.getCurrentAvatarEntity()); - } - } - - public synchronized void setupAvatarTeam(int teamId, List list) { - // Sanity checks - if (list.size() == 0 || list.size() > this.getMaxTeamSize() || this.getPlayer().isInMultiplayer()) { - return; - } - - // Get team - TeamInfo teamInfo = this.getTeams().get(teamId); - if (teamInfo == null) { - return; - } - - // Set team data - LinkedHashSet newTeam = new LinkedHashSet<>(); - for (Long aLong : list) { - Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); - if (avatar == null || newTeam.contains(avatar)) { - // Should never happen - return; - } - newTeam.add(avatar); - } - - // Clear current team info and add avatars from our new team - teamInfo.getAvatars().clear(); - this.addAvatarsToTeam(teamInfo, newTeam); - } - - public void setupMpTeam(List list) { - // Sanity checks - if (list.size() == 0 || list.size() > this.getMaxTeamSize() || !this.getPlayer().isInMultiplayer()) { - return; - } - - TeamInfo teamInfo = this.getMpTeam(); - - // Set team data - LinkedHashSet newTeam = new LinkedHashSet<>(); - for (Long aLong : list) { - Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); - if (avatar == null || newTeam.contains(avatar)) { - // Should never happen - return; - } - newTeam.add(avatar); - } - - // Clear current team info and add avatars from our new team - teamInfo.getAvatars().clear(); - this.addAvatarsToTeam(teamInfo, newTeam); - } - - public void setupTemporaryTeam(List> guidList) { - this.temporaryTeam = guidList.stream().map(list -> { - // Sanity checks - if (list.size() == 0 || list.size() > this.getMaxTeamSize()) { - return null; - } - - // Set team data - LinkedHashSet newTeam = new LinkedHashSet<>(); - for (Long aLong : list) { - Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); - if (avatar == null || newTeam.contains(avatar)) { - // Should never happen - return null; - } - newTeam.add(avatar); - } - - // convert to avatar ids - return newTeam.stream() - .map(Avatar::getAvatarId) - .toList(); - }) - .filter(Objects::nonNull) - .map(TeamInfo::new) - .toList(); - } - - public void useTemporaryTeam(int index) { - this.useTemporarilyTeamIndex = index; - this.updateTeamEntities(null); - } - - public void cleanTemporaryTeam() { - // check if using temporary team - if (useTemporarilyTeamIndex < 0) { - return; - } - - this.useTemporarilyTeamIndex = -1; - this.temporaryTeam = null; - this.updateTeamEntities(null); - } - - public synchronized void setCurrentTeam(int teamId) { - // - if (this.getPlayer().isInMultiplayer()) { - return; - } - - // Get team - TeamInfo teamInfo = this.getTeams().get(teamId); - if (teamInfo == null || teamInfo.getAvatars().size() == 0) { - return; - } - - // Set - this.setCurrentTeamId(teamId); - this.updateTeamEntities(new PacketChooseCurAvatarTeamRsp(teamId)); - } - - public synchronized void setTeamName(int teamId, String teamName) { - // Get team - TeamInfo teamInfo = this.getTeams().get(teamId); - if (teamInfo == null) { - return; - } - - teamInfo.setName(teamName); - - // Packet - this.getPlayer().sendPacket(new PacketChangeTeamNameRsp(teamId, teamName)); - } - - public synchronized void changeAvatar(long guid) { - EntityAvatar oldEntity = this.getCurrentAvatarEntity(); - - if (guid == oldEntity.getAvatar().getGuid()) { - return; - } - - EntityAvatar newEntity = null; - int index = -1; - for (int i = 0; i < this.getActiveTeam().size(); i++) { - if (guid == this.getActiveTeam().get(i).getAvatar().getGuid()) { - index = i; - newEntity = this.getActiveTeam().get(i); - } - } - - if (index < 0 || newEntity == oldEntity) { - return; - } - - // Set index - this.setCurrentCharacterIndex(index); - - // Old entity motion state - oldEntity.setMotionState(MotionState.MOTION_STATE_STANDBY); - - // Remove and Add - this.getPlayer().getScene().replaceEntity(oldEntity, newEntity); - this.getPlayer().sendPacket(new PacketChangeAvatarRsp(guid)); - } - - public void onAvatarDie(long dieGuid) { - EntityAvatar deadAvatar = this.getCurrentAvatarEntity(); - - if (deadAvatar.isAlive() || deadAvatar.getId() != dieGuid) { - return; - } - - PlayerDieType dieType = deadAvatar.getKilledType(); - int killedBy = deadAvatar.getKilledBy(); - - if (dieType == PlayerDieType.PLAYER_DIE_TYPE_DRAWN) { - // Died in water. Do not replace - // The official server has skipped this notify and will just respawn the team immediately after the animation. - // TODO: Perhaps find a way to get vanilla experience? - this.getPlayer().sendPacket(new PacketWorldPlayerDieNotify(dieType, killedBy)); - } else { - // Replacement avatar - EntityAvatar replacement = null; - int replaceIndex = -1; - - for (int i = 0; i < this.getActiveTeam().size(); i++) { - EntityAvatar entity = this.getActiveTeam().get(i); - if (entity.isAlive()) { - replaceIndex = i; - replacement = entity; - break; - } - } - - if (replacement == null) { - // No more living team members... - this.getPlayer().sendPacket(new PacketWorldPlayerDieNotify(dieType, killedBy)); - // Invoke player team death event. - PlayerTeamDeathEvent event = new PlayerTeamDeathEvent(this.getPlayer(), - this.getActiveTeam().get(this.getCurrentCharacterIndex())); - event.call(); - } else { - // Set index and spawn replacement member - this.setCurrentCharacterIndex(replaceIndex); - this.getPlayer().getScene().addEntity(replacement); - } - } - - // Response packet - this.getPlayer().sendPacket(new PacketAvatarDieAnimationEndRsp(deadAvatar.getId(), 0)); - } - - public boolean reviveAvatar(Avatar avatar) { - for (EntityAvatar entity : this.getActiveTeam()) { - if (entity.getAvatar() == avatar) { - if (entity.isAlive()) { - return false; - } - - entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 1f); - // Satiation is reset when reviving an avatar - player.getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); - this.getPlayer().sendPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); - this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); - return true; - } - } - - return false; - } - - public boolean healAvatar(Avatar avatar, int healRate, int healAmount) { - for (EntityAvatar entity : this.getActiveTeam()) { - if (entity.getAvatar() == avatar) { - if (!entity.isAlive()) { - return false; - } - - entity.setFightProperty( - FightProperty.FIGHT_PROP_CUR_HP, - (float) Math.min( - (entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) + - entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * (float) healRate / 100.0 + - (float) healAmount / 100.0), - entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) - ) - ); - this.getPlayer().sendPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); - this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); - return true; - } - } - return false; - } - - public void respawnTeam() { - // Make sure all team members are dead - // Drowning needs revive when there may be other team members still alive. - // for (EntityAvatar entity : getActiveTeam()) { - // if (entity.isAlive()) { - // return; - // } - // } - player.getStaminaManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn - - // Revive all team members - for (EntityAvatar entity : this.getActiveTeam()) { - entity.setFightProperty( - FightProperty.FIGHT_PROP_CUR_HP, - entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f - ); - player.getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); - this.getPlayer().sendPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); - this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); - } - - // Teleport player and set player position - try { - this.getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(this.getPlayer(), EnterType.ENTER_TYPE_SELF, EnterReason.Revival, player.getSceneId(), getRespawnPosition())); - player.getPosition().set(getRespawnPosition()); - } catch (Exception e) { - this.getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(this.getPlayer(), EnterType.ENTER_TYPE_SELF, EnterReason.Revival, 3, GameConstants.START_POSITION)); - player.getPosition().set(GameConstants.START_POSITION); // If something goes wrong, the resurrection is here - } - - // Packets - this.getPlayer().sendPacket(new BasePacket(PacketOpcodes.WorldPlayerReviveRsp)); - } - - public Position getRespawnPosition() { - var deathPos = this.getPlayer().getPosition(); - int sceneId = this.getPlayer().getSceneId(); - - // Get the closest trans point to where the player died. - var respawnPoint = this.getPlayer().getUnlockedScenePoints(sceneId).stream() - .map(pointId -> GameData.getScenePointEntryById(sceneId, pointId)) - .filter(point -> point.getPointData().getType().equals("SceneTransPoint")) - .min((Comparator.comparingDouble(pos -> Utils.getDist(pos.getPointData().getTranPos(), deathPos)))); - - return respawnPoint.get().getPointData().getTranPos(); - } - - public void saveAvatars() { - // Save all avatars from active team - for (EntityAvatar entity : this.getActiveTeam()) { - entity.getAvatar().save(); - } - } - - public void onPlayerLogin() { // Hack for now to fix resonances on login - this.updateTeamResonances(); - } - - public synchronized void addNewCustomTeam() { - // Sanity check - max number of teams. - if (this.teams.size() == GameConstants.MAX_TEAMS) { - player.sendPacket(new PacketAddBackupAvatarTeamRsp(Retcode.RET_FAIL)); - return; - } - - // The id of the new custom team is the lowest id in [5,MAX_TEAMS] that is not yet taken. - int id = -1; - for (int i = 5; i <= GameConstants.MAX_TEAMS; i++) { - if (!this.teams.containsKey(i)) { - id = i; - break; - } - } - - // Create the new team. - this.teams.put(id, new TeamInfo()); - - // Send packets. - player.sendPacket(new PacketAvatarTeamAllDataNotify(player)); - player.sendPacket(new PacketAddBackupAvatarTeamRsp()); - } - - public synchronized void removeCustomTeam(int id) { - // Check if the target id exists. - if (!this.teams.containsKey(id)) { - player.sendPacket(new PacketDelBackupAvatarTeamRsp(Retcode.RET_FAIL, id)); - } - - // Remove team. - this.teams.remove(id); - - // Send packets. - player.sendPacket(new PacketAvatarTeamAllDataNotify(player)); - player.sendPacket(new PacketDelBackupAvatarTeamRsp(id)); - } -} +package emu.grasscutter.game.player; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.GameConstants; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntityBaseGadget; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.props.EnterReason; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.event.player.PlayerTeamDeathEvent; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; +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.Object2IntOpenHashMap; +import java.util.*; +import lombok.Getter; +import lombok.Setter; + +@Entity +public class TeamManager extends BasePlayerDataManager { + @Transient private final List avatars; + @Transient @Getter private final Set gadgets; + @Transient @Getter private final IntSet teamResonances; + @Transient @Getter private final IntSet teamResonancesConfig; + // This needs to be a LinkedHashMap to guarantee insertion order. + @Getter private LinkedHashMap teams; + private int currentTeamIndex; + @Getter @Setter private int currentCharacterIndex; + @Transient @Getter @Setter private TeamInfo mpTeam; + @Transient @Getter @Setter private int entityId; + @Transient private int useTemporarilyTeamIndex = -1; + @Transient private List temporaryTeam; // Temporary Team for tower + + public TeamManager() { + this.mpTeam = new TeamInfo(); + this.avatars = new ArrayList<>(); + this.gadgets = new HashSet<>(); + this.teamResonances = new IntOpenHashSet(); + this.teamResonancesConfig = new IntOpenHashSet(); + } + + public TeamManager(Player player) { + this(); + this.setPlayer(player); + + this.teams = new LinkedHashMap<>(); + this.currentTeamIndex = 1; + for (int i = 1; i <= GameConstants.DEFAULT_TEAMS; i++) { + this.teams.put(i, new TeamInfo()); + } + } + + public World getWorld() { + return this.getPlayer().getWorld(); + } + + /** + * Search through all teams and if the team matches, return that index. Otherwise, return -1. No + * match could mean that the team does not currently belong to the player. + */ + public int getTeamId(TeamInfo team) { + for (int i = 1; i <= this.teams.size(); i++) { + if (this.teams.get(i).equals(team)) { + return i; + } + } + return -1; + } + + public int getCurrentTeamId() { + // Starts from 1 + return currentTeamIndex; + } + + private void setCurrentTeamId(int currentTeamIndex) { + this.currentTeamIndex = currentTeamIndex; + } + + public long getCurrentCharacterGuid() { + return this.getCurrentAvatarEntity().getAvatar().getGuid(); + } + + public TeamInfo getCurrentTeamInfo() { + if (useTemporarilyTeamIndex >= 0 && useTemporarilyTeamIndex < temporaryTeam.size()) { + return temporaryTeam.get(useTemporarilyTeamIndex); + } + if (this.getPlayer().isInMultiplayer()) { + return this.getMpTeam(); + } + return this.getTeams().get(this.currentTeamIndex); + } + + public TeamInfo getCurrentSinglePlayerTeamInfo() { + return this.getTeams().get(this.currentTeamIndex); + } + + public List getActiveTeam() { + return avatars; + } + + public EntityAvatar getCurrentAvatarEntity() { + return this.getActiveTeam().get(currentCharacterIndex); + } + + public boolean isSpawned() { + return this.getPlayer().getScene() != null + && this.getPlayer() + .getScene() + .getEntities() + .containsKey(this.getCurrentAvatarEntity().getId()); + } + + public int getMaxTeamSize() { + if (this.getPlayer().isInMultiplayer()) { + int max = GAME_OPTIONS.avatarLimits.multiplayerTeam; + if (this.getPlayer().getWorld().getHost() == this.getPlayer()) { + return Math.max(1, (int) Math.ceil(max / (double) this.getWorld().getPlayerCount())); + } + return Math.max(1, (int) Math.floor(max / (double) this.getWorld().getPlayerCount())); + } + + return GAME_OPTIONS.avatarLimits.singlePlayerTeam; + } + + // Methods + + /** Returns true if there is space to add the number of avatars to the team. */ + public boolean canAddAvatarsToTeam(TeamInfo team, int avatars) { + return team.size() + avatars <= this.getMaxTeamSize(); + } + + /** Returns true if there is space to add to the team. */ + public boolean canAddAvatarToTeam(TeamInfo team) { + return this.canAddAvatarsToTeam(team, 1); + } + + /** + * Returns true if there is space to add the number of avatars to the current team. If the current + * team is temporary, returns false. + */ + public boolean canAddAvatarsToCurrentTeam(int avatars) { + if (this.useTemporarilyTeamIndex != -1) { + return false; + } + return this.canAddAvatarsToTeam(this.getCurrentTeamInfo(), avatars); + } + + /** + * Returns true if there is space to add to the current team. If the current team is temporary, + * returns false. + */ + public boolean canAddAvatarToCurrentTeam() { + return this.canAddAvatarsToCurrentTeam(1); + } + + /** + * Try to add the collection of avatars to the team. Returns true if all were successfully added. + * If some can not be added, returns false and does not add any. + */ + public boolean addAvatarsToTeam(TeamInfo team, Collection avatars) { + if (!this.canAddAvatarsToTeam(team, avatars.size())) { + return false; + } + + // Convert avatars into a collection of avatar IDs, then add + team.getAvatars().addAll(avatars.stream().map(a -> a.getAvatarId()).toList()); + + // Update team + if (this.getPlayer().isInMultiplayer()) { + if (team.equals(this.getMpTeam())) { + // MP team Packet + this.updateTeamEntities(new PacketChangeMpTeamAvatarRsp(this.getPlayer(), team)); + } + } else { + // SP team update packet + this.getPlayer().sendPacket(new PacketAvatarTeamUpdateNotify(this.getPlayer())); + + int teamId = this.getTeamId(team); + if (teamId != -1) { + // This is one of the player's teams + // Update entites + if (teamId == this.getCurrentTeamId()) { + this.updateTeamEntities(new PacketSetUpAvatarTeamRsp(this.getPlayer(), teamId, team)); + } else { + this.getPlayer().sendPacket(new PacketSetUpAvatarTeamRsp(this.getPlayer(), teamId, team)); + } + } + } + + return true; + } + + /** Try to add an avatar to a team. Returns true if successful. */ + public boolean addAvatarToTeam(TeamInfo team, Avatar avatar) { + return this.addAvatarsToTeam(team, Collections.singleton(avatar)); + } + + /** + * Try to add the collection of avatars to the current team. Will not modify a temporary team. + * Returns true if all were successfully added. If some can not be added, returns false and does + * not add any. + */ + public boolean addAvatarsToCurrentTeam(Collection avatars) { + if (this.useTemporarilyTeamIndex != -1) { + return false; + } + return this.addAvatarsToTeam(this.getCurrentTeamInfo(), avatars); + } + + /** + * Try to add an avatar to the current team. Will not modify a temporary team. Returns true if + * successful. + */ + public boolean addAvatarToCurrentTeam(Avatar avatar) { + return this.addAvatarsToCurrentTeam(Collections.singleton(avatar)); + } + + private void updateTeamResonances() { + this.getTeamResonances().clear(); + this.getTeamResonancesConfig().clear(); + // Official resonances require a full party + if (this.avatars.size() < 4) return; + + // TODO: make this actually read from TeamResonanceExcelConfigData.json for the real resonances + // and conditions + // Currently we just hardcode these conditions, but this won't work for modded resources or + // future changes + var elementCounts = new Object2IntOpenHashMap(); + this.getActiveTeam().stream() + .map(EntityAvatar::getAvatar) + .filter(Objects::nonNull) + .map(Avatar::getSkillDepot) + .filter(Objects::nonNull) + .map(AvatarSkillDepotData::getElementType) + .filter(Objects::nonNull) + .forEach(elementType -> elementCounts.addTo(elementType, 1)); + + // Dual element resonances + elementCounts.object2IntEntrySet().stream() + .filter(e -> e.getIntValue() >= 2) + .map(e -> e.getKey()) + .filter(elementType -> elementType.getTeamResonanceId() != 0) + .forEach( + elementType -> { + this.teamResonances.add(elementType.getTeamResonanceId()); + this.teamResonancesConfig.add(elementType.getConfigHash()); + }); + + // Four element resonance + if (elementCounts.size() >= 4) { + this.teamResonances.add(ElementType.Default.getTeamResonanceId()); + this.teamResonancesConfig.add(ElementType.Default.getConfigHash()); + } + } + + public void updateTeamEntities(BasePacket responsePacket) { + // Sanity check - Should never happen + if (this.getCurrentTeamInfo().getAvatars().size() <= 0) { + return; + } + + // If current team has changed + EntityAvatar currentEntity = this.getCurrentAvatarEntity(); + Int2ObjectMap existingAvatars = new Int2ObjectOpenHashMap<>(); + int prevSelectedAvatarIndex = -1; + + for (EntityAvatar entity : this.getActiveTeam()) { + existingAvatars.put(entity.getAvatar().getAvatarId(), entity); + } + + // Clear active team entity list + this.getActiveTeam().clear(); + + // Add back entities into team + for (int i = 0; i < this.getCurrentTeamInfo().getAvatars().size(); i++) { + int avatarId = this.getCurrentTeamInfo().getAvatars().get(i); + EntityAvatar entity; + + if (existingAvatars.containsKey(avatarId)) { + entity = existingAvatars.get(avatarId); + existingAvatars.remove(avatarId); + if (entity == currentEntity) { + prevSelectedAvatarIndex = i; + } + } else { + entity = + new EntityAvatar( + this.getPlayer().getScene(), this.getPlayer().getAvatars().getAvatarById(avatarId)); + } + + this.getActiveTeam().add(entity); + } + + // Unload removed entities + for (EntityAvatar entity : existingAvatars.values()) { + this.getPlayer().getScene().removeEntity(entity); + entity.getAvatar().save(); + } + + // Set new selected character index + if (prevSelectedAvatarIndex == -1) { + // Previous selected avatar is not in the same spot, we will select the current one in the + // prev slot + prevSelectedAvatarIndex = + Math.min(this.currentCharacterIndex, this.getActiveTeam().size() - 1); + } + this.currentCharacterIndex = prevSelectedAvatarIndex; + + // Update team resonances + this.updateTeamResonances(); + + // Packets + this.getPlayer().getWorld().broadcastPacket(new PacketSceneTeamUpdateNotify(this.getPlayer())); + + // Skill charges packet - Yes, this is official server behavior as of 2.6.0 + this.getActiveTeam().stream() + .map(EntityAvatar::getAvatar) + .forEach(Avatar::sendSkillExtraChargeMap); + + // Run callback + if (responsePacket != null) { + this.getPlayer().sendPacket(responsePacket); + } + + // Check if character changed + if (currentEntity != this.getCurrentAvatarEntity()) { + // Remove and Add + this.getPlayer().getScene().replaceEntity(currentEntity, this.getCurrentAvatarEntity()); + } + } + + public synchronized void setupAvatarTeam(int teamId, List list) { + // Sanity checks + if (list.size() == 0 + || list.size() > this.getMaxTeamSize() + || this.getPlayer().isInMultiplayer()) { + return; + } + + // Get team + TeamInfo teamInfo = this.getTeams().get(teamId); + if (teamInfo == null) { + return; + } + + // Set team data + LinkedHashSet newTeam = new LinkedHashSet<>(); + for (Long aLong : list) { + Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); + if (avatar == null || newTeam.contains(avatar)) { + // Should never happen + return; + } + newTeam.add(avatar); + } + + // Clear current team info and add avatars from our new team + teamInfo.getAvatars().clear(); + this.addAvatarsToTeam(teamInfo, newTeam); + } + + public void setupMpTeam(List list) { + // Sanity checks + if (list.size() == 0 + || list.size() > this.getMaxTeamSize() + || !this.getPlayer().isInMultiplayer()) { + return; + } + + TeamInfo teamInfo = this.getMpTeam(); + + // Set team data + LinkedHashSet newTeam = new LinkedHashSet<>(); + for (Long aLong : list) { + Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); + if (avatar == null || newTeam.contains(avatar)) { + // Should never happen + return; + } + newTeam.add(avatar); + } + + // Clear current team info and add avatars from our new team + teamInfo.getAvatars().clear(); + this.addAvatarsToTeam(teamInfo, newTeam); + } + + public void setupTemporaryTeam(List> guidList) { + this.temporaryTeam = + guidList.stream() + .map( + list -> { + // Sanity checks + if (list.size() == 0 || list.size() > this.getMaxTeamSize()) { + return null; + } + + // Set team data + LinkedHashSet newTeam = new LinkedHashSet<>(); + for (Long aLong : list) { + Avatar avatar = this.getPlayer().getAvatars().getAvatarByGuid(aLong); + if (avatar == null || newTeam.contains(avatar)) { + // Should never happen + return null; + } + newTeam.add(avatar); + } + + // convert to avatar ids + return newTeam.stream().map(Avatar::getAvatarId).toList(); + }) + .filter(Objects::nonNull) + .map(TeamInfo::new) + .toList(); + } + + public void useTemporaryTeam(int index) { + this.useTemporarilyTeamIndex = index; + this.updateTeamEntities(null); + } + + public void cleanTemporaryTeam() { + // check if using temporary team + if (useTemporarilyTeamIndex < 0) { + return; + } + + this.useTemporarilyTeamIndex = -1; + this.temporaryTeam = null; + this.updateTeamEntities(null); + } + + public synchronized void setCurrentTeam(int teamId) { + // + if (this.getPlayer().isInMultiplayer()) { + return; + } + + // Get team + TeamInfo teamInfo = this.getTeams().get(teamId); + if (teamInfo == null || teamInfo.getAvatars().size() == 0) { + return; + } + + // Set + this.setCurrentTeamId(teamId); + this.updateTeamEntities(new PacketChooseCurAvatarTeamRsp(teamId)); + } + + public synchronized void setTeamName(int teamId, String teamName) { + // Get team + TeamInfo teamInfo = this.getTeams().get(teamId); + if (teamInfo == null) { + return; + } + + teamInfo.setName(teamName); + + // Packet + this.getPlayer().sendPacket(new PacketChangeTeamNameRsp(teamId, teamName)); + } + + public synchronized void changeAvatar(long guid) { + EntityAvatar oldEntity = this.getCurrentAvatarEntity(); + + if (guid == oldEntity.getAvatar().getGuid()) { + return; + } + + EntityAvatar newEntity = null; + int index = -1; + for (int i = 0; i < this.getActiveTeam().size(); i++) { + if (guid == this.getActiveTeam().get(i).getAvatar().getGuid()) { + index = i; + newEntity = this.getActiveTeam().get(i); + } + } + + if (index < 0 || newEntity == oldEntity) { + return; + } + + // Set index + this.setCurrentCharacterIndex(index); + + // Old entity motion state + oldEntity.setMotionState(MotionState.MOTION_STATE_STANDBY); + + // Remove and Add + this.getPlayer().getScene().replaceEntity(oldEntity, newEntity); + this.getPlayer().sendPacket(new PacketChangeAvatarRsp(guid)); + } + + public void onAvatarDie(long dieGuid) { + EntityAvatar deadAvatar = this.getCurrentAvatarEntity(); + + if (deadAvatar.isAlive() || deadAvatar.getId() != dieGuid) { + return; + } + + PlayerDieType dieType = deadAvatar.getKilledType(); + int killedBy = deadAvatar.getKilledBy(); + + if (dieType == PlayerDieType.PLAYER_DIE_TYPE_DRAWN) { + // Died in water. Do not replace + // The official server has skipped this notify and will just respawn the team immediately + // after the animation. + // TODO: Perhaps find a way to get vanilla experience? + this.getPlayer().sendPacket(new PacketWorldPlayerDieNotify(dieType, killedBy)); + } else { + // Replacement avatar + EntityAvatar replacement = null; + int replaceIndex = -1; + + for (int i = 0; i < this.getActiveTeam().size(); i++) { + EntityAvatar entity = this.getActiveTeam().get(i); + if (entity.isAlive()) { + replaceIndex = i; + replacement = entity; + break; + } + } + + if (replacement == null) { + // No more living team members... + this.getPlayer().sendPacket(new PacketWorldPlayerDieNotify(dieType, killedBy)); + // Invoke player team death event. + PlayerTeamDeathEvent event = + new PlayerTeamDeathEvent( + this.getPlayer(), this.getActiveTeam().get(this.getCurrentCharacterIndex())); + event.call(); + } else { + // Set index and spawn replacement member + this.setCurrentCharacterIndex(replaceIndex); + this.getPlayer().getScene().addEntity(replacement); + } + } + + // Response packet + this.getPlayer().sendPacket(new PacketAvatarDieAnimationEndRsp(deadAvatar.getId(), 0)); + } + + public boolean reviveAvatar(Avatar avatar) { + for (EntityAvatar entity : this.getActiveTeam()) { + if (entity.getAvatar() == avatar) { + if (entity.isAlive()) { + return false; + } + + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 1f); + // Satiation is reset when reviving an avatar + player.getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); + this.getPlayer() + .sendPacket( + new PacketAvatarFightPropUpdateNotify( + entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); + this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); + return true; + } + } + + return false; + } + + public boolean healAvatar(Avatar avatar, int healRate, int healAmount) { + for (EntityAvatar entity : this.getActiveTeam()) { + if (entity.getAvatar() == avatar) { + if (!entity.isAlive()) { + return false; + } + + entity.setFightProperty( + FightProperty.FIGHT_PROP_CUR_HP, + (float) + Math.min( + (entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) + + entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) + * (float) healRate + / 100.0 + + (float) healAmount / 100.0), + entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP))); + this.getPlayer() + .sendPacket( + new PacketAvatarFightPropUpdateNotify( + entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); + this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); + return true; + } + } + return false; + } + + public void respawnTeam() { + // Make sure all team members are dead + // Drowning needs revive when there may be other team members still alive. + // for (EntityAvatar entity : getActiveTeam()) { + // if (entity.isAlive()) { + // return; + // } + // } + player + .getStaminaManager() + .stopSustainedStaminaHandler(); // prevent drowning immediately after respawn + + // Revive all team members + for (EntityAvatar entity : this.getActiveTeam()) { + entity.setFightProperty( + FightProperty.FIGHT_PROP_CUR_HP, + entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f); + player.getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); + this.getPlayer() + .sendPacket( + new PacketAvatarFightPropUpdateNotify( + entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); + this.getPlayer().sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); + } + + // Teleport player and set player position + try { + this.getPlayer() + .sendPacket( + new PacketPlayerEnterSceneNotify( + this.getPlayer(), + EnterType.ENTER_TYPE_SELF, + EnterReason.Revival, + player.getSceneId(), + getRespawnPosition())); + player.getPosition().set(getRespawnPosition()); + } catch (Exception e) { + this.getPlayer() + .sendPacket( + new PacketPlayerEnterSceneNotify( + this.getPlayer(), + EnterType.ENTER_TYPE_SELF, + EnterReason.Revival, + 3, + GameConstants.START_POSITION)); + player + .getPosition() + .set(GameConstants.START_POSITION); // If something goes wrong, the resurrection is here + } + + // Packets + this.getPlayer().sendPacket(new BasePacket(PacketOpcodes.WorldPlayerReviveRsp)); + } + + public Position getRespawnPosition() { + var deathPos = this.getPlayer().getPosition(); + int sceneId = this.getPlayer().getSceneId(); + + // Get the closest trans point to where the player died. + var respawnPoint = + this.getPlayer().getUnlockedScenePoints(sceneId).stream() + .map(pointId -> GameData.getScenePointEntryById(sceneId, pointId)) + .filter(point -> point.getPointData().getType().equals("SceneTransPoint")) + .min( + (Comparator.comparingDouble( + pos -> Utils.getDist(pos.getPointData().getTranPos(), deathPos)))); + + return respawnPoint.get().getPointData().getTranPos(); + } + + public void saveAvatars() { + // Save all avatars from active team + for (EntityAvatar entity : this.getActiveTeam()) { + entity.getAvatar().save(); + } + } + + public void onPlayerLogin() { // Hack for now to fix resonances on login + this.updateTeamResonances(); + } + + public synchronized void addNewCustomTeam() { + // Sanity check - max number of teams. + if (this.teams.size() == GameConstants.MAX_TEAMS) { + player.sendPacket(new PacketAddBackupAvatarTeamRsp(Retcode.RET_FAIL)); + return; + } + + // The id of the new custom team is the lowest id in [5,MAX_TEAMS] that is not yet taken. + int id = -1; + for (int i = 5; i <= GameConstants.MAX_TEAMS; i++) { + if (!this.teams.containsKey(i)) { + id = i; + break; + } + } + + // Create the new team. + this.teams.put(id, new TeamInfo()); + + // Send packets. + player.sendPacket(new PacketAvatarTeamAllDataNotify(player)); + player.sendPacket(new PacketAddBackupAvatarTeamRsp()); + } + + public synchronized void removeCustomTeam(int id) { + // Check if the target id exists. + if (!this.teams.containsKey(id)) { + player.sendPacket(new PacketDelBackupAvatarTeamRsp(Retcode.RET_FAIL, id)); + } + + // Remove team. + this.teams.remove(id); + + // Send packets. + player.sendPacket(new PacketAvatarTeamAllDataNotify(player)); + player.sendPacket(new PacketDelBackupAvatarTeamRsp(id)); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ActionReason.java b/src/main/java/emu/grasscutter/game/props/ActionReason.java index dc5ce0ea6..bad6f3513 100644 --- a/src/main/java/emu/grasscutter/game/props/ActionReason.java +++ b/src/main/java/emu/grasscutter/game/props/ActionReason.java @@ -1,212 +1,213 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum ActionReason { - None(0), - QuestItem(1), - QuestReward(2), - Trifle(3), - Shop(4), - PlayerUpgradeReward(5), - AddAvatar(6), - GadgetEnvAnimal(7), - MonsterEnvAnimal(8), - Compound(9), - Cook(10), - Gather(11), - MailAttachment(12), - CityLevelupReturn(15), - CityLevelupReward(17), - AreaExploreReward(18), - UnlockPointReward(19), - DungeonFirstPass(20), - DungeonPass(21), - ChangeElemType(23), - FetterOpen(25), - DailyTaskScore(26), - DailyTaskHost(27), - RandTaskHost(28), - Expedition(29), - Gacha(30), - Combine(31), - RandTaskGuest(32), - DailyTaskGuest(33), - ForgeOutput(34), - ForgeReturn(35), - InitAvatar(36), - MonsterDie(37), - Gm(38), - OpenChest(39), - GadgetDie(40), - MonsterChangeHp(41), - SubfieldDrop(42), - PushTipsReward(43), - ActivityMonsterDrop(44), - ActivityGather(45), - ActivitySubfieldDrop(46), - TowerScheduleReward(47), - TowerFloorStarReward(48), - TowerFirstPassReward(49), - TowerDailyReward(50), - HitClientTrivialEntity(51), - OpenWorldBossChest(52), - MaterialDeleteReturn(53), - SignInReward(54), - OpenBlossomChest(55), - Recharge(56), - BonusActivityReward(57), - TowerCommemorativeReward(58), - TowerSkipFloorReward(59), - RechargeBonus(60), - RechargeCard(61), - RechargeCardDaily(62), - RechargeCardReplace(63), - RechargeCardReplaceFree(64), - RechargePlayReplace(65), - MpPlayTakeReward(66), - ActivityWatcher(67), - SalesmanDeliverItem(68), - SalesmanReward(69), - Rebate(70), - McoinExchangeHcoin(71), - DailyTaskExchangeLegendaryKey(72), - UnlockPersonLine(73), - FetterLevelReward(74), - BuyResin(75), - RechargePackage(76), - DeliveryDailyReward(77), - CityReputationLevel(78), - CityReputationQuest(79), - CityReputationRequest(80), - CityReputationExplore(81), - OffergingLevel(82), - RoutineHost(83), - RoutineGuest(84), - TreasureMapSpotToken(89), - TreasureMapBonusLevelReward(90), - TreasureMapMpReward(91), - Convert(92), - OverflowTransform(93), - ActivityAvatarSelectionReward(96), - ActivityWatcherBatch(97), - HitTreeDrop(98), - GetHomeLevelupReward(99), - HomeDefaultFurniture(100), - ActivityCond(101), - BattlePassNotify(102), - PlayerUseItem(1001), - DropItem(1002), - WeaponUpgrade(1011), - WeaponPromote(1012), - WeaponAwaken(1013), - RelicUpgrade(1014), - Ability(1015), - DungeonStatueDrop(1016), - OfflineMsg(1017), - AvatarUpgrade(1018), - AvatarPromote(1019), - QuestAction(1021), - CityLevelup(1022), - UpgradeSkill(1024), - UnlockTalent(1025), - UpgradeProudSkill(1026), - PlayerLevelLimitUp(1027), - DungeonDaily(1028), - ItemGiving(1030), - ForgeCost(1031), - InvestigationReward(1032), - InvestigationTargetReward(1033), - GadgetInteract(1034), - SeaLampCiMaterial(1036), - SeaLampContributionReward(1037), - SeaLampPhaseReward(1038), - SeaLampFlyLamp(1039), - AutoRecover(1040), - ActivityExpireItem(1041), - SubCoinNegative(1042), - BargainDeduct(1043), - BattlePassPaidReward(1044), - BattlePassLevelReward(1045), - TrialAvatarActivityFirstPassReward(1046), - BuyBattlePassLevel(1047), - GrantBirthdayBenefit(1048), - AchievementReward(1049), - AchievementGoalReward(1050), - FirstShareToSocialNetwork(1051), - DestroyMaterial(1052), - CodexLevelupReward(1053), - HuntingOfferReward(1054), - UseWidgetAnchorPoint(1055), - UseWidgetBonfire(1056), - UngradeWeaponReturnMaterial(1057), - UseWidgetOneoffGatherPointDetector(1058), - UseWidgetClientCollector(1059), - UseWidgetClientDetector(1060), - TakeGeneralReward(1061), - AsterTakeSpecialReward(1062), - RemoveCodexBook(1063), - OfferingItem(1064), - UseWidgetGadgetBuilder(1065), - EffigyFirstPassReward(1066), - EffigyReward(1067), - ReunionFirstGiftReward(1068), - ReunionSignInReward(1069), - ReunionWatcherReward(1070), - SalesmanMpReward(1071), - ActionReasionAvatarPromoteReward(1072), - BlessingRedeemReward(1073), - ActionMiracleRingReward(1074), - ExpeditionReward(1075), - TreasureMapRemoveDetector(1076), - MechanicusDungeonTicket(1077), - MechanicusLevelupGear(1078), - MechanicusBattleSettle(1079), - RegionSearchReward(1080), - UnlockCoopChapter(1081), - TakeCoopReward(1082), - FleurFairDungeonReward(1083), - ActivityScore(1084), - ChannellerSlabOneoffDungeonReward(1085), - FurnitureMakeStart(1086), - FurnitureMakeTake(1087), - FurnitureMakeCancel(1088), - FurnitureMakeFastFinish(1089), - ChannellerSlabLoopDungeonFirstPassReward(1090), - ChannellerSlabLoopDungeonScoreReward(1091), - HomeLimitedShopBuy(1092), - HomeCoinCollect(1093); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - ActionReason(int value) { - this.value = value; - } - - public static ActionReason getTypeByValue(int value) { - return map.getOrDefault(value, None); - } - - public static ActionReason getTypeByName(String name) { - return stringMap.getOrDefault(name, None); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum ActionReason { + None(0), + QuestItem(1), + QuestReward(2), + Trifle(3), + Shop(4), + PlayerUpgradeReward(5), + AddAvatar(6), + GadgetEnvAnimal(7), + MonsterEnvAnimal(8), + Compound(9), + Cook(10), + Gather(11), + MailAttachment(12), + CityLevelupReturn(15), + CityLevelupReward(17), + AreaExploreReward(18), + UnlockPointReward(19), + DungeonFirstPass(20), + DungeonPass(21), + ChangeElemType(23), + FetterOpen(25), + DailyTaskScore(26), + DailyTaskHost(27), + RandTaskHost(28), + Expedition(29), + Gacha(30), + Combine(31), + RandTaskGuest(32), + DailyTaskGuest(33), + ForgeOutput(34), + ForgeReturn(35), + InitAvatar(36), + MonsterDie(37), + Gm(38), + OpenChest(39), + GadgetDie(40), + MonsterChangeHp(41), + SubfieldDrop(42), + PushTipsReward(43), + ActivityMonsterDrop(44), + ActivityGather(45), + ActivitySubfieldDrop(46), + TowerScheduleReward(47), + TowerFloorStarReward(48), + TowerFirstPassReward(49), + TowerDailyReward(50), + HitClientTrivialEntity(51), + OpenWorldBossChest(52), + MaterialDeleteReturn(53), + SignInReward(54), + OpenBlossomChest(55), + Recharge(56), + BonusActivityReward(57), + TowerCommemorativeReward(58), + TowerSkipFloorReward(59), + RechargeBonus(60), + RechargeCard(61), + RechargeCardDaily(62), + RechargeCardReplace(63), + RechargeCardReplaceFree(64), + RechargePlayReplace(65), + MpPlayTakeReward(66), + ActivityWatcher(67), + SalesmanDeliverItem(68), + SalesmanReward(69), + Rebate(70), + McoinExchangeHcoin(71), + DailyTaskExchangeLegendaryKey(72), + UnlockPersonLine(73), + FetterLevelReward(74), + BuyResin(75), + RechargePackage(76), + DeliveryDailyReward(77), + CityReputationLevel(78), + CityReputationQuest(79), + CityReputationRequest(80), + CityReputationExplore(81), + OffergingLevel(82), + RoutineHost(83), + RoutineGuest(84), + TreasureMapSpotToken(89), + TreasureMapBonusLevelReward(90), + TreasureMapMpReward(91), + Convert(92), + OverflowTransform(93), + ActivityAvatarSelectionReward(96), + ActivityWatcherBatch(97), + HitTreeDrop(98), + GetHomeLevelupReward(99), + HomeDefaultFurniture(100), + ActivityCond(101), + BattlePassNotify(102), + PlayerUseItem(1001), + DropItem(1002), + WeaponUpgrade(1011), + WeaponPromote(1012), + WeaponAwaken(1013), + RelicUpgrade(1014), + Ability(1015), + DungeonStatueDrop(1016), + OfflineMsg(1017), + AvatarUpgrade(1018), + AvatarPromote(1019), + QuestAction(1021), + CityLevelup(1022), + UpgradeSkill(1024), + UnlockTalent(1025), + UpgradeProudSkill(1026), + PlayerLevelLimitUp(1027), + DungeonDaily(1028), + ItemGiving(1030), + ForgeCost(1031), + InvestigationReward(1032), + InvestigationTargetReward(1033), + GadgetInteract(1034), + SeaLampCiMaterial(1036), + SeaLampContributionReward(1037), + SeaLampPhaseReward(1038), + SeaLampFlyLamp(1039), + AutoRecover(1040), + ActivityExpireItem(1041), + SubCoinNegative(1042), + BargainDeduct(1043), + BattlePassPaidReward(1044), + BattlePassLevelReward(1045), + TrialAvatarActivityFirstPassReward(1046), + BuyBattlePassLevel(1047), + GrantBirthdayBenefit(1048), + AchievementReward(1049), + AchievementGoalReward(1050), + FirstShareToSocialNetwork(1051), + DestroyMaterial(1052), + CodexLevelupReward(1053), + HuntingOfferReward(1054), + UseWidgetAnchorPoint(1055), + UseWidgetBonfire(1056), + UngradeWeaponReturnMaterial(1057), + UseWidgetOneoffGatherPointDetector(1058), + UseWidgetClientCollector(1059), + UseWidgetClientDetector(1060), + TakeGeneralReward(1061), + AsterTakeSpecialReward(1062), + RemoveCodexBook(1063), + OfferingItem(1064), + UseWidgetGadgetBuilder(1065), + EffigyFirstPassReward(1066), + EffigyReward(1067), + ReunionFirstGiftReward(1068), + ReunionSignInReward(1069), + ReunionWatcherReward(1070), + SalesmanMpReward(1071), + ActionReasionAvatarPromoteReward(1072), + BlessingRedeemReward(1073), + ActionMiracleRingReward(1074), + ExpeditionReward(1075), + TreasureMapRemoveDetector(1076), + MechanicusDungeonTicket(1077), + MechanicusLevelupGear(1078), + MechanicusBattleSettle(1079), + RegionSearchReward(1080), + UnlockCoopChapter(1081), + TakeCoopReward(1082), + FleurFairDungeonReward(1083), + ActivityScore(1084), + ChannellerSlabOneoffDungeonReward(1085), + FurnitureMakeStart(1086), + FurnitureMakeTake(1087), + FurnitureMakeCancel(1088), + FurnitureMakeFastFinish(1089), + ChannellerSlabLoopDungeonFirstPassReward(1090), + ChannellerSlabLoopDungeonScoreReward(1091), + HomeLimitedShopBuy(1092), + HomeCoinCollect(1093); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + ActionReason(int value) { + this.value = value; + } + + public static ActionReason getTypeByValue(int value) { + return map.getOrDefault(value, None); + } + + public static ActionReason getTypeByName(String name) { + return stringMap.getOrDefault(name, None); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ActivityType.java b/src/main/java/emu/grasscutter/game/props/ActivityType.java index 17b608e8c..a8264f2c9 100644 --- a/src/main/java/emu/grasscutter/game/props/ActivityType.java +++ b/src/main/java/emu/grasscutter/game/props/ActivityType.java @@ -1,39 +1,39 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -@Getter -@AllArgsConstructor -public enum ActivityType { - NONE(0), - NEW_ACTIVITY_MUSIC_GAME(2202), - - ; - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - public static ActivityType getTypeByValue(int value) { - return map.getOrDefault(value, NONE); - } - - public static ActivityType getTypeByName(String name) { - return stringMap.getOrDefault(name, NONE); - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ActivityType { + NONE(0), + NEW_ACTIVITY_MUSIC_GAME(2202), + ; + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + public static ActivityType getTypeByValue(int value) { + return map.getOrDefault(value, NONE); + } + + public static ActivityType getTypeByName(String name) { + return stringMap.getOrDefault(name, NONE); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/BattlePassMissionRefreshType.java b/src/main/java/emu/grasscutter/game/props/BattlePassMissionRefreshType.java index d95a858a1..1bbb1d18b 100644 --- a/src/main/java/emu/grasscutter/game/props/BattlePassMissionRefreshType.java +++ b/src/main/java/emu/grasscutter/game/props/BattlePassMissionRefreshType.java @@ -1,18 +1,18 @@ -package emu.grasscutter.game.props; - -public enum BattlePassMissionRefreshType { - BATTLE_PASS_MISSION_REFRESH_DAILY(0), - BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE(1), // Weekly - BATTLE_PASS_MISSION_REFRESH_SCHEDULE(2), // Per BP - BATTLE_PASS_MISSION_REFRESH_CYCLE(1); // Event? - - private final int value; - - BattlePassMissionRefreshType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +public enum BattlePassMissionRefreshType { + BATTLE_PASS_MISSION_REFRESH_DAILY(0), + BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE(1), // Weekly + BATTLE_PASS_MISSION_REFRESH_SCHEDULE(2), // Per BP + BATTLE_PASS_MISSION_REFRESH_CYCLE(1); // Event? + + private final int value; + + BattlePassMissionRefreshType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/BattlePassMissionStatus.java b/src/main/java/emu/grasscutter/game/props/BattlePassMissionStatus.java index 385f0775f..a983639d8 100644 --- a/src/main/java/emu/grasscutter/game/props/BattlePassMissionStatus.java +++ b/src/main/java/emu/grasscutter/game/props/BattlePassMissionStatus.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.props; - -import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus; - -public enum BattlePassMissionStatus { - MISSION_STATUS_INVALID(0, MissionStatus.MISSION_STATUS_INVALID), - MISSION_STATUS_UNFINISHED(1, MissionStatus.MISSION_STATUS_UNFINISHED), - MISSION_STATUS_FINISHED(2, MissionStatus.MISSION_STATUS_FINISHED), - MISSION_STATUS_POINT_TAKEN(3, MissionStatus.MISSION_STATUS_POINT_TAKEN); - - private final int value; - private final MissionStatus missionStatus; - - BattlePassMissionStatus(int value, MissionStatus missionStatus) { - this.value = value; - this.missionStatus = missionStatus; // In case proto enum values change later - } - - public int getValue() { - return value; - } - - public MissionStatus getMissionStatus() { - return missionStatus; - } -} +package emu.grasscutter.game.props; + +import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus; + +public enum BattlePassMissionStatus { + MISSION_STATUS_INVALID(0, MissionStatus.MISSION_STATUS_INVALID), + MISSION_STATUS_UNFINISHED(1, MissionStatus.MISSION_STATUS_UNFINISHED), + MISSION_STATUS_FINISHED(2, MissionStatus.MISSION_STATUS_FINISHED), + MISSION_STATUS_POINT_TAKEN(3, MissionStatus.MISSION_STATUS_POINT_TAKEN); + + private final int value; + private final MissionStatus missionStatus; + + BattlePassMissionStatus(int value, MissionStatus missionStatus) { + this.value = value; + this.missionStatus = missionStatus; // In case proto enum values change later + } + + public int getValue() { + return value; + } + + public MissionStatus getMissionStatus() { + return missionStatus; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ClimateType.java b/src/main/java/emu/grasscutter/game/props/ClimateType.java index dce021208..3ea3df95f 100644 --- a/src/main/java/emu/grasscutter/game/props/ClimateType.java +++ b/src/main/java/emu/grasscutter/game/props/ClimateType.java @@ -1,55 +1,56 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum ClimateType { - CLIMATE_NONE(0), - CLIMATE_SUNNY(1), - CLIMATE_CLOUDY(2), - CLIMATE_RAIN(3), - CLIMATE_THUNDERSTORM(4), - CLIMATE_SNOW(5), - CLIMATE_MIST(6); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - ClimateType(int value) { - this.value = value; - } - - public static ClimateType getTypeByValue(int value) { - return map.getOrDefault(value, CLIMATE_NONE); - } - - public static ClimateType getTypeByName(String name) { - return stringMap.getOrDefault(name, CLIMATE_NONE); - } - - public static ClimateType getTypeByShortName(String shortName) { - String name = "CLIMATE_" + shortName.toUpperCase(); - return stringMap.getOrDefault(name, CLIMATE_NONE); - } - - public int getValue() { - return this.value; - } - - public String getShortName() { - return this.name().substring(8).toLowerCase(); - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum ClimateType { + CLIMATE_NONE(0), + CLIMATE_SUNNY(1), + CLIMATE_CLOUDY(2), + CLIMATE_RAIN(3), + CLIMATE_THUNDERSTORM(4), + CLIMATE_SNOW(5), + CLIMATE_MIST(6); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + ClimateType(int value) { + this.value = value; + } + + public static ClimateType getTypeByValue(int value) { + return map.getOrDefault(value, CLIMATE_NONE); + } + + public static ClimateType getTypeByName(String name) { + return stringMap.getOrDefault(name, CLIMATE_NONE); + } + + public static ClimateType getTypeByShortName(String shortName) { + String name = "CLIMATE_" + shortName.toUpperCase(); + return stringMap.getOrDefault(name, CLIMATE_NONE); + } + + public int getValue() { + return this.value; + } + + public String getShortName() { + return this.name().substring(8).toLowerCase(); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ElementType.java b/src/main/java/emu/grasscutter/game/props/ElementType.java index 917b71800..97fc9e6bf 100644 --- a/src/main/java/emu/grasscutter/game/props/ElementType.java +++ b/src/main/java/emu/grasscutter/game/props/ElementType.java @@ -1,76 +1,129 @@ -package emu.grasscutter.game.props; - -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum ElementType { - None(0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), - Fire(1, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2", 2), - Water(2, FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2", 3), - Grass(3, FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY, 10501, "TeamResonance_Grass_Lv2", 8), - Electric(4, FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2", 7), - Ice(5, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2", 5), - Frozen(6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), - Wind(7, FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2", 4), - Rock(8, FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2", 6), - AntiFire(9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), - Default(255, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10801, "TeamResonance_AllDifferent"); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - @Getter - private final int value; - @Getter - private final int teamResonanceId; - @Getter - private final FightProperty curEnergyProp; - @Getter - private final FightProperty maxEnergyProp; - @Getter - private final int depotValue; - @Getter - private final int configHash; - - ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp) { - this(value, curEnergyProp, maxEnergyProp, 0, null, 1); - } - - ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName) { - this(value, curEnergyProp, maxEnergyProp, teamResonanceId, configName, 1); - } - - ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName, int depotValue) { - this.value = value; - this.curEnergyProp = curEnergyProp; - this.maxEnergyProp = maxEnergyProp; - this.teamResonanceId = teamResonanceId; - this.depotValue = depotValue; - if (configName != null) { - this.configHash = Utils.abilityHash(configName); - } else { - this.configHash = 0; - } - } - - public static ElementType getTypeByValue(int value) { - return map.getOrDefault(value, None); - } - - public static ElementType getTypeByName(String name) { - return stringMap.getOrDefault(name, None); - } -} +package emu.grasscutter.game.props; + +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import lombok.Getter; + +public enum ElementType { + None(0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), + Fire( + 1, + FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, + FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, + 10101, + "TeamResonance_Fire_Lv2", + 2), + Water( + 2, + FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, + FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, + 10201, + "TeamResonance_Water_Lv2", + 3), + Grass( + 3, + FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, + FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY, + 10501, + "TeamResonance_Grass_Lv2", + 8), + Electric( + 4, + FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, + FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, + 10401, + "TeamResonance_Electric_Lv2", + 7), + Ice( + 5, + FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, + FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, + 10601, + "TeamResonance_Ice_Lv2", + 5), + Frozen(6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), + Wind( + 7, + FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, + FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, + 10301, + "TeamResonance_Wind_Lv2", + 4), + Rock( + 8, + FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, + FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, + 10701, + "TeamResonance_Rock_Lv2", + 6), + AntiFire(9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), + Default( + 255, + FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, + FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, + 10801, + "TeamResonance_AllDifferent"); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + @Getter private final int value; + @Getter private final int teamResonanceId; + @Getter private final FightProperty curEnergyProp; + @Getter private final FightProperty maxEnergyProp; + @Getter private final int depotValue; + @Getter private final int configHash; + + ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp) { + this(value, curEnergyProp, maxEnergyProp, 0, null, 1); + } + + ElementType( + int value, + FightProperty curEnergyProp, + FightProperty maxEnergyProp, + int teamResonanceId, + String configName) { + this(value, curEnergyProp, maxEnergyProp, teamResonanceId, configName, 1); + } + + ElementType( + int value, + FightProperty curEnergyProp, + FightProperty maxEnergyProp, + int teamResonanceId, + String configName, + int depotValue) { + this.value = value; + this.curEnergyProp = curEnergyProp; + this.maxEnergyProp = maxEnergyProp; + this.teamResonanceId = teamResonanceId; + this.depotValue = depotValue; + if (configName != null) { + this.configHash = Utils.abilityHash(configName); + } else { + this.configHash = 0; + } + } + + public static ElementType getTypeByValue(int value) { + return map.getOrDefault(value, None); + } + + public static ElementType getTypeByName(String name) { + return stringMap.getOrDefault(name, None); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/EnterReason.java b/src/main/java/emu/grasscutter/game/props/EnterReason.java index 5765f2d5f..1e138d6f5 100644 --- a/src/main/java/emu/grasscutter/game/props/EnterReason.java +++ b/src/main/java/emu/grasscutter/game/props/EnterReason.java @@ -1,71 +1,72 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum EnterReason { - None(0), - Login(1), - DungeonReplay(11), - DungeonReviveOnWaypoint(12), - DungeonEnter(13), - DungeonQuit(14), - Gm(21), - QuestRollback(31), - Revival(32), - PersonalScene(41), - TransPoint(42), - ClientTransmit(43), - ForceDragBack(44), - TeamKick(51), - TeamJoin(52), - TeamBack(53), - Muip(54), - DungeonInviteAccept(55), - Lua(56), - ActivityLoadTerrain(57), - HostFromSingleToMp(58), - MpPlay(59), - AnchorPoint(60), - LuaSkipUi(61), - ReloadTerrain(62), - DraftTransfer(63), - EnterHome(64), - ExitHome(65), - ChangeHomeModule(66), - Gallery(67), - HomeSceneJump(68), - HideAndSeek(69); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - EnterReason(int value) { - this.value = value; - } - - public static EnterReason getTypeByValue(int value) { - return map.getOrDefault(value, None); - } - - public static EnterReason getTypeByName(String name) { - return stringMap.getOrDefault(name, None); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum EnterReason { + None(0), + Login(1), + DungeonReplay(11), + DungeonReviveOnWaypoint(12), + DungeonEnter(13), + DungeonQuit(14), + Gm(21), + QuestRollback(31), + Revival(32), + PersonalScene(41), + TransPoint(42), + ClientTransmit(43), + ForceDragBack(44), + TeamKick(51), + TeamJoin(52), + TeamBack(53), + Muip(54), + DungeonInviteAccept(55), + Lua(56), + ActivityLoadTerrain(57), + HostFromSingleToMp(58), + MpPlay(59), + AnchorPoint(60), + LuaSkipUi(61), + ReloadTerrain(62), + DraftTransfer(63), + EnterHome(64), + ExitHome(65), + ChangeHomeModule(66), + Gallery(67), + HomeSceneJump(68), + HideAndSeek(69); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + EnterReason(int value) { + this.value = value; + } + + public static EnterReason getTypeByValue(int value) { + return map.getOrDefault(value, None); + } + + public static EnterReason getTypeByName(String name) { + return stringMap.getOrDefault(name, None); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/EntityIdType.java b/src/main/java/emu/grasscutter/game/props/EntityIdType.java index 7d546dbb9..d4eded2de 100644 --- a/src/main/java/emu/grasscutter/game/props/EntityIdType.java +++ b/src/main/java/emu/grasscutter/game/props/EntityIdType.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.props; - -public enum EntityIdType { - AVATAR(0x01), - MONSTER(0x02), - NPC(0x03), - GADGET(0x04), - REGION(0x05), - WEAPON(0x06), - TEAM(0x09), - MPLEVEL(0x0b); - - private final int id; - - EntityIdType(int id) { - this.id = id; - } - - public int getId() { - return id; - } -} +package emu.grasscutter.game.props; + +public enum EntityIdType { + AVATAR(0x01), + MONSTER(0x02), + NPC(0x03), + GADGET(0x04), + REGION(0x05), + WEAPON(0x06), + TEAM(0x09), + MPLEVEL(0x0b); + + private final int id; + + EntityIdType(int id) { + this.id = id; + } + + public int getId() { + return id; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/EntityType.java b/src/main/java/emu/grasscutter/game/props/EntityType.java index 938fdef74..7456f72bf 100644 --- a/src/main/java/emu/grasscutter/game/props/EntityType.java +++ b/src/main/java/emu/grasscutter/game/props/EntityType.java @@ -1,107 +1,108 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum EntityType { - None(0), - Avatar(1), - Monster(2), - Bullet(3), - AttackPhyisicalUnit(4), - AOE(5), - Camera(6), - EnviroArea(7), - Equip(8), - MonsterEquip(9), - Grass(10), - Level(11), - NPC(12), - TransPointFirst(13), - TransPointFirstGadget(14), - TransPointSecond(15), - TransPointSecondGadget(16), - DropItem(17), - Field(18), - Gadget(19), - Water(20), - GatherPoint(21), - GatherObject(22), - AirflowField(23), - SpeedupField(24), - Gear(25), - Chest(26), - EnergyBall(27), - ElemCrystal(28), - Timeline(29), - Worktop(30), - Team(31), - Platform(32), - AmberWind(33), - EnvAnimal(34), - SealGadget(35), - Tree(36), - Bush(37), - QuestGadget(38), - Lightning(39), - RewardPoint(40), - RewardStatue(41), - MPLevel(42), - WindSeed(43), - MpPlayRewardPoint(44), - ViewPoint(45), - RemoteAvatar(46), - GeneralRewardPoint(47), - PlayTeam(48), - OfferingGadget(49), - EyePoint(50), - MiracleRing(51), - Foundation(52), - WidgetGadget(53), - Vehicle(54), - SubEquip(55), - FishRod(56), - CustomTile(57), - FishPool(58), - CustomGadget(59), - BlackMud(60), - RoguelikeOperatorGadget(61), - NightCrowGadget(62), - Projector(63), - Screen(64), - EchoShell(65), - UIInteractGadget(66), - PlaceHolder(99); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - EntityType(int value) { - this.value = value; - } - - public static EntityType getTypeByValue(int value) { - return map.getOrDefault(value, None); - } - - public static EntityType getTypeByName(String name) { - return stringMap.getOrDefault(name, None); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum EntityType { + None(0), + Avatar(1), + Monster(2), + Bullet(3), + AttackPhyisicalUnit(4), + AOE(5), + Camera(6), + EnviroArea(7), + Equip(8), + MonsterEquip(9), + Grass(10), + Level(11), + NPC(12), + TransPointFirst(13), + TransPointFirstGadget(14), + TransPointSecond(15), + TransPointSecondGadget(16), + DropItem(17), + Field(18), + Gadget(19), + Water(20), + GatherPoint(21), + GatherObject(22), + AirflowField(23), + SpeedupField(24), + Gear(25), + Chest(26), + EnergyBall(27), + ElemCrystal(28), + Timeline(29), + Worktop(30), + Team(31), + Platform(32), + AmberWind(33), + EnvAnimal(34), + SealGadget(35), + Tree(36), + Bush(37), + QuestGadget(38), + Lightning(39), + RewardPoint(40), + RewardStatue(41), + MPLevel(42), + WindSeed(43), + MpPlayRewardPoint(44), + ViewPoint(45), + RemoteAvatar(46), + GeneralRewardPoint(47), + PlayTeam(48), + OfferingGadget(49), + EyePoint(50), + MiracleRing(51), + Foundation(52), + WidgetGadget(53), + Vehicle(54), + SubEquip(55), + FishRod(56), + CustomTile(57), + FishPool(58), + CustomGadget(59), + BlackMud(60), + RoguelikeOperatorGadget(61), + NightCrowGadget(62), + Projector(63), + Screen(64), + EchoShell(65), + UIInteractGadget(66), + PlaceHolder(99); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + EntityType(int value) { + this.value = value; + } + + public static EntityType getTypeByValue(int value) { + return map.getOrDefault(value, None); + } + + public static EntityType getTypeByName(String name) { + return stringMap.getOrDefault(name, None); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/FetterState.java b/src/main/java/emu/grasscutter/game/props/FetterState.java index 4630268e7..10b71e291 100644 --- a/src/main/java/emu/grasscutter/game/props/FetterState.java +++ b/src/main/java/emu/grasscutter/game/props/FetterState.java @@ -1,43 +1,44 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum FetterState { - NONE(0), - NOT_OPEN(1), - OPEN(1), - FINISH(3); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - FetterState(int value) { - this.value = value; - } - - public static FetterState getTypeByValue(int value) { - return map.getOrDefault(value, NONE); - } - - public static FetterState getTypeByName(String name) { - return stringMap.getOrDefault(name, NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum FetterState { + NONE(0), + NOT_OPEN(1), + OPEN(1), + FINISH(3); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + FetterState(int value) { + this.value = value; + } + + public static FetterState getTypeByValue(int value) { + return map.getOrDefault(value, NONE); + } + + public static FetterState getTypeByName(String name) { + return stringMap.getOrDefault(name, NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/FightProperty.java b/src/main/java/emu/grasscutter/game/props/FightProperty.java index 69b51941d..bd67b01c1 100644 --- a/src/main/java/emu/grasscutter/game/props/FightProperty.java +++ b/src/main/java/emu/grasscutter/game/props/FightProperty.java @@ -1,226 +1,263 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Stream; - -import static java.util.Map.entry; - -public enum FightProperty { - FIGHT_PROP_NONE(0), - FIGHT_PROP_BASE_HP(1), - FIGHT_PROP_HP(2), - FIGHT_PROP_HP_PERCENT(3), - FIGHT_PROP_BASE_ATTACK(4), - FIGHT_PROP_ATTACK(5), - FIGHT_PROP_ATTACK_PERCENT(6), - FIGHT_PROP_BASE_DEFENSE(7), - FIGHT_PROP_DEFENSE(8), - FIGHT_PROP_DEFENSE_PERCENT(9), - FIGHT_PROP_BASE_SPEED(10), - FIGHT_PROP_SPEED_PERCENT(11), - FIGHT_PROP_HP_MP_PERCENT(12), - FIGHT_PROP_ATTACK_MP_PERCENT(13), - FIGHT_PROP_CRITICAL(20), - FIGHT_PROP_ANTI_CRITICAL(21), - FIGHT_PROP_CRITICAL_HURT(22), - FIGHT_PROP_CHARGE_EFFICIENCY(23), - FIGHT_PROP_ADD_HURT(24), - FIGHT_PROP_SUB_HURT(25), - FIGHT_PROP_HEAL_ADD(26), - FIGHT_PROP_HEALED_ADD(27), - FIGHT_PROP_ELEMENT_MASTERY(28), - FIGHT_PROP_PHYSICAL_SUB_HURT(29), - FIGHT_PROP_PHYSICAL_ADD_HURT(30), - FIGHT_PROP_DEFENCE_IGNORE_RATIO(31), - FIGHT_PROP_DEFENCE_IGNORE_DELTA(32), - FIGHT_PROP_FIRE_ADD_HURT(40), - FIGHT_PROP_ELEC_ADD_HURT(41), - FIGHT_PROP_WATER_ADD_HURT(42), - FIGHT_PROP_GRASS_ADD_HURT(43), - FIGHT_PROP_WIND_ADD_HURT(44), - FIGHT_PROP_ROCK_ADD_HURT(45), - FIGHT_PROP_ICE_ADD_HURT(46), - FIGHT_PROP_HIT_HEAD_ADD_HURT(47), - FIGHT_PROP_FIRE_SUB_HURT(50), - FIGHT_PROP_ELEC_SUB_HURT(51), - FIGHT_PROP_WATER_SUB_HURT(52), - FIGHT_PROP_GRASS_SUB_HURT(53), - FIGHT_PROP_WIND_SUB_HURT(54), - FIGHT_PROP_ROCK_SUB_HURT(55), - FIGHT_PROP_ICE_SUB_HURT(56), - FIGHT_PROP_EFFECT_HIT(60), - FIGHT_PROP_EFFECT_RESIST(61), - FIGHT_PROP_FREEZE_RESIST(62), - FIGHT_PROP_TORPOR_RESIST(63), - FIGHT_PROP_DIZZY_RESIST(64), - FIGHT_PROP_FREEZE_SHORTEN(65), - FIGHT_PROP_TORPOR_SHORTEN(66), - FIGHT_PROP_DIZZY_SHORTEN(67), - FIGHT_PROP_MAX_FIRE_ENERGY(70), - FIGHT_PROP_MAX_ELEC_ENERGY(71), - FIGHT_PROP_MAX_WATER_ENERGY(72), - FIGHT_PROP_MAX_GRASS_ENERGY(73), - FIGHT_PROP_MAX_WIND_ENERGY(74), - FIGHT_PROP_MAX_ICE_ENERGY(75), - FIGHT_PROP_MAX_ROCK_ENERGY(76), - FIGHT_PROP_SKILL_CD_MINUS_RATIO(80), - FIGHT_PROP_SHIELD_COST_MINUS_RATIO(81), - FIGHT_PROP_CUR_FIRE_ENERGY(1000), - FIGHT_PROP_CUR_ELEC_ENERGY(1001), - FIGHT_PROP_CUR_WATER_ENERGY(1002), - FIGHT_PROP_CUR_GRASS_ENERGY(1003), - FIGHT_PROP_CUR_WIND_ENERGY(1004), - FIGHT_PROP_CUR_ICE_ENERGY(1005), - FIGHT_PROP_CUR_ROCK_ENERGY(1006), - FIGHT_PROP_CUR_HP(1010), - FIGHT_PROP_MAX_HP(2000), - FIGHT_PROP_CUR_ATTACK(2001), - FIGHT_PROP_CUR_DEFENSE(2002), - FIGHT_PROP_CUR_SPEED(2003), - FIGHT_PROP_NONEXTRA_ATTACK(3000), - FIGHT_PROP_NONEXTRA_DEFENSE(3001), - FIGHT_PROP_NONEXTRA_CRITICAL(3002), - FIGHT_PROP_NONEXTRA_ANTI_CRITICAL(3003), - FIGHT_PROP_NONEXTRA_CRITICAL_HURT(3004), - FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY(3005), - FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY(3006), - FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT(3007), - FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT(3008), - FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT(3009), - FIGHT_PROP_NONEXTRA_WATER_ADD_HURT(3010), - FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT(3011), - FIGHT_PROP_NONEXTRA_WIND_ADD_HURT(3012), - FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT(3013), - FIGHT_PROP_NONEXTRA_ICE_ADD_HURT(3014), - FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT(3015), - FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT(3016), - FIGHT_PROP_NONEXTRA_WATER_SUB_HURT(3017), - FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT(3018), - FIGHT_PROP_NONEXTRA_WIND_SUB_HURT(3019), - FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT(3020), - FIGHT_PROP_NONEXTRA_ICE_SUB_HURT(3021), - FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO(3022), - FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO(3023), - FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT(3024); - - public static final int[] fightProps = new int[]{1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 55, 56, 2000, 2001, 2002, 2003, 1010}; - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - // This was originally for relic properties so some names might not be applicable for e.g. setstats - private static final Map shortNameMap = Map.ofEntries( - // Normal relic stats - entry("hp", FIGHT_PROP_HP), - entry("atk", FIGHT_PROP_ATTACK), - entry("def", FIGHT_PROP_DEFENSE), - entry("hp%", FIGHT_PROP_HP_PERCENT), - entry("atk%", FIGHT_PROP_ATTACK_PERCENT), - entry("def%", FIGHT_PROP_DEFENSE_PERCENT), - entry("em", FIGHT_PROP_ELEMENT_MASTERY), - entry("er", FIGHT_PROP_CHARGE_EFFICIENCY), - entry("hb", FIGHT_PROP_HEAL_ADD), - entry("heal", FIGHT_PROP_HEAL_ADD), - entry("cd", FIGHT_PROP_CRITICAL_HURT), - entry("cdmg", FIGHT_PROP_CRITICAL_HURT), - entry("cr", FIGHT_PROP_CRITICAL), - entry("crate", FIGHT_PROP_CRITICAL), - entry("phys%", FIGHT_PROP_PHYSICAL_ADD_HURT), - entry("dendro%", FIGHT_PROP_GRASS_ADD_HURT), - entry("geo%", FIGHT_PROP_ROCK_ADD_HURT), - entry("anemo%", FIGHT_PROP_WIND_ADD_HURT), - entry("hydro%", FIGHT_PROP_WATER_ADD_HURT), - entry("cryo%", FIGHT_PROP_ICE_ADD_HURT), - entry("electro%", FIGHT_PROP_ELEC_ADD_HURT), - entry("pyro%", FIGHT_PROP_FIRE_ADD_HURT), - // Other stats - entry("maxhp", FIGHT_PROP_MAX_HP), - entry("dmg", FIGHT_PROP_ADD_HURT), // This seems to get reset after attacks - entry("cdr", FIGHT_PROP_SKILL_CD_MINUS_RATIO), - entry("heali", FIGHT_PROP_HEALED_ADD), - entry("shield", FIGHT_PROP_SHIELD_COST_MINUS_RATIO), - entry("defi", FIGHT_PROP_DEFENCE_IGNORE_RATIO), - entry("resall", FIGHT_PROP_SUB_HURT), // This seems to get reset after attacks - entry("resanemo", FIGHT_PROP_WIND_SUB_HURT), - entry("rescryo", FIGHT_PROP_ICE_SUB_HURT), - entry("resdendro", FIGHT_PROP_GRASS_SUB_HURT), - entry("reselectro", FIGHT_PROP_ELEC_SUB_HURT), - entry("resgeo", FIGHT_PROP_ROCK_SUB_HURT), - entry("reshydro", FIGHT_PROP_WATER_SUB_HURT), - entry("respyro", FIGHT_PROP_FIRE_SUB_HURT), - entry("resphys", FIGHT_PROP_PHYSICAL_SUB_HURT) - ); - private static final List flatProps = Arrays.asList( - FIGHT_PROP_BASE_HP, FIGHT_PROP_HP, FIGHT_PROP_BASE_ATTACK, FIGHT_PROP_ATTACK, FIGHT_PROP_BASE_DEFENSE, - FIGHT_PROP_DEFENSE, FIGHT_PROP_HEALED_ADD, FIGHT_PROP_CUR_FIRE_ENERGY, FIGHT_PROP_CUR_ELEC_ENERGY, - FIGHT_PROP_CUR_WATER_ENERGY, FIGHT_PROP_CUR_GRASS_ENERGY, FIGHT_PROP_CUR_WIND_ENERGY, FIGHT_PROP_CUR_ICE_ENERGY, - FIGHT_PROP_CUR_ROCK_ENERGY, FIGHT_PROP_CUR_HP, FIGHT_PROP_MAX_HP, FIGHT_PROP_CUR_ATTACK, FIGHT_PROP_CUR_DEFENSE); - private static final Map compoundProperties = Map.ofEntries( - entry(FIGHT_PROP_MAX_HP, new CompoundProperty(FIGHT_PROP_MAX_HP, FIGHT_PROP_BASE_HP, FIGHT_PROP_HP_PERCENT, FIGHT_PROP_HP)), - entry(FIGHT_PROP_CUR_ATTACK, new CompoundProperty(FIGHT_PROP_CUR_ATTACK, FIGHT_PROP_BASE_ATTACK, FIGHT_PROP_ATTACK_PERCENT, FIGHT_PROP_ATTACK)), - entry(FIGHT_PROP_CUR_DEFENSE, new CompoundProperty(FIGHT_PROP_CUR_DEFENSE, FIGHT_PROP_BASE_DEFENSE, FIGHT_PROP_DEFENSE_PERCENT, FIGHT_PROP_DEFENSE)) - ); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getId(), e); - stringMap.put(e.name(), e); - }); - } - - private final int id; - - FightProperty(int id) { - this.id = id; - } - - public static FightProperty getPropById(int value) { - return map.getOrDefault(value, FIGHT_PROP_NONE); - } - - public static FightProperty getPropByName(String name) { - return stringMap.getOrDefault(name, FIGHT_PROP_NONE); - } - - public static FightProperty getPropByShortName(String name) { - return shortNameMap.getOrDefault(name, FIGHT_PROP_NONE); - } - - public static Set getShortNames() { - return shortNameMap.keySet(); - } - - public static CompoundProperty getCompoundProperty(FightProperty result) { - return compoundProperties.get(result); - } - - public static void forEachCompoundProperty(Consumer consumer) { - compoundProperties.values().forEach(consumer); - } - - public static boolean isPercentage(FightProperty prop) { - return !flatProps.contains(prop); - } - - public int getId() { - return id; - } - - @Getter - public static class CompoundProperty { - private final FightProperty result; - private final FightProperty base; - private final FightProperty percent; - private final FightProperty flat; - - public CompoundProperty(FightProperty result, FightProperty base, FightProperty percent, FightProperty flat) { - this.result = result; - this.base = base; - this.percent = percent; - this.flat = flat; - } - } -} +package emu.grasscutter.game.props; + +import static java.util.Map.entry; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Stream; +import lombok.Getter; + +public enum FightProperty { + FIGHT_PROP_NONE(0), + FIGHT_PROP_BASE_HP(1), + FIGHT_PROP_HP(2), + FIGHT_PROP_HP_PERCENT(3), + FIGHT_PROP_BASE_ATTACK(4), + FIGHT_PROP_ATTACK(5), + FIGHT_PROP_ATTACK_PERCENT(6), + FIGHT_PROP_BASE_DEFENSE(7), + FIGHT_PROP_DEFENSE(8), + FIGHT_PROP_DEFENSE_PERCENT(9), + FIGHT_PROP_BASE_SPEED(10), + FIGHT_PROP_SPEED_PERCENT(11), + FIGHT_PROP_HP_MP_PERCENT(12), + FIGHT_PROP_ATTACK_MP_PERCENT(13), + FIGHT_PROP_CRITICAL(20), + FIGHT_PROP_ANTI_CRITICAL(21), + FIGHT_PROP_CRITICAL_HURT(22), + FIGHT_PROP_CHARGE_EFFICIENCY(23), + FIGHT_PROP_ADD_HURT(24), + FIGHT_PROP_SUB_HURT(25), + FIGHT_PROP_HEAL_ADD(26), + FIGHT_PROP_HEALED_ADD(27), + FIGHT_PROP_ELEMENT_MASTERY(28), + FIGHT_PROP_PHYSICAL_SUB_HURT(29), + FIGHT_PROP_PHYSICAL_ADD_HURT(30), + FIGHT_PROP_DEFENCE_IGNORE_RATIO(31), + FIGHT_PROP_DEFENCE_IGNORE_DELTA(32), + FIGHT_PROP_FIRE_ADD_HURT(40), + FIGHT_PROP_ELEC_ADD_HURT(41), + FIGHT_PROP_WATER_ADD_HURT(42), + FIGHT_PROP_GRASS_ADD_HURT(43), + FIGHT_PROP_WIND_ADD_HURT(44), + FIGHT_PROP_ROCK_ADD_HURT(45), + FIGHT_PROP_ICE_ADD_HURT(46), + FIGHT_PROP_HIT_HEAD_ADD_HURT(47), + FIGHT_PROP_FIRE_SUB_HURT(50), + FIGHT_PROP_ELEC_SUB_HURT(51), + FIGHT_PROP_WATER_SUB_HURT(52), + FIGHT_PROP_GRASS_SUB_HURT(53), + FIGHT_PROP_WIND_SUB_HURT(54), + FIGHT_PROP_ROCK_SUB_HURT(55), + FIGHT_PROP_ICE_SUB_HURT(56), + FIGHT_PROP_EFFECT_HIT(60), + FIGHT_PROP_EFFECT_RESIST(61), + FIGHT_PROP_FREEZE_RESIST(62), + FIGHT_PROP_TORPOR_RESIST(63), + FIGHT_PROP_DIZZY_RESIST(64), + FIGHT_PROP_FREEZE_SHORTEN(65), + FIGHT_PROP_TORPOR_SHORTEN(66), + FIGHT_PROP_DIZZY_SHORTEN(67), + FIGHT_PROP_MAX_FIRE_ENERGY(70), + FIGHT_PROP_MAX_ELEC_ENERGY(71), + FIGHT_PROP_MAX_WATER_ENERGY(72), + FIGHT_PROP_MAX_GRASS_ENERGY(73), + FIGHT_PROP_MAX_WIND_ENERGY(74), + FIGHT_PROP_MAX_ICE_ENERGY(75), + FIGHT_PROP_MAX_ROCK_ENERGY(76), + FIGHT_PROP_SKILL_CD_MINUS_RATIO(80), + FIGHT_PROP_SHIELD_COST_MINUS_RATIO(81), + FIGHT_PROP_CUR_FIRE_ENERGY(1000), + FIGHT_PROP_CUR_ELEC_ENERGY(1001), + FIGHT_PROP_CUR_WATER_ENERGY(1002), + FIGHT_PROP_CUR_GRASS_ENERGY(1003), + FIGHT_PROP_CUR_WIND_ENERGY(1004), + FIGHT_PROP_CUR_ICE_ENERGY(1005), + FIGHT_PROP_CUR_ROCK_ENERGY(1006), + FIGHT_PROP_CUR_HP(1010), + FIGHT_PROP_MAX_HP(2000), + FIGHT_PROP_CUR_ATTACK(2001), + FIGHT_PROP_CUR_DEFENSE(2002), + FIGHT_PROP_CUR_SPEED(2003), + FIGHT_PROP_NONEXTRA_ATTACK(3000), + FIGHT_PROP_NONEXTRA_DEFENSE(3001), + FIGHT_PROP_NONEXTRA_CRITICAL(3002), + FIGHT_PROP_NONEXTRA_ANTI_CRITICAL(3003), + FIGHT_PROP_NONEXTRA_CRITICAL_HURT(3004), + FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY(3005), + FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY(3006), + FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT(3007), + FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT(3008), + FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT(3009), + FIGHT_PROP_NONEXTRA_WATER_ADD_HURT(3010), + FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT(3011), + FIGHT_PROP_NONEXTRA_WIND_ADD_HURT(3012), + FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT(3013), + FIGHT_PROP_NONEXTRA_ICE_ADD_HURT(3014), + FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT(3015), + FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT(3016), + FIGHT_PROP_NONEXTRA_WATER_SUB_HURT(3017), + FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT(3018), + FIGHT_PROP_NONEXTRA_WIND_SUB_HURT(3019), + FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT(3020), + FIGHT_PROP_NONEXTRA_ICE_SUB_HURT(3021), + FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO(3022), + FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO(3023), + FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT(3024); + + public static final int[] fightProps = + new int[] { + 1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, + 55, 56, 2000, 2001, 2002, 2003, 1010 + }; + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + // This was originally for relic properties so some names might not be applicable for e.g. + // setstats + private static final Map shortNameMap = + Map.ofEntries( + // Normal relic stats + entry("hp", FIGHT_PROP_HP), + entry("atk", FIGHT_PROP_ATTACK), + entry("def", FIGHT_PROP_DEFENSE), + entry("hp%", FIGHT_PROP_HP_PERCENT), + entry("atk%", FIGHT_PROP_ATTACK_PERCENT), + entry("def%", FIGHT_PROP_DEFENSE_PERCENT), + entry("em", FIGHT_PROP_ELEMENT_MASTERY), + entry("er", FIGHT_PROP_CHARGE_EFFICIENCY), + entry("hb", FIGHT_PROP_HEAL_ADD), + entry("heal", FIGHT_PROP_HEAL_ADD), + entry("cd", FIGHT_PROP_CRITICAL_HURT), + entry("cdmg", FIGHT_PROP_CRITICAL_HURT), + entry("cr", FIGHT_PROP_CRITICAL), + entry("crate", FIGHT_PROP_CRITICAL), + entry("phys%", FIGHT_PROP_PHYSICAL_ADD_HURT), + entry("dendro%", FIGHT_PROP_GRASS_ADD_HURT), + entry("geo%", FIGHT_PROP_ROCK_ADD_HURT), + entry("anemo%", FIGHT_PROP_WIND_ADD_HURT), + entry("hydro%", FIGHT_PROP_WATER_ADD_HURT), + entry("cryo%", FIGHT_PROP_ICE_ADD_HURT), + entry("electro%", FIGHT_PROP_ELEC_ADD_HURT), + entry("pyro%", FIGHT_PROP_FIRE_ADD_HURT), + // Other stats + entry("maxhp", FIGHT_PROP_MAX_HP), + entry("dmg", FIGHT_PROP_ADD_HURT), // This seems to get reset after attacks + entry("cdr", FIGHT_PROP_SKILL_CD_MINUS_RATIO), + entry("heali", FIGHT_PROP_HEALED_ADD), + entry("shield", FIGHT_PROP_SHIELD_COST_MINUS_RATIO), + entry("defi", FIGHT_PROP_DEFENCE_IGNORE_RATIO), + entry("resall", FIGHT_PROP_SUB_HURT), // This seems to get reset after attacks + entry("resanemo", FIGHT_PROP_WIND_SUB_HURT), + entry("rescryo", FIGHT_PROP_ICE_SUB_HURT), + entry("resdendro", FIGHT_PROP_GRASS_SUB_HURT), + entry("reselectro", FIGHT_PROP_ELEC_SUB_HURT), + entry("resgeo", FIGHT_PROP_ROCK_SUB_HURT), + entry("reshydro", FIGHT_PROP_WATER_SUB_HURT), + entry("respyro", FIGHT_PROP_FIRE_SUB_HURT), + entry("resphys", FIGHT_PROP_PHYSICAL_SUB_HURT)); + private static final List flatProps = + Arrays.asList( + FIGHT_PROP_BASE_HP, + FIGHT_PROP_HP, + FIGHT_PROP_BASE_ATTACK, + FIGHT_PROP_ATTACK, + FIGHT_PROP_BASE_DEFENSE, + FIGHT_PROP_DEFENSE, + FIGHT_PROP_HEALED_ADD, + FIGHT_PROP_CUR_FIRE_ENERGY, + FIGHT_PROP_CUR_ELEC_ENERGY, + FIGHT_PROP_CUR_WATER_ENERGY, + FIGHT_PROP_CUR_GRASS_ENERGY, + FIGHT_PROP_CUR_WIND_ENERGY, + FIGHT_PROP_CUR_ICE_ENERGY, + FIGHT_PROP_CUR_ROCK_ENERGY, + FIGHT_PROP_CUR_HP, + FIGHT_PROP_MAX_HP, + FIGHT_PROP_CUR_ATTACK, + FIGHT_PROP_CUR_DEFENSE); + private static final Map compoundProperties = + Map.ofEntries( + entry( + FIGHT_PROP_MAX_HP, + new CompoundProperty( + FIGHT_PROP_MAX_HP, FIGHT_PROP_BASE_HP, FIGHT_PROP_HP_PERCENT, FIGHT_PROP_HP)), + entry( + FIGHT_PROP_CUR_ATTACK, + new CompoundProperty( + FIGHT_PROP_CUR_ATTACK, + FIGHT_PROP_BASE_ATTACK, + FIGHT_PROP_ATTACK_PERCENT, + FIGHT_PROP_ATTACK)), + entry( + FIGHT_PROP_CUR_DEFENSE, + new CompoundProperty( + FIGHT_PROP_CUR_DEFENSE, + FIGHT_PROP_BASE_DEFENSE, + FIGHT_PROP_DEFENSE_PERCENT, + FIGHT_PROP_DEFENSE))); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getId(), e); + stringMap.put(e.name(), e); + }); + } + + private final int id; + + FightProperty(int id) { + this.id = id; + } + + public static FightProperty getPropById(int value) { + return map.getOrDefault(value, FIGHT_PROP_NONE); + } + + public static FightProperty getPropByName(String name) { + return stringMap.getOrDefault(name, FIGHT_PROP_NONE); + } + + public static FightProperty getPropByShortName(String name) { + return shortNameMap.getOrDefault(name, FIGHT_PROP_NONE); + } + + public static Set getShortNames() { + return shortNameMap.keySet(); + } + + public static CompoundProperty getCompoundProperty(FightProperty result) { + return compoundProperties.get(result); + } + + public static void forEachCompoundProperty(Consumer consumer) { + compoundProperties.values().forEach(consumer); + } + + public static boolean isPercentage(FightProperty prop) { + return !flatProps.contains(prop); + } + + public int getId() { + return id; + } + + @Getter + public static class CompoundProperty { + private final FightProperty result; + private final FightProperty base; + private final FightProperty percent; + private final FightProperty flat; + + public CompoundProperty( + FightProperty result, FightProperty base, FightProperty percent, FightProperty flat) { + this.result = result; + this.base = base; + this.percent = percent; + this.flat = flat; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/props/GrowCurve.java b/src/main/java/emu/grasscutter/game/props/GrowCurve.java index e4f6ae362..f6b27a6ea 100644 --- a/src/main/java/emu/grasscutter/game/props/GrowCurve.java +++ b/src/main/java/emu/grasscutter/game/props/GrowCurve.java @@ -1,100 +1,105 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum GrowCurve { - GROW_CURVE_NONE(0), - GROW_CURVE_HP(1), - GROW_CURVE_ATTACK(2), - GROW_CURVE_STAMINA(3), - GROW_CURVE_STRIKE(4), - GROW_CURVE_ANTI_STRIKE(5), - GROW_CURVE_ANTI_STRIKE1(6), - GROW_CURVE_ANTI_STRIKE2(7), - GROW_CURVE_ANTI_STRIKE3(8), - GROW_CURVE_STRIKE_HURT(9), - GROW_CURVE_ELEMENT(10), - GROW_CURVE_KILL_EXP(11), - GROW_CURVE_DEFENSE(12), - GROW_CURVE_ATTACK_BOMB(13), - GROW_CURVE_HP_LITTLEMONSTER(14), - GROW_CURVE_ELEMENT_MASTERY(15), - GROW_CURVE_PROGRESSION(16), - GROW_CURVE_DEFENDING(17), - GROW_CURVE_MHP(18), - GROW_CURVE_MATK(19), - GROW_CURVE_TOWERATK(20), - GROW_CURVE_HP_S5(21), - GROW_CURVE_HP_S4(22), - GROW_CURVE_HP_2(23), - GROW_CURVE_ATTACK_S5(31), - GROW_CURVE_ATTACK_S4(32), - GROW_CURVE_ATTACK_S3(33), - GROW_CURVE_STRIKE_S5(34), - GROW_CURVE_DEFENSE_S5(41), - GROW_CURVE_DEFENSE_S4(42), - GROW_CURVE_ATTACK_101(1101), - GROW_CURVE_ATTACK_102(1102), - GROW_CURVE_ATTACK_103(1103), - GROW_CURVE_ATTACK_104(1104), - GROW_CURVE_ATTACK_105(1105), - GROW_CURVE_ATTACK_201(1201), - GROW_CURVE_ATTACK_202(1202), - GROW_CURVE_ATTACK_203(1203), - GROW_CURVE_ATTACK_204(1204), - GROW_CURVE_ATTACK_205(1205), - GROW_CURVE_ATTACK_301(1301), - GROW_CURVE_ATTACK_302(1302), - GROW_CURVE_ATTACK_303(1303), - GROW_CURVE_ATTACK_304(1304), - GROW_CURVE_ATTACK_305(1305), - GROW_CURVE_CRITICAL_101(2101), - GROW_CURVE_CRITICAL_102(2102), - GROW_CURVE_CRITICAL_103(2103), - GROW_CURVE_CRITICAL_104(2104), - GROW_CURVE_CRITICAL_105(2105), - GROW_CURVE_CRITICAL_201(2201), - GROW_CURVE_CRITICAL_202(2202), - GROW_CURVE_CRITICAL_203(2203), - GROW_CURVE_CRITICAL_204(2204), - GROW_CURVE_CRITICAL_205(2205), - GROW_CURVE_CRITICAL_301(2301), - GROW_CURVE_CRITICAL_302(2302), - GROW_CURVE_CRITICAL_303(2303), - GROW_CURVE_CRITICAL_304(2304), - GROW_CURVE_CRITICAL_305(2305); - - public static final int[] fightProps = new int[]{1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 55, 56, 2000, 2001, 2002, 2003, 1010}; - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getId(), e); - stringMap.put(e.name(), e); - }); - } - - private final int id; - - GrowCurve(int id) { - this.id = id; - } - - public static GrowCurve getPropById(int value) { - return map.getOrDefault(value, GROW_CURVE_NONE); - } - - public static GrowCurve getPropByName(String name) { - return stringMap.getOrDefault(name, GROW_CURVE_NONE); - } - - public int getId() { - return id; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum GrowCurve { + GROW_CURVE_NONE(0), + GROW_CURVE_HP(1), + GROW_CURVE_ATTACK(2), + GROW_CURVE_STAMINA(3), + GROW_CURVE_STRIKE(4), + GROW_CURVE_ANTI_STRIKE(5), + GROW_CURVE_ANTI_STRIKE1(6), + GROW_CURVE_ANTI_STRIKE2(7), + GROW_CURVE_ANTI_STRIKE3(8), + GROW_CURVE_STRIKE_HURT(9), + GROW_CURVE_ELEMENT(10), + GROW_CURVE_KILL_EXP(11), + GROW_CURVE_DEFENSE(12), + GROW_CURVE_ATTACK_BOMB(13), + GROW_CURVE_HP_LITTLEMONSTER(14), + GROW_CURVE_ELEMENT_MASTERY(15), + GROW_CURVE_PROGRESSION(16), + GROW_CURVE_DEFENDING(17), + GROW_CURVE_MHP(18), + GROW_CURVE_MATK(19), + GROW_CURVE_TOWERATK(20), + GROW_CURVE_HP_S5(21), + GROW_CURVE_HP_S4(22), + GROW_CURVE_HP_2(23), + GROW_CURVE_ATTACK_S5(31), + GROW_CURVE_ATTACK_S4(32), + GROW_CURVE_ATTACK_S3(33), + GROW_CURVE_STRIKE_S5(34), + GROW_CURVE_DEFENSE_S5(41), + GROW_CURVE_DEFENSE_S4(42), + GROW_CURVE_ATTACK_101(1101), + GROW_CURVE_ATTACK_102(1102), + GROW_CURVE_ATTACK_103(1103), + GROW_CURVE_ATTACK_104(1104), + GROW_CURVE_ATTACK_105(1105), + GROW_CURVE_ATTACK_201(1201), + GROW_CURVE_ATTACK_202(1202), + GROW_CURVE_ATTACK_203(1203), + GROW_CURVE_ATTACK_204(1204), + GROW_CURVE_ATTACK_205(1205), + GROW_CURVE_ATTACK_301(1301), + GROW_CURVE_ATTACK_302(1302), + GROW_CURVE_ATTACK_303(1303), + GROW_CURVE_ATTACK_304(1304), + GROW_CURVE_ATTACK_305(1305), + GROW_CURVE_CRITICAL_101(2101), + GROW_CURVE_CRITICAL_102(2102), + GROW_CURVE_CRITICAL_103(2103), + GROW_CURVE_CRITICAL_104(2104), + GROW_CURVE_CRITICAL_105(2105), + GROW_CURVE_CRITICAL_201(2201), + GROW_CURVE_CRITICAL_202(2202), + GROW_CURVE_CRITICAL_203(2203), + GROW_CURVE_CRITICAL_204(2204), + GROW_CURVE_CRITICAL_205(2205), + GROW_CURVE_CRITICAL_301(2301), + GROW_CURVE_CRITICAL_302(2302), + GROW_CURVE_CRITICAL_303(2303), + GROW_CURVE_CRITICAL_304(2304), + GROW_CURVE_CRITICAL_305(2305); + + public static final int[] fightProps = + new int[] { + 1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, + 55, 56, 2000, 2001, 2002, 2003, 1010 + }; + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getId(), e); + stringMap.put(e.name(), e); + }); + } + + private final int id; + + GrowCurve(int id) { + this.id = id; + } + + public static GrowCurve getPropById(int value) { + return map.getOrDefault(value, GROW_CURVE_NONE); + } + + public static GrowCurve getPropByName(String name) { + return stringMap.getOrDefault(name, GROW_CURVE_NONE); + } + + public int getId() { + return id; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAcceptQuest.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAcceptQuest.java index 292e2f775..4a51b6859 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAcceptQuest.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAcceptQuest.java @@ -1,19 +1,19 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAcceptQuest extends ItemUseInt { - public ItemUseAcceptQuest(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ACCEPT_QUEST; - } - - @Override - public boolean useItem(UseItemParams params) { - return (params.player.getQuestManager().addQuest(this.i) != null); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAcceptQuest extends ItemUseInt { + public ItemUseAcceptQuest(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ACCEPT_QUEST; + } + + @Override + public boolean useItem(UseItemParams params) { + return (params.player.getQuestManager().addQuest(this.i) != null); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAction.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAction.java index e20eb112a..09a232a17 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAction.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAction.java @@ -1,80 +1,83 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.data.common.ItemUseData; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAction { - public static ItemUseAction fromItemUseData(ItemUseData data) { - var useParam = data.getUseParam(); - return switch (data.getUseOp()) { - case ITEM_USE_NONE -> null; - // Uprade materials - no direct usage - case ITEM_USE_ADD_EXP -> new ItemUseAddExp(useParam); - case ITEM_USE_ADD_RELIQUARY_EXP -> new ItemUseAddReliquaryExp(useParam); - case ITEM_USE_ADD_WEAPON_EXP -> new ItemUseAddWeaponExp(useParam); - // Energy pickups - case ITEM_USE_ADD_ALL_ENERGY -> new ItemUseAddAllEnergy(useParam); - case ITEM_USE_ADD_ELEM_ENERGY -> new ItemUseAddElemEnergy(useParam); - // Give items - case ITEM_USE_ADD_ITEM -> new ItemUseAddItem(useParam); - case ITEM_USE_GAIN_AVATAR -> new ItemUseGainAvatar(useParam); - case ITEM_USE_GAIN_COSTUME -> new ItemUseGainCostume(useParam); // TODO - real success/fail - case ITEM_USE_GAIN_FLYCLOAK -> new ItemUseGainFlycloak(useParam); // TODO - real success/fail - case ITEM_USE_GAIN_NAME_CARD -> new ItemUseGainNameCard(useParam); - case ITEM_USE_CHEST_SELECT_ITEM -> new ItemUseChestSelectItem(useParam); - case ITEM_USE_ADD_SELECT_ITEM -> new ItemUseAddSelectItem(useParam); - case ITEM_USE_GRANT_SELECT_REWARD -> new ItemUseGrantSelectReward(useParam); - case ITEM_USE_COMBINE_ITEM -> new ItemUseCombineItem(useParam); - case ITEM_USE_OPEN_RANDOM_CHEST -> new ItemUseOpenRandomChest(useParam); - // Food effects - case ITEM_USE_RELIVE_AVATAR -> - new ItemUseReliveAvatar(useParam); // First action for revival food. Should we worry about race conditions in parallel streams? - case ITEM_USE_ADD_CUR_HP -> new ItemUseAddCurHp(useParam); - case ITEM_USE_ADD_CUR_STAMINA -> new ItemUseAddCurStamina(useParam); - case ITEM_USE_ADD_SERVER_BUFF -> new ItemUseAddServerBuff(useParam); - case ITEM_USE_MAKE_GADGET -> new ItemUseMakeGadget(useParam); - // Unlock recipes - TODO: allow scheduling packets for after recipe is removed - case ITEM_USE_UNLOCK_COMBINE -> new ItemUseUnlockCombine(useParam); - case ITEM_USE_UNLOCK_CODEX -> new ItemUseUnlockCodex(useParam); // TODO: No backend for this yet - case ITEM_USE_UNLOCK_COOK_RECIPE -> new ItemUseUnlockCookRecipe(useParam); - case ITEM_USE_UNLOCK_FORGE -> new ItemUseUnlockForge(useParam); - case ITEM_USE_UNLOCK_FURNITURE_FORMULA -> new ItemUseUnlockFurnitureFormula(useParam); - case ITEM_USE_UNLOCK_FURNITURE_SUITE -> new ItemUseUnlockFurnitureSuite(useParam); - case ITEM_USE_UNLOCK_HOME_MODULE -> new ItemUseUnlockHomeModule(useParam); // No backend for this yet - case ITEM_USE_UNLOCK_HOME_BGM -> new ItemUseUnlockHomeBgm(useParam); - // Account things - case ITEM_USE_ACCEPT_QUEST -> new ItemUseAcceptQuest(useParam); - case ITEM_USE_GAIN_CARD_PRODUCT -> new ItemUseGainCardProduct(useParam); - case ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL -> - new ItemUseUnlockPaidBattlePassNormal(useParam); // TODO: add paid BP - - // Unused in current resources - case ITEM_USE_DEL_SERVER_BUFF -> null; - case ITEM_USE_ADD_BIG_TALENT_POINT -> null; - case ITEM_USE_GAIN_RESIN_CARD_PRODUCT -> null; - case ITEM_USE_TRIGGER_ABILITY -> null; - case ITEM_USE_ADD_TREASURE_MAP_BONUS_REGION_FRAGMENT -> null; - // Used in current resources but no point yet - case ITEM_USE_ADD_PERSIST_STAMINA -> null; // [int amount] one Test item - case ITEM_USE_ADD_TEMPORARY_STAMINA -> null; // [int amount] one Test item - case ITEM_USE_ADD_DUNGEON_COND_TIME -> null; // [int 1, int 15 or 20] - minigame shards - case ITEM_USE_ADD_CHANNELLER_SLAB_BUFF -> null; // [int] minigame buffs - case ITEM_USE_ADD_REGIONAL_PLAY_VAR -> null; // [String, int] - coral butterfly effect - }; - } - - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_NONE; - } - - public boolean useItem(UseItemParams params) { - // An item must return true on at least one of its actions to count as successfully used. - // If all of the actions return false, the item will not be consumed from inventory. - return false; - } - - public boolean postUseItem(UseItemParams params) { - // This is run after the item has been consumed from inventory. - return false; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.data.common.ItemUseData; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAction { + public static ItemUseAction fromItemUseData(ItemUseData data) { + var useParam = data.getUseParam(); + return switch (data.getUseOp()) { + case ITEM_USE_NONE -> null; + // Uprade materials - no direct usage + case ITEM_USE_ADD_EXP -> new ItemUseAddExp(useParam); + case ITEM_USE_ADD_RELIQUARY_EXP -> new ItemUseAddReliquaryExp(useParam); + case ITEM_USE_ADD_WEAPON_EXP -> new ItemUseAddWeaponExp(useParam); + // Energy pickups + case ITEM_USE_ADD_ALL_ENERGY -> new ItemUseAddAllEnergy(useParam); + case ITEM_USE_ADD_ELEM_ENERGY -> new ItemUseAddElemEnergy(useParam); + // Give items + case ITEM_USE_ADD_ITEM -> new ItemUseAddItem(useParam); + case ITEM_USE_GAIN_AVATAR -> new ItemUseGainAvatar(useParam); + case ITEM_USE_GAIN_COSTUME -> new ItemUseGainCostume(useParam); // TODO - real success/fail + case ITEM_USE_GAIN_FLYCLOAK -> new ItemUseGainFlycloak(useParam); // TODO - real success/fail + case ITEM_USE_GAIN_NAME_CARD -> new ItemUseGainNameCard(useParam); + case ITEM_USE_CHEST_SELECT_ITEM -> new ItemUseChestSelectItem(useParam); + case ITEM_USE_ADD_SELECT_ITEM -> new ItemUseAddSelectItem(useParam); + case ITEM_USE_GRANT_SELECT_REWARD -> new ItemUseGrantSelectReward(useParam); + case ITEM_USE_COMBINE_ITEM -> new ItemUseCombineItem(useParam); + case ITEM_USE_OPEN_RANDOM_CHEST -> new ItemUseOpenRandomChest(useParam); + // Food effects + case ITEM_USE_RELIVE_AVATAR -> new ItemUseReliveAvatar( + useParam); // First action for revival food. Should we worry about race conditions in + // parallel streams? + case ITEM_USE_ADD_CUR_HP -> new ItemUseAddCurHp(useParam); + case ITEM_USE_ADD_CUR_STAMINA -> new ItemUseAddCurStamina(useParam); + case ITEM_USE_ADD_SERVER_BUFF -> new ItemUseAddServerBuff(useParam); + case ITEM_USE_MAKE_GADGET -> new ItemUseMakeGadget(useParam); + // Unlock recipes - TODO: allow scheduling packets for after recipe is removed + case ITEM_USE_UNLOCK_COMBINE -> new ItemUseUnlockCombine(useParam); + case ITEM_USE_UNLOCK_CODEX -> new ItemUseUnlockCodex( + useParam); // TODO: No backend for this yet + case ITEM_USE_UNLOCK_COOK_RECIPE -> new ItemUseUnlockCookRecipe(useParam); + case ITEM_USE_UNLOCK_FORGE -> new ItemUseUnlockForge(useParam); + case ITEM_USE_UNLOCK_FURNITURE_FORMULA -> new ItemUseUnlockFurnitureFormula(useParam); + case ITEM_USE_UNLOCK_FURNITURE_SUITE -> new ItemUseUnlockFurnitureSuite(useParam); + case ITEM_USE_UNLOCK_HOME_MODULE -> new ItemUseUnlockHomeModule( + useParam); // No backend for this yet + case ITEM_USE_UNLOCK_HOME_BGM -> new ItemUseUnlockHomeBgm(useParam); + // Account things + case ITEM_USE_ACCEPT_QUEST -> new ItemUseAcceptQuest(useParam); + case ITEM_USE_GAIN_CARD_PRODUCT -> new ItemUseGainCardProduct(useParam); + case ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL -> new ItemUseUnlockPaidBattlePassNormal( + useParam); // TODO: add paid BP + + // Unused in current resources + case ITEM_USE_DEL_SERVER_BUFF -> null; + case ITEM_USE_ADD_BIG_TALENT_POINT -> null; + case ITEM_USE_GAIN_RESIN_CARD_PRODUCT -> null; + case ITEM_USE_TRIGGER_ABILITY -> null; + case ITEM_USE_ADD_TREASURE_MAP_BONUS_REGION_FRAGMENT -> null; + // Used in current resources but no point yet + case ITEM_USE_ADD_PERSIST_STAMINA -> null; // [int amount] one Test item + case ITEM_USE_ADD_TEMPORARY_STAMINA -> null; // [int amount] one Test item + case ITEM_USE_ADD_DUNGEON_COND_TIME -> null; // [int 1, int 15 or 20] - minigame shards + case ITEM_USE_ADD_CHANNELLER_SLAB_BUFF -> null; // [int] minigame buffs + case ITEM_USE_ADD_REGIONAL_PLAY_VAR -> null; // [String, int] - coral butterfly effect + }; + } + + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_NONE; + } + + public boolean useItem(UseItemParams params) { + // An item must return true on at least one of its actions to count as successfully used. + // If all of the actions return false, the item will not be consumed from inventory. + return false; + } + + public boolean postUseItem(UseItemParams params) { + // This is run after the item has been consumed from inventory. + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddAllEnergy.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddAllEnergy.java index 4021e4bcb..6642d8af8 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddAllEnergy.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddAllEnergy.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddAllEnergy extends ItemUseAddEnergy { - private float energy = 0f; - - public ItemUseAddAllEnergy(String[] useParam) { - try { - this.energy = Float.parseFloat(useParam[0]); - } catch (Exception ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_ALL_ENERGY; - } - - public float getAddEnergy(ElementType avatarElement) { - return this.energy; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddAllEnergy extends ItemUseAddEnergy { + private float energy = 0f; + + public ItemUseAddAllEnergy(String[] useParam) { + try { + this.energy = Float.parseFloat(useParam[0]); + } catch (Exception ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_ALL_ENERGY; + } + + public float getAddEnergy(ElementType avatarElement) { + return this.energy; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurHp.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurHp.java index ac9f84ee8..84c036506 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurHp.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurHp.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddCurHp extends ItemUseInt { - private final String icon; - - public ItemUseAddCurHp(String[] useParam) { - super(useParam); - this.icon = useParam[1]; - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_CUR_HP; - } - - @Override - public boolean useItem(UseItemParams params) { - return (params.targetAvatar.getAsEntity().heal(params.count * this.i) > 0.01); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddCurHp extends ItemUseInt { + private final String icon; + + public ItemUseAddCurHp(String[] useParam) { + super(useParam); + this.icon = useParam[1]; + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_CUR_HP; + } + + @Override + public boolean useItem(UseItemParams params) { + return (params.targetAvatar.getAsEntity().heal(params.count * this.i) > 0.01); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurStamina.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurStamina.java index a591c9feb..69cc9911d 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurStamina.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddCurStamina.java @@ -1,19 +1,19 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddCurStamina extends ItemUseInt { - public ItemUseAddCurStamina(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_CUR_STAMINA; - } - - @Override - public boolean useItem(UseItemParams params) { - return params.player.getStaminaManager().addCurrentStamina(this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddCurStamina extends ItemUseInt { + public ItemUseAddCurStamina(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_CUR_STAMINA; + } + + @Override + public boolean useItem(UseItemParams params) { + return params.player.getStaminaManager().addCurrentStamina(this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddElemEnergy.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddElemEnergy.java index 642b27682..855a00b81 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddElemEnergy.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddElemEnergy.java @@ -1,34 +1,34 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddElemEnergy extends ItemUseAddEnergy { - private ElementType element = ElementType.None; - private float elemEnergy = 0f; - private float otherEnergy = 0f; - - public ItemUseAddElemEnergy(String[] useParam) { - try { - this.element = ElementType.getTypeByValue(Integer.parseInt(useParam[0])); - } catch (Exception ignored) { - } - try { - this.elemEnergy = Float.parseFloat(useParam[1]); - } catch (Exception ignored) { - } - try { - this.otherEnergy = Float.parseFloat(useParam[2]); - } catch (Exception ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_ELEM_ENERGY; - } - - public float getAddEnergy(ElementType avatarElement) { - return (avatarElement == this.element) ? this.elemEnergy : this.otherEnergy; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddElemEnergy extends ItemUseAddEnergy { + private ElementType element = ElementType.None; + private float elemEnergy = 0f; + private float otherEnergy = 0f; + + public ItemUseAddElemEnergy(String[] useParam) { + try { + this.element = ElementType.getTypeByValue(Integer.parseInt(useParam[0])); + } catch (Exception ignored) { + } + try { + this.elemEnergy = Float.parseFloat(useParam[1]); + } catch (Exception ignored) { + } + try { + this.otherEnergy = Float.parseFloat(useParam[2]); + } catch (Exception ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_ELEM_ENERGY; + } + + public float getAddEnergy(ElementType avatarElement) { + return (avatarElement == this.element) ? this.elemEnergy : this.otherEnergy; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddEnergy.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddEnergy.java index 6f3074205..149ef3bbd 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddEnergy.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddEnergy.java @@ -1,61 +1,62 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.ElementType; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; - -public abstract class ItemUseAddEnergy extends ItemUseAction { - public abstract float getAddEnergy(ElementType avatarElement); - - public float getAddEnergy(AvatarSkillDepotData depot) { - if (depot == null) return 0f; - var element = depot.getElementType(); - if (element == null) return 0f; - return this.getAddEnergy(element); - } - - @Override - public boolean useItem(UseItemParams params) { - var teamManager = params.player.getTeamManager(); - return switch (params.itemUseTarget) { - case ITEM_USE_TARGET_CUR_AVATAR -> { - this.addEnergy(teamManager.getCurrentAvatarEntity().getAvatar(), params.count); - yield true; // Always consume elem balls - } - case ITEM_USE_TARGET_CUR_TEAM -> { - var activeTeam = teamManager.getActiveTeam(); - // On-field vs off-field multiplier. - // The on-field character gets full amount, off-field characters get less depending on the team size. - final float offFieldRatio = switch (activeTeam.size()) { - case 2 -> 0.8f; - case 3 -> 0.7f; - default -> 0.6f; - }; - final int currentCharacterIndex = teamManager.getCurrentCharacterIndex(); - - // Add energy to every team member. - for (int i = 0; i < activeTeam.size(); i++) { - var avatar = activeTeam.get(i).getAvatar(); - if (i == currentCharacterIndex) - this.addEnergy(avatar, params.count); - else - this.addEnergy(avatar, params.count * offFieldRatio); - } - - yield true; // Always consume elem balls - } - case ITEM_USE_TARGET_SPECIFY_AVATAR, ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR, ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR -> - this.addEnergy(params.targetAvatar, params.count); // Targeted items might care about this - case ITEM_USE_TARGET_NONE -> false; - }; - } - - private boolean addEnergy(Avatar avatar, float multiplier) { - float energy = this.getAddEnergy(avatar.getSkillDepot()) * multiplier; - if (energy < 0.01f) - return false; - avatar.getAsEntity().addEnergy(energy, PropChangeReason.PROP_CHANGE_REASON_ENERGY_BALL); - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; + +public abstract class ItemUseAddEnergy extends ItemUseAction { + public abstract float getAddEnergy(ElementType avatarElement); + + public float getAddEnergy(AvatarSkillDepotData depot) { + if (depot == null) return 0f; + var element = depot.getElementType(); + if (element == null) return 0f; + return this.getAddEnergy(element); + } + + @Override + public boolean useItem(UseItemParams params) { + var teamManager = params.player.getTeamManager(); + return switch (params.itemUseTarget) { + case ITEM_USE_TARGET_CUR_AVATAR -> { + this.addEnergy(teamManager.getCurrentAvatarEntity().getAvatar(), params.count); + yield true; // Always consume elem balls + } + case ITEM_USE_TARGET_CUR_TEAM -> { + var activeTeam = teamManager.getActiveTeam(); + // On-field vs off-field multiplier. + // The on-field character gets full amount, off-field characters get less depending on the + // team size. + final float offFieldRatio = + switch (activeTeam.size()) { + case 2 -> 0.8f; + case 3 -> 0.7f; + default -> 0.6f; + }; + final int currentCharacterIndex = teamManager.getCurrentCharacterIndex(); + + // Add energy to every team member. + for (int i = 0; i < activeTeam.size(); i++) { + var avatar = activeTeam.get(i).getAvatar(); + if (i == currentCharacterIndex) this.addEnergy(avatar, params.count); + else this.addEnergy(avatar, params.count * offFieldRatio); + } + + yield true; // Always consume elem balls + } + case ITEM_USE_TARGET_SPECIFY_AVATAR, + ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR, + ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR -> this.addEnergy( + params.targetAvatar, params.count); // Targeted items might care about this + case ITEM_USE_TARGET_NONE -> false; + }; + } + + private boolean addEnergy(Avatar avatar, float multiplier) { + float energy = this.getAddEnergy(avatar.getSkillDepot()) * multiplier; + if (energy < 0.01f) return false; + avatar.getAsEntity().addEnergy(energy, PropChangeReason.PROP_CHANGE_REASON_ENERGY_BALL); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddExp.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddExp.java index 03565bdc7..0bdd1404b 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddExp.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddExp.java @@ -1,18 +1,18 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddExp extends ItemUseInt { - public ItemUseAddExp(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_EXP; - } - - public int getExp() { - return this.i; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddExp extends ItemUseInt { + public ItemUseAddExp(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_EXP; + } + + public int getExp() { + return this.i; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddItem.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddItem.java index aa04db0c4..6820c94b1 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddItem.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddItem.java @@ -1,25 +1,25 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddItem extends ItemUseInt { - private int count = 0; - - public ItemUseAddItem(String[] useParam) { - super(useParam); - try { - this.count = Integer.parseInt(useParam[1]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_ITEM; - } - - @Override - public boolean useItem(UseItemParams params) { - return params.player.getInventory().addItem(this.i, this.count * params.count); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddItem extends ItemUseInt { + private int count = 0; + + public ItemUseAddItem(String[] useParam) { + super(useParam); + try { + this.count = Integer.parseInt(useParam[1]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_ITEM; + } + + @Override + public boolean useItem(UseItemParams params) { + return params.player.getInventory().addItem(this.i, this.count * params.count); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddReliquaryExp.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddReliquaryExp.java index c8b627b14..6d26372dd 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddReliquaryExp.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddReliquaryExp.java @@ -1,14 +1,14 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddReliquaryExp extends ItemUseAddExp { - public ItemUseAddReliquaryExp(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_RELIQUARY_EXP; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddReliquaryExp extends ItemUseAddExp { + public ItemUseAddReliquaryExp(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_RELIQUARY_EXP; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddSelectItem.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddSelectItem.java index 6c22f6bed..80efb272b 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddSelectItem.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddSelectItem.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddSelectItem extends ItemUseSelectItems { - public ItemUseAddSelectItem(String[] useParam) { - String[] options = useParam[0].split(","); - this.optionItemIds = new int[options.length]; - for (int i = 0; i < options.length; i++) { - try { - this.optionItemIds[i] = Integer.parseInt(options[i]); - } catch (NumberFormatException ignored) { - this.optionItemIds[i] = INVALID; - } - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddSelectItem extends ItemUseSelectItems { + public ItemUseAddSelectItem(String[] useParam) { + String[] options = useParam[0].split(","); + this.optionItemIds = new int[options.length]; + for (int i = 0; i < options.length; i++) { + try { + this.optionItemIds[i] = Integer.parseInt(options[i]); + } catch (NumberFormatException ignored) { + this.optionItemIds[i] = INVALID; + } + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddServerBuff.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddServerBuff.java index 1f11d13e4..11845dd25 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddServerBuff.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddServerBuff.java @@ -1,25 +1,25 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddServerBuff extends ItemUseInt { - private int duration = 0; - - public ItemUseAddServerBuff(String[] useParam) { - super(useParam); - try { - this.duration = Integer.parseInt(useParam[1]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_SERVER_BUFF; - } - - @Override - public boolean useItem(UseItemParams params) { - return params.player.getBuffManager().addBuff(this.i, this.duration, params.targetAvatar); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddServerBuff extends ItemUseInt { + private int duration = 0; + + public ItemUseAddServerBuff(String[] useParam) { + super(useParam); + try { + this.duration = Integer.parseInt(useParam[1]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_SERVER_BUFF; + } + + @Override + public boolean useItem(UseItemParams params) { + return params.player.getBuffManager().addBuff(this.i, this.duration, params.targetAvatar); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddWeaponExp.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddWeaponExp.java index c98178c76..f2885562c 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddWeaponExp.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseAddWeaponExp.java @@ -1,14 +1,14 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseAddWeaponExp extends ItemUseAddExp { - public ItemUseAddWeaponExp(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_WEAPON_EXP; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseAddWeaponExp extends ItemUseAddExp { + public ItemUseAddWeaponExp(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_WEAPON_EXP; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseChestSelectItem.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseChestSelectItem.java index 423721c2d..ee9f8b4bb 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseChestSelectItem.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseChestSelectItem.java @@ -1,37 +1,38 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseChestSelectItem extends ItemUseSelectItems { - private final int[] optionItemCounts; - - public ItemUseChestSelectItem(String[] useParam) { - String[] options = useParam[0].split(","); - this.optionItemIds = new int[options.length]; - this.optionItemCounts = new int[options.length]; - for (int i = 0; i < options.length; i++) { - String[] optionParts = options[i].split(":"); - try { - this.optionItemIds[i] = Integer.parseInt(optionParts[0]); - } catch (NumberFormatException ignored) { - this.optionItemIds[i] = INVALID; - } - try { - this.optionItemCounts[i] = Integer.parseInt(optionParts[1]); - } catch (NumberFormatException ignored) { - this.optionItemCounts[i] = INVALID; - } - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_CHEST_SELECT_ITEM; - } - - @Override - protected int getItemCount(int index) { - if ((optionItemCounts == null) || (index < 0) || (index > optionItemCounts.length)) return INVALID; - return this.optionItemCounts[index]; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseChestSelectItem extends ItemUseSelectItems { + private final int[] optionItemCounts; + + public ItemUseChestSelectItem(String[] useParam) { + String[] options = useParam[0].split(","); + this.optionItemIds = new int[options.length]; + this.optionItemCounts = new int[options.length]; + for (int i = 0; i < options.length; i++) { + String[] optionParts = options[i].split(":"); + try { + this.optionItemIds[i] = Integer.parseInt(optionParts[0]); + } catch (NumberFormatException ignored) { + this.optionItemIds[i] = INVALID; + } + try { + this.optionItemCounts[i] = Integer.parseInt(optionParts[1]); + } catch (NumberFormatException ignored) { + this.optionItemCounts[i] = INVALID; + } + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_CHEST_SELECT_ITEM; + } + + @Override + protected int getItemCount(int index) { + if ((optionItemCounts == null) || (index < 0) || (index > optionItemCounts.length)) + return INVALID; + return this.optionItemCounts[index]; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseCombineItem.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseCombineItem.java index 801b790b6..a538e435b 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseCombineItem.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseCombineItem.java @@ -1,31 +1,31 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseCombineItem extends ItemUseInt { - private int resultId = 0; - private int resultCount = 1; - - public ItemUseCombineItem(String[] useParam) { - super(useParam); - try { - this.resultId = Integer.parseInt(useParam[1]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - try { - this.resultCount = Integer.parseInt(useParam[2]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_COMBINE_ITEM; - } - - @Override - public boolean useItem(UseItemParams params) { - if (params.count != this.i) return false; // Wrong amount of fragments supplied! - return params.player.getInventory().addItem(this.resultId, this.resultCount); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseCombineItem extends ItemUseInt { + private int resultId = 0; + private int resultCount = 1; + + public ItemUseCombineItem(String[] useParam) { + super(useParam); + try { + this.resultId = Integer.parseInt(useParam[1]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + try { + this.resultCount = Integer.parseInt(useParam[2]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_COMBINE_ITEM; + } + + @Override + public boolean useItem(UseItemParams params) { + if (params.count != this.i) return false; // Wrong amount of fragments supplied! + return params.player.getInventory().addItem(this.resultId, this.resultCount); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainAvatar.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainAvatar.java index 3ddef564e..02537e37d 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainAvatar.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainAvatar.java @@ -1,50 +1,51 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.ItemUseOp; -import emu.grasscutter.game.systems.InventorySystem; - -import java.util.Optional; - -public class ItemUseGainAvatar extends ItemUseInt { - private int level = 1; - private int constellation = 0; - - public ItemUseGainAvatar(String[] useParam) { - super(useParam); - try { - this.level = Integer.parseInt(useParam[1]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - try { - this.constellation = Integer.parseInt(useParam[2]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_GAIN_AVATAR; - } - - @Override - public boolean useItem(UseItemParams params) { - int haveConstellation = InventorySystem.checkPlayerAvatarConstellationLevel(params.player, this.i); - if (haveConstellation == -2 || haveConstellation >= 6) { - return false; - } else if (haveConstellation == -1) { - var avatar = new Avatar(this.i); - avatar.setLevel(this.level); - avatar.forceConstellationLevel(this.constellation); - avatar.recalcStats(); - params.player.addAvatar(avatar); - return true; - } else { - int itemId = Optional.ofNullable(params.player.getAvatars().getAvatarById(this.i)) - .map(Avatar::getSkillDepot) - .map(depot -> depot.getTalentCostItemId()) - .orElse((this.i % 1000) + 100); - return params.player.getInventory().addItem(itemId); - } - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.ItemUseOp; +import emu.grasscutter.game.systems.InventorySystem; +import java.util.Optional; + +public class ItemUseGainAvatar extends ItemUseInt { + private int level = 1; + private int constellation = 0; + + public ItemUseGainAvatar(String[] useParam) { + super(useParam); + try { + this.level = Integer.parseInt(useParam[1]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + try { + this.constellation = Integer.parseInt(useParam[2]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_GAIN_AVATAR; + } + + @Override + public boolean useItem(UseItemParams params) { + int haveConstellation = + InventorySystem.checkPlayerAvatarConstellationLevel(params.player, this.i); + if (haveConstellation == -2 || haveConstellation >= 6) { + return false; + } else if (haveConstellation == -1) { + var avatar = new Avatar(this.i); + avatar.setLevel(this.level); + avatar.forceConstellationLevel(this.constellation); + avatar.recalcStats(); + params.player.addAvatar(avatar); + return true; + } else { + int itemId = + Optional.ofNullable(params.player.getAvatars().getAvatarById(this.i)) + .map(Avatar::getSkillDepot) + .map(depot -> depot.getTalentCostItemId()) + .orElse((this.i % 1000) + 100); + return params.player.getInventory().addItem(itemId); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCardProduct.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCardProduct.java index 51671eca6..12ab66ddf 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCardProduct.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCardProduct.java @@ -1,18 +1,17 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseGainCardProduct extends ItemUseAction { - public ItemUseGainCardProduct(String[] useParam) { - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_GAIN_CARD_PRODUCT; - } - - @Override - public boolean useItem(UseItemParams params) { - return params.player.rechargeMoonCard(); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseGainCardProduct extends ItemUseAction { + public ItemUseGainCardProduct(String[] useParam) {} + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_GAIN_CARD_PRODUCT; + } + + @Override + public boolean useItem(UseItemParams params) { + return params.player.rechargeMoonCard(); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCostume.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCostume.java index 61980af75..4dd2709e7 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCostume.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainCostume.java @@ -1,23 +1,23 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseGainCostume extends ItemUseInt { - public ItemUseGainCostume(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_GAIN_COSTUME; - } - - @Override - public boolean useItem(UseItemParams params) { - if (GameData.getAvatarCostumeDataMap().containsKey(this.i)) { - params.player.addCostume(this.i); - } - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseGainCostume extends ItemUseInt { + public ItemUseGainCostume(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_GAIN_COSTUME; + } + + @Override + public boolean useItem(UseItemParams params) { + if (GameData.getAvatarCostumeDataMap().containsKey(this.i)) { + params.player.addCostume(this.i); + } + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainFlycloak.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainFlycloak.java index 019ea6023..80a2d6e51 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainFlycloak.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainFlycloak.java @@ -1,23 +1,23 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseGainFlycloak extends ItemUseInt { - public ItemUseGainFlycloak(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_GAIN_FLYCLOAK; - } - - @Override - public boolean useItem(UseItemParams params) { - if (GameData.getAvatarFlycloakDataMap().containsKey(this.i)) { - params.player.addFlycloak(this.i); - } - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseGainFlycloak extends ItemUseInt { + public ItemUseGainFlycloak(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_GAIN_FLYCLOAK; + } + + @Override + public boolean useItem(UseItemParams params) { + if (GameData.getAvatarFlycloakDataMap().containsKey(this.i)) { + params.player.addFlycloak(this.i); + } + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainNameCard.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainNameCard.java index 9ba2895cd..4d173e64e 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainNameCard.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGainNameCard.java @@ -1,19 +1,18 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseGainNameCard extends ItemUseAction { - public ItemUseGainNameCard(String[] useParam) { - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_GAIN_NAME_CARD; - } - - @Override - public boolean useItem(UseItemParams params) { - params.player.addNameCard(params.usedItemId); - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseGainNameCard extends ItemUseAction { + public ItemUseGainNameCard(String[] useParam) {} + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_GAIN_NAME_CARD; + } + + @Override + public boolean useItem(UseItemParams params) { + params.player.addNameCard(params.usedItemId); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGrantSelectReward.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGrantSelectReward.java index 9dcb6d387..5cf35107f 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGrantSelectReward.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseGrantSelectReward.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseGrantSelectReward extends ItemUseSelectItems { - public ItemUseGrantSelectReward(String[] useParam) { - String[] options = useParam[0].split(","); - this.optionItemIds = new int[options.length]; - for (int i = 0; i < options.length; i++) { - try { - this.optionItemIds[i] = Integer.parseInt(options[i]); - } catch (NumberFormatException ignored) { - this.optionItemIds[i] = INVALID; - } - } - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseGrantSelectReward extends ItemUseSelectItems { + public ItemUseGrantSelectReward(String[] useParam) { + String[] options = useParam[0].split(","); + this.optionItemIds = new int[options.length]; + for (int i = 0; i < options.length; i++) { + try { + this.optionItemIds[i] = Integer.parseInt(options[i]); + } catch (NumberFormatException ignored) { + this.optionItemIds[i] = INVALID; + } + } + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseInt.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseInt.java index 03b458920..342d1962c 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseInt.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseInt.java @@ -1,15 +1,14 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import lombok.Getter; - -public abstract class ItemUseInt extends ItemUseAction { - @Getter - protected int i = 0; - - public ItemUseInt(String[] useParam) { - try { - this.i = Integer.parseInt(useParam[0]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { - } - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import lombok.Getter; + +public abstract class ItemUseInt extends ItemUseAction { + @Getter protected int i = 0; + + public ItemUseInt(String[] useParam) { + try { + this.i = Integer.parseInt(useParam[0]); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { + } + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseMakeGadget.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseMakeGadget.java index d7b2062ec..be3292a4b 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseMakeGadget.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseMakeGadget.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.entity.EntityVehicle; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseMakeGadget extends ItemUseInt { - public ItemUseMakeGadget(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_MAKE_GADGET; - } - - @Override - public boolean useItem(UseItemParams params) { - var player = params.player; - var scene = player.getScene(); - var pos = player.getPosition().nearby2d(1f); - var rot = player.getRotation().clone(); - var e = new EntityVehicle(scene, player, this.i, 0, pos, rot); - scene.addEntity(e); - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseMakeGadget extends ItemUseInt { + public ItemUseMakeGadget(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_MAKE_GADGET; + } + + @Override + public boolean useItem(UseItemParams params) { + var player = params.player; + var scene = player.getScene(); + var pos = player.getPosition().nearby2d(1f); + var rot = player.getRotation().clone(); + var e = new EntityVehicle(scene, player, this.i, 0, pos, rot); + scene.addEntity(e); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseOpenRandomChest.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseOpenRandomChest.java index 984c0e775..662a6e818 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseOpenRandomChest.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseOpenRandomChest.java @@ -1,28 +1,27 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseOpenRandomChest extends ItemUseInt { - public ItemUseOpenRandomChest(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_OPEN_RANDOM_CHEST; - } - - @Override - public boolean useItem(UseItemParams params) { // cash shop material bundles - var data = params.player.getServer().getShopSystem().getShopChestData(this.i); - if (data == null) - return false; - var rewardItems = data.stream().map(GameItem::new).toList(); - if (!rewardItems.isEmpty()) { - params.player.getInventory().addItems(rewardItems, ActionReason.Shop); - } - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseOpenRandomChest extends ItemUseInt { + public ItemUseOpenRandomChest(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_OPEN_RANDOM_CHEST; + } + + @Override + public boolean useItem(UseItemParams params) { // cash shop material bundles + var data = params.player.getServer().getShopSystem().getShopChestData(this.i); + if (data == null) return false; + var rewardItems = data.stream().map(GameItem::new).toList(); + if (!rewardItems.isEmpty()) { + params.player.getInventory().addItems(rewardItems, ActionReason.Shop); + } + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseReliveAvatar.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseReliveAvatar.java index 0d28eb44d..8d78106b5 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseReliveAvatar.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseReliveAvatar.java @@ -1,18 +1,17 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseReliveAvatar extends ItemUseAction { - public ItemUseReliveAvatar(String[] useParam) { - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_RELIVE_AVATAR; - } - - @Override - public boolean useItem(UseItemParams params) { - return params.player.getTeamManager().reviveAvatar(params.targetAvatar); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseReliveAvatar extends ItemUseAction { + public ItemUseReliveAvatar(String[] useParam) {} + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_RELIVE_AVATAR; + } + + @Override + public boolean useItem(UseItemParams params) { + return params.player.getTeamManager().reviveAvatar(params.targetAvatar); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCodex.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCodex.java index 2089bac98..f8e822b23 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCodex.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCodex.java @@ -1,19 +1,19 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockCodex extends ItemUseInt { - public ItemUseUnlockCodex(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_CODEX; - } - - @Override - public boolean useItem(UseItemParams params) { - return false; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockCodex extends ItemUseInt { + public ItemUseUnlockCodex(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_CODEX; + } + + @Override + public boolean useItem(UseItemParams params) { + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCombine.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCombine.java index c2a3b0900..1ed15bd7a 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCombine.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCombine.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockCombine extends ItemUseInt { - public ItemUseUnlockCombine(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_COMBINE; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - return params.player.getServer().getCombineSystem().unlockCombineDiagram(params.player, this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockCombine extends ItemUseInt { + public ItemUseUnlockCombine(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_COMBINE; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + return params.player.getServer().getCombineSystem().unlockCombineDiagram(params.player, this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCookRecipe.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCookRecipe.java index b7435e048..a94a4df52 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCookRecipe.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockCookRecipe.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockCookRecipe extends ItemUseInt { - public ItemUseUnlockCookRecipe(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_COOK_RECIPE; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - return params.player.getCookingManager().unlockRecipe(this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockCookRecipe extends ItemUseInt { + public ItemUseUnlockCookRecipe(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_COOK_RECIPE; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + return params.player.getCookingManager().unlockRecipe(this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockForge.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockForge.java index 2ca1765e7..88e681f5a 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockForge.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockForge.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockForge extends ItemUseInt { - public ItemUseUnlockForge(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_FORGE; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - return params.player.getForgingManager().unlockForgingBlueprint(this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockForge extends ItemUseInt { + public ItemUseUnlockForge(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_FORGE; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + return params.player.getForgingManager().unlockForgingBlueprint(this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureFormula.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureFormula.java index 63b2d4a7a..083b690a3 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureFormula.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureFormula.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockFurnitureFormula extends ItemUseInt { - public ItemUseUnlockFurnitureFormula(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_FORMULA; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - return params.player.getFurnitureManager().unlockFurnitureFormula(this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockFurnitureFormula extends ItemUseInt { + public ItemUseUnlockFurnitureFormula(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_FORMULA; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + return params.player.getFurnitureManager().unlockFurnitureFormula(this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureSuite.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureSuite.java index 9657baa59..af6a34f8e 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureSuite.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockFurnitureSuite.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockFurnitureSuite extends ItemUseInt { - public ItemUseUnlockFurnitureSuite(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_SUITE; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - return params.player.getFurnitureManager().unlockFurnitureSuite(this.i); - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockFurnitureSuite extends ItemUseInt { + public ItemUseUnlockFurnitureSuite(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_SUITE; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + return params.player.getFurnitureManager().unlockFurnitureSuite(this.i); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeBgm.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeBgm.java index 06afc16a4..d11598131 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeBgm.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeBgm.java @@ -1,20 +1,20 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockHomeBgm extends ItemUseInt { - public ItemUseUnlockHomeBgm(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_HOME_BGM; - } - - @Override - public boolean useItem(UseItemParams params) { - params.player.getHome().addUnlockedHomeBgm(this.i); - return true; // Probably best to remove the item even if the bgm was already unlocked. - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockHomeBgm extends ItemUseInt { + public ItemUseUnlockHomeBgm(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_HOME_BGM; + } + + @Override + public boolean useItem(UseItemParams params) { + params.player.getHome().addUnlockedHomeBgm(this.i); + return true; // Probably best to remove the item even if the bgm was already unlocked. + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeModule.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeModule.java index 5d0f78489..2cb9bae14 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeModule.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockHomeModule.java @@ -1,25 +1,25 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockHomeModule extends ItemUseInt { - public ItemUseUnlockHomeModule(String[] useParam) { - super(useParam); - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_HOME_MODULE; - } - - @Override - public boolean useItem(UseItemParams params) { - return true; - } - - @Override - public boolean postUseItem(UseItemParams params) { - params.player.addRealmList(this.i); - return true; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockHomeModule extends ItemUseInt { + public ItemUseUnlockHomeModule(String[] useParam) { + super(useParam); + } + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_HOME_MODULE; + } + + @Override + public boolean useItem(UseItemParams params) { + return true; + } + + @Override + public boolean postUseItem(UseItemParams params) { + params.player.addRealmList(this.i); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockPaidBattlePassNormal.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockPaidBattlePassNormal.java index d85bb9e51..c6638b630 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockPaidBattlePassNormal.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/ItemUseUnlockPaidBattlePassNormal.java @@ -1,20 +1,19 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.props.ItemUseOp; - -public class ItemUseUnlockPaidBattlePassNormal extends ItemUseAction { - public ItemUseUnlockPaidBattlePassNormal(String[] useParam) { - } - - @Override - public ItemUseOp getItemUseOp() { - return ItemUseOp.ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL; - } - - @Override - public boolean useItem(UseItemParams params) { - // TODO: add paid BP - //return params.player.getBattlePassManager().setPaid(true); - return false; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.props.ItemUseOp; + +public class ItemUseUnlockPaidBattlePassNormal extends ItemUseAction { + public ItemUseUnlockPaidBattlePassNormal(String[] useParam) {} + + @Override + public ItemUseOp getItemUseOp() { + return ItemUseOp.ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL; + } + + @Override + public boolean useItem(UseItemParams params) { + // TODO: add paid BP + // return params.player.getBattlePassManager().setPaid(true); + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseAction/UseItemParams.java b/src/main/java/emu/grasscutter/game/props/ItemUseAction/UseItemParams.java index b2af9145b..e404a3c62 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseAction/UseItemParams.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseAction/UseItemParams.java @@ -1,30 +1,36 @@ -package emu.grasscutter.game.props.ItemUseAction; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ItemUseTarget; - -public class UseItemParams { - // Don't want to change 40 method signatures when this gets extended! - public Player player; - public ItemUseTarget itemUseTarget; - public Avatar targetAvatar = null; - public int count = 1; - public int optionId = 0; - public boolean isEnterMpDungeonTeam = false; - public int usedItemId = 0; - - public UseItemParams(Player player, ItemUseTarget itemUseTarget, Avatar targetAvatar, int count, int optionId, boolean isEnterMpDungeonTeam) { - this.player = player; - this.itemUseTarget = itemUseTarget; - this.targetAvatar = targetAvatar; - this.count = count; - this.optionId = optionId; - this.isEnterMpDungeonTeam = isEnterMpDungeonTeam; - } - - public UseItemParams(Player player, ItemUseTarget itemUseTarget) { - this.player = player; - this.itemUseTarget = itemUseTarget; - } -} +package emu.grasscutter.game.props.ItemUseAction; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ItemUseTarget; + +public class UseItemParams { + // Don't want to change 40 method signatures when this gets extended! + public Player player; + public ItemUseTarget itemUseTarget; + public Avatar targetAvatar = null; + public int count = 1; + public int optionId = 0; + public boolean isEnterMpDungeonTeam = false; + public int usedItemId = 0; + + public UseItemParams( + Player player, + ItemUseTarget itemUseTarget, + Avatar targetAvatar, + int count, + int optionId, + boolean isEnterMpDungeonTeam) { + this.player = player; + this.itemUseTarget = itemUseTarget; + this.targetAvatar = targetAvatar; + this.count = count; + this.optionId = optionId; + this.isEnterMpDungeonTeam = isEnterMpDungeonTeam; + } + + public UseItemParams(Player player, ItemUseTarget itemUseTarget) { + this.player = player; + this.itemUseTarget = itemUseTarget; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseOp.java b/src/main/java/emu/grasscutter/game/props/ItemUseOp.java index 89990b778..4a07fd7a0 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseOp.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseOp.java @@ -1,73 +1,74 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.stream.Stream; - -public enum ItemUseOp { - ITEM_USE_NONE(0), - ITEM_USE_ACCEPT_QUEST(1), - ITEM_USE_TRIGGER_ABILITY(2), - ITEM_USE_GAIN_AVATAR(3), - ITEM_USE_ADD_EXP(4), - ITEM_USE_RELIVE_AVATAR(5), - ITEM_USE_ADD_BIG_TALENT_POINT(6), - ITEM_USE_ADD_PERSIST_STAMINA(7), - ITEM_USE_ADD_TEMPORARY_STAMINA(8), - ITEM_USE_ADD_CUR_STAMINA(9), - ITEM_USE_ADD_CUR_HP(10), - ITEM_USE_ADD_ELEM_ENERGY(11), - ITEM_USE_ADD_ALL_ENERGY(12), - ITEM_USE_ADD_DUNGEON_COND_TIME(13), - ITEM_USE_ADD_WEAPON_EXP(14), - ITEM_USE_ADD_SERVER_BUFF(15), - ITEM_USE_DEL_SERVER_BUFF(16), - ITEM_USE_UNLOCK_COOK_RECIPE(17), - ITEM_USE_OPEN_RANDOM_CHEST(20), - ITEM_USE_MAKE_GADGET(24), - ITEM_USE_ADD_ITEM(25), - ITEM_USE_GRANT_SELECT_REWARD(26), - ITEM_USE_ADD_SELECT_ITEM(27), - ITEM_USE_GAIN_FLYCLOAK(28), - ITEM_USE_GAIN_NAME_CARD(29), - ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL(30), - ITEM_USE_GAIN_CARD_PRODUCT(31), - ITEM_USE_UNLOCK_FORGE(32), - ITEM_USE_UNLOCK_COMBINE(33), - ITEM_USE_UNLOCK_CODEX(34), - ITEM_USE_CHEST_SELECT_ITEM(35), - ITEM_USE_GAIN_RESIN_CARD_PRODUCT(36), - ITEM_USE_ADD_RELIQUARY_EXP(37), - ITEM_USE_UNLOCK_FURNITURE_FORMULA(38), - ITEM_USE_UNLOCK_FURNITURE_SUITE(39), - ITEM_USE_ADD_CHANNELLER_SLAB_BUFF(40), - ITEM_USE_GAIN_COSTUME(41), - ITEM_USE_ADD_TREASURE_MAP_BONUS_REGION_FRAGMENT(42), - ITEM_USE_COMBINE_ITEM(43), - ITEM_USE_UNLOCK_HOME_MODULE(44), - ITEM_USE_UNLOCK_HOME_BGM(45), - ITEM_USE_ADD_REGIONAL_PLAY_VAR(46); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - }); - } - - private final int value; - - ItemUseOp(int value) { - this.value = value; - } - - public static ItemUseOp getTypeByValue(int value) { - return map.getOrDefault(value, ITEM_USE_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.stream.Stream; + +public enum ItemUseOp { + ITEM_USE_NONE(0), + ITEM_USE_ACCEPT_QUEST(1), + ITEM_USE_TRIGGER_ABILITY(2), + ITEM_USE_GAIN_AVATAR(3), + ITEM_USE_ADD_EXP(4), + ITEM_USE_RELIVE_AVATAR(5), + ITEM_USE_ADD_BIG_TALENT_POINT(6), + ITEM_USE_ADD_PERSIST_STAMINA(7), + ITEM_USE_ADD_TEMPORARY_STAMINA(8), + ITEM_USE_ADD_CUR_STAMINA(9), + ITEM_USE_ADD_CUR_HP(10), + ITEM_USE_ADD_ELEM_ENERGY(11), + ITEM_USE_ADD_ALL_ENERGY(12), + ITEM_USE_ADD_DUNGEON_COND_TIME(13), + ITEM_USE_ADD_WEAPON_EXP(14), + ITEM_USE_ADD_SERVER_BUFF(15), + ITEM_USE_DEL_SERVER_BUFF(16), + ITEM_USE_UNLOCK_COOK_RECIPE(17), + ITEM_USE_OPEN_RANDOM_CHEST(20), + ITEM_USE_MAKE_GADGET(24), + ITEM_USE_ADD_ITEM(25), + ITEM_USE_GRANT_SELECT_REWARD(26), + ITEM_USE_ADD_SELECT_ITEM(27), + ITEM_USE_GAIN_FLYCLOAK(28), + ITEM_USE_GAIN_NAME_CARD(29), + ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL(30), + ITEM_USE_GAIN_CARD_PRODUCT(31), + ITEM_USE_UNLOCK_FORGE(32), + ITEM_USE_UNLOCK_COMBINE(33), + ITEM_USE_UNLOCK_CODEX(34), + ITEM_USE_CHEST_SELECT_ITEM(35), + ITEM_USE_GAIN_RESIN_CARD_PRODUCT(36), + ITEM_USE_ADD_RELIQUARY_EXP(37), + ITEM_USE_UNLOCK_FURNITURE_FORMULA(38), + ITEM_USE_UNLOCK_FURNITURE_SUITE(39), + ITEM_USE_ADD_CHANNELLER_SLAB_BUFF(40), + ITEM_USE_GAIN_COSTUME(41), + ITEM_USE_ADD_TREASURE_MAP_BONUS_REGION_FRAGMENT(42), + ITEM_USE_COMBINE_ITEM(43), + ITEM_USE_UNLOCK_HOME_MODULE(44), + ITEM_USE_UNLOCK_HOME_BGM(45), + ITEM_USE_ADD_REGIONAL_PLAY_VAR(46); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + }); + } + + private final int value; + + ItemUseOp(int value) { + this.value = value; + } + + public static ItemUseOp getTypeByValue(int value) { + return map.getOrDefault(value, ITEM_USE_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ItemUseTarget.java b/src/main/java/emu/grasscutter/game/props/ItemUseTarget.java index f4d901c9e..a2a1b4beb 100644 --- a/src/main/java/emu/grasscutter/game/props/ItemUseTarget.java +++ b/src/main/java/emu/grasscutter/game/props/ItemUseTarget.java @@ -1,37 +1,38 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.stream.Stream; - -public enum ItemUseTarget { - ITEM_USE_TARGET_NONE(0), - ITEM_USE_TARGET_CUR_AVATAR(1), - ITEM_USE_TARGET_CUR_TEAM(2), - ITEM_USE_TARGET_SPECIFY_AVATAR(3), - ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR(4), - ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR(5); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - }); - } - - private final int value; - - ItemUseTarget(int value) { - this.value = value; - } - - public static ItemUseTarget getTypeByValue(int value) { - return map.getOrDefault(value, ITEM_USE_TARGET_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.stream.Stream; + +public enum ItemUseTarget { + ITEM_USE_TARGET_NONE(0), + ITEM_USE_TARGET_CUR_AVATAR(1), + ITEM_USE_TARGET_CUR_TEAM(2), + ITEM_USE_TARGET_SPECIFY_AVATAR(3), + ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR(4), + ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR(5); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + }); + } + + private final int value; + + ItemUseTarget(int value) { + this.value = value; + } + + public static ItemUseTarget getTypeByValue(int value) { + return map.getOrDefault(value, ITEM_USE_TARGET_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/LifeState.java b/src/main/java/emu/grasscutter/game/props/LifeState.java index 613b60932..39486019d 100644 --- a/src/main/java/emu/grasscutter/game/props/LifeState.java +++ b/src/main/java/emu/grasscutter/game/props/LifeState.java @@ -1,43 +1,44 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum LifeState { - LIFE_NONE(0), - LIFE_ALIVE(1), - LIFE_DEAD(2), - LIFE_REVIVE(3); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - LifeState(int value) { - this.value = value; - } - - public static LifeState getTypeByValue(int value) { - return map.getOrDefault(value, LIFE_NONE); - } - - public static LifeState getTypeByName(String name) { - return stringMap.getOrDefault(name, LIFE_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum LifeState { + LIFE_NONE(0), + LIFE_ALIVE(1), + LIFE_DEAD(2), + LIFE_REVIVE(3); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + LifeState(int value) { + this.value = value; + } + + public static LifeState getTypeByValue(int value) { + return map.getOrDefault(value, LIFE_NONE); + } + + public static LifeState getTypeByName(String name) { + return stringMap.getOrDefault(name, LIFE_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/MonsterType.java b/src/main/java/emu/grasscutter/game/props/MonsterType.java index 6a8ab99d3..dfdfa0c4d 100644 --- a/src/main/java/emu/grasscutter/game/props/MonsterType.java +++ b/src/main/java/emu/grasscutter/game/props/MonsterType.java @@ -1,45 +1,46 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum MonsterType { - MONSTER_NONE(0), - MONSTER_ORDINARY(1), - MONSTER_BOSS(2), - MONSTER_ENV_ANIMAL(3), - MONSTER_LITTLE_MONSTER(4), - MONSTER_FISH(5); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - MonsterType(int value) { - this.value = value; - } - - public static MonsterType getTypeByValue(int value) { - return map.getOrDefault(value, MONSTER_NONE); - } - - public static MonsterType getTypeByName(String name) { - return stringMap.getOrDefault(name, MONSTER_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum MonsterType { + MONSTER_NONE(0), + MONSTER_ORDINARY(1), + MONSTER_BOSS(2), + MONSTER_ENV_ANIMAL(3), + MONSTER_LITTLE_MONSTER(4), + MONSTER_FISH(5); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + MonsterType(int value) { + this.value = value; + } + + public static MonsterType getTypeByValue(int value) { + return map.getOrDefault(value, MONSTER_NONE); + } + + public static MonsterType getTypeByName(String name) { + return stringMap.getOrDefault(name, MONSTER_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/PlayerProperty.java b/src/main/java/emu/grasscutter/game/props/PlayerProperty.java index 52ef3a298..a450ac6af 100644 --- a/src/main/java/emu/grasscutter/game/props/PlayerProperty.java +++ b/src/main/java/emu/grasscutter/game/props/PlayerProperty.java @@ -1,94 +1,97 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.Getter; - -import java.util.stream.Stream; - -public enum PlayerProperty { - PROP_NONE(0), - PROP_EXP(1001, 0), - PROP_BREAK_LEVEL(1002), - PROP_SATIATION_VAL(1003), - PROP_SATIATION_PENALTY_TIME(1004), - PROP_LEVEL(4001, 0, 90), - PROP_LAST_CHANGE_AVATAR_TIME(10001), - PROP_MAX_SPRING_VOLUME(10002, 0, 8_500_000), // Maximum volume of the Statue of the Seven for the player [0, 8500000] - PROP_CUR_SPRING_VOLUME(10003, true), // Current volume of the Statue of the Seven [0, PROP_MAX_SPRING_VOLUME] - PROP_IS_SPRING_AUTO_USE(10004, 0, 1), // Auto HP recovery when approaching the Statue of the Seven [0, 1] - PROP_SPRING_AUTO_USE_PERCENT(10005, 0, 100), // Auto HP recovery percentage [0, 100] - PROP_IS_FLYABLE(10006, 0, 1), // Are you in a state that disables your flying ability? e.g. new player [0, 1] - PROP_IS_WEATHER_LOCKED(10007, 0, 1), - PROP_IS_GAME_TIME_LOCKED(10008, 0, 1), - PROP_IS_TRANSFERABLE(10009, 0, 1), - PROP_MAX_STAMINA(10010, 0, 24_000), // Maximum stamina of the player (0 - 24000) - PROP_CUR_PERSIST_STAMINA(10011, true), // Used stamina of the player (0 - PROP_MAX_STAMINA) - PROP_CUR_TEMPORARY_STAMINA(10012), - PROP_PLAYER_LEVEL(10013, 1, 60), - PROP_PLAYER_EXP(10014), - PROP_PLAYER_HCOIN(10015), // Primogem (-inf, +inf) - // It is known that Mihoyo will make Primogem negative in the cases that a player spends - // his gems and then got a money refund, so negative is allowed. - PROP_PLAYER_SCOIN(10016, 0), // Mora [0, +inf) - PROP_PLAYER_MP_SETTING_TYPE(10017, 0, 2), // Do you allow other players to join your game? [0=no 1=direct 2=approval] - PROP_IS_MP_MODE_AVAILABLE(10018, 0, 1), // 0 if in quest or something that disables MP [0, 1] - PROP_PLAYER_WORLD_LEVEL(10019, 0, 8), // [0, 8] - PROP_PLAYER_RESIN(10020, 0, 2000), // Original Resin [0, 2000] - note that values above 160 require refills - PROP_PLAYER_WAIT_SUB_HCOIN(10022), - PROP_PLAYER_WAIT_SUB_SCOIN(10023), - PROP_IS_ONLY_MP_WITH_PS_PLAYER(10024, 0, 1), // Is only MP with PlayStation players? [0, 1] - PROP_PLAYER_MCOIN(10025), // Genesis Crystal (-inf, +inf) see 10015 - PROP_PLAYER_WAIT_SUB_MCOIN(10026), - PROP_PLAYER_LEGENDARY_KEY(10027, 0), - PROP_IS_HAS_FIRST_SHARE(10028), - PROP_PLAYER_FORGE_POINT(10029, 0, 300_000), - PROP_CUR_CLIMATE_METER(10035), - PROP_CUR_CLIMATE_TYPE(10036), - PROP_CUR_CLIMATE_AREA_ID(10037), - PROP_CUR_CLIMATE_AREA_CLIMATE_TYPE(10038), - PROP_PLAYER_WORLD_LEVEL_LIMIT(10039), - PROP_PLAYER_WORLD_LEVEL_ADJUST_CD(10040), - PROP_PLAYER_LEGENDARY_DAILY_TASK_NUM(10041), - PROP_PLAYER_HOME_COIN(10042, 0), // Realm currency [0, +inf) - PROP_PLAYER_WAIT_SUB_HOME_COIN(10043); - - private static final int inf = Integer.MAX_VALUE; // Maybe this should be something else? - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - - static { - Stream.of(values()).forEach(e -> map.put(e.getId(), e)); - } - - @Getter - private final int id, min, max; - @Getter - private final boolean dynamicRange; - - PlayerProperty(int id, int min, int max, boolean dynamicRange) { - this.id = id; - this.min = min; - this.max = max; - this.dynamicRange = dynamicRange; - } - - PlayerProperty(int id, int min) { - this(id, min, inf, false); - } - - PlayerProperty(int id, int min, int max) { - this(id, min, max, false); - } - - PlayerProperty(int id) { - this(id, Integer.MIN_VALUE, inf, false); - } - - PlayerProperty(int id, boolean dynamicRange) { - this(id, Integer.MIN_VALUE, inf, dynamicRange); - } - - public static PlayerProperty getPropById(int value) { - return map.getOrDefault(value, null); - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.stream.Stream; +import lombok.Getter; + +public enum PlayerProperty { + PROP_NONE(0), + PROP_EXP(1001, 0), + PROP_BREAK_LEVEL(1002), + PROP_SATIATION_VAL(1003), + PROP_SATIATION_PENALTY_TIME(1004), + PROP_LEVEL(4001, 0, 90), + PROP_LAST_CHANGE_AVATAR_TIME(10001), + PROP_MAX_SPRING_VOLUME( + 10002, 0, 8_500_000), // Maximum volume of the Statue of the Seven for the player [0, 8500000] + PROP_CUR_SPRING_VOLUME( + 10003, true), // Current volume of the Statue of the Seven [0, PROP_MAX_SPRING_VOLUME] + PROP_IS_SPRING_AUTO_USE( + 10004, 0, 1), // Auto HP recovery when approaching the Statue of the Seven [0, 1] + PROP_SPRING_AUTO_USE_PERCENT(10005, 0, 100), // Auto HP recovery percentage [0, 100] + PROP_IS_FLYABLE( + 10006, 0, 1), // Are you in a state that disables your flying ability? e.g. new player [0, 1] + PROP_IS_WEATHER_LOCKED(10007, 0, 1), + PROP_IS_GAME_TIME_LOCKED(10008, 0, 1), + PROP_IS_TRANSFERABLE(10009, 0, 1), + PROP_MAX_STAMINA(10010, 0, 24_000), // Maximum stamina of the player (0 - 24000) + PROP_CUR_PERSIST_STAMINA(10011, true), // Used stamina of the player (0 - PROP_MAX_STAMINA) + PROP_CUR_TEMPORARY_STAMINA(10012), + PROP_PLAYER_LEVEL(10013, 1, 60), + PROP_PLAYER_EXP(10014), + PROP_PLAYER_HCOIN(10015), // Primogem (-inf, +inf) + // It is known that Mihoyo will make Primogem negative in the cases that a player spends + // his gems and then got a money refund, so negative is allowed. + PROP_PLAYER_SCOIN(10016, 0), // Mora [0, +inf) + PROP_PLAYER_MP_SETTING_TYPE( + 10017, 0, 2), // Do you allow other players to join your game? [0=no 1=direct 2=approval] + PROP_IS_MP_MODE_AVAILABLE(10018, 0, 1), // 0 if in quest or something that disables MP [0, 1] + PROP_PLAYER_WORLD_LEVEL(10019, 0, 8), // [0, 8] + PROP_PLAYER_RESIN( + 10020, 0, 2000), // Original Resin [0, 2000] - note that values above 160 require refills + PROP_PLAYER_WAIT_SUB_HCOIN(10022), + PROP_PLAYER_WAIT_SUB_SCOIN(10023), + PROP_IS_ONLY_MP_WITH_PS_PLAYER(10024, 0, 1), // Is only MP with PlayStation players? [0, 1] + PROP_PLAYER_MCOIN(10025), // Genesis Crystal (-inf, +inf) see 10015 + PROP_PLAYER_WAIT_SUB_MCOIN(10026), + PROP_PLAYER_LEGENDARY_KEY(10027, 0), + PROP_IS_HAS_FIRST_SHARE(10028), + PROP_PLAYER_FORGE_POINT(10029, 0, 300_000), + PROP_CUR_CLIMATE_METER(10035), + PROP_CUR_CLIMATE_TYPE(10036), + PROP_CUR_CLIMATE_AREA_ID(10037), + PROP_CUR_CLIMATE_AREA_CLIMATE_TYPE(10038), + PROP_PLAYER_WORLD_LEVEL_LIMIT(10039), + PROP_PLAYER_WORLD_LEVEL_ADJUST_CD(10040), + PROP_PLAYER_LEGENDARY_DAILY_TASK_NUM(10041), + PROP_PLAYER_HOME_COIN(10042, 0), // Realm currency [0, +inf) + PROP_PLAYER_WAIT_SUB_HOME_COIN(10043); + + private static final int inf = Integer.MAX_VALUE; // Maybe this should be something else? + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + + static { + Stream.of(values()).forEach(e -> map.put(e.getId(), e)); + } + + @Getter private final int id, min, max; + @Getter private final boolean dynamicRange; + + PlayerProperty(int id, int min, int max, boolean dynamicRange) { + this.id = id; + this.min = min; + this.max = max; + this.dynamicRange = dynamicRange; + } + + PlayerProperty(int id, int min) { + this(id, min, inf, false); + } + + PlayerProperty(int id, int min, int max) { + this(id, min, max, false); + } + + PlayerProperty(int id) { + this(id, Integer.MIN_VALUE, inf, false); + } + + PlayerProperty(int id, boolean dynamicRange) { + this(id, Integer.MIN_VALUE, inf, dynamicRange); + } + + public static PlayerProperty getPropById(int value) { + return map.getOrDefault(value, null); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/SceneType.java b/src/main/java/emu/grasscutter/game/props/SceneType.java index d945d3d81..912e060db 100644 --- a/src/main/java/emu/grasscutter/game/props/SceneType.java +++ b/src/main/java/emu/grasscutter/game/props/SceneType.java @@ -1,46 +1,47 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum SceneType { - SCENE_NONE(0), - SCENE_WORLD(1), - SCENE_DUNGEON(2), - SCENE_ROOM(3), - SCENE_HOME_WORLD(4), - SCENE_HOME_ROOM(5), - SCENE_ACTIVITY(6); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - SceneType(int value) { - this.value = value; - } - - public static SceneType getTypeByValue(int value) { - return map.getOrDefault(value, SCENE_NONE); - } - - public static SceneType getTypeByName(String name) { - return stringMap.getOrDefault(name, SCENE_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum SceneType { + SCENE_NONE(0), + SCENE_WORLD(1), + SCENE_DUNGEON(2), + SCENE_ROOM(3), + SCENE_HOME_WORLD(4), + SCENE_HOME_ROOM(5), + SCENE_ACTIVITY(6); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + SceneType(int value) { + this.value = value; + } + + public static SceneType getTypeByValue(int value) { + return map.getOrDefault(value, SCENE_NONE); + } + + public static SceneType getTypeByName(String name) { + return stringMap.getOrDefault(name, SCENE_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ServerBuffType.java b/src/main/java/emu/grasscutter/game/props/ServerBuffType.java index f602d91ba..a57ca900c 100644 --- a/src/main/java/emu/grasscutter/game/props/ServerBuffType.java +++ b/src/main/java/emu/grasscutter/game/props/ServerBuffType.java @@ -1,35 +1,36 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.stream.Stream; - -public enum ServerBuffType { - SERVER_BUFF_NONE(0), - SERVER_BUFF_AVATAR(1), - SERVER_BUFF_TEAM(2), - SERVER_BUFF_TOWER(3); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - }); - } - - private final int value; - - ServerBuffType(int value) { - this.value = value; - } - - public static ServerBuffType getTypeByValue(int value) { - return map.getOrDefault(value, SERVER_BUFF_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.stream.Stream; + +public enum ServerBuffType { + SERVER_BUFF_NONE(0), + SERVER_BUFF_AVATAR(1), + SERVER_BUFF_TEAM(2), + SERVER_BUFF_TOWER(3); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + }); + } + + private final int value; + + ServerBuffType(int value) { + this.value = value; + } + + public static ServerBuffType getTypeByValue(int value) { + return map.getOrDefault(value, SERVER_BUFF_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/WatcherTriggerType.java b/src/main/java/emu/grasscutter/game/props/WatcherTriggerType.java index d14cf5277..3a3a2eb6f 100644 --- a/src/main/java/emu/grasscutter/game/props/WatcherTriggerType.java +++ b/src/main/java/emu/grasscutter/game/props/WatcherTriggerType.java @@ -1,338 +1,339 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum WatcherTriggerType { - TRIGGER_NONE(0), - TRIGGER_COMBAT_CONFIG_COMMON(1), - TRIGGER_ELEMENT_VIEW(2), - TRIGGER_ENTER_AIRFLOW(5), - TRIGGER_NEW_MONSTER(6), - TRIGGER_NEW_AFFIX(8), - TRIGGER_CHANGE_INPUT_DEVICE_TYPE(9), - TRIGGER_PAIMON_ANGRY_VOICE_EASTER_EGG(10), - TRIGGER_WIND_CRYSTAL(11), - TRIGGER_ELEMENT_BALL(101), - TRIGGER_WORLD_LEVEL_UP(102), - TRIGGER_DUNGEON_ENTRY_TO_BE_EXPLORED(103), - TRIGGER_UNLOCK_GATE_TEMPLE(104), - TRIGGER_UNLOCK_AREA(105), - TRIGGER_UNLOCK_TRANS_POINT(106), - TRIGGER_OPEN_CHEST_WITH_GADGET_ID(107), - TRIGGER_CITY_LEVEL_UP(108), - TRIGGER_MONSTER_DIE(109), - TRIGGER_PLATFORM_START_MOVE(110), - TRIGGER_GROUP_NOTIFY(111), - TRIGGER_ELEMENT_TYPE_CHANGE(112), - TRIGGER_GADGET_INTERACTABLE(113), - TRIGGER_COLLECT_SET_OF_READINGS(114), - TRIGGER_TELEPORT_WITH_CERTAIN_PORTAL(115), - TRIGGER_WORLD_GATHER(116), - TRIGGER_TAKE_GENERAL_REWARD(117), - TRIGGER_BATTLE_FOR_MONSTER_DIE_OR(118), - TRIGGER_BATTLE_FOR_MONSTER_DIE_AND(119), - TRIGGER_OPEN_WORLD_CHEST(120), - TRIGGER_ENTER_CLIMATE_AREA(121), - TRIGGER_UNLOCK_SCENE_POINT(122), - TRIGGER_INTERACT_GADGET_WITH_INTERACT_ID(123), - TRIGGER_OBTAIN_AVATAR(201), - TRIGGER_PLAYER_LEVEL(202), - TRIGGER_AVATAR_UPGRADE(203), - TRIGGER_AVATAR_PROMOTE(204), - TRIGGER_WEAPON_UPGRADE(205), - TRIGGER_WEAPON_PROMOTE(206), - TRIGGER_RELIQUARY_UPGRADE(207), - TRIGGER_WEAR_RELIQUARY(208), - TRIGGER_UPGRADE_TALENT(209), - TRIGGER_UNLOCK_RECIPE(210), - TRIGGER_RELIQUARY_SET_NUM(211), - TRIGGER_OBTAIN_MATERIAL_NUM(212), - TRIGGER_OBTAIN_RELIQUARY_NUM(213), - TRIGGER_GACHA_NUM(214), - TRIGGER_ANY_RELIQUARY_UPGRADE(215), - TRIGGER_FETTER_LEVEL_AVATAR_NUM(216), - TRIGGER_SKILLED_AT_RECIPE(217), - TRIGGER_RELIQUARY_UPGRADE_EQUAL_RANK_LEVEL(218), - TRIGGER_SPECIFIED_WEAPON_UPGRADE(219), - TRIGGER_SPECIFIED_WEAPON_AWAKEN(220), - TRIGGER_UNLOCK_SPECIFIC_RECIPE_OR(221), - TRIGGER_POSSESS_MATERIAL_NUM(222), - TRIGGER_EXHIBITION_ACCUMULABLE_VALUE(223), - TRIGGER_EXHIBITION_REPLACEABLE_VALUE_SETTLE_NUM(224), - TRIGGER_ANY_WEAPON_UPGRADE_NUM(225), - TRIGGER_ANY_RELIQUARY_UPGRADE_NUM(226), - TRIGGER_ACTIVITY_SCORE_EXCEED_VALUE(227), - TRIGGER_UNLOCK_SPECIFIC_FORGE_OR(228), - TRIGGER_UNLOCK_SPECIFIC_ANIMAL_CODEX(229), - TRIGGER_OBTAIN_ITEM_NUM(230), - TRIGGER_CAPTURE_ANIMAL(231), - TRIGGER_DAILY_TASK(301), - TRIGGER_RAND_TASK(302), - TRIGGER_AVATAR_EXPEDITION(303), - TRIGGER_FINISH_TOWER_LEVEL(304), - TRIGGER_WORLD_BOSS_REWARD(306), - TRIGGER_FINISH_DUNGEON(307), - TRIGGER_START_AVATAR_EXPEDITION(308), - TRIGGER_OPEN_BLOSSOM_CHEST(309), - TRIGGER_FINISH_BLOSSOM_PROGRESS(310), - TRIGGER_DONE_TOWER_GADGET_UNHURT(311), - TRIGGER_DONE_TOWER_STARS(312), - TRIGGER_DONE_TOWER_UNHURT(313), - TRIGGER_STEAL_FOOD_TIMES(314), - TRIGGER_DONE_DUNGEON_WITH_SAME_ELEMENT_AVATARS(315), - TRIGGER_GROUP_FLIGHT_CHALLENGE_REACH_POINTS(316), - TRIGGER_FINISH_DAILY_DELIVERY_NUM(317), - TRIGGER_TOWER_STARS_NUM(318), - TRIGGER_FINISH_SPECIFED_TYPE_BLOSSOM_NUM(319), - TRIGGER_FINISH_SPECIFED_TYPE_BLOSSOM_CLIMATE_METER(320), - TRIGGER_FINISH_BLOSSOM_GROUP_VARIABLE_GT(321), - TRIGGER_EFFIGY_CHALLENGE_SCORE(322), - TRIGGER_FINISH_ROUTINE(323), - TRIGGER_ACTIVITY_EXPEDITION_FINISH(324), - TRIGGER_ACTIVITY_CHANNELLER_SLAB_FINISH_ALL_CAMP(325), - TRIGGER_ACTIVITY_CHANNELLER_SLAB_FINISH_ALL_ONEOFF_DUNGEON(326), - TRIGGER_ACTIVITY_CHANNELLER_SLAB_LOOP_DUNGEON_TOTAL_SCORE(327), - TRIGGER_GROUP_SUMMER_TIME_SPRINT_BOAT_REACH_POINTS(328), - TRIGGER_WEEKLY_BOSS_KILL(329), - TRIGGER_BOUNCE_CONJURING_FINISH_COUNT(330), - TRIGGER_BOUNCE_CONJURING_SCORE(331), - TRIGGER_GROUP_VARIABLE_SET_VALUE_TO(332), - TRIGGER_KILL_GADGETS_BY_SPECIFIC_SKILL(333), - TRIGGER_KILL_MONSTERS_WITHOUT_VEHICLE(334), - TRIGGER_KILL_MONSTER_IN_AREA(335), - TRIGGER_ENTER_VEHICLE(336), - TRIGGER_VEHICLE_DURATION(337), - TRIGGER_VEHICLE_FRIENDS(338), - TRIGGER_VEHICLE_KILLED_BY_MONSTER(339), - TRIGGER_VEHICLE_DASH(340), - TRIGGER_DO_COOK(401), - TRIGGER_DO_FORGE(402), - TRIGGER_DO_COMPOUND(403), - TRIGGER_DO_COMBINE(404), - TRIGGER_BUY_SHOP_GOODS(405), - TRIGGER_FORGE_WEAPON(406), - TRIGGER_MP_PLAY_BATTLE_WIN(421), - TRIGGER_KILL_GROUP_MONSTER(422), - TRIGGER_CRUCIBLE_ELEMENT_SCORE(423), - TRIGGER_MP_DUNGEON_TIMES(424), - TRIGGER_MP_KILL_MONSTER_NUM(425), - TRIGGER_CRUCIBLE_MAX_BALL(426), - TRIGGER_CRUCIBLE_MAX_SCORE(427), - TRIGGER_CRUCIBLE_SUBMIT_BALL(428), - TRIGGER_CRUCIBLE_WORLD_LEVEL_SCORE(429), - TRIGGER_MP_PLAY_GROUP_STATISTIC(430), - TRIGGER_KILL_GROUP_SPECIFIC_MONSTER(431), - TRIGGER_REACH_MP_PLAY_SCORE(432), - TRIGGER_REACH_MP_PLAY_RECORD(433), - TRIGGER_TREASURE_MAP_DONE_REGION(434), - TRIGGER_SEA_LAMP_MINI_QUEST(435), - TRIGGER_FINISH_FIND_HILICHURL_LEVEL(436), - TRIGGER_COMBINE_ITEM(437), - TRIGGER_FINISH_CHALLENGE_IN_DURATION(438), - TRIGGER_FINISH_CHALLENGE_LEFT_TIME(439), - TRIGGER_MP_KILL_MONSTER_ID_NUM(440), - TRIGGER_LOGIN(501), - TRIGGER_COST_MATERIAL(502), - TRIGGER_DELIVER_ITEM_TO_SALESMAN(503), - TRIGGER_USE_ITEM(504), - TRIGGER_ACCUMULATE_DAILY_LOGIN(505), - TRIGGER_FINISH_CHALLENGE(601), - TRIGGER_MECHANICUS_UNLOCK_GEAR(602), - TRIGGER_MECHANICUS_LEVELUP_GEAR(603), - TRIGGER_MECHANICUS_DIFFICULT(604), - TRIGGER_MECHANICUS_DIFFICULT_SCORE(605), - TRIGGER_MECHANICUS_KILL_MONSTER(606), - TRIGGER_MECHANICUS_BUILDING_POINT(607), - TRIGGER_MECHANICUS_DIFFICULT_EQ(608), - TRIGGER_MECHANICUS_BATTLE_END(609), - TRIGGER_MECHANICUS_BATTLE_END_EXCAPED_LESS_THAN(610), - TRIGGER_MECHANICUS_BATTLE_END_POINTS_MORE_THAN(611), - TRIGGER_MECHANICUS_BATTLE_END_GEAR_MORE_THAN(612), - TRIGGER_MECHANICUS_BATTLE_END_PURE_GEAR_DAMAGE(613), - TRIGGER_MECHANICUS_BATTLE_END_CARD_PICK_MORE_THAN(614), - TRIGGER_MECHANICUS_BATTLE_END_CARD_TARGET_MORE_THAN(615), - TRIGGER_MECHANICUS_BATTLE_END_BUILD_GEAR_MORE_THAN(616), - TRIGGER_MECHANICUS_BATTLE_END_GEAR_KILL_MORE_THAN(617), - TRIGGER_MECHANICUS_BATTLE_END_ROUND_MORE_THAN(618), - TRIGGER_MECHANICUS_BATTLE_END_ROUND(619), - TRIGGER_MECHANICUS_BATTLE_FIN_CHALLENGE_MORE_THAN(620), - TRIGGER_MECHANICUS_BATTLE_WATCHER_FINISH_COUNT(621), - TRIGGER_MECHANICUS_BATTLE_INTERACT_COUNT(622), - TRIGGER_MECHANICUS_BATTLE_DIFFICULT_ESCAPE(623), - TRIGGER_MECHANICUS_BATTLE_DIFFICULT_GEAR_NUM(624), - TRIGGER_MECHANICUS_BATTLE_DIFFICULT_GEAR_ID_NUM(625), - TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_IN_LIMIT_TIME(626), - TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_KEEP_ENERGY(627), - TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_WITH_GROUP_VARIABLE(628), - TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_WITH_BUFF_NUM(629), - TRIGGER_FLEUR_FAIR_DUNGEON_MISSION_FINISH(630), - TRIGGER_FINISH_DUNGEON_AND_CHALLENGE_REMAIN_TIME_GREATER_THAN(631), - TRIGGER_FINISH_DUNGEON_WITH_MIST_TRIAL_STAT(632), - TRIGGER_DUNGEON_MIST_TRIAL_STAT(633), - TRIGGER_DUNGEON_ELEMENT_REACTION_NUM(634), - TRIGGER_LEVEL_AVATAR_FINISH_DUNGEON_COUNT(635), - TRIGGER_CHESS_REACH_LEVEL(636), - TRIGGER_CHESS_DUNGEON_ADD_SCORE(637), - TRIGGER_CHESS_DUNGEON_SUCC_WITH_ESCAPED_MONSTERS_LESS_THAN(638), - TRIGGER_CHESS_DUNGEON_SUCC_WITH_TOWER_COUNT_LESS_OR_EQUAL(639), - TRIGGER_CHESS_DUNGEON_SUCC_WITH_CARD_COUNT_LESS_OR_EQUAL(640), - TRIGGER_CHESS_DUNGEON_SUCC_WITH_CARD_COUNT_GREATER_THAN(641), - TRIGGER_CHESS_KILL_MONSTERS(642), - TRIGGER_CHESS_COST_BUILDING_POINTS(643), - TRIGGER_SUMO_STAGE_SCORE_REACH(644), - TRIGGER_SUMO_TOTAL_MAX_SCORE_REACH(645), - TRIGGER_ROGUE_DESTROY_GADGET_NUM(646), - TRIGGER_ROGUE_KILL_MONSTER_NUM(647), - TRIGGER_ROGUE_FINISH_WITHOUT_USING_SPRING_CELL(649), - TRIGGER_ROGUE_FINISH_ALL_CHALLENGE_CELL(650), - TRIGGER_ROGUE_FINISH_WITH_AVATAR_ELEMENT_TYPE_NUM_LESS_THAN(651), - TRIGGER_ROGUE_FINISH_WITH_AVATAR_NUM_LESS_THAN(652), - TRIGGER_ROGUE_FINISH_NO_AVATAR_DEAD(653), - TRIGGER_ROGUE_SHIKIGAMI_UPGRADE(654), - TRIGGER_ROGUE_CURSE_NUM(655), - TRIGGER_ROGUE_SELECT_CARD_NUM(656), - TRIGGER_FINISH_QUEST_AND(700), - TRIGGER_FINISH_QUEST_OR(701), - TRIGGER_DAILY_TASK_VAR_EQUAL(702), - TRIGGER_QUEST_GLOBAL_VAR_EQUAL(703), - TRIGGER_TALK_NUM(704), - TRIGGER_FINISH_PARENT_QUEST_AND(705), - TRIGGER_FINISH_PARENT_QUEST_OR(706), - TRIGGER_ELEMENT_REACTION_TIMELIMIT_NUM(800), - TRIGGER_ELEMENT_REACTION_TIMELIMIT_KILL_NUM(801), - TRIGGER_ELEMENT_REACTION_TIMELIMIT_DAMAGE_NUM(802), - TRIGGER_ABILITY_STATE_PASS_TIME(803), - TRIGGER_MAX_CRITICAL_DAMAGE(804), - TRIGGER_FULL_SATIATION_TEAM_AVATAR_NUM(805), - TRIGGER_KILLED_BY_CERTAIN_MONSTER(806), - TRIGGER_CUR_AVATAR_HURT(807), - TRIGGER_CUR_AVATAR_ABILITY_STATE(808), - TRIGGER_USE_ENERGY_SKILL_NUM_TIMELIMIT(809), - TRIGGER_SHIELD_SOURCE_NUM(810), - TRIGGER_CUR_AVATAR_HURT_BY_SPECIFIC_ABILITY(811), - TRIGGER_KILLED_BY_SPECIFIC_ABILITY(812), - TRIGGER_MAX_DASH_TIME(900), - TRIGGER_MAX_FLY_TIME(901), - TRIGGER_MAX_FLY_MAP_DISTANCE(902), - TRIGGER_SIT_DOWN_IN_POINT(903), - TRIGGER_DASH(904), - TRIGGER_CLIMB(905), - TRIGGER_FLY(906), - TRIGGER_CITY_REPUTATION_LEVEL(930), - TRIGGER_CITY_REPUTATION_FINISH_REQUEST(931), - TRIGGER_HUNTING_FINISH_NUM(932), - TRIGGER_HUNTING_FAIL_NUM(933), - TRIGGER_OFFERING_LEVEL(934), - TRIGGER_MIRACLE_RING_DELIVER_ITEM(935), - TRIGGER_MIRACLE_RING_TAKE_REWARD(936), - TRIGGER_BLESSING_EXCHANGE_PIC_NUM(937), - TRIGGER_BLESSING_REDEEM_REWARD_NUM(938), - TRIGGER_GALLERY_BALLOON_REACH_SCORE(939), - TRIGGER_GALLERY_FALL_REACH_SCORE(940), - TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE(941), - TRIGGER_MAIN_COOP_SAVE_POINT_AND(942), - TRIGGER_MAIN_COOP_SAVE_POINT_OR(943), - TRIGGER_MAIN_COOP_VAR_EQUAL(944), - TRIGGER_FINISH_ALL_ARENA_CHALLENGE_WATCHER_IN_SCHEDULE(945), - TRIGGER_GALLERY_BUOYANT_COMBAT_REACH_SCORE(946), - TRIGGER_BUOYANT_COMBAT_REACH_NEW_SCORE_LEVEL(947), - TRIGGER_PLACE_MIRACLE_RING(948), - TRIGGER_LUNA_RITE_SEARCH(949), - TRIGGER_GALLERY_FISH_REACH_SCORE(950), - TRIGGER_GALLERY_TRIATHLON_REACH_SCORE(951), - TRIGGER_WINTER_CAMP_SNOWMAN_COMPLEIET(952), - TRIGGER_CREATE_CUSTOM_DUNGEON(953), - TRIGGER_PUBLISH_CUSTOM_DUNGEON(954), - TRIGGER_PLAY_OTHER_CUSTOM_DUNGEON(955), - TRIGGER_FINISH_CUSTOM_DUNGEON_OFFICIAL(956), - TRIGGER_CUSTOM_DUNGEON_OFFICIAL_COIN(957), - TRIGGER_OBTAIN_WOOD_TYPE(1000), - TRIGGER_OBTAIN_WOOD_COUNT(1001), - TRIGGER_UNLOCK_FURNITURE_COUNT(1002), - TRIGGER_FURNITURE_MAKE(1003), - TRIGGER_HOME_LEVEL(1004), - TRIGGER_HOME_COIN(1005), - TRIGGER_HOME_COMFORT_LEVEL(1006), - TRIGGER_HOME_LIMITED_SHOP_BUY(1007), - TRIGGER_FURNITURE_SUITE_TYPE(1008), - TRIGGER_ARRANGEMENT_FURNITURE_COUNT(1009), - TRIGGER_ENTER_SELF_HOME(1010), - TRIGGER_HOME_MODULE_COMFORT_VALUE(1011), - TRIGGER_HOME_ENTER_ROOM(1012), - TRIGGER_HOME_AVATAR_IN(1013), - TRIGGER_HOME_AVATAR_REWARD_EVENT_COUNT(1014), - TRIGGER_HOME_AVATAR_TALK_FINISH_COUNT(1015), - TRIGGER_HOME_AVATAR_REWARD_EVENT_ALL_COUNT(1016), - TRIGGER_HOME_AVATAR_TALK_FINISH_ALL_COUNT(1017), - TRIGGER_HOME_AVATAR_FETTER_GET(1018), - TRIGGER_HOME_AVATAR_IN_COUNT(1019), - TRIGGER_HOME_DO_PLANT(1020), - TRIGGER_ARRANGEMENT_FURNITURE(1021), - TRIGGER_HOME_GATHER_COUNT(1022), - TRIGGER_HOME_FIELD_GATHER_COUNT(1023), - TRIGGER_HOME_UNLOCK_BGM_COUNT(1024), - TRIGGER_FISHING_SUCC_NUM(1100), - TRIGGER_FISHING_KEEP_BONUS(1101), - TRIGGER_EMPTY_FISH_POOL(1102), - TRIGGER_FISHING_FAIL_NUM(1103), - TRIGGER_SHOCK_FISH_NUM(1104), - TRIGGER_PLANT_FLOWER_SET_WISH(1105), - TRIGGER_PLANT_FLOWER_GIVE_FLOWER(1106), - TRIGGER_PLANT_FLOWER_OBTAIN_FLOWER_TYPE(1107), - TRIGGER_PLANT_FLOWER_COMMON_OBTAIN_FLOWER_TYPE(1108), - TRIGGER_FINISH_LANV2_PROJECTION_LEVEL(1111), - TRIGGER_GALLERY_SALVAGE_REACH_SCORE(1112), - TRIGGER_LANV2_FIREWORKS_CHALLENGE_REACH_SCORE(1113), - TRIGGER_POTION_STAGE_LEVEL_PASS_NUM(1115), - TRIGGER_POTION_STAGE_OBTAIN_MEDAL_NUM(1116), - TRIGGER_POTION_STAGE_REACH_TOTAL_SCORE(1117), - TRIGGER_BARTENDER_FINISH_STORY_MODULE(1120), - TRIGGER_BARTENDER_CHALLENGE_MODULE_LEVEL_SCORE(1121), - TRIGGER_BARTENDER_UNLOCK_FORMULA(1122), - TRIGGER_MICHIAE_MATSURI_UNLOCK_CRYSTAL_SKILL_REACH_NUM(1123), - TRIGGER_MICHIAE_MATSURI_FINISH_DARK_CHALLENGE_REACH_NUM(1124), - TRIGGER_CAPTURE_ENV_ANIMAL_REACH_NUM(1125), - TRIGGER_SPICE_MAKE_FORMULA_TIMES(1126), - TRIGGER_SPICE_GIVE_FOOD_TIMES(1127), - TRIGGER_SPICE_MAKE_FORMULA_SUCCESSFUL_TIMES(1128), - TRIGGER_IRODORI_FINISH_FLOWER_THEME(1131), - TRIGGER_IRODORI_FINISH_MASTER_STAGE(1132), - TRIGGER_IRODORI_CHESS_STAGE_REACH_SCORE(1133), - TRIGGER_IRODORI_FINISH_POETRY_THEME(1134), - TRIGGER_PHOTO_FINISH_POS_ID(1135), - TRIGGER_CRYSTAL_LINK_LEVEL_SCORE_REACH(1138), - TRIGGER_CRYSTAL_LINK_TOTAL_MAX_SCORE_REACH(1139); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - - WatcherTriggerType(int value) { - this.value = value; - } - - public static WatcherTriggerType getTypeByValue(int value) { - return map.getOrDefault(value, TRIGGER_NONE); - } - - public static WatcherTriggerType getTypeByName(String name) { - return stringMap.getOrDefault(name, TRIGGER_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum WatcherTriggerType { + TRIGGER_NONE(0), + TRIGGER_COMBAT_CONFIG_COMMON(1), + TRIGGER_ELEMENT_VIEW(2), + TRIGGER_ENTER_AIRFLOW(5), + TRIGGER_NEW_MONSTER(6), + TRIGGER_NEW_AFFIX(8), + TRIGGER_CHANGE_INPUT_DEVICE_TYPE(9), + TRIGGER_PAIMON_ANGRY_VOICE_EASTER_EGG(10), + TRIGGER_WIND_CRYSTAL(11), + TRIGGER_ELEMENT_BALL(101), + TRIGGER_WORLD_LEVEL_UP(102), + TRIGGER_DUNGEON_ENTRY_TO_BE_EXPLORED(103), + TRIGGER_UNLOCK_GATE_TEMPLE(104), + TRIGGER_UNLOCK_AREA(105), + TRIGGER_UNLOCK_TRANS_POINT(106), + TRIGGER_OPEN_CHEST_WITH_GADGET_ID(107), + TRIGGER_CITY_LEVEL_UP(108), + TRIGGER_MONSTER_DIE(109), + TRIGGER_PLATFORM_START_MOVE(110), + TRIGGER_GROUP_NOTIFY(111), + TRIGGER_ELEMENT_TYPE_CHANGE(112), + TRIGGER_GADGET_INTERACTABLE(113), + TRIGGER_COLLECT_SET_OF_READINGS(114), + TRIGGER_TELEPORT_WITH_CERTAIN_PORTAL(115), + TRIGGER_WORLD_GATHER(116), + TRIGGER_TAKE_GENERAL_REWARD(117), + TRIGGER_BATTLE_FOR_MONSTER_DIE_OR(118), + TRIGGER_BATTLE_FOR_MONSTER_DIE_AND(119), + TRIGGER_OPEN_WORLD_CHEST(120), + TRIGGER_ENTER_CLIMATE_AREA(121), + TRIGGER_UNLOCK_SCENE_POINT(122), + TRIGGER_INTERACT_GADGET_WITH_INTERACT_ID(123), + TRIGGER_OBTAIN_AVATAR(201), + TRIGGER_PLAYER_LEVEL(202), + TRIGGER_AVATAR_UPGRADE(203), + TRIGGER_AVATAR_PROMOTE(204), + TRIGGER_WEAPON_UPGRADE(205), + TRIGGER_WEAPON_PROMOTE(206), + TRIGGER_RELIQUARY_UPGRADE(207), + TRIGGER_WEAR_RELIQUARY(208), + TRIGGER_UPGRADE_TALENT(209), + TRIGGER_UNLOCK_RECIPE(210), + TRIGGER_RELIQUARY_SET_NUM(211), + TRIGGER_OBTAIN_MATERIAL_NUM(212), + TRIGGER_OBTAIN_RELIQUARY_NUM(213), + TRIGGER_GACHA_NUM(214), + TRIGGER_ANY_RELIQUARY_UPGRADE(215), + TRIGGER_FETTER_LEVEL_AVATAR_NUM(216), + TRIGGER_SKILLED_AT_RECIPE(217), + TRIGGER_RELIQUARY_UPGRADE_EQUAL_RANK_LEVEL(218), + TRIGGER_SPECIFIED_WEAPON_UPGRADE(219), + TRIGGER_SPECIFIED_WEAPON_AWAKEN(220), + TRIGGER_UNLOCK_SPECIFIC_RECIPE_OR(221), + TRIGGER_POSSESS_MATERIAL_NUM(222), + TRIGGER_EXHIBITION_ACCUMULABLE_VALUE(223), + TRIGGER_EXHIBITION_REPLACEABLE_VALUE_SETTLE_NUM(224), + TRIGGER_ANY_WEAPON_UPGRADE_NUM(225), + TRIGGER_ANY_RELIQUARY_UPGRADE_NUM(226), + TRIGGER_ACTIVITY_SCORE_EXCEED_VALUE(227), + TRIGGER_UNLOCK_SPECIFIC_FORGE_OR(228), + TRIGGER_UNLOCK_SPECIFIC_ANIMAL_CODEX(229), + TRIGGER_OBTAIN_ITEM_NUM(230), + TRIGGER_CAPTURE_ANIMAL(231), + TRIGGER_DAILY_TASK(301), + TRIGGER_RAND_TASK(302), + TRIGGER_AVATAR_EXPEDITION(303), + TRIGGER_FINISH_TOWER_LEVEL(304), + TRIGGER_WORLD_BOSS_REWARD(306), + TRIGGER_FINISH_DUNGEON(307), + TRIGGER_START_AVATAR_EXPEDITION(308), + TRIGGER_OPEN_BLOSSOM_CHEST(309), + TRIGGER_FINISH_BLOSSOM_PROGRESS(310), + TRIGGER_DONE_TOWER_GADGET_UNHURT(311), + TRIGGER_DONE_TOWER_STARS(312), + TRIGGER_DONE_TOWER_UNHURT(313), + TRIGGER_STEAL_FOOD_TIMES(314), + TRIGGER_DONE_DUNGEON_WITH_SAME_ELEMENT_AVATARS(315), + TRIGGER_GROUP_FLIGHT_CHALLENGE_REACH_POINTS(316), + TRIGGER_FINISH_DAILY_DELIVERY_NUM(317), + TRIGGER_TOWER_STARS_NUM(318), + TRIGGER_FINISH_SPECIFED_TYPE_BLOSSOM_NUM(319), + TRIGGER_FINISH_SPECIFED_TYPE_BLOSSOM_CLIMATE_METER(320), + TRIGGER_FINISH_BLOSSOM_GROUP_VARIABLE_GT(321), + TRIGGER_EFFIGY_CHALLENGE_SCORE(322), + TRIGGER_FINISH_ROUTINE(323), + TRIGGER_ACTIVITY_EXPEDITION_FINISH(324), + TRIGGER_ACTIVITY_CHANNELLER_SLAB_FINISH_ALL_CAMP(325), + TRIGGER_ACTIVITY_CHANNELLER_SLAB_FINISH_ALL_ONEOFF_DUNGEON(326), + TRIGGER_ACTIVITY_CHANNELLER_SLAB_LOOP_DUNGEON_TOTAL_SCORE(327), + TRIGGER_GROUP_SUMMER_TIME_SPRINT_BOAT_REACH_POINTS(328), + TRIGGER_WEEKLY_BOSS_KILL(329), + TRIGGER_BOUNCE_CONJURING_FINISH_COUNT(330), + TRIGGER_BOUNCE_CONJURING_SCORE(331), + TRIGGER_GROUP_VARIABLE_SET_VALUE_TO(332), + TRIGGER_KILL_GADGETS_BY_SPECIFIC_SKILL(333), + TRIGGER_KILL_MONSTERS_WITHOUT_VEHICLE(334), + TRIGGER_KILL_MONSTER_IN_AREA(335), + TRIGGER_ENTER_VEHICLE(336), + TRIGGER_VEHICLE_DURATION(337), + TRIGGER_VEHICLE_FRIENDS(338), + TRIGGER_VEHICLE_KILLED_BY_MONSTER(339), + TRIGGER_VEHICLE_DASH(340), + TRIGGER_DO_COOK(401), + TRIGGER_DO_FORGE(402), + TRIGGER_DO_COMPOUND(403), + TRIGGER_DO_COMBINE(404), + TRIGGER_BUY_SHOP_GOODS(405), + TRIGGER_FORGE_WEAPON(406), + TRIGGER_MP_PLAY_BATTLE_WIN(421), + TRIGGER_KILL_GROUP_MONSTER(422), + TRIGGER_CRUCIBLE_ELEMENT_SCORE(423), + TRIGGER_MP_DUNGEON_TIMES(424), + TRIGGER_MP_KILL_MONSTER_NUM(425), + TRIGGER_CRUCIBLE_MAX_BALL(426), + TRIGGER_CRUCIBLE_MAX_SCORE(427), + TRIGGER_CRUCIBLE_SUBMIT_BALL(428), + TRIGGER_CRUCIBLE_WORLD_LEVEL_SCORE(429), + TRIGGER_MP_PLAY_GROUP_STATISTIC(430), + TRIGGER_KILL_GROUP_SPECIFIC_MONSTER(431), + TRIGGER_REACH_MP_PLAY_SCORE(432), + TRIGGER_REACH_MP_PLAY_RECORD(433), + TRIGGER_TREASURE_MAP_DONE_REGION(434), + TRIGGER_SEA_LAMP_MINI_QUEST(435), + TRIGGER_FINISH_FIND_HILICHURL_LEVEL(436), + TRIGGER_COMBINE_ITEM(437), + TRIGGER_FINISH_CHALLENGE_IN_DURATION(438), + TRIGGER_FINISH_CHALLENGE_LEFT_TIME(439), + TRIGGER_MP_KILL_MONSTER_ID_NUM(440), + TRIGGER_LOGIN(501), + TRIGGER_COST_MATERIAL(502), + TRIGGER_DELIVER_ITEM_TO_SALESMAN(503), + TRIGGER_USE_ITEM(504), + TRIGGER_ACCUMULATE_DAILY_LOGIN(505), + TRIGGER_FINISH_CHALLENGE(601), + TRIGGER_MECHANICUS_UNLOCK_GEAR(602), + TRIGGER_MECHANICUS_LEVELUP_GEAR(603), + TRIGGER_MECHANICUS_DIFFICULT(604), + TRIGGER_MECHANICUS_DIFFICULT_SCORE(605), + TRIGGER_MECHANICUS_KILL_MONSTER(606), + TRIGGER_MECHANICUS_BUILDING_POINT(607), + TRIGGER_MECHANICUS_DIFFICULT_EQ(608), + TRIGGER_MECHANICUS_BATTLE_END(609), + TRIGGER_MECHANICUS_BATTLE_END_EXCAPED_LESS_THAN(610), + TRIGGER_MECHANICUS_BATTLE_END_POINTS_MORE_THAN(611), + TRIGGER_MECHANICUS_BATTLE_END_GEAR_MORE_THAN(612), + TRIGGER_MECHANICUS_BATTLE_END_PURE_GEAR_DAMAGE(613), + TRIGGER_MECHANICUS_BATTLE_END_CARD_PICK_MORE_THAN(614), + TRIGGER_MECHANICUS_BATTLE_END_CARD_TARGET_MORE_THAN(615), + TRIGGER_MECHANICUS_BATTLE_END_BUILD_GEAR_MORE_THAN(616), + TRIGGER_MECHANICUS_BATTLE_END_GEAR_KILL_MORE_THAN(617), + TRIGGER_MECHANICUS_BATTLE_END_ROUND_MORE_THAN(618), + TRIGGER_MECHANICUS_BATTLE_END_ROUND(619), + TRIGGER_MECHANICUS_BATTLE_FIN_CHALLENGE_MORE_THAN(620), + TRIGGER_MECHANICUS_BATTLE_WATCHER_FINISH_COUNT(621), + TRIGGER_MECHANICUS_BATTLE_INTERACT_COUNT(622), + TRIGGER_MECHANICUS_BATTLE_DIFFICULT_ESCAPE(623), + TRIGGER_MECHANICUS_BATTLE_DIFFICULT_GEAR_NUM(624), + TRIGGER_MECHANICUS_BATTLE_DIFFICULT_GEAR_ID_NUM(625), + TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_IN_LIMIT_TIME(626), + TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_KEEP_ENERGY(627), + TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_WITH_GROUP_VARIABLE(628), + TRIGGER_FLEUR_FAIR_DUNGEON_FINISH_WITH_BUFF_NUM(629), + TRIGGER_FLEUR_FAIR_DUNGEON_MISSION_FINISH(630), + TRIGGER_FINISH_DUNGEON_AND_CHALLENGE_REMAIN_TIME_GREATER_THAN(631), + TRIGGER_FINISH_DUNGEON_WITH_MIST_TRIAL_STAT(632), + TRIGGER_DUNGEON_MIST_TRIAL_STAT(633), + TRIGGER_DUNGEON_ELEMENT_REACTION_NUM(634), + TRIGGER_LEVEL_AVATAR_FINISH_DUNGEON_COUNT(635), + TRIGGER_CHESS_REACH_LEVEL(636), + TRIGGER_CHESS_DUNGEON_ADD_SCORE(637), + TRIGGER_CHESS_DUNGEON_SUCC_WITH_ESCAPED_MONSTERS_LESS_THAN(638), + TRIGGER_CHESS_DUNGEON_SUCC_WITH_TOWER_COUNT_LESS_OR_EQUAL(639), + TRIGGER_CHESS_DUNGEON_SUCC_WITH_CARD_COUNT_LESS_OR_EQUAL(640), + TRIGGER_CHESS_DUNGEON_SUCC_WITH_CARD_COUNT_GREATER_THAN(641), + TRIGGER_CHESS_KILL_MONSTERS(642), + TRIGGER_CHESS_COST_BUILDING_POINTS(643), + TRIGGER_SUMO_STAGE_SCORE_REACH(644), + TRIGGER_SUMO_TOTAL_MAX_SCORE_REACH(645), + TRIGGER_ROGUE_DESTROY_GADGET_NUM(646), + TRIGGER_ROGUE_KILL_MONSTER_NUM(647), + TRIGGER_ROGUE_FINISH_WITHOUT_USING_SPRING_CELL(649), + TRIGGER_ROGUE_FINISH_ALL_CHALLENGE_CELL(650), + TRIGGER_ROGUE_FINISH_WITH_AVATAR_ELEMENT_TYPE_NUM_LESS_THAN(651), + TRIGGER_ROGUE_FINISH_WITH_AVATAR_NUM_LESS_THAN(652), + TRIGGER_ROGUE_FINISH_NO_AVATAR_DEAD(653), + TRIGGER_ROGUE_SHIKIGAMI_UPGRADE(654), + TRIGGER_ROGUE_CURSE_NUM(655), + TRIGGER_ROGUE_SELECT_CARD_NUM(656), + TRIGGER_FINISH_QUEST_AND(700), + TRIGGER_FINISH_QUEST_OR(701), + TRIGGER_DAILY_TASK_VAR_EQUAL(702), + TRIGGER_QUEST_GLOBAL_VAR_EQUAL(703), + TRIGGER_TALK_NUM(704), + TRIGGER_FINISH_PARENT_QUEST_AND(705), + TRIGGER_FINISH_PARENT_QUEST_OR(706), + TRIGGER_ELEMENT_REACTION_TIMELIMIT_NUM(800), + TRIGGER_ELEMENT_REACTION_TIMELIMIT_KILL_NUM(801), + TRIGGER_ELEMENT_REACTION_TIMELIMIT_DAMAGE_NUM(802), + TRIGGER_ABILITY_STATE_PASS_TIME(803), + TRIGGER_MAX_CRITICAL_DAMAGE(804), + TRIGGER_FULL_SATIATION_TEAM_AVATAR_NUM(805), + TRIGGER_KILLED_BY_CERTAIN_MONSTER(806), + TRIGGER_CUR_AVATAR_HURT(807), + TRIGGER_CUR_AVATAR_ABILITY_STATE(808), + TRIGGER_USE_ENERGY_SKILL_NUM_TIMELIMIT(809), + TRIGGER_SHIELD_SOURCE_NUM(810), + TRIGGER_CUR_AVATAR_HURT_BY_SPECIFIC_ABILITY(811), + TRIGGER_KILLED_BY_SPECIFIC_ABILITY(812), + TRIGGER_MAX_DASH_TIME(900), + TRIGGER_MAX_FLY_TIME(901), + TRIGGER_MAX_FLY_MAP_DISTANCE(902), + TRIGGER_SIT_DOWN_IN_POINT(903), + TRIGGER_DASH(904), + TRIGGER_CLIMB(905), + TRIGGER_FLY(906), + TRIGGER_CITY_REPUTATION_LEVEL(930), + TRIGGER_CITY_REPUTATION_FINISH_REQUEST(931), + TRIGGER_HUNTING_FINISH_NUM(932), + TRIGGER_HUNTING_FAIL_NUM(933), + TRIGGER_OFFERING_LEVEL(934), + TRIGGER_MIRACLE_RING_DELIVER_ITEM(935), + TRIGGER_MIRACLE_RING_TAKE_REWARD(936), + TRIGGER_BLESSING_EXCHANGE_PIC_NUM(937), + TRIGGER_BLESSING_REDEEM_REWARD_NUM(938), + TRIGGER_GALLERY_BALLOON_REACH_SCORE(939), + TRIGGER_GALLERY_FALL_REACH_SCORE(940), + TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE(941), + TRIGGER_MAIN_COOP_SAVE_POINT_AND(942), + TRIGGER_MAIN_COOP_SAVE_POINT_OR(943), + TRIGGER_MAIN_COOP_VAR_EQUAL(944), + TRIGGER_FINISH_ALL_ARENA_CHALLENGE_WATCHER_IN_SCHEDULE(945), + TRIGGER_GALLERY_BUOYANT_COMBAT_REACH_SCORE(946), + TRIGGER_BUOYANT_COMBAT_REACH_NEW_SCORE_LEVEL(947), + TRIGGER_PLACE_MIRACLE_RING(948), + TRIGGER_LUNA_RITE_SEARCH(949), + TRIGGER_GALLERY_FISH_REACH_SCORE(950), + TRIGGER_GALLERY_TRIATHLON_REACH_SCORE(951), + TRIGGER_WINTER_CAMP_SNOWMAN_COMPLEIET(952), + TRIGGER_CREATE_CUSTOM_DUNGEON(953), + TRIGGER_PUBLISH_CUSTOM_DUNGEON(954), + TRIGGER_PLAY_OTHER_CUSTOM_DUNGEON(955), + TRIGGER_FINISH_CUSTOM_DUNGEON_OFFICIAL(956), + TRIGGER_CUSTOM_DUNGEON_OFFICIAL_COIN(957), + TRIGGER_OBTAIN_WOOD_TYPE(1000), + TRIGGER_OBTAIN_WOOD_COUNT(1001), + TRIGGER_UNLOCK_FURNITURE_COUNT(1002), + TRIGGER_FURNITURE_MAKE(1003), + TRIGGER_HOME_LEVEL(1004), + TRIGGER_HOME_COIN(1005), + TRIGGER_HOME_COMFORT_LEVEL(1006), + TRIGGER_HOME_LIMITED_SHOP_BUY(1007), + TRIGGER_FURNITURE_SUITE_TYPE(1008), + TRIGGER_ARRANGEMENT_FURNITURE_COUNT(1009), + TRIGGER_ENTER_SELF_HOME(1010), + TRIGGER_HOME_MODULE_COMFORT_VALUE(1011), + TRIGGER_HOME_ENTER_ROOM(1012), + TRIGGER_HOME_AVATAR_IN(1013), + TRIGGER_HOME_AVATAR_REWARD_EVENT_COUNT(1014), + TRIGGER_HOME_AVATAR_TALK_FINISH_COUNT(1015), + TRIGGER_HOME_AVATAR_REWARD_EVENT_ALL_COUNT(1016), + TRIGGER_HOME_AVATAR_TALK_FINISH_ALL_COUNT(1017), + TRIGGER_HOME_AVATAR_FETTER_GET(1018), + TRIGGER_HOME_AVATAR_IN_COUNT(1019), + TRIGGER_HOME_DO_PLANT(1020), + TRIGGER_ARRANGEMENT_FURNITURE(1021), + TRIGGER_HOME_GATHER_COUNT(1022), + TRIGGER_HOME_FIELD_GATHER_COUNT(1023), + TRIGGER_HOME_UNLOCK_BGM_COUNT(1024), + TRIGGER_FISHING_SUCC_NUM(1100), + TRIGGER_FISHING_KEEP_BONUS(1101), + TRIGGER_EMPTY_FISH_POOL(1102), + TRIGGER_FISHING_FAIL_NUM(1103), + TRIGGER_SHOCK_FISH_NUM(1104), + TRIGGER_PLANT_FLOWER_SET_WISH(1105), + TRIGGER_PLANT_FLOWER_GIVE_FLOWER(1106), + TRIGGER_PLANT_FLOWER_OBTAIN_FLOWER_TYPE(1107), + TRIGGER_PLANT_FLOWER_COMMON_OBTAIN_FLOWER_TYPE(1108), + TRIGGER_FINISH_LANV2_PROJECTION_LEVEL(1111), + TRIGGER_GALLERY_SALVAGE_REACH_SCORE(1112), + TRIGGER_LANV2_FIREWORKS_CHALLENGE_REACH_SCORE(1113), + TRIGGER_POTION_STAGE_LEVEL_PASS_NUM(1115), + TRIGGER_POTION_STAGE_OBTAIN_MEDAL_NUM(1116), + TRIGGER_POTION_STAGE_REACH_TOTAL_SCORE(1117), + TRIGGER_BARTENDER_FINISH_STORY_MODULE(1120), + TRIGGER_BARTENDER_CHALLENGE_MODULE_LEVEL_SCORE(1121), + TRIGGER_BARTENDER_UNLOCK_FORMULA(1122), + TRIGGER_MICHIAE_MATSURI_UNLOCK_CRYSTAL_SKILL_REACH_NUM(1123), + TRIGGER_MICHIAE_MATSURI_FINISH_DARK_CHALLENGE_REACH_NUM(1124), + TRIGGER_CAPTURE_ENV_ANIMAL_REACH_NUM(1125), + TRIGGER_SPICE_MAKE_FORMULA_TIMES(1126), + TRIGGER_SPICE_GIVE_FOOD_TIMES(1127), + TRIGGER_SPICE_MAKE_FORMULA_SUCCESSFUL_TIMES(1128), + TRIGGER_IRODORI_FINISH_FLOWER_THEME(1131), + TRIGGER_IRODORI_FINISH_MASTER_STAGE(1132), + TRIGGER_IRODORI_CHESS_STAGE_REACH_SCORE(1133), + TRIGGER_IRODORI_FINISH_POETRY_THEME(1134), + TRIGGER_PHOTO_FINISH_POS_ID(1135), + TRIGGER_CRYSTAL_LINK_LEVEL_SCORE_REACH(1138), + TRIGGER_CRYSTAL_LINK_TOTAL_MAX_SCORE_REACH(1139); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + + WatcherTriggerType(int value) { + this.value = value; + } + + public static WatcherTriggerType getTypeByValue(int value) { + return map.getOrDefault(value, TRIGGER_NONE); + } + + public static WatcherTriggerType getTypeByName(String name) { + return stringMap.getOrDefault(name, TRIGGER_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/props/WeaponType.java b/src/main/java/emu/grasscutter/game/props/WeaponType.java index e2f297885..0d8414750 100644 --- a/src/main/java/emu/grasscutter/game/props/WeaponType.java +++ b/src/main/java/emu/grasscutter/game/props/WeaponType.java @@ -1,69 +1,70 @@ -package emu.grasscutter.game.props; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum WeaponType { - WEAPON_NONE(0), - WEAPON_SWORD_ONE_HAND(1, 10, 5), - WEAPON_CROSSBOW(2), - WEAPON_STAFF(3), - WEAPON_DOUBLE_DAGGER(4), - WEAPON_KATANA(5), - WEAPON_SHURIKEN(6), - WEAPON_STICK(7), - WEAPON_SPEAR(8), - WEAPON_SHIELD_SMALL(9), - WEAPON_CATALYST(10, 0, 10), - WEAPON_CLAYMORE(11, 0, 10), - WEAPON_BOW(12, 0, 5), - WEAPON_POLE(13, 0, 4); - - private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - private static final Map stringMap = new HashMap<>(); - - static { - Stream.of(values()).forEach(e -> { - map.put(e.getValue(), e); - stringMap.put(e.name(), e); - }); - } - - private final int value; - private int energyGainInitialProbability; - private int energyGainIncreaseProbability; - - WeaponType(int value) { - this.value = value; - } - - WeaponType(int value, int energyGainInitialProbability, int energyGainIncreaseProbability) { - this.value = value; - this.energyGainInitialProbability = energyGainInitialProbability; - this.energyGainIncreaseProbability = energyGainIncreaseProbability; - } - - public static WeaponType getTypeByValue(int value) { - return map.getOrDefault(value, WEAPON_NONE); - } - - public static WeaponType getTypeByName(String name) { - return stringMap.getOrDefault(name, WEAPON_NONE); - } - - public int getValue() { - return value; - } - - public int getEnergyGainInitialProbability() { - return energyGainInitialProbability; - } - - public int getEnergyGainIncreaseProbability() { - return energyGainIncreaseProbability; - } -} +package emu.grasscutter.game.props; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum WeaponType { + WEAPON_NONE(0), + WEAPON_SWORD_ONE_HAND(1, 10, 5), + WEAPON_CROSSBOW(2), + WEAPON_STAFF(3), + WEAPON_DOUBLE_DAGGER(4), + WEAPON_KATANA(5), + WEAPON_SHURIKEN(6), + WEAPON_STICK(7), + WEAPON_SPEAR(8), + WEAPON_SHIELD_SMALL(9), + WEAPON_CATALYST(10, 0, 10), + WEAPON_CLAYMORE(11, 0, 10), + WEAPON_BOW(12, 0, 5), + WEAPON_POLE(13, 0, 4); + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()) + .forEach( + e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private final int value; + private int energyGainInitialProbability; + private int energyGainIncreaseProbability; + + WeaponType(int value) { + this.value = value; + } + + WeaponType(int value, int energyGainInitialProbability, int energyGainIncreaseProbability) { + this.value = value; + this.energyGainInitialProbability = energyGainInitialProbability; + this.energyGainIncreaseProbability = energyGainIncreaseProbability; + } + + public static WeaponType getTypeByValue(int value) { + return map.getOrDefault(value, WEAPON_NONE); + } + + public static WeaponType getTypeByName(String name) { + return stringMap.getOrDefault(name, WEAPON_NONE); + } + + public int getValue() { + return value; + } + + public int getEnergyGainInitialProbability() { + return energyGainInitialProbability; + } + + public int getEnergyGainIncreaseProbability() { + return energyGainIncreaseProbability; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java index 78b1686b6..449fadd68 100644 --- a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java +++ b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java @@ -1,401 +1,443 @@ -package emu.grasscutter.game.quest; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Id; -import dev.morphia.annotations.Indexed; -import dev.morphia.annotations.Transient; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.binout.MainQuestData.SubQuestData; -import emu.grasscutter.data.binout.MainQuestData.TalkData; -import emu.grasscutter.data.binout.ScriptSceneData; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.data.excels.RewardData; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.quest.enums.LogicType; -import emu.grasscutter.game.quest.enums.ParentQuestState; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest; -import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest; -import emu.grasscutter.scripts.ScriptLoader; -import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; -import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; -import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; -import emu.grasscutter.utils.Position; -import lombok.Getter; -import org.bson.types.ObjectId; - -import javax.script.Bindings; -import javax.script.CompiledScript; -import javax.script.ScriptException; -import java.util.*; - - -@Entity(value = "quests", useDiscriminator = false) -public class GameMainQuest { - @Getter - List questGroupSuites; - @Getter - int[] suggestTrackMainQuestList; - @Id - private ObjectId id; - @Indexed - @Getter - private int ownerUid; - @Transient - @Getter - private Player owner; - @Transient - @Getter - private QuestManager questManager; - @Getter - private Map childQuests; - @Getter - private int parentQuestId; - @Getter - private int[] questVars; - //QuestUpdateQuestVarReq is sent in two stages... - @Getter - private List questVarsUpdate; - @Getter - private ParentQuestState state; - @Getter - private boolean isFinished; - @Getter - private Map talks; - //key is subId - private Map rewindPositions; - private Map rewindRotations; - - @Deprecated // Morphia only. Do not use. - public GameMainQuest() { - } - - public GameMainQuest(Player player, int parentQuestId) { - this.owner = player; - this.ownerUid = player.getUid(); - this.questManager = player.getQuestManager(); - this.parentQuestId = parentQuestId; - this.childQuests = new HashMap<>(); - this.talks = new HashMap<>(); - //official server always has a list of 5 questVars, with default value 0 - this.questVars = new int[]{0, 0, 0, 0, 0}; - this.state = ParentQuestState.PARENT_QUEST_STATE_NONE; - this.questGroupSuites = new ArrayList<>(); - this.rewindPositions = new HashMap<>(); - this.rewindRotations = new HashMap<>(); - addAllChildQuests(); - addRewindPoints(); - } - - private void addAllChildQuests() { - List subQuestIds = Arrays.stream(GameData.getMainQuestDataMap().get(this.parentQuestId).getSubQuests()).map(SubQuestData::getSubId).toList(); - for (Integer subQuestId : subQuestIds) { - QuestData questConfig = GameData.getQuestDataMap().get(subQuestId); - this.childQuests.put(subQuestId, new GameQuest(this, questConfig)); - } - } - - public void setOwner(Player player) { - if (player.getUid() != this.getOwnerUid()) return; - this.owner = player; - } - - public int getQuestVar(int i) { - return questVars[i]; - } - - public void setQuestVar(int i, int value) { - int previousValue = this.questVars[i]; - this.questVars[i] = value; - Grasscutter.getLogger().debug("questVar {} value changed from {} to {}", i, previousValue, value); - } - - public void incQuestVar(int i, int inc) { - int previousValue = this.questVars[i]; - this.questVars[i] += inc; - Grasscutter.getLogger().debug("questVar {} value incremented from {} to {}", i, previousValue, previousValue + inc); - } - - public void decQuestVar(int i, int dec) { - int previousValue = this.questVars[i]; - this.questVars[i] -= dec; - Grasscutter.getLogger().debug("questVar {} value decremented from {} to {}", i, previousValue, previousValue - dec); - } - - - public GameQuest getChildQuestById(int id) { - return this.getChildQuests().get(id); - } - - public GameQuest getChildQuestByOrder(int order) { - return this.getChildQuests().values().stream().filter(p -> p.getQuestData().getOrder() == order).toList().get(0); - } - - public void finish() { - this.isFinished = true; - this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED; - - this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this)); - this.getOwner().getSession().send(new PacketCodexDataUpdateNotify(this)); - - this.save(); - - // Add rewards - MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(this.getParentQuestId()); - if (mainQuestData != null && mainQuestData.getRewardIdList() != null) { - for (int rewardId : mainQuestData.getRewardIdList()) { - RewardData rewardData = GameData.getRewardDataMap().get(rewardId); - - if (rewardData == null) { - continue; - } - - getOwner().getInventory().addItemParamDatas(rewardData.getRewardItemList(), ActionReason.QuestReward); - } - } - - // handoff main quest - if (mainQuestData.getSuggestTrackMainQuestList() != null) { - Arrays.stream(mainQuestData.getSuggestTrackMainQuestList()) - .forEach(getQuestManager()::startMainQuest); - } - } - - //TODO - public void fail() { - } - - public void cancel() { - } - - // Rewinds to the last finished/unfinished rewind quest, and returns the avatar rewind position (if it exists) - public List rewind() { - if (this.questManager == null) { - this.questManager = getOwner().getQuestManager(); - } - List sortedByOrder = new ArrayList<>(getChildQuests().values().stream().filter(q -> q.getQuestData().isRewind()).toList()); - sortedByOrder.sort((a, b) -> { - if (a == b) { - return 0; - } - return a.getQuestData().getOrder() > b.getQuestData().getOrder() ? 1 : -1; - }); - boolean didRewind = false; - for (GameQuest quest : sortedByOrder) { - int i = sortedByOrder.indexOf(quest); - if ((i + 1) >= sortedByOrder.size()) { - didRewind = quest.rewind(null); - } else { - didRewind = quest.rewind(sortedByOrder.get(i + 1)); - } - if (didRewind) { - break; - } - } - List rewindQuests = getChildQuests().values().stream() - .filter(p -> (p.getState() == QuestState.QUEST_STATE_UNFINISHED || p.getState() == QuestState.QUEST_STATE_FINISHED) && p.getQuestData().isRewind()).toList(); - for (GameQuest quest : rewindQuests) { - if (rewindPositions.containsKey(quest.getSubQuestId())) { - List posAndRot = new ArrayList<>(); - posAndRot.add(0, rewindPositions.get(quest.getSubQuestId())); - posAndRot.add(1, rewindRotations.get(quest.getSubQuestId())); - return posAndRot; - } - } - return null; - } - - public void addRewindPoints() { - Bindings bindings = ScriptLoader.getEngine().createBindings(); - String script = "Quest/Share/Q" + getParentQuestId() + "ShareConfig.lua"; - CompiledScript cs = ScriptLoader.getScript(script); - - //mainQuest 303 doesn't have a ShareConfig - if (cs == null) { - Grasscutter.getLogger().debug("Couldn't find " + script); - return; - } - - - // Eval script - try { - cs.eval(bindings); - - var rewindDataMap = ScriptLoader.getSerializer().toMap(RewindData.class, bindings.get("rewind_data")); - for (String subId : rewindDataMap.keySet()) { - RewindData questRewind = rewindDataMap.get(subId); - if (questRewind != null) { - RewindData.AvatarData avatarData = questRewind.getAvatar(); - if (avatarData != null) { - String avatarPos = avatarData.getPos(); - QuestData.Guide guide = GameData.getQuestDataMap().get(Integer.valueOf(subId)).getGuide(); - if (guide != null) { - int sceneId = guide.getGuideScene(); - ScriptSceneData fullGlobals = GameData.getScriptSceneDataMap().get("flat.luas.scenes.full_globals.lua.json"); - if (fullGlobals != null) { - ScriptSceneData.ScriptObject dummyPointScript = fullGlobals.getScriptObjectList().get(sceneId + "/scene" + sceneId + "_dummy_points.lua"); - if (dummyPointScript != null) { - Map> dummyPointMap = dummyPointScript.getDummyPoints(); - if (dummyPointMap != null) { - List avatarPosPos = dummyPointMap.get(avatarPos + ".pos"); - if (avatarPosPos != null) { - Position pos = new Position(avatarPosPos.get(0), avatarPosPos.get(1), avatarPosPos.get(2)); - List avatarPosRot = dummyPointMap.get(avatarPos + ".rot"); - Position rot = new Position(avatarPosRot.get(0), avatarPosRot.get(1), avatarPosRot.get(2)); - rewindPositions.put(Integer.valueOf(subId), pos); - rewindRotations.put(Integer.valueOf(subId), rot); - Grasscutter.getLogger().debug("Succesfully loaded rewind position for subQuest {}", subId); - } - } - } - } - } - } - } - } - - } catch (ScriptException e) { - Grasscutter.getLogger().error("An error occurred while loading rewind positions"); - } - } - - public void tryAcceptSubQuests(QuestTrigger condType, String paramStr, int... params) { - try { - List subQuestsWithCond = getChildQuests().values().stream() - .filter(p -> p.getState() == QuestState.QUEST_STATE_UNSTARTED) - .filter(p -> p.getQuestData().getAcceptCond().stream().anyMatch(q -> q.getType() == condType)) - .toList(); - - for (GameQuest subQuestWithCond : subQuestsWithCond) { - List acceptCond = subQuestWithCond.getQuestData().getAcceptCond(); - int[] accept = new int[acceptCond.size()]; - - for (int i = 0; i < subQuestWithCond.getQuestData().getAcceptCond().size(); i++) { - QuestData.QuestCondition condition = acceptCond.get(i); - boolean result = this.getOwner().getServer().getQuestSystem().triggerCondition(subQuestWithCond, condition, paramStr, params); - accept[i] = result ? 1 : 0; - } - - boolean shouldAccept = LogicType.calculate(subQuestWithCond.getQuestData().getAcceptCondComb(), accept); - - if (shouldAccept) { - subQuestWithCond.start(); - getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); - } - - } - this.save(); - } catch (Exception e) { - Grasscutter.getLogger().error("An error occurred while trying to accept quest.", e); - } - - } - - public void tryFailSubQuests(QuestTrigger condType, String paramStr, int... params) { - try { - List subQuestsWithCond = getChildQuests().values().stream() - .filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED) - .filter(p -> p.getQuestData().getFailCond().stream().anyMatch(q -> q.getType() == condType)) - .toList(); - - for (GameQuest subQuestWithCond : subQuestsWithCond) { - List failCond = subQuestWithCond.getQuestData().getFailCond(); - - for (int i = 0; i < subQuestWithCond.getQuestData().getFailCond().size(); i++) { - QuestData.QuestCondition condition = failCond.get(i); - if (condition.getType() == condType) { - boolean result = this.getOwner().getServer().getQuestSystem().triggerContent(subQuestWithCond, condition, paramStr, params); - subQuestWithCond.getFailProgressList()[i] = result ? 1 : 0; - if (result) { - getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond)); - } - } - } - - boolean shouldFail = LogicType.calculate(subQuestWithCond.getQuestData().getFailCondComb(), subQuestWithCond.getFailProgressList()); - - if (shouldFail) { - subQuestWithCond.fail(); - getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); - } - } - - } catch (Exception e) { - Grasscutter.getLogger().error("An error occurred while trying to fail quest.", e); - } - } - - public void tryFinishSubQuests(QuestTrigger condType, String paramStr, int... params) { - try { - List subQuestsWithCond = getChildQuests().values().stream() - //There are subQuests with no acceptCond, but can be finished (example: 35104) - .filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED && p.getQuestData().getAcceptCond() != null) - .filter(p -> p.getQuestData().getFinishCond().stream().anyMatch(q -> q.getType() == condType)) - .toList(); - - for (GameQuest subQuestWithCond : subQuestsWithCond) { - List finishCond = subQuestWithCond.getQuestData().getFinishCond(); - - for (int i = 0; i < finishCond.size(); i++) { - QuestData.QuestCondition condition = finishCond.get(i); - if (condition.getType() == condType) { - boolean result = this.getOwner().getServer().getQuestSystem().triggerContent(subQuestWithCond, condition, paramStr, params); - subQuestWithCond.getFinishProgressList()[i] = result ? 1 : 0; - if (result) { - getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond)); - } - } - } - - boolean shouldFinish = LogicType.calculate(subQuestWithCond.getQuestData().getFinishCondComb(), subQuestWithCond.getFinishProgressList()); - - if (shouldFinish) { - subQuestWithCond.finish(); - getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); - } - } - } catch (Exception e) { - Grasscutter.getLogger().debug("An error occurred while trying to finish quest.", e); - } - } - - public void save() { - DatabaseHelper.saveQuest(this); - } - - public void delete() { - DatabaseHelper.deleteQuest(this); - } - - public ParentQuest toProto() { - ParentQuest.Builder proto = ParentQuest.newBuilder() - .setParentQuestId(getParentQuestId()) - .setIsFinished(isFinished()); - - proto.setParentQuestState(getState().getValue()) - .setVideoKey(QuestManager.getQuestKey(parentQuestId)); - for (GameQuest quest : this.getChildQuests().values()) { - if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) { - ChildQuest childQuest = ChildQuest.newBuilder() - .setQuestId(quest.getSubQuestId()) - .setState(quest.getState().getValue()) - .build(); - - proto.addChildQuestList(childQuest); - } - } - - for (int i : getQuestVars()) { - proto.addQuestVar(i); - } - - - return proto.build(); - } - -} +package emu.grasscutter.game.quest; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.binout.MainQuestData.SubQuestData; +import emu.grasscutter.data.binout.MainQuestData.TalkData; +import emu.grasscutter.data.binout.ScriptSceneData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.data.excels.RewardData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.ParentQuestState; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest; +import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest; +import emu.grasscutter.scripts.ScriptLoader; +import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; +import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.utils.Position; +import java.util.*; +import javax.script.Bindings; +import javax.script.CompiledScript; +import javax.script.ScriptException; +import lombok.Getter; +import org.bson.types.ObjectId; + +@Entity(value = "quests", useDiscriminator = false) +public class GameMainQuest { + @Getter List questGroupSuites; + @Getter int[] suggestTrackMainQuestList; + @Id private ObjectId id; + @Indexed @Getter private int ownerUid; + @Transient @Getter private Player owner; + @Transient @Getter private QuestManager questManager; + @Getter private Map childQuests; + @Getter private int parentQuestId; + @Getter private int[] questVars; + // QuestUpdateQuestVarReq is sent in two stages... + @Getter private List questVarsUpdate; + @Getter private ParentQuestState state; + @Getter private boolean isFinished; + @Getter private Map talks; + // key is subId + private Map rewindPositions; + private Map rewindRotations; + + @Deprecated // Morphia only. Do not use. + public GameMainQuest() {} + + public GameMainQuest(Player player, int parentQuestId) { + this.owner = player; + this.ownerUid = player.getUid(); + this.questManager = player.getQuestManager(); + this.parentQuestId = parentQuestId; + this.childQuests = new HashMap<>(); + this.talks = new HashMap<>(); + // official server always has a list of 5 questVars, with default value 0 + this.questVars = new int[] {0, 0, 0, 0, 0}; + this.state = ParentQuestState.PARENT_QUEST_STATE_NONE; + this.questGroupSuites = new ArrayList<>(); + this.rewindPositions = new HashMap<>(); + this.rewindRotations = new HashMap<>(); + addAllChildQuests(); + addRewindPoints(); + } + + private void addAllChildQuests() { + List subQuestIds = + Arrays.stream(GameData.getMainQuestDataMap().get(this.parentQuestId).getSubQuests()) + .map(SubQuestData::getSubId) + .toList(); + for (Integer subQuestId : subQuestIds) { + QuestData questConfig = GameData.getQuestDataMap().get(subQuestId); + this.childQuests.put(subQuestId, new GameQuest(this, questConfig)); + } + } + + public void setOwner(Player player) { + if (player.getUid() != this.getOwnerUid()) return; + this.owner = player; + } + + public int getQuestVar(int i) { + return questVars[i]; + } + + public void setQuestVar(int i, int value) { + int previousValue = this.questVars[i]; + this.questVars[i] = value; + Grasscutter.getLogger() + .debug("questVar {} value changed from {} to {}", i, previousValue, value); + } + + public void incQuestVar(int i, int inc) { + int previousValue = this.questVars[i]; + this.questVars[i] += inc; + Grasscutter.getLogger() + .debug( + "questVar {} value incremented from {} to {}", i, previousValue, previousValue + inc); + } + + public void decQuestVar(int i, int dec) { + int previousValue = this.questVars[i]; + this.questVars[i] -= dec; + Grasscutter.getLogger() + .debug( + "questVar {} value decremented from {} to {}", i, previousValue, previousValue - dec); + } + + public GameQuest getChildQuestById(int id) { + return this.getChildQuests().get(id); + } + + public GameQuest getChildQuestByOrder(int order) { + return this.getChildQuests().values().stream() + .filter(p -> p.getQuestData().getOrder() == order) + .toList() + .get(0); + } + + public void finish() { + this.isFinished = true; + this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED; + + this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this)); + this.getOwner().getSession().send(new PacketCodexDataUpdateNotify(this)); + + this.save(); + + // Add rewards + MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(this.getParentQuestId()); + if (mainQuestData != null && mainQuestData.getRewardIdList() != null) { + for (int rewardId : mainQuestData.getRewardIdList()) { + RewardData rewardData = GameData.getRewardDataMap().get(rewardId); + + if (rewardData == null) { + continue; + } + + getOwner() + .getInventory() + .addItemParamDatas(rewardData.getRewardItemList(), ActionReason.QuestReward); + } + } + + // handoff main quest + if (mainQuestData.getSuggestTrackMainQuestList() != null) { + Arrays.stream(mainQuestData.getSuggestTrackMainQuestList()) + .forEach(getQuestManager()::startMainQuest); + } + } + + // TODO + public void fail() {} + + public void cancel() {} + + // Rewinds to the last finished/unfinished rewind quest, and returns the avatar rewind position + // (if it exists) + public List rewind() { + if (this.questManager == null) { + this.questManager = getOwner().getQuestManager(); + } + List sortedByOrder = + new ArrayList<>( + getChildQuests().values().stream().filter(q -> q.getQuestData().isRewind()).toList()); + sortedByOrder.sort( + (a, b) -> { + if (a == b) { + return 0; + } + return a.getQuestData().getOrder() > b.getQuestData().getOrder() ? 1 : -1; + }); + boolean didRewind = false; + for (GameQuest quest : sortedByOrder) { + int i = sortedByOrder.indexOf(quest); + if ((i + 1) >= sortedByOrder.size()) { + didRewind = quest.rewind(null); + } else { + didRewind = quest.rewind(sortedByOrder.get(i + 1)); + } + if (didRewind) { + break; + } + } + List rewindQuests = + getChildQuests().values().stream() + .filter( + p -> + (p.getState() == QuestState.QUEST_STATE_UNFINISHED + || p.getState() == QuestState.QUEST_STATE_FINISHED) + && p.getQuestData().isRewind()) + .toList(); + for (GameQuest quest : rewindQuests) { + if (rewindPositions.containsKey(quest.getSubQuestId())) { + List posAndRot = new ArrayList<>(); + posAndRot.add(0, rewindPositions.get(quest.getSubQuestId())); + posAndRot.add(1, rewindRotations.get(quest.getSubQuestId())); + return posAndRot; + } + } + return null; + } + + public void addRewindPoints() { + Bindings bindings = ScriptLoader.getEngine().createBindings(); + String script = "Quest/Share/Q" + getParentQuestId() + "ShareConfig.lua"; + CompiledScript cs = ScriptLoader.getScript(script); + + // mainQuest 303 doesn't have a ShareConfig + if (cs == null) { + Grasscutter.getLogger().debug("Couldn't find " + script); + return; + } + + // Eval script + try { + cs.eval(bindings); + + var rewindDataMap = + ScriptLoader.getSerializer().toMap(RewindData.class, bindings.get("rewind_data")); + for (String subId : rewindDataMap.keySet()) { + RewindData questRewind = rewindDataMap.get(subId); + if (questRewind != null) { + RewindData.AvatarData avatarData = questRewind.getAvatar(); + if (avatarData != null) { + String avatarPos = avatarData.getPos(); + QuestData.Guide guide = + GameData.getQuestDataMap().get(Integer.valueOf(subId)).getGuide(); + if (guide != null) { + int sceneId = guide.getGuideScene(); + ScriptSceneData fullGlobals = + GameData.getScriptSceneDataMap().get("flat.luas.scenes.full_globals.lua.json"); + if (fullGlobals != null) { + ScriptSceneData.ScriptObject dummyPointScript = + fullGlobals + .getScriptObjectList() + .get(sceneId + "/scene" + sceneId + "_dummy_points.lua"); + if (dummyPointScript != null) { + Map> dummyPointMap = dummyPointScript.getDummyPoints(); + if (dummyPointMap != null) { + List avatarPosPos = dummyPointMap.get(avatarPos + ".pos"); + if (avatarPosPos != null) { + Position pos = + new Position( + avatarPosPos.get(0), avatarPosPos.get(1), avatarPosPos.get(2)); + List avatarPosRot = dummyPointMap.get(avatarPos + ".rot"); + Position rot = + new Position( + avatarPosRot.get(0), avatarPosRot.get(1), avatarPosRot.get(2)); + rewindPositions.put(Integer.valueOf(subId), pos); + rewindRotations.put(Integer.valueOf(subId), rot); + Grasscutter.getLogger() + .debug("Succesfully loaded rewind position for subQuest {}", subId); + } + } + } + } + } + } + } + } + + } catch (ScriptException e) { + Grasscutter.getLogger().error("An error occurred while loading rewind positions"); + } + } + + public void tryAcceptSubQuests(QuestTrigger condType, String paramStr, int... params) { + try { + List subQuestsWithCond = + getChildQuests().values().stream() + .filter(p -> p.getState() == QuestState.QUEST_STATE_UNSTARTED) + .filter( + p -> + p.getQuestData().getAcceptCond().stream() + .anyMatch(q -> q.getType() == condType)) + .toList(); + + for (GameQuest subQuestWithCond : subQuestsWithCond) { + List acceptCond = subQuestWithCond.getQuestData().getAcceptCond(); + int[] accept = new int[acceptCond.size()]; + + for (int i = 0; i < subQuestWithCond.getQuestData().getAcceptCond().size(); i++) { + QuestData.QuestCondition condition = acceptCond.get(i); + boolean result = + this.getOwner() + .getServer() + .getQuestSystem() + .triggerCondition(subQuestWithCond, condition, paramStr, params); + accept[i] = result ? 1 : 0; + } + + boolean shouldAccept = + LogicType.calculate(subQuestWithCond.getQuestData().getAcceptCondComb(), accept); + + if (shouldAccept) { + subQuestWithCond.start(); + getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); + } + } + this.save(); + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while trying to accept quest.", e); + } + } + + public void tryFailSubQuests(QuestTrigger condType, String paramStr, int... params) { + try { + List subQuestsWithCond = + getChildQuests().values().stream() + .filter(p -> p.getState() == QuestState.QUEST_STATE_UNFINISHED) + .filter( + p -> + p.getQuestData().getFailCond().stream() + .anyMatch(q -> q.getType() == condType)) + .toList(); + + for (GameQuest subQuestWithCond : subQuestsWithCond) { + List failCond = subQuestWithCond.getQuestData().getFailCond(); + + for (int i = 0; i < subQuestWithCond.getQuestData().getFailCond().size(); i++) { + QuestData.QuestCondition condition = failCond.get(i); + if (condition.getType() == condType) { + boolean result = + this.getOwner() + .getServer() + .getQuestSystem() + .triggerContent(subQuestWithCond, condition, paramStr, params); + subQuestWithCond.getFailProgressList()[i] = result ? 1 : 0; + if (result) { + getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond)); + } + } + } + + boolean shouldFail = + LogicType.calculate( + subQuestWithCond.getQuestData().getFailCondComb(), + subQuestWithCond.getFailProgressList()); + + if (shouldFail) { + subQuestWithCond.fail(); + getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); + } + } + + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while trying to fail quest.", e); + } + } + + public void tryFinishSubQuests(QuestTrigger condType, String paramStr, int... params) { + try { + List subQuestsWithCond = + getChildQuests().values().stream() + // There are subQuests with no acceptCond, but can be finished (example: 35104) + .filter( + p -> + p.getState() == QuestState.QUEST_STATE_UNFINISHED + && p.getQuestData().getAcceptCond() != null) + .filter( + p -> + p.getQuestData().getFinishCond().stream() + .anyMatch(q -> q.getType() == condType)) + .toList(); + + for (GameQuest subQuestWithCond : subQuestsWithCond) { + List finishCond = subQuestWithCond.getQuestData().getFinishCond(); + + for (int i = 0; i < finishCond.size(); i++) { + QuestData.QuestCondition condition = finishCond.get(i); + if (condition.getType() == condType) { + boolean result = + this.getOwner() + .getServer() + .getQuestSystem() + .triggerContent(subQuestWithCond, condition, paramStr, params); + subQuestWithCond.getFinishProgressList()[i] = result ? 1 : 0; + if (result) { + getOwner().getSession().send(new PacketQuestProgressUpdateNotify(subQuestWithCond)); + } + } + } + + boolean shouldFinish = + LogicType.calculate( + subQuestWithCond.getQuestData().getFinishCondComb(), + subQuestWithCond.getFinishProgressList()); + + if (shouldFinish) { + subQuestWithCond.finish(); + getQuestManager().getAddToQuestListUpdateNotify().add(subQuestWithCond); + } + } + } catch (Exception e) { + Grasscutter.getLogger().debug("An error occurred while trying to finish quest.", e); + } + } + + public void save() { + DatabaseHelper.saveQuest(this); + } + + public void delete() { + DatabaseHelper.deleteQuest(this); + } + + public ParentQuest toProto() { + ParentQuest.Builder proto = + ParentQuest.newBuilder().setParentQuestId(getParentQuestId()).setIsFinished(isFinished()); + + proto + .setParentQuestState(getState().getValue()) + .setVideoKey(QuestManager.getQuestKey(parentQuestId)); + for (GameQuest quest : this.getChildQuests().values()) { + if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) { + ChildQuest childQuest = + ChildQuest.newBuilder() + .setQuestId(quest.getSubQuestId()) + .setState(quest.getState().getValue()) + .build(); + + proto.addChildQuestList(childQuest); + } + } + + for (int i : getQuestVars()) { + proto.addQuestVar(i); + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameQuest.java b/src/main/java/emu/grasscutter/game/quest/GameQuest.java index 1648da761..a66abb991 100644 --- a/src/main/java/emu/grasscutter/game/quest/GameQuest.java +++ b/src/main/java/emu/grasscutter/game/quest/GameQuest.java @@ -1,231 +1,268 @@ -package emu.grasscutter.game.quest; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.ChapterData; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.data.excels.TriggerExcelConfigData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.proto.ChapterStateOuterClass; -import emu.grasscutter.net.proto.QuestOuterClass.Quest; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.server.packet.send.PacketChapterStateNotify; -import emu.grasscutter.utils.Utils; -import lombok.Getter; -import lombok.Setter; - -import javax.script.Bindings; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Entity -public class GameQuest { - @Transient - @Getter - @Setter - private GameMainQuest mainQuest; - @Transient - @Getter - private QuestData questData; - - @Getter - private int subQuestId; - @Getter - private int mainQuestId; - @Getter - @Setter - private QuestState state; - - @Getter - @Setter - private int startTime; - @Getter - @Setter - private int acceptTime; - @Getter - @Setter - private int finishTime; - - @Getter - private int[] finishProgressList; - @Getter - private int[] failProgressList; - @Transient - @Getter - private Map triggerData; - @Getter - private Map triggers; - private transient Bindings bindings; - - @Deprecated // Morphia only. Do not use. - public GameQuest() { - } - - public GameQuest(GameMainQuest mainQuest, QuestData questData) { - this.mainQuest = mainQuest; - this.subQuestId = questData.getId(); - this.mainQuestId = questData.getMainId(); - this.questData = questData; - this.state = QuestState.QUEST_STATE_UNSTARTED; - this.triggerData = new HashMap<>(); - this.triggers = new HashMap<>(); - } - - public void start() { - this.acceptTime = Utils.getCurrentSeconds(); - this.startTime = this.acceptTime; - this.state = QuestState.QUEST_STATE_UNFINISHED; - List triggerCond = questData.getFinishCond().stream() - .filter(p -> p.getType() == QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE).toList(); - if (triggerCond.size() > 0) { - for (QuestData.QuestCondition cond : triggerCond) { - TriggerExcelConfigData newTrigger = GameData.getTriggerExcelConfigDataMap().get(cond.getParam()[0]); - if (newTrigger != null) { - if (this.triggerData == null) { - this.triggerData = new HashMap<>(); - } - triggerData.put(newTrigger.getTriggerName(), newTrigger); - triggers.put(newTrigger.getTriggerName(), false); - SceneGroup group = SceneGroup.of(newTrigger.getGroupId()).load(newTrigger.getSceneId()); - getOwner().getWorld().getSceneById(newTrigger.getSceneId()).loadTriggerFromGroup(group, newTrigger.getTriggerName()); - } - } - } - - if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) { - this.finishProgressList = new int[questData.getFinishCond().size()]; - } - - if (questData.getFailCond() != null && questData.getFailCond().size() != 0) { - this.failProgressList = new int[questData.getFailCond().size()]; - } - - getQuestData().getBeginExec().forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); - - - if (ChapterData.beginQuestChapterMap.containsKey(subQuestId)) { - mainQuest.getOwner().sendPacket(new PacketChapterStateNotify( - ChapterData.beginQuestChapterMap.get(subQuestId).getId(), - ChapterStateOuterClass.ChapterState.CHAPTER_STATE_BEGIN - )); - } - - //Some subQuests and talks become active when some other subQuests are unfinished (even from different MainQuests) - this.getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, this.getSubQuestId(), this.getState().getValue(), 0, 0, 0); - this.getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_STATE_EQUAL, this.getSubQuestId(), this.getState().getValue(), 0, 0, 0); - - Grasscutter.getLogger().debug("Quest {} is started", subQuestId); - } - - public String getTriggerNameById(int id) { - TriggerExcelConfigData trigger = GameData.getTriggerExcelConfigDataMap().get(id); - if (trigger != null) { - String triggerName = trigger.getTriggerName(); - return triggerName; - } - //return empty string if can't find trigger - return ""; - } - - public Player getOwner() { - return this.getMainQuest().getOwner(); - } - - public void setConfig(QuestData config) { - if (getSubQuestId() != config.getId()) return; - this.questData = config; - } - - public void setFinishProgress(int index, int value) { - finishProgressList[index] = value; - } - - public void setFailProgress(int index, int value) { - failProgressList[index] = value; - } - - public void finish() { - this.state = QuestState.QUEST_STATE_FINISHED; - this.finishTime = Utils.getCurrentSeconds(); - - if (getQuestData().finishParent()) { - // This quest finishes the questline - the main quest will also save the quest to db, so we don't have to call save() here - getMainQuest().finish(); - } - - getQuestData().getFinishExec().forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); - //Some subQuests have conditions that subQuests are finished (even from different MainQuests) - getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); - getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); - - if (ChapterData.endQuestChapterMap.containsKey(subQuestId)) { - mainQuest.getOwner().sendPacket(new PacketChapterStateNotify( - ChapterData.endQuestChapterMap.get(subQuestId).getId(), - ChapterStateOuterClass.ChapterState.CHAPTER_STATE_END - )); - } - - Grasscutter.getLogger().debug("Quest {} is finished", subQuestId); - } - - //TODO - public void fail() { - this.state = QuestState.QUEST_STATE_FAILED; - this.finishTime = Utils.getCurrentSeconds(); - - getQuestData().getFailExec().forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); - //Some subQuests have conditions that subQuests fail (even from different MainQuests) - getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); - getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); - - } - - // Return true if ParentQuest should rewind to this childQuest - public boolean rewind(GameQuest nextRewind) { - if (questData.isRewind()) { - if (nextRewind == null) { - return true; - } - // if the next isRewind subQuest is none or unstarted, reset all subQuests with order higher than this one, and restart this quest - if (nextRewind.getState() == QuestState.QUEST_STATE_NONE || nextRewind.getState() == QuestState.QUEST_STATE_UNSTARTED) { - getMainQuest().getChildQuests().values().stream().filter(p -> p.getQuestData().getOrder() > this.getQuestData().getOrder()).forEach(q -> q.setState(QuestState.QUEST_STATE_UNSTARTED)); - this.start(); - return true; - } - } - return false; - } - - public void save() { - getMainQuest().save(); - } - - public Quest toProto() { - Quest.Builder proto = Quest.newBuilder() - .setQuestId(getSubQuestId()) - .setState(getState().getValue()) - .setParentQuestId(getMainQuestId()) - .setStartTime(getStartTime()) - .setStartGameTime(438) - .setAcceptTime(getAcceptTime()); - - if (getFinishProgressList() != null) { - for (int i : getFinishProgressList()) { - proto.addFinishProgressList(i); - } - } - - if (getFailProgressList() != null) { - for (int i : getFailProgressList()) { - proto.addFailProgressList(i); - } - } - - return proto.build(); - } -} +package emu.grasscutter.game.quest; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.ChapterData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.data.excels.TriggerExcelConfigData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.proto.ChapterStateOuterClass; +import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.server.packet.send.PacketChapterStateNotify; +import emu.grasscutter.utils.Utils; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.script.Bindings; +import lombok.Getter; +import lombok.Setter; + +@Entity +public class GameQuest { + @Transient @Getter @Setter private GameMainQuest mainQuest; + @Transient @Getter private QuestData questData; + + @Getter private int subQuestId; + @Getter private int mainQuestId; + @Getter @Setter private QuestState state; + + @Getter @Setter private int startTime; + @Getter @Setter private int acceptTime; + @Getter @Setter private int finishTime; + + @Getter private int[] finishProgressList; + @Getter private int[] failProgressList; + @Transient @Getter private Map triggerData; + @Getter private Map triggers; + private transient Bindings bindings; + + @Deprecated // Morphia only. Do not use. + public GameQuest() {} + + public GameQuest(GameMainQuest mainQuest, QuestData questData) { + this.mainQuest = mainQuest; + this.subQuestId = questData.getId(); + this.mainQuestId = questData.getMainId(); + this.questData = questData; + this.state = QuestState.QUEST_STATE_UNSTARTED; + this.triggerData = new HashMap<>(); + this.triggers = new HashMap<>(); + } + + public void start() { + this.acceptTime = Utils.getCurrentSeconds(); + this.startTime = this.acceptTime; + this.state = QuestState.QUEST_STATE_UNFINISHED; + List triggerCond = + questData.getFinishCond().stream() + .filter(p -> p.getType() == QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE) + .toList(); + if (triggerCond.size() > 0) { + for (QuestData.QuestCondition cond : triggerCond) { + TriggerExcelConfigData newTrigger = + GameData.getTriggerExcelConfigDataMap().get(cond.getParam()[0]); + if (newTrigger != null) { + if (this.triggerData == null) { + this.triggerData = new HashMap<>(); + } + triggerData.put(newTrigger.getTriggerName(), newTrigger); + triggers.put(newTrigger.getTriggerName(), false); + SceneGroup group = SceneGroup.of(newTrigger.getGroupId()).load(newTrigger.getSceneId()); + getOwner() + .getWorld() + .getSceneById(newTrigger.getSceneId()) + .loadTriggerFromGroup(group, newTrigger.getTriggerName()); + } + } + } + + if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) { + this.finishProgressList = new int[questData.getFinishCond().size()]; + } + + if (questData.getFailCond() != null && questData.getFailCond().size() != 0) { + this.failProgressList = new int[questData.getFailCond().size()]; + } + + getQuestData() + .getBeginExec() + .forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); + + if (ChapterData.beginQuestChapterMap.containsKey(subQuestId)) { + mainQuest + .getOwner() + .sendPacket( + new PacketChapterStateNotify( + ChapterData.beginQuestChapterMap.get(subQuestId).getId(), + ChapterStateOuterClass.ChapterState.CHAPTER_STATE_BEGIN)); + } + + // Some subQuests and talks become active when some other subQuests are unfinished (even from + // different MainQuests) + this.getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, + this.getSubQuestId(), + this.getState().getValue(), + 0, + 0, + 0); + this.getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_COND_STATE_EQUAL, + this.getSubQuestId(), + this.getState().getValue(), + 0, + 0, + 0); + + Grasscutter.getLogger().debug("Quest {} is started", subQuestId); + } + + public String getTriggerNameById(int id) { + TriggerExcelConfigData trigger = GameData.getTriggerExcelConfigDataMap().get(id); + if (trigger != null) { + String triggerName = trigger.getTriggerName(); + return triggerName; + } + // return empty string if can't find trigger + return ""; + } + + public Player getOwner() { + return this.getMainQuest().getOwner(); + } + + public void setConfig(QuestData config) { + if (getSubQuestId() != config.getId()) return; + this.questData = config; + } + + public void setFinishProgress(int index, int value) { + finishProgressList[index] = value; + } + + public void setFailProgress(int index, int value) { + failProgressList[index] = value; + } + + public void finish() { + this.state = QuestState.QUEST_STATE_FINISHED; + this.finishTime = Utils.getCurrentSeconds(); + + if (getQuestData().finishParent()) { + // This quest finishes the questline - the main quest will also save the quest to db, so we + // don't have to call save() here + getMainQuest().finish(); + } + + getQuestData() + .getFinishExec() + .forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); + // Some subQuests have conditions that subQuests are finished (even from different MainQuests) + getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, + this.subQuestId, + this.state.getValue(), + 0, + 0, + 0); + getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); + + if (ChapterData.endQuestChapterMap.containsKey(subQuestId)) { + mainQuest + .getOwner() + .sendPacket( + new PacketChapterStateNotify( + ChapterData.endQuestChapterMap.get(subQuestId).getId(), + ChapterStateOuterClass.ChapterState.CHAPTER_STATE_END)); + } + + Grasscutter.getLogger().debug("Quest {} is finished", subQuestId); + } + + // TODO + public void fail() { + this.state = QuestState.QUEST_STATE_FAILED; + this.finishTime = Utils.getCurrentSeconds(); + + getQuestData() + .getFailExec() + .forEach(e -> getOwner().getServer().getQuestSystem().triggerExec(this, e, e.getParam())); + // Some subQuests have conditions that subQuests fail (even from different MainQuests) + getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL, + this.subQuestId, + this.state.getValue(), + 0, + 0, + 0); + getOwner() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_COND_STATE_EQUAL, this.subQuestId, this.state.getValue(), 0, 0, 0); + } + + // Return true if ParentQuest should rewind to this childQuest + public boolean rewind(GameQuest nextRewind) { + if (questData.isRewind()) { + if (nextRewind == null) { + return true; + } + // if the next isRewind subQuest is none or unstarted, reset all subQuests with order higher + // than this one, and restart this quest + if (nextRewind.getState() == QuestState.QUEST_STATE_NONE + || nextRewind.getState() == QuestState.QUEST_STATE_UNSTARTED) { + getMainQuest().getChildQuests().values().stream() + .filter(p -> p.getQuestData().getOrder() > this.getQuestData().getOrder()) + .forEach(q -> q.setState(QuestState.QUEST_STATE_UNSTARTED)); + this.start(); + return true; + } + } + return false; + } + + public void save() { + getMainQuest().save(); + } + + public Quest toProto() { + Quest.Builder proto = + Quest.newBuilder() + .setQuestId(getSubQuestId()) + .setState(getState().getValue()) + .setParentQuestId(getMainQuestId()) + .setStartTime(getStartTime()) + .setStartGameTime(438) + .setAcceptTime(getAcceptTime()); + + if (getFinishProgressList() != null) { + for (int i : getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (getFailProgressList() != null) { + for (int i : getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/QuestSystem.java b/src/main/java/emu/grasscutter/game/quest/QuestSystem.java index 6869bcc0e..b6e32a447 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestSystem.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestSystem.java @@ -1,93 +1,110 @@ -package emu.grasscutter.game.quest; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.data.excels.QuestData.QuestExecParam; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import org.reflections.Reflections; - -@SuppressWarnings("unchecked") -public class QuestSystem extends BaseGameSystem { - private final Int2ObjectMap condHandlers; - private final Int2ObjectMap contHandlers; - private final Int2ObjectMap execHandlers; - - public QuestSystem(GameServer server) { - super(server); - - this.condHandlers = new Int2ObjectOpenHashMap<>(); - this.contHandlers = new Int2ObjectOpenHashMap<>(); - this.execHandlers = new Int2ObjectOpenHashMap<>(); - - this.registerHandlers(); - } - - public void registerHandlers() { - this.registerHandlers(this.condHandlers, "emu.grasscutter.game.quest.conditions", QuestBaseHandler.class); - this.registerHandlers(this.contHandlers, "emu.grasscutter.game.quest.content", QuestBaseHandler.class); - this.registerHandlers(this.execHandlers, "emu.grasscutter.game.quest.exec", QuestExecHandler.class); - } - - public void registerHandlers(Int2ObjectMap map, String packageName, Class clazz) { - Reflections reflections = new Reflections(packageName); - var handlerClasses = reflections.getSubTypesOf(clazz); - - for (var obj : handlerClasses) { - this.registerPacketHandler(map, obj); - } - } - - public void registerPacketHandler(Int2ObjectMap map, Class handlerClass) { - try { - QuestValue opcode = handlerClass.getAnnotation(QuestValue.class); - - if (opcode == null || opcode.value().getValue() <= 0) { - return; - } - - map.put(opcode.value().getValue(), handlerClass.getDeclaredConstructor().newInstance()); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // TODO make cleaner - - public boolean triggerCondition(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - QuestBaseHandler handler = condHandlers.get(condition.getType().getValue()); - - if (handler == null || quest.getQuestData() == null) { - Grasscutter.getLogger().debug("Could not trigger condition {} at {}", condition.getType().getValue(), quest.getQuestData()); - return false; - } - - return handler.execute(quest, condition, paramStr, params); - } - - public boolean triggerContent(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - QuestBaseHandler handler = contHandlers.get(condition.getType().getValue()); - - if (handler == null || quest.getQuestData() == null) { - Grasscutter.getLogger().debug("Could not trigger content {} at {}", condition.getType().getValue(), quest.getQuestData()); - return false; - } - - return handler.execute(quest, condition, paramStr, params); - } - - public boolean triggerExec(GameQuest quest, QuestExecParam execParam, String... params) { - QuestExecHandler handler = execHandlers.get(execParam.getType().getValue()); - - if (handler == null || quest.getQuestData() == null) { - Grasscutter.getLogger().debug("Could not trigger exec {} at {}", execParam.getType().getValue(), quest.getQuestData()); - return false; - } - - return handler.execute(quest, execParam, params); - } -} +package emu.grasscutter.game.quest; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.data.excels.QuestData.QuestExecParam; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.reflections.Reflections; + +@SuppressWarnings("unchecked") +public class QuestSystem extends BaseGameSystem { + private final Int2ObjectMap condHandlers; + private final Int2ObjectMap contHandlers; + private final Int2ObjectMap execHandlers; + + public QuestSystem(GameServer server) { + super(server); + + this.condHandlers = new Int2ObjectOpenHashMap<>(); + this.contHandlers = new Int2ObjectOpenHashMap<>(); + this.execHandlers = new Int2ObjectOpenHashMap<>(); + + this.registerHandlers(); + } + + public void registerHandlers() { + this.registerHandlers( + this.condHandlers, "emu.grasscutter.game.quest.conditions", QuestBaseHandler.class); + this.registerHandlers( + this.contHandlers, "emu.grasscutter.game.quest.content", QuestBaseHandler.class); + this.registerHandlers( + this.execHandlers, "emu.grasscutter.game.quest.exec", QuestExecHandler.class); + } + + public void registerHandlers(Int2ObjectMap map, String packageName, Class clazz) { + Reflections reflections = new Reflections(packageName); + var handlerClasses = reflections.getSubTypesOf(clazz); + + for (var obj : handlerClasses) { + this.registerPacketHandler(map, obj); + } + } + + public void registerPacketHandler(Int2ObjectMap map, Class handlerClass) { + try { + QuestValue opcode = handlerClass.getAnnotation(QuestValue.class); + + if (opcode == null || opcode.value().getValue() <= 0) { + return; + } + + map.put(opcode.value().getValue(), handlerClass.getDeclaredConstructor().newInstance()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // TODO make cleaner + + public boolean triggerCondition( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + QuestBaseHandler handler = condHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getQuestData() == null) { + Grasscutter.getLogger() + .debug( + "Could not trigger condition {} at {}", + condition.getType().getValue(), + quest.getQuestData()); + return false; + } + + return handler.execute(quest, condition, paramStr, params); + } + + public boolean triggerContent( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + QuestBaseHandler handler = contHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getQuestData() == null) { + Grasscutter.getLogger() + .debug( + "Could not trigger content {} at {}", + condition.getType().getValue(), + quest.getQuestData()); + return false; + } + + return handler.execute(quest, condition, paramStr, params); + } + + public boolean triggerExec(GameQuest quest, QuestExecParam execParam, String... params) { + QuestExecHandler handler = execHandlers.get(execParam.getType().getValue()); + + if (handler == null || quest.getQuestData() == null) { + Grasscutter.getLogger() + .debug( + "Could not trigger exec {} at {}", + execParam.getType().getValue(), + quest.getQuestData()); + return false; + } + + return handler.execute(quest, execParam, params); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/QuestValue.java b/src/main/java/emu/grasscutter/game/quest/QuestValue.java index 7a16e3dd0..464106ef0 100644 --- a/src/main/java/emu/grasscutter/game/quest/QuestValue.java +++ b/src/main/java/emu/grasscutter/game/quest/QuestValue.java @@ -1,11 +1,10 @@ -package emu.grasscutter.game.quest; - -import emu.grasscutter.game.quest.enums.QuestTrigger; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface QuestValue { - QuestTrigger value(); -} +package emu.grasscutter.game.quest; + +import emu.grasscutter.game.quest.enums.QuestTrigger; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface QuestValue { + QuestTrigger value(); +} diff --git a/src/main/java/emu/grasscutter/game/quest/RewindData.java b/src/main/java/emu/grasscutter/game/quest/RewindData.java index 1a0b0dcd1..7769fd773 100644 --- a/src/main/java/emu/grasscutter/game/quest/RewindData.java +++ b/src/main/java/emu/grasscutter/game/quest/RewindData.java @@ -1,29 +1,27 @@ -package emu.grasscutter.game.quest; - -import lombok.Data; -import lombok.Getter; - -import java.util.List; - -@Data -public class RewindData { - AvatarData avatar; - List npcs; - - @Data - public static class AvatarData { - @Getter - private String pos; - } - - @Data - private static class Npc { - private String script; - private int room_id; - private int data_index; - private int id; - private String pos; - private int scene_id; - private String alias; - } -} +package emu.grasscutter.game.quest; + +import java.util.List; +import lombok.Data; +import lombok.Getter; + +@Data +public class RewindData { + AvatarData avatar; + List npcs; + + @Data + public static class AvatarData { + @Getter private String pos; + } + + @Data + private static class Npc { + private String script; + private int room_id; + private int data_index; + private int id; + private String pos; + private int scene_id; + private String alias; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java index 751891784..262bbe8eb 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java @@ -1,18 +1,18 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) -public class BaseCondition extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - // TODO Auto-generated method stub - return false; - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) +public class BaseCondition extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionCompleteTalk.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionCompleteTalk.java index bc82ff7c7..d80be6cb4 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionCompleteTalk.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionCompleteTalk.java @@ -1,27 +1,33 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_COMPLETE_TALK) -public class ConditionCompleteTalk extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - GameMainQuest checkMainQuest = quest.getOwner().getQuestManager().getMainQuestById(condition.getParam()[0] / 100); - if (checkMainQuest == null || GameData.getMainQuestDataMap().get(checkMainQuest.getParentQuestId()).getTalks() == null) { - Grasscutter.getLogger().debug("Warning: mainQuest {} hasn't been started yet, or has no talks", condition.getParam()[0] / 100); - return false; - } - MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0])); - return talkData != null || checkMainQuest.getChildQuestById(params[0]) != null; - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_COMPLETE_TALK) +public class ConditionCompleteTalk extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + GameMainQuest checkMainQuest = + quest.getOwner().getQuestManager().getMainQuestById(condition.getParam()[0] / 100); + if (checkMainQuest == null + || GameData.getMainQuestDataMap().get(checkMainQuest.getParentQuestId()).getTalks() + == null) { + Grasscutter.getLogger() + .debug( + "Warning: mainQuest {} hasn't been started yet, or has no talks", + condition.getParam()[0] / 100); + return false; + } + MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0])); + return talkData != null || checkMainQuest.getChildQuestById(params[0]) != null; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionLuaNotify.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionLuaNotify.java index e4678118d..71f0a4f70 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionLuaNotify.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionLuaNotify.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_LUA_NOTIFY) -public class ConditionLuaNotify extends QuestBaseHandler { - //Wrong implementation. Example: 7010226 has no paramStr - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return condition.getParam()[0] == Integer.parseInt(paramStr); - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_LUA_NOTIFY) +public class ConditionLuaNotify extends QuestBaseHandler { + // Wrong implementation. Example: 7010226 has no paramStr + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return condition.getParam()[0] == Integer.parseInt(paramStr); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java index 7a97b91dc..da8420f31 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) -public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return quest.getOwner().getLevel() >= params[0]; - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) +public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return quest.getOwner().getLevel() >= params[0]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarEqual.java index 74b903503..696dbf7a2 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarEqual.java @@ -1,19 +1,21 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_EQUAL) -public class ConditionQuestGlobalVarEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - Integer questGlobalVarValue = quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); - Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); - return questGlobalVarValue.intValue() == params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_EQUAL) +public class ConditionQuestGlobalVarEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + Integer questGlobalVarValue = + quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); + Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); + return questGlobalVarValue.intValue() == params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarGreater.java index 6f6200147..098b27a6a 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarGreater.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarGreater.java @@ -1,19 +1,21 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_GREATER) -public class ConditionQuestGlobalVarGreater extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - Integer questGlobalVarValue = quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); - Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); - return questGlobalVarValue.intValue() > params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_GREATER) +public class ConditionQuestGlobalVarGreater extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + Integer questGlobalVarValue = + quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); + Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); + return questGlobalVarValue.intValue() > params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarLess.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarLess.java index 9885692b1..ef85abe3c 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarLess.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarLess.java @@ -1,19 +1,21 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_LESS) -public class ConditionQuestGlobalVarLess extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - Integer questGlobalVarValue = quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); - Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); - return questGlobalVarValue.intValue() < params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_GLOBAL_VAR_LESS) +public class ConditionQuestGlobalVarLess extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + Integer questGlobalVarValue = + quest.getMainQuest().getQuestManager().getQuestGlobalVarValue(Integer.valueOf(params[0])); + Grasscutter.getLogger().debug("questGlobarVar {} : {}", params[0], questGlobalVarValue); + return questGlobalVarValue.intValue() < params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarEqual.java index 039506ff3..ede9ff631 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarEqual.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_EQUAL) -public class ConditionQuestVarEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue == params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_EQUAL) +public class ConditionQuestVarEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue == params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarGreater.java index 7717cb80a..2952e2bd8 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarGreater.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarGreater.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_GREATER) -public class ConditionQuestVarGreater extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue > params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_GREATER) +public class ConditionQuestVarGreater extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue > params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarLess.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarLess.java index 293c9bfe3..9a8678eba 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarLess.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarLess.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_LESS) -public class ConditionQuestVarLess extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue < params[1]; - } -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_QUEST_VAR_LESS) +public class ConditionQuestVarLess extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue < params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java index d0b96bb7f..37a8867ae 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_STATE_EQUAL) -public class ConditionStateEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); - if (checkQuest == null) { - /* - Will spam the console - //Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]); - - */ - return false; - } - return checkQuest.getState().getValue() == condition.getParam()[1]; - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_STATE_EQUAL) +public class ConditionStateEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); + if (checkQuest == null) { + /* + Will spam the console + //Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]); + + */ + return false; + } + return checkQuest.getState().getValue() == condition.getParam()[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateNotEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateNotEqual.java index a5a7445d9..58751a388 100644 --- a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateNotEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateNotEqual.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.quest.conditions; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_COND_STATE_NOT_EQUAL) -public class ConditionStateNotEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); - if (checkQuest == null) { - /* - Will spam the console - //Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]); - - */ - return false; - } - return checkQuest.getState().getValue() != condition.getParam()[1]; - } - -} +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_STATE_NOT_EQUAL) +public class ConditionStateNotEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); + if (checkQuest == null) { + /* + Will spam the console + //Grasscutter.getLogger().debug("Warning: quest {} hasn't been started yet!", condition.getParam()[0]); + + */ + return false; + } + return checkQuest.getState().getValue() != condition.getParam()[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java index 6d6715d69..39b7a282c 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java +++ b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java @@ -1,18 +1,18 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) -public class BaseContent extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - // TODO Auto-generated method stub - return false; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) +public class BaseContent extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteAnyTalk.java b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteAnyTalk.java index 35cc5a0bc..5a8de37e1 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteAnyTalk.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteAnyTalk.java @@ -1,24 +1,27 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK) -public class ContentCompleteAnyTalk extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - GameMainQuest checkMainQuest = quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); - if (checkMainQuest == null) { - return false; - } - MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(paramStr)); - return talkData == null || condition.getParamStr().contains(paramStr) || checkMainQuest.getChildQuestById(params[0]) != null; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK) +public class ContentCompleteAnyTalk extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + GameMainQuest checkMainQuest = + quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); + if (checkMainQuest == null) { + return false; + } + MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(paramStr)); + return talkData == null + || condition.getParamStr().contains(paramStr) + || checkMainQuest.getChildQuestById(params[0]) != null; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java index aa57476c2..14b1cf284 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java @@ -1,27 +1,30 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK) -public class ContentCompleteTalk extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - GameMainQuest checkMainQuest = quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); - if (checkMainQuest == null) { - return false; - } - - MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(condition.getParam()[0]); - return talkData != null; - - // This expression makes zero sense. - // return talkData == null || condition.getParamStr().contains(paramStr) || checkMainQuest.getChildQuestById(params[0]) != null; - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK) +public class ContentCompleteTalk extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + GameMainQuest checkMainQuest = + quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); + if (checkMainQuest == null) { + return false; + } + + MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(condition.getParam()[0]); + return talkData != null; + + // This expression makes zero sense. + // return talkData == null || condition.getParamStr().contains(paramStr) || + // checkMainQuest.getChildQuestById(params[0]) != null; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java index 646a558af..7d137f58b 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON) -public class ContentEnterDungeon extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return condition.getParam()[0] == params[0]; //missing params[1] - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON) +public class ContentEnterDungeon extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return condition.getParam()[0] == params[0]; // missing params[1] + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterRoom.java b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterRoom.java index 1b6590472..5c9ff80ed 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterRoom.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterRoom.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_ROOM) -public class ContentEnterRoom extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return condition.getParam()[0] == params[0]; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_ROOM) +public class ContentEnterRoom extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return condition.getParam()[0] == params[0]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java b/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java index 7d34fb2b5..7afaf4c0a 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java @@ -1,20 +1,21 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_FINISH_PLOT) -public class ContentFinishPlot extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - MainQuestData.TalkData talkData = quest.getMainQuest().getTalks().get(Integer.valueOf(params[0])); - GameQuest subQuest = quest.getMainQuest().getChildQuestById(params[0]); - return talkData != null || subQuest != null; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_FINISH_PLOT) +public class ContentFinishPlot extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + MainQuestData.TalkData talkData = + quest.getMainQuest().getTalks().get(Integer.valueOf(params[0])); + GameQuest subQuest = quest.getMainQuest().getChildQuestById(params[0]); + return talkData != null || subQuest != null; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentGameTimeTick.java b/src/main/java/emu/grasscutter/game/quest/content/ContentGameTimeTick.java index 5c9807557..1b584476f 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentGameTimeTick.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentGameTimeTick.java @@ -1,23 +1,22 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_GAME_TIME_TICK) -public class ContentGameTimeTick extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - var range = condition.getParamStr().split(","); - var min = Math.min(Integer.parseInt(range[0]), Integer.parseInt(range[1])); - var max = Math.max(Integer.parseInt(range[0]), Integer.parseInt(range[1])); - - // params[0] is clock, params[1] is day - return params[0] >= min && params[0] <= max && - params[1] >= condition.getParam()[0]; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_GAME_TIME_TICK) +public class ContentGameTimeTick extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + var range = condition.getParamStr().split(","); + var min = Math.min(Integer.parseInt(range[0]), Integer.parseInt(range[1])); + var max = Math.max(Integer.parseInt(range[0]), Integer.parseInt(range[1])); + + // params[0] is clock, params[1] is day + return params[0] >= min && params[0] <= max && params[1] >= condition.getParam()[0]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentInteractGadget.java b/src/main/java/emu/grasscutter/game/quest/content/ContentInteractGadget.java index 1617478b9..598c6e066 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentInteractGadget.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentInteractGadget.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_INTERACT_GADGET) -public class ContentInteractGadget extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return params[0] == condition.getParam()[0]; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_INTERACT_GADGET) +public class ContentInteractGadget extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return params[0] == condition.getParam()[0]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentLeaveScene.java b/src/main/java/emu/grasscutter/game/quest/content/ContentLeaveScene.java index 9542c9517..4c43b646f 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentLeaveScene.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentLeaveScene.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_LEAVE_SCENE) -public class ContentLeaveScene extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return quest.getOwner().getScene().getPrevScene() == params[0]; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_LEAVE_SCENE) +public class ContentLeaveScene extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return quest.getOwner().getScene().getPrevScene() == params[0]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentLuaNotify.java b/src/main/java/emu/grasscutter/game/quest/content/ContentLuaNotify.java index 5c2114275..ba230097c 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentLuaNotify.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentLuaNotify.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY) -public class ContentLuaNotify extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - return condition.getParamStr().equals(paramStr); - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY) +public class ContentLuaNotify extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + return condition.getParamStr().equals(paramStr); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentNotFinishPlot.java b/src/main/java/emu/grasscutter/game/quest/content/ContentNotFinishPlot.java index b8234ac68..0a7d05138 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentNotFinishPlot.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentNotFinishPlot.java @@ -1,24 +1,25 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_NOT_FINISH_PLOT) -public class ContentNotFinishPlot extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - GameMainQuest checkMainQuest = quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); - if (checkMainQuest == null) { - return false; - } - MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0])); - return talkData == null; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_NOT_FINISH_PLOT) +public class ContentNotFinishPlot extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + GameMainQuest checkMainQuest = + quest.getOwner().getQuestManager().getMainQuestById(params[0] / 100); + if (checkMainQuest == null) { + return false; + } + MainQuestData.TalkData talkData = checkMainQuest.getTalks().get(Integer.valueOf(params[0])); + return talkData == null; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateEqual.java b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateEqual.java index e3795399d..1c84bb6f4 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateEqual.java @@ -1,21 +1,21 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL) -public class ContentQuestStateEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params) { - GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); - if (checkQuest == null) { - return false; - } - return checkQuest.getState().getValue() == params[1]; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_EQUAL) +public class ContentQuestStateEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]); + if (checkQuest == null) { + return false; + } + return checkQuest.getState().getValue() == params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateNotEqual.java b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateNotEqual.java index 22dbe111a..fe4c10605 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateNotEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestStateNotEqual.java @@ -1,23 +1,23 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL) -public class ContentQuestStateNotEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]); - - if (checkQuest != null) { - return checkQuest.getState().getValue() != params[1]; - } - - return false; - } - -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL) +public class ContentQuestStateNotEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]); + + if (checkQuest != null) { + return checkQuest.getState().getValue() != params[1]; + } + + return false; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarEqual.java b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarEqual.java index 733fd0fac..75d9b0457 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarEqual.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarEqual.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_EQUAL) -public class ContentQuestVarEqual extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue == params[1]; - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_EQUAL) +public class ContentQuestVarEqual extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue == params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarGreater.java b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarGreater.java index 1e59b640a..432a9f800 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarGreater.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarGreater.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_GREATER) -public class ContentQuestVarGreater extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue > params[1]; - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_GREATER) +public class ContentQuestVarGreater extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue > params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarLess.java b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarLess.java index 232ff8934..f642f5749 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarLess.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentQuestVarLess.java @@ -1,19 +1,20 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_LESS) -public class ContentQuestVarLess extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; - Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); - return questVarValue < params[1]; - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_LESS) +public class ContentQuestVarLess extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + int questVarValue = quest.getMainQuest().getQuestVars()[params[0]]; + Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue); + return questVarValue < params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentSkill.java b/src/main/java/emu/grasscutter/game/quest/content/ContentSkill.java index 73401c3c0..8f00a074f 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentSkill.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentSkill.java @@ -1,14 +1,15 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; - -@QuestValue(QuestTrigger.QUEST_CONTENT_SKILL) -public class ContentSkill extends BaseContent { - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - return (condition.getParam()[0] == params[0]) && (condition.getParam()[1] == params[1]); - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; + +@QuestValue(QuestTrigger.QUEST_CONTENT_SKILL) +public class ContentSkill extends BaseContent { + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + return (condition.getParam()[0] == params[0]) && (condition.getParam()[1] == params[1]); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentTriggerFire.java b/src/main/java/emu/grasscutter/game/quest/content/ContentTriggerFire.java index 773583c0c..fb926fded 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentTriggerFire.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentTriggerFire.java @@ -1,23 +1,25 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE) -public class ContentTriggerFire extends QuestBaseHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - if (quest.getTriggers().containsKey(quest.getTriggerNameById(params[0]))) { - //We don't want to put a new key here - return quest.getTriggers().get(quest.getTriggerNameById(params[0])); - } else { - Grasscutter.getLogger().error("quest {} doesn't have trigger {}", quest.getSubQuestId(), params[0]); - return false; - } - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE) +public class ContentTriggerFire extends QuestBaseHandler { + + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + if (quest.getTriggers().containsKey(quest.getTriggerNameById(params[0]))) { + // We don't want to put a new key here + return quest.getTriggers().get(quest.getTriggerNameById(params[0])); + } else { + Grasscutter.getLogger() + .error("quest {} doesn't have trigger {}", quest.getSubQuestId(), params[0]); + return false; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentUnlockTransPoint.java b/src/main/java/emu/grasscutter/game/quest/content/ContentUnlockTransPoint.java index fed3b7927..a8dad8d25 100644 --- a/src/main/java/emu/grasscutter/game/quest/content/ContentUnlockTransPoint.java +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentUnlockTransPoint.java @@ -1,15 +1,16 @@ -package emu.grasscutter.game.quest.content; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestBaseHandler; - -@QuestValue(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT) -public class ContentUnlockTransPoint extends QuestBaseHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { - return condition.getParam()[0] == params[0] && condition.getParam()[1] == params[1]; - } -} +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT) +public class ContentUnlockTransPoint extends QuestBaseHandler { + @Override + public boolean execute( + GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) { + return condition.getParam()[0] == params[0] && condition.getParam()[1] == params[1]; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java index a89e2e557..468b9b5c3 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java @@ -1,43 +1,43 @@ -package emu.grasscutter.game.quest.enums; - -import java.util.Arrays; - -public enum LogicType { - LOGIC_NONE(0), - LOGIC_AND(1), - LOGIC_OR(2), - LOGIC_NOT(3), - LOGIC_A_AND_ETCOR(4), - LOGIC_A_AND_B_AND_ETCOR(5), - LOGIC_A_OR_ETCAND(6), - LOGIC_A_OR_B_OR_ETCAND(7), - LOGIC_A_AND_B_OR_ETCAND(8); - - private final int value; - - LogicType(int id) { - this.value = id; - } - - public static boolean calculate(LogicType logicType, int[] progress) { - if (logicType == null) { - return progress[0] == 1; - } - - switch (logicType) { - case LOGIC_AND -> { - return Arrays.stream(progress).allMatch(i -> i == 1); - } - case LOGIC_OR -> { - return Arrays.stream(progress).anyMatch(i -> i == 1); - } - default -> { - return Arrays.stream(progress).anyMatch(i -> i == 1); - } - } - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +import java.util.Arrays; + +public enum LogicType { + LOGIC_NONE(0), + LOGIC_AND(1), + LOGIC_OR(2), + LOGIC_NOT(3), + LOGIC_A_AND_ETCOR(4), + LOGIC_A_AND_B_AND_ETCOR(5), + LOGIC_A_OR_ETCAND(6), + LOGIC_A_OR_B_OR_ETCAND(7), + LOGIC_A_AND_B_OR_ETCAND(8); + + private final int value; + + LogicType(int id) { + this.value = id; + } + + public static boolean calculate(LogicType logicType, int[] progress) { + if (logicType == null) { + return progress[0] == 1; + } + + switch (logicType) { + case LOGIC_AND -> { + return Arrays.stream(progress).allMatch(i -> i == 1); + } + case LOGIC_OR -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + default -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + } + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java index a89b09f3a..4a976b5cb 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java @@ -1,18 +1,18 @@ -package emu.grasscutter.game.quest.enums; - -public enum ParentQuestState { - PARENT_QUEST_STATE_NONE(0), - PARENT_QUEST_STATE_FINISHED(1), - PARENT_QUEST_STATE_FAILED(2), - PARENT_QUEST_STATE_CANCELED(3); - - private final int value; - - ParentQuestState(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum ParentQuestState { + PARENT_QUEST_STATE_NONE(0), + PARENT_QUEST_STATE_FINISHED(1), + PARENT_QUEST_STATE_FAILED(2), + PARENT_QUEST_STATE_CANCELED(3); + + private final int value; + + ParentQuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java index 90cd6ea2d..e95e770bc 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestGuideType { - QUEST_GUIDE_NONE(0), - QUEST_GUIDE_LOCATION(1), - QUEST_GUIDE_NPC(2); - - private final int value; - - QuestGuideType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum QuestGuideType { + QUEST_GUIDE_NONE(0), + QUEST_GUIDE_LOCATION(1), + QUEST_GUIDE_NPC(2); + + private final int value; + + QuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java index 2ea9c61f4..10e70ba0b 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java @@ -1,16 +1,16 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestShowType { - QUEST_SHOW(0), - QUEST_HIDDEN(1); - - private final int value; - - QuestShowType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum QuestShowType { + QUEST_SHOW(0), + QUEST_HIDDEN(1); + + private final int value; + + QuestShowType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java index 71ad52130..0856469ea 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java @@ -1,26 +1,26 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestState { - QUEST_STATE_NONE(0), - QUEST_STATE_UNSTARTED(1), - QUEST_STATE_UNFINISHED(2), - QUEST_STATE_FINISHED(3), - QUEST_STATE_FAILED(4), - - // Used by lua - NONE(0), - UNSTARTED(1), - UNFINISHED(2), - FINISHED(3), - FAILED(4); - - private final int value; - - QuestState(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum QuestState { + QUEST_STATE_NONE(0), + QUEST_STATE_UNSTARTED(1), + QUEST_STATE_UNFINISHED(2), + QUEST_STATE_FINISHED(3), + QUEST_STATE_FAILED(4), + + // Used by lua + NONE(0), + UNSTARTED(1), + UNFINISHED(2), + FINISHED(3), + FAILED(4); + + private final int value; + + QuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java index 27a044712..f20158929 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java @@ -1,261 +1,262 @@ -package emu.grasscutter.game.quest.enums; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -public enum QuestTrigger { - QUEST_COND_NONE(0), - QUEST_COND_STATE_EQUAL(1), - QUEST_COND_STATE_NOT_EQUAL(2), - QUEST_COND_PACK_HAVE_ITEM(3), - QUEST_COND_AVATAR_ELEMENT_EQUAL(4), - QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL(5), - QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT(6), - QUEST_COND_CITY_LEVEL_EQUAL_GREATER(7), - QUEST_COND_ITEM_NUM_LESS_THAN(8), - QUEST_COND_DAILY_TASK_START(9), - QUEST_COND_OPEN_STATE_EQUAL(10), - QUEST_COND_DAILY_TASK_OPEN(11), - QUEST_COND_DAILY_TASK_REWARD_CAN_GET(12), - QUEST_COND_DAILY_TASK_REWARD_RECEIVED(13), - QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET(14), - QUEST_COND_EXPLORATION_REWARD_CAN_GET(15), - QUEST_COND_IS_WORLD_OWNER(16), - QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER(17), - QUEST_COND_SCENE_AREA_UNLOCKED(18), - QUEST_COND_ITEM_GIVING_ACTIVED(19), - QUEST_COND_ITEM_GIVING_FINISHED(20), - QUEST_COND_IS_DAYTIME(21), - QUEST_COND_CURRENT_AVATAR(22), - QUEST_COND_CURRENT_AREA(23), - QUEST_COND_QUEST_VAR_EQUAL(24), - QUEST_COND_QUEST_VAR_GREATER(25), - QUEST_COND_QUEST_VAR_LESS(26), - QUEST_COND_FORGE_HAVE_FINISH(27), - QUEST_COND_DAILY_TASK_IN_PROGRESS(28), - QUEST_COND_DAILY_TASK_FINISHED(29), - QUEST_COND_ACTIVITY_COND(30), - QUEST_COND_ACTIVITY_OPEN(31), - QUEST_COND_DAILY_TASK_VAR_GT(32), - QUEST_COND_DAILY_TASK_VAR_EQ(33), - QUEST_COND_DAILY_TASK_VAR_LT(34), - QUEST_COND_BARGAIN_ITEM_GT(35), - QUEST_COND_BARGAIN_ITEM_EQ(36), - QUEST_COND_BARGAIN_ITEM_LT(37), - QUEST_COND_COMPLETE_TALK(38), - QUEST_COND_NOT_HAVE_BLOSSOM_TALK(39), - QUEST_COND_IS_CUR_BLOSSOM_TALK(40), - QUEST_COND_QUEST_NOT_RECEIVE(41), - QUEST_COND_QUEST_SERVER_COND_VALID(42), - QUEST_COND_ACTIVITY_CLIENT_COND(43), - QUEST_COND_QUEST_GLOBAL_VAR_EQUAL(44), - QUEST_COND_QUEST_GLOBAL_VAR_GREATER(45), - QUEST_COND_QUEST_GLOBAL_VAR_LESS(46), - QUEST_COND_PERSONAL_LINE_UNLOCK(47), - QUEST_COND_CITY_REPUTATION_REQUEST(48), - QUEST_COND_MAIN_COOP_START(49), - QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), - QUEST_COND_CITY_REPUTATION_LEVEL(51), - QUEST_COND_CITY_REPUTATION_UNLOCK(52), - QUEST_COND_LUA_NOTIFY(53), - QUEST_COND_CUR_CLIMATE(54), - QUEST_COND_ACTIVITY_END(55), - QUEST_COND_COOP_POINT_RUNNING(56), - QUEST_COND_GADGET_TALK_STATE_EQUAL(57), - QUEST_COND_AVATAR_FETTER_GT(58), - QUEST_COND_AVATAR_FETTER_EQ(59), - QUEST_COND_AVATAR_FETTER_LT(60), - QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK(61), - QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD(62), - QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH(63), - QUEST_COND_HOMEWORLD_NPC_EVENT(64), - QUEST_COND_TIME_VAR_GT_EQ(65), - QUEST_COND_TIME_VAR_PASS_DAY(66), - QUEST_COND_HOMEWORLD_NPC_NEW_TALK(67), - QUEST_COND_PLAYER_CHOOSE_MALE(68), - QUEST_COND_HISTORY_GOT_ANY_ITEM(69), - QUEST_COND_LEARNED_RECIPE(70), - QUEST_COND_LUNARITE_REGION_UNLOCKED(71), - QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT(72), - QUEST_COND_LUNARITE_COLLECT_FINISH(73), - QUEST_COND_LUNARITE_MARK_ALL_FINISH(74), - QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM(75), - QUEST_COND_SCENE_POINT_UNLOCK(76), - QUEST_COND_SCENE_LEVEL_TAG_EQ(77), - - QUEST_CONTENT_NONE(0), - QUEST_CONTENT_KILL_MONSTER(1), - QUEST_CONTENT_COMPLETE_TALK(2), - QUEST_CONTENT_MONSTER_DIE(3), - QUEST_CONTENT_FINISH_PLOT(4), - QUEST_CONTENT_OBTAIN_ITEM(5), - QUEST_CONTENT_TRIGGER_FIRE(6), - QUEST_CONTENT_CLEAR_GROUP_MONSTER(7), - QUEST_CONTENT_NOT_FINISH_PLOT(8), - QUEST_CONTENT_ENTER_DUNGEON(9), - QUEST_CONTENT_ENTER_MY_WORLD(10), - QUEST_CONTENT_FINISH_DUNGEON(11), - QUEST_CONTENT_DESTROY_GADGET(12), - QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE(13), - QUEST_CONTENT_NICK_NAME(14), - QUEST_CONTENT_WORKTOP_SELECT(15), - QUEST_CONTENT_SEAL_BATTLE_RESULT(16), - QUEST_CONTENT_ENTER_ROOM(17), - QUEST_CONTENT_GAME_TIME_TICK(18), - QUEST_CONTENT_FAIL_DUNGEON(19), - QUEST_CONTENT_LUA_NOTIFY(20), - QUEST_CONTENT_TEAM_DEAD(21), - QUEST_CONTENT_COMPLETE_ANY_TALK(22), - QUEST_CONTENT_UNLOCK_TRANS_POINT(23), - QUEST_CONTENT_ADD_QUEST_PROGRESS(24), - QUEST_CONTENT_INTERACT_GADGET(25), - QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26), - QUEST_CONTENT_FINISH_ITEM_GIVING(27), - QUEST_CONTENT_SKILL(107), - QUEST_CONTENT_CITY_LEVEL_UP(109), - QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110), - QUEST_CONTENT_ITEM_LESS_THAN(111), - QUEST_CONTENT_PLAYER_LEVEL_UP(112), - QUEST_CONTENT_DUNGEON_OPEN_STATUE(113), - QUEST_CONTENT_UNLOCK_AREA(114), - QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID(115), - QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE(116), - QUEST_CONTENT_FINISH_DAILY_DUNGEON(117), - QUEST_CONTENT_FINISH_WEEKLY_DUNGEON(118), - QUEST_CONTENT_QUEST_VAR_EQUAL(119), - QUEST_CONTENT_QUEST_VAR_GREATER(120), - QUEST_CONTENT_QUEST_VAR_LESS(121), - QUEST_CONTENT_OBTAIN_VARIOUS_ITEM(122), - QUEST_CONTENT_FINISH_TOWER_LEVEL(123), - QUEST_CONTENT_BARGAIN_SUCC(124), - QUEST_CONTENT_BARGAIN_FAIL(125), - QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126), - QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED(127), - QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT(128), - QUEST_CONTENT_ANY_MANUAL_TRANSPORT(129), - QUEST_CONTENT_USE_ITEM(130), - QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT(131), - QUEST_CONTENT_ENTER_MY_HOME_WORLD(132), - QUEST_CONTENT_ENTER_MY_WORLD_SCENE(133), - QUEST_CONTENT_TIME_VAR_GT_EQ(134), - QUEST_CONTENT_TIME_VAR_PASS_DAY(135), - QUEST_CONTENT_QUEST_STATE_EQUAL(136), - QUEST_CONTENT_QUEST_STATE_NOT_EQUAL(137), - QUEST_CONTENT_UNLOCKED_RECIPE(138), - QUEST_CONTENT_NOT_UNLOCKED_RECIPE(139), - QUEST_CONTENT_FISHING_SUCC(140), - QUEST_CONTENT_ENTER_ROGUE_DUNGEON(141), - QUEST_CONTENT_USE_WIDGET(142), - QUEST_CONTENT_CAPTURE_SUCC(143), - QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST(144), - QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST(145), - QUEST_CONTENT_ENTER_VEHICLE(147), - QUEST_CONTENT_SCENE_LEVEL_TAG_EQ(148), - QUEST_CONTENT_LEAVE_SCENE(149), - QUEST_CONTENT_LEAVE_SCENE_RANGE(150), - QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION(151), - QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS(152), - QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY(153), - - QUEST_EXEC_NONE(0), - QUEST_EXEC_DEL_PACK_ITEM(1), - QUEST_EXEC_UNLOCK_POINT(2), - QUEST_EXEC_UNLOCK_AREA(3), - QUEST_EXEC_UNLOCK_FORCE(4), - QUEST_EXEC_LOCK_FORCE(5), - QUEST_EXEC_CHANGE_AVATAR_ELEMET(6), - QUEST_EXEC_REFRESH_GROUP_MONSTER(7), - QUEST_EXEC_SET_IS_FLYABLE(8), - QUEST_EXEC_SET_IS_WEATHER_LOCKED(9), - QUEST_EXEC_SET_IS_GAME_TIME_LOCKED(10), - QUEST_EXEC_SET_IS_TRANSFERABLE(11), - QUEST_EXEC_GRANT_TRIAL_AVATAR(12), - QUEST_EXEC_OPEN_BORED(13), - QUEST_EXEC_ROLLBACK_QUEST(14), - QUEST_EXEC_NOTIFY_GROUP_LUA(15), - QUEST_EXEC_SET_OPEN_STATE(16), - QUEST_EXEC_LOCK_POINT(17), - QUEST_EXEC_DEL_PACK_ITEM_BATCH(18), - QUEST_EXEC_REFRESH_GROUP_SUITE(19), - QUEST_EXEC_REMOVE_TRIAL_AVATAR(20), - QUEST_EXEC_SET_GAME_TIME(21), - QUEST_EXEC_SET_WEATHER_GADGET(22), - QUEST_EXEC_ADD_QUEST_PROGRESS(23), - QUEST_EXEC_NOTIFY_DAILY_TASK(24), - QUEST_EXEC_CREATE_PATTERN_GROUP(25), - QUEST_EXEC_REMOVE_PATTERN_GROUP(26), - QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27), - QUEST_EXEC_ACTIVE_ITEM_GIVING(28), - QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29), - QUEST_EXEC_ROLLBACK_PARENT_QUEST(30), - QUEST_EXEC_LOCK_AVATAR_TEAM(31), - QUEST_EXEC_UNLOCK_AVATAR_TEAM(32), - QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX(33), - QUEST_EXEC_SET_DAILY_TASK_VAR(34), - QUEST_EXEC_INC_DAILY_TASK_VAR(35), - QUEST_EXEC_DEC_DAILY_TASK_VAR(36), - QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE(37), - QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE(38), - QUEST_EXEC_ADD_CUR_AVATAR_ENERGY(39), - QUEST_EXEC_START_BARGAIN(41), - QUEST_EXEC_STOP_BARGAIN(42), - QUEST_EXEC_SET_QUEST_GLOBAL_VAR(43), - QUEST_EXEC_INC_QUEST_GLOBAL_VAR(44), - QUEST_EXEC_DEC_QUEST_GLOBAL_VAR(45), - QUEST_EXEC_REGISTER_DYNAMIC_GROUP(46), - QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP(47), - QUEST_EXEC_SET_QUEST_VAR(48), - QUEST_EXEC_INC_QUEST_VAR(49), - QUEST_EXEC_DEC_QUEST_VAR(50), - QUEST_EXEC_RANDOM_QUEST_VAR(51), - QUEST_EXEC_ACTIVATE_SCANNING_PIC(52), - QUEST_EXEC_RELOAD_SCENE_TAG(53), - QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY(54), - QUEST_EXEC_CHANGE_SKILL_DEPOT(55), - QUEST_EXEC_ADD_SCENE_TAG(56), - QUEST_EXEC_DEL_SCENE_TAG(57), - QUEST_EXEC_INIT_TIME_VAR(58), - QUEST_EXEC_CLEAR_TIME_VAR(59), - QUEST_EXEC_MODIFY_CLIMATE_AREA(60), - QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61), - QUEST_EXEC_CHANGE_MAP_AREA_STATE(62), - QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), - QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64), - QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65), - QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66), - QUEST_EXEC_FAIL_MAINCOOP(67), - QUEST_EXEC_MODIFY_WEATHER_AREA(68); - - private static final Int2ObjectMap contentMap = new Int2ObjectOpenHashMap<>(); - private static final Map contentStringMap = new HashMap<>(); - - static { - Stream.of(values()) - .filter(e -> e.name().startsWith("QUEST_CONTENT_")) - .forEach(e -> { - contentMap.put(e.getValue(), e); - contentStringMap.put(e.name(), e); - }); - } - - private final int value; - QuestTrigger(int id) { - this.value = id; - } - - public static QuestTrigger getContentTriggerByValue(int value) { - return contentMap.getOrDefault(value, QUEST_CONTENT_NONE); - } - - public static QuestTrigger getContentTriggerByName(String name) { - return contentStringMap.getOrDefault(name, QUEST_CONTENT_NONE); - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public enum QuestTrigger { + QUEST_COND_NONE(0), + QUEST_COND_STATE_EQUAL(1), + QUEST_COND_STATE_NOT_EQUAL(2), + QUEST_COND_PACK_HAVE_ITEM(3), + QUEST_COND_AVATAR_ELEMENT_EQUAL(4), + QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL(5), + QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT(6), + QUEST_COND_CITY_LEVEL_EQUAL_GREATER(7), + QUEST_COND_ITEM_NUM_LESS_THAN(8), + QUEST_COND_DAILY_TASK_START(9), + QUEST_COND_OPEN_STATE_EQUAL(10), + QUEST_COND_DAILY_TASK_OPEN(11), + QUEST_COND_DAILY_TASK_REWARD_CAN_GET(12), + QUEST_COND_DAILY_TASK_REWARD_RECEIVED(13), + QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET(14), + QUEST_COND_EXPLORATION_REWARD_CAN_GET(15), + QUEST_COND_IS_WORLD_OWNER(16), + QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER(17), + QUEST_COND_SCENE_AREA_UNLOCKED(18), + QUEST_COND_ITEM_GIVING_ACTIVED(19), + QUEST_COND_ITEM_GIVING_FINISHED(20), + QUEST_COND_IS_DAYTIME(21), + QUEST_COND_CURRENT_AVATAR(22), + QUEST_COND_CURRENT_AREA(23), + QUEST_COND_QUEST_VAR_EQUAL(24), + QUEST_COND_QUEST_VAR_GREATER(25), + QUEST_COND_QUEST_VAR_LESS(26), + QUEST_COND_FORGE_HAVE_FINISH(27), + QUEST_COND_DAILY_TASK_IN_PROGRESS(28), + QUEST_COND_DAILY_TASK_FINISHED(29), + QUEST_COND_ACTIVITY_COND(30), + QUEST_COND_ACTIVITY_OPEN(31), + QUEST_COND_DAILY_TASK_VAR_GT(32), + QUEST_COND_DAILY_TASK_VAR_EQ(33), + QUEST_COND_DAILY_TASK_VAR_LT(34), + QUEST_COND_BARGAIN_ITEM_GT(35), + QUEST_COND_BARGAIN_ITEM_EQ(36), + QUEST_COND_BARGAIN_ITEM_LT(37), + QUEST_COND_COMPLETE_TALK(38), + QUEST_COND_NOT_HAVE_BLOSSOM_TALK(39), + QUEST_COND_IS_CUR_BLOSSOM_TALK(40), + QUEST_COND_QUEST_NOT_RECEIVE(41), + QUEST_COND_QUEST_SERVER_COND_VALID(42), + QUEST_COND_ACTIVITY_CLIENT_COND(43), + QUEST_COND_QUEST_GLOBAL_VAR_EQUAL(44), + QUEST_COND_QUEST_GLOBAL_VAR_GREATER(45), + QUEST_COND_QUEST_GLOBAL_VAR_LESS(46), + QUEST_COND_PERSONAL_LINE_UNLOCK(47), + QUEST_COND_CITY_REPUTATION_REQUEST(48), + QUEST_COND_MAIN_COOP_START(49), + QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), + QUEST_COND_CITY_REPUTATION_LEVEL(51), + QUEST_COND_CITY_REPUTATION_UNLOCK(52), + QUEST_COND_LUA_NOTIFY(53), + QUEST_COND_CUR_CLIMATE(54), + QUEST_COND_ACTIVITY_END(55), + QUEST_COND_COOP_POINT_RUNNING(56), + QUEST_COND_GADGET_TALK_STATE_EQUAL(57), + QUEST_COND_AVATAR_FETTER_GT(58), + QUEST_COND_AVATAR_FETTER_EQ(59), + QUEST_COND_AVATAR_FETTER_LT(60), + QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK(61), + QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD(62), + QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH(63), + QUEST_COND_HOMEWORLD_NPC_EVENT(64), + QUEST_COND_TIME_VAR_GT_EQ(65), + QUEST_COND_TIME_VAR_PASS_DAY(66), + QUEST_COND_HOMEWORLD_NPC_NEW_TALK(67), + QUEST_COND_PLAYER_CHOOSE_MALE(68), + QUEST_COND_HISTORY_GOT_ANY_ITEM(69), + QUEST_COND_LEARNED_RECIPE(70), + QUEST_COND_LUNARITE_REGION_UNLOCKED(71), + QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT(72), + QUEST_COND_LUNARITE_COLLECT_FINISH(73), + QUEST_COND_LUNARITE_MARK_ALL_FINISH(74), + QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM(75), + QUEST_COND_SCENE_POINT_UNLOCK(76), + QUEST_COND_SCENE_LEVEL_TAG_EQ(77), + + QUEST_CONTENT_NONE(0), + QUEST_CONTENT_KILL_MONSTER(1), + QUEST_CONTENT_COMPLETE_TALK(2), + QUEST_CONTENT_MONSTER_DIE(3), + QUEST_CONTENT_FINISH_PLOT(4), + QUEST_CONTENT_OBTAIN_ITEM(5), + QUEST_CONTENT_TRIGGER_FIRE(6), + QUEST_CONTENT_CLEAR_GROUP_MONSTER(7), + QUEST_CONTENT_NOT_FINISH_PLOT(8), + QUEST_CONTENT_ENTER_DUNGEON(9), + QUEST_CONTENT_ENTER_MY_WORLD(10), + QUEST_CONTENT_FINISH_DUNGEON(11), + QUEST_CONTENT_DESTROY_GADGET(12), + QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE(13), + QUEST_CONTENT_NICK_NAME(14), + QUEST_CONTENT_WORKTOP_SELECT(15), + QUEST_CONTENT_SEAL_BATTLE_RESULT(16), + QUEST_CONTENT_ENTER_ROOM(17), + QUEST_CONTENT_GAME_TIME_TICK(18), + QUEST_CONTENT_FAIL_DUNGEON(19), + QUEST_CONTENT_LUA_NOTIFY(20), + QUEST_CONTENT_TEAM_DEAD(21), + QUEST_CONTENT_COMPLETE_ANY_TALK(22), + QUEST_CONTENT_UNLOCK_TRANS_POINT(23), + QUEST_CONTENT_ADD_QUEST_PROGRESS(24), + QUEST_CONTENT_INTERACT_GADGET(25), + QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26), + QUEST_CONTENT_FINISH_ITEM_GIVING(27), + QUEST_CONTENT_SKILL(107), + QUEST_CONTENT_CITY_LEVEL_UP(109), + QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110), + QUEST_CONTENT_ITEM_LESS_THAN(111), + QUEST_CONTENT_PLAYER_LEVEL_UP(112), + QUEST_CONTENT_DUNGEON_OPEN_STATUE(113), + QUEST_CONTENT_UNLOCK_AREA(114), + QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID(115), + QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE(116), + QUEST_CONTENT_FINISH_DAILY_DUNGEON(117), + QUEST_CONTENT_FINISH_WEEKLY_DUNGEON(118), + QUEST_CONTENT_QUEST_VAR_EQUAL(119), + QUEST_CONTENT_QUEST_VAR_GREATER(120), + QUEST_CONTENT_QUEST_VAR_LESS(121), + QUEST_CONTENT_OBTAIN_VARIOUS_ITEM(122), + QUEST_CONTENT_FINISH_TOWER_LEVEL(123), + QUEST_CONTENT_BARGAIN_SUCC(124), + QUEST_CONTENT_BARGAIN_FAIL(125), + QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126), + QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED(127), + QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT(128), + QUEST_CONTENT_ANY_MANUAL_TRANSPORT(129), + QUEST_CONTENT_USE_ITEM(130), + QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT(131), + QUEST_CONTENT_ENTER_MY_HOME_WORLD(132), + QUEST_CONTENT_ENTER_MY_WORLD_SCENE(133), + QUEST_CONTENT_TIME_VAR_GT_EQ(134), + QUEST_CONTENT_TIME_VAR_PASS_DAY(135), + QUEST_CONTENT_QUEST_STATE_EQUAL(136), + QUEST_CONTENT_QUEST_STATE_NOT_EQUAL(137), + QUEST_CONTENT_UNLOCKED_RECIPE(138), + QUEST_CONTENT_NOT_UNLOCKED_RECIPE(139), + QUEST_CONTENT_FISHING_SUCC(140), + QUEST_CONTENT_ENTER_ROGUE_DUNGEON(141), + QUEST_CONTENT_USE_WIDGET(142), + QUEST_CONTENT_CAPTURE_SUCC(143), + QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST(144), + QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST(145), + QUEST_CONTENT_ENTER_VEHICLE(147), + QUEST_CONTENT_SCENE_LEVEL_TAG_EQ(148), + QUEST_CONTENT_LEAVE_SCENE(149), + QUEST_CONTENT_LEAVE_SCENE_RANGE(150), + QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION(151), + QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS(152), + QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY(153), + + QUEST_EXEC_NONE(0), + QUEST_EXEC_DEL_PACK_ITEM(1), + QUEST_EXEC_UNLOCK_POINT(2), + QUEST_EXEC_UNLOCK_AREA(3), + QUEST_EXEC_UNLOCK_FORCE(4), + QUEST_EXEC_LOCK_FORCE(5), + QUEST_EXEC_CHANGE_AVATAR_ELEMET(6), + QUEST_EXEC_REFRESH_GROUP_MONSTER(7), + QUEST_EXEC_SET_IS_FLYABLE(8), + QUEST_EXEC_SET_IS_WEATHER_LOCKED(9), + QUEST_EXEC_SET_IS_GAME_TIME_LOCKED(10), + QUEST_EXEC_SET_IS_TRANSFERABLE(11), + QUEST_EXEC_GRANT_TRIAL_AVATAR(12), + QUEST_EXEC_OPEN_BORED(13), + QUEST_EXEC_ROLLBACK_QUEST(14), + QUEST_EXEC_NOTIFY_GROUP_LUA(15), + QUEST_EXEC_SET_OPEN_STATE(16), + QUEST_EXEC_LOCK_POINT(17), + QUEST_EXEC_DEL_PACK_ITEM_BATCH(18), + QUEST_EXEC_REFRESH_GROUP_SUITE(19), + QUEST_EXEC_REMOVE_TRIAL_AVATAR(20), + QUEST_EXEC_SET_GAME_TIME(21), + QUEST_EXEC_SET_WEATHER_GADGET(22), + QUEST_EXEC_ADD_QUEST_PROGRESS(23), + QUEST_EXEC_NOTIFY_DAILY_TASK(24), + QUEST_EXEC_CREATE_PATTERN_GROUP(25), + QUEST_EXEC_REMOVE_PATTERN_GROUP(26), + QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27), + QUEST_EXEC_ACTIVE_ITEM_GIVING(28), + QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29), + QUEST_EXEC_ROLLBACK_PARENT_QUEST(30), + QUEST_EXEC_LOCK_AVATAR_TEAM(31), + QUEST_EXEC_UNLOCK_AVATAR_TEAM(32), + QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX(33), + QUEST_EXEC_SET_DAILY_TASK_VAR(34), + QUEST_EXEC_INC_DAILY_TASK_VAR(35), + QUEST_EXEC_DEC_DAILY_TASK_VAR(36), + QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE(37), + QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE(38), + QUEST_EXEC_ADD_CUR_AVATAR_ENERGY(39), + QUEST_EXEC_START_BARGAIN(41), + QUEST_EXEC_STOP_BARGAIN(42), + QUEST_EXEC_SET_QUEST_GLOBAL_VAR(43), + QUEST_EXEC_INC_QUEST_GLOBAL_VAR(44), + QUEST_EXEC_DEC_QUEST_GLOBAL_VAR(45), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP(46), + QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP(47), + QUEST_EXEC_SET_QUEST_VAR(48), + QUEST_EXEC_INC_QUEST_VAR(49), + QUEST_EXEC_DEC_QUEST_VAR(50), + QUEST_EXEC_RANDOM_QUEST_VAR(51), + QUEST_EXEC_ACTIVATE_SCANNING_PIC(52), + QUEST_EXEC_RELOAD_SCENE_TAG(53), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY(54), + QUEST_EXEC_CHANGE_SKILL_DEPOT(55), + QUEST_EXEC_ADD_SCENE_TAG(56), + QUEST_EXEC_DEL_SCENE_TAG(57), + QUEST_EXEC_INIT_TIME_VAR(58), + QUEST_EXEC_CLEAR_TIME_VAR(59), + QUEST_EXEC_MODIFY_CLIMATE_AREA(60), + QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61), + QUEST_EXEC_CHANGE_MAP_AREA_STATE(62), + QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), + QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64), + QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65), + QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66), + QUEST_EXEC_FAIL_MAINCOOP(67), + QUEST_EXEC_MODIFY_WEATHER_AREA(68); + + private static final Int2ObjectMap contentMap = new Int2ObjectOpenHashMap<>(); + private static final Map contentStringMap = new HashMap<>(); + + static { + Stream.of(values()) + .filter(e -> e.name().startsWith("QUEST_CONTENT_")) + .forEach( + e -> { + contentMap.put(e.getValue(), e); + contentStringMap.put(e.name(), e); + }); + } + + private final int value; + + QuestTrigger(int id) { + this.value = id; + } + + public static QuestTrigger getContentTriggerByValue(int value) { + return contentMap.getOrDefault(value, QUEST_CONTENT_NONE); + } + + public static QuestTrigger getContentTriggerByName(String name) { + return contentStringMap.getOrDefault(name, QUEST_CONTENT_NONE); + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java index be1e31fe7..45e9ac446 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java @@ -1,22 +1,22 @@ -package emu.grasscutter.game.quest.enums; - -public enum QuestType { - AQ(0), - FQ(1), - LQ(2), - EQ(3), - DQ(4), - IQ(5), - VQ(6), - WQ(7); - - private final int value; - - QuestType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum QuestType { + AQ(0), + FQ(1), + LQ(2), + EQ(3), + DQ(4), + IQ(5), + VQ(6), + WQ(7); + + private final int value; + + QuestType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java index d59d1737b..a973fe818 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java @@ -1,17 +1,17 @@ -package emu.grasscutter.game.quest.enums; - -public enum ShowQuestGuideType { - QUEST_GUIDE_ITEM_ENABLE(0), - QUEST_GUIDE_ITEM_DISABLE(1), - QUEST_GUIDE_ITEM_MOVE_HIDE(2); - - private final int value; - - ShowQuestGuideType(int id) { - this.value = id; - } - - public int getValue() { - return value; - } -} +package emu.grasscutter.game.quest.enums; + +public enum ShowQuestGuideType { + QUEST_GUIDE_ITEM_ENABLE(0), + QUEST_GUIDE_ITEM_DISABLE(1), + QUEST_GUIDE_ITEM_MOVE_HIDE(2); + + private final int value; + + ShowQuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecAddQuestProgress.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecAddQuestProgress.java index 57d1f5450..5ed6c2d25 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecAddQuestProgress.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecAddQuestProgress.java @@ -1,24 +1,24 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; - -import java.util.Arrays; - -@QuestValue(QuestTrigger.QUEST_EXEC_ADD_QUEST_PROGRESS) -public class ExecAddQuestProgress extends QuestExecHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - var param = Arrays.stream(paramStr) - .filter(i -> !i.isBlank()) - .mapToInt(Integer::parseInt) - .toArray(); - - quest.getOwner().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ADD_QUEST_PROGRESS, param); - - return true; - } -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; +import java.util.Arrays; + +@QuestValue(QuestTrigger.QUEST_EXEC_ADD_QUEST_PROGRESS) +public class ExecAddQuestProgress extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + var param = + Arrays.stream(paramStr).filter(i -> !i.isBlank()).mapToInt(Integer::parseInt).toArray(); + + quest + .getOwner() + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_ADD_QUEST_PROGRESS, param); + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecDecQuestGlobalVar.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecDecQuestGlobalVar.java index 13323ac40..5d29a8209 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecDecQuestGlobalVar.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecDecQuestGlobalVar.java @@ -1,17 +1,19 @@ -package emu.grasscutter.game.quest.exec; - - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; - -@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_GLOBAL_VAR) -public class ExecDecQuestGlobalVar extends QuestExecHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - quest.getOwner().getQuestManager().decQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); - return true; - } -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_GLOBAL_VAR) +public class ExecDecQuestGlobalVar extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + quest + .getOwner() + .getQuestManager() + .decQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecIncQuestGlobalVar.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecIncQuestGlobalVar.java index e300cf5c4..4d1c32a8f 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecIncQuestGlobalVar.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecIncQuestGlobalVar.java @@ -1,16 +1,19 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; - -@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_GLOBAL_VAR) -public class ExecIncQuestGlobalVar extends QuestExecHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - quest.getOwner().getQuestManager().incQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); - return true; - } -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_GLOBAL_VAR) +public class ExecIncQuestGlobalVar extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + quest + .getOwner() + .getQuestManager() + .incQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecNotifyGroupLua.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecNotifyGroupLua.java index 9c04dc173..e0cf9edd3 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecNotifyGroupLua.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecNotifyGroupLua.java @@ -1,32 +1,32 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.ScriptArgs; - -@QuestValue(QuestTrigger.QUEST_EXEC_NOTIFY_GROUP_LUA) -public class ExecNotifyGroupLua extends QuestExecHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - var sceneId = Integer.parseInt(paramStr[0]); - var groupId = Integer.parseInt(paramStr[1]); - - var scriptManager = quest.getOwner().getScene().getScriptManager(); - - if (quest.getOwner().getScene().getId() == sceneId) { - scriptManager.callEvent( - quest.getState() == QuestState.QUEST_STATE_FINISHED ? - EventType.EVENT_QUEST_FINISH : EventType.EVENT_QUEST_START - , new ScriptArgs()); - } - - return true; - } - -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.ScriptArgs; + +@QuestValue(QuestTrigger.QUEST_EXEC_NOTIFY_GROUP_LUA) +public class ExecNotifyGroupLua extends QuestExecHandler { + + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + var sceneId = Integer.parseInt(paramStr[0]); + var groupId = Integer.parseInt(paramStr[1]); + + var scriptManager = quest.getOwner().getScene().getScriptManager(); + + if (quest.getOwner().getScene().getId() == sceneId) { + scriptManager.callEvent( + quest.getState() == QuestState.QUEST_STATE_FINISHED + ? EventType.EVENT_QUEST_FINISH + : EventType.EVENT_QUEST_START, + new ScriptArgs()); + } + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecRefreshGroupSuite.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecRefreshGroupSuite.java index 11dc7306e..a79c62ad9 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecRefreshGroupSuite.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecRefreshGroupSuite.java @@ -1,37 +1,35 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestGroupSuite; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; -import emu.grasscutter.server.packet.send.PacketGroupSuiteNotify; - -@QuestValue(QuestTrigger.QUEST_EXEC_REFRESH_GROUP_SUITE) -public class ExecRefreshGroupSuite extends QuestExecHandler { - - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - var sceneId = Integer.parseInt(paramStr[0]); - var groupId = Integer.parseInt(paramStr[1].split(",")[0]); - var suiteId = Integer.parseInt(paramStr[1].split(",")[1]); - - var scriptManager = quest.getOwner().getScene().getScriptManager(); - - quest.getMainQuest().getQuestGroupSuites().add(QuestGroupSuite.of() - .scene(sceneId) - .group(groupId) - .suite(suiteId) - .build()); - - // refresh immediately if player is in this scene - if (quest.getOwner().getScene().getId() == sceneId) { - scriptManager.refreshGroup(scriptManager.getGroupById(groupId), suiteId); - quest.getOwner().sendPacket(new PacketGroupSuiteNotify(groupId, suiteId)); - } - - return true; - } - -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestGroupSuite; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; +import emu.grasscutter.server.packet.send.PacketGroupSuiteNotify; + +@QuestValue(QuestTrigger.QUEST_EXEC_REFRESH_GROUP_SUITE) +public class ExecRefreshGroupSuite extends QuestExecHandler { + + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + var sceneId = Integer.parseInt(paramStr[0]); + var groupId = Integer.parseInt(paramStr[1].split(",")[0]); + var suiteId = Integer.parseInt(paramStr[1].split(",")[1]); + + var scriptManager = quest.getOwner().getScene().getScriptManager(); + + quest + .getMainQuest() + .getQuestGroupSuites() + .add(QuestGroupSuite.of().scene(sceneId).group(groupId).suite(suiteId).build()); + + // refresh immediately if player is in this scene + if (quest.getOwner().getScene().getId() == sceneId) { + scriptManager.refreshGroup(scriptManager.getGroupById(groupId), suiteId); + quest.getOwner().sendPacket(new PacketGroupSuiteNotify(groupId, suiteId)); + } + + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecSetQuestGlobalVar.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecSetQuestGlobalVar.java index 89827ea59..497faa14c 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecSetQuestGlobalVar.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecSetQuestGlobalVar.java @@ -1,16 +1,19 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; - -@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_GLOBAL_VAR) -public class ExecSetQuestGlobalVar extends QuestExecHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - quest.getOwner().getQuestManager().setQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); - return true; - } -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_GLOBAL_VAR) +public class ExecSetQuestGlobalVar extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + quest + .getOwner() + .getQuestManager() + .setQuestGlobalVarValue(Integer.valueOf(paramStr[0]), Integer.valueOf(paramStr[1])); + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/exec/ExecUnlockArea.java b/src/main/java/emu/grasscutter/game/quest/exec/ExecUnlockArea.java index b6164f92d..fcede0b46 100644 --- a/src/main/java/emu/grasscutter/game/quest/exec/ExecUnlockArea.java +++ b/src/main/java/emu/grasscutter/game/quest/exec/ExecUnlockArea.java @@ -1,21 +1,21 @@ -package emu.grasscutter.game.quest.exec; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.game.quest.QuestValue; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.game.quest.handlers.QuestExecHandler; - -@QuestValue(QuestTrigger.QUEST_EXEC_UNLOCK_AREA) -public class ExecUnlockArea extends QuestExecHandler { - @Override - public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { - // Unlock the trans point for the player. - int sceneId = Integer.parseInt(paramStr[0]); - int areaId = Integer.parseInt(paramStr[1]); - quest.getOwner().getProgressManager().unlockSceneArea(sceneId, areaId); - - // Done. - return true; - } -} +package emu.grasscutter.game.quest.exec; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestExecHandler; + +@QuestValue(QuestTrigger.QUEST_EXEC_UNLOCK_AREA) +public class ExecUnlockArea extends QuestExecHandler { + @Override + public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) { + // Unlock the trans point for the player. + int sceneId = Integer.parseInt(paramStr[0]); + int areaId = Integer.parseInt(paramStr[1]); + quest.getOwner().getProgressManager().unlockSceneArea(sceneId, areaId); + + // Done. + return true; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java index 625212b59..507777979 100644 --- a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java +++ b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java @@ -1,10 +1,10 @@ -package emu.grasscutter.game.quest.handlers; - -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.GameQuest; - -public abstract class QuestBaseHandler { - - public abstract boolean execute(GameQuest quest, QuestCondition condition, String paramStr, int... params); - -} +package emu.grasscutter.game.quest.handlers; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; + +public abstract class QuestBaseHandler { + + public abstract boolean execute( + GameQuest quest, QuestCondition condition, String paramStr, int... params); +} diff --git a/src/main/java/emu/grasscutter/game/quest/handlers/QuestExecHandler.java b/src/main/java/emu/grasscutter/game/quest/handlers/QuestExecHandler.java index 3dcc6e889..dc927532e 100644 --- a/src/main/java/emu/grasscutter/game/quest/handlers/QuestExecHandler.java +++ b/src/main/java/emu/grasscutter/game/quest/handlers/QuestExecHandler.java @@ -1,10 +1,10 @@ -package emu.grasscutter.game.quest.handlers; - -import emu.grasscutter.data.excels.QuestData; -import emu.grasscutter.game.quest.GameQuest; - -public abstract class QuestExecHandler { - - public abstract boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr); - -} +package emu.grasscutter.game.quest.handlers; + +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.game.quest.GameQuest; + +public abstract class QuestExecHandler { + + public abstract boolean execute( + GameQuest quest, QuestData.QuestExecParam condition, String... paramStr); +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java index 2cc8656f9..9b213107f 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java @@ -1,126 +1,95 @@ -package emu.grasscutter.game.shop; - -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ShopGoodsData; -import lombok.Getter; -import lombok.Setter; - -import java.util.ArrayList; -import java.util.List; - -public class ShopInfo { - @Getter - @Setter - private int goodsId = 0; - @Getter - @Setter - private ItemParamData goodsItem; - @Getter - @Setter - private int scoin = 0; - @Getter - @Setter - private List costItemList; - @Getter - @Setter - private int boughtNum = 0; - @Getter - @Setter - private int buyLimit = 0; - @Getter - @Setter - private int beginTime = 0; - @Getter - @Setter - private int endTime = 1924992000; - @Getter - @Setter - private int minLevel = 0; - @Getter - @Setter - private int maxLevel = 61; - @Getter - @Setter - private List preGoodsIdList = new ArrayList<>(); - @Getter - @Setter - private int mcoin = 0; - @Getter - @Setter - private int hcoin = 0; - @Getter - @Setter - private int disableType = 0; - @Getter - @Setter - private int secondarySheetId = 0; - - private String refreshType; - @Setter - private transient ShopRefreshType shopRefreshType; - @Getter - @Setter - private int shopRefreshParam; - public ShopInfo(ShopGoodsData sgd) { - this.goodsId = sgd.getGoodsId(); - this.goodsItem = new ItemParamData(sgd.getItemId(), sgd.getItemCount()); - this.scoin = sgd.getCostScoin(); - this.mcoin = sgd.getCostMcoin(); - this.hcoin = sgd.getCostHcoin(); - this.buyLimit = sgd.getBuyLimit(); - - this.minLevel = sgd.getMinPlayerLevel(); - this.maxLevel = sgd.getMaxPlayerLevel(); - this.costItemList = sgd.getCostItems().stream().filter(x -> x.getId() != 0).map(x -> new ItemParamData(x.getId(), x.getCount())).toList(); - this.secondarySheetId = sgd.getSubTabId(); - this.shopRefreshType = sgd.getRefreshType(); - this.shopRefreshParam = sgd.getRefreshParam(); - } - - public ShopRefreshType getShopRefreshType() { - if (refreshType == null) - return ShopRefreshType.NONE; - return switch (refreshType) { - case "SHOP_REFRESH_DAILY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_DAILY; - case "SHOP_REFRESH_WEEKLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_WEEKLY; - case "SHOP_REFRESH_MONTHLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_MONTHLY; - default -> ShopInfo.ShopRefreshType.NONE; - }; - } - - private boolean evaluateVirtualCost(ItemParamData item) { - return switch (item.getId()) { - case 201 -> { - this.hcoin += item.getCount(); - yield true; - } - case 203 -> { - this.mcoin += item.getCount(); - yield true; - } - default -> false; - }; - } - - public void removeVirtualCosts() { - if (this.costItemList != null) - this.costItemList.removeIf(item -> evaluateVirtualCost(item)); - } - - public enum ShopRefreshType { - NONE(0), - SHOP_REFRESH_DAILY(1), - SHOP_REFRESH_WEEKLY(2), - SHOP_REFRESH_MONTHLY(3); - - private final int value; - - ShopRefreshType(int value) { - this.value = value; - } - - public int value() { - return value; - } - } -} +package emu.grasscutter.game.shop; + +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ShopGoodsData; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +public class ShopInfo { + @Getter @Setter private int goodsId = 0; + @Getter @Setter private ItemParamData goodsItem; + @Getter @Setter private int scoin = 0; + @Getter @Setter private List costItemList; + @Getter @Setter private int boughtNum = 0; + @Getter @Setter private int buyLimit = 0; + @Getter @Setter private int beginTime = 0; + @Getter @Setter private int endTime = 1924992000; + @Getter @Setter private int minLevel = 0; + @Getter @Setter private int maxLevel = 61; + @Getter @Setter private List preGoodsIdList = new ArrayList<>(); + @Getter @Setter private int mcoin = 0; + @Getter @Setter private int hcoin = 0; + @Getter @Setter private int disableType = 0; + @Getter @Setter private int secondarySheetId = 0; + + private String refreshType; + @Setter private transient ShopRefreshType shopRefreshType; + @Getter @Setter private int shopRefreshParam; + + public ShopInfo(ShopGoodsData sgd) { + this.goodsId = sgd.getGoodsId(); + this.goodsItem = new ItemParamData(sgd.getItemId(), sgd.getItemCount()); + this.scoin = sgd.getCostScoin(); + this.mcoin = sgd.getCostMcoin(); + this.hcoin = sgd.getCostHcoin(); + this.buyLimit = sgd.getBuyLimit(); + + this.minLevel = sgd.getMinPlayerLevel(); + this.maxLevel = sgd.getMaxPlayerLevel(); + this.costItemList = + sgd.getCostItems().stream() + .filter(x -> x.getId() != 0) + .map(x -> new ItemParamData(x.getId(), x.getCount())) + .toList(); + this.secondarySheetId = sgd.getSubTabId(); + this.shopRefreshType = sgd.getRefreshType(); + this.shopRefreshParam = sgd.getRefreshParam(); + } + + public ShopRefreshType getShopRefreshType() { + if (refreshType == null) return ShopRefreshType.NONE; + return switch (refreshType) { + case "SHOP_REFRESH_DAILY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_DAILY; + case "SHOP_REFRESH_WEEKLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_WEEKLY; + case "SHOP_REFRESH_MONTHLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_MONTHLY; + default -> ShopInfo.ShopRefreshType.NONE; + }; + } + + private boolean evaluateVirtualCost(ItemParamData item) { + return switch (item.getId()) { + case 201 -> { + this.hcoin += item.getCount(); + yield true; + } + case 203 -> { + this.mcoin += item.getCount(); + yield true; + } + default -> false; + }; + } + + public void removeVirtualCosts() { + if (this.costItemList != null) this.costItemList.removeIf(item -> evaluateVirtualCost(item)); + } + + public enum ShopRefreshType { + NONE(0), + SHOP_REFRESH_DAILY(1), + SHOP_REFRESH_WEEKLY(2), + SHOP_REFRESH_MONTHLY(3); + + private final int value; + + ShopRefreshType(int value) { + this.value = value; + } + + public int value() { + return value; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopLimit.java b/src/main/java/emu/grasscutter/game/shop/ShopLimit.java index 827826803..c8e7840df 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopLimit.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopLimit.java @@ -1,43 +1,43 @@ -package emu.grasscutter.game.shop; - -import dev.morphia.annotations.Entity; - -@Entity -public class ShopLimit { - private int shopGoodId; - private int hasBought; - private int hasBoughtInPeriod = 0; - private int nextRefreshTime = 0; - - public int getShopGoodId() { - return shopGoodId; - } - - public void setShopGoodId(int shopGoodId) { - this.shopGoodId = shopGoodId; - } - - public int getHasBought() { - return hasBought; - } - - public void setHasBought(int hasBought) { - this.hasBought = hasBought; - } - - public int getNextRefreshTime() { - return nextRefreshTime; - } - - public void setNextRefreshTime(int nextRefreshTime) { - this.nextRefreshTime = nextRefreshTime; - } - - public int getHasBoughtInPeriod() { - return hasBoughtInPeriod; - } - - public void setHasBoughtInPeriod(int hasBoughtInPeriod) { - this.hasBoughtInPeriod = hasBoughtInPeriod; - } -} +package emu.grasscutter.game.shop; + +import dev.morphia.annotations.Entity; + +@Entity +public class ShopLimit { + private int shopGoodId; + private int hasBought; + private int hasBoughtInPeriod = 0; + private int nextRefreshTime = 0; + + public int getShopGoodId() { + return shopGoodId; + } + + public void setShopGoodId(int shopGoodId) { + this.shopGoodId = shopGoodId; + } + + public int getHasBought() { + return hasBought; + } + + public void setHasBought(int hasBought) { + this.hasBought = hasBought; + } + + public int getNextRefreshTime() { + return nextRefreshTime; + } + + public void setNextRefreshTime(int nextRefreshTime) { + this.nextRefreshTime = nextRefreshTime; + } + + public int getHasBoughtInPeriod() { + return hasBoughtInPeriod; + } + + public void setHasBoughtInPeriod(int hasBoughtInPeriod) { + this.hasBoughtInPeriod = hasBoughtInPeriod; + } +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopSystem.java b/src/main/java/emu/grasscutter/game/shop/ShopSystem.java index 3f034e99b..3b804e210 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopSystem.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopSystem.java @@ -1,112 +1,115 @@ -package emu.grasscutter.game.shop; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.ShopGoodsData; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -public class ShopSystem extends BaseGameSystem { - private static final int REFRESH_HOUR = 4; // In GMT+8 server - private static final String TIME_ZONE = "Asia/Shanghai"; // GMT+8 Timezone - private final Int2ObjectMap> shopData; - private final Int2ObjectMap> shopChestData; - - public ShopSystem(GameServer server) { - super(server); - this.shopData = new Int2ObjectOpenHashMap<>(); - this.shopChestData = new Int2ObjectOpenHashMap<>(); - this.load(); - } - - public static int getShopNextRefreshTime(ShopInfo shopInfo) { - return switch (shopInfo.getShopRefreshType()) { - case SHOP_REFRESH_DAILY -> - Utils.getNextTimestampOfThisHour(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); - case SHOP_REFRESH_WEEKLY -> - Utils.getNextTimestampOfThisHourInNextWeek(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); - case SHOP_REFRESH_MONTHLY -> - Utils.getNextTimestampOfThisHourInNextMonth(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); - default -> 0; - }; - } - - public Int2ObjectMap> getShopData() { - return shopData; - } - - public List getShopChestData(int chestId) { - return this.shopChestData.get(chestId); - } - - private void loadShop() { - getShopData().clear(); - try { - List banners = DataLoader.loadList("Shop.json", ShopTable.class); - if (banners.size() > 0) { - for (ShopTable shopTable : banners) { - shopTable.getItems().forEach(ShopInfo::removeVirtualCosts); - getShopData().put(shopTable.getShopId(), shopTable.getItems()); - } - Grasscutter.getLogger().debug("Shop data successfully loaded."); - } else { - Grasscutter.getLogger().error("Unable to load shop data. Shop data size is 0."); - } - - if (GAME_OPTIONS.enableShopItems) { - GameData.getShopGoodsDataEntries().forEach((k, v) -> { - if (!getShopData().containsKey(k.intValue())) - getShopData().put(k.intValue(), new ArrayList<>()); - for (ShopGoodsData sgd : v) { - var shopInfo = new ShopInfo(sgd); - getShopData().get(k.intValue()).add(shopInfo); - } - }); - } - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load shop data.", e); - } - } - - private void loadShopChest() { - shopChestData.clear(); - try { - Map chestMap = DataLoader.loadMap("ShopChest.v2.json", Integer.class, String.class); - chestMap.forEach((chestId, itemStr) -> { - if (itemStr.isEmpty()) return; - var entries = itemStr.split(","); - var list = new ArrayList(entries.length); - for (var entry : entries) { - var idAndCount = entry.split(":"); - int id = Integer.parseInt(idAndCount[0]); - int count = Integer.parseInt(idAndCount[1]); - list.add(new ItemParamData(id, count)); - } - this.shopChestData.put((int) chestId, list); - }); - Grasscutter.getLogger().debug("Loaded " + chestMap.size() + " ShopChest entries."); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load ShopChest data.", e); - } - } - - public synchronized void load() { - loadShop(); - loadShopChest(); - } - - public GameServer getServer() { - return server; - } -} +package emu.grasscutter.game.shop; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ShopGoodsData; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class ShopSystem extends BaseGameSystem { + private static final int REFRESH_HOUR = 4; // In GMT+8 server + private static final String TIME_ZONE = "Asia/Shanghai"; // GMT+8 Timezone + private final Int2ObjectMap> shopData; + private final Int2ObjectMap> shopChestData; + + public ShopSystem(GameServer server) { + super(server); + this.shopData = new Int2ObjectOpenHashMap<>(); + this.shopChestData = new Int2ObjectOpenHashMap<>(); + this.load(); + } + + public static int getShopNextRefreshTime(ShopInfo shopInfo) { + return switch (shopInfo.getShopRefreshType()) { + case SHOP_REFRESH_DAILY -> Utils.getNextTimestampOfThisHour( + REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); + case SHOP_REFRESH_WEEKLY -> Utils.getNextTimestampOfThisHourInNextWeek( + REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); + case SHOP_REFRESH_MONTHLY -> Utils.getNextTimestampOfThisHourInNextMonth( + REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam()); + default -> 0; + }; + } + + public Int2ObjectMap> getShopData() { + return shopData; + } + + public List getShopChestData(int chestId) { + return this.shopChestData.get(chestId); + } + + private void loadShop() { + getShopData().clear(); + try { + List banners = DataLoader.loadList("Shop.json", ShopTable.class); + if (banners.size() > 0) { + for (ShopTable shopTable : banners) { + shopTable.getItems().forEach(ShopInfo::removeVirtualCosts); + getShopData().put(shopTable.getShopId(), shopTable.getItems()); + } + Grasscutter.getLogger().debug("Shop data successfully loaded."); + } else { + Grasscutter.getLogger().error("Unable to load shop data. Shop data size is 0."); + } + + if (GAME_OPTIONS.enableShopItems) { + GameData.getShopGoodsDataEntries() + .forEach( + (k, v) -> { + if (!getShopData().containsKey(k.intValue())) + getShopData().put(k.intValue(), new ArrayList<>()); + for (ShopGoodsData sgd : v) { + var shopInfo = new ShopInfo(sgd); + getShopData().get(k.intValue()).add(shopInfo); + } + }); + } + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load shop data.", e); + } + } + + private void loadShopChest() { + shopChestData.clear(); + try { + Map chestMap = + DataLoader.loadMap("ShopChest.v2.json", Integer.class, String.class); + chestMap.forEach( + (chestId, itemStr) -> { + if (itemStr.isEmpty()) return; + var entries = itemStr.split(","); + var list = new ArrayList(entries.length); + for (var entry : entries) { + var idAndCount = entry.split(":"); + int id = Integer.parseInt(idAndCount[0]); + int count = Integer.parseInt(idAndCount[1]); + list.add(new ItemParamData(id, count)); + } + this.shopChestData.put((int) chestId, list); + }); + Grasscutter.getLogger().debug("Loaded " + chestMap.size() + " ShopChest entries."); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load ShopChest data.", e); + } + } + + public synchronized void load() { + loadShop(); + loadShopChest(); + } + + public GameServer getServer() { + return server; + } +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopType.java b/src/main/java/emu/grasscutter/game/shop/ShopType.java index 7a314d4d0..8c082d149 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopType.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopType.java @@ -1,107 +1,107 @@ -package emu.grasscutter.game.shop; - -/** - * ShopTypes 0-1010 based on `ActivityShopOverallExcelConfigData.json` - * ShopTypes for activities are partially guessed on the version, and partially tested - * ShopTypes 1011-1070 are mostly based of `BinOutput/InterAction/Shop` - */ -public enum ShopType { - SHOP_TYPE_NONE(0), - SHOP_TYPE_PAIMON(900), - SHOP_TYPE_PACKAGE(902), - SHOP_TYPE_MCOIN(903), - SHOP_TYPE_RECOMMEND(1001), - SHOP_TYPE_CITY(1002), - SHOP_TYPE_BLACKSMITH(1003), - SHOP_TYPE_GROCERY(1004), - SHOP_TYPE_FOOD(1005), - SHOP_TYPE_SEA_LAMP(1006), - SHOP_TYPE_VIRTUAL_SHOP(1007), - SHOP_TYPE_LIYUE_GROCERY(1008), - SHOP_TYPE_LIYUE_SOUVENIR(1009), - SHOP_TYPE_LIYUE_RESTAURANT(1010), - SHOP_TYPE_NPC_Flora(1011), - SHOP_TYPE_NPC_Charles(1012), - SHOP_TYPE_NPC_Shiliu(1013), - SHOP_TYPE_NPC_Schulz(1014), - SHOP_TYPE_NPC_Brook(1015), - SHOP_TYPE_NPC_Hopkins(1016), - SHOP_TYPE_NPC_Draff(1017), - SHOP_TYPE_NPC_Chloris(1018), - SHOP_TYPE_NPC_Licai(1019), - SHOP_TYPE_NPC_Yueshu(1020), - SHOP_TYPE_NPC_Gui(1021), - SHOP_TYPE_NPC_Gao(1022), - SHOP_TYPE_NPC_Sun(1023), - SHOP_TYPE_NPC_Qiming(1024), - SHOP_TYPE_NPC_Zhangshun(1025), - SHOP_TYPE_NPC_Chen(1026), - SHOP_TYPE_NPC_ErNiang(1027), - SHOP_TYPE_NPC_Shitou(1028), - SHOP_TYPE_NPC_Jifang(1029), - SHOP_TYPE_NPC_Zhu(1030), - SHOP_TYPE_NPC_Bai(1031), - SHOP_TYPE_NPC_Kai(1032), - SHOP_TYPE_NPC_Linglang(1033), - SHOP_TYPE_NPC_VerrGoldet(1034), - SHOP_TYPE_NPC_Zhou(1035), - SHOP_TYPE_TASK_Ekaterina(1036), - SHOP_TYPE_ACTIVITY_ASTER(1037), - SHOP_TYPE_TASK_Tartaglia(1038), - SHOP_TYPE_NPC_Harris(1039), - SHOP_TYPE_ACTIVITY_DRAGON_SPINE(1040), - SHOP_TYPE_ACTIVITY_TREASURE_MAP(1041), - SHOP_TYPE_NPC_Yinian(1042), - SHOP_TYPE_ACTIVITY_SEA_LAMP(1043), //event guess - SHOP_TYPE_ACTIVITY_FLEUR_FAIR(1044), - SHOP_TYPE_NPC_Changshun(1045), - SHOP_TYPE_NPC_Bolai(1046), - SHOP_TYPE_NPC_Ashanpo(1047), - SHOP_TYPE_HOME(1048), - SHOP_TYPE_HOME_LIMIT(1049), - SHOP_TYPE_NPC_MasterLu(1050), - SHOP_TYPE_NPC_Goth(1051), - SHOP_TYPE_COSTUME(1052), - SHOP_TYPE_NPC_Obata(1053), - SHOP_TYPE_NPC_Qiuyue(1054), - SHOP_TYPE_NPC_Ryouko(1055), - SHOP_TYPE_INAZUMA_GROCERY(1056), - SHOP_TYPE_INAZUMA_SOUVENIR(1057), - SHOP_TYPE_INAZUMA_RESTAURANT(1058), - SHOP_TYPE_NPC_Kuroda(1059), - SHOP_TYPE_NPC_KiminamiAnna(1060), - SHOP_TYPE_NPC_Tomoki(1061), - SHOP_TYPE_NPC_Karpillia(1062), - SHOP_TYPE_BLACKSMITH_INAZUMA(1063), - SHOP_TYPE_FISH(1064), - SHOP_TYPE_FISH_LIYUE(1065), - SHOP_TYPE_FISH_INAZUMA(1066), - SHOP_TYPE_NPC_Kiyoko(1067), - SHOP_TYPE_EXPIRED_WIDGET_MENGDE(1068), - SHOP_TYPE_CAPTURE_ANIMAL_SHOP(1069), - SHOP_TYPE_NPC_YamashiroKenta(1070), - SHOP_TYPE_ACTIVITY_CHANNELLER_SLAB(15001), //prob - SHOP_TYPE_ACTIVITY_SUMMER_TIME(16001), - SHOP_TYPE_ACTIVITY_BOUNCE_CONJURING(16002), - SHOP_TYPE_ACTIVITY_BLITZ_RUSH(20001),// guess - SHOP_TYPE_ACTIVITY_CHESS(20002),// guess - SHOP_TYPE_ACTIVITY_WINTER_CAMP(20004), - SHOP_TYPE_ACTIVITY_LANTERN_RITE(20005),// guess - SHOP_TYPE_ACTIVITY_ROGUELIKE_DUNGEON(22001),// guess - SHOP_TYPE_ACTIVITY_ROGUE_DIARY(27001),// guess - SHOP_TYPE_ACTIVITY_SUMMER_TIME_V2(28001), // guess - SHOP_TYPE_ACTIVITY_GRAVEN_INNOCENCE(30001); // guess - - public final int shopTypeId; - - ShopType(int shopTypeId) { - this.shopTypeId = shopTypeId; - } - - public static ShopType getById(int shopTypeId) { - for (ShopType type : ShopType.values()) { - if (type.shopTypeId == shopTypeId) return type; - } - return SHOP_TYPE_NONE; - } -} +package emu.grasscutter.game.shop; + +/** + * ShopTypes 0-1010 based on `ActivityShopOverallExcelConfigData.json` ShopTypes for activities are + * partially guessed on the version, and partially tested ShopTypes 1011-1070 are mostly based of + * `BinOutput/InterAction/Shop` + */ +public enum ShopType { + SHOP_TYPE_NONE(0), + SHOP_TYPE_PAIMON(900), + SHOP_TYPE_PACKAGE(902), + SHOP_TYPE_MCOIN(903), + SHOP_TYPE_RECOMMEND(1001), + SHOP_TYPE_CITY(1002), + SHOP_TYPE_BLACKSMITH(1003), + SHOP_TYPE_GROCERY(1004), + SHOP_TYPE_FOOD(1005), + SHOP_TYPE_SEA_LAMP(1006), + SHOP_TYPE_VIRTUAL_SHOP(1007), + SHOP_TYPE_LIYUE_GROCERY(1008), + SHOP_TYPE_LIYUE_SOUVENIR(1009), + SHOP_TYPE_LIYUE_RESTAURANT(1010), + SHOP_TYPE_NPC_Flora(1011), + SHOP_TYPE_NPC_Charles(1012), + SHOP_TYPE_NPC_Shiliu(1013), + SHOP_TYPE_NPC_Schulz(1014), + SHOP_TYPE_NPC_Brook(1015), + SHOP_TYPE_NPC_Hopkins(1016), + SHOP_TYPE_NPC_Draff(1017), + SHOP_TYPE_NPC_Chloris(1018), + SHOP_TYPE_NPC_Licai(1019), + SHOP_TYPE_NPC_Yueshu(1020), + SHOP_TYPE_NPC_Gui(1021), + SHOP_TYPE_NPC_Gao(1022), + SHOP_TYPE_NPC_Sun(1023), + SHOP_TYPE_NPC_Qiming(1024), + SHOP_TYPE_NPC_Zhangshun(1025), + SHOP_TYPE_NPC_Chen(1026), + SHOP_TYPE_NPC_ErNiang(1027), + SHOP_TYPE_NPC_Shitou(1028), + SHOP_TYPE_NPC_Jifang(1029), + SHOP_TYPE_NPC_Zhu(1030), + SHOP_TYPE_NPC_Bai(1031), + SHOP_TYPE_NPC_Kai(1032), + SHOP_TYPE_NPC_Linglang(1033), + SHOP_TYPE_NPC_VerrGoldet(1034), + SHOP_TYPE_NPC_Zhou(1035), + SHOP_TYPE_TASK_Ekaterina(1036), + SHOP_TYPE_ACTIVITY_ASTER(1037), + SHOP_TYPE_TASK_Tartaglia(1038), + SHOP_TYPE_NPC_Harris(1039), + SHOP_TYPE_ACTIVITY_DRAGON_SPINE(1040), + SHOP_TYPE_ACTIVITY_TREASURE_MAP(1041), + SHOP_TYPE_NPC_Yinian(1042), + SHOP_TYPE_ACTIVITY_SEA_LAMP(1043), // event guess + SHOP_TYPE_ACTIVITY_FLEUR_FAIR(1044), + SHOP_TYPE_NPC_Changshun(1045), + SHOP_TYPE_NPC_Bolai(1046), + SHOP_TYPE_NPC_Ashanpo(1047), + SHOP_TYPE_HOME(1048), + SHOP_TYPE_HOME_LIMIT(1049), + SHOP_TYPE_NPC_MasterLu(1050), + SHOP_TYPE_NPC_Goth(1051), + SHOP_TYPE_COSTUME(1052), + SHOP_TYPE_NPC_Obata(1053), + SHOP_TYPE_NPC_Qiuyue(1054), + SHOP_TYPE_NPC_Ryouko(1055), + SHOP_TYPE_INAZUMA_GROCERY(1056), + SHOP_TYPE_INAZUMA_SOUVENIR(1057), + SHOP_TYPE_INAZUMA_RESTAURANT(1058), + SHOP_TYPE_NPC_Kuroda(1059), + SHOP_TYPE_NPC_KiminamiAnna(1060), + SHOP_TYPE_NPC_Tomoki(1061), + SHOP_TYPE_NPC_Karpillia(1062), + SHOP_TYPE_BLACKSMITH_INAZUMA(1063), + SHOP_TYPE_FISH(1064), + SHOP_TYPE_FISH_LIYUE(1065), + SHOP_TYPE_FISH_INAZUMA(1066), + SHOP_TYPE_NPC_Kiyoko(1067), + SHOP_TYPE_EXPIRED_WIDGET_MENGDE(1068), + SHOP_TYPE_CAPTURE_ANIMAL_SHOP(1069), + SHOP_TYPE_NPC_YamashiroKenta(1070), + SHOP_TYPE_ACTIVITY_CHANNELLER_SLAB(15001), // prob + SHOP_TYPE_ACTIVITY_SUMMER_TIME(16001), + SHOP_TYPE_ACTIVITY_BOUNCE_CONJURING(16002), + SHOP_TYPE_ACTIVITY_BLITZ_RUSH(20001), // guess + SHOP_TYPE_ACTIVITY_CHESS(20002), // guess + SHOP_TYPE_ACTIVITY_WINTER_CAMP(20004), + SHOP_TYPE_ACTIVITY_LANTERN_RITE(20005), // guess + SHOP_TYPE_ACTIVITY_ROGUELIKE_DUNGEON(22001), // guess + SHOP_TYPE_ACTIVITY_ROGUE_DIARY(27001), // guess + SHOP_TYPE_ACTIVITY_SUMMER_TIME_V2(28001), // guess + SHOP_TYPE_ACTIVITY_GRAVEN_INNOCENCE(30001); // guess + + public final int shopTypeId; + + ShopType(int shopTypeId) { + this.shopTypeId = shopTypeId; + } + + public static ShopType getById(int shopTypeId) { + for (ShopType type : ShopType.values()) { + if (type.shopTypeId == shopTypeId) return type; + } + return SHOP_TYPE_NONE; + } +} diff --git a/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java b/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java index e09647acc..27ec0e744 100644 --- a/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java +++ b/src/main/java/emu/grasscutter/game/systems/AnnouncementSystem.java @@ -1,108 +1,107 @@ -package emu.grasscutter.game.systems; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.proto.AnnounceDataOuterClass; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify; -import emu.grasscutter.server.packet.send.PacketServerAnnounceRevokeNotify; -import emu.grasscutter.utils.Utils; -import lombok.AccessLevel; -import lombok.Data; -import lombok.Getter; -import lombok.experimental.FieldDefaults; - -import java.util.*; - -@Getter -public class AnnouncementSystem extends BaseGameSystem { - private final Map announceConfigItemMap; - - public AnnouncementSystem(GameServer server) { - super(server); - this.announceConfigItemMap = new HashMap<>(); - loadConfig(); - } - - private int loadConfig() { - try { - List announceConfigItems = DataLoader.loadList("Announcement.json", AnnounceConfigItem.class); - - announceConfigItemMap.clear(); - announceConfigItems.forEach(i -> announceConfigItemMap.put(i.getTemplateId(), i)); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load server announce config.", e); - } - - return announceConfigItemMap.size(); - } - - public List getOnlinePlayers() { - return getServer().getWorlds().stream() - .map(World::getPlayers) - .flatMap(Collection::stream) - .toList(); - } - - public void broadcast(List tpl) { - if (tpl == null || tpl.size() == 0) { - return; - } - - var list = tpl.stream() - .map(AnnounceConfigItem::toProto) - .map(AnnounceDataOuterClass.AnnounceData.Builder::build) - .toList(); - - getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(list))); - } - - public int refresh() { - return loadConfig(); - } - - public void revoke(int tplId) { - getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceRevokeNotify(tplId))); - } - - public enum AnnounceType { - CENTER, COUNTDOWN - } - - @Data - @FieldDefaults(level = AccessLevel.PRIVATE) - public class AnnounceConfigItem { - int templateId; - AnnounceType type; - int frequency; - String content; - Date beginTime; - Date endTime; - boolean tick; - int interval; - - public AnnounceDataOuterClass.AnnounceData.Builder toProto() { - var proto = AnnounceDataOuterClass.AnnounceData.newBuilder(); - - proto.setConfigId(templateId) - // I found the time here is useless - .setBeginTime(Utils.getCurrentSeconds() + 1) - .setEndTime(Utils.getCurrentSeconds() + 10); - - if (type == AnnounceType.CENTER) { - proto.setCenterSystemText(content) - .setCenterSystemFrequency(frequency) - ; - } else { - proto.setCountDownText(content) - .setCountDownFrequency(frequency) - ; - } - - return proto; - } - } -} +package emu.grasscutter.game.systems; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.proto.AnnounceDataOuterClass; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify; +import emu.grasscutter.server.packet.send.PacketServerAnnounceRevokeNotify; +import emu.grasscutter.utils.Utils; +import java.util.*; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@Getter +public class AnnouncementSystem extends BaseGameSystem { + private final Map announceConfigItemMap; + + public AnnouncementSystem(GameServer server) { + super(server); + this.announceConfigItemMap = new HashMap<>(); + loadConfig(); + } + + private int loadConfig() { + try { + List announceConfigItems = + DataLoader.loadList("Announcement.json", AnnounceConfigItem.class); + + announceConfigItemMap.clear(); + announceConfigItems.forEach(i -> announceConfigItemMap.put(i.getTemplateId(), i)); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load server announce config.", e); + } + + return announceConfigItemMap.size(); + } + + public List getOnlinePlayers() { + return getServer().getWorlds().stream() + .map(World::getPlayers) + .flatMap(Collection::stream) + .toList(); + } + + public void broadcast(List tpl) { + if (tpl == null || tpl.size() == 0) { + return; + } + + var list = + tpl.stream() + .map(AnnounceConfigItem::toProto) + .map(AnnounceDataOuterClass.AnnounceData.Builder::build) + .toList(); + + getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(list))); + } + + public int refresh() { + return loadConfig(); + } + + public void revoke(int tplId) { + getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceRevokeNotify(tplId))); + } + + public enum AnnounceType { + CENTER, + COUNTDOWN + } + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + public class AnnounceConfigItem { + int templateId; + AnnounceType type; + int frequency; + String content; + Date beginTime; + Date endTime; + boolean tick; + int interval; + + public AnnounceDataOuterClass.AnnounceData.Builder toProto() { + var proto = AnnounceDataOuterClass.AnnounceData.newBuilder(); + + proto + .setConfigId(templateId) + // I found the time here is useless + .setBeginTime(Utils.getCurrentSeconds() + 1) + .setEndTime(Utils.getCurrentSeconds() + 10); + + if (type == AnnounceType.CENTER) { + proto.setCenterSystemText(content).setCenterSystemFrequency(frequency); + } else { + proto.setCountDownText(content).setCountDownFrequency(frequency); + } + + return proto; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/systems/InventorySystem.java b/src/main/java/emu/grasscutter/game/systems/InventorySystem.java index 31a7fe446..b5fb139c4 100644 --- a/src/main/java/emu/grasscutter/game/systems/InventorySystem.java +++ b/src/main/java/emu/grasscutter/game/systems/InventorySystem.java @@ -1,830 +1,915 @@ -package emu.grasscutter.game.systems; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.excels.AvatarPromoteData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.data.excels.WeaponPromoteData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.inventory.MaterialType; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.ItemUseAction.ItemUseAddExp; -import emu.grasscutter.game.props.ItemUseAction.ItemUseAddReliquaryExp; -import emu.grasscutter.game.props.ItemUseAction.ItemUseAddWeaponExp; -import emu.grasscutter.game.props.ItemUseAction.UseItemParams; -import emu.grasscutter.game.props.ItemUseOp; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; -import emu.grasscutter.server.event.player.PlayerUseFoodEvent; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Utils; -import it.unimi.dsi.fastutil.ints.*; -import lombok.val; - -import java.util.*; -import java.util.stream.Stream; - -public class InventorySystem extends BaseGameSystem { - private static final Int2IntMap weaponRefundMaterials = new Int2IntArrayMap(); - - { - // Use a sorted map, use exp as key to sort by exp - // We want to have weaponRefundMaterials as (id, exp) in descending exp order - var temp = new Int2IntRBTreeMap(Collections.reverseOrder()); - GameData.getItemDataMap().forEach((id, data) -> { - if (data == null) return; - if (data.getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) return; - var actions = data.getItemUseActions(); - if (actions == null) return; - for (var action : actions) { - if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) { - temp.putIfAbsent(((ItemUseAddWeaponExp) action).getExp(), (int) id); - return; - } - } - }); - temp.forEach((exp, id) -> weaponRefundMaterials.putIfAbsent((int) id, (int) exp)); - } - - public InventorySystem(GameServer server) { - super(server); - } - - public static synchronized int checkPlayerAvatarConstellationLevel(Player player, int id) { - // Try to accept itemId OR avatarId - int avatarId = 0; - if (GameData.getAvatarDataMap().containsKey(id)) { - avatarId = id; - } else { - avatarId = Optional.ofNullable(GameData.getItemDataMap().get(id)) - .map(itemData -> itemData.getItemUseActions()) - .flatMap(actions -> - actions.stream() - .filter(action -> action.getItemUseOp() == ItemUseOp.ITEM_USE_GAIN_AVATAR) - .map(action -> ((emu.grasscutter.game.props.ItemUseAction.ItemUseGainAvatar) action).getI()) - .findFirst()) - .orElse(0); - } - - if (avatarId == 0) - return -2; // Not an Avatar - - Avatar avatar = player.getAvatars().getAvatarById(avatarId); - if (avatar == null) - return -1; // Doesn't have - - // Constellation - int constLevel = avatar.getCoreProudSkillLevel(); - val avatarData = avatar.getSkillDepot(); - if (avatarData == null) { - Grasscutter.getLogger().error("Attempted to check constellation level for UID" + player.getUid() + "'s avatar " + avatarId + " but avatar has no skillDepot!"); - return 0; - } - int constItemId = avatarData.getTalentCostItemId(); - GameItem constItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId); - constLevel += Optional.ofNullable(constItem).map(GameItem::getCount).orElse(0); - return constLevel; - } - - public void lockEquip(Player player, long targetEquipGuid, boolean isLocked) { - GameItem equip = player.getInventory().getItemByGuid(targetEquipGuid); - - if (equip == null || !equip.getItemData().isEquip()) { - return; - } - - equip.setLocked(isLocked); - equip.save(); - - player.sendPacket(new PacketStoreItemChangeNotify(equip)); - player.sendPacket(new PacketSetEquipLockStateRsp(equip)); - } - - public void upgradeRelic(Player player, long targetGuid, List foodRelicList, List list) { - GameItem relic = player.getInventory().getItemByGuid(targetGuid); - - if (relic == null || relic.getItemType() != ItemType.ITEM_RELIQUARY) { - return; - } - - int moraCost = 0; - int expGain = 0; - - List foodRelics = new ArrayList(); - for (long guid : foodRelicList) { - // Add to delete queue - GameItem food = player.getInventory().getItemByGuid(guid); - if (food == null || !food.isDestroyable()) { - continue; - } - // Calculate mora cost - int exp = food.getItemData().getBaseConvExp(); - moraCost += exp; - expGain += exp; - // Feeding artifact with exp already - if (food.getTotalExp() > 0) { - expGain += (food.getTotalExp() * 4) / 5; - } - foodRelics.add(food); - } - List payList = new ArrayList(); - for (ItemParam itemParam : list) { - int amount = itemParam.getCount(); // Previously this capped to inventory amount, but rejecting the payment makes more sense for an invalid order - int gain = 0; - var data = GameData.getItemDataMap().get(itemParam.getItemId()); - if (data != null) { - var actions = data.getItemUseActions(); - if (actions != null) { - for (var action : actions) { - if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_RELIQUARY_EXP) { - gain += ((ItemUseAddReliquaryExp) action).getExp(); - } - } - } - } - gain *= amount; - expGain += gain; - moraCost += gain; - payList.add(new ItemParamData(itemParam.getItemId(), itemParam.getCount())); - } - - // Make sure exp gain is valid - if (expGain <= 0) { - return; - } - - // Confirm payment of materials and mora (assume food relics are payable afterwards) - payList.add(new ItemParamData(202, moraCost)); - if (!player.getInventory().payItems(payList)) { - return; - } - - // Consume food relics - player.getInventory().removeItems(foodRelics); - - // Implement random rate boost - int rate = 1; - int boost = Utils.randomRange(1, 100); - if (boost == 100) { - rate = 5; - } else if (boost <= 9) { - rate = 2; - } - expGain *= rate; - - // Now we upgrade - int level = relic.getLevel(); - int oldLevel = level; - int exp = relic.getExp(); - int totalExp = relic.getTotalExp(); - int reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); - int upgrades = 0; - List oldAppendPropIdList = new ArrayList<>(relic.getAppendPropIdList()); - - while (expGain > 0 && reqExp > 0 && level < relic.getItemData().getMaxLevel()) { - // Do calculations - int toGain = Math.min(expGain, reqExp - exp); - exp += toGain; - totalExp += toGain; - expGain -= toGain; - // Level up - if (exp >= reqExp) { - // Exp - exp = 0; - level += 1; - // On relic levelup - if (relic.getItemData().getAddPropLevelSet() != null && relic.getItemData().getAddPropLevelSet().contains(level)) { - upgrades += 1; - } - // Set req exp - reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); - } - } - - relic.addAppendProps(upgrades); - - // Save - relic.setLevel(level); - relic.setExp(exp); - relic.setTotalExp(totalExp); - relic.save(); - - // Avatar - if (oldLevel != level) { - Avatar avatar = relic.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(relic.getEquipCharacter()) : null; - if (avatar != null) { - avatar.recalcStats(); - } - } - - // Packet - player.sendPacket(new PacketStoreItemChangeNotify(relic)); - player.sendPacket(new PacketReliquaryUpgradeRsp(relic, rate, oldLevel, oldAppendPropIdList)); - } - - public List calcWeaponUpgradeReturnItems(Player player, long targetGuid, List foodWeaponGuidList, List itemParamList) { - GameItem weapon = player.getInventory().getItemByGuid(targetGuid); - - // Sanity checks - if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { - return null; - } - - WeaponPromoteData promoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); - if (promoteData == null) { - return null; - } - - // Get exp gain - int expGain = foodWeaponGuidList.stream() - .map(player.getInventory()::getItemByGuid) - .filter(Objects::nonNull) - .mapToInt(food -> food.getItemData().getWeaponBaseExp() + ((food.getTotalExp() * 4) / 5)) - .sum(); - // Stream::ofNullable version - expGain += itemParamList.stream() - .mapToInt(param -> { - int exp = Stream.ofNullable(GameData.getItemDataMap().get(param.getItemId())) - .map(ItemData::getItemUseActions) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(action -> action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) - .mapToInt(action -> ((ItemUseAddWeaponExp) action).getExp()) - .sum(); - return exp * param.getCount(); - }) - .sum(); - // Optional::ofNullable version - // expGain += itemParamList.stream() - // .mapToInt(param -> { - // int exp = Optional.ofNullable(GameData.getItemDataMap().get(param.getItemId())) - // .map(ItemData::getItemUseActions) - // .map(actions -> { - // return actions.stream() - // .filter(action -> action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) - // .mapToInt(action -> ((ItemUseAddWeaponExp) action).getExp()) - // .sum(); - // }) - // .orElse(0); - // return exp * param.getCount(); - // }) - // .sum(); - - // Try - int maxLevel = promoteData.getUnlockMaxLevel(); - int level = weapon.getLevel(); - int exp = weapon.getExp(); - int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); - - while (expGain > 0 && reqExp > 0 && level < maxLevel) { - // Do calculations - int toGain = Math.min(expGain, reqExp - exp); - exp += toGain; - expGain -= toGain; - // Level up - if (exp >= reqExp) { - // Exp - exp = 0; - level += 1; - // Set req exp - reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); - } - } - - return getLeftoverOres(expGain); - } - - public void upgradeWeapon(Player player, long targetGuid, List foodWeaponGuidList, List itemParamList) { - GameItem weapon = player.getInventory().getItemByGuid(targetGuid); - - // Sanity checks - if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { - return; - } - - WeaponPromoteData promoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); - if (promoteData == null) { - return; - } - - // Get exp gain - int expGain = 0, expGainFree = 0; - List foodWeapons = new ArrayList(); - for (long guid : foodWeaponGuidList) { - GameItem food = player.getInventory().getItemByGuid(guid); - if (food == null || !food.isDestroyable()) { - continue; - } - expGain += food.getItemData().getWeaponBaseExp(); - if (food.getTotalExp() > 0) { - expGainFree += (food.getTotalExp() * 4) / 5; // No tax :D - } - foodWeapons.add(food); - } - List payList = new ArrayList(); - for (ItemParam param : itemParamList) { - int amount = param.getCount(); // Previously this capped to inventory amount, but rejecting the payment makes more sense for an invalid order - - var data = GameData.getItemDataMap().get(param.getItemId()); - if (data != null) { - var actions = data.getItemUseActions(); - if (actions != null) { - for (var action : actions) { - if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) { - expGain += ((ItemUseAddWeaponExp) action).getExp() * amount; - } - } - } - } - - payList.add(new ItemParamData(param.getItemId(), amount)); - } - - // Make sure exp gain is valid - int moraCost = expGain / 10; - expGain += expGainFree; - if (expGain <= 0) { - return; - } - - // Confirm payment of materials and mora (assume food weapons are payable afterwards) - payList.add(new ItemParamData(202, moraCost)); - if (!player.getInventory().payItems(payList)) { - return; - } - player.getInventory().removeItems(foodWeapons); - - // Level up - int maxLevel = promoteData.getUnlockMaxLevel(); - int level = weapon.getLevel(); - int oldLevel = level; - int exp = weapon.getExp(); - int totalExp = weapon.getTotalExp(); - int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); - - while (expGain > 0 && reqExp > 0 && level < maxLevel) { - // Do calculations - int toGain = Math.min(expGain, reqExp - exp); - exp += toGain; - totalExp += toGain; - expGain -= toGain; - // Level up - if (exp >= reqExp) { - // Exp - exp = 0; - level += 1; - // Set req exp - reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); - } - } - - List leftovers = getLeftoverOres(expGain); - player.getInventory().addItemParams(leftovers); - - weapon.setLevel(level); - weapon.setExp(exp); - weapon.setTotalExp(totalExp); - weapon.save(); - - // Avatar - if (oldLevel != level) { - Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; - if (avatar != null) { - avatar.recalcStats(); - } - } - - // Packets - player.sendPacket(new PacketStoreItemChangeNotify(weapon)); - player.sendPacket(new PacketWeaponUpgradeRsp(weapon, oldLevel, leftovers)); - } - - private List getLeftoverOres(int leftover) { - List leftoverOreList = new ArrayList<>(3); - - for (var e : weaponRefundMaterials.int2IntEntrySet()) { - int exp = e.getIntValue(); - int ores = leftover / exp; - leftover = leftover % exp; - - if (ores > 0) - leftoverOreList.add(ItemParam.newBuilder().setItemId(e.getIntKey()).setCount(ores).build()); - } - - return leftoverOreList; - } - - public void refineWeapon(Player player, long targetGuid, long feedGuid) { - GameItem weapon = player.getInventory().getItemByGuid(targetGuid); - GameItem feed = player.getInventory().getItemByGuid(feedGuid); - - // Sanity checks - if (weapon == null || feed == null || !feed.isDestroyable()) { - return; - } - - if (weapon.getItemData().getAwakenMaterial() == 0) { - if (weapon.getItemType() != ItemType.ITEM_WEAPON || weapon.getItemId() != feed.getItemId()) { - return; - } - } else { - if (weapon.getItemType() != ItemType.ITEM_WEAPON || weapon.getItemData().getAwakenMaterial() != feed.getItemId()) { - return; - } - } - - if (weapon.getRefinement() >= 4 || weapon.getAffixes() == null || weapon.getAffixes().size() == 0) { - return; - } - - // Calculate - int oldRefineLevel = weapon.getRefinement(); - int targetRefineLevel = Math.min(oldRefineLevel + feed.getRefinement() + 1, 4); - int moraCost = 0; - - try { - moraCost = weapon.getItemData().getAwakenCosts()[weapon.getRefinement()]; - } catch (Exception e) { - return; - } - - // Mora check - if (player.getMora() >= moraCost) { - player.setMora(player.getMora() - moraCost); - } else { - return; - } - - // Consume weapon - player.getInventory().removeItem(feed, 1); - - // Get - weapon.setRefinement(targetRefineLevel); - weapon.save(); - - // Avatar - Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; - if (avatar != null) { - avatar.recalcStats(); - } - - // Packets - player.sendPacket(new PacketStoreItemChangeNotify(weapon)); - player.sendPacket(new PacketWeaponAwakenRsp(avatar, weapon, feed, oldRefineLevel)); - } - - public void promoteWeapon(Player player, long targetGuid) { - GameItem weapon = player.getInventory().getItemByGuid(targetGuid); - - if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { - return; - } - - int nextPromoteLevel = weapon.getPromoteLevel() + 1; - WeaponPromoteData currentPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); - WeaponPromoteData nextPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), nextPromoteLevel); - if (currentPromoteData == null || nextPromoteData == null) { - return; - } - - // Level check - if (weapon.getLevel() != currentPromoteData.getUnlockMaxLevel()) { - return; - } - - // Pay materials and mora if possible - ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? - if (nextPromoteData.getCoinCost() > 0) { - costs = Arrays.copyOf(costs, costs.length + 1); - costs[costs.length - 1] = new ItemParamData(202, nextPromoteData.getCoinCost()); - } - if (!player.getInventory().payItems(costs)) { - return; - } - - int oldPromoteLevel = weapon.getPromoteLevel(); - weapon.setPromoteLevel(nextPromoteLevel); - weapon.save(); - - // Avatar - Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; - if (avatar != null) { - avatar.recalcStats(); - } - - // Packets - player.sendPacket(new PacketStoreItemChangeNotify(weapon)); - player.sendPacket(new PacketWeaponPromoteRsp(weapon, oldPromoteLevel)); - } - - public void promoteAvatar(Player player, long guid) { - Avatar avatar = player.getAvatars().getAvatarByGuid(guid); - - // Sanity checks - if (avatar == null) { - return; - } - - int nextPromoteLevel = avatar.getPromoteLevel() + 1; - AvatarPromoteData currentPromoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); - AvatarPromoteData nextPromoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), nextPromoteLevel); - if (currentPromoteData == null || nextPromoteData == null) { - return; - } - - // Level check - if (avatar.getLevel() != currentPromoteData.getUnlockMaxLevel()) { - return; - } - - // Pay materials and mora if possible - ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? - if (nextPromoteData.getCoinCost() > 0) { - costs = Arrays.copyOf(costs, costs.length + 1); - costs[costs.length - 1] = new ItemParamData(202, nextPromoteData.getCoinCost()); - } - if (!player.getInventory().payItems(costs)) { - return; - } - - // Update promote level - avatar.setPromoteLevel(nextPromoteLevel); - - // Update proud skills - Optional.ofNullable(GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId())) - .map(AvatarSkillDepotData::getInherentProudSkillOpens) - .ifPresent(d -> d.stream() - .filter(openData -> openData.getProudSkillGroupId() > 0) - .filter(openData -> openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) - .mapToInt(openData -> (openData.getProudSkillGroupId() * 100) + 1) - .filter(GameData.getProudSkillDataMap()::containsKey) - .forEach(proudSkillId -> { - avatar.getProudSkillList().add(proudSkillId); - player.sendPacket(new PacketProudSkillChangeNotify(avatar)); - }) - ); - - // Packets - player.sendPacket(new PacketAvatarPropNotify(avatar)); - player.sendPacket(new PacketAvatarPromoteRsp(avatar)); - - // TODO Send entity prop update packet to world - avatar.recalcStats(true); - avatar.save(); - } - - public void upgradeAvatar(Player player, long guid, int itemId, int count) { - Avatar avatar = player.getAvatars().getAvatarByGuid(guid); - - // Sanity checks - if (avatar == null) { - return; - } - - AvatarPromoteData promoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); - if (promoteData == null) { - return; - } - - // Calc exp - int expGain = 0; - - var data = GameData.getItemDataMap().get(itemId); - if (data != null) { - var actions = data.getItemUseActions(); - if (actions != null) { - for (var action : actions) { - if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_EXP) { - expGain += ((ItemUseAddExp) action).getExp() * count; - } - } - } - } - - // Sanity check - if (expGain <= 0) { - return; - } - - // Payment check - int moraCost = expGain / 5; - ItemParamData[] costItems = new ItemParamData[]{new ItemParamData(itemId, count), new ItemParamData(202, moraCost)}; - if (!player.getInventory().payItems(costItems)) { - return; - } - - // Level up - upgradeAvatar(player, avatar, promoteData, expGain); - } - - public void upgradeAvatar(Player player, Avatar avatar, int expGain) { - AvatarPromoteData promoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); - if (promoteData == null) { - return; - } - - upgradeAvatar(player, avatar, promoteData, expGain); - } - - public void upgradeAvatar(Player player, Avatar avatar, AvatarPromoteData promoteData, int expGain) { - int maxLevel = promoteData.getUnlockMaxLevel(); - int level = avatar.getLevel(); - int oldLevel = level; - int exp = avatar.getExp(); - int reqExp = GameData.getAvatarLevelExpRequired(level); - - while (expGain > 0 && reqExp > 0 && level < maxLevel) { - // Do calculations - int toGain = Math.min(expGain, reqExp - exp); - exp += toGain; - expGain -= toGain; - // Level up - if (exp >= reqExp) { - // Exp - exp = 0; - level += 1; - // Set req exp - reqExp = GameData.getAvatarLevelExpRequired(level); - } - } - - // Old map for packet - Map oldPropMap = avatar.getFightProperties(); - if (oldLevel != level) { - // Deep copy if level has changed - oldPropMap = new Int2FloatArrayMap(avatar.getFightProperties()); - } - - // Done - avatar.setLevel(level); - avatar.setExp(exp); - avatar.recalcStats(); - avatar.save(); - - // TODO Send entity prop update packet to world - - // Packets - player.sendPacket(new PacketAvatarPropNotify(avatar)); - player.sendPacket(new PacketAvatarUpgradeRsp(avatar, oldLevel, oldPropMap)); - } - - public void upgradeAvatarFetterLevel(Player player, Avatar avatar, int expGain) { - // May work. Not test. - int maxLevel = 10; // Keep it until I think of a more "elegant" way - int level = avatar.getFetterLevel(); - int exp = avatar.getFetterExp(); - int reqExp = GameData.getAvatarFetterLevelExpRequired(level); - - while (expGain > 0 && reqExp > 0 && level < maxLevel) { - int toGain = Math.min(expGain, reqExp - exp); - exp += toGain; - expGain -= toGain; - if (exp >= reqExp) { - exp = 0; - level += 1; - reqExp = GameData.getAvatarFetterLevelExpRequired(level); - } - } - - avatar.setFetterLevel(level); - avatar.setFetterExp(exp); - avatar.save(); - - player.sendPacket(new PacketAvatarPropNotify(avatar)); - player.sendPacket(new PacketAvatarFetterDataNotify(avatar)); - } - - @Deprecated(forRemoval = true) - public void upgradeAvatarSkill(Player player, long guid, int skillId) { - // Sanity checks - Avatar avatar = player.getAvatars().getAvatarByGuid(guid); - if (avatar == null) return; - - avatar.upgradeSkill(skillId); - } - - @Deprecated(forRemoval = true) - public void unlockAvatarConstellation(Player player, long guid) { - // Sanity check - Avatar avatar = player.getAvatars().getAvatarByGuid(guid); - if (avatar == null) return; - - avatar.unlockConstellation(); - } - - public void destroyMaterial(Player player, List list) { - // Return materials - val returnMaterialMap = new Int2IntOpenHashMap(); - val inventory = player.getInventory(); - - for (MaterialInfo info : list) { - // Sanity check - if (info.getCount() <= 0) { - continue; - } - - GameItem item = inventory.getItemByGuid(info.getGuid()); - if (item == null || !item.isDestroyable()) { - continue; - } - - // Remove - int removeAmount = Math.min(info.getCount(), item.getCount()); - inventory.removeItem(item, removeAmount); - - // Delete material return items - val data = item.getItemData(); - if (data.getDestroyReturnMaterial().length > 0) { - for (int i = 0; i < data.getDestroyReturnMaterial().length; i++) { - returnMaterialMap.addTo(data.getDestroyReturnMaterial()[i], data.getDestroyReturnMaterialCount()[i]); - } - } - } - - // Give back items - if (returnMaterialMap.size() > 0) { - returnMaterialMap.forEach((id, count) -> inventory.addItem(new GameItem(id, count))); - } - - // Packets - player.sendPacket(new PacketDestroyMaterialRsp(returnMaterialMap)); - } - - // Uses an item from the player's inventory. - public synchronized GameItem useItem(Player player, long targetGuid, long itemGuid, int count, int optionId, boolean isEnterMpDungeonTeam) { - Grasscutter.getLogger().debug("Attempting to use item from inventory"); - Avatar target = player.getAvatars().getAvatarByGuid(targetGuid); - GameItem item = player.getInventory().getItemByGuid(itemGuid); - if (item == null) return null; - if (item.getCount() < count) return null; - ItemData itemData = item.getItemData(); - if (itemData == null) return null; - - var params = new UseItemParams(player, itemData.getUseTarget(), target, count, optionId, isEnterMpDungeonTeam); - params.usedItemId = item.getItemId(); - if (useItemDirect(itemData, params)) { - player.getInventory().removeItem(item, count); - var actions = itemData.getItemUseActions(); - if (actions != null) - actions.forEach(use -> use.postUseItem(params)); - Grasscutter.getLogger().debug("Item use succeeded!"); - return item; - } else { - Grasscutter.getLogger().debug("Item use failed!"); - return null; - } - } - - // Uses an item without checking the player's inventory. - public synchronized boolean useItemDirect(ItemData itemData, UseItemParams params) { - if (itemData == null) return false; - - // Ensure targeting conditions are satisfied - val target = Optional.ofNullable(params.targetAvatar); - switch (params.itemUseTarget) { - case ITEM_USE_TARGET_NONE -> { - } - case ITEM_USE_TARGET_SPECIFY_AVATAR -> { - if (target.isEmpty()) return false; - } - case ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR -> { - if (target.map(a -> !a.getAsEntity().isAlive()).orElse(true)) return false; - } - case ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR -> { - if (target.map(a -> a.getAsEntity().isAlive()).orElse(true)) return false; - } - case ITEM_USE_TARGET_CUR_AVATAR -> { - } - case ITEM_USE_TARGET_CUR_TEAM -> { - } - } - - int[] satiationParams = itemData.getSatiationParams(); - if (satiationParams != null && satiationParams.length > 0 && target.isPresent()) { - // Invoke and call player use food event. - var event = new PlayerUseFoodEvent(params.player, itemData, params.targetAvatar.getAsEntity()); - event.call(); - if (event.isCanceled()) return false; - - float satiationIncrease = satiationParams[0] + ((float) satiationParams[1]) / params.targetAvatar.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - if (!params.player.getSatiationManager().addSatiation(params.targetAvatar, satiationIncrease, itemData.getId())) { // Make sure avatar can eat - return false; - } - } - - // Use - var actions = itemData.getItemUseActions(); - Grasscutter.getLogger().debug("Using - actions - {}", actions); - if (actions == null) return true; // Maybe returning false would be more appropriate? - return actions.stream() - .map(use -> use.useItem(params)) - .reduce(false, (a, b) -> a || b); // Don't short-circuit!!! - } -} +package emu.grasscutter.game.systems; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.AvatarPromoteData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.WeaponPromoteData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.inventory.MaterialType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.ItemUseAction.ItemUseAddExp; +import emu.grasscutter.game.props.ItemUseAction.ItemUseAddReliquaryExp; +import emu.grasscutter.game.props.ItemUseAction.ItemUseAddWeaponExp; +import emu.grasscutter.game.props.ItemUseAction.UseItemParams; +import emu.grasscutter.game.props.ItemUseOp; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; +import emu.grasscutter.server.event.player.PlayerUseFoodEvent; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.*; +import java.util.*; +import java.util.stream.Stream; +import lombok.val; + +public class InventorySystem extends BaseGameSystem { + private static final Int2IntMap weaponRefundMaterials = new Int2IntArrayMap(); + + { + // Use a sorted map, use exp as key to sort by exp + // We want to have weaponRefundMaterials as (id, exp) in descending exp order + var temp = new Int2IntRBTreeMap(Collections.reverseOrder()); + GameData.getItemDataMap() + .forEach( + (id, data) -> { + if (data == null) return; + if (data.getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) return; + var actions = data.getItemUseActions(); + if (actions == null) return; + for (var action : actions) { + if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) { + temp.putIfAbsent(((ItemUseAddWeaponExp) action).getExp(), (int) id); + return; + } + } + }); + temp.forEach((exp, id) -> weaponRefundMaterials.putIfAbsent((int) id, (int) exp)); + } + + public InventorySystem(GameServer server) { + super(server); + } + + public static synchronized int checkPlayerAvatarConstellationLevel(Player player, int id) { + // Try to accept itemId OR avatarId + int avatarId = 0; + if (GameData.getAvatarDataMap().containsKey(id)) { + avatarId = id; + } else { + avatarId = + Optional.ofNullable(GameData.getItemDataMap().get(id)) + .map(itemData -> itemData.getItemUseActions()) + .flatMap( + actions -> + actions.stream() + .filter(action -> action.getItemUseOp() == ItemUseOp.ITEM_USE_GAIN_AVATAR) + .map( + action -> + ((emu.grasscutter.game.props.ItemUseAction.ItemUseGainAvatar) + action) + .getI()) + .findFirst()) + .orElse(0); + } + + if (avatarId == 0) return -2; // Not an Avatar + + Avatar avatar = player.getAvatars().getAvatarById(avatarId); + if (avatar == null) return -1; // Doesn't have + + // Constellation + int constLevel = avatar.getCoreProudSkillLevel(); + val avatarData = avatar.getSkillDepot(); + if (avatarData == null) { + Grasscutter.getLogger() + .error( + "Attempted to check constellation level for UID" + + player.getUid() + + "'s avatar " + + avatarId + + " but avatar has no skillDepot!"); + return 0; + } + int constItemId = avatarData.getTalentCostItemId(); + GameItem constItem = + player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId); + constLevel += Optional.ofNullable(constItem).map(GameItem::getCount).orElse(0); + return constLevel; + } + + public void lockEquip(Player player, long targetEquipGuid, boolean isLocked) { + GameItem equip = player.getInventory().getItemByGuid(targetEquipGuid); + + if (equip == null || !equip.getItemData().isEquip()) { + return; + } + + equip.setLocked(isLocked); + equip.save(); + + player.sendPacket(new PacketStoreItemChangeNotify(equip)); + player.sendPacket(new PacketSetEquipLockStateRsp(equip)); + } + + public void upgradeRelic( + Player player, long targetGuid, List foodRelicList, List list) { + GameItem relic = player.getInventory().getItemByGuid(targetGuid); + + if (relic == null || relic.getItemType() != ItemType.ITEM_RELIQUARY) { + return; + } + + int moraCost = 0; + int expGain = 0; + + List foodRelics = new ArrayList(); + for (long guid : foodRelicList) { + // Add to delete queue + GameItem food = player.getInventory().getItemByGuid(guid); + if (food == null || !food.isDestroyable()) { + continue; + } + // Calculate mora cost + int exp = food.getItemData().getBaseConvExp(); + moraCost += exp; + expGain += exp; + // Feeding artifact with exp already + if (food.getTotalExp() > 0) { + expGain += (food.getTotalExp() * 4) / 5; + } + foodRelics.add(food); + } + List payList = new ArrayList(); + for (ItemParam itemParam : list) { + int amount = + itemParam + .getCount(); // Previously this capped to inventory amount, but rejecting the payment + // makes more sense for an invalid order + int gain = 0; + var data = GameData.getItemDataMap().get(itemParam.getItemId()); + if (data != null) { + var actions = data.getItemUseActions(); + if (actions != null) { + for (var action : actions) { + if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_RELIQUARY_EXP) { + gain += ((ItemUseAddReliquaryExp) action).getExp(); + } + } + } + } + gain *= amount; + expGain += gain; + moraCost += gain; + payList.add(new ItemParamData(itemParam.getItemId(), itemParam.getCount())); + } + + // Make sure exp gain is valid + if (expGain <= 0) { + return; + } + + // Confirm payment of materials and mora (assume food relics are payable afterwards) + payList.add(new ItemParamData(202, moraCost)); + if (!player.getInventory().payItems(payList)) { + return; + } + + // Consume food relics + player.getInventory().removeItems(foodRelics); + + // Implement random rate boost + int rate = 1; + int boost = Utils.randomRange(1, 100); + if (boost == 100) { + rate = 5; + } else if (boost <= 9) { + rate = 2; + } + expGain *= rate; + + // Now we upgrade + int level = relic.getLevel(); + int oldLevel = level; + int exp = relic.getExp(); + int totalExp = relic.getTotalExp(); + int reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); + int upgrades = 0; + List oldAppendPropIdList = new ArrayList<>(relic.getAppendPropIdList()); + + while (expGain > 0 && reqExp > 0 && level < relic.getItemData().getMaxLevel()) { + // Do calculations + int toGain = Math.min(expGain, reqExp - exp); + exp += toGain; + totalExp += toGain; + expGain -= toGain; + // Level up + if (exp >= reqExp) { + // Exp + exp = 0; + level += 1; + // On relic levelup + if (relic.getItemData().getAddPropLevelSet() != null + && relic.getItemData().getAddPropLevelSet().contains(level)) { + upgrades += 1; + } + // Set req exp + reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); + } + } + + relic.addAppendProps(upgrades); + + // Save + relic.setLevel(level); + relic.setExp(exp); + relic.setTotalExp(totalExp); + relic.save(); + + // Avatar + if (oldLevel != level) { + Avatar avatar = + relic.getEquipCharacter() > 0 + ? player.getAvatars().getAvatarById(relic.getEquipCharacter()) + : null; + if (avatar != null) { + avatar.recalcStats(); + } + } + + // Packet + player.sendPacket(new PacketStoreItemChangeNotify(relic)); + player.sendPacket(new PacketReliquaryUpgradeRsp(relic, rate, oldLevel, oldAppendPropIdList)); + } + + public List calcWeaponUpgradeReturnItems( + Player player, + long targetGuid, + List foodWeaponGuidList, + List itemParamList) { + GameItem weapon = player.getInventory().getItemByGuid(targetGuid); + + // Sanity checks + if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { + return null; + } + + WeaponPromoteData promoteData = + GameData.getWeaponPromoteData( + weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); + if (promoteData == null) { + return null; + } + + // Get exp gain + int expGain = + foodWeaponGuidList.stream() + .map(player.getInventory()::getItemByGuid) + .filter(Objects::nonNull) + .mapToInt( + food -> food.getItemData().getWeaponBaseExp() + ((food.getTotalExp() * 4) / 5)) + .sum(); + // Stream::ofNullable version + expGain += + itemParamList.stream() + .mapToInt( + param -> { + int exp = + Stream.ofNullable(GameData.getItemDataMap().get(param.getItemId())) + .map(ItemData::getItemUseActions) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter( + action -> action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) + .mapToInt(action -> ((ItemUseAddWeaponExp) action).getExp()) + .sum(); + return exp * param.getCount(); + }) + .sum(); + // Optional::ofNullable version + // expGain += itemParamList.stream() + // .mapToInt(param -> { + // int exp = Optional.ofNullable(GameData.getItemDataMap().get(param.getItemId())) + // .map(ItemData::getItemUseActions) + // .map(actions -> { + // return actions.stream() + // .filter(action -> action.getItemUseOp() == + // ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) + // .mapToInt(action -> ((ItemUseAddWeaponExp) action).getExp()) + // .sum(); + // }) + // .orElse(0); + // return exp * param.getCount(); + // }) + // .sum(); + + // Try + int maxLevel = promoteData.getUnlockMaxLevel(); + int level = weapon.getLevel(); + int exp = weapon.getExp(); + int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); + + while (expGain > 0 && reqExp > 0 && level < maxLevel) { + // Do calculations + int toGain = Math.min(expGain, reqExp - exp); + exp += toGain; + expGain -= toGain; + // Level up + if (exp >= reqExp) { + // Exp + exp = 0; + level += 1; + // Set req exp + reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); + } + } + + return getLeftoverOres(expGain); + } + + public void upgradeWeapon( + Player player, + long targetGuid, + List foodWeaponGuidList, + List itemParamList) { + GameItem weapon = player.getInventory().getItemByGuid(targetGuid); + + // Sanity checks + if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { + return; + } + + WeaponPromoteData promoteData = + GameData.getWeaponPromoteData( + weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); + if (promoteData == null) { + return; + } + + // Get exp gain + int expGain = 0, expGainFree = 0; + List foodWeapons = new ArrayList(); + for (long guid : foodWeaponGuidList) { + GameItem food = player.getInventory().getItemByGuid(guid); + if (food == null || !food.isDestroyable()) { + continue; + } + expGain += food.getItemData().getWeaponBaseExp(); + if (food.getTotalExp() > 0) { + expGainFree += (food.getTotalExp() * 4) / 5; // No tax :D + } + foodWeapons.add(food); + } + List payList = new ArrayList(); + for (ItemParam param : itemParamList) { + int amount = + param.getCount(); // Previously this capped to inventory amount, but rejecting the payment + // makes more sense for an invalid order + + var data = GameData.getItemDataMap().get(param.getItemId()); + if (data != null) { + var actions = data.getItemUseActions(); + if (actions != null) { + for (var action : actions) { + if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_WEAPON_EXP) { + expGain += ((ItemUseAddWeaponExp) action).getExp() * amount; + } + } + } + } + + payList.add(new ItemParamData(param.getItemId(), amount)); + } + + // Make sure exp gain is valid + int moraCost = expGain / 10; + expGain += expGainFree; + if (expGain <= 0) { + return; + } + + // Confirm payment of materials and mora (assume food weapons are payable afterwards) + payList.add(new ItemParamData(202, moraCost)); + if (!player.getInventory().payItems(payList)) { + return; + } + player.getInventory().removeItems(foodWeapons); + + // Level up + int maxLevel = promoteData.getUnlockMaxLevel(); + int level = weapon.getLevel(); + int oldLevel = level; + int exp = weapon.getExp(); + int totalExp = weapon.getTotalExp(); + int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); + + while (expGain > 0 && reqExp > 0 && level < maxLevel) { + // Do calculations + int toGain = Math.min(expGain, reqExp - exp); + exp += toGain; + totalExp += toGain; + expGain -= toGain; + // Level up + if (exp >= reqExp) { + // Exp + exp = 0; + level += 1; + // Set req exp + reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); + } + } + + List leftovers = getLeftoverOres(expGain); + player.getInventory().addItemParams(leftovers); + + weapon.setLevel(level); + weapon.setExp(exp); + weapon.setTotalExp(totalExp); + weapon.save(); + + // Avatar + if (oldLevel != level) { + Avatar avatar = + weapon.getEquipCharacter() > 0 + ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) + : null; + if (avatar != null) { + avatar.recalcStats(); + } + } + + // Packets + player.sendPacket(new PacketStoreItemChangeNotify(weapon)); + player.sendPacket(new PacketWeaponUpgradeRsp(weapon, oldLevel, leftovers)); + } + + private List getLeftoverOres(int leftover) { + List leftoverOreList = new ArrayList<>(3); + + for (var e : weaponRefundMaterials.int2IntEntrySet()) { + int exp = e.getIntValue(); + int ores = leftover / exp; + leftover = leftover % exp; + + if (ores > 0) + leftoverOreList.add(ItemParam.newBuilder().setItemId(e.getIntKey()).setCount(ores).build()); + } + + return leftoverOreList; + } + + public void refineWeapon(Player player, long targetGuid, long feedGuid) { + GameItem weapon = player.getInventory().getItemByGuid(targetGuid); + GameItem feed = player.getInventory().getItemByGuid(feedGuid); + + // Sanity checks + if (weapon == null || feed == null || !feed.isDestroyable()) { + return; + } + + if (weapon.getItemData().getAwakenMaterial() == 0) { + if (weapon.getItemType() != ItemType.ITEM_WEAPON || weapon.getItemId() != feed.getItemId()) { + return; + } + } else { + if (weapon.getItemType() != ItemType.ITEM_WEAPON + || weapon.getItemData().getAwakenMaterial() != feed.getItemId()) { + return; + } + } + + if (weapon.getRefinement() >= 4 + || weapon.getAffixes() == null + || weapon.getAffixes().size() == 0) { + return; + } + + // Calculate + int oldRefineLevel = weapon.getRefinement(); + int targetRefineLevel = Math.min(oldRefineLevel + feed.getRefinement() + 1, 4); + int moraCost = 0; + + try { + moraCost = weapon.getItemData().getAwakenCosts()[weapon.getRefinement()]; + } catch (Exception e) { + return; + } + + // Mora check + if (player.getMora() >= moraCost) { + player.setMora(player.getMora() - moraCost); + } else { + return; + } + + // Consume weapon + player.getInventory().removeItem(feed, 1); + + // Get + weapon.setRefinement(targetRefineLevel); + weapon.save(); + + // Avatar + Avatar avatar = + weapon.getEquipCharacter() > 0 + ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) + : null; + if (avatar != null) { + avatar.recalcStats(); + } + + // Packets + player.sendPacket(new PacketStoreItemChangeNotify(weapon)); + player.sendPacket(new PacketWeaponAwakenRsp(avatar, weapon, feed, oldRefineLevel)); + } + + public void promoteWeapon(Player player, long targetGuid) { + GameItem weapon = player.getInventory().getItemByGuid(targetGuid); + + if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { + return; + } + + int nextPromoteLevel = weapon.getPromoteLevel() + 1; + WeaponPromoteData currentPromoteData = + GameData.getWeaponPromoteData( + weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); + WeaponPromoteData nextPromoteData = + GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), nextPromoteLevel); + if (currentPromoteData == null || nextPromoteData == null) { + return; + } + + // Level check + if (weapon.getLevel() != currentPromoteData.getUnlockMaxLevel()) { + return; + } + + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length - 1] = new ItemParamData(202, nextPromoteData.getCoinCost()); + } + if (!player.getInventory().payItems(costs)) { + return; + } + + int oldPromoteLevel = weapon.getPromoteLevel(); + weapon.setPromoteLevel(nextPromoteLevel); + weapon.save(); + + // Avatar + Avatar avatar = + weapon.getEquipCharacter() > 0 + ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) + : null; + if (avatar != null) { + avatar.recalcStats(); + } + + // Packets + player.sendPacket(new PacketStoreItemChangeNotify(weapon)); + player.sendPacket(new PacketWeaponPromoteRsp(weapon, oldPromoteLevel)); + } + + public void promoteAvatar(Player player, long guid) { + Avatar avatar = player.getAvatars().getAvatarByGuid(guid); + + // Sanity checks + if (avatar == null) { + return; + } + + int nextPromoteLevel = avatar.getPromoteLevel() + 1; + AvatarPromoteData currentPromoteData = + GameData.getAvatarPromoteData( + avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); + AvatarPromoteData nextPromoteData = + GameData.getAvatarPromoteData( + avatar.getAvatarData().getAvatarPromoteId(), nextPromoteLevel); + if (currentPromoteData == null || nextPromoteData == null) { + return; + } + + // Level check + if (avatar.getLevel() != currentPromoteData.getUnlockMaxLevel()) { + return; + } + + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length - 1] = new ItemParamData(202, nextPromoteData.getCoinCost()); + } + if (!player.getInventory().payItems(costs)) { + return; + } + + // Update promote level + avatar.setPromoteLevel(nextPromoteLevel); + + // Update proud skills + Optional.ofNullable(GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId())) + .map(AvatarSkillDepotData::getInherentProudSkillOpens) + .ifPresent( + d -> + d.stream() + .filter(openData -> openData.getProudSkillGroupId() > 0) + .filter( + openData -> + openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) + .mapToInt(openData -> (openData.getProudSkillGroupId() * 100) + 1) + .filter(GameData.getProudSkillDataMap()::containsKey) + .forEach( + proudSkillId -> { + avatar.getProudSkillList().add(proudSkillId); + player.sendPacket(new PacketProudSkillChangeNotify(avatar)); + })); + + // Packets + player.sendPacket(new PacketAvatarPropNotify(avatar)); + player.sendPacket(new PacketAvatarPromoteRsp(avatar)); + + // TODO Send entity prop update packet to world + avatar.recalcStats(true); + avatar.save(); + } + + public void upgradeAvatar(Player player, long guid, int itemId, int count) { + Avatar avatar = player.getAvatars().getAvatarByGuid(guid); + + // Sanity checks + if (avatar == null) { + return; + } + + AvatarPromoteData promoteData = + GameData.getAvatarPromoteData( + avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); + if (promoteData == null) { + return; + } + + // Calc exp + int expGain = 0; + + var data = GameData.getItemDataMap().get(itemId); + if (data != null) { + var actions = data.getItemUseActions(); + if (actions != null) { + for (var action : actions) { + if (action.getItemUseOp() == ItemUseOp.ITEM_USE_ADD_EXP) { + expGain += ((ItemUseAddExp) action).getExp() * count; + } + } + } + } + + // Sanity check + if (expGain <= 0) { + return; + } + + // Payment check + int moraCost = expGain / 5; + ItemParamData[] costItems = + new ItemParamData[] {new ItemParamData(itemId, count), new ItemParamData(202, moraCost)}; + if (!player.getInventory().payItems(costItems)) { + return; + } + + // Level up + upgradeAvatar(player, avatar, promoteData, expGain); + } + + public void upgradeAvatar(Player player, Avatar avatar, int expGain) { + AvatarPromoteData promoteData = + GameData.getAvatarPromoteData( + avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); + if (promoteData == null) { + return; + } + + upgradeAvatar(player, avatar, promoteData, expGain); + } + + public void upgradeAvatar( + Player player, Avatar avatar, AvatarPromoteData promoteData, int expGain) { + int maxLevel = promoteData.getUnlockMaxLevel(); + int level = avatar.getLevel(); + int oldLevel = level; + int exp = avatar.getExp(); + int reqExp = GameData.getAvatarLevelExpRequired(level); + + while (expGain > 0 && reqExp > 0 && level < maxLevel) { + // Do calculations + int toGain = Math.min(expGain, reqExp - exp); + exp += toGain; + expGain -= toGain; + // Level up + if (exp >= reqExp) { + // Exp + exp = 0; + level += 1; + // Set req exp + reqExp = GameData.getAvatarLevelExpRequired(level); + } + } + + // Old map for packet + Map oldPropMap = avatar.getFightProperties(); + if (oldLevel != level) { + // Deep copy if level has changed + oldPropMap = new Int2FloatArrayMap(avatar.getFightProperties()); + } + + // Done + avatar.setLevel(level); + avatar.setExp(exp); + avatar.recalcStats(); + avatar.save(); + + // TODO Send entity prop update packet to world + + // Packets + player.sendPacket(new PacketAvatarPropNotify(avatar)); + player.sendPacket(new PacketAvatarUpgradeRsp(avatar, oldLevel, oldPropMap)); + } + + public void upgradeAvatarFetterLevel(Player player, Avatar avatar, int expGain) { + // May work. Not test. + int maxLevel = 10; // Keep it until I think of a more "elegant" way + int level = avatar.getFetterLevel(); + int exp = avatar.getFetterExp(); + int reqExp = GameData.getAvatarFetterLevelExpRequired(level); + + while (expGain > 0 && reqExp > 0 && level < maxLevel) { + int toGain = Math.min(expGain, reqExp - exp); + exp += toGain; + expGain -= toGain; + if (exp >= reqExp) { + exp = 0; + level += 1; + reqExp = GameData.getAvatarFetterLevelExpRequired(level); + } + } + + avatar.setFetterLevel(level); + avatar.setFetterExp(exp); + avatar.save(); + + player.sendPacket(new PacketAvatarPropNotify(avatar)); + player.sendPacket(new PacketAvatarFetterDataNotify(avatar)); + } + + @Deprecated(forRemoval = true) + public void upgradeAvatarSkill(Player player, long guid, int skillId) { + // Sanity checks + Avatar avatar = player.getAvatars().getAvatarByGuid(guid); + if (avatar == null) return; + + avatar.upgradeSkill(skillId); + } + + @Deprecated(forRemoval = true) + public void unlockAvatarConstellation(Player player, long guid) { + // Sanity check + Avatar avatar = player.getAvatars().getAvatarByGuid(guid); + if (avatar == null) return; + + avatar.unlockConstellation(); + } + + public void destroyMaterial(Player player, List list) { + // Return materials + val returnMaterialMap = new Int2IntOpenHashMap(); + val inventory = player.getInventory(); + + for (MaterialInfo info : list) { + // Sanity check + if (info.getCount() <= 0) { + continue; + } + + GameItem item = inventory.getItemByGuid(info.getGuid()); + if (item == null || !item.isDestroyable()) { + continue; + } + + // Remove + int removeAmount = Math.min(info.getCount(), item.getCount()); + inventory.removeItem(item, removeAmount); + + // Delete material return items + val data = item.getItemData(); + if (data.getDestroyReturnMaterial().length > 0) { + for (int i = 0; i < data.getDestroyReturnMaterial().length; i++) { + returnMaterialMap.addTo( + data.getDestroyReturnMaterial()[i], data.getDestroyReturnMaterialCount()[i]); + } + } + } + + // Give back items + if (returnMaterialMap.size() > 0) { + returnMaterialMap.forEach((id, count) -> inventory.addItem(new GameItem(id, count))); + } + + // Packets + player.sendPacket(new PacketDestroyMaterialRsp(returnMaterialMap)); + } + + // Uses an item from the player's inventory. + public synchronized GameItem useItem( + Player player, + long targetGuid, + long itemGuid, + int count, + int optionId, + boolean isEnterMpDungeonTeam) { + Grasscutter.getLogger().debug("Attempting to use item from inventory"); + Avatar target = player.getAvatars().getAvatarByGuid(targetGuid); + GameItem item = player.getInventory().getItemByGuid(itemGuid); + if (item == null) return null; + if (item.getCount() < count) return null; + ItemData itemData = item.getItemData(); + if (itemData == null) return null; + + var params = + new UseItemParams( + player, itemData.getUseTarget(), target, count, optionId, isEnterMpDungeonTeam); + params.usedItemId = item.getItemId(); + if (useItemDirect(itemData, params)) { + player.getInventory().removeItem(item, count); + var actions = itemData.getItemUseActions(); + if (actions != null) actions.forEach(use -> use.postUseItem(params)); + Grasscutter.getLogger().debug("Item use succeeded!"); + return item; + } else { + Grasscutter.getLogger().debug("Item use failed!"); + return null; + } + } + + // Uses an item without checking the player's inventory. + public synchronized boolean useItemDirect(ItemData itemData, UseItemParams params) { + if (itemData == null) return false; + + // Ensure targeting conditions are satisfied + val target = Optional.ofNullable(params.targetAvatar); + switch (params.itemUseTarget) { + case ITEM_USE_TARGET_NONE -> {} + case ITEM_USE_TARGET_SPECIFY_AVATAR -> { + if (target.isEmpty()) return false; + } + case ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR -> { + if (target.map(a -> !a.getAsEntity().isAlive()).orElse(true)) return false; + } + case ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR -> { + if (target.map(a -> a.getAsEntity().isAlive()).orElse(true)) return false; + } + case ITEM_USE_TARGET_CUR_AVATAR -> {} + case ITEM_USE_TARGET_CUR_TEAM -> {} + } + + int[] satiationParams = itemData.getSatiationParams(); + if (satiationParams != null && satiationParams.length > 0 && target.isPresent()) { + // Invoke and call player use food event. + var event = + new PlayerUseFoodEvent(params.player, itemData, params.targetAvatar.getAsEntity()); + event.call(); + if (event.isCanceled()) return false; + + float satiationIncrease = + satiationParams[0] + + ((float) satiationParams[1]) + / params.targetAvatar.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + if (!params + .player + .getSatiationManager() + .addSatiation( + params.targetAvatar, + satiationIncrease, + itemData.getId())) { // Make sure avatar can eat + return false; + } + } + + // Use + var actions = itemData.getItemUseActions(); + Grasscutter.getLogger().debug("Using - actions - {}", actions); + if (actions == null) return true; // Maybe returning false would be more appropriate? + return actions.stream() + .map(use -> use.useItem(params)) + .reduce(false, (a, b) -> a || b); // Don't short-circuit!!! + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerData.java b/src/main/java/emu/grasscutter/game/tower/TowerData.java index df0d548ef..83ff0ba3c 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerData.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerData.java @@ -1,25 +1,19 @@ -package emu.grasscutter.game.tower; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; - -import java.util.Map; - -@Entity -public class TowerData { - /** - * the floor players chose - */ - int currentFloorId; - int currentLevel; - @Transient - int currentLevelId; - - /** - * floorId - Record - */ - Map recordMap; - - @Transient - int entryScene; -} +package emu.grasscutter.game.tower; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import java.util.Map; + +@Entity +public class TowerData { + /** the floor players chose */ + int currentFloorId; + + int currentLevel; + @Transient int currentLevelId; + + /** floorId - Record */ + Map recordMap; + + @Transient int entryScene; +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java index 4b16ae26b..fbb2568e1 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java @@ -1,64 +1,56 @@ -package emu.grasscutter.game.tower; - -import dev.morphia.annotations.Entity; - -import java.util.HashMap; -import java.util.Map; - -@Entity -public class TowerLevelRecord { - /** - * floorId in config - */ - private int floorId; - /** - * LevelId - Stars - */ - private Map passedLevelMap; - - private int floorStarRewardProgress; - - public TowerLevelRecord() { - - } - - public TowerLevelRecord(int floorId) { - this.floorId = floorId; - this.passedLevelMap = new HashMap<>(); - this.floorStarRewardProgress = 0; - } - - public TowerLevelRecord setLevelStars(int levelId, int stars) { - passedLevelMap.put(levelId, stars); - return this; - } - - public int getStarCount() { - return passedLevelMap.values().stream().mapToInt(Integer::intValue).sum(); - } - - public int getFloorId() { - return floorId; - } - - public void setFloorId(int floorId) { - this.floorId = floorId; - } - - public Map getPassedLevelMap() { - return passedLevelMap; - } - - public void setPassedLevelMap(Map passedLevelMap) { - this.passedLevelMap = passedLevelMap; - } - - public int getFloorStarRewardProgress() { - return floorStarRewardProgress; - } - - public void setFloorStarRewardProgress(int floorStarRewardProgress) { - this.floorStarRewardProgress = floorStarRewardProgress; - } - -} +package emu.grasscutter.game.tower; + +import dev.morphia.annotations.Entity; +import java.util.HashMap; +import java.util.Map; + +@Entity +public class TowerLevelRecord { + /** floorId in config */ + private int floorId; + /** LevelId - Stars */ + private Map passedLevelMap; + + private int floorStarRewardProgress; + + public TowerLevelRecord() {} + + public TowerLevelRecord(int floorId) { + this.floorId = floorId; + this.passedLevelMap = new HashMap<>(); + this.floorStarRewardProgress = 0; + } + + public TowerLevelRecord setLevelStars(int levelId, int stars) { + passedLevelMap.put(levelId, stars); + return this; + } + + public int getStarCount() { + return passedLevelMap.values().stream().mapToInt(Integer::intValue).sum(); + } + + public int getFloorId() { + return floorId; + } + + public void setFloorId(int floorId) { + this.floorId = floorId; + } + + public Map getPassedLevelMap() { + return passedLevelMap; + } + + public void setPassedLevelMap(Map passedLevelMap) { + this.passedLevelMap = passedLevelMap; + } + + public int getFloorStarRewardProgress() { + return floorStarRewardProgress; + } + + public void setFloorStarRewardProgress(int floorStarRewardProgress) { + this.floorStarRewardProgress = floorStarRewardProgress; + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index 9dccd1f7e..69a444afa 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -1,149 +1,161 @@ -package emu.grasscutter.game.tower; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.TowerLevelData; -import emu.grasscutter.game.dungeons.DungeonSettleListener; -import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; -import emu.grasscutter.game.player.BasePlayerManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.*; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class TowerManager extends BasePlayerManager { - - private static final List towerDungeonSettleListener = List.of(new TowerDungeonSettleListener()); - - public TowerManager(Player player) { - super(player); - } - - public TowerData getTowerData() { - return getPlayer().getTowerData(); - } - - public int getCurrentFloorId() { - return getTowerData().currentFloorId; - } - - public int getCurrentLevelId() { - return getTowerData().currentLevelId + getTowerData().currentLevel; - } - - /** - * form 1-3 - */ - public int getCurrentLevel() { - return getTowerData().currentLevel + 1; - } - - public Map getRecordMap() { - Map recordMap = getTowerData().recordMap; - if (recordMap == null || recordMap.size() == 0) { - recordMap = new HashMap<>(); - recordMap.put(1001, new TowerLevelRecord(1001)); - getTowerData().recordMap = recordMap; - } - return recordMap; - } - - public void teamSelect(int floor, List> towerTeams) { - var floorData = GameData.getTowerFloorDataMap().get(floor); - getTowerData().currentFloorId = floorData.getFloorId(); - getTowerData().currentLevel = 0; - getTowerData().currentLevelId = GameData.getTowerLevelDataMap().values().stream() - .filter(x -> x.getLevelGroupId() == floorData.getLevelGroupId() && x.getLevelIndex() == 1) - .findFirst() - .map(TowerLevelData::getId) - .orElse(0); - - if (getTowerData().entryScene == 0) { - getTowerData().entryScene = player.getSceneId(); - } - - player.getTeamManager().setupTemporaryTeam(towerTeams); - } - - - public void enterLevel(int enterPointId) { - var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId()); - - var dungeonId = levelData.getDungeonId(); - - notifyCurLevelRecordChange(); - // use team user choose - player.getTeamManager().useTemporaryTeam(0); - player.getServer().getDungeonSystem().handoffDungeon(player, dungeonId, - towerDungeonSettleListener); - - // make sure user can exit dungeon correctly - player.getScene().setPrevScene(getTowerData().entryScene); - player.getScene().setPrevScenePoint(enterPointId); - - player.getSession().send(new PacketTowerEnterLevelRsp(getTowerData().currentFloorId, getCurrentLevel())); - // stop using skill - player.getSession().send(new PacketCanUseSkillNotify(false)); - // notify the cond of stars - player.getSession().send(new PacketTowerLevelStarCondNotify(getTowerData().currentFloorId, getCurrentLevel())); - } - - public void notifyCurLevelRecordChange() { - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(getTowerData().currentFloorId, getCurrentLevel())); - } - - public void notifyCurLevelRecordChangeWhenDone(int stars) { - Map recordMap = getRecordMap(); - int currentFloorId = getTowerData().currentFloorId; - if (!recordMap.containsKey(currentFloorId)) { - recordMap.put(currentFloorId, - new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(), stars)); - } else { - recordMap.put(currentFloorId, - recordMap.get(currentFloorId).setLevelStars(getCurrentLevelId(), stars)); - } - - getTowerData().currentLevel++; - - if (!hasNextLevel()) { - // set up the next floor - var nextFloorId = this.getNextFloorId(); - recordMap.computeIfAbsent(nextFloorId, TowerLevelRecord::new); - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(nextFloorId, 1)); - } else { - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); - } - } - - public boolean hasNextLevel() { - return getTowerData().currentLevel < 3; - } - - public int getNextFloorId() { - return player.getServer().getTowerSystem().getNextFloorId(getTowerData().currentFloorId); - } - - public boolean hasNextFloor() { - return player.getServer().getTowerSystem().getNextFloorId(getTowerData().currentFloorId) > 0; - } - - public void clearEntry() { - getTowerData().entryScene = 0; - } - - public boolean canEnterScheduleFloor() { - Map recordMap = getRecordMap(); - if (!recordMap.containsKey(player.getServer().getTowerSystem().getLastEntranceFloor())) { - return false; - } - return recordMap.get(player.getServer().getTowerSystem().getLastEntranceFloor()) - .getStarCount() >= 6; - } - - public void mirrorTeamSetUp(int teamId) { - // use team user choose - player.getTeamManager().useTemporaryTeam(teamId); - player.sendPacket(new PacketTowerMiddleLevelChangeTeamNotify()); - } -} +package emu.grasscutter.game.tower; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.TowerLevelData; +import emu.grasscutter.game.dungeons.DungeonSettleListener; +import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; +import emu.grasscutter.game.player.BasePlayerManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TowerManager extends BasePlayerManager { + + private static final List towerDungeonSettleListener = + List.of(new TowerDungeonSettleListener()); + + public TowerManager(Player player) { + super(player); + } + + public TowerData getTowerData() { + return getPlayer().getTowerData(); + } + + public int getCurrentFloorId() { + return getTowerData().currentFloorId; + } + + public int getCurrentLevelId() { + return getTowerData().currentLevelId + getTowerData().currentLevel; + } + + /** form 1-3 */ + public int getCurrentLevel() { + return getTowerData().currentLevel + 1; + } + + public Map getRecordMap() { + Map recordMap = getTowerData().recordMap; + if (recordMap == null || recordMap.size() == 0) { + recordMap = new HashMap<>(); + recordMap.put(1001, new TowerLevelRecord(1001)); + getTowerData().recordMap = recordMap; + } + return recordMap; + } + + public void teamSelect(int floor, List> towerTeams) { + var floorData = GameData.getTowerFloorDataMap().get(floor); + getTowerData().currentFloorId = floorData.getFloorId(); + getTowerData().currentLevel = 0; + getTowerData().currentLevelId = + GameData.getTowerLevelDataMap().values().stream() + .filter( + x -> x.getLevelGroupId() == floorData.getLevelGroupId() && x.getLevelIndex() == 1) + .findFirst() + .map(TowerLevelData::getId) + .orElse(0); + + if (getTowerData().entryScene == 0) { + getTowerData().entryScene = player.getSceneId(); + } + + player.getTeamManager().setupTemporaryTeam(towerTeams); + } + + public void enterLevel(int enterPointId) { + var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId()); + + var dungeonId = levelData.getDungeonId(); + + notifyCurLevelRecordChange(); + // use team user choose + player.getTeamManager().useTemporaryTeam(0); + player + .getServer() + .getDungeonSystem() + .handoffDungeon(player, dungeonId, towerDungeonSettleListener); + + // make sure user can exit dungeon correctly + player.getScene().setPrevScene(getTowerData().entryScene); + player.getScene().setPrevScenePoint(enterPointId); + + player + .getSession() + .send(new PacketTowerEnterLevelRsp(getTowerData().currentFloorId, getCurrentLevel())); + // stop using skill + player.getSession().send(new PacketCanUseSkillNotify(false)); + // notify the cond of stars + player + .getSession() + .send(new PacketTowerLevelStarCondNotify(getTowerData().currentFloorId, getCurrentLevel())); + } + + public void notifyCurLevelRecordChange() { + player + .getSession() + .send( + new PacketTowerCurLevelRecordChangeNotify( + getTowerData().currentFloorId, getCurrentLevel())); + } + + public void notifyCurLevelRecordChangeWhenDone(int stars) { + Map recordMap = getRecordMap(); + int currentFloorId = getTowerData().currentFloorId; + if (!recordMap.containsKey(currentFloorId)) { + recordMap.put( + currentFloorId, + new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(), stars)); + } else { + recordMap.put( + currentFloorId, recordMap.get(currentFloorId).setLevelStars(getCurrentLevelId(), stars)); + } + + getTowerData().currentLevel++; + + if (!hasNextLevel()) { + // set up the next floor + var nextFloorId = this.getNextFloorId(); + recordMap.computeIfAbsent(nextFloorId, TowerLevelRecord::new); + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(nextFloorId, 1)); + } else { + player + .getSession() + .send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); + } + } + + public boolean hasNextLevel() { + return getTowerData().currentLevel < 3; + } + + public int getNextFloorId() { + return player.getServer().getTowerSystem().getNextFloorId(getTowerData().currentFloorId); + } + + public boolean hasNextFloor() { + return player.getServer().getTowerSystem().getNextFloorId(getTowerData().currentFloorId) > 0; + } + + public void clearEntry() { + getTowerData().entryScene = 0; + } + + public boolean canEnterScheduleFloor() { + Map recordMap = getRecordMap(); + if (!recordMap.containsKey(player.getServer().getTowerSystem().getLastEntranceFloor())) { + return false; + } + return recordMap.get(player.getServer().getTowerSystem().getLastEntranceFloor()).getStarCount() + >= 6; + } + + public void mirrorTeamSetUp(int teamId) { + // use team user choose + player.getTeamManager().useTemporaryTeam(teamId); + player.sendPacket(new PacketTowerMiddleLevelChangeTeamNotify()); + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java index 35afbc7ba..d9067592b 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java @@ -1,35 +1,34 @@ -package emu.grasscutter.game.tower; - -import java.util.Date; - -public class TowerScheduleConfig { - private int scheduleId; - - private Date scheduleStartTime; - private Date nextScheduleChangeTime; - - - public int getScheduleId() { - return scheduleId; - } - - public void setScheduleId(int scheduleId) { - this.scheduleId = scheduleId; - } - - public Date getScheduleStartTime() { - return scheduleStartTime; - } - - public void setScheduleStartTime(Date scheduleStartTime) { - this.scheduleStartTime = scheduleStartTime; - } - - public Date getNextScheduleChangeTime() { - return nextScheduleChangeTime; - } - - public void setNextScheduleChangeTime(Date nextScheduleChangeTime) { - this.nextScheduleChangeTime = nextScheduleChangeTime; - } -} +package emu.grasscutter.game.tower; + +import java.util.Date; + +public class TowerScheduleConfig { + private int scheduleId; + + private Date scheduleStartTime; + private Date nextScheduleChangeTime; + + public int getScheduleId() { + return scheduleId; + } + + public void setScheduleId(int scheduleId) { + this.scheduleId = scheduleId; + } + + public Date getScheduleStartTime() { + return scheduleStartTime; + } + + public void setScheduleStartTime(Date scheduleStartTime) { + this.scheduleStartTime = scheduleStartTime; + } + + public Date getNextScheduleChangeTime() { + return nextScheduleChangeTime; + } + + public void setNextScheduleChangeTime(Date nextScheduleChangeTime) { + this.nextScheduleChangeTime = nextScheduleChangeTime; + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerSystem.java b/src/main/java/emu/grasscutter/game/tower/TowerSystem.java index 21a0f5c0d..f9aef2876 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerSystem.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerSystem.java @@ -1,86 +1,89 @@ -package emu.grasscutter.game.tower; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.TowerScheduleData; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; - -import java.util.ArrayList; -import java.util.List; - -public class TowerSystem extends BaseGameSystem { - - private TowerScheduleConfig towerScheduleConfig; - - public TowerSystem(GameServer server) { - super(server); - this.load(); - } - - public synchronized void load() { - try { - towerScheduleConfig = DataLoader.loadClass("TowerSchedule.json", TowerScheduleConfig.class); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load tower schedule config.", e); - } - } - - public TowerScheduleConfig getTowerScheduleConfig() { - return towerScheduleConfig; - } - - public TowerScheduleData getCurrentTowerScheduleData() { - var data = GameData.getTowerScheduleDataMap().get(towerScheduleConfig.getScheduleId()); - if (data == null) { - Grasscutter.getLogger().error("Could not get current tower schedule data by schedule id {}, please check your resource files", - towerScheduleConfig.getScheduleId()); - } - - return data; - } - - public List getAllFloors() { - List floors = new ArrayList<>(this.getCurrentTowerScheduleData().getEntranceFloorId()); - floors.addAll(this.getScheduleFloors()); - return floors; - } - - public List getScheduleFloors() { - return getCurrentTowerScheduleData().getSchedules().get(0).getFloorList(); - } - - public int getNextFloorId(int floorId) { - var entranceFloors = getCurrentTowerScheduleData().getEntranceFloorId(); - var scheduleFloors = getScheduleFloors(); - var nextId = 0; - - // find in entrance floors first - for (int i = 0; i < entranceFloors.size() - 1; i++) { - if (floorId == entranceFloors.get(i)) { - nextId = entranceFloors.get(i + 1); - } - } - - if (floorId == entranceFloors.get(entranceFloors.size() - 1)) { - nextId = scheduleFloors.get(0); - } - - if (nextId != 0) { - return nextId; - } - - // find in schedule floors - for (int i = 0; i < scheduleFloors.size() - 1; i++) { - if (floorId == scheduleFloors.get(i)) { - nextId = scheduleFloors.get(i + 1); - } - } - return nextId; - } - - public Integer getLastEntranceFloor() { - return getCurrentTowerScheduleData().getEntranceFloorId().get(getCurrentTowerScheduleData().getEntranceFloorId().size() - 1); - } -} +package emu.grasscutter.game.tower; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.TowerScheduleData; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import java.util.ArrayList; +import java.util.List; + +public class TowerSystem extends BaseGameSystem { + + private TowerScheduleConfig towerScheduleConfig; + + public TowerSystem(GameServer server) { + super(server); + this.load(); + } + + public synchronized void load() { + try { + towerScheduleConfig = DataLoader.loadClass("TowerSchedule.json", TowerScheduleConfig.class); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load tower schedule config.", e); + } + } + + public TowerScheduleConfig getTowerScheduleConfig() { + return towerScheduleConfig; + } + + public TowerScheduleData getCurrentTowerScheduleData() { + var data = GameData.getTowerScheduleDataMap().get(towerScheduleConfig.getScheduleId()); + if (data == null) { + Grasscutter.getLogger() + .error( + "Could not get current tower schedule data by schedule id {}, please check your resource files", + towerScheduleConfig.getScheduleId()); + } + + return data; + } + + public List getAllFloors() { + List floors = new ArrayList<>(this.getCurrentTowerScheduleData().getEntranceFloorId()); + floors.addAll(this.getScheduleFloors()); + return floors; + } + + public List getScheduleFloors() { + return getCurrentTowerScheduleData().getSchedules().get(0).getFloorList(); + } + + public int getNextFloorId(int floorId) { + var entranceFloors = getCurrentTowerScheduleData().getEntranceFloorId(); + var scheduleFloors = getScheduleFloors(); + var nextId = 0; + + // find in entrance floors first + for (int i = 0; i < entranceFloors.size() - 1; i++) { + if (floorId == entranceFloors.get(i)) { + nextId = entranceFloors.get(i + 1); + } + } + + if (floorId == entranceFloors.get(entranceFloors.size() - 1)) { + nextId = scheduleFloors.get(0); + } + + if (nextId != 0) { + return nextId; + } + + // find in schedule floors + for (int i = 0; i < scheduleFloors.size() - 1; i++) { + if (floorId == scheduleFloors.get(i)) { + nextId = scheduleFloors.get(i + 1); + } + } + return nextId; + } + + public Integer getLastEntranceFloor() { + return getCurrentTowerScheduleData() + .getEntranceFloorId() + .get(getCurrentTowerScheduleData().getEntranceFloorId().size() - 1); + } +} diff --git a/src/main/java/emu/grasscutter/game/world/ChestReward.java b/src/main/java/emu/grasscutter/game/world/ChestReward.java index 7d3d8de76..06c7a23cf 100644 --- a/src/main/java/emu/grasscutter/game/world/ChestReward.java +++ b/src/main/java/emu/grasscutter/game/world/ChestReward.java @@ -1,22 +1,20 @@ -package emu.grasscutter.game.world; - -import emu.grasscutter.game.inventory.ItemDef; -import lombok.AccessLevel; -import lombok.Data; -import lombok.experimental.FieldDefaults; - -import java.util.List; - -@Data -@FieldDefaults(level = AccessLevel.PRIVATE) -public class ChestReward { - List objNames; - int advExp; - int resin; - int mora; - int sigil; - List content; - int randomCount; - List randomContent; - -} +package emu.grasscutter.game.world; + +import emu.grasscutter.game.inventory.ItemDef; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ChestReward { + List objNames; + int advExp; + int resin; + int mora; + int sigil; + List content; + int randomCount; + List randomContent; +} diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index 64ca135c9..e39f76d57 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -1,799 +1,828 @@ -package emu.grasscutter.game.world; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.GameDepot; -import emu.grasscutter.data.binout.SceneNpcBornEntry; -import emu.grasscutter.data.excels.*; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.dungeons.DungeonSettleListener; -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.game.entity.*; -import emu.grasscutter.game.entity.gadget.GadgetWorktop; -import emu.grasscutter.game.managers.blossom.BlossomManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.TeamInfo; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.LifeState; -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.game.quest.QuestGroupSuite; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; -import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass; -import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; -import emu.grasscutter.scripts.SceneIndexManager; -import emu.grasscutter.scripts.SceneScriptManager; -import emu.grasscutter.scripts.data.SceneBlock; -import emu.grasscutter.scripts.data.SceneGadget; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Position; -import lombok.Getter; -import lombok.Setter; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.stream.Collectors; - -public class Scene { - @Getter - private final World world; - @Getter - private final SceneData sceneData; - @Getter - private final List players; - @Getter - private final Map entities; - @Getter - private final Set spawnedEntities; - @Getter - private final Set deadSpawnedEntities; - @Getter - private final Set loadedBlocks; - @Getter - private final BlossomManager blossomManager; - private Set loadedGridBlocks; - @Getter - @Setter - private boolean dontDestroyWhenEmpty; - - @Getter - @Setter - private int autoCloseTime; - @Getter - @Setter - private int time; - private final long startTime; - - @Getter - private final SceneScriptManager scriptManager; - @Getter - @Setter - private WorldChallenge challenge; - @Getter - private List dungeonSettleListeners; - @Getter - private DungeonData dungeonData; - @Getter - @Setter - private int prevScene; // Id of the previous scene - @Getter - @Setter - private int prevScenePoint; - private Set npcBornEntrySet; - - public Scene(World world, SceneData sceneData) { - this.world = world; - this.sceneData = sceneData; - this.players = new CopyOnWriteArrayList<>(); - this.entities = new ConcurrentHashMap<>(); - - this.time = 8 * 60; - this.startTime = System.currentTimeMillis(); - this.prevScene = 3; - - this.spawnedEntities = ConcurrentHashMap.newKeySet(); - this.deadSpawnedEntities = ConcurrentHashMap.newKeySet(); - this.loadedBlocks = ConcurrentHashMap.newKeySet(); - this.loadedGridBlocks = new HashSet<>(); - this.npcBornEntrySet = ConcurrentHashMap.newKeySet(); - this.scriptManager = new SceneScriptManager(this); - this.blossomManager = new BlossomManager(this); - } - - public int getId() { - return sceneData.getId(); - } - - public SceneType getSceneType() { - return getSceneData().getSceneType(); - } - - public int getPlayerCount() { - return this.getPlayers().size(); - } - - public GameEntity getEntityById(int id) { - return this.entities.get(id); - } - - public GameEntity getEntityByConfigId(int configId) { - return this.entities.values().stream() - .filter(x -> x.getConfigId() == configId) - .findFirst() - .orElse(null); - } - - public void changeTime(int time) { - this.time = time % 1440; - } - - public int getSceneTime() { - return (int) (System.currentTimeMillis() - this.startTime); - } - - public void setDungeonData(DungeonData dungeonData) { - if (dungeonData == null || this.dungeonData != null || this.getSceneType() != SceneType.SCENE_DUNGEON || dungeonData.getSceneId() != this.getId()) { - return; - } - this.dungeonData = dungeonData; - } - - public void addDungeonSettleObserver(DungeonSettleListener dungeonSettleListener) { - if (dungeonSettleListeners == null) { - dungeonSettleListeners = new ArrayList<>(); - } - dungeonSettleListeners.add(dungeonSettleListener); - } - - public boolean isInScene(GameEntity entity) { - return this.entities.containsKey(entity.getId()); - } - - public synchronized void addPlayer(Player player) { - // Check if player already in - if (getPlayers().contains(player)) { - return; - } - - // Remove player from prev scene - if (player.getScene() != null) { - player.getScene().removePlayer(player); - } - - // Add - getPlayers().add(player); - player.setSceneId(this.getId()); - player.setScene(this); - - this.setupPlayerAvatars(player); - } - - public synchronized void removePlayer(Player player) { - // Remove from challenge if leaving - if (this.getChallenge() != null && this.getChallenge().inProgress()) { - player.sendPacket(new PacketDungeonChallengeFinishNotify(this.getChallenge())); - } - - // Remove player from scene - getPlayers().remove(player); - player.setScene(null); - - // Remove player avatars - this.removePlayerAvatars(player); - - // Remove player gadgets - for (EntityBaseGadget gadget : player.getTeamManager().getGadgets()) { - this.removeEntity(gadget); - } - - // Deregister scene if not in use - if (this.getPlayerCount() <= 0 && !this.dontDestroyWhenEmpty) { - this.getWorld().deregisterScene(this); - } - } - - private void setupPlayerAvatars(Player player) { - // Clear entities from old team - player.getTeamManager().getActiveTeam().clear(); - - // Add new entities for player - TeamInfo teamInfo = player.getTeamManager().getCurrentTeamInfo(); - for (int avatarId : teamInfo.getAvatars()) { - EntityAvatar entity = new EntityAvatar(player.getScene(), player.getAvatars().getAvatarById(avatarId)); - player.getTeamManager().getActiveTeam().add(entity); - } - - // Limit character index in case its out of bounds - if (player.getTeamManager().getCurrentCharacterIndex() >= player.getTeamManager().getActiveTeam().size() || player.getTeamManager().getCurrentCharacterIndex() < 0) { - player.getTeamManager().setCurrentCharacterIndex(player.getTeamManager().getCurrentCharacterIndex() - 1); - } - } - - private synchronized void removePlayerAvatars(Player player) { - var team = player.getTeamManager().getActiveTeam(); - // removeEntities(team, VisionType.VISION_TYPE_REMOVE); // List isn't cool apparently :( - team.forEach(e -> removeEntity(e, VisionType.VISION_TYPE_REMOVE)); - team.clear(); - } - - public void spawnPlayer(Player player) { - var teamManager = player.getTeamManager(); - if (this.isInScene(teamManager.getCurrentAvatarEntity())) { - return; - } - - if (teamManager.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) { - teamManager.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 1f); - } - - this.addEntity(teamManager.getCurrentAvatarEntity()); - - // Notify the client of any extra skill charges - teamManager.getActiveTeam().stream().map(EntityAvatar::getAvatar).forEach(Avatar::sendSkillExtraChargeMap); - } - - private void addEntityDirectly(GameEntity entity) { - getEntities().put(entity.getId(), entity); - entity.onCreate(); // Call entity create event - } - - public synchronized void addEntity(GameEntity entity) { - this.addEntityDirectly(entity); - this.broadcastPacket(new PacketSceneEntityAppearNotify(entity)); - } - - public synchronized void addEntityToSingleClient(Player player, GameEntity entity) { - this.addEntityDirectly(entity); - player.sendPacket(new PacketSceneEntityAppearNotify(entity)); - - } - - public void addEntities(Collection entities) { - addEntities(entities, VisionType.VISION_TYPE_BORN); - } - - public synchronized void addEntities(Collection entities, VisionType visionType) { - if (entities == null || entities.isEmpty()) { - return; - } - for (GameEntity entity : entities) { - this.addEntityDirectly(entity); - } - - this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, visionType)); - } - - private GameEntity removeEntityDirectly(GameEntity entity) { - var removed = getEntities().remove(entity.getId()); - if (removed != null) { - removed.onRemoved();//Call entity remove event - } - return removed; - } - - public void removeEntity(GameEntity entity) { - this.removeEntity(entity, VisionType.VISION_TYPE_DIE); - } - - public synchronized void removeEntity(GameEntity entity, VisionType visionType) { - GameEntity removed = this.removeEntityDirectly(entity); - if (removed != null) { - this.broadcastPacket(new PacketSceneEntityDisappearNotify(removed, visionType)); - } - } - - public synchronized void removeEntities(List entity, VisionType visionType) { - var toRemove = entity.stream() - .map(this::removeEntityDirectly) - .toList(); - if (toRemove.size() > 0) { - this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, visionType)); - } - } - - public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { - this.removeEntityDirectly(oldEntity); - this.addEntityDirectly(newEntity); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_TYPE_REPLACE)); - this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_TYPE_REPLACE, oldEntity.getId())); - } - - public void showOtherEntities(Player player) { - GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity(); - List entities = this.getEntities().values().stream().filter(entity -> entity != currentEntity).toList(); - - player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET)); - } - - public void handleAttack(AttackResult result) { - //GameEntity attacker = getEntityById(result.getAttackerId()); - GameEntity target = getEntityById(result.getDefenseId()); - - if (target == null) { - return; - } - - // Godmode check - if (target instanceof EntityAvatar) { - if (((EntityAvatar) target).getPlayer().inGodmode()) { - return; - } - } - - // Sanity check - target.damage(result.getDamage(), result.getAttackerId()); - } - - public void killEntity(GameEntity target) { - killEntity(target, 0); - } - - public void killEntity(GameEntity target, int attackerId) { - GameEntity attacker = null; - - if (attackerId > 0) { - attacker = getEntityById(attackerId); - } - - if (attacker != null) { - // Check codex - if (attacker instanceof EntityClientGadget gadgetAttacker) { - var clientGadgetOwner = getEntityById(gadgetAttacker.getOwnerEntityId()); - if (clientGadgetOwner instanceof EntityAvatar) { - ((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL); - } - } else if (attacker instanceof EntityAvatar avatarAttacker) { - avatarAttacker.getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL); - } - } - - // Packet - this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD)); - - // Reward drop - if (target instanceof EntityMonster && this.getSceneType() != SceneType.SCENE_DUNGEON) { - getWorld().getServer().getDropSystem().callDrop((EntityMonster) target); - } - - // Remove entity from world - this.removeEntity(target); - - // Death event - target.onDeath(attackerId); - } - - public void onTick() { - // disable script for home - if (this.getSceneType() == SceneType.SCENE_HOME_WORLD || this.getSceneType() == SceneType.SCENE_HOME_ROOM) { - return; - } - if (this.getScriptManager().isInit()) { - this.checkBlocks(); - } else { - // TEMPORARY - this.checkSpawns(); - } - // Triggers - this.scriptManager.checkRegions(); - - if (challenge != null) { - challenge.onCheckTimeOut(); - } - - blossomManager.onTick(); - - checkNpcGroup(); - } - - public int getEntityLevel(int baseLevel, int worldLevelOverride) { - int level = worldLevelOverride > 0 ? worldLevelOverride + baseLevel - 22 : baseLevel; - level = level >= 100 ? 100 : level; - level = level <= 0 ? 1 : level; - - return level; - } - - public void checkNpcGroup() { - Set npcBornEntries = ConcurrentHashMap.newKeySet(); - for (Player player : this.getPlayers()) { - npcBornEntries.addAll(loadNpcForPlayer(player)); - } - - // clear the unreachable group for client - var toUnload = this.npcBornEntrySet.stream() - .filter(i -> !npcBornEntries.contains(i)) - .map(SceneNpcBornEntry::getGroupId) - .toList(); - - if (toUnload.size() > 0) { - broadcastPacket(new PacketGroupUnloadNotify(toUnload)); - Grasscutter.getLogger().debug("Unload NPC Group {}", toUnload); - } - // exchange the new npcBornEntry Set - this.npcBornEntrySet = npcBornEntries; - } - - public synchronized void checkSpawns() { - Set loadedGridBlocks = new HashSet<>(); - for (Player player : this.getPlayers()) { - Collections.addAll(loadedGridBlocks, SpawnDataEntry.GridBlockId.getAdjacentGridBlockIds(player.getSceneId(), player.getPosition())); - } - if (this.loadedGridBlocks.containsAll(loadedGridBlocks)) { // Don't recalculate static spawns if nothing has changed - return; - } - this.loadedGridBlocks = loadedGridBlocks; - var spawnLists = GameDepot.getSpawnLists(); - Set visible = new HashSet<>(); - for (var block : loadedGridBlocks) { - var spawns = spawnLists.get(block); - if (spawns != null) { - visible.addAll(spawns); - } - } - - // World level - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getWorld().getWorldLevel()); - int worldLevelOverride = 0; - - if (worldLevelData != null) { - worldLevelOverride = worldLevelData.getMonsterLevel(); - } - - // Todo - List toAdd = new ArrayList<>(); - List toRemove = new ArrayList<>(); - var spawnedEntities = this.getSpawnedEntities(); - for (SpawnDataEntry entry : visible) { - // If spawn entry is in our view and hasnt been spawned/killed yet, we should spawn it - if (!spawnedEntities.contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) { - // Entity object holder - GameEntity entity = null; - - // Check if spawn entry is monster or gadget - if (entry.getMonsterId() > 0) { - MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId()); - if (data == null) continue; - - int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride); - - EntityMonster monster = new EntityMonster(this, data, entry.getPos(), level); - monster.getRotation().set(entry.getRot()); - monster.setGroupId(entry.getGroup().getGroupId()); - monster.setPoseId(entry.getPoseId()); - monster.setConfigId(entry.getConfigId()); - monster.setSpawnEntry(entry); - - entity = monster; - } else if (entry.getGadgetId() > 0) { - EntityGadget gadget = new EntityGadget(this, entry.getGadgetId(), entry.getPos(), entry.getRot()); - gadget.setGroupId(entry.getGroup().getGroupId()); - gadget.setConfigId(entry.getConfigId()); - gadget.setSpawnEntry(entry); - int state = entry.getGadgetState(); - if (state > 0) { - gadget.setState(state); - } - gadget.buildContent(); - - gadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, Float.POSITIVE_INFINITY); - gadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Float.POSITIVE_INFINITY); - gadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, Float.POSITIVE_INFINITY); - - entity = gadget; - blossomManager.initBlossom(gadget); - } - - if (entity == null) continue; - - // Add to scene and spawned list - toAdd.add(entity); - spawnedEntities.add(entry); - } - } - - for (GameEntity entity : this.getEntities().values()) { - var spawnEntry = entity.getSpawnEntry(); - if (spawnEntry != null && !visible.contains(spawnEntry)) { - toRemove.add(entity); - spawnedEntities.remove(spawnEntry); - } - } - - if (toAdd.size() > 0) { - toAdd.stream().forEach(this::addEntityDirectly); - this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_TYPE_BORN)); - } - if (toRemove.size() > 0) { - toRemove.stream().forEach(this::removeEntityDirectly); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); - blossomManager.recycleGadgetEntity(toRemove); - } - } - - public List getPlayerActiveBlocks(Player player) { - // consider the borders' entities of blocks, so we check if contains by index - return SceneIndexManager.queryNeighbors(getScriptManager().getBlocksIndex(), - player.getPosition().toXZDoubleArray(), Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); - } - - private boolean unloadBlockIfNotVisible(Collection visible, SceneBlock block) { - if (visible.contains(block)) return false; - this.onUnloadBlock(block); - return true; - } - - private synchronized boolean loadBlock(SceneBlock block) { - if (this.loadedBlocks.contains(block)) return false; - this.onLoadBlock(block, this.players); - this.loadedBlocks.add(block); - return true; - } - - public synchronized void checkBlocks() { - Set visible = this.players.stream() - .map(player -> this.getPlayerActiveBlocks(player)) - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - - this.loadedBlocks.removeIf(block -> unloadBlockIfNotVisible(visible, block)); - visible.stream() - .filter(block -> !this.loadBlock(block)) - .forEach(block -> { - // dynamic load the groups for players in a loaded block - var toLoad = this.players.stream() - .filter(p -> block.contains(p.getPosition())) - .map(p -> this.playerMeetGroups(p, block)) - .flatMap(Collection::stream) - .toList(); - this.onLoadGroup(toLoad); - }); - } - - public List playerMeetGroups(Player player, SceneBlock block) { - List sceneGroups = SceneIndexManager.queryNeighbors(block.sceneGroupIndex, player.getPosition().toDoubleArray(), - Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); - - List groups = sceneGroups.stream() - .filter(group -> !scriptManager.getLoadedGroupSetPerBlock().get(block.id).contains(group)) - .peek(group -> scriptManager.getLoadedGroupSetPerBlock().get(block.id).add(group)) - .toList(); - - if (groups.size() == 0) { - return List.of(); - } - - return groups; - } - - public void onLoadBlock(SceneBlock block, List players) { - this.getScriptManager().loadBlockFromScript(block); - scriptManager.getLoadedGroupSetPerBlock().put(block.id, new HashSet<>()); - - // the groups form here is not added in current scene - var groups = players.stream() - .filter(player -> block.contains(player.getPosition())) - .map(p -> playerMeetGroups(p, block)) - .flatMap(Collection::stream) - .toList(); - - onLoadGroup(groups); - Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id); - } - - public void loadTriggerFromGroup(SceneGroup group, String triggerName) { - //Load triggers and regions - getScriptManager().registerTrigger(group.triggers.values().stream().filter(p -> p.name.contains(triggerName)).toList()); - group.regions.values().stream().filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13))).map(region -> new EntityRegion(this, region)) - .forEach(getScriptManager()::registerRegion); - } - - public void onLoadGroup(List groups) { - if (groups == null || groups.isEmpty()) { - return; - } - for (SceneGroup group : groups) { - // We load the script files for the groups here - this.getScriptManager().loadGroupFromScript(group); - } - - // Spawn gadgets AFTER triggers are added - // TODO - var entities = new ArrayList(); - for (SceneGroup group : groups) { - if (group.init_config == null) { - continue; - } - - // Load garbages - List garbageGadgets = group.getGarbageGadgets(); - - if (garbageGadgets != null) { - entities.addAll(garbageGadgets.stream().map(g -> scriptManager.createGadget(group.id, group.block_id, g)) - .filter(Objects::nonNull) - .toList()); - } - - // Load suites - int suite = group.init_config.suite; - - if (suite == 0 || group.suites == null || group.suites.size() == 0) { - continue; - } - - // just load the 'init' suite, avoid spawn the suite added by AddExtraGroupSuite etc. - var suiteData = group.getSuiteByIndex(suite); - suiteData.sceneTriggers.forEach(getScriptManager()::registerTrigger); - - entities.addAll(scriptManager.getGadgetsInGroupSuite(group, suiteData)); - entities.addAll(scriptManager.getMonstersInGroupSuite(group, suiteData)); - - scriptManager.registerRegionInGroupSuite(group, suiteData); - } - - scriptManager.meetEntities(entities); - //scriptManager.callEvent(EventType.EVENT_GROUP_LOAD, null); - //groups.forEach(g -> scriptManager.callEvent(EventType.EVENT_GROUP_LOAD, null)); - Grasscutter.getLogger().info("Scene {} loaded {} group(s)", this.getId(), groups.size()); - } - - public void onUnloadBlock(SceneBlock block) { - List toRemove = this.getEntities().values().stream() - .filter(e -> e.getBlockId() == block.id).toList(); - - if (toRemove.size() > 0) { - toRemove.forEach(this::removeEntityDirectly); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); - } - - for (SceneGroup group : block.groups.values()) { - if (group.triggers != null) { - group.triggers.values().forEach(getScriptManager()::deregisterTrigger); - } - if (group.regions != null) { - group.regions.values().forEach(getScriptManager()::deregisterRegion); - } - } - scriptManager.getLoadedGroupSetPerBlock().remove(block.id); - Grasscutter.getLogger().info("Scene {} Block {} is unloaded.", this.getId(), block.id); - } - // Gadgets - - public void onPlayerCreateGadget(EntityClientGadget gadget) { - // Directly add - this.addEntityDirectly(gadget); - - // Add to owner's gadget list - gadget.getOwner().getTeamManager().getGadgets().add(gadget); - - // Optimization - if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) { - return; - } - - this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityAppearNotify(gadget)); - } - - public void onPlayerDestroyGadget(int entityId) { - GameEntity entity = getEntities().get(entityId); - - if (entity == null || !(entity instanceof EntityClientGadget gadget)) { - return; - } - - // Get and remove entity - this.removeEntityDirectly(gadget); - - // Remove from owner's gadget list - gadget.getOwner().getTeamManager().getGadgets().remove(gadget); - - // Optimization - if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) { - return; - } - - this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_TYPE_DIE)); - } - - // Broadcasting - - public void broadcastPacket(BasePacket packet) { - // Send to all players - might have to check if player has been sent data packets - for (Player player : this.getPlayers()) { - player.getSession().send(packet); - } - } - - public void broadcastPacketToOthers(Player excludedPlayer, BasePacket packet) { - // Optimization - if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) { - return; - } - // Send to all players - might have to check if player has been sent data packets - for (Player player : this.getPlayers()) { - if (player == excludedPlayer) { - continue; - } - // Send - player.getSession().send(packet); - } - } - - public void addItemEntity(int itemId, int amount, GameEntity bornForm) { - ItemData itemData = GameData.getItemDataMap().get(itemId); - if (itemData == null) { - return; - } - if (itemData.isEquip()) { - float range = (1.5f + (.05f * amount)); - for (int i = 0; i < amount; i++) { - Position pos = bornForm.getPosition().nearby2d(range).addZ(.9f); // Why Z? - EntityItem entity = new EntityItem(this, null, itemData, pos, 1); - addEntity(entity); - } - } else { - EntityItem entity = new EntityItem(this, null, itemData, bornForm.getPosition().clone().addZ(.9f), amount); // Why Z? - addEntity(entity); - } - } - - public void loadNpcForPlayerEnter(Player player) { - this.npcBornEntrySet.addAll(loadNpcForPlayer(player)); - } - - private List loadNpcForPlayer(Player player) { - var pos = player.getPosition(); - var data = GameData.getSceneNpcBornData().get(getId()); - if (data == null) { - return List.of(); - } - - var npcList = SceneIndexManager.queryNeighbors(data.getIndex(), pos.toDoubleArray(), - Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); - - var sceneNpcBornEntries = npcList.stream() - .filter(i -> !this.npcBornEntrySet.contains(i)) - .toList(); - - if (sceneNpcBornEntries.size() > 0) { - this.broadcastPacket(new PacketGroupSuiteNotify(sceneNpcBornEntries)); - Grasscutter.getLogger().debug("Loaded Npc Group Suite {}", sceneNpcBornEntries); - } - return npcList; - } - - public void loadGroupForQuest(List sceneGroupSuite) { - if (!scriptManager.isInit()) { - return; - } - - sceneGroupSuite.forEach(i -> { - var group = scriptManager.getGroupById(i.getGroup()); - if (group == null) { - return; - } - var suite = group.getSuiteByIndex(i.getSuite()); - if (suite == null) { - return; - } - scriptManager.addGroupSuite(group, suite); - }); - } - - public void selectWorktopOptionWith(SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq req) { - GameEntity entity = getEntityById(req.getGadgetEntityId()); - if (entity == null) { - return; - } - // Handle - if (entity instanceof EntityGadget gadget) { - if (gadget.getContent() instanceof GadgetWorktop worktop) { - boolean shouldDelete = worktop.onSelectWorktopOption(req); - if (shouldDelete) { - entity.getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE); - } - } - } - } -} +package emu.grasscutter.game.world; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; +import emu.grasscutter.data.binout.SceneNpcBornEntry; +import emu.grasscutter.data.excels.*; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.dungeons.DungeonSettleListener; +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.game.entity.*; +import emu.grasscutter.game.entity.gadget.GadgetWorktop; +import emu.grasscutter.game.managers.blossom.BlossomManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.TeamInfo; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.QuestGroupSuite; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; +import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass; +import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; +import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.scripts.SceneScriptManager; +import emu.grasscutter.scripts.data.SceneBlock; +import emu.grasscutter.scripts.data.SceneGadget; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Position; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; + +public class Scene { + @Getter private final World world; + @Getter private final SceneData sceneData; + @Getter private final List players; + @Getter private final Map entities; + @Getter private final Set spawnedEntities; + @Getter private final Set deadSpawnedEntities; + @Getter private final Set loadedBlocks; + @Getter private final BlossomManager blossomManager; + private Set loadedGridBlocks; + @Getter @Setter private boolean dontDestroyWhenEmpty; + + @Getter @Setter private int autoCloseTime; + @Getter @Setter private int time; + private final long startTime; + + @Getter private final SceneScriptManager scriptManager; + @Getter @Setter private WorldChallenge challenge; + @Getter private List dungeonSettleListeners; + @Getter private DungeonData dungeonData; + @Getter @Setter private int prevScene; // Id of the previous scene + @Getter @Setter private int prevScenePoint; + private Set npcBornEntrySet; + + public Scene(World world, SceneData sceneData) { + this.world = world; + this.sceneData = sceneData; + this.players = new CopyOnWriteArrayList<>(); + this.entities = new ConcurrentHashMap<>(); + + this.time = 8 * 60; + this.startTime = System.currentTimeMillis(); + this.prevScene = 3; + + this.spawnedEntities = ConcurrentHashMap.newKeySet(); + this.deadSpawnedEntities = ConcurrentHashMap.newKeySet(); + this.loadedBlocks = ConcurrentHashMap.newKeySet(); + this.loadedGridBlocks = new HashSet<>(); + this.npcBornEntrySet = ConcurrentHashMap.newKeySet(); + this.scriptManager = new SceneScriptManager(this); + this.blossomManager = new BlossomManager(this); + } + + public int getId() { + return sceneData.getId(); + } + + public SceneType getSceneType() { + return getSceneData().getSceneType(); + } + + public int getPlayerCount() { + return this.getPlayers().size(); + } + + public GameEntity getEntityById(int id) { + return this.entities.get(id); + } + + public GameEntity getEntityByConfigId(int configId) { + return this.entities.values().stream() + .filter(x -> x.getConfigId() == configId) + .findFirst() + .orElse(null); + } + + public void changeTime(int time) { + this.time = time % 1440; + } + + public int getSceneTime() { + return (int) (System.currentTimeMillis() - this.startTime); + } + + public void setDungeonData(DungeonData dungeonData) { + if (dungeonData == null + || this.dungeonData != null + || this.getSceneType() != SceneType.SCENE_DUNGEON + || dungeonData.getSceneId() != this.getId()) { + return; + } + this.dungeonData = dungeonData; + } + + public void addDungeonSettleObserver(DungeonSettleListener dungeonSettleListener) { + if (dungeonSettleListeners == null) { + dungeonSettleListeners = new ArrayList<>(); + } + dungeonSettleListeners.add(dungeonSettleListener); + } + + public boolean isInScene(GameEntity entity) { + return this.entities.containsKey(entity.getId()); + } + + public synchronized void addPlayer(Player player) { + // Check if player already in + if (getPlayers().contains(player)) { + return; + } + + // Remove player from prev scene + if (player.getScene() != null) { + player.getScene().removePlayer(player); + } + + // Add + getPlayers().add(player); + player.setSceneId(this.getId()); + player.setScene(this); + + this.setupPlayerAvatars(player); + } + + public synchronized void removePlayer(Player player) { + // Remove from challenge if leaving + if (this.getChallenge() != null && this.getChallenge().inProgress()) { + player.sendPacket(new PacketDungeonChallengeFinishNotify(this.getChallenge())); + } + + // Remove player from scene + getPlayers().remove(player); + player.setScene(null); + + // Remove player avatars + this.removePlayerAvatars(player); + + // Remove player gadgets + for (EntityBaseGadget gadget : player.getTeamManager().getGadgets()) { + this.removeEntity(gadget); + } + + // Deregister scene if not in use + if (this.getPlayerCount() <= 0 && !this.dontDestroyWhenEmpty) { + this.getWorld().deregisterScene(this); + } + } + + private void setupPlayerAvatars(Player player) { + // Clear entities from old team + player.getTeamManager().getActiveTeam().clear(); + + // Add new entities for player + TeamInfo teamInfo = player.getTeamManager().getCurrentTeamInfo(); + for (int avatarId : teamInfo.getAvatars()) { + EntityAvatar entity = + new EntityAvatar(player.getScene(), player.getAvatars().getAvatarById(avatarId)); + player.getTeamManager().getActiveTeam().add(entity); + } + + // Limit character index in case its out of bounds + if (player.getTeamManager().getCurrentCharacterIndex() + >= player.getTeamManager().getActiveTeam().size() + || player.getTeamManager().getCurrentCharacterIndex() < 0) { + player + .getTeamManager() + .setCurrentCharacterIndex(player.getTeamManager().getCurrentCharacterIndex() - 1); + } + } + + private synchronized void removePlayerAvatars(Player player) { + var team = player.getTeamManager().getActiveTeam(); + // removeEntities(team, VisionType.VISION_TYPE_REMOVE); // List isn't cool apparently + // :( + team.forEach(e -> removeEntity(e, VisionType.VISION_TYPE_REMOVE)); + team.clear(); + } + + public void spawnPlayer(Player player) { + var teamManager = player.getTeamManager(); + if (this.isInScene(teamManager.getCurrentAvatarEntity())) { + return; + } + + if (teamManager.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) + <= 0f) { + teamManager.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 1f); + } + + this.addEntity(teamManager.getCurrentAvatarEntity()); + + // Notify the client of any extra skill charges + teamManager.getActiveTeam().stream() + .map(EntityAvatar::getAvatar) + .forEach(Avatar::sendSkillExtraChargeMap); + } + + private void addEntityDirectly(GameEntity entity) { + getEntities().put(entity.getId(), entity); + entity.onCreate(); // Call entity create event + } + + public synchronized void addEntity(GameEntity entity) { + this.addEntityDirectly(entity); + this.broadcastPacket(new PacketSceneEntityAppearNotify(entity)); + } + + public synchronized void addEntityToSingleClient(Player player, GameEntity entity) { + this.addEntityDirectly(entity); + player.sendPacket(new PacketSceneEntityAppearNotify(entity)); + } + + public void addEntities(Collection entities) { + addEntities(entities, VisionType.VISION_TYPE_BORN); + } + + public synchronized void addEntities( + Collection entities, VisionType visionType) { + if (entities == null || entities.isEmpty()) { + return; + } + for (GameEntity entity : entities) { + this.addEntityDirectly(entity); + } + + this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, visionType)); + } + + private GameEntity removeEntityDirectly(GameEntity entity) { + var removed = getEntities().remove(entity.getId()); + if (removed != null) { + removed.onRemoved(); // Call entity remove event + } + return removed; + } + + public void removeEntity(GameEntity entity) { + this.removeEntity(entity, VisionType.VISION_TYPE_DIE); + } + + public synchronized void removeEntity(GameEntity entity, VisionType visionType) { + GameEntity removed = this.removeEntityDirectly(entity); + if (removed != null) { + this.broadcastPacket(new PacketSceneEntityDisappearNotify(removed, visionType)); + } + } + + public synchronized void removeEntities(List entity, VisionType visionType) { + var toRemove = entity.stream().map(this::removeEntityDirectly).toList(); + if (toRemove.size() > 0) { + this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, visionType)); + } + } + + public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { + this.removeEntityDirectly(oldEntity); + this.addEntityDirectly(newEntity); + this.broadcastPacket( + new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_TYPE_REPLACE)); + this.broadcastPacket( + new PacketSceneEntityAppearNotify( + newEntity, VisionType.VISION_TYPE_REPLACE, oldEntity.getId())); + } + + public void showOtherEntities(Player player) { + GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity(); + List entities = + this.getEntities().values().stream().filter(entity -> entity != currentEntity).toList(); + + player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET)); + } + + public void handleAttack(AttackResult result) { + // GameEntity attacker = getEntityById(result.getAttackerId()); + GameEntity target = getEntityById(result.getDefenseId()); + + if (target == null) { + return; + } + + // Godmode check + if (target instanceof EntityAvatar) { + if (((EntityAvatar) target).getPlayer().inGodmode()) { + return; + } + } + + // Sanity check + target.damage(result.getDamage(), result.getAttackerId()); + } + + public void killEntity(GameEntity target) { + killEntity(target, 0); + } + + public void killEntity(GameEntity target, int attackerId) { + GameEntity attacker = null; + + if (attackerId > 0) { + attacker = getEntityById(attackerId); + } + + if (attacker != null) { + // Check codex + if (attacker instanceof EntityClientGadget gadgetAttacker) { + var clientGadgetOwner = getEntityById(gadgetAttacker.getOwnerEntityId()); + if (clientGadgetOwner instanceof EntityAvatar) { + ((EntityClientGadget) attacker) + .getOwner() + .getCodex() + .checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL); + } + } else if (attacker instanceof EntityAvatar avatarAttacker) { + avatarAttacker + .getPlayer() + .getCodex() + .checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL); + } + } + + // Packet + this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD)); + + // Reward drop + if (target instanceof EntityMonster && this.getSceneType() != SceneType.SCENE_DUNGEON) { + getWorld().getServer().getDropSystem().callDrop((EntityMonster) target); + } + + // Remove entity from world + this.removeEntity(target); + + // Death event + target.onDeath(attackerId); + } + + public void onTick() { + // disable script for home + if (this.getSceneType() == SceneType.SCENE_HOME_WORLD + || this.getSceneType() == SceneType.SCENE_HOME_ROOM) { + return; + } + if (this.getScriptManager().isInit()) { + this.checkBlocks(); + } else { + // TEMPORARY + this.checkSpawns(); + } + // Triggers + this.scriptManager.checkRegions(); + + if (challenge != null) { + challenge.onCheckTimeOut(); + } + + blossomManager.onTick(); + + checkNpcGroup(); + } + + public int getEntityLevel(int baseLevel, int worldLevelOverride) { + int level = worldLevelOverride > 0 ? worldLevelOverride + baseLevel - 22 : baseLevel; + level = level >= 100 ? 100 : level; + level = level <= 0 ? 1 : level; + + return level; + } + + public void checkNpcGroup() { + Set npcBornEntries = ConcurrentHashMap.newKeySet(); + for (Player player : this.getPlayers()) { + npcBornEntries.addAll(loadNpcForPlayer(player)); + } + + // clear the unreachable group for client + var toUnload = + this.npcBornEntrySet.stream() + .filter(i -> !npcBornEntries.contains(i)) + .map(SceneNpcBornEntry::getGroupId) + .toList(); + + if (toUnload.size() > 0) { + broadcastPacket(new PacketGroupUnloadNotify(toUnload)); + Grasscutter.getLogger().debug("Unload NPC Group {}", toUnload); + } + // exchange the new npcBornEntry Set + this.npcBornEntrySet = npcBornEntries; + } + + public synchronized void checkSpawns() { + Set loadedGridBlocks = new HashSet<>(); + for (Player player : this.getPlayers()) { + Collections.addAll( + loadedGridBlocks, + SpawnDataEntry.GridBlockId.getAdjacentGridBlockIds( + player.getSceneId(), player.getPosition())); + } + if (this.loadedGridBlocks.containsAll( + loadedGridBlocks)) { // Don't recalculate static spawns if nothing has changed + return; + } + this.loadedGridBlocks = loadedGridBlocks; + var spawnLists = GameDepot.getSpawnLists(); + Set visible = new HashSet<>(); + for (var block : loadedGridBlocks) { + var spawns = spawnLists.get(block); + if (spawns != null) { + visible.addAll(spawns); + } + } + + // World level + WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getWorld().getWorldLevel()); + int worldLevelOverride = 0; + + if (worldLevelData != null) { + worldLevelOverride = worldLevelData.getMonsterLevel(); + } + + // Todo + List toAdd = new ArrayList<>(); + List toRemove = new ArrayList<>(); + var spawnedEntities = this.getSpawnedEntities(); + for (SpawnDataEntry entry : visible) { + // If spawn entry is in our view and hasnt been spawned/killed yet, we should spawn it + if (!spawnedEntities.contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) { + // Entity object holder + GameEntity entity = null; + + // Check if spawn entry is monster or gadget + if (entry.getMonsterId() > 0) { + MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId()); + if (data == null) continue; + + int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride); + + EntityMonster monster = new EntityMonster(this, data, entry.getPos(), level); + monster.getRotation().set(entry.getRot()); + monster.setGroupId(entry.getGroup().getGroupId()); + monster.setPoseId(entry.getPoseId()); + monster.setConfigId(entry.getConfigId()); + monster.setSpawnEntry(entry); + + entity = monster; + } else if (entry.getGadgetId() > 0) { + EntityGadget gadget = + new EntityGadget(this, entry.getGadgetId(), entry.getPos(), entry.getRot()); + gadget.setGroupId(entry.getGroup().getGroupId()); + gadget.setConfigId(entry.getConfigId()); + gadget.setSpawnEntry(entry); + int state = entry.getGadgetState(); + if (state > 0) { + gadget.setState(state); + } + gadget.buildContent(); + + gadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, Float.POSITIVE_INFINITY); + gadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Float.POSITIVE_INFINITY); + gadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, Float.POSITIVE_INFINITY); + + entity = gadget; + blossomManager.initBlossom(gadget); + } + + if (entity == null) continue; + + // Add to scene and spawned list + toAdd.add(entity); + spawnedEntities.add(entry); + } + } + + for (GameEntity entity : this.getEntities().values()) { + var spawnEntry = entity.getSpawnEntry(); + if (spawnEntry != null && !visible.contains(spawnEntry)) { + toRemove.add(entity); + spawnedEntities.remove(spawnEntry); + } + } + + if (toAdd.size() > 0) { + toAdd.stream().forEach(this::addEntityDirectly); + this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_TYPE_BORN)); + } + if (toRemove.size() > 0) { + toRemove.stream().forEach(this::removeEntityDirectly); + this.broadcastPacket( + new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); + blossomManager.recycleGadgetEntity(toRemove); + } + } + + public List getPlayerActiveBlocks(Player player) { + // consider the borders' entities of blocks, so we check if contains by index + return SceneIndexManager.queryNeighbors( + getScriptManager().getBlocksIndex(), + player.getPosition().toXZDoubleArray(), + Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); + } + + private boolean unloadBlockIfNotVisible(Collection visible, SceneBlock block) { + if (visible.contains(block)) return false; + this.onUnloadBlock(block); + return true; + } + + private synchronized boolean loadBlock(SceneBlock block) { + if (this.loadedBlocks.contains(block)) return false; + this.onLoadBlock(block, this.players); + this.loadedBlocks.add(block); + return true; + } + + public synchronized void checkBlocks() { + Set visible = + this.players.stream() + .map(player -> this.getPlayerActiveBlocks(player)) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + this.loadedBlocks.removeIf(block -> unloadBlockIfNotVisible(visible, block)); + visible.stream() + .filter(block -> !this.loadBlock(block)) + .forEach( + block -> { + // dynamic load the groups for players in a loaded block + var toLoad = + this.players.stream() + .filter(p -> block.contains(p.getPosition())) + .map(p -> this.playerMeetGroups(p, block)) + .flatMap(Collection::stream) + .toList(); + this.onLoadGroup(toLoad); + }); + } + + public List playerMeetGroups(Player player, SceneBlock block) { + List sceneGroups = + SceneIndexManager.queryNeighbors( + block.sceneGroupIndex, + player.getPosition().toDoubleArray(), + Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); + + List groups = + sceneGroups.stream() + .filter( + group -> !scriptManager.getLoadedGroupSetPerBlock().get(block.id).contains(group)) + .peek(group -> scriptManager.getLoadedGroupSetPerBlock().get(block.id).add(group)) + .toList(); + + if (groups.size() == 0) { + return List.of(); + } + + return groups; + } + + public void onLoadBlock(SceneBlock block, List players) { + this.getScriptManager().loadBlockFromScript(block); + scriptManager.getLoadedGroupSetPerBlock().put(block.id, new HashSet<>()); + + // the groups form here is not added in current scene + var groups = + players.stream() + .filter(player -> block.contains(player.getPosition())) + .map(p -> playerMeetGroups(p, block)) + .flatMap(Collection::stream) + .toList(); + + onLoadGroup(groups); + Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id); + } + + public void loadTriggerFromGroup(SceneGroup group, String triggerName) { + // Load triggers and regions + getScriptManager() + .registerTrigger( + group.triggers.values().stream().filter(p -> p.name.contains(triggerName)).toList()); + group.regions.values().stream() + .filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13))) + .map(region -> new EntityRegion(this, region)) + .forEach(getScriptManager()::registerRegion); + } + + public void onLoadGroup(List groups) { + if (groups == null || groups.isEmpty()) { + return; + } + for (SceneGroup group : groups) { + // We load the script files for the groups here + this.getScriptManager().loadGroupFromScript(group); + } + + // Spawn gadgets AFTER triggers are added + // TODO + var entities = new ArrayList(); + for (SceneGroup group : groups) { + if (group.init_config == null) { + continue; + } + + // Load garbages + List garbageGadgets = group.getGarbageGadgets(); + + if (garbageGadgets != null) { + entities.addAll( + garbageGadgets.stream() + .map(g -> scriptManager.createGadget(group.id, group.block_id, g)) + .filter(Objects::nonNull) + .toList()); + } + + // Load suites + int suite = group.init_config.suite; + + if (suite == 0 || group.suites == null || group.suites.size() == 0) { + continue; + } + + // just load the 'init' suite, avoid spawn the suite added by AddExtraGroupSuite etc. + var suiteData = group.getSuiteByIndex(suite); + suiteData.sceneTriggers.forEach(getScriptManager()::registerTrigger); + + entities.addAll(scriptManager.getGadgetsInGroupSuite(group, suiteData)); + entities.addAll(scriptManager.getMonstersInGroupSuite(group, suiteData)); + + scriptManager.registerRegionInGroupSuite(group, suiteData); + } + + scriptManager.meetEntities(entities); + // scriptManager.callEvent(EventType.EVENT_GROUP_LOAD, null); + // groups.forEach(g -> scriptManager.callEvent(EventType.EVENT_GROUP_LOAD, null)); + Grasscutter.getLogger().info("Scene {} loaded {} group(s)", this.getId(), groups.size()); + } + + public void onUnloadBlock(SceneBlock block) { + List toRemove = + this.getEntities().values().stream().filter(e -> e.getBlockId() == block.id).toList(); + + if (toRemove.size() > 0) { + toRemove.forEach(this::removeEntityDirectly); + this.broadcastPacket( + new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); + } + + for (SceneGroup group : block.groups.values()) { + if (group.triggers != null) { + group.triggers.values().forEach(getScriptManager()::deregisterTrigger); + } + if (group.regions != null) { + group.regions.values().forEach(getScriptManager()::deregisterRegion); + } + } + scriptManager.getLoadedGroupSetPerBlock().remove(block.id); + Grasscutter.getLogger().info("Scene {} Block {} is unloaded.", this.getId(), block.id); + } + // Gadgets + + public void onPlayerCreateGadget(EntityClientGadget gadget) { + // Directly add + this.addEntityDirectly(gadget); + + // Add to owner's gadget list + gadget.getOwner().getTeamManager().getGadgets().add(gadget); + + // Optimization + if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) { + return; + } + + this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityAppearNotify(gadget)); + } + + public void onPlayerDestroyGadget(int entityId) { + GameEntity entity = getEntities().get(entityId); + + if (entity == null || !(entity instanceof EntityClientGadget gadget)) { + return; + } + + // Get and remove entity + this.removeEntityDirectly(gadget); + + // Remove from owner's gadget list + gadget.getOwner().getTeamManager().getGadgets().remove(gadget); + + // Optimization + if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == gadget.getOwner()) { + return; + } + + this.broadcastPacketToOthers( + gadget.getOwner(), + new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_TYPE_DIE)); + } + + // Broadcasting + + public void broadcastPacket(BasePacket packet) { + // Send to all players - might have to check if player has been sent data packets + for (Player player : this.getPlayers()) { + player.getSession().send(packet); + } + } + + public void broadcastPacketToOthers(Player excludedPlayer, BasePacket packet) { + // Optimization + if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) { + return; + } + // Send to all players - might have to check if player has been sent data packets + for (Player player : this.getPlayers()) { + if (player == excludedPlayer) { + continue; + } + // Send + player.getSession().send(packet); + } + } + + public void addItemEntity(int itemId, int amount, GameEntity bornForm) { + ItemData itemData = GameData.getItemDataMap().get(itemId); + if (itemData == null) { + return; + } + if (itemData.isEquip()) { + float range = (1.5f + (.05f * amount)); + for (int i = 0; i < amount; i++) { + Position pos = bornForm.getPosition().nearby2d(range).addZ(.9f); // Why Z? + EntityItem entity = new EntityItem(this, null, itemData, pos, 1); + addEntity(entity); + } + } else { + EntityItem entity = + new EntityItem( + this, null, itemData, bornForm.getPosition().clone().addZ(.9f), amount); // Why Z? + addEntity(entity); + } + } + + public void loadNpcForPlayerEnter(Player player) { + this.npcBornEntrySet.addAll(loadNpcForPlayer(player)); + } + + private List loadNpcForPlayer(Player player) { + var pos = player.getPosition(); + var data = GameData.getSceneNpcBornData().get(getId()); + if (data == null) { + return List.of(); + } + + var npcList = + SceneIndexManager.queryNeighbors( + data.getIndex(), + pos.toDoubleArray(), + Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange); + + var sceneNpcBornEntries = + npcList.stream().filter(i -> !this.npcBornEntrySet.contains(i)).toList(); + + if (sceneNpcBornEntries.size() > 0) { + this.broadcastPacket(new PacketGroupSuiteNotify(sceneNpcBornEntries)); + Grasscutter.getLogger().debug("Loaded Npc Group Suite {}", sceneNpcBornEntries); + } + return npcList; + } + + public void loadGroupForQuest(List sceneGroupSuite) { + if (!scriptManager.isInit()) { + return; + } + + sceneGroupSuite.forEach( + i -> { + var group = scriptManager.getGroupById(i.getGroup()); + if (group == null) { + return; + } + var suite = group.getSuiteByIndex(i.getSuite()); + if (suite == null) { + return; + } + scriptManager.addGroupSuite(group, suite); + }); + } + + public void selectWorktopOptionWith(SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq req) { + GameEntity entity = getEntityById(req.getGadgetEntityId()); + if (entity == null) { + return; + } + // Handle + if (entity instanceof EntityGadget gadget) { + if (gadget.getContent() instanceof GadgetWorktop worktop) { + boolean shouldDelete = worktop.onSelectWorktopOption(req); + if (shouldDelete) { + entity.getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE); + } + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/world/SpawnDataEntry.java b/src/main/java/emu/grasscutter/game/world/SpawnDataEntry.java index 0006b0846..05fee5110 100644 --- a/src/main/java/emu/grasscutter/game/world/SpawnDataEntry.java +++ b/src/main/java/emu/grasscutter/game/world/SpawnDataEntry.java @@ -1,113 +1,97 @@ -package emu.grasscutter.game.world; - -import emu.grasscutter.data.GameDepot; -import emu.grasscutter.utils.Position; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.Objects; - -public class SpawnDataEntry { - @Getter - @Setter - private transient SpawnGroupEntry group; - @Getter - private int monsterId; - @Getter - private int gadgetId; - @Getter - private int configId; - @Getter - private int level; - @Getter - private int poseId; - @Getter - private int gatherItemId; - @Getter - private int gadgetState; - @Getter - private Position pos; - @Getter - private Position rot; - - public GridBlockId getBlockId() { - int scale = GridBlockId.getScale(gadgetId); - return new GridBlockId(group.sceneId, scale, - (int) (pos.getX() / GameDepot.BLOCK_SIZE[scale]), - (int) (pos.getZ() / GameDepot.BLOCK_SIZE[scale]) - ); - } - - public static class SpawnGroupEntry { - @Getter - private int sceneId; - @Getter - private int groupId; - @Getter - private int blockId; - @Getter - @Setter - private List spawns; - } - - public static class GridBlockId { - @Getter - private final int sceneId; - @Getter - private final int scale; - @Getter - private final int x; - @Getter - private final int z; - - public GridBlockId(int sceneId, int scale, int x, int z) { - this.sceneId = sceneId; - this.scale = scale; - this.x = x; - this.z = z; - } - - public static GridBlockId[] getAdjacentGridBlockIds(int sceneId, Position pos) { - GridBlockId[] results = new GridBlockId[5 * 5 * GameDepot.BLOCK_SIZE.length]; - int t = 0; - for (int scale = 0; scale < GameDepot.BLOCK_SIZE.length; scale++) { - int x = ((int) (pos.getX() / GameDepot.BLOCK_SIZE[scale])); - int z = ((int) (pos.getZ() / GameDepot.BLOCK_SIZE[scale])); - for (int i = x - 2; i < x + 3; i++) { - for (int j = z - 2; j < z + 3; j++) { - results[t++] = new GridBlockId(sceneId, scale, i, j); - } - } - } - return results; - } - - public static int getScale(int gadgetId) { - return 0;//you should implement here,this is index of GameDepot.BLOCK_SIZE - } - - @Override - public String toString() { - return "SpawnDataEntryScaledPoint{" + - "sceneId=" + sceneId + - ", scale=" + scale + - ", x=" + x + - ", z=" + z + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GridBlockId that = (GridBlockId) o; - return sceneId == that.sceneId && scale == that.scale && x == that.x && z == that.z; - } - - @Override - public int hashCode() { - return Objects.hash(sceneId, scale, x, z); - } - } -} +package emu.grasscutter.game.world; + +import emu.grasscutter.data.GameDepot; +import emu.grasscutter.utils.Position; +import java.util.List; +import java.util.Objects; +import lombok.Getter; +import lombok.Setter; + +public class SpawnDataEntry { + @Getter @Setter private transient SpawnGroupEntry group; + @Getter private int monsterId; + @Getter private int gadgetId; + @Getter private int configId; + @Getter private int level; + @Getter private int poseId; + @Getter private int gatherItemId; + @Getter private int gadgetState; + @Getter private Position pos; + @Getter private Position rot; + + public GridBlockId getBlockId() { + int scale = GridBlockId.getScale(gadgetId); + return new GridBlockId( + group.sceneId, + scale, + (int) (pos.getX() / GameDepot.BLOCK_SIZE[scale]), + (int) (pos.getZ() / GameDepot.BLOCK_SIZE[scale])); + } + + public static class SpawnGroupEntry { + @Getter private int sceneId; + @Getter private int groupId; + @Getter private int blockId; + @Getter @Setter private List spawns; + } + + public static class GridBlockId { + @Getter private final int sceneId; + @Getter private final int scale; + @Getter private final int x; + @Getter private final int z; + + public GridBlockId(int sceneId, int scale, int x, int z) { + this.sceneId = sceneId; + this.scale = scale; + this.x = x; + this.z = z; + } + + public static GridBlockId[] getAdjacentGridBlockIds(int sceneId, Position pos) { + GridBlockId[] results = new GridBlockId[5 * 5 * GameDepot.BLOCK_SIZE.length]; + int t = 0; + for (int scale = 0; scale < GameDepot.BLOCK_SIZE.length; scale++) { + int x = ((int) (pos.getX() / GameDepot.BLOCK_SIZE[scale])); + int z = ((int) (pos.getZ() / GameDepot.BLOCK_SIZE[scale])); + for (int i = x - 2; i < x + 3; i++) { + for (int j = z - 2; j < z + 3; j++) { + results[t++] = new GridBlockId(sceneId, scale, i, j); + } + } + } + return results; + } + + public static int getScale(int gadgetId) { + return 0; // you should implement here,this is index of GameDepot.BLOCK_SIZE + } + + @Override + public String toString() { + return "SpawnDataEntryScaledPoint{" + + "sceneId=" + + sceneId + + ", scale=" + + scale + + ", x=" + + x + + ", z=" + + z + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GridBlockId that = (GridBlockId) o; + return sceneId == that.sceneId && scale == that.scale && x == that.x && z == that.z; + } + + @Override + public int hashCode() { + return Objects.hash(sceneId, scale, x, z); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/world/World.java b/src/main/java/emu/grasscutter/game/world/World.java index 3477954dd..e98e80ea0 100644 --- a/src/main/java/emu/grasscutter/game/world/World.java +++ b/src/main/java/emu/grasscutter/game/world/World.java @@ -1,343 +1,363 @@ -package emu.grasscutter.game.world; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.DungeonData; -import emu.grasscutter.data.excels.SceneData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.game.props.EnterReason; -import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; -import emu.grasscutter.scripts.data.SceneConfig; -import emu.grasscutter.server.event.player.PlayerTeleportEvent; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Position; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -public class World implements Iterable { - private final GameServer server; - private final Player owner; - private final List players; - private final Int2ObjectMap scenes; - - private final int levelEntityId; - private int nextEntityId = 0; - private int nextPeerId = 0; - private int worldLevel; - - private final boolean isMultiplayer; - - public World(Player player) { - this(player, false); - } - - public World(Player player, boolean isMultiplayer) { - this.owner = player; - this.server = player.getServer(); - this.players = Collections.synchronizedList(new ArrayList<>()); - this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); - - this.levelEntityId = this.getNextEntityId(EntityIdType.MPLEVEL); - this.worldLevel = player.getWorldLevel(); - this.isMultiplayer = isMultiplayer; - - this.owner.getServer().registerWorld(this); - } - - public Player getHost() { - return owner; - } - - public GameServer getServer() { - return server; - } - - public int getLevelEntityId() { - return levelEntityId; - } - - public int getHostPeerId() { - if (this.getHost() == null) { - return 0; - } - return this.getHost().getPeerId(); - } - - public int getNextPeerId() { - return ++this.nextPeerId; - } - - public int getWorldLevel() { - return worldLevel; - } - - public void setWorldLevel(int worldLevel) { - this.worldLevel = worldLevel; - } - - public List getPlayers() { - return players; - } - - public Int2ObjectMap getScenes() { - return this.scenes; - } - - public Scene getSceneById(int sceneId) { - // Get scene normally - Scene scene = this.getScenes().get(sceneId); - if (scene != null) { - return scene; - } - - // Create scene from scene data if it doesnt exist - SceneData sceneData = GameData.getSceneDataMap().get(sceneId); - if (sceneData != null) { - scene = new Scene(this, sceneData); - this.registerScene(scene); - return scene; - } - - return null; - } - - public int getPlayerCount() { - return this.getPlayers().size(); - } - - public boolean isMultiplayer() { - return isMultiplayer; - } - - public int getNextEntityId(EntityIdType idType) { - return (idType.getId() << 24) + ++this.nextEntityId; - } - - public synchronized void addPlayer(Player player) { - // Check if player already in - if (this.getPlayers().contains(player)) { - return; - } - - // Remove player from prev world - if (player.getWorld() != null) { - player.getWorld().removePlayer(player); - } - - // Register - player.setWorld(this); - this.getPlayers().add(player); - - // Set player variables - player.setPeerId(this.getNextPeerId()); - player.getTeamManager().setEntityId(this.getNextEntityId(EntityIdType.TEAM)); - - // Copy main team to multiplayer team - if (this.isMultiplayer()) { - player.getTeamManager().getMpTeam().copyFrom(player.getTeamManager().getCurrentSinglePlayerTeamInfo(), player.getTeamManager().getMaxTeamSize()); - player.getTeamManager().setCurrentCharacterIndex(0); - } - - // Add to scene - Scene scene = this.getSceneById(player.getSceneId()); - scene.addPlayer(player); - - // Info packet for other players - if (this.getPlayers().size() > 1) { - this.updatePlayerInfos(player); - } - } - - public synchronized void removePlayer(Player player) { - // Remove team entities - player.sendPacket( - new PacketDelTeamEntityNotify( - player.getSceneId(), - this.getPlayers().stream().map(p -> p.getTeamManager().getEntityId()).collect(Collectors.toList()) - ) - ); - - // Deregister - this.getPlayers().remove(player); - player.setWorld(null); - - // Remove from scene - Scene scene = this.getSceneById(player.getSceneId()); - scene.removePlayer(player); - - // Info packet for other players - if (this.getPlayers().size() > 0) { - this.updatePlayerInfos(player); - } - - // Disband world if host leaves - if (this.getHost() == player) { - List kicked = new ArrayList<>(this.getPlayers()); - for (Player victim : kicked) { - World world = new World(victim); - world.addPlayer(victim); - - victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_TYPE_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPosition())); - } - } - } - - public void registerScene(Scene scene) { - this.getScenes().put(scene.getId(), scene); - } - - public void deregisterScene(Scene scene) { - this.getScenes().remove(scene.getId()); - } - - public boolean transferPlayerToScene(Player player, int sceneId, Position pos) { - return this.transferPlayerToScene(player, sceneId, TeleportType.INTERNAL, null, pos); - } - - public boolean transferPlayerToScene(Player player, int sceneId, TeleportType teleportType, Position pos) { - return this.transferPlayerToScene(player, sceneId, teleportType, null, pos); - } - - public boolean transferPlayerToScene(Player player, int sceneId, DungeonData data) { - return this.transferPlayerToScene(player, sceneId, TeleportType.DUNGEON, data, null); - } - - public boolean transferPlayerToScene(Player player, int sceneId, TeleportType teleportType, DungeonData dungeonData, Position teleportTo) { - // Call player teleport event. - PlayerTeleportEvent event = new PlayerTeleportEvent(player, teleportType, player.getPosition(), teleportTo); - // Call event & check if it was canceled. - event.call(); - if (event.isCanceled()) { - return false; // Teleport was canceled. - } - - // Set the destination. - teleportTo = event.getDestination(); - - if (GameData.getSceneDataMap().get(sceneId) == null) { - return false; - } - - Scene oldScene = null; - - if (player.getScene() != null) { - oldScene = player.getScene(); - - // Don't deregister scenes if the player is going to tp back into them - if (oldScene.getId() == sceneId) { - oldScene.setDontDestroyWhenEmpty(true); - } - - oldScene.removePlayer(player); - } - - Scene newScene = this.getSceneById(sceneId); - newScene.setDungeonData(dungeonData); - newScene.addPlayer(player); - - // Dungeon - SceneConfig config = newScene.getScriptManager().getConfig(); - if (teleportTo == null && config != null) { - if (config.born_pos != null) { - teleportTo = newScene.getScriptManager().getConfig().born_pos; - } - if (config.born_rot != null) { - player.getRotation().set(config.born_rot); - } - } - - // Set player position - if (teleportTo == null) { - teleportTo = player.getPosition(); - } - - player.getPosition().set(teleportTo); - - if (oldScene != null) { - newScene.setPrevScene(oldScene.getId()); - oldScene.setDontDestroyWhenEmpty(false); - } - - // Get enter types - EnterType enterType = EnterType.ENTER_TYPE_JUMP; - EnterReason enterReason = EnterReason.TransPoint; - - if (dungeonData != null) { - enterType = EnterType.ENTER_TYPE_DUNGEON; - enterReason = EnterReason.DungeonEnter; - } else if (oldScene == newScene) { - enterType = EnterType.ENTER_TYPE_GOTO; - } else if (newScene.getSceneType() == SceneType.SCENE_HOME_WORLD) { - // Home - enterReason = EnterReason.EnterHome; - enterType = EnterType.ENTER_TYPE_SELF_HOME; - - } - - // Teleport packet - player.sendPacket(new PacketPlayerEnterSceneNotify(player, enterType, enterReason, sceneId, teleportTo)); - return true; - } - - private void updatePlayerInfos(Player paramPlayer) { - for (Player player : this.getPlayers()) { - // Dont send packets if player is logging in and filter out joining player - if (!player.hasSentLoginPackets() || player == paramPlayer) { - continue; - } - - // Update team of all players since max players has been changed - Probably not the best way to do it - if (this.isMultiplayer()) { - player.getTeamManager().getMpTeam().copyFrom(player.getTeamManager().getMpTeam(), player.getTeamManager().getMaxTeamSize()); - player.getTeamManager().updateTeamEntities(null); - } - - // Dont send packets if player is loading into the scene - if (player.getSceneLoadState().getValue() < SceneLoadState.INIT.getValue()) { - // World player info packets - player.getSession().send(new PacketWorldPlayerInfoNotify(this)); - player.getSession().send(new PacketScenePlayerInfoNotify(this)); - player.getSession().send(new PacketWorldPlayerRTTNotify(this)); - - // Team packets - player.getSession().send(new PacketSyncTeamEntityNotify(player)); - player.getSession().send(new PacketSyncScenePlayTeamEntityNotify(player)); - } - } - } - - public void broadcastPacket(BasePacket packet) { - // Send to all players - might have to check if player has been sent data packets - for (Player player : this.getPlayers()) { - player.getSession().send(packet); - } - } - - // Returns true if the world should be deleted - public boolean onTick() { - if (this.getPlayerCount() == 0) return true; - this.scenes.forEach((k, scene) -> scene.onTick()); - return false; - } - - public void close() { - - } - - @Override - public Iterator iterator() { - return this.getPlayers().iterator(); - } -} +package emu.grasscutter.game.world; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.DungeonData; +import emu.grasscutter.data.excels.SceneData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.Player.SceneLoadState; +import emu.grasscutter.game.props.EnterReason; +import emu.grasscutter.game.props.EntityIdType; +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; +import emu.grasscutter.scripts.data.SceneConfig; +import emu.grasscutter.server.event.player.PlayerTeleportEvent; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +public class World implements Iterable { + private final GameServer server; + private final Player owner; + private final List players; + private final Int2ObjectMap scenes; + + private final int levelEntityId; + private int nextEntityId = 0; + private int nextPeerId = 0; + private int worldLevel; + + private final boolean isMultiplayer; + + public World(Player player) { + this(player, false); + } + + public World(Player player, boolean isMultiplayer) { + this.owner = player; + this.server = player.getServer(); + this.players = Collections.synchronizedList(new ArrayList<>()); + this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); + + this.levelEntityId = this.getNextEntityId(EntityIdType.MPLEVEL); + this.worldLevel = player.getWorldLevel(); + this.isMultiplayer = isMultiplayer; + + this.owner.getServer().registerWorld(this); + } + + public Player getHost() { + return owner; + } + + public GameServer getServer() { + return server; + } + + public int getLevelEntityId() { + return levelEntityId; + } + + public int getHostPeerId() { + if (this.getHost() == null) { + return 0; + } + return this.getHost().getPeerId(); + } + + public int getNextPeerId() { + return ++this.nextPeerId; + } + + public int getWorldLevel() { + return worldLevel; + } + + public void setWorldLevel(int worldLevel) { + this.worldLevel = worldLevel; + } + + public List getPlayers() { + return players; + } + + public Int2ObjectMap getScenes() { + return this.scenes; + } + + public Scene getSceneById(int sceneId) { + // Get scene normally + Scene scene = this.getScenes().get(sceneId); + if (scene != null) { + return scene; + } + + // Create scene from scene data if it doesnt exist + SceneData sceneData = GameData.getSceneDataMap().get(sceneId); + if (sceneData != null) { + scene = new Scene(this, sceneData); + this.registerScene(scene); + return scene; + } + + return null; + } + + public int getPlayerCount() { + return this.getPlayers().size(); + } + + public boolean isMultiplayer() { + return isMultiplayer; + } + + public int getNextEntityId(EntityIdType idType) { + return (idType.getId() << 24) + ++this.nextEntityId; + } + + public synchronized void addPlayer(Player player) { + // Check if player already in + if (this.getPlayers().contains(player)) { + return; + } + + // Remove player from prev world + if (player.getWorld() != null) { + player.getWorld().removePlayer(player); + } + + // Register + player.setWorld(this); + this.getPlayers().add(player); + + // Set player variables + player.setPeerId(this.getNextPeerId()); + player.getTeamManager().setEntityId(this.getNextEntityId(EntityIdType.TEAM)); + + // Copy main team to multiplayer team + if (this.isMultiplayer()) { + player + .getTeamManager() + .getMpTeam() + .copyFrom( + player.getTeamManager().getCurrentSinglePlayerTeamInfo(), + player.getTeamManager().getMaxTeamSize()); + player.getTeamManager().setCurrentCharacterIndex(0); + } + + // Add to scene + Scene scene = this.getSceneById(player.getSceneId()); + scene.addPlayer(player); + + // Info packet for other players + if (this.getPlayers().size() > 1) { + this.updatePlayerInfos(player); + } + } + + public synchronized void removePlayer(Player player) { + // Remove team entities + player.sendPacket( + new PacketDelTeamEntityNotify( + player.getSceneId(), + this.getPlayers().stream() + .map(p -> p.getTeamManager().getEntityId()) + .collect(Collectors.toList()))); + + // Deregister + this.getPlayers().remove(player); + player.setWorld(null); + + // Remove from scene + Scene scene = this.getSceneById(player.getSceneId()); + scene.removePlayer(player); + + // Info packet for other players + if (this.getPlayers().size() > 0) { + this.updatePlayerInfos(player); + } + + // Disband world if host leaves + if (this.getHost() == player) { + List kicked = new ArrayList<>(this.getPlayers()); + for (Player victim : kicked) { + World world = new World(victim); + world.addPlayer(victim); + + victim.sendPacket( + new PacketPlayerEnterSceneNotify( + victim, + EnterType.ENTER_TYPE_SELF, + EnterReason.TeamKick, + victim.getSceneId(), + victim.getPosition())); + } + } + } + + public void registerScene(Scene scene) { + this.getScenes().put(scene.getId(), scene); + } + + public void deregisterScene(Scene scene) { + this.getScenes().remove(scene.getId()); + } + + public boolean transferPlayerToScene(Player player, int sceneId, Position pos) { + return this.transferPlayerToScene(player, sceneId, TeleportType.INTERNAL, null, pos); + } + + public boolean transferPlayerToScene( + Player player, int sceneId, TeleportType teleportType, Position pos) { + return this.transferPlayerToScene(player, sceneId, teleportType, null, pos); + } + + public boolean transferPlayerToScene(Player player, int sceneId, DungeonData data) { + return this.transferPlayerToScene(player, sceneId, TeleportType.DUNGEON, data, null); + } + + public boolean transferPlayerToScene( + Player player, + int sceneId, + TeleportType teleportType, + DungeonData dungeonData, + Position teleportTo) { + // Call player teleport event. + PlayerTeleportEvent event = + new PlayerTeleportEvent(player, teleportType, player.getPosition(), teleportTo); + // Call event & check if it was canceled. + event.call(); + if (event.isCanceled()) { + return false; // Teleport was canceled. + } + + // Set the destination. + teleportTo = event.getDestination(); + + if (GameData.getSceneDataMap().get(sceneId) == null) { + return false; + } + + Scene oldScene = null; + + if (player.getScene() != null) { + oldScene = player.getScene(); + + // Don't deregister scenes if the player is going to tp back into them + if (oldScene.getId() == sceneId) { + oldScene.setDontDestroyWhenEmpty(true); + } + + oldScene.removePlayer(player); + } + + Scene newScene = this.getSceneById(sceneId); + newScene.setDungeonData(dungeonData); + newScene.addPlayer(player); + + // Dungeon + SceneConfig config = newScene.getScriptManager().getConfig(); + if (teleportTo == null && config != null) { + if (config.born_pos != null) { + teleportTo = newScene.getScriptManager().getConfig().born_pos; + } + if (config.born_rot != null) { + player.getRotation().set(config.born_rot); + } + } + + // Set player position + if (teleportTo == null) { + teleportTo = player.getPosition(); + } + + player.getPosition().set(teleportTo); + + if (oldScene != null) { + newScene.setPrevScene(oldScene.getId()); + oldScene.setDontDestroyWhenEmpty(false); + } + + // Get enter types + EnterType enterType = EnterType.ENTER_TYPE_JUMP; + EnterReason enterReason = EnterReason.TransPoint; + + if (dungeonData != null) { + enterType = EnterType.ENTER_TYPE_DUNGEON; + enterReason = EnterReason.DungeonEnter; + } else if (oldScene == newScene) { + enterType = EnterType.ENTER_TYPE_GOTO; + } else if (newScene.getSceneType() == SceneType.SCENE_HOME_WORLD) { + // Home + enterReason = EnterReason.EnterHome; + enterType = EnterType.ENTER_TYPE_SELF_HOME; + } + + // Teleport packet + player.sendPacket( + new PacketPlayerEnterSceneNotify(player, enterType, enterReason, sceneId, teleportTo)); + return true; + } + + private void updatePlayerInfos(Player paramPlayer) { + for (Player player : this.getPlayers()) { + // Dont send packets if player is logging in and filter out joining player + if (!player.hasSentLoginPackets() || player == paramPlayer) { + continue; + } + + // Update team of all players since max players has been changed - Probably not the best way + // to do it + if (this.isMultiplayer()) { + player + .getTeamManager() + .getMpTeam() + .copyFrom( + player.getTeamManager().getMpTeam(), player.getTeamManager().getMaxTeamSize()); + player.getTeamManager().updateTeamEntities(null); + } + + // Dont send packets if player is loading into the scene + if (player.getSceneLoadState().getValue() < SceneLoadState.INIT.getValue()) { + // World player info packets + player.getSession().send(new PacketWorldPlayerInfoNotify(this)); + player.getSession().send(new PacketScenePlayerInfoNotify(this)); + player.getSession().send(new PacketWorldPlayerRTTNotify(this)); + + // Team packets + player.getSession().send(new PacketSyncTeamEntityNotify(player)); + player.getSession().send(new PacketSyncScenePlayTeamEntityNotify(player)); + } + } + } + + public void broadcastPacket(BasePacket packet) { + // Send to all players - might have to check if player has been sent data packets + for (Player player : this.getPlayers()) { + player.getSession().send(packet); + } + } + + // Returns true if the world should be deleted + public boolean onTick() { + if (this.getPlayerCount() == 0) return true; + this.scenes.forEach((k, scene) -> scene.onTick()); + return false; + } + + public void close() {} + + @Override + public Iterator iterator() { + return this.getPlayers().iterator(); + } +} diff --git a/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java b/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java index 428682ecf..28da33333 100644 --- a/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java +++ b/src/main/java/emu/grasscutter/game/world/WorldDataSystem.java @@ -1,147 +1,153 @@ -package emu.grasscutter.game.world; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.InvestigationMonsterData; -import emu.grasscutter.data.excels.RewardPreviewData; -import emu.grasscutter.data.excels.WorldLevelData; -import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler; -import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler; -import emu.grasscutter.game.entity.gadget.chest.NormalChestInteractHandler; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.proto.InvestigationMonsterOuterClass; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.SceneMonster; -import emu.grasscutter.server.game.BaseGameSystem; -import emu.grasscutter.server.game.GameServer; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -public class WorldDataSystem extends BaseGameSystem { - private final Map chestInteractHandlerMap; // chestType-Handler - private final Map sceneInvestigationGroupMap; // - - public WorldDataSystem(GameServer server) { - super(server); - this.chestInteractHandlerMap = new HashMap<>(); - this.sceneInvestigationGroupMap = new ConcurrentHashMap<>(); - - loadChestConfig(); - } - - public synchronized void loadChestConfig() { - // set the special chest first - chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler()); - - try { - DataLoader.loadList("ChestReward.json", ChestReward.class) - .forEach(reward -> - reward.getObjNames().forEach(name -> - chestInteractHandlerMap.computeIfAbsent(name, x -> new NormalChestInteractHandler(reward)))); - } catch (Exception e) { - Grasscutter.getLogger().error("Unable to load chest reward config.", e); - } - } - - public Map getChestInteractHandlerMap() { - return chestInteractHandlerMap; - } - - public RewardPreviewData getRewardByBossId(int monsterId) { - var investigationMonsterData = GameData.getInvestigationMonsterDataMap().values().parallelStream() - .filter(imd -> imd.getMonsterIdList() != null && !imd.getMonsterIdList().isEmpty()) - .filter(imd -> imd.getMonsterIdList().get(0) == monsterId) - .findFirst(); - - if (investigationMonsterData.isEmpty()) { - return null; - } - return GameData.getRewardPreviewDataMap().get(investigationMonsterData.get().getRewardPreviewId()); - } - - private SceneGroup getInvestigationGroup(int sceneId, int groupId) { - var key = sceneId + "_" + groupId; - if (!sceneInvestigationGroupMap.containsKey(key)) { - var group = SceneGroup.of(groupId).load(sceneId); - sceneInvestigationGroupMap.putIfAbsent(key, group); - return group; - } - return sceneInvestigationGroupMap.get(key); - } - - public int getMonsterLevel(SceneMonster monster, World world) { - // Calculate level - int level = monster.level; - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(world.getWorldLevel()); - - if (worldLevelData != null) { - level = worldLevelData.getMonsterLevel(); - } - return level; - } - - private InvestigationMonsterOuterClass.InvestigationMonster getInvestigationMonster(Player player, InvestigationMonsterData imd) { - if (imd.getGroupIdList().isEmpty() || imd.getMonsterIdList().isEmpty()) { - return null; - } - - var groupId = imd.getGroupIdList().get(0); - var monsterId = imd.getMonsterIdList().get(0); - var sceneId = imd.getCityData().getSceneId(); - var group = getInvestigationGroup(sceneId, groupId); - - if (group == null || group.monsters == null) { - return null; - } - - var monster = group.monsters.values().stream() - .filter(x -> x.monster_id == monsterId) - .findFirst(); - if (monster.isEmpty()) { - return null; - } - - var builder = InvestigationMonsterOuterClass.InvestigationMonster.newBuilder(); - - builder.setId(imd.getId()) - .setCityId(imd.getCityId()) - .setSceneId(imd.getCityData().getSceneId()) - .setGroupId(groupId) - .setMonsterId(monsterId) - .setLevel(getMonsterLevel(monster.get(), player.getWorld())) - .setIsAlive(true) - .setNextRefreshTime(Integer.MAX_VALUE) - .setRefreshInterval(Integer.MAX_VALUE) - .setPos(monster.get().pos.toProto()); - - if ("Boss".equals(imd.getMonsterCategory())) { - var bossChest = group.searchBossChestInGroup(); - if (bossChest.isPresent()) { - builder.setResin(bossChest.get().resin); - builder.setMaxBossChestNum(bossChest.get().take_num); - } - } - return builder.build(); - } - - public List getInvestigationMonstersByCityId(Player player, int cityId) { - var cityData = GameData.getCityDataMap().get(cityId); - if (cityData == null) { - Grasscutter.getLogger().warn("City not exist {}", cityId); - return List.of(); - } - - return GameData.getInvestigationMonsterDataMap().values() - .parallelStream() - .filter(imd -> imd.getCityId() == cityId) - .map(imd -> this.getInvestigationMonster(player, imd)) - .filter(Objects::nonNull) - .toList(); - } - -} +package emu.grasscutter.game.world; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.InvestigationMonsterData; +import emu.grasscutter.data.excels.RewardPreviewData; +import emu.grasscutter.data.excels.WorldLevelData; +import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler; +import emu.grasscutter.game.entity.gadget.chest.ChestInteractHandler; +import emu.grasscutter.game.entity.gadget.chest.NormalChestInteractHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.InvestigationMonsterOuterClass; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.SceneMonster; +import emu.grasscutter.server.game.BaseGameSystem; +import emu.grasscutter.server.game.GameServer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +public class WorldDataSystem extends BaseGameSystem { + private final Map chestInteractHandlerMap; // chestType-Handler + private final Map sceneInvestigationGroupMap; // + + public WorldDataSystem(GameServer server) { + super(server); + this.chestInteractHandlerMap = new HashMap<>(); + this.sceneInvestigationGroupMap = new ConcurrentHashMap<>(); + + loadChestConfig(); + } + + public synchronized void loadChestConfig() { + // set the special chest first + chestInteractHandlerMap.put("SceneObj_Chest_Flora", new BossChestInteractHandler()); + + try { + DataLoader.loadList("ChestReward.json", ChestReward.class) + .forEach( + reward -> + reward + .getObjNames() + .forEach( + name -> + chestInteractHandlerMap.computeIfAbsent( + name, x -> new NormalChestInteractHandler(reward)))); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load chest reward config.", e); + } + } + + public Map getChestInteractHandlerMap() { + return chestInteractHandlerMap; + } + + public RewardPreviewData getRewardByBossId(int monsterId) { + var investigationMonsterData = + GameData.getInvestigationMonsterDataMap().values().parallelStream() + .filter(imd -> imd.getMonsterIdList() != null && !imd.getMonsterIdList().isEmpty()) + .filter(imd -> imd.getMonsterIdList().get(0) == monsterId) + .findFirst(); + + if (investigationMonsterData.isEmpty()) { + return null; + } + return GameData.getRewardPreviewDataMap() + .get(investigationMonsterData.get().getRewardPreviewId()); + } + + private SceneGroup getInvestigationGroup(int sceneId, int groupId) { + var key = sceneId + "_" + groupId; + if (!sceneInvestigationGroupMap.containsKey(key)) { + var group = SceneGroup.of(groupId).load(sceneId); + sceneInvestigationGroupMap.putIfAbsent(key, group); + return group; + } + return sceneInvestigationGroupMap.get(key); + } + + public int getMonsterLevel(SceneMonster monster, World world) { + // Calculate level + int level = monster.level; + WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(world.getWorldLevel()); + + if (worldLevelData != null) { + level = worldLevelData.getMonsterLevel(); + } + return level; + } + + private InvestigationMonsterOuterClass.InvestigationMonster getInvestigationMonster( + Player player, InvestigationMonsterData imd) { + if (imd.getGroupIdList().isEmpty() || imd.getMonsterIdList().isEmpty()) { + return null; + } + + var groupId = imd.getGroupIdList().get(0); + var monsterId = imd.getMonsterIdList().get(0); + var sceneId = imd.getCityData().getSceneId(); + var group = getInvestigationGroup(sceneId, groupId); + + if (group == null || group.monsters == null) { + return null; + } + + var monster = + group.monsters.values().stream().filter(x -> x.monster_id == monsterId).findFirst(); + if (monster.isEmpty()) { + return null; + } + + var builder = InvestigationMonsterOuterClass.InvestigationMonster.newBuilder(); + + builder + .setId(imd.getId()) + .setCityId(imd.getCityId()) + .setSceneId(imd.getCityData().getSceneId()) + .setGroupId(groupId) + .setMonsterId(monsterId) + .setLevel(getMonsterLevel(monster.get(), player.getWorld())) + .setIsAlive(true) + .setNextRefreshTime(Integer.MAX_VALUE) + .setRefreshInterval(Integer.MAX_VALUE) + .setPos(monster.get().pos.toProto()); + + if ("Boss".equals(imd.getMonsterCategory())) { + var bossChest = group.searchBossChestInGroup(); + if (bossChest.isPresent()) { + builder.setResin(bossChest.get().resin); + builder.setMaxBossChestNum(bossChest.get().take_num); + } + } + return builder.build(); + } + + public List getInvestigationMonstersByCityId( + Player player, int cityId) { + var cityData = GameData.getCityDataMap().get(cityId); + if (cityData == null) { + Grasscutter.getLogger().warn("City not exist {}", cityId); + return List.of(); + } + + return GameData.getInvestigationMonsterDataMap().values().parallelStream() + .filter(imd -> imd.getCityId() == cityId) + .map(imd -> this.getInvestigationMonster(player, imd)) + .filter(Objects::nonNull) + .toList(); + } +} diff --git a/src/main/java/emu/grasscutter/net/packet/BasePacket.java b/src/main/java/emu/grasscutter/net/packet/BasePacket.java index 63a896721..1442aa45d 100644 --- a/src/main/java/emu/grasscutter/net/packet/BasePacket.java +++ b/src/main/java/emu/grasscutter/net/packet/BasePacket.java @@ -1,138 +1,143 @@ -package emu.grasscutter.net.packet; - -import com.google.protobuf.GeneratedMessageV3; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.utils.Crypto; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -public class BasePacket { - private static final int const1 = 17767; // 0x4567 - private static final int const2 = -30293; // 0x89ab - public boolean shouldEncrypt = true; - private int opcode; - private boolean shouldBuildHeader = false; - private byte[] header; - private byte[] data; - // Encryption - private boolean useDispatchKey; - - public BasePacket(int opcode) { - this.opcode = opcode; - } - - public BasePacket(int opcode, int clientSequence) { - this.opcode = opcode; - this.buildHeader(clientSequence); - } - - public BasePacket(int opcode, boolean buildHeader) { - this.opcode = opcode; - this.shouldBuildHeader = buildHeader; - } - - public int getOpcode() { - return opcode; - } - - public void setOpcode(int opcode) { - this.opcode = opcode; - } - - public boolean useDispatchKey() { - return useDispatchKey; - } - - public void setUseDispatchKey(boolean useDispatchKey) { - this.useDispatchKey = useDispatchKey; - } - - public byte[] getHeader() { - return header; - } - - public void setHeader(byte[] header) { - this.header = header; - } - - public boolean shouldBuildHeader() { - return shouldBuildHeader; - } - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - } - - public void setData(GeneratedMessageV3 proto) { - this.data = proto.toByteArray(); - } - - @SuppressWarnings("rawtypes") - public void setData(GeneratedMessageV3.Builder proto) { - this.data = proto.build().toByteArray(); - } - - public BasePacket buildHeader(int clientSequence) { - if (this.getHeader() != null && clientSequence == 0) { - return this; - } - setHeader(PacketHead.newBuilder().setClientSequenceId(clientSequence).setSentMs(System.currentTimeMillis()).build().toByteArray()); - return this; - } - - public byte[] build() { - if (getHeader() == null) { - this.header = new byte[0]; - } - - if (getData() == null) { - this.data = new byte[0]; - } - - ByteArrayOutputStream baos = new ByteArrayOutputStream(2 + 2 + 2 + 4 + getHeader().length + getData().length + 2); - - this.writeUint16(baos, const1); - this.writeUint16(baos, opcode); - this.writeUint16(baos, header.length); - this.writeUint32(baos, data.length); - this.writeBytes(baos, header); - this.writeBytes(baos, data); - this.writeUint16(baos, const2); - - byte[] packet = baos.toByteArray(); - - if (this.shouldEncrypt) { - Crypto.xor(packet, this.useDispatchKey() ? Crypto.DISPATCH_KEY : Crypto.ENCRYPT_KEY); - } - - return packet; - } - - public void writeUint16(ByteArrayOutputStream baos, int i) { - // Unsigned short - baos.write((byte) ((i >>> 8) & 0xFF)); - baos.write((byte) (i & 0xFF)); - } - - public void writeUint32(ByteArrayOutputStream baos, int i) { - // Unsigned int (long) - baos.write((byte) ((i >>> 24) & 0xFF)); - baos.write((byte) ((i >>> 16) & 0xFF)); - baos.write((byte) ((i >>> 8) & 0xFF)); - baos.write((byte) (i & 0xFF)); - } - - public void writeBytes(ByteArrayOutputStream baos, byte[] bytes) { - try { - baos.write(bytes); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package emu.grasscutter.net.packet; + +import com.google.protobuf.GeneratedMessageV3; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.utils.Crypto; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class BasePacket { + private static final int const1 = 17767; // 0x4567 + private static final int const2 = -30293; // 0x89ab + public boolean shouldEncrypt = true; + private int opcode; + private boolean shouldBuildHeader = false; + private byte[] header; + private byte[] data; + // Encryption + private boolean useDispatchKey; + + public BasePacket(int opcode) { + this.opcode = opcode; + } + + public BasePacket(int opcode, int clientSequence) { + this.opcode = opcode; + this.buildHeader(clientSequence); + } + + public BasePacket(int opcode, boolean buildHeader) { + this.opcode = opcode; + this.shouldBuildHeader = buildHeader; + } + + public int getOpcode() { + return opcode; + } + + public void setOpcode(int opcode) { + this.opcode = opcode; + } + + public boolean useDispatchKey() { + return useDispatchKey; + } + + public void setUseDispatchKey(boolean useDispatchKey) { + this.useDispatchKey = useDispatchKey; + } + + public byte[] getHeader() { + return header; + } + + public void setHeader(byte[] header) { + this.header = header; + } + + public boolean shouldBuildHeader() { + return shouldBuildHeader; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public void setData(GeneratedMessageV3 proto) { + this.data = proto.toByteArray(); + } + + @SuppressWarnings("rawtypes") + public void setData(GeneratedMessageV3.Builder proto) { + this.data = proto.build().toByteArray(); + } + + public BasePacket buildHeader(int clientSequence) { + if (this.getHeader() != null && clientSequence == 0) { + return this; + } + setHeader( + PacketHead.newBuilder() + .setClientSequenceId(clientSequence) + .setSentMs(System.currentTimeMillis()) + .build() + .toByteArray()); + return this; + } + + public byte[] build() { + if (getHeader() == null) { + this.header = new byte[0]; + } + + if (getData() == null) { + this.data = new byte[0]; + } + + ByteArrayOutputStream baos = + new ByteArrayOutputStream(2 + 2 + 2 + 4 + getHeader().length + getData().length + 2); + + this.writeUint16(baos, const1); + this.writeUint16(baos, opcode); + this.writeUint16(baos, header.length); + this.writeUint32(baos, data.length); + this.writeBytes(baos, header); + this.writeBytes(baos, data); + this.writeUint16(baos, const2); + + byte[] packet = baos.toByteArray(); + + if (this.shouldEncrypt) { + Crypto.xor(packet, this.useDispatchKey() ? Crypto.DISPATCH_KEY : Crypto.ENCRYPT_KEY); + } + + return packet; + } + + public void writeUint16(ByteArrayOutputStream baos, int i) { + // Unsigned short + baos.write((byte) ((i >>> 8) & 0xFF)); + baos.write((byte) (i & 0xFF)); + } + + public void writeUint32(ByteArrayOutputStream baos, int i) { + // Unsigned int (long) + baos.write((byte) ((i >>> 24) & 0xFF)); + baos.write((byte) ((i >>> 16) & 0xFF)); + baos.write((byte) ((i >>> 8) & 0xFF)); + baos.write((byte) (i & 0xFF)); + } + + public void writeBytes(ByteArrayOutputStream baos, byte[] bytes) { + try { + baos.write(bytes); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/net/packet/Opcodes.java b/src/main/java/emu/grasscutter/net/packet/Opcodes.java index 221f18520..f4cf605b5 100644 --- a/src/main/java/emu/grasscutter/net/packet/Opcodes.java +++ b/src/main/java/emu/grasscutter/net/packet/Opcodes.java @@ -1,17 +1,13 @@ -package emu.grasscutter.net.packet; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface Opcodes { - /** - * Opcode for the packet/handler - */ - int value(); - - /** - * HANDLER ONLY - will disable this handler from being registered - */ - boolean disabled() default false; -} +package emu.grasscutter.net.packet; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Opcodes { + /** Opcode for the packet/handler */ + int value(); + + /** HANDLER ONLY - will disable this handler from being registered */ + boolean disabled() default false; +} diff --git a/src/main/java/emu/grasscutter/net/packet/PacketHandler.java b/src/main/java/emu/grasscutter/net/packet/PacketHandler.java index f99618ab0..c0306faaa 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketHandler.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketHandler.java @@ -1,9 +1,9 @@ -package emu.grasscutter.net.packet; - -import emu.grasscutter.server.game.GameSession; - -public abstract class PacketHandler { - protected static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - - public abstract void handle(GameSession session, byte[] header, byte[] payload) throws Exception; -} +package emu.grasscutter.net.packet; + +import emu.grasscutter.server.game.GameSession; + +public abstract class PacketHandler { + protected static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + + public abstract void handle(GameSession session, byte[] header, byte[] payload) throws Exception; +} diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java index 16b66ae0f..004b37b21 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java @@ -1,1925 +1,1925 @@ -package emu.grasscutter.net.packet; - -public class PacketOpcodes { - - // Empty - public static final int NONE = 0; - - // Opcodes - public static final int AbilityChangeNotify = 1159; - public static final int AbilityInvocationFailNotify = 1114; - public static final int AbilityInvocationFixedNotify = 1167; - public static final int AbilityInvocationsNotify = 1175; - public static final int AcceptCityReputationRequestReq = 2882; - public static final int AcceptCityReputationRequestRsp = 2865; - public static final int AchievementAllDataNotify = 2698; - public static final int AchievementUpdateNotify = 2693; - public static final int ActivityCoinInfoNotify = 2189; - public static final int ActivityCondStateChangeNotify = 2012; - public static final int ActivityDisableTransferPointInteractionNotify = 8969; - public static final int ActivityInfoNotify = 2134; - public static final int ActivityPlayOpenAnimNotify = 2136; - public static final int ActivitySaleChangeNotify = 2034; - public static final int ActivityScheduleInfoNotify = 2068; - public static final int ActivitySelectAvatarCardReq = 2043; - public static final int ActivitySelectAvatarCardRsp = 2130; - public static final int ActivityTakeAllScoreRewardReq = 8731; - public static final int ActivityTakeAllScoreRewardRsp = 8964; - public static final int ActivityTakeScoreRewardReq = 8869; - public static final int ActivityTakeScoreRewardRsp = 8852; - public static final int ActivityTakeWatcherRewardBatchReq = 2044; - public static final int ActivityTakeWatcherRewardBatchRsp = 2023; - public static final int ActivityTakeWatcherRewardReq = 2063; - public static final int ActivityTakeWatcherRewardRsp = 2082; - public static final int ActivityUpdateWatcherNotify = 2183; - public static final int AddBlacklistReq = 4041; - public static final int AddBlacklistRsp = 4070; - public static final int AddFriendNotify = 4019; - public static final int AddNoGachaAvatarCardNotify = 1787; - public static final int AddQuestContentProgressReq = 434; - public static final int AddQuestContentProgressRsp = 472; - public static final int AddRandTaskInfoNotify = 187; - public static final int AddSeenMonsterNotify = 235; - public static final int AdjustWorldLevelReq = 132; - public static final int AdjustWorldLevelRsp = 131; - public static final int AllCoopInfoNotify = 1998; - public static final int AllMarkPointNotify = 3156; - public static final int AllSeenMonsterNotify = 252; - public static final int AllWidgetDataNotify = 4300; - public static final int AnchorPointDataNotify = 4298; - public static final int AnchorPointOpReq = 4296; - public static final int AnchorPointOpRsp = 4286; - public static final int AnimatorForceSetAirMoveNotify = 337; - public static final int AntiAddictNotify = 103; - public static final int ArenaChallengeFinishNotify = 2169; - public static final int AskAddFriendNotify = 4044; - public static final int AskAddFriendReq = 4014; - public static final int AskAddFriendRsp = 4034; - public static final int AsterLargeInfoNotify = 2059; - public static final int AsterLittleInfoNotify = 2006; - public static final int AsterMidCampInfoNotify = 2142; - public static final int AsterMidInfoNotify = 2118; - public static final int AsterMiscInfoNotify = 2072; - public static final int AsterProgressInfoNotify = 2173; - public static final int AvatarAddNotify = 1756; - public static final int AvatarBuffAddNotify = 341; - public static final int AvatarBuffDelNotify = 370; - public static final int AvatarCardChangeReq = 641; - public static final int AvatarCardChangeRsp = 670; - public static final int AvatarChangeAnimHashReq = 1620; - public static final int AvatarChangeAnimHashRsp = 1694; - public static final int AvatarChangeCostumeNotify = 1759; - public static final int AvatarChangeCostumeReq = 1611; - public static final int AvatarChangeCostumeRsp = 1760; - public static final int AvatarChangeElementTypeReq = 1790; - public static final int AvatarChangeElementTypeRsp = 1781; - public static final int AvatarDataNotify = 1613; - public static final int AvatarDelNotify = 1621; - public static final int AvatarDieAnimationEndReq = 1665; - public static final int AvatarDieAnimationEndRsp = 1795; - public static final int AvatarEnterElementViewNotify = 326; - public static final int AvatarEquipAffixStartNotify = 1666; - public static final int AvatarEquipChangeNotify = 661; - public static final int AvatarExpeditionAllDataReq = 1748; - public static final int AvatarExpeditionAllDataRsp = 1671; - public static final int AvatarExpeditionCallBackReq = 1791; - public static final int AvatarExpeditionCallBackRsp = 1631; - public static final int AvatarExpeditionDataNotify = 1646; - public static final int AvatarExpeditionGetRewardReq = 1641; - public static final int AvatarExpeditionGetRewardRsp = 1707; - public static final int AvatarExpeditionStartReq = 1763; - public static final int AvatarExpeditionStartRsp = 1699; - public static final int AvatarFetterDataNotify = 1648; - public static final int AvatarFetterLevelRewardReq = 1653; - public static final int AvatarFetterLevelRewardRsp = 1691; - public static final int AvatarFightPropNotify = 1214; - public static final int AvatarFightPropUpdateNotify = 1234; - public static final int AvatarFlycloakChangeNotify = 1728; - public static final int AvatarFollowRouteNotify = 3300; - public static final int AvatarGainCostumeNotify = 1701; - public static final int AvatarGainFlycloakNotify = 1793; - public static final int AvatarLifeStateChangeNotify = 1282; - public static final int AvatarPromoteGetRewardReq = 1610; - public static final int AvatarPromoteGetRewardRsp = 1711; - public static final int AvatarPromoteReq = 1799; - public static final int AvatarPromoteRsp = 1681; - public static final int AvatarPropChangeReasonNotify = 1265; - public static final int AvatarPropNotify = 1259; - public static final int AvatarSatiationDataNotify = 1655; - public static final int AvatarSkillChangeNotify = 1042; - public static final int AvatarSkillDepotChangeNotify = 1064; - public static final int AvatarSkillInfoNotify = 1082; - public static final int AvatarSkillMaxChargeCountNotify = 1072; - public static final int AvatarSkillUpgradeReq = 1007; - public static final int AvatarSkillUpgradeRsp = 1091; - public static final int AvatarTeamUpdateNotify = 1744; - public static final int AvatarUnlockTalentNotify = 1054; - public static final int AvatarUpgradeReq = 1764; - public static final int AvatarUpgradeRsp = 1741; - public static final int AvatarWearFlycloakReq = 1700; - public static final int AvatarWearFlycloakRsp = 1745; - public static final int BackMyWorldReq = 280; - public static final int BackMyWorldRsp = 247; - public static final int BargainOfferPriceReq = 474; - public static final int BargainOfferPriceRsp = 446; - public static final int BargainStartNotify = 494; - public static final int BargainTerminateNotify = 484; - public static final int BattlePassAllDataNotify = 2648; - public static final int BattlePassBuySuccNotify = 2617; - public static final int BattlePassCurScheduleUpdateNotify = 2646; - public static final int BattlePassMissionDelNotify = 2609; - public static final int BattlePassMissionUpdateNotify = 2643; - public static final int BeginCameraSceneLookNotify = 260; - public static final int BigTalentPointConvertReq = 1014; - public static final int BigTalentPointConvertRsp = 1034; - public static final int BlessingAcceptAllGivePicReq = 2160; - public static final int BlessingAcceptAllGivePicRsp = 2159; - public static final int BlessingAcceptGivePicReq = 2091; - public static final int BlessingAcceptGivePicRsp = 2187; - public static final int BlessingGetAllRecvPicRecordListReq = 2010; - public static final int BlessingGetAllRecvPicRecordListRsp = 2111; - public static final int BlessingGetFriendPicListReq = 2128; - public static final int BlessingGetFriendPicListRsp = 2193; - public static final int BlessingGiveFriendPicReq = 2066; - public static final int BlessingGiveFriendPicRsp = 2053; - public static final int BlessingRecvFriendPicNotify = 2011; - public static final int BlessingRedeemRewardReq = 2100; - public static final int BlessingRedeemRewardRsp = 2145; - public static final int BlessingScanReq = 2004; - public static final int BlessingScanRsp = 2055; - public static final int BlitzRushParkourRestartReq = 8085; - public static final int BlitzRushParkourRestartRsp = 8538; - public static final int BlossomBriefInfoNotify = 2754; - public static final int BlossomChestCreateNotify = 2734; - public static final int BlossomChestInfoNotify = 882; - public static final int BonusActivityInfoReq = 2591; - public static final int BonusActivityInfoRsp = 2542; - public static final int BonusActivityUpdateNotify = 2507; - public static final int BossChestActivateNotify = 872; - public static final int BounceConjuringSettleNotify = 8434; - public static final int BuoyantCombatSettleNotify = 8387; - public static final int BuyBattlePassLevelReq = 2626; - public static final int BuyBattlePassLevelRsp = 2612; - public static final int BuyGoodsReq = 754; - public static final int BuyGoodsRsp = 764; - public static final int BuyResinReq = 630; - public static final int BuyResinRsp = 687; - public static final int CalcWeaponUpgradeReturnItemsReq = 601; - public static final int CalcWeaponUpgradeReturnItemsRsp = 698; - public static final int CanUseSkillNotify = 1027; - public static final int CancelCityReputationRequestReq = 2850; - public static final int CancelCityReputationRequestRsp = 2859; - public static final int CancelCoopTaskReq = 1976; - public static final int CancelCoopTaskRsp = 1962; - public static final int CancelFinishParentQuestNotify = 402; - public static final int CardProductRewardNotify = 4146; - public static final int ChallengeDataNotify = 923; - public static final int ChallengeRecordNotify = 974; - public static final int ChangeAvatarReq = 1704; - public static final int ChangeAvatarRsp = 1689; - public static final int ChangeGameTimeReq = 165; - public static final int ChangeGameTimeRsp = 150; - public static final int ChangeMailStarNotify = 1491; - public static final int ChangeMpTeamAvatarReq = 1660; - public static final int ChangeMpTeamAvatarRsp = 1747; - public static final int ChangeServerGlobalValueNotify = 46; - public static final int ChangeTeamNameReq = 1692; - public static final int ChangeTeamNameRsp = 1664; - public static final int ChangeWorldToSingleModeNotify = 3025; - public static final int ChangeWorldToSingleModeReq = 3243; - public static final int ChangeWorldToSingleModeRsp = 3271; - public static final int ChannelerSlabCheckEnterLoopDungeonReq = 8678; - public static final int ChannelerSlabCheckEnterLoopDungeonRsp = 8961; - public static final int ChannelerSlabEnterLoopDungeonReq = 8928; - public static final int ChannelerSlabEnterLoopDungeonRsp = 8892; - public static final int ChannelerSlabLoopDungeonChallengeInfoNotify = 8499; - public static final int ChannelerSlabLoopDungeonSelectConditionReq = 8368; - public static final int ChannelerSlabLoopDungeonSelectConditionRsp = 8943; - public static final int ChannelerSlabLoopDungeonTakeFirstPassRewardReq = 8779; - public static final int ChannelerSlabLoopDungeonTakeFirstPassRewardRsp = 8654; - public static final int ChannelerSlabLoopDungeonTakeScoreRewardReq = 8751; - public static final int ChannelerSlabLoopDungeonTakeScoreRewardRsp = 8186; - public static final int ChannelerSlabOneOffDungeonInfoNotify = 8038; - public static final int ChannelerSlabOneOffDungeonInfoReq = 8069; - public static final int ChannelerSlabOneOffDungeonInfoRsp = 8731; - public static final int ChannelerSlabSaveAssistInfoReq = 8304; - public static final int ChannelerSlabSaveAssistInfoRsp = 8443; - public static final int ChannelerSlabStageActiveChallengeIndexNotify = 8647; - public static final int ChannelerSlabStageOneofDungeonNotify = 8203; - public static final int ChannelerSlabTakeoffBuffReq = 8329; - public static final int ChannelerSlabTakeoffBuffRsp = 8646; - public static final int ChannelerSlabWearBuffReq = 8487; - public static final int ChannelerSlabWearBuffRsp = 8651; - public static final int ChapterStateNotify = 427; - public static final int ChatChannelDataNotify = 5041; - public static final int ChatChannelUpdateNotify = 4957; - public static final int ChatHistoryNotify = 3301; - public static final int CheckAddItemExceedLimitNotify = 685; - public static final int CheckSegmentCRCNotify = 56; - public static final int CheckSegmentCRCReq = 23; - public static final int ChessEscapedMonstersNotify = 5389; - public static final int ChessLeftMonstersNotify = 5376; - public static final int ChessManualRefreshCardsReq = 5306; - public static final int ChessManualRefreshCardsRsp = 5390; - public static final int ChessPickCardNotify = 5303; - public static final int ChessPickCardReq = 5301; - public static final int ChessPickCardRsp = 5398; - public static final int ChessPlayerInfoNotify = 5392; - public static final int ChessSelectedCardsNotify = 5385; - public static final int ChooseCurAvatarTeamReq = 1650; - public static final int ChooseCurAvatarTeamRsp = 1625; - public static final int CityReputationDataNotify = 2827; - public static final int CityReputationLevelupNotify = 2814; - public static final int ClearRoguelikeCurseNotify = 8565; - public static final int ClientAIStateNotify = 1129; - public static final int ClientAbilitiesInitFinishCombineNotify = 1172; - public static final int ClientAbilityChangeNotify = 1107; - public static final int ClientAbilityInitBeginNotify = 1154; - public static final int ClientAbilityInitFinishNotify = 1164; - public static final int ClientBulletCreateNotify = 94; - public static final int ClientCollectorDataNotify = 4267; - public static final int ClientHashDebugNotify = 3234; - public static final int ClientLoadingCostumeVerificationNotify = 3387; - public static final int ClientLockGameTimeNotify = 189; - public static final int ClientNewMailNotify = 1450; - public static final int ClientPauseNotify = 276; - public static final int ClientReconnectNotify = 7; - public static final int ClientReportNotify = 29; - public static final int ClientScriptEventNotify = 248; - public static final int ClientTransmitReq = 271; - public static final int ClientTransmitRsp = 202; - public static final int ClientTriggerEventNotify = 191; - public static final int CloseCommonTipsNotify = 3196; - public static final int ClosedItemNotify = 689; - public static final int CodexDataFullNotify = 4203; - public static final int CodexDataUpdateNotify = 4207; - public static final int CombatInvocationsNotify = 387; - public static final int CombineDataNotify = 690; - public static final int CombineFormulaDataNotify = 692; - public static final int CombineReq = 616; - public static final int CombineRsp = 637; - public static final int CommonPlayerTipsNotify = 8076; - public static final int CompoundDataNotify = 118; - public static final int CompoundUnlockNotify = 155; - public static final int CookDataNotify = 157; - public static final int CookGradeDataNotify = 126; - public static final int CookRecipeDataNotify = 186; - public static final int CoopCgShowNotify = 1957; - public static final int CoopCgUpdateNotify = 1989; - public static final int CoopChapterUpdateNotify = 1982; - public static final int CoopDataNotify = 1994; - public static final int CoopPointUpdateNotify = 1951; - public static final int CoopProgressUpdateNotify = 1990; - public static final int CoopRewardUpdateNotify = 1981; - public static final int CreateMassiveEntityNotify = 340; - public static final int CreateMassiveEntityReq = 349; - public static final int CreateMassiveEntityRsp = 397; - public static final int CreateVehicleReq = 874; - public static final int CreateVehicleRsp = 846; - public static final int CutSceneBeginNotify = 295; - public static final int CutSceneEndNotify = 283; - public static final int CutSceneFinishNotify = 228; - public static final int DailyTaskDataNotify = 111; - public static final int DailyTaskFilterCityReq = 199; - public static final int DailyTaskFilterCityRsp = 178; - public static final int DailyTaskProgressNotify = 160; - public static final int DailyTaskScoreRewardNotify = 193; - public static final int DailyTaskUnlockedCitiesNotify = 180; - public static final int DataResVersionNotify = 140; - public static final int DealAddFriendReq = 4072; - public static final int DealAddFriendRsp = 4082; - public static final int DebugNotify = 101; - public static final int DelMailReq = 1434; - public static final int DelMailRsp = 1472; - public static final int DelScenePlayTeamEntityNotify = 3214; - public static final int DelTeamEntityNotify = 330; - public static final int DeleteFriendNotify = 4023; - public static final int DeleteFriendReq = 4059; - public static final int DeleteFriendRsp = 4007; - public static final int DestroyMassiveEntityNotify = 311; - public static final int DestroyMaterialReq = 608; - public static final int DestroyMaterialRsp = 679; - public static final int DigActivityChangeGadgetStateReq = 8140; - public static final int DigActivityChangeGadgetStateRsp = 8656; - public static final int DigActivityMarkPointChangeNotify = 8585; - public static final int DisableRoguelikeTrapNotify = 8007; - public static final int DoGachaReq = 1554; - public static final int DoGachaRsp = 1564; - public static final int DoRoguelikeDungeonCardGachaReq = 8427; - public static final int DoRoguelikeDungeonCardGachaRsp = 8567; - public static final int DoSetPlayerBornDataNotify = 161; - public static final int DraftGuestReplyInviteNotify = 5482; - public static final int DraftGuestReplyInviteReq = 5434; - public static final int DraftGuestReplyInviteRsp = 5472; - public static final int DraftGuestReplyTwiceConfirmNotify = 5442; - public static final int DraftGuestReplyTwiceConfirmReq = 5459; - public static final int DraftGuestReplyTwiceConfirmRsp = 5407; - public static final int DraftInviteResultNotify = 5465; - public static final int DraftOwnerInviteNotify = 5414; - public static final int DraftOwnerStartInviteReq = 5454; - public static final int DraftOwnerStartInviteRsp = 5464; - public static final int DraftOwnerTwiceConfirmNotify = 5450; - public static final int DraftTwiceConfirmResultNotify = 5491; - public static final int DragonSpineChapterFinishNotify = 2182; - public static final int DragonSpineChapterOpenNotify = 2126; - public static final int DragonSpineChapterProgressChangeNotify = 2155; - public static final int DragonSpineCoinChangeNotify = 2076; - public static final int DropHintNotify = 633; - public static final int DropItemReq = 650; - public static final int DropItemRsp = 659; - public static final int DungeonCandidateTeamChangeAvatarReq = 988; - public static final int DungeonCandidateTeamChangeAvatarRsp = 949; - public static final int DungeonCandidateTeamCreateReq = 957; - public static final int DungeonCandidateTeamCreateRsp = 986; - public static final int DungeonCandidateTeamDismissNotify = 913; - public static final int DungeonCandidateTeamInfoNotify = 946; - public static final int DungeonCandidateTeamInviteNotify = 984; - public static final int DungeonCandidateTeamInviteReq = 926; - public static final int DungeonCandidateTeamInviteRsp = 933; - public static final int DungeonCandidateTeamKickReq = 916; - public static final int DungeonCandidateTeamKickRsp = 937; - public static final int DungeonCandidateTeamLeaveReq = 925; - public static final int DungeonCandidateTeamLeaveRsp = 918; - public static final int DungeonCandidateTeamPlayerLeaveNotify = 970; - public static final int DungeonCandidateTeamRefuseNotify = 941; - public static final int DungeonCandidateTeamReplyInviteReq = 958; - public static final int DungeonCandidateTeamReplyInviteRsp = 905; - public static final int DungeonCandidateTeamSetChangingAvatarReq = 979; - public static final int DungeonCandidateTeamSetChangingAvatarRsp = 945; - public static final int DungeonCandidateTeamSetReadyReq = 971; - public static final int DungeonCandidateTeamSetReadyRsp = 902; - public static final int DungeonChallengeBeginNotify = 961; - public static final int DungeonChallengeFinishNotify = 956; - public static final int DungeonDataNotify = 966; - public static final int DungeonDieOptionReq = 907; - public static final int DungeonDieOptionRsp = 991; - public static final int DungeonEntryInfoReq = 967; - public static final int DungeonEntryInfoRsp = 975; - public static final int DungeonEntryToBeExploreNotify = 3313; - public static final int DungeonFollowNotify = 919; - public static final int DungeonGetStatueDropReq = 944; - public static final int DungeonGetStatueDropRsp = 994; - public static final int DungeonInterruptChallengeReq = 993; - public static final int DungeonInterruptChallengeRsp = 930; - public static final int DungeonPlayerDieNotify = 959; - public static final int DungeonPlayerDieReq = 929; - public static final int DungeonPlayerDieRsp = 927; - public static final int DungeonRestartInviteNotify = 904; - public static final int DungeonRestartInviteReplyNotify = 936; - public static final int DungeonRestartInviteReplyReq = 920; - public static final int DungeonRestartInviteReplyRsp = 943; - public static final int DungeonRestartReq = 953; - public static final int DungeonRestartResultNotify = 908; - public static final int DungeonRestartRsp = 938; - public static final int DungeonReviseLevelNotify = 901; - public static final int DungeonSettleNotify = 950; - public static final int DungeonShowReminderNotify = 942; - public static final int DungeonSlipRevivePointActivateReq = 911; - public static final int DungeonSlipRevivePointActivateRsp = 960; - public static final int DungeonWayPointActivateReq = 982; - public static final int DungeonWayPointActivateRsp = 965; - public static final int DungeonWayPointNotify = 972; - public static final int EchoNotify = 44; - public static final int EchoShellTakeRewardReq = 8078; - public static final int EchoShellTakeRewardRsp = 8523; - public static final int EchoShellUpdateNotify = 8377; - public static final int EffigyChallengeInfoNotify = 2038; - public static final int EffigyChallengeResultNotify = 2028; - public static final int EndCameraSceneLookNotify = 293; - public static final int EnterChessDungeonReq = 8341; - public static final int EnterChessDungeonRsp = 8947; - public static final int EnterFishingReq = 5848; - public static final int EnterFishingRsp = 5843; - public static final int EnterMechanicusDungeonReq = 3959; - public static final int EnterMechanicusDungeonRsp = 3907; - public static final int EnterRoguelikeDungeonNotify = 8557; - public static final int EnterSceneDoneReq = 269; - public static final int EnterSceneDoneRsp = 281; - public static final int EnterScenePeerNotify = 215; - public static final int EnterSceneReadyReq = 300; - public static final int EnterSceneReadyRsp = 239; - public static final int EnterSceneWeatherAreaNotify = 288; - public static final int EnterTransPointRegionNotify = 227; - public static final int EnterTrialAvatarActivityDungeonReq = 2084; - public static final int EnterTrialAvatarActivityDungeonRsp = 2154; - public static final int EnterWorldAreaReq = 233; - public static final int EnterWorldAreaRsp = 216; - public static final int EntityAiKillSelfNotify = 308; - public static final int EntityAiSyncNotify = 320; - public static final int EntityAuthorityChangeNotify = 384; - public static final int EntityConfigHashNotify = 3103; - public static final int EntityFightPropChangeReasonNotify = 1272; - public static final int EntityFightPropNotify = 1254; - public static final int EntityFightPropUpdateNotify = 1264; - public static final int EntityForceSyncReq = 237; - public static final int EntityForceSyncRsp = 225; - public static final int EntityJumpNotify = 219; - public static final int EntityMoveRoomNotify = 3060; - public static final int EntityPropNotify = 1267; - public static final int EntityTagChangeNotify = 3428; - public static final int EquipRoguelikeRuneReq = 8526; - public static final int EquipRoguelikeRuneRsp = 8572; - public static final int EvtAiSyncCombatThreatInfoNotify = 338; - public static final int EvtAiSyncSkillCdNotify = 325; - public static final int EvtAnimatorParameterNotify = 375; - public static final int EvtAnimatorStateChangedNotify = 359; - public static final int EvtAvatarEnterFocusNotify = 394; - public static final int EvtAvatarExitFocusNotify = 374; - public static final int EvtAvatarLockChairReq = 379; - public static final int EvtAvatarLockChairRsp = 345; - public static final int EvtAvatarSitDownNotify = 302; - public static final int EvtAvatarStandUpNotify = 388; - public static final int EvtAvatarUpdateFocusNotify = 346; - public static final int EvtBeingHitNotify = 367; - public static final int EvtBeingHitsCombineNotify = 318; - public static final int EvtBulletDeactiveNotify = 342; - public static final int EvtBulletHitNotify = 391; - public static final int EvtBulletMoveNotify = 344; - public static final int EvtCostStaminaNotify = 365; - public static final int EvtCreateGadgetNotify = 314; - public static final int EvtDestroyGadgetNotify = 334; - public static final int EvtDestroyServerGadgetNotify = 336; - public static final int EvtDoSkillSuccNotify = 364; - public static final int EvtEntityRenderersChangedNotify = 316; - public static final int EvtEntityStartDieEndNotify = 329; - public static final int EvtFaceToDirNotify = 382; - public static final int EvtFaceToEntityNotify = 372; - public static final int EvtRushMoveNotify = 307; - public static final int EvtSetAttackTargetNotify = 350; - public static final int ExecuteGadgetLuaReq = 217; - public static final int ExecuteGadgetLuaRsp = 224; - public static final int ExecuteGroupTriggerReq = 204; - public static final int ExecuteGroupTriggerRsp = 220; - public static final int ExitFishingReq = 5817; - public static final int ExitFishingRsp = 5826; - public static final int ExitSceneWeatherAreaNotify = 249; - public static final int ExitTransPointRegionNotify = 266; - public static final int ExpeditionChallengeEnterRegionNotify = 2077; - public static final int ExpeditionChallengeFinishedNotify = 2075; - public static final int ExpeditionRecallReq = 2008; - public static final int ExpeditionRecallRsp = 2015; - public static final int ExpeditionStartReq = 2002; - public static final int ExpeditionStartRsp = 2177; - public static final int ExpeditionTakeRewardReq = 2129; - public static final int ExpeditionTakeRewardRsp = 2158; - public static final int FindHilichurlAcceptQuestNotify = 8170; - public static final int FindHilichurlFinishSecondQuestNotify = 8326; - public static final int FinishDeliveryNotify = 2110; - public static final int FinishMainCoopReq = 1986; - public static final int FinishMainCoopRsp = 1965; - public static final int FinishedParentQuestNotify = 464; - public static final int FinishedParentQuestUpdateNotify = 414; - public static final int FireworkNotify = 5934; - public static final int FireworkReq = 6068; - public static final int FireworkRsp = 5918; - public static final int FireworkSetNotify = 6079; - public static final int FireworkSetReq = 6099; - public static final int FireworkSetRsp = 5969; - public static final int FishAttractNotify = 5812; - public static final int FishBaitGoneNotify = 5825; - public static final int FishBattleBeginReq = 5835; - public static final int FishBattleBeginRsp = 5821; - public static final int FishBattleEndReq = 5801; - public static final int FishBattleEndRsp = 5802; - public static final int FishBiteReq = 5839; - public static final int FishBiteRsp = 5831; - public static final int FishCastRodReq = 5836; - public static final int FishCastRodRsp = 5815; - public static final int FishChosenNotify = 5844; - public static final int FishEscapeNotify = 5832; - public static final int FishPoolDataNotify = 5840; - public static final int FishingGallerySettleNotify = 8594; - public static final int FleurFairBalloonSettleNotify = 2200; - public static final int FleurFairBuffEnergyNotify = 5302; - public static final int FleurFairFallSettleNotify = 2027; - public static final int FleurFairFinishGalleryStageNotify = 5349; - public static final int FleurFairMusicGameSettleReq = 2086; - public static final int FleurFairMusicGameSettleRsp = 2033; - public static final int FleurFairMusicGameStartReq = 2150; - public static final int FleurFairMusicGameStartRsp = 2174; - public static final int FleurFairReplayMiniGameReq = 2165; - public static final int FleurFairReplayMiniGameRsp = 2192; - public static final int FleurFairStageSettleNotify = 5388; - public static final int FlightActivityRestartReq = 2039; - public static final int FlightActivityRestartRsp = 2093; - public static final int FlightActivitySettleNotify = 2115; - public static final int FocusAvatarReq = 1712; - public static final int FocusAvatarRsp = 1604; - public static final int ForceAddPlayerFriendReq = 4004; - public static final int ForceAddPlayerFriendRsp = 4020; - public static final int ForceDragAvatarNotify = 3017; - public static final int ForceDragBackTransferNotify = 3245; - public static final int ForgeDataNotify = 603; - public static final int ForgeFormulaDataNotify = 606; - public static final int ForgeGetQueueDataReq = 618; - public static final int ForgeGetQueueDataRsp = 658; - public static final int ForgeQueueDataNotify = 625; - public static final int ForgeQueueManipulateReq = 602; - public static final int ForgeQueueManipulateRsp = 688; - public static final int ForgeStartReq = 605; - public static final int ForgeStartRsp = 671; - public static final int FoundationNotify = 861; - public static final int FoundationReq = 827; - public static final int FoundationRsp = 866; - public static final int FriendInfoChangeNotify = 4092; - public static final int FunitureMakeMakeInfoChangeNotify = 4588; - public static final int FurnitureCurModuleArrangeCountNotify = 4864; - public static final int FurnitureMakeBeHelpedNotify = 4694; - public static final int FurnitureMakeCancelReq = 4619; - public static final int FurnitureMakeCancelRsp = 4825; - public static final int FurnitureMakeFinishNotify = 4658; - public static final int FurnitureMakeHelpReq = 4851; - public static final int FurnitureMakeHelpRsp = 4841; - public static final int FurnitureMakeReq = 4681; - public static final int FurnitureMakeRsp = 4506; - public static final int FurnitureMakeStartReq = 4552; - public static final int FurnitureMakeStartRsp = 4487; - public static final int GMShowNavMeshReq = 2304; - public static final int GMShowNavMeshRsp = 2320; - public static final int GMShowObstacleReq = 2353; - public static final int GMShowObstacleRsp = 2338; - public static final int GachaOpenWishNotify = 1572; - public static final int GachaSimpleInfoNotify = 1582; - public static final int GachaWishReq = 1514; - public static final int GachaWishRsp = 1534; - public static final int GadgetAutoPickDropInfoNotify = 842; - public static final int GadgetChainLevelChangeNotify = 819; - public static final int GadgetChainLevelUpdateNotify = 823; - public static final int GadgetCustomTreeInfoNotify = 833; - public static final int GadgetGeneralRewardInfoNotify = 891; - public static final int GadgetInteractReq = 867; - public static final int GadgetInteractRsp = 875; - public static final int GadgetPlayDataNotify = 859; - public static final int GadgetPlayStartNotify = 865; - public static final int GadgetPlayStopNotify = 850; - public static final int GadgetPlayUidOpNotify = 807; - public static final int GadgetStateNotify = 854; - public static final int GadgetTalkChangeNotify = 856; - public static final int GalleryBalloonScoreNotify = 5554; - public static final int GalleryBalloonShootNotify = 5575; - public static final int GalleryBounceConjuringHitNotify = 5527; - public static final int GalleryBrokenFloorFallNotify = 5507; - public static final int GalleryBulletHitNotify = 5559; - public static final int GalleryFallCatchNotify = 5514; - public static final int GalleryFallScoreNotify = 5534; - public static final int GalleryFlowerCatchNotify = 5565; - public static final int GalleryPreStartNotify = 5550; - public static final int GalleryStartNotify = 5567; - public static final int GalleryStopNotify = 5564; - public static final int GallerySumoKillMonsterNotify = 5566; - public static final int GetActivityInfoReq = 2116; - public static final int GetActivityInfoRsp = 2140; - public static final int GetActivityScheduleReq = 2153; - public static final int GetActivityScheduleRsp = 2032; - public static final int GetActivityShopSheetInfoReq = 772; - public static final int GetActivityShopSheetInfoRsp = 782; - public static final int GetAllActivatedBargainDataReq = 413; - public static final int GetAllActivatedBargainDataRsp = 457; - public static final int GetAllH5ActivityInfoReq = 5693; - public static final int GetAllH5ActivityInfoRsp = 5698; - public static final int GetAllMailReq = 1459; - public static final int GetAllMailRsp = 1407; - public static final int GetAllSceneGalleryInfoReq = 5572; - public static final int GetAllSceneGalleryInfoRsp = 5582; - public static final int GetAllUnlockNameCardReq = 4046; - public static final int GetAllUnlockNameCardRsp = 4084; - public static final int GetAreaExplorePointReq = 258; - public static final int GetAreaExplorePointRsp = 205; - public static final int GetAuthSalesmanInfoReq = 2139; - public static final int GetAuthSalesmanInfoRsp = 2123; - public static final int GetAuthkeyReq = 1482; - public static final int GetAuthkeyRsp = 1465; - public static final int GetBargainDataReq = 441; - public static final int GetBargainDataRsp = 470; - public static final int GetBattlePassProductReq = 2639; - public static final int GetBattlePassProductRsp = 2631; - public static final int GetBlossomBriefInfoListReq = 2767; - public static final int GetBlossomBriefInfoListRsp = 2775; - public static final int GetBonusActivityRewardReq = 2529; - public static final int GetBonusActivityRewardRsp = 2527; - public static final int GetChatEmojiCollectionReq = 4021; - public static final int GetChatEmojiCollectionRsp = 4001; - public static final int GetCityHuntingOfferReq = 4309; - public static final int GetCityHuntingOfferRsp = 4346; - public static final int GetCityReputationInfoReq = 2867; - public static final int GetCityReputationInfoRsp = 2875; - public static final int GetCityReputationMapInfoReq = 2807; - public static final int GetCityReputationMapInfoRsp = 2891; - public static final int GetCompoundDataReq = 158; - public static final int GetCompoundDataRsp = 105; - public static final int GetDailyDungeonEntryInfoReq = 997; - public static final int GetDailyDungeonEntryInfoRsp = 940; - public static final int GetDungeonEntryExploreConditionReq = 3449; - public static final int GetDungeonEntryExploreConditionRsp = 3413; - public static final int GetExpeditionAssistInfoListReq = 2180; - public static final int GetExpeditionAssistInfoListRsp = 2197; - public static final int GetFriendShowAvatarInfoReq = 4060; - public static final int GetFriendShowAvatarInfoRsp = 4093; - public static final int GetFriendShowNameCardInfoReq = 4053; - public static final int GetFriendShowNameCardInfoRsp = 4038; - public static final int GetFurnitureCurModuleArrangeCountReq = 4899; - public static final int GetGachaInfoReq = 1567; - public static final int GetGachaInfoRsp = 1575; - public static final int GetHomeLevelUpRewardReq = 4821; - public static final int GetHomeLevelUpRewardRsp = 4585; - public static final int GetHuntingOfferRewardReq = 4336; - public static final int GetHuntingOfferRewardRsp = 4315; - public static final int GetInvestigationMonsterReq = 1909; - public static final int GetInvestigationMonsterRsp = 1923; - public static final int GetMailItemReq = 1464; - public static final int GetMailItemRsp = 1414; - public static final int GetMapAreaReq = 3084; - public static final int GetMapAreaRsp = 3458; - public static final int GetMapMarkTipsReq = 3342; - public static final int GetMapMarkTipsRsp = 3465; - public static final int GetMechanicusInfoReq = 3967; - public static final int GetMechanicusInfoRsp = 3975; - public static final int GetNextResourceInfoReq = 185; - public static final int GetNextResourceInfoRsp = 173; - public static final int GetOnlinePlayerInfoReq = 66; - public static final int GetOnlinePlayerInfoRsp = 61; - public static final int GetOnlinePlayerListReq = 82; - public static final int GetOnlinePlayerListRsp = 65; - public static final int GetOpActivityInfoReq = 5167; - public static final int GetOpActivityInfoRsp = 5175; - public static final int GetPlayerAskFriendListReq = 4079; - public static final int GetPlayerAskFriendListRsp = 4045; - public static final int GetPlayerBlacklistReq = 4005; - public static final int GetPlayerBlacklistRsp = 4071; - public static final int GetPlayerFriendListReq = 4067; - public static final int GetPlayerFriendListRsp = 4075; - public static final int GetPlayerHomeCompInfoReq = 4511; - public static final int GetPlayerMpModeAvailabilityReq = 1839; - public static final int GetPlayerMpModeAvailabilityRsp = 1831; - public static final int GetPlayerSocialDetailReq = 4065; - public static final int GetPlayerSocialDetailRsp = 4050; - public static final int GetPlayerTokenReq = 167; - public static final int GetPlayerTokenRsp = 175; - public static final int GetPushTipsRewardReq = 2246; - public static final int GetPushTipsRewardRsp = 2284; - public static final int GetQuestTalkHistoryReq = 482; - public static final int GetQuestTalkHistoryRsp = 465; - public static final int GetRecentMpPlayerListReq = 4026; - public static final int GetRecentMpPlayerListRsp = 4033; - public static final int GetRegionSearchReq = 5636; - public static final int GetReunionMissionInfoReq = 5089; - public static final int GetReunionMissionInfoRsp = 5081; - public static final int GetReunionPrivilegeInfoReq = 5076; - public static final int GetReunionPrivilegeInfoRsp = 5062; - public static final int GetReunionSignInInfoReq = 5086; - public static final int GetReunionSignInInfoRsp = 5065; - public static final int GetSceneAreaReq = 244; - public static final int GetSceneAreaRsp = 294; - public static final int GetSceneNpcPositionReq = 564; - public static final int GetSceneNpcPositionRsp = 514; - public static final int GetScenePerformanceReq = 3283; - public static final int GetScenePerformanceRsp = 3274; - public static final int GetScenePointReq = 242; - public static final int GetScenePointRsp = 229; - public static final int GetShopReq = 767; - public static final int GetShopRsp = 775; - public static final int GetShopmallDataReq = 714; - public static final int GetShopmallDataRsp = 734; - public static final int GetSignInRewardReq = 2514; - public static final int GetSignInRewardRsp = 2534; - public static final int GetWidgetSlotReq = 4255; - public static final int GetWidgetSlotRsp = 4266; - public static final int GetWorldMpInfoReq = 3479; - public static final int GetWorldMpInfoRsp = 3118; - public static final int GiveUpRoguelikeDungeonCardReq = 8292; - public static final int GiveUpRoguelikeDungeonCardRsp = 8752; - public static final int GivingRecordChangeNotify = 136; - public static final int GivingRecordNotify = 143; - public static final int GmTalkNotify = 84; - public static final int GmTalkReq = 75; - public static final int GmTalkRsp = 54; - public static final int GrantRewardNotify = 613; - public static final int GroupLinkAllNotify = 5798; - public static final int GroupLinkChangeNotify = 5793; - public static final int GroupLinkDeleteNotify = 5759; - public static final int GroupSuiteNotify = 3263; - public static final int GroupUnloadNotify = 3167; - public static final int GuestBeginEnterSceneNotify = 3195; - public static final int GuestPostEnterSceneNotify = 3012; - public static final int H5ActivityIdsNotify = 5659; - public static final int HideAndSeekPlayerReadyNotify = 5330; - public static final int HideAndSeekPlayerSetAvatarNotify = 5387; - public static final int HideAndSeekSelectAvatarReq = 5397; - public static final int HideAndSeekSelectAvatarRsp = 5340; - public static final int HideAndSeekSelectSkillReq = 8896; - public static final int HideAndSeekSelectSkillRsp = 8715; - public static final int HideAndSeekSetReadyReq = 5311; - public static final int HideAndSeekSetReadyRsp = 5360; - public static final int HideAndSeekSettleNotify = 5393; - public static final int HitClientTrivialNotify = 278; - public static final int HitTreeNotify = 3299; - public static final int HomeAvatarAllFinishRewardNotify = 4504; - public static final int HomeAvatarCostumeChangeNotify = 4651; - public static final int HomeAvatarRewardEventGetReq = 4859; - public static final int HomeAvatarRewardEventGetRsp = 4784; - public static final int HomeAvatarRewardEventNotify = 4682; - public static final int HomeAvatarSummonAllEventNotify = 4892; - public static final int HomeAvatarSummonEventReq = 4708; - public static final int HomeAvatarSummonEventRsp = 4633; - public static final int HomeAvatarSummonFinishReq = 4510; - public static final int HomeAvatarSummonFinishRsp = 4566; - public static final int HomeAvatarTalkFinishInfoNotify = 4517; - public static final int HomeAvatarTalkReq = 4603; - public static final int HomeAvatarTalkRsp = 4484; - public static final int HomeAvtarAllFinishRewardNotify = 4480; - public static final int HomeBasicInfoNotify = 4501; - public static final int HomeBlockNotify = 4857; - public static final int HomeChangeEditModeReq = 4533; - public static final int HomeChangeEditModeRsp = 4862; - public static final int HomeChangeModuleReq = 4789; - public static final int HomeChangeModuleRsp = 4876; - public static final int HomeChooseModuleReq = 4843; - public static final int HomeChooseModuleRsp = 4736; - public static final int HomeComfortInfoNotify = 4816; - public static final int HomeCustomFurnitureInfoNotify = 4647; - public static final int HomeEditCustomFurnitureReq = 4558; - public static final int HomeEditCustomFurnitureRsp = 4749; - public static final int HomeFishFarmingInfoNotify = 4807; - public static final int HomeGetArrangementInfoReq = 4538; - public static final int HomeGetArrangementInfoRsp = 4704; - public static final int HomeGetBasicInfoReq = 4817; - public static final int HomeGetFishFarmingInfoReq = 4575; - public static final int HomeGetFishFarmingInfoRsp = 4849; - public static final int HomeGetOnlineStatusReq = 4589; - public static final int HomeGetOnlineStatusRsp = 4642; - public static final int HomeKickPlayerReq = 4610; - public static final int HomeKickPlayerRsp = 4889; - public static final int HomeLimitedShopBuyGoodsReq = 4471; - public static final int HomeLimitedShopBuyGoodsRsp = 4883; - public static final int HomeLimitedShopGoodsListReq = 4769; - public static final int HomeLimitedShopGoodsListRsp = 4451; - public static final int HomeLimitedShopInfoChangeNotify = 4722; - public static final int HomeLimitedShopInfoNotify = 4584; - public static final int HomeLimitedShopInfoReq = 4476; - public static final int HomeLimitedShopInfoRsp = 4791; - public static final int HomeMarkPointNotify = 4697; - public static final int HomeModuleSeenReq = 4672; - public static final int HomeModuleSeenRsp = 4507; - public static final int HomeModuleUnlockNotify = 4700; - public static final int HomePlantFieldNotify = 4710; - public static final int HomePlantInfoNotify = 4545; - public static final int HomePlantInfoReq = 4645; - public static final int HomePlantInfoRsp = 4848; - public static final int HomePlantSeedReq = 4607; - public static final int HomePlantSeedRsp = 4546; - public static final int HomePlantWeedReq = 4614; - public static final int HomePlantWeedRsp = 4671; - public static final int HomePriorCheckNotify = 4872; - public static final int HomeResourceNotify = 4753; - public static final int HomeResourceTakeFetterExpReq = 4534; - public static final int HomeResourceTakeFetterExpRsp = 4808; - public static final int HomeResourceTakeHomeCoinReq = 4688; - public static final int HomeResourceTakeHomeCoinRsp = 4554; - public static final int HomeSceneInitFinishReq = 4900; - public static final int HomeSceneInitFinishRsp = 4780; - public static final int HomeSceneJumpReq = 4665; - public static final int HomeSceneJumpRsp = 4482; - public static final int HomeTransferReq = 4537; - public static final int HomeTransferRsp = 4623; - public static final int HomeUpdateArrangementInfoReq = 4840; - public static final int HomeUpdateArrangementInfoRsp = 4776; - public static final int HomeUpdateFishFarmingInfoReq = 4746; - public static final int HomeUpdateFishFarmingInfoRsp = 4551; - public static final int HostPlayerNotify = 354; - public static final int HuntingFailNotify = 4335; - public static final int HuntingGiveUpReq = 4301; - public static final int HuntingGiveUpRsp = 4302; - public static final int HuntingOngoingNotify = 4321; - public static final int HuntingRevealClueNotify = 4332; - public static final int HuntingRevealFinalNotify = 4339; - public static final int HuntingStartNotify = 4344; - public static final int HuntingSuccessNotify = 4331; - public static final int InBattleMechanicusBuildingPointsNotify = 5372; - public static final int InBattleMechanicusCardResultNotify = 5342; - public static final int InBattleMechanicusConfirmCardNotify = 5391; - public static final int InBattleMechanicusConfirmCardReq = 5359; - public static final int InBattleMechanicusConfirmCardRsp = 5307; - public static final int InBattleMechanicusEscapeMonsterNotify = 5320; - public static final int InBattleMechanicusLeftMonsterNotify = 5334; - public static final int InBattleMechanicusPickCardNotify = 5350; - public static final int InBattleMechanicusPickCardReq = 5382; - public static final int InBattleMechanicusPickCardRsp = 5365; - public static final int InBattleMechanicusSettleNotify = 5327; - public static final int InteractDailyDungeonInfoNotify = 987; - public static final int InterruptGalleryReq = 5591; - public static final int InterruptGalleryRsp = 5542; - public static final int InvestigationMonsterUpdateNotify = 1920; - public static final int ItemAddHintNotify = 614; - public static final int ItemCdGroupTimeNotify = 626; - public static final int ItemGivingReq = 108; - public static final int ItemGivingRsp = 179; - public static final int JoinHomeWorldFailNotify = 4847; - public static final int JoinPlayerFailNotify = 251; - public static final int JoinPlayerSceneReq = 285; - public static final int JoinPlayerSceneRsp = 273; - public static final int KeepAliveNotify = 67; - public static final int LeaveSceneReq = 275; - public static final int LeaveSceneRsp = 254; - public static final int LeaveWorldNotify = 3009; - public static final int LevelupCityReq = 243; - public static final int LevelupCityRsp = 236; - public static final int LifeStateChangeNotify = 1275; - public static final int LiveEndNotify = 886; - public static final int LiveStartNotify = 870; - public static final int LoadActivityTerrainNotify = 2146; - public static final int LuaEnvironmentEffectNotify = 3136; - public static final int LuaSetOptionNotify = 343; - public static final int LunaRiteAreaFinishNotify = 8956; - public static final int LunaRiteGroupBundleRegisterNotify = 8279; - public static final int LunaRiteHintPointRemoveNotify = 8793; - public static final int LunaRiteHintPointReq = 8114; - public static final int LunaRiteHintPointRsp = 8873; - public static final int LunaRiteSacrificeReq = 8182; - public static final int LunaRiteSacrificeRsp = 8159; - public static final int LunaRiteTakeSacrificeRewardReq = 8999; - public static final int LunaRiteTakeSacrificeRewardRsp = 8156; - public static final int MailChangeNotify = 1475; - public static final int MainCoopUpdateNotify = 1993; - public static final int MapAreaChangeNotify = 3284; - public static final int MarkEntityInMinMapNotify = 230; - public static final int MarkMapReq = 3087; - public static final int MarkMapRsp = 3193; - public static final int MarkNewNotify = 1207; - public static final int MarkTargetInvestigationMonsterNotify = 1916; - public static final int MassiveEntityElementOpBatchNotify = 304; - public static final int MassiveEntityStateChangedNotify = 360; - public static final int MaterialDeleteReturnNotify = 653; - public static final int MaterialDeleteUpdateNotify = 620; - public static final int McoinExchangeHcoinReq = 643; - public static final int McoinExchangeHcoinRsp = 636; - public static final int MechanicusCandidateTeamCreateReq = 3929; - public static final int MechanicusCandidateTeamCreateRsp = 3927; - public static final int MechanicusCloseNotify = 3934; - public static final int MechanicusCoinNotify = 3964; - public static final int MechanicusLevelupGearReq = 3965; - public static final int MechanicusLevelupGearRsp = 3950; - public static final int MechanicusOpenNotify = 3914; - public static final int MechanicusSequenceOpenNotify = 3954; - public static final int MechanicusUnlockGearReq = 3972; - public static final int MechanicusUnlockGearRsp = 3982; - public static final int MeetNpcReq = 572; - public static final int MeetNpcRsp = 582; - public static final int MetNpcIdListNotify = 534; - public static final int MiracleRingDataNotify = 5209; - public static final int MiracleRingDeliverItemReq = 5244; - public static final int MiracleRingDeliverItemRsp = 5232; - public static final int MiracleRingDestroyNotify = 5239; - public static final int MiracleRingDropResultNotify = 5215; - public static final int MiracleRingTakeRewardReq = 5246; - public static final int MiracleRingTakeRewardRsp = 5236; - public static final int MistTrialDunegonFailNotify = 8765; - public static final int MistTrialGetChallengeMissionReq = 8002; - public static final int MistTrialGetChallengeMissionRsp = 8558; - public static final int MistTrialSelectAvatarAndEnterDungeonReq = 8641; - public static final int MistTrialSelectAvatarAndEnterDungeonRsp = 8060; - public static final int MonsterAIConfigHashNotify = 3379; - public static final int MonsterAlertChangeNotify = 313; - public static final int MonsterForceAlertNotify = 357; - public static final int MonsterPointArrayRouteUpdateNotify = 3498; - public static final int MonsterSummonTagNotify = 1367; - public static final int MpBlockNotify = 1837; - public static final int MpPlayGuestReplyInviteReq = 1840; - public static final int MpPlayGuestReplyInviteRsp = 1822; - public static final int MpPlayGuestReplyNotify = 1810; - public static final int MpPlayInviteResultNotify = 1828; - public static final int MpPlayOwnerCheckReq = 1817; - public static final int MpPlayOwnerCheckRsp = 1826; - public static final int MpPlayOwnerInviteNotify = 1838; - public static final int MpPlayOwnerStartInviteReq = 1812; - public static final int MpPlayOwnerStartInviteRsp = 1825; - public static final int MpPlayPrepareInterruptNotify = 1818; - public static final int MpPlayPrepareNotify = 1807; - public static final int MultistagePlayEndNotify = 5312; - public static final int MultistagePlayFinishStageReq = 5375; - public static final int MultistagePlayFinishStageRsp = 5329; - public static final int MultistagePlayInfoNotify = 5367; - public static final int MultistagePlaySettleNotify = 5348; - public static final int MultistagePlayStageEndNotify = 5322; - public static final int GetUgcRsp = 6343; - public static final int MusicGameGetBeatmapRsp = 6309; - public static final int MusicGameSettleReq = 8278; - public static final int MusicGameSettleRsp = 8542; - public static final int MusicGameStartReq = 8103; - public static final int MusicGameStartRsp = 8334; - public static final int MusicGameCreateBeatmapRsp = 6347; - public static final int GetUgcReq = 6348; - public static final int MusicGameSearchBeatmapRsp = 6304; - public static final int MusicGameSearchBeatmapReq = 6343; - public static final int MusicGameStartToPlayOthersBeatmapReq = 6302; - public static final int MusicGameStartToPlayOthersBeatmapRsp = 6313; - public static final int NavMeshStatsNotify = 2343; - public static final int NormalUidOpNotify = 5748; - public static final int NpcTalkReq = 567; - public static final int NpcTalkRsp = 575; - public static final int ObstacleModifyNotify = 2354; - public static final int OfferingInteractReq = 2901; - public static final int OfferingInteractRsp = 2913; - public static final int OneofGatherPointDetectorDataNotify = 4297; - public static final int OpActivityDataNotify = 5154; - public static final int OpActivityStateNotify = 2567; - public static final int OpActivityUpdateNotify = 5164; - public static final int OpenBlossomCircleCampGuideNotify = 2772; - public static final int OpenStateChangeNotify = 146; - public static final int OpenStateUpdateNotify = 174; - public static final int OrderDisplayNotify = 4115; - public static final int OrderFinishNotify = 4109; - public static final int OtherPlayerEnterHomeNotify = 4771; - public static final int PSNBlackListNotify = 4008; - public static final int PSNFriendListNotify = 4036; - public static final int PSPlayerApplyEnterMpReq = 1801; - public static final int PSPlayerApplyEnterMpRsp = 1802; - public static final int PathfindingEnterSceneReq = 2314; - public static final int PathfindingEnterSceneRsp = 2334; - public static final int PathfindingPingNotify = 2364; - public static final int PersonalLineAllDataReq = 437; - public static final int PersonalLineAllDataRsp = 425; - public static final int PersonalLineNewUnlockNotify = 449; - public static final int PersonalSceneJumpReq = 298; - public static final int PersonalSceneJumpRsp = 203; - public static final int PingReq = 14; - public static final int PingRsp = 34; - public static final int PlantFlowerAcceptAllGiveFlowerReq = 8807; - public static final int PlantFlowerAcceptAllGiveFlowerRsp = 8040; - public static final int PlantFlowerAcceptGiveFlowerReq = 8989; - public static final int PlantFlowerAcceptGiveFlowerRsp = 8343; - public static final int PlantFlowerEditFlowerCombinationReq = 8301; - public static final int PlantFlowerEditFlowerCombinationRsp = 8975; - public static final int PlantFlowerGetCanGiveFriendFlowerReq = 8510; - public static final int PlantFlowerGetCanGiveFriendFlowerRsp = 8692; - public static final int PlantFlowerGetFriendFlowerWishListReq = 8828; - public static final int PlantFlowerGetFriendFlowerWishListRsp = 8375; - public static final int PlantFlowerGetRecvFlowerListReq = 8123; - public static final int PlantFlowerGetRecvFlowerListRsp = 8779; - public static final int PlantFlowerGetSeedInfoReq = 8055; - public static final int PlantFlowerGetSeedInfoRsp = 8797; - public static final int PlantFlowerGiveFriendFlowerReq = 8593; - public static final int PlantFlowerGiveFriendFlowerRsp = 8688; - public static final int PlantFlowerHaveRecvFlowerNotify = 8729; - public static final int PlantFlowerSetFlowerWishReq = 8997; - public static final int PlantFlowerSetFlowerWishRsp = 8034; - public static final int PlantFlowerTakeSeedRewardReq = 8851; - public static final int PlantFlowerTakeSeedRewardRsp = 8340; - public static final int PlatformChangeRouteNotify = 221; - public static final int PlatformStartRouteNotify = 279; - public static final int PlatformStopRouteNotify = 245; - public static final int PlayerAllowEnterMpAfterAgreeMatchNotify = 4181; - public static final int PlayerApplyEnterHomeNotify = 4757; - public static final int PlayerApplyEnterHomeResultNotify = 4568; - public static final int PlayerApplyEnterHomeResultReq = 4668; - public static final int PlayerApplyEnterHomeResultRsp = 4714; - public static final int PlayerApplyEnterMpAfterMatchAgreedNotify = 4171; - public static final int PlayerApplyEnterMpNotify = 1848; - public static final int PlayerApplyEnterMpReq = 1843; - public static final int PlayerApplyEnterMpResultNotify = 1846; - public static final int PlayerApplyEnterMpResultReq = 1836; - public static final int PlayerApplyEnterMpResultRsp = 1815; - public static final int PlayerApplyEnterMpRsp = 1809; - public static final int PlayerCancelMatchReq = 4196; - public static final int PlayerCancelMatchRsp = 4186; - public static final int PlayerChatCDNotify = 3354; - public static final int PlayerChatNotify = 3236; - public static final int PlayerChatReq = 3125; - public static final int PlayerChatRsp = 3070; - public static final int PlayerCompoundMaterialReq = 133; - public static final int PlayerCompoundMaterialRsp = 116; - public static final int PlayerConfirmMatchReq = 4182; - public static final int PlayerConfirmMatchRsp = 4189; - public static final int PlayerCookArgsReq = 145; - public static final int PlayerCookArgsRsp = 121; - public static final int PlayerCookReq = 184; - public static final int PlayerCookRsp = 141; - public static final int PlayerDataNotify = 182; - public static final int PlayerEnterDungeonReq = 954; - public static final int PlayerEnterDungeonRsp = 964; - public static final int PlayerEnterSceneInfoNotify = 289; - public static final int PlayerEnterSceneNotify = 267; - public static final int PlayerEyePointStateNotify = 3065; - public static final int PlayerFishingDataNotify = 5838; - public static final int PlayerForceExitReq = 106; - public static final int PlayerForceExitRsp = 190; - public static final int PlayerGameTimeNotify = 159; - public static final int PlayerGeneralMatchConfirmNotify = 4152; - public static final int PlayerGeneralMatchDismissNotify = 4151; - public static final int PlayerGetForceQuitBanInfoReq = 4167; - public static final int PlayerGetForceQuitBanInfoRsp = 4176; - public static final int PlayerHomeCompInfoNotify = 4886; - public static final int PlayerInjectFixNotify = 192; - public static final int PlayerInvestigationAllInfoNotify = 1911; - public static final int PlayerInvestigationNotify = 1901; - public static final int PlayerInvestigationTargetNotify = 1930; - public static final int PlayerLevelRewardUpdateNotify = 120; - public static final int PlayerLoginReq = 154; - public static final int PlayerLoginRsp = 164; - public static final int PlayerLogoutNotify = 172; - public static final int PlayerLogoutReq = 114; - public static final int PlayerLogoutRsp = 134; - public static final int PlayerLuaShellNotify = 101; - public static final int PlayerMatchAgreedResultNotify = 4185; - public static final int PlayerMatchInfoNotify = 4159; - public static final int PlayerMatchStopNotify = 4165; - public static final int PlayerMatchSuccNotify = 4194; - public static final int PlayerOfferingDataNotify = 2925; - public static final int PlayerOfferingReq = 2916; - public static final int PlayerOfferingRsp = 2924; - public static final int PlayerPreEnterMpNotify = 1832; - public static final int PlayerPropChangeNotify = 156; - public static final int PlayerPropChangeReasonNotify = 1250; - public static final int PlayerPropNotify = 107; - public static final int PlayerQuitDungeonReq = 914; - public static final int PlayerQuitDungeonRsp = 934; - public static final int PlayerQuitFromHomeNotify = 4837; - public static final int PlayerQuitFromMpNotify = 1844; - public static final int PlayerRandomCookReq = 170; - public static final int PlayerRandomCookRsp = 113; - public static final int PlayerRechargeDataNotify = 4136; - public static final int PlayerReportReq = 4002; - public static final int PlayerReportRsp = 4088; - public static final int PlayerRoutineDataNotify = 3548; - public static final int PlayerSetLanguageReq = 149; - public static final int PlayerSetLanguageRsp = 197; - public static final int PlayerSetOnlyMPWithPSPlayerReq = 1835; - public static final int PlayerSetOnlyMPWithPSPlayerRsp = 1821; - public static final int PlayerSetPauseReq = 102; - public static final int PlayerSetPauseRsp = 188; - public static final int PlayerStartMatchReq = 4198; - public static final int PlayerStartMatchRsp = 4193; - public static final int PlayerStoreNotify = 667; - public static final int PlayerTimeNotify = 171; - public static final int PlayerWorldSceneInfoListNotify = 3152; - public static final int PostEnterSceneReq = 3446; - public static final int PostEnterSceneRsp = 3030; - public static final int PrivateChatNotify = 5004; - public static final int PrivateChatReq = 5017; - public static final int PrivateChatRsp = 5025; - public static final int PrivateChatSetSequenceReq = 4985; - public static final int PrivateChatSetSequenceRsp = 4957; - public static final int ProfilePictureChangeNotify = 4043; - public static final int ProjectorOptionReq = 813; - public static final int ProjectorOptionRsp = 857; - public static final int ProudSkillChangeNotify = 1059; - public static final int ProudSkillExtraLevelNotify = 1029; - public static final int ProudSkillUpgradeReq = 1065; - public static final int ProudSkillUpgradeRsp = 1050; - public static final int PullPrivateChatReq = 4984; - public static final int PullPrivateChatRsp = 5022; - public static final int PullRecentChatReq = 5032; - public static final int PullRecentChatRsp = 5015; - public static final int PushTipsAllDataNotify = 2219; - public static final int PushTipsChangeNotify = 2244; - public static final int PushTipsReadFinishReq = 2294; - public static final int PushTipsReadFinishRsp = 2274; - public static final int QueryCodexMonsterBeKilledNumReq = 4208; - public static final int QueryCodexMonsterBeKilledNumRsp = 4201; - public static final int QueryPathReq = 2367; - public static final int QueryPathRsp = 2375; - public static final int QuestCreateEntityReq = 450; - public static final int QuestCreateEntityRsp = 459; - public static final int QuestDelNotify = 454; - public static final int QuestDestroyEntityReq = 407; - public static final int QuestDestroyEntityRsp = 491; - public static final int QuestDestroyNpcReq = 419; - public static final int QuestDestroyNpcRsp = 444; - public static final int QuestGlobalVarNotify = 426; - public static final int QuestListNotify = 467; - public static final int QuestListUpdateNotify = 475; - public static final int QuestProgressUpdateNotify = 466; - public static final int QuestTransmitReq = 433; - public static final int QuestTransmitRsp = 416; - public static final int QuestUpdateQuestTimeVarNotify = 488; - public static final int QuestUpdateQuestVarNotify = 423; - public static final int QuestUpdateQuestVarReq = 461; - public static final int QuestUpdateQuestVarRsp = 456; - public static final int QuickUseWidgetReq = 4281; - public static final int QuickUseWidgetRsp = 4285; - public static final int ReadMailNotify = 1454; - public static final int ReadPrivateChatReq = 5000; - public static final int ReadPrivateChatRsp = 5009; - public static final int ReceivedTrialAvatarActivityRewardReq = 2005; - public static final int ReceivedTrialAvatarActivityRewardRsp = 2009; - public static final int RechargeReq = 4148; - public static final int RechargeRsp = 4143; - public static final int RedeemLegendaryKeyReq = 418; - public static final int RedeemLegendaryKeyRsp = 458; - public static final int RefreshBackgroundAvatarReq = 1636; - public static final int RefreshBackgroundAvatarRsp = 1786; - public static final int RefreshRoguelikeDungeonCardReq = 8092; - public static final int RefreshRoguelikeDungeonCardRsp = 8721; - public static final int RegionSearchChangeRegionNotify = 5643; - public static final int RegionSearchNotify = 5648; - public static final int ReliquaryDecomposeReq = 631; - public static final int ReliquaryDecomposeRsp = 699; - public static final int ReliquaryPromoteReq = 646; - public static final int ReliquaryPromoteRsp = 684; - public static final int ReliquaryUpgradeReq = 694; - public static final int ReliquaryUpgradeRsp = 674; - public static final int RemoveBlacklistReq = 4013; - public static final int RemoveBlacklistRsp = 4057; - public static final int RemoveRandTaskInfoNotify = 153; - public static final int ReportFightAntiCheatNotify = 321; - public static final int ReportTrackingIOInfoNotify = 4144; - public static final int RequestLiveInfoReq = 884; - public static final int RequestLiveInfoRsp = 841; - public static final int ResinCardDataUpdateNotify = 4131; - public static final int ResinChangeNotify = 649; - public static final int RestartEffigyChallengeReq = 2188; - public static final int RestartEffigyChallengeRsp = 2137; - public static final int ReunionActivateNotify = 5088; - public static final int ReunionBriefInfoReq = 5098; - public static final int ReunionBriefInfoRsp = 5093; - public static final int ReunionDailyRefreshNotify = 5072; - public static final int ReunionPrivilegeChangeNotify = 5090; - public static final int ReunionSettleNotify = 5075; - public static final int RobotPushPlayerDataNotify = 42; - public static final int RogueCellUpdateNotify = 8624; - public static final int RogueDungeonPlayerCellChangeNotify = 8320; - public static final int RogueHealAvatarsReq = 8610; - public static final int RogueHealAvatarsRsp = 8941; - public static final int RogueResumeDungeonReq = 8029; - public static final int RogueResumeDungeonRsp = 8009; - public static final int RogueSwitchAvatarReq = 8770; - public static final int RogueSwitchAvatarRsp = 8259; - public static final int RoguelikeCardGachaNotify = 8494; - public static final int RoguelikeEffectDataNotify = 8556; - public static final int RoguelikeEffectViewReq = 8885; - public static final int RoguelikeEffectViewRsp = 8862; - public static final int RoguelikeGiveUpReq = 8061; - public static final int RoguelikeGiveUpRsp = 8868; - public static final int RoguelikeMistClearNotify = 8512; - public static final int RoguelikeRefreshCardCostUpdateNotify = 8266; - public static final int RoguelikeResourceBonusPropUpdateNotify = 8376; - public static final int RoguelikeRuneRecordUpdateNotify = 8950; - public static final int RoguelikeSelectAvatarAndEnterDungeonReq = 8863; - public static final int RoguelikeSelectAvatarAndEnterDungeonRsp = 8400; - public static final int RoguelikeTakeStageFirstPassRewardReq = 8541; - public static final int RoguelikeTakeStageFirstPassRewardRsp = 8530; - public static final int SalesmanDeliverItemReq = 2167; - public static final int SalesmanDeliverItemRsp = 2067; - public static final int SalesmanTakeRewardReq = 2062; - public static final int SalesmanTakeRewardRsp = 2070; - public static final int SalesmanTakeSpecialRewardReq = 2166; - public static final int SalesmanTakeSpecialRewardRsp = 2184; - public static final int SaveCoopDialogReq = 1972; - public static final int SaveCoopDialogRsp = 1960; - public static final int SaveMainCoopReq = 1959; - public static final int SaveMainCoopRsp = 1996; - public static final int SceneAreaUnlockNotify = 274; - public static final int SceneAreaWeatherNotify = 297; - public static final int SceneAudioNotify = 3412; - public static final int SceneAvatarStaminaStepReq = 250; - public static final int SceneAvatarStaminaStepRsp = 259; - public static final int SceneCreateEntityReq = 241; - public static final int SceneCreateEntityRsp = 270; - public static final int SceneDataNotify = 3210; - public static final int SceneDestroyEntityReq = 213; - public static final int SceneDestroyEntityRsp = 257; - public static final int SceneEntitiesMoveCombineNotify = 3188; - public static final int SceneEntitiesMovesReq = 222; - public static final int SceneEntitiesMovesRsp = 212; - public static final int SceneEntityAppearNotify = 234; - public static final int SceneEntityDisappearNotify = 272; - public static final int SceneEntityDrownReq = 246; - public static final int SceneEntityDrownRsp = 284; - public static final int SceneEntityMoveNotify = 207; - public static final int SceneEntityMoveReq = 282; - public static final int SceneEntityMoveRsp = 265; - public static final int SceneEntityUpdateNotify = 3095; - public static final int SceneForceLockNotify = 226; - public static final int SceneForceUnlockNotify = 286; - public static final int SceneGalleryInfoNotify = 5529; - public static final int SceneInitFinishReq = 264; - public static final int SceneInitFinishRsp = 214; - public static final int SceneKickPlayerNotify = 299; - public static final int SceneKickPlayerReq = 232; - public static final int SceneKickPlayerRsp = 231; - public static final int ScenePlayBattleInfoListNotify = 4379; - public static final int ScenePlayBattleInfoNotify = 4417; - public static final int ScenePlayBattleInterruptNotify = 4357; - public static final int ScenePlayBattleResultNotify = 4441; - public static final int ScenePlayBattleUidOpNotify = 4392; - public static final int ScenePlayGuestReplyInviteReq = 4422; - public static final int ScenePlayGuestReplyInviteRsp = 4432; - public static final int ScenePlayGuestReplyNotify = 4415; - public static final int ScenePlayInfoListNotify = 4409; - public static final int ScenePlayInviteResultNotify = 4400; - public static final int ScenePlayOutofRegionNotify = 4377; - public static final int ScenePlayOwnerCheckReq = 4425; - public static final int ScenePlayOwnerCheckRsp = 4404; - public static final int ScenePlayOwnerInviteNotify = 4384; - public static final int ScenePlayOwnerStartInviteReq = 4414; - public static final int ScenePlayOwnerStartInviteRsp = 4364; - public static final int ScenePlayerInfoNotify = 240; - public static final int ScenePlayerLocationNotify = 291; - public static final int ScenePlayerSoundNotify = 201; - public static final int ScenePointUnlockNotify = 261; - public static final int SceneRouteChangeNotify = 208; - public static final int SceneTeamUpdateNotify = 1762; - public static final int SceneTimeNotify = 210; - public static final int SceneTransToPointReq = 256; - public static final int SceneTransToPointRsp = 223; - public static final int SceneWeatherForcastReq = 3037; - public static final int SceneWeatherForcastRsp = 3257; - public static final int SeaLampCoinNotify = 2127; - public static final int SeaLampContributeItemReq = 2119; - public static final int SeaLampContributeItemRsp = 2138; - public static final int SeaLampFlyLampNotify = 2161; - public static final int SeaLampFlyLampReq = 2175; - public static final int SeaLampFlyLampRsp = 2152; - public static final int SeaLampPopularityNotify = 2087; - public static final int SeaLampTakeContributionRewardReq = 2149; - public static final int SeaLampTakeContributionRewardRsp = 2170; - public static final int SeaLampTakePhaseRewardReq = 2135; - public static final int SeaLampTakePhaseRewardRsp = 2085; - public static final int SealBattleBeginNotify = 206; - public static final int SealBattleEndNotify = 290; - public static final int SealBattleProgressNotify = 292; - public static final int SeeMonsterReq = 255; - public static final int SeeMonsterRsp = 209; - public static final int SelectAsterMidDifficultyReq = 2003; - public static final int SelectAsterMidDifficultyRsp = 2001; - public static final int SelectEffigyChallengeConditionReq = 2199; - public static final int SelectEffigyChallengeConditionRsp = 2081; - public static final int SelectRoguelikeDungeonCardReq = 8229; - public static final int SelectRoguelikeDungeonCardRsp = 8037; - public static final int SelectWorktopOptionReq = 814; - public static final int SelectWorktopOptionRsp = 834; - public static final int ServerAnnounceNotify = 2073; - public static final int ServerAnnounceRevokeNotify = 2103; - public static final int ServerBuffChangeNotify = 353; - public static final int ServerCondMeetQuestListUpdateNotify = 486; - public static final int ServerDisconnectClientNotify = 198; - public static final int ServerGlobalValueChangeNotify = 1142; - public static final int ServerLogNotify = 59; - public static final int ServerMessageNotify = 5743; - public static final int ServerTimeNotify = 50; - public static final int ServerUpdateGlobalValueNotify = 1191; - public static final int SetBattlePassViewedReq = 2601; - public static final int SetBattlePassViewedRsp = 2602; - public static final int SetChatEmojiCollectionReq = 4098; - public static final int SetChatEmojiCollectionRsp = 4003; - public static final int SetCoopChapterViewedReq = 1978; - public static final int SetCoopChapterViewedRsp = 1968; - public static final int SetCurExpeditionChallengeIdReq = 2168; - public static final int SetCurExpeditionChallengeIdRsp = 2052; - public static final int SetEntityClientDataNotify = 3457; - public static final int SetEquipLockStateReq = 645; - public static final int SetEquipLockStateRsp = 621; - public static final int SetFriendEnterHomeOptionReq = 4732; - public static final int SetFriendEnterHomeOptionRsp = 4835; - public static final int SetFriendRemarkNameReq = 4049; - public static final int SetFriendRemarkNameRsp = 4097; - public static final int SetH5ActivityRedDotTimestampReq = 5696; - public static final int SetH5ActivityRedDotTimestampRsp = 5686; - public static final int SetIsAutoUnlockSpecificEquipReq = 673; - public static final int SetIsAutoUnlockSpecificEquipRsp = 632; - public static final int SetLimitOptimizationNotify = 8431; - public static final int SetNameCardReq = 4094; - public static final int SetNameCardRsp = 4074; - public static final int SetOpenStateReq = 144; - public static final int SetOpenStateRsp = 194; - public static final int SetPlayerBirthdayReq = 4091; - public static final int SetPlayerBirthdayRsp = 4042; - public static final int SetPlayerBornDataReq = 127; - public static final int SetPlayerBornDataRsp = 166; - public static final int SetPlayerHeadImageReq = 4066; - public static final int SetPlayerHeadImageRsp = 4061; - public static final int SetPlayerNameReq = 123; - public static final int SetPlayerNameRsp = 119; - public static final int SetPlayerPropReq = 142; - public static final int SetPlayerPropRsp = 129; - public static final int SetPlayerSignatureReq = 4029; - public static final int SetPlayerSignatureRsp = 4027; - public static final int SetSceneWeatherAreaReq = 296; - public static final int SetSceneWeatherAreaRsp = 263; - public static final int SetUpAvatarTeamReq = 1638; - public static final int SetUpAvatarTeamRsp = 1628; - public static final int SetUpLunchBoxWidgetReq = 4282; - public static final int SetUpLunchBoxWidgetRsp = 4289; - public static final int SetWidgetSlotReq = 4297; - public static final int SetWidgetSlotRsp = 4270; - public static final int ShowClientGuideNotify = 3384; - public static final int ShowClientTutorialNotify = 3120; - public static final int ShowCommonTipsNotify = 3469; - public static final int ShowMessageNotify = 64; - public static final int ShowTemplateReminderNotify = 3186; - public static final int SignInInfoReq = 2554; - public static final int SignInInfoRsp = 2564; - public static final int SocialDataNotify = 4016; - public static final int SpringUseReq = 1788; - public static final int SpringUseRsp = 1737; - public static final int StartArenaChallengeLevelReq = 2194; - public static final int StartArenaChallengeLevelRsp = 2057; - public static final int StartBuoyantCombatGalleryReq = 8282; - public static final int StartBuoyantCombatGalleryRsp = 8916; - public static final int StartCoopPointReq = 1952; - public static final int StartCoopPointRsp = 1967; - public static final int StartEffigyChallengeReq = 2156; - public static final int StartEffigyChallengeRsp = 2021; - public static final int StartFishingReq = 5809; - public static final int StartFishingRsp = 5846; - public static final int StartRogueEliteCellChallengeReq = 8874; - public static final int StartRogueEliteCellChallengeRsp = 8759; - public static final int StartRogueNormalCellChallengeReq = 8809; - public static final int StartRogueNormalCellChallengeRsp = 8834; - public static final int StoreItemChangeNotify = 654; - public static final int StoreItemDelNotify = 664; - public static final int StoreWeightLimitNotify = 675; - public static final int SummerTimeFloatSignalPositionNotify = 8639; - public static final int SummerTimeFloatSignalUpdateNotify = 8576; - public static final int SummerTimeSprintBoatRestartReq = 8178; - public static final int SummerTimeSprintBoatRestartRsp = 8987; - public static final int SummerTimeSprintBoatSettleNotify = 8256; - public static final int SumoDungeonSettleNotify = 8665; - public static final int SumoEnterDungeonNotify = 8823; - public static final int SumoLeaveDungeonNotify = 8778; - public static final int SumoRestartDungeonReq = 8246; - public static final int SumoRestartDungeonRsp = 8249; - public static final int SumoSaveTeamReq = 8607; - public static final int SumoSaveTeamRsp = 8005; - public static final int SumoSelectTeamAndEnterDungeonReq = 8930; - public static final int SumoSelectTeamAndEnterDungeonRsp = 8131; - public static final int SumoSetNoSwitchPunishTimeNotify = 8536; - public static final int SumoSwitchTeamReq = 8384; - public static final int SumoSwitchTeamRsp = 8065; - public static final int SyncScenePlayTeamEntityNotify = 3362; - public static final int SyncTeamEntityNotify = 393; - public static final int TakeAchievementGoalRewardReq = 2686; - public static final int TakeAchievementGoalRewardRsp = 2665; - public static final int TakeAchievementRewardReq = 2659; - public static final int TakeAchievementRewardRsp = 2696; - public static final int TakeAsterSpecialRewardReq = 2061; - public static final int TakeAsterSpecialRewardRsp = 2026; - public static final int TakeBattlePassMissionPointReq = 2644; - public static final int TakeBattlePassMissionPointRsp = 2632; - public static final int TakeBattlePassRewardReq = 2636; - public static final int TakeBattlePassRewardRsp = 2615; - public static final int TakeCityReputationExploreRewardReq = 2842; - public static final int TakeCityReputationExploreRewardRsp = 2829; - public static final int TakeCityReputationLevelRewardReq = 2854; - public static final int TakeCityReputationLevelRewardRsp = 2864; - public static final int TakeCityReputationParentQuestReq = 2834; - public static final int TakeCityReputationParentQuestRsp = 2872; - public static final int TakeCompoundOutputReq = 137; - public static final int TakeCompoundOutputRsp = 125; - public static final int TakeCoopRewardReq = 1975; - public static final int TakeCoopRewardRsp = 1988; - public static final int TakeDeliveryDailyRewardReq = 2054; - public static final int TakeDeliveryDailyRewardRsp = 2029; - public static final int TakeEffigyFirstPassRewardReq = 2050; - public static final int TakeEffigyFirstPassRewardRsp = 2025; - public static final int TakeEffigyRewardReq = 2104; - public static final int TakeEffigyRewardRsp = 2089; - public static final int TakeFirstShareRewardReq = 4037; - public static final int TakeFirstShareRewardRsp = 4025; - public static final int TakeFurnitureMakeReq = 4713; - public static final int TakeFurnitureMakeRsp = 4630; - public static final int TakeHuntingOfferReq = 4348; - public static final int TakeHuntingOfferRsp = 4343; - public static final int TakeInvestigationRewardReq = 1928; - public static final int TakeInvestigationRewardRsp = 1910; - public static final int TakeInvestigationTargetRewardReq = 1926; - public static final int TakeInvestigationTargetRewardRsp = 1927; - public static final int TakeMaterialDeleteReturnReq = 638; - public static final int TakeMaterialDeleteReturnRsp = 604; - public static final int TakeOfferingLevelRewardReq = 2921; - public static final int TakeOfferingLevelRewardRsp = 2908; - public static final int TakePlayerLevelRewardReq = 138; - public static final int TakePlayerLevelRewardRsp = 104; - public static final int TakeRegionSearchRewardReq = 5609; - public static final int TakeRegionSearchRewardRsp = 5646; - public static final int TakeResinCardDailyRewardReq = 4132; - public static final int TakeResinCardDailyRewardRsp = 4139; - public static final int TakeReunionFirstGiftRewardReq = 5059; - public static final int TakeReunionFirstGiftRewardRsp = 5096; - public static final int TakeReunionMissionRewardReq = 5052; - public static final int TakeReunionMissionRewardRsp = 5067; - public static final int TakeReunionSignInRewardReq = 5094; - public static final int TakeReunionSignInRewardRsp = 5082; - public static final int TakeReunionWatcherRewardReq = 5085; - public static final int TakeReunionWatcherRewardRsp = 5071; - public static final int TakeoffEquipReq = 627; - public static final int TakeoffEquipRsp = 666; - public static final int TaskVarNotify = 176; - public static final int TeamResonanceChangeNotify = 1066; - public static final int TowerAllDataReq = 2482; - public static final int TowerAllDataRsp = 2465; - public static final int TowerBriefDataNotify = 2467; - public static final int TowerBuffSelectReq = 2491; - public static final int TowerBuffSelectRsp = 2442; - public static final int TowerCurLevelRecordChangeNotify = 2454; - public static final int TowerDailyRewardProgressChangeNotify = 2464; - public static final int TowerEnterLevelReq = 2459; - public static final int TowerEnterLevelRsp = 2407; - public static final int TowerFloorRecordChangeNotify = 2475; - public static final int TowerGetFloorStarRewardReq = 2494; - public static final int TowerGetFloorStarRewardRsp = 2474; - public static final int TowerLevelEndNotify = 2457; - public static final int TowerLevelStarCondNotify = 2486; - public static final int TowerMiddleLevelChangeTeamNotify = 2426; - public static final int TowerRecordHandbookReq = 2433; - public static final int TowerRecordHandbookRsp = 2416; - public static final int TowerSurrenderReq = 2419; - public static final int TowerSurrenderRsp = 2444; - public static final int TowerTeamSelectReq = 2434; - public static final int TowerTeamSelectRsp = 2472; - public static final int TreasureMapBonusChallengeNotify = 2163; - public static final int TreasureMapCurrencyNotify = 2046; - public static final int TreasureMapDetectorDataNotify = 4272; - public static final int TreasureMapGuideTaskDoneNotify = 2099; - public static final int TreasureMapHostInfoNotify = 8260; - public static final int TreasureMapMpChallengeNotify = 2071; - public static final int TreasureMapPreTaskDoneNotify = 2191; - public static final int TreasureMapRegionActiveNotify = 2148; - public static final int TreasureMapRegionInfoNotify = 2190; - public static final int TrialAvatarFirstPassDungeonNotify = 2105; - public static final int TrialAvatarInDungeonIndexNotify = 2109; - public static final int TriggerCreateGadgetToEquipPartNotify = 333; - public static final int TriggerRoguelikeCurseNotify = 8901; - public static final int TriggerRoguelikeRuneReq = 8053; - public static final int TriggerRoguelikeRuneRsp = 8631; - public static final int TryEnterHomeReq = 4729; - public static final int TryEnterHomeRsp = 4597; - public static final int UnfreezeGroupLimitNotify = 3464; - public static final int UnionCmdNotify = 27; - public static final int LastPacketPrintNotify = 41; - public static final int SalvagePreventSettleNotify = 8967; - public static final int HomeEnterEditModeFinishReq = 4676; - public static final int ReplayCustomDungeonRsp = 6234; - public static final int SpiceActivityFinishMakeSpiceRsp = 8004; - public static final int GachaActivityTakeRewardRsp = 8272; - public static final int MistTrialGetDungeonExhibitionDataRsp = 8058; - public static final int CrystalLinkEnterDungeonRsp = 8067; - public static final int ChangeCustomDungeonRoomRsp = 6239; - public static final int MistTrialGetDungeonExhibitionDataReq = 8931; - public static final int ActivityGetRecvGiftListRsp = 8791; - public static final int ReformFireworksReq = 6040; - public static final int CrystalLinkRestartDungeonReq = 8317; - public static final int LaunchFireworksReq = 6053; - public static final int WinterCampGetCanGiveFriendItemRsp = 8147; - public static final int PublishUgcReq = 6339; - public static final int GachaActivityCreateRobotReq = 8654; - public static final int GachaActivityCreateRobotRsp = 8808; - public static final int SpiceActivityProcessFoodReq = 8697; - public static final int PotionSaveDungeonResultReq = 8306; - public static final int WinterCampRecvItemNotify = 8740; - public static final int StartRogueDiaryPlayReq = 8804; - public static final int BartenderFinishLevelReq = 9000; - public static final int SalvageEscortSettleNotify = 8353; - public static final int HomeChangeBgmReq = 4806; - public static final int EvtBeingHealedNotify = 301; - public static final int GetCustomDungeonReq = 6247; - public static final int IrodoriChessEquipCardReq = 8511; - public static final int ResetRogueDiaryPlayRsp = 8336; - public static final int SpiceActivityProcessFoodRsp = 8075; - public static final int HomeBalloonGalleryScoreNotify = 4532; - public static final int PhotoActivityFinishRsp = 8713; - public static final int QuickOpenActivityReq = 8171; - public static final int LanternRiteDoFireworksReformReq = 8261; - public static final int RogueDiaryCoinAddNotify = 8059; - public static final int RogueDiaryRepairInfoNotify = 8835; - public static final int PhotoActivityFinishReq = 8473; - public static final int ViewLanternProjectionTipsRsp = 8108; - public static final int MichiaeMatsuriInteractStatueRsp = 8216; - public static final int TryEnterNextRogueDiaryDungeonReq = 8832; - public static final int ActivityAcceptGiveGiftRsp = 8915; - public static final int RogueDiaryDungeonInfoNotify = 8415; - public static final int StartRogueDiaryRoomReq = 8291; - public static final int LevelTagDataNotify = 3072; - public static final int StoreCustomDungeonReq = 6218; - public static final int WinterCampGetRecvItemListReq = 8547; - public static final int GachaActivityResetRsp = 8296; - public static final int WinterCampRaceScoreNotify = 8664; - public static final int MainCoopFailNotify = 1987; - public static final int CheckUgcStateReq = 6302; - public static final int WinterCampTakeBattleRewardRsp = 8573; - public static final int ActivityGetRecvGiftListReq = 8973; - public static final int SalvagePreventRestartRsp = 8030; - public static final int TryInterruptRogueDiaryDungeonRsp = 8655; - public static final int WinterCampGiveFriendItemRsp = 8781; - public static final int RogueFinishRepairRsp = 8024; - public static final int IrodoriChessUnequipCardRsp = 8825; - public static final int MichiaeMatsuriUnlockCrystalSkillRsp = 8845; - public static final int SaveUgcReq = 6344; - public static final int ResetRogueDiaryPlayReq = 8360; - public static final int CrystalLinkDungeonInfoNotify = 8925; - public static final int SaveCustomDungeonRoomRsp = 6246; - public static final int WinterCampEditSnowmanCombinationReq = 8743; - public static final int SearchCustomDungeonRsp = 6228; - public static final int BartenderCancelOrderReq = 8717; - public static final int WinterCampTriathlonSettleNotify = 8920; - public static final int ViewLanternProjectionLevelTipsRsp = 8134; - public static final int WinterCampTriathlonRestartReq = 8117; - public static final int ServerCombatEndNotify = 1127; - public static final int ReadSignatureAuditRsp = 4032; - public static final int GetGameplayRecommendationReq = 109; - public static final int TryInterruptRogueDiaryDungeonReq = 8362; - public static final int ResumeRogueDiaryDungeonReq = 8056; - public static final int EnterIrodoriChessDungeonReq = 8933; - public static final int GetRecommendCustomDungeonReq = 6238; - public static final int GachaActivityUpdateElemNotify = 8338; - public static final int ActivityHaveRecvGiftNotify = 8350; - public static final int WinterCampAcceptGiveItemReq = 8014; - public static final int MistTrialSettleNotify = 8559; - public static final int HomeRacingGallerySettleNotify = 4764; - public static final int QuickOpenActivityRsp = 8670; - public static final int SaveUgcRsp = 6332; - public static final int BartenderCancelOrderRsp = 8850; - public static final int MichiaeMatsuriRemoveChestMarkNotify = 8082; - public static final int GachaActivityResetReq = 8231; - public static final int GachaActivityNextStageRsp = 8304; - public static final int WinterCampSetWishListReq = 8405; - public static final int RetryCurRogueDiaryDungeonRsp = 8960; - public static final int BartenderStartLevelReq = 8460; - public static final int ResumeRogueDiaryDungeonRsp = 8712; - public static final int OutStuckCustomDungeonReq = 6227; - public static final int EnterIrodoriChessDungeonRsp = 8211; - public static final int RetryCurRogueDiaryDungeonReq = 8423; - public static final int WinterCampGetFriendWishListRsp = 8224; - public static final int HomeChangeBgmNotify = 4653; - public static final int GachaActivityPercentNotify = 8469; - public static final int RegionalPlayInfoNotify = 6298; - public static final int PotionEnterDungeonRsp = 8889; - public static final int LikeCustomDungeonReq = 6219; - public static final int ChangeCustomDungeonRoomReq = 6232; - public static final int GetRecommendCustomDungeonRsp = 6240; - public static final int CrystalLinkRestartDungeonRsp = 8748; - public static final int RemoveCustomDungeonReq = 6231; - public static final int BackPlayCustomDungeonOfficialRsp = 6216; - public static final int PlayerSignatureAuditDataNotify = 4076; - public static final int GalleryCrystalLinkKillMonsterNotify = 5561; - public static final int GetRogueDairyRepairInfoReq = 8633; - public static final int HomeClearGroupRecordRsp = 4846; - public static final int IrodoriChessPlayerInfoNotify = 5332; - public static final int LanternRiteDoFireworksReformRsp = 8564; - public static final int GetStoreCustomDungeonReq = 6222; - public static final int TryCustomDungeonRsp = 6201; - public static final int GetParentQuestVideoKeyRsp = 493; - public static final int IrodoriEditFlowerCombinationReq = 8746; - public static final int PotionSaveDungeonResultRsp = 8911; - public static final int PotionEnterDungeonReq = 8630; - public static final int WidgetUpdateExtraCDReq = 6005; - public static final int UgcNotify = 6301; - public static final int IrodoriChessUnequipCardReq = 8783; - public static final int EnterRogueDiaryDungeonRsp = 8515; - public static final int TryCustomDungeonReq = 6221; - public static final int RefreshRogueDiaryCardReq = 8849; - public static final int PhotoActivityClientViewReq = 8167; - public static final int ActivityAcceptGiveGiftReq = 8303; - public static final int SearchCustomDungeonReq = 6207; - public static final int UpdateSalvageBundleMarkReq = 8157; - public static final int ReadNicknameAuditRsp = 181; - public static final int AllShareCDDataNotify = 9067; - public static final int GetUgcBriefInfoReq = 6309; - public static final int IrodoriFillPoetryReq = 8228; - public static final int LanternRiteTakeSkinRewardReq = 8502; - public static final int RemoveCustomDungeonRsp = 6235; - public static final int CustomDungeonRecoverNotify = 6204; - public static final int SetCodexPushtipsReadRsp = 4202; - public static final int LanternRiteEndFireworksReformRsp = 8142; - public static final int ActivitySetGiftWishReq = 8848; - public static final int WinterCampGetFriendWishListReq = 8440; - public static final int FinishLanternProjectionRsp = 8016; - public static final int ActivitySetGiftWishRsp = 8764; - public static final int WinterCampTakeExploreRewardReq = 8750; - public static final int WidgetUpdateExtraCDRsp = 5925; - public static final int SignatureAuditConfigNotify = 4085; - public static final int BartenderCompleteOrderReq = 8327; - public static final int HomeGetGroupRecordReq = 4844; - public static final int MichiaeMatsuriDarkPressureLevelUpdateNotify = 8135; - public static final int RefreshRogueDiaryCardRsp = 8105; - public static final int ReplayCustomDungeonReq = 6242; - public static final int ReserveRogueDiaryAvatarRsp = 8457; - public static final int StartRogueDiaryRoomRsp = 8755; - public static final int BartenderStartLevelRsp = 8747; - public static final int IrodoriFillPoetryRsp = 8346; - public static final int EnterCustomDungeonRsp = 6243; - public static final int CheckUgcUpdateReq = 6335; - public static final int CrystalLinkEnterDungeonReq = 8861; - public static final int BartenderCancelLevelReq = 8161; - public static final int BartenderLevelProgressNotify = 8518; - public static final int LanternRiteEndFireworksReformReq = 8322; - public static final int GetParentQuestVideoKeyReq = 460; - public static final int SalvageEscortRestartRsp = 8118; - public static final int LuminanceStoneChallengeSettleNotify = 8895; - public static final int PublishCustomDungeonReq = 6202; - public static final int ActivityAcceptAllGiveGiftRsp = 8241; - public static final int FinishLanternProjectionReq = 8720; - public static final int ReformFireworksRsp = 5982; - public static final int HomePreChangeEditModeNotify = 4670; - public static final int SpiceActivityFinishMakeSpiceReq = 8032; - public static final int PlayerNicknameNotify = 139; - public static final int IrodoriMasterStartGalleryRsp = 8017; - public static final int LanternRiteStartFireworksReformRsp = 8546; - public static final int GetUgcBriefInfoRsp = 6346; - public static final int EnterCustomDungeonReq = 6248; - public static final int GlobalBuildingInfoNotify = 5373; - public static final int GetQuestLackingResourceReq = 440; - public static final int ExitCustomDungeonTryReq = 6226; - public static final int ActivityGiveFriendGiftRsp = 8524; - public static final int WidgetCaptureAnimalReq = 4274; - public static final int WinterCampEditSnowmanCombinationRsp = 8128; - public static final int WidgetCaptureAnimalRsp = 4261; - public static final int GetGameplayRecommendationRsp = 135; - public static final int IrodoriChessEquipCardRsp = 8145; - public static final int LanternRiteTakeSkinRewardRsp = 8356; - public static final int ClientRemoveCombatEndModifierNotify = 1166; - public static final int WinterCampTakeExploreRewardRsp = 8707; - public static final int HomeUpdatePictureFrameInfoRsp = 4748; - public static final int BartenderGetFormulaRsp = 8608; - public static final int SaveCustomDungeonRoomReq = 6209; - public static final int PlayerNicknameAuditDataNotify = 200; - public static final int HomeEnterEditModeFinishRsp = 4562; - public static final int ViewLanternProjectionTipsReq = 8818; - public static final int ActivityGetCanGiveFriendGiftRsp = 8186; - public static final int StoreCustomDungeonRsp = 6237; - public static final int ActivityBannerClearRsp = 2037; - public static final int EvtLocalGadgetOwnerLeaveSceneNotify = 398; - public static final int SetCodexPushtipsReadReq = 4210; - public static final int WinterCampAcceptGiveItemRsp = 8374; - public static final int RogueFinishRepairReq = 8749; - public static final int HomeGalleryInPlayingNotify = 5523; - public static final int HomeClearGroupRecordReq = 4870; - public static final int PotionRestartDungeonRsp = 8275; - public static final int PlayerSignatureNotify = 4089; - public static final int ReserveRogueDiaryAvatarReq = 8416; - public static final int TryEnterNextRogueDiaryDungeonRsp = 8223; - public static final int PublishUgcRsp = 6331; - public static final int ReadNicknameAuditReq = 169; - public static final int GetCustomDungeonRsp = 6220; - public static final int WinterCampAcceptAllGiveItemReq = 8251; - public static final int WinterCampGetCanGiveFriendItemReq = 8866; - public static final int ActivityAcceptAllGiveGiftReq = 8394; - public static final int GetQuestLackingResourceRsp = 411; - public static final int WinterCampStageInfoChangeNotify = 8531; - public static final int ActivityGetFriendGiftWishListRsp = 8777; - public static final int HomeSeekFurnitureGalleryScoreNotify = 4795; - public static final int WinterCampGiveFriendItemReq = 8187; - public static final int HomeAllUnlockedBgmIdListNotify = 4544; - public static final int LanternRiteStartFireworksReformReq = 8865; - public static final int GroupLinkMarkUpdateNotify = 5796; - public static final int FireworksReformDataNotify = 6080; - public static final int CheckUgcUpdateRsp = 6321; - public static final int RogueDiaryReviveAvatarReq = 8575; - public static final int ReadSignatureAuditReq = 4073; - public static final int HomeNewUnlockedBgmIdListNotify = 4612; - public static final int IrodoriChessLeftMonsterNotify = 5331; - public static final int MichiaeMatsuriStartDarkChallengeRsp = 8160; - public static final int MichiaeMatsuriUnlockCrystalSkillReq = 8949; - public static final int NicknameAuditConfigNotify = 115; - public static final int OutStuckCustomDungeonRsp = 6230; - public static final int BartenderGetFormulaReq = 8500; - public static final int PotionResetChallengeReq = 8958; - public static final int WinterCampTriathlonRestartRsp = 8258; - public static final int GetStoreCustomDungeonRsp = 6210; - public static final int NpcTalkStateNotify = 497; - public static final int SkyCrystalDetectorDataUpdateNotify = 4262; - public static final int IrodoriScanEntityRsp = 8730; - public static final int HomePictureFrameInfoNotify = 4895; - public static final int CustomDungeonOfficialNotify = 6250; - public static final int HomeUpdatePictureFrameInfoReq = 4813; - public static final int RogueDiaryTiredAvatarNotify = 8929; - public static final int ServerTryCancelGeneralMatchNotify = 4162; - public static final int GachaActivityNextStageReq = 8212; - public static final int LaunchFireworksRsp = 6011; - public static final int FireworksLaunchDataNotify = 6038; - public static final int SpiceActivityGivingRecordNotify = 8049; - public static final int IrodoriScanEntityReq = 8281; - public static final int IrodoriMasterGallerySettleNotify = 8379; - public static final int ActivityGetFriendGiftWishListReq = 8091; - public static final int CheckUgcStateRsp = 6317; - public static final int HomeBalloonGallerySettleNotify = 4618; - public static final int MichiaeMatsuriStartBossChallengeReq = 8225; - public static final int Unk2700_NGPMINKIOPK = 8956; - public static final int CustomDungeonBattleRecordNotify = 6233; - public static final int ActivityBannerNotify = 2018; - public static final int BartenderFinishLevelRsp = 8044; - public static final int UpdateSalvageBundleMarkRsp = 8732; - public static final int WinterCampAcceptAllGiveItemRsp = 8815; - public static final int WinterCampSetWishListRsp = 8985; - public static final int GachaActivityTakeRewardReq = 8796; - public static final int IrodoriMasterGalleryCgEndNotify = 8555; - public static final int EnterRogueDiaryDungeonReq = 8388; - public static final int GalleryCrystalLinkBuffInfoNotify = 5556; - public static final int HomeGetGroupRecordRsp = 4522; - public static final int MichiaeMatsuriRemoveChallengeMarkNotify = 8578; - public static final int MichiaeMatsuriGainCrystalExpUpdateNotify = 8289; - public static final int MichiaeMatsuriInteractStatueReq = 8836; - public static final int MichiaeMatsuriStartDarkChallengeReq = 8357; - public static final int PotionResetChallengeRsp = 8262; - public static final int BartenderCancelLevelRsp = 8701; - public static final int CustomDungeonUpdateNotify = 6225; - public static final int HomeChangeBgmRsp = 4815; - public static final int BartenderCompleteOrderRsp = 8709; - public static final int ActivityGiveFriendGiftReq = 8763; - public static final int ActivityBannerClearReq = 2114; - public static final int BackPlayCustomDungeonOfficialReq = 6205; - public static final int SalvageEscortRestartReq = 8020; - public static final int MichiaeMatsuriStartBossChallengeRsp = 8826; - public static final int RogueDiaryReviveAvatarRsp = 8812; - public static final int WinterCampTakeBattleRewardReq = 8495; - public static final int TanukiTravelFinishGuideQuestNotify = 8130; - public static final int ViewLanternProjectionLevelTipsReq = 8937; - public static final int GetRogueDairyRepairInfoRsp = 8433; - public static final int PublishCustomDungeonRsp = 6217; - public static final int IrodoriEditFlowerCombinationRsp = 8800; - public static final int ActivityGetCanGiveFriendGiftReq = 8934; - public static final int IrodoriMasterStartGalleryReq = 8344; - public static final int ExitCustomDungeonTryRsp = 6212; - public static final int PotionEnterDungeonNotify = 8295; - public static final int SalvagePreventRestartReq = 8439; - public static final int RogueDiaryDungeonSettleNotify = 8220; - public static final int WinterCampGetRecvItemListRsp = 8234; - public static final int PhotoActivityClientViewRsp = 8945; - public static final int StartRogueDiaryPlayRsp = 8169; - public static final int PotionRestartDungeonReq = 8613; - public static final int LikeCustomDungeonRsp = 6203; - public static final int GearActivityFinishPlayGearRsp = 20017; - public static final int NightCrowGadgetObservationMatchRsp = 818; - public static final int GearActivityStartPlayPictureReq = 24138; - public static final int ActivityReadPushTipsRsp = 8119; - public static final int IslandPartyRaftInfoNotify = 5544; - public static final int GearActivityStartPlayGearReq = 24337; - public static final int SummerTimeV2RestartDungeonReq = 8988; - public static final int NightCrowGadgetObservationMatchReq = 825; - public static final int InvestigationReadQuestDailyNotify = 1921; - public static final int InvestigationQuestDailyNotify = 1902; - public static final int GearActivityFinishPlayPictureRsp = 23580; - public static final int GearActivityStartPlayGearRsp = 22301; - public static final int IslandPartySettleNotify = 20411; - public static final int GearActivityStartPlayPictureRsp = 23136; - public static final int TakeBackGivingItemRsp = 110; - public static final int GalleryWillStartCountdownNotify = 5584; - public static final int ActivityPushTipsInfoNotify = 8419; - public static final int PersistentDungeonSwitchAvatarReq = 1720; - public static final int SummerTimeV2RestartBoatGalleryReq = 8676; - public static final int StopReminderNotify = 3241; - public static final int IslandPartySailInfoNotify = 5594; - public static final int SummerTimeV2RestartDungeonRsp = 8101; - public static final int GearActivityFinishPlayGearReq = 24069; - public static final int BackRebornGalleryReq = 5574; - public static final int PersistentDungeonSwitchAvatarRsp = 1656; - public static final int GalleryIslandPartyDownHillInfoNotify = 5519; - public static final int GadgetChangeLevelTagRsp = 837; - public static final int ActivityReadPushTipsReq = 8285; - public static final int BackRebornGalleryRsp = 5546; - public static final int SummerTimeV2RestartBoatGalleryRsp = 8599; - public static final int SummerTimeV2BoatSettleNotify = 8436; - public static final int TakeBackGivingItemReq = 152; - public static final int GadgetChangeLevelTagReq = 816; - public static final int GearActivityFinishPlayPictureReq = 21009; - public static final int HomeExchangeWoodRsp = 4582; - public static final int HomeExchangeWoodReq = 4716; - public static final int GravenInnocenceEditCarveCombinationRsp = 20912; - public static final int GetAllMailResultNotify = 1429; - public static final int MuqadasPotionRestartDungeonReq = 23633; - public static final int ToTheMoonRemoveObstacleRsp = 6165; - public static final int MuqadasPotionCaptureWeaknessReq = 23970; - public static final int GravenInnocenceEditCarveCombinationReq = 24190; - public static final int ParentQuestInferenceDataNotify = 430; - public static final int DelBackupAvatarTeamReq = 1608; - public static final int AssociateInferenceWordReq = 438; - public static final int AvatarTeamAllDataNotify = 1729; - public static final int InstableSprayGalleryInfoNotify = 5541; - public static final int PlayerCompoundMaterialBoostReq = 177; - public static final int GravenInnocencePhotoFinishReq = 23079; - public static final int InstableSpraySwitchTeamReq = 24932; - public static final int SubmitInferenceWordRsp = 443; - public static final int InstableSprayEnterDungeonRsp = 24557; - public static final int AllWidgetBackgroundActiveStateNotify = 6034; - public static final int GetHomeExchangeWoodInfoReq = 4852; - public static final int GetAllMailNotify = 1442; - public static final int GravenInnocenceRaceRestartRsp = 24201; - public static final int InstableSprayRestartDungeonReq = 23108; - public static final int ToTheMoonAddObstacleRsp = 6172; - public static final int GetHomeExchangeWoodInfoRsp = 4592; - public static final int WorldChestOpenNotify = 3279; - public static final int DeshretObeliskChestInfoNotify = 858; - public static final int MuqadasPotionRestartDungeonRsp = 20273; - public static final int RemotePlayerWidgetNotify = 6009; - public static final int GravenInnocencePhotoFinishRsp = 23629; - public static final int InstableSprayLevelFinishNotify = 23121; - public static final int ChangeWidgetBackgroundActiveStateRsp = 6042; - public static final int AddBackupAvatarTeamRsp = 1777; - public static final int MuqadasPotionActivityEnterDungeonRsp = 22334; - public static final int AddBackupAvatarTeamReq = 1602; - public static final int PlayerDeathZoneNotify = 6259; - public static final int PlayerCompoundMaterialBoostRsp = 162; - public static final int InstableSpraySwitchTeamRsp = 23402; - public static final int TreasureSeelieCollectOrbsNotify = 24055; - public static final int AranaraCollectionDataNotify = 6398; - public static final int AssociateInferenceWordRsp = 404; - public static final int MuqadasPotionCaptureWeaknessRsp = 23854; - public static final int DelBackupAvatarTeamRsp = 1615; - public static final int InterpretInferenceWordRsp = 453; - public static final int MuqadasPotionActivityEnterDungeonReq = 21504; - public static final int ToTheMoonRemoveObstacleReq = 6182; - public static final int CheckGroupReplacedReq = 3036; - public static final int ToTheMoonEnterSceneRsp = 6114; - public static final int CheckGroupReplacedRsp = 3190; - public static final int InstableSprayEnterDungeonReq = 23181; - public static final int ToTheMoonEnterSceneReq = 6164; - public static final int ToTheMoonQueryPathRsp = 6175; - public static final int InterpretInferenceWordReq = 487; - public static final int AreaPlayInfoNotify = 3472; - public static final int ToTheMoonAddObstacleReq = 6134; - public static final int MuqadasPotionDungeonSettleNotify = 20893; - public static final int ToTheMoonPingNotify = 6154; - public static final int InstableSprayRestartDungeonRsp = 20879; - public static final int ToTheMoonQueryPathReq = 6167; - public static final int DeathZoneInfoNotify = 6293; - public static final int WidgetQuickHitTreeReq = 3068; - public static final int AddAranaraCollectionNotify = 6393; - public static final int ChangeWidgetBackgroundActiveStateReq = 5953; - public static final int DeathZoneObserveNotify = 3232; - public static final int GravenInnocenceRaceRestartReq = 22616; - public static final int GravenInnocencePhotoReminderNotify = 24173; - public static final int WidgetQuickHitTreeRsp = 3174; - public static final int GravenInnocenceRaceSettleNotify = 24552; - public static final int WatcherEventStageNotify = 2214; - public static final int SubmitInferenceWordReq = 420; - public static final int UnlockAvatarTalentReq = 1067; - public static final int UnlockAvatarTalentRsp = 1075; - public static final int UnlockCoopChapterReq = 1985; - public static final int UnlockCoopChapterRsp = 1971; - public static final int UnlockNameCardNotify = 4086; - public static final int UnlockPersonalLineReq = 405; - public static final int UnlockPersonalLineRsp = 471; - public static final int UnlockTransPointReq = 3180; - public static final int UnlockTransPointRsp = 3311; - public static final int UnlockedFurnitureFormulaDataNotify = 4481; - public static final int UnlockedFurnitureSuiteDataNotify = 4684; - public static final int UnmarkEntityInMinMapNotify = 287; - public static final int UpdateAbilityCreatedMovingPlatformNotify = 829; - public static final int UpdatePS4BlockListReq = 4018; - public static final int UpdatePS4BlockListRsp = 4058; - public static final int UpdatePS4FriendListNotify = 4056; - public static final int UpdatePS4FriendListReq = 4006; - public static final int UpdatePS4FriendListRsp = 4090; - public static final int UpdatePlayerShowAvatarListReq = 4040; - public static final int UpdatePlayerShowAvatarListRsp = 4011; - public static final int UpdatePlayerShowNameCardListReq = 4030; - public static final int UpdatePlayerShowNameCardListRsp = 4087; - public static final int UpdateRedPointNotify = 74; - public static final int UpdateReunionWatcherNotify = 5051; - public static final int UpgradeRoguelikeShikigamiReq = 8907; - public static final int UpgradeRoguelikeShikigamiRsp = 8493; - public static final int UseItemReq = 682; - public static final int UseItemRsp = 665; - public static final int UseMiracleRingReq = 5248; - public static final int UseMiracleRingRsp = 5243; - public static final int UseWidgetCreateGadgetReq = 4292; - public static final int UseWidgetCreateGadgetRsp = 4284; - public static final int UseWidgetRetractGadgetReq = 4283; - public static final int UseWidgetRetractGadgetRsp = 4277; - public static final int VehicleInteractReq = 844; - public static final int VehicleInteractRsp = 894; - public static final int VehicleStaminaNotify = 826; - public static final int ViewCodexReq = 4206; - public static final int ViewCodexRsp = 4204; - public static final int WatcherAllDataNotify = 2267; - public static final int WatcherChangeNotify = 2275; - public static final int WatcherEventNotify = 2254; - public static final int WatcherEventTypeNotify = 2264; - public static final int WaterSpritePhaseFinishNotify = 2096; - public static final int WeaponAwakenReq = 657; - public static final int WeaponAwakenRsp = 686; - public static final int WeaponPromoteReq = 619; - public static final int WeaponPromoteRsp = 644; - public static final int WeaponUpgradeReq = 656; - public static final int WeaponUpgradeRsp = 623; - public static final int WearEquipReq = 642; - public static final int WearEquipRsp = 629; - public static final int WidgetActiveChangeNotify = 4264; - public static final int WidgetCoolDownNotify = 4271; - public static final int WidgetDoBagReq = 4299; - public static final int WidgetDoBagRsp = 4295; - public static final int WidgetGadgetAllDataNotify = 4280; - public static final int WidgetGadgetDataNotify = 4273; - public static final int WidgetGadgetDestroyNotify = 4263; - public static final int WidgetReportReq = 4251; - public static final int WidgetReportRsp = 4252; - public static final int WidgetSlotChangeNotify = 4254; - public static final int WidgetUseAttachAbilityGroupChangeNotify = 4291; - public static final int WindSeedClientNotify = 1150; - public static final int WorktopOptionNotify = 864; - public static final int WorldAllRoutineTypeNotify = 3543; - public static final int WorldDataNotify = 3357; - public static final int WorldOwnerBlossomBriefInfoNotify = 2764; - public static final int WorldOwnerBlossomScheduleInfoNotify = 2714; - public static final int WorldOwnerDailyTaskNotify = 130; - public static final int WorldPlayerDieNotify = 277; - public static final int WorldPlayerInfoNotify = 3247; - public static final int WorldPlayerLocationNotify = 211; - public static final int WorldPlayerRTTNotify = 19; - public static final int WorldPlayerReviveReq = 262; - public static final int WorldPlayerReviveRsp = 268; - public static final int WorldRoutineChangeNotify = 3546; - public static final int WorldRoutineTypeCloseNotify = 3536; - public static final int WorldRoutineTypeRefreshNotify = 3509; - public static final int SkipPlayerGameTimeReq = 163; - public static final int SkipPlayerGameTimeRsp = 196; -} +package emu.grasscutter.net.packet; + +public class PacketOpcodes { + + // Empty + public static final int NONE = 0; + + // Opcodes + public static final int AbilityChangeNotify = 1159; + public static final int AbilityInvocationFailNotify = 1114; + public static final int AbilityInvocationFixedNotify = 1167; + public static final int AbilityInvocationsNotify = 1175; + public static final int AcceptCityReputationRequestReq = 2882; + public static final int AcceptCityReputationRequestRsp = 2865; + public static final int AchievementAllDataNotify = 2698; + public static final int AchievementUpdateNotify = 2693; + public static final int ActivityCoinInfoNotify = 2189; + public static final int ActivityCondStateChangeNotify = 2012; + public static final int ActivityDisableTransferPointInteractionNotify = 8969; + public static final int ActivityInfoNotify = 2134; + public static final int ActivityPlayOpenAnimNotify = 2136; + public static final int ActivitySaleChangeNotify = 2034; + public static final int ActivityScheduleInfoNotify = 2068; + public static final int ActivitySelectAvatarCardReq = 2043; + public static final int ActivitySelectAvatarCardRsp = 2130; + public static final int ActivityTakeAllScoreRewardReq = 8731; + public static final int ActivityTakeAllScoreRewardRsp = 8964; + public static final int ActivityTakeScoreRewardReq = 8869; + public static final int ActivityTakeScoreRewardRsp = 8852; + public static final int ActivityTakeWatcherRewardBatchReq = 2044; + public static final int ActivityTakeWatcherRewardBatchRsp = 2023; + public static final int ActivityTakeWatcherRewardReq = 2063; + public static final int ActivityTakeWatcherRewardRsp = 2082; + public static final int ActivityUpdateWatcherNotify = 2183; + public static final int AddBlacklistReq = 4041; + public static final int AddBlacklistRsp = 4070; + public static final int AddFriendNotify = 4019; + public static final int AddNoGachaAvatarCardNotify = 1787; + public static final int AddQuestContentProgressReq = 434; + public static final int AddQuestContentProgressRsp = 472; + public static final int AddRandTaskInfoNotify = 187; + public static final int AddSeenMonsterNotify = 235; + public static final int AdjustWorldLevelReq = 132; + public static final int AdjustWorldLevelRsp = 131; + public static final int AllCoopInfoNotify = 1998; + public static final int AllMarkPointNotify = 3156; + public static final int AllSeenMonsterNotify = 252; + public static final int AllWidgetDataNotify = 4300; + public static final int AnchorPointDataNotify = 4298; + public static final int AnchorPointOpReq = 4296; + public static final int AnchorPointOpRsp = 4286; + public static final int AnimatorForceSetAirMoveNotify = 337; + public static final int AntiAddictNotify = 103; + public static final int ArenaChallengeFinishNotify = 2169; + public static final int AskAddFriendNotify = 4044; + public static final int AskAddFriendReq = 4014; + public static final int AskAddFriendRsp = 4034; + public static final int AsterLargeInfoNotify = 2059; + public static final int AsterLittleInfoNotify = 2006; + public static final int AsterMidCampInfoNotify = 2142; + public static final int AsterMidInfoNotify = 2118; + public static final int AsterMiscInfoNotify = 2072; + public static final int AsterProgressInfoNotify = 2173; + public static final int AvatarAddNotify = 1756; + public static final int AvatarBuffAddNotify = 341; + public static final int AvatarBuffDelNotify = 370; + public static final int AvatarCardChangeReq = 641; + public static final int AvatarCardChangeRsp = 670; + public static final int AvatarChangeAnimHashReq = 1620; + public static final int AvatarChangeAnimHashRsp = 1694; + public static final int AvatarChangeCostumeNotify = 1759; + public static final int AvatarChangeCostumeReq = 1611; + public static final int AvatarChangeCostumeRsp = 1760; + public static final int AvatarChangeElementTypeReq = 1790; + public static final int AvatarChangeElementTypeRsp = 1781; + public static final int AvatarDataNotify = 1613; + public static final int AvatarDelNotify = 1621; + public static final int AvatarDieAnimationEndReq = 1665; + public static final int AvatarDieAnimationEndRsp = 1795; + public static final int AvatarEnterElementViewNotify = 326; + public static final int AvatarEquipAffixStartNotify = 1666; + public static final int AvatarEquipChangeNotify = 661; + public static final int AvatarExpeditionAllDataReq = 1748; + public static final int AvatarExpeditionAllDataRsp = 1671; + public static final int AvatarExpeditionCallBackReq = 1791; + public static final int AvatarExpeditionCallBackRsp = 1631; + public static final int AvatarExpeditionDataNotify = 1646; + public static final int AvatarExpeditionGetRewardReq = 1641; + public static final int AvatarExpeditionGetRewardRsp = 1707; + public static final int AvatarExpeditionStartReq = 1763; + public static final int AvatarExpeditionStartRsp = 1699; + public static final int AvatarFetterDataNotify = 1648; + public static final int AvatarFetterLevelRewardReq = 1653; + public static final int AvatarFetterLevelRewardRsp = 1691; + public static final int AvatarFightPropNotify = 1214; + public static final int AvatarFightPropUpdateNotify = 1234; + public static final int AvatarFlycloakChangeNotify = 1728; + public static final int AvatarFollowRouteNotify = 3300; + public static final int AvatarGainCostumeNotify = 1701; + public static final int AvatarGainFlycloakNotify = 1793; + public static final int AvatarLifeStateChangeNotify = 1282; + public static final int AvatarPromoteGetRewardReq = 1610; + public static final int AvatarPromoteGetRewardRsp = 1711; + public static final int AvatarPromoteReq = 1799; + public static final int AvatarPromoteRsp = 1681; + public static final int AvatarPropChangeReasonNotify = 1265; + public static final int AvatarPropNotify = 1259; + public static final int AvatarSatiationDataNotify = 1655; + public static final int AvatarSkillChangeNotify = 1042; + public static final int AvatarSkillDepotChangeNotify = 1064; + public static final int AvatarSkillInfoNotify = 1082; + public static final int AvatarSkillMaxChargeCountNotify = 1072; + public static final int AvatarSkillUpgradeReq = 1007; + public static final int AvatarSkillUpgradeRsp = 1091; + public static final int AvatarTeamUpdateNotify = 1744; + public static final int AvatarUnlockTalentNotify = 1054; + public static final int AvatarUpgradeReq = 1764; + public static final int AvatarUpgradeRsp = 1741; + public static final int AvatarWearFlycloakReq = 1700; + public static final int AvatarWearFlycloakRsp = 1745; + public static final int BackMyWorldReq = 280; + public static final int BackMyWorldRsp = 247; + public static final int BargainOfferPriceReq = 474; + public static final int BargainOfferPriceRsp = 446; + public static final int BargainStartNotify = 494; + public static final int BargainTerminateNotify = 484; + public static final int BattlePassAllDataNotify = 2648; + public static final int BattlePassBuySuccNotify = 2617; + public static final int BattlePassCurScheduleUpdateNotify = 2646; + public static final int BattlePassMissionDelNotify = 2609; + public static final int BattlePassMissionUpdateNotify = 2643; + public static final int BeginCameraSceneLookNotify = 260; + public static final int BigTalentPointConvertReq = 1014; + public static final int BigTalentPointConvertRsp = 1034; + public static final int BlessingAcceptAllGivePicReq = 2160; + public static final int BlessingAcceptAllGivePicRsp = 2159; + public static final int BlessingAcceptGivePicReq = 2091; + public static final int BlessingAcceptGivePicRsp = 2187; + public static final int BlessingGetAllRecvPicRecordListReq = 2010; + public static final int BlessingGetAllRecvPicRecordListRsp = 2111; + public static final int BlessingGetFriendPicListReq = 2128; + public static final int BlessingGetFriendPicListRsp = 2193; + public static final int BlessingGiveFriendPicReq = 2066; + public static final int BlessingGiveFriendPicRsp = 2053; + public static final int BlessingRecvFriendPicNotify = 2011; + public static final int BlessingRedeemRewardReq = 2100; + public static final int BlessingRedeemRewardRsp = 2145; + public static final int BlessingScanReq = 2004; + public static final int BlessingScanRsp = 2055; + public static final int BlitzRushParkourRestartReq = 8085; + public static final int BlitzRushParkourRestartRsp = 8538; + public static final int BlossomBriefInfoNotify = 2754; + public static final int BlossomChestCreateNotify = 2734; + public static final int BlossomChestInfoNotify = 882; + public static final int BonusActivityInfoReq = 2591; + public static final int BonusActivityInfoRsp = 2542; + public static final int BonusActivityUpdateNotify = 2507; + public static final int BossChestActivateNotify = 872; + public static final int BounceConjuringSettleNotify = 8434; + public static final int BuoyantCombatSettleNotify = 8387; + public static final int BuyBattlePassLevelReq = 2626; + public static final int BuyBattlePassLevelRsp = 2612; + public static final int BuyGoodsReq = 754; + public static final int BuyGoodsRsp = 764; + public static final int BuyResinReq = 630; + public static final int BuyResinRsp = 687; + public static final int CalcWeaponUpgradeReturnItemsReq = 601; + public static final int CalcWeaponUpgradeReturnItemsRsp = 698; + public static final int CanUseSkillNotify = 1027; + public static final int CancelCityReputationRequestReq = 2850; + public static final int CancelCityReputationRequestRsp = 2859; + public static final int CancelCoopTaskReq = 1976; + public static final int CancelCoopTaskRsp = 1962; + public static final int CancelFinishParentQuestNotify = 402; + public static final int CardProductRewardNotify = 4146; + public static final int ChallengeDataNotify = 923; + public static final int ChallengeRecordNotify = 974; + public static final int ChangeAvatarReq = 1704; + public static final int ChangeAvatarRsp = 1689; + public static final int ChangeGameTimeReq = 165; + public static final int ChangeGameTimeRsp = 150; + public static final int ChangeMailStarNotify = 1491; + public static final int ChangeMpTeamAvatarReq = 1660; + public static final int ChangeMpTeamAvatarRsp = 1747; + public static final int ChangeServerGlobalValueNotify = 46; + public static final int ChangeTeamNameReq = 1692; + public static final int ChangeTeamNameRsp = 1664; + public static final int ChangeWorldToSingleModeNotify = 3025; + public static final int ChangeWorldToSingleModeReq = 3243; + public static final int ChangeWorldToSingleModeRsp = 3271; + public static final int ChannelerSlabCheckEnterLoopDungeonReq = 8678; + public static final int ChannelerSlabCheckEnterLoopDungeonRsp = 8961; + public static final int ChannelerSlabEnterLoopDungeonReq = 8928; + public static final int ChannelerSlabEnterLoopDungeonRsp = 8892; + public static final int ChannelerSlabLoopDungeonChallengeInfoNotify = 8499; + public static final int ChannelerSlabLoopDungeonSelectConditionReq = 8368; + public static final int ChannelerSlabLoopDungeonSelectConditionRsp = 8943; + public static final int ChannelerSlabLoopDungeonTakeFirstPassRewardReq = 8779; + public static final int ChannelerSlabLoopDungeonTakeFirstPassRewardRsp = 8654; + public static final int ChannelerSlabLoopDungeonTakeScoreRewardReq = 8751; + public static final int ChannelerSlabLoopDungeonTakeScoreRewardRsp = 8186; + public static final int ChannelerSlabOneOffDungeonInfoNotify = 8038; + public static final int ChannelerSlabOneOffDungeonInfoReq = 8069; + public static final int ChannelerSlabOneOffDungeonInfoRsp = 8731; + public static final int ChannelerSlabSaveAssistInfoReq = 8304; + public static final int ChannelerSlabSaveAssistInfoRsp = 8443; + public static final int ChannelerSlabStageActiveChallengeIndexNotify = 8647; + public static final int ChannelerSlabStageOneofDungeonNotify = 8203; + public static final int ChannelerSlabTakeoffBuffReq = 8329; + public static final int ChannelerSlabTakeoffBuffRsp = 8646; + public static final int ChannelerSlabWearBuffReq = 8487; + public static final int ChannelerSlabWearBuffRsp = 8651; + public static final int ChapterStateNotify = 427; + public static final int ChatChannelDataNotify = 5041; + public static final int ChatChannelUpdateNotify = 4957; + public static final int ChatHistoryNotify = 3301; + public static final int CheckAddItemExceedLimitNotify = 685; + public static final int CheckSegmentCRCNotify = 56; + public static final int CheckSegmentCRCReq = 23; + public static final int ChessEscapedMonstersNotify = 5389; + public static final int ChessLeftMonstersNotify = 5376; + public static final int ChessManualRefreshCardsReq = 5306; + public static final int ChessManualRefreshCardsRsp = 5390; + public static final int ChessPickCardNotify = 5303; + public static final int ChessPickCardReq = 5301; + public static final int ChessPickCardRsp = 5398; + public static final int ChessPlayerInfoNotify = 5392; + public static final int ChessSelectedCardsNotify = 5385; + public static final int ChooseCurAvatarTeamReq = 1650; + public static final int ChooseCurAvatarTeamRsp = 1625; + public static final int CityReputationDataNotify = 2827; + public static final int CityReputationLevelupNotify = 2814; + public static final int ClearRoguelikeCurseNotify = 8565; + public static final int ClientAIStateNotify = 1129; + public static final int ClientAbilitiesInitFinishCombineNotify = 1172; + public static final int ClientAbilityChangeNotify = 1107; + public static final int ClientAbilityInitBeginNotify = 1154; + public static final int ClientAbilityInitFinishNotify = 1164; + public static final int ClientBulletCreateNotify = 94; + public static final int ClientCollectorDataNotify = 4267; + public static final int ClientHashDebugNotify = 3234; + public static final int ClientLoadingCostumeVerificationNotify = 3387; + public static final int ClientLockGameTimeNotify = 189; + public static final int ClientNewMailNotify = 1450; + public static final int ClientPauseNotify = 276; + public static final int ClientReconnectNotify = 7; + public static final int ClientReportNotify = 29; + public static final int ClientScriptEventNotify = 248; + public static final int ClientTransmitReq = 271; + public static final int ClientTransmitRsp = 202; + public static final int ClientTriggerEventNotify = 191; + public static final int CloseCommonTipsNotify = 3196; + public static final int ClosedItemNotify = 689; + public static final int CodexDataFullNotify = 4203; + public static final int CodexDataUpdateNotify = 4207; + public static final int CombatInvocationsNotify = 387; + public static final int CombineDataNotify = 690; + public static final int CombineFormulaDataNotify = 692; + public static final int CombineReq = 616; + public static final int CombineRsp = 637; + public static final int CommonPlayerTipsNotify = 8076; + public static final int CompoundDataNotify = 118; + public static final int CompoundUnlockNotify = 155; + public static final int CookDataNotify = 157; + public static final int CookGradeDataNotify = 126; + public static final int CookRecipeDataNotify = 186; + public static final int CoopCgShowNotify = 1957; + public static final int CoopCgUpdateNotify = 1989; + public static final int CoopChapterUpdateNotify = 1982; + public static final int CoopDataNotify = 1994; + public static final int CoopPointUpdateNotify = 1951; + public static final int CoopProgressUpdateNotify = 1990; + public static final int CoopRewardUpdateNotify = 1981; + public static final int CreateMassiveEntityNotify = 340; + public static final int CreateMassiveEntityReq = 349; + public static final int CreateMassiveEntityRsp = 397; + public static final int CreateVehicleReq = 874; + public static final int CreateVehicleRsp = 846; + public static final int CutSceneBeginNotify = 295; + public static final int CutSceneEndNotify = 283; + public static final int CutSceneFinishNotify = 228; + public static final int DailyTaskDataNotify = 111; + public static final int DailyTaskFilterCityReq = 199; + public static final int DailyTaskFilterCityRsp = 178; + public static final int DailyTaskProgressNotify = 160; + public static final int DailyTaskScoreRewardNotify = 193; + public static final int DailyTaskUnlockedCitiesNotify = 180; + public static final int DataResVersionNotify = 140; + public static final int DealAddFriendReq = 4072; + public static final int DealAddFriendRsp = 4082; + public static final int DebugNotify = 101; + public static final int DelMailReq = 1434; + public static final int DelMailRsp = 1472; + public static final int DelScenePlayTeamEntityNotify = 3214; + public static final int DelTeamEntityNotify = 330; + public static final int DeleteFriendNotify = 4023; + public static final int DeleteFriendReq = 4059; + public static final int DeleteFriendRsp = 4007; + public static final int DestroyMassiveEntityNotify = 311; + public static final int DestroyMaterialReq = 608; + public static final int DestroyMaterialRsp = 679; + public static final int DigActivityChangeGadgetStateReq = 8140; + public static final int DigActivityChangeGadgetStateRsp = 8656; + public static final int DigActivityMarkPointChangeNotify = 8585; + public static final int DisableRoguelikeTrapNotify = 8007; + public static final int DoGachaReq = 1554; + public static final int DoGachaRsp = 1564; + public static final int DoRoguelikeDungeonCardGachaReq = 8427; + public static final int DoRoguelikeDungeonCardGachaRsp = 8567; + public static final int DoSetPlayerBornDataNotify = 161; + public static final int DraftGuestReplyInviteNotify = 5482; + public static final int DraftGuestReplyInviteReq = 5434; + public static final int DraftGuestReplyInviteRsp = 5472; + public static final int DraftGuestReplyTwiceConfirmNotify = 5442; + public static final int DraftGuestReplyTwiceConfirmReq = 5459; + public static final int DraftGuestReplyTwiceConfirmRsp = 5407; + public static final int DraftInviteResultNotify = 5465; + public static final int DraftOwnerInviteNotify = 5414; + public static final int DraftOwnerStartInviteReq = 5454; + public static final int DraftOwnerStartInviteRsp = 5464; + public static final int DraftOwnerTwiceConfirmNotify = 5450; + public static final int DraftTwiceConfirmResultNotify = 5491; + public static final int DragonSpineChapterFinishNotify = 2182; + public static final int DragonSpineChapterOpenNotify = 2126; + public static final int DragonSpineChapterProgressChangeNotify = 2155; + public static final int DragonSpineCoinChangeNotify = 2076; + public static final int DropHintNotify = 633; + public static final int DropItemReq = 650; + public static final int DropItemRsp = 659; + public static final int DungeonCandidateTeamChangeAvatarReq = 988; + public static final int DungeonCandidateTeamChangeAvatarRsp = 949; + public static final int DungeonCandidateTeamCreateReq = 957; + public static final int DungeonCandidateTeamCreateRsp = 986; + public static final int DungeonCandidateTeamDismissNotify = 913; + public static final int DungeonCandidateTeamInfoNotify = 946; + public static final int DungeonCandidateTeamInviteNotify = 984; + public static final int DungeonCandidateTeamInviteReq = 926; + public static final int DungeonCandidateTeamInviteRsp = 933; + public static final int DungeonCandidateTeamKickReq = 916; + public static final int DungeonCandidateTeamKickRsp = 937; + public static final int DungeonCandidateTeamLeaveReq = 925; + public static final int DungeonCandidateTeamLeaveRsp = 918; + public static final int DungeonCandidateTeamPlayerLeaveNotify = 970; + public static final int DungeonCandidateTeamRefuseNotify = 941; + public static final int DungeonCandidateTeamReplyInviteReq = 958; + public static final int DungeonCandidateTeamReplyInviteRsp = 905; + public static final int DungeonCandidateTeamSetChangingAvatarReq = 979; + public static final int DungeonCandidateTeamSetChangingAvatarRsp = 945; + public static final int DungeonCandidateTeamSetReadyReq = 971; + public static final int DungeonCandidateTeamSetReadyRsp = 902; + public static final int DungeonChallengeBeginNotify = 961; + public static final int DungeonChallengeFinishNotify = 956; + public static final int DungeonDataNotify = 966; + public static final int DungeonDieOptionReq = 907; + public static final int DungeonDieOptionRsp = 991; + public static final int DungeonEntryInfoReq = 967; + public static final int DungeonEntryInfoRsp = 975; + public static final int DungeonEntryToBeExploreNotify = 3313; + public static final int DungeonFollowNotify = 919; + public static final int DungeonGetStatueDropReq = 944; + public static final int DungeonGetStatueDropRsp = 994; + public static final int DungeonInterruptChallengeReq = 993; + public static final int DungeonInterruptChallengeRsp = 930; + public static final int DungeonPlayerDieNotify = 959; + public static final int DungeonPlayerDieReq = 929; + public static final int DungeonPlayerDieRsp = 927; + public static final int DungeonRestartInviteNotify = 904; + public static final int DungeonRestartInviteReplyNotify = 936; + public static final int DungeonRestartInviteReplyReq = 920; + public static final int DungeonRestartInviteReplyRsp = 943; + public static final int DungeonRestartReq = 953; + public static final int DungeonRestartResultNotify = 908; + public static final int DungeonRestartRsp = 938; + public static final int DungeonReviseLevelNotify = 901; + public static final int DungeonSettleNotify = 950; + public static final int DungeonShowReminderNotify = 942; + public static final int DungeonSlipRevivePointActivateReq = 911; + public static final int DungeonSlipRevivePointActivateRsp = 960; + public static final int DungeonWayPointActivateReq = 982; + public static final int DungeonWayPointActivateRsp = 965; + public static final int DungeonWayPointNotify = 972; + public static final int EchoNotify = 44; + public static final int EchoShellTakeRewardReq = 8078; + public static final int EchoShellTakeRewardRsp = 8523; + public static final int EchoShellUpdateNotify = 8377; + public static final int EffigyChallengeInfoNotify = 2038; + public static final int EffigyChallengeResultNotify = 2028; + public static final int EndCameraSceneLookNotify = 293; + public static final int EnterChessDungeonReq = 8341; + public static final int EnterChessDungeonRsp = 8947; + public static final int EnterFishingReq = 5848; + public static final int EnterFishingRsp = 5843; + public static final int EnterMechanicusDungeonReq = 3959; + public static final int EnterMechanicusDungeonRsp = 3907; + public static final int EnterRoguelikeDungeonNotify = 8557; + public static final int EnterSceneDoneReq = 269; + public static final int EnterSceneDoneRsp = 281; + public static final int EnterScenePeerNotify = 215; + public static final int EnterSceneReadyReq = 300; + public static final int EnterSceneReadyRsp = 239; + public static final int EnterSceneWeatherAreaNotify = 288; + public static final int EnterTransPointRegionNotify = 227; + public static final int EnterTrialAvatarActivityDungeonReq = 2084; + public static final int EnterTrialAvatarActivityDungeonRsp = 2154; + public static final int EnterWorldAreaReq = 233; + public static final int EnterWorldAreaRsp = 216; + public static final int EntityAiKillSelfNotify = 308; + public static final int EntityAiSyncNotify = 320; + public static final int EntityAuthorityChangeNotify = 384; + public static final int EntityConfigHashNotify = 3103; + public static final int EntityFightPropChangeReasonNotify = 1272; + public static final int EntityFightPropNotify = 1254; + public static final int EntityFightPropUpdateNotify = 1264; + public static final int EntityForceSyncReq = 237; + public static final int EntityForceSyncRsp = 225; + public static final int EntityJumpNotify = 219; + public static final int EntityMoveRoomNotify = 3060; + public static final int EntityPropNotify = 1267; + public static final int EntityTagChangeNotify = 3428; + public static final int EquipRoguelikeRuneReq = 8526; + public static final int EquipRoguelikeRuneRsp = 8572; + public static final int EvtAiSyncCombatThreatInfoNotify = 338; + public static final int EvtAiSyncSkillCdNotify = 325; + public static final int EvtAnimatorParameterNotify = 375; + public static final int EvtAnimatorStateChangedNotify = 359; + public static final int EvtAvatarEnterFocusNotify = 394; + public static final int EvtAvatarExitFocusNotify = 374; + public static final int EvtAvatarLockChairReq = 379; + public static final int EvtAvatarLockChairRsp = 345; + public static final int EvtAvatarSitDownNotify = 302; + public static final int EvtAvatarStandUpNotify = 388; + public static final int EvtAvatarUpdateFocusNotify = 346; + public static final int EvtBeingHitNotify = 367; + public static final int EvtBeingHitsCombineNotify = 318; + public static final int EvtBulletDeactiveNotify = 342; + public static final int EvtBulletHitNotify = 391; + public static final int EvtBulletMoveNotify = 344; + public static final int EvtCostStaminaNotify = 365; + public static final int EvtCreateGadgetNotify = 314; + public static final int EvtDestroyGadgetNotify = 334; + public static final int EvtDestroyServerGadgetNotify = 336; + public static final int EvtDoSkillSuccNotify = 364; + public static final int EvtEntityRenderersChangedNotify = 316; + public static final int EvtEntityStartDieEndNotify = 329; + public static final int EvtFaceToDirNotify = 382; + public static final int EvtFaceToEntityNotify = 372; + public static final int EvtRushMoveNotify = 307; + public static final int EvtSetAttackTargetNotify = 350; + public static final int ExecuteGadgetLuaReq = 217; + public static final int ExecuteGadgetLuaRsp = 224; + public static final int ExecuteGroupTriggerReq = 204; + public static final int ExecuteGroupTriggerRsp = 220; + public static final int ExitFishingReq = 5817; + public static final int ExitFishingRsp = 5826; + public static final int ExitSceneWeatherAreaNotify = 249; + public static final int ExitTransPointRegionNotify = 266; + public static final int ExpeditionChallengeEnterRegionNotify = 2077; + public static final int ExpeditionChallengeFinishedNotify = 2075; + public static final int ExpeditionRecallReq = 2008; + public static final int ExpeditionRecallRsp = 2015; + public static final int ExpeditionStartReq = 2002; + public static final int ExpeditionStartRsp = 2177; + public static final int ExpeditionTakeRewardReq = 2129; + public static final int ExpeditionTakeRewardRsp = 2158; + public static final int FindHilichurlAcceptQuestNotify = 8170; + public static final int FindHilichurlFinishSecondQuestNotify = 8326; + public static final int FinishDeliveryNotify = 2110; + public static final int FinishMainCoopReq = 1986; + public static final int FinishMainCoopRsp = 1965; + public static final int FinishedParentQuestNotify = 464; + public static final int FinishedParentQuestUpdateNotify = 414; + public static final int FireworkNotify = 5934; + public static final int FireworkReq = 6068; + public static final int FireworkRsp = 5918; + public static final int FireworkSetNotify = 6079; + public static final int FireworkSetReq = 6099; + public static final int FireworkSetRsp = 5969; + public static final int FishAttractNotify = 5812; + public static final int FishBaitGoneNotify = 5825; + public static final int FishBattleBeginReq = 5835; + public static final int FishBattleBeginRsp = 5821; + public static final int FishBattleEndReq = 5801; + public static final int FishBattleEndRsp = 5802; + public static final int FishBiteReq = 5839; + public static final int FishBiteRsp = 5831; + public static final int FishCastRodReq = 5836; + public static final int FishCastRodRsp = 5815; + public static final int FishChosenNotify = 5844; + public static final int FishEscapeNotify = 5832; + public static final int FishPoolDataNotify = 5840; + public static final int FishingGallerySettleNotify = 8594; + public static final int FleurFairBalloonSettleNotify = 2200; + public static final int FleurFairBuffEnergyNotify = 5302; + public static final int FleurFairFallSettleNotify = 2027; + public static final int FleurFairFinishGalleryStageNotify = 5349; + public static final int FleurFairMusicGameSettleReq = 2086; + public static final int FleurFairMusicGameSettleRsp = 2033; + public static final int FleurFairMusicGameStartReq = 2150; + public static final int FleurFairMusicGameStartRsp = 2174; + public static final int FleurFairReplayMiniGameReq = 2165; + public static final int FleurFairReplayMiniGameRsp = 2192; + public static final int FleurFairStageSettleNotify = 5388; + public static final int FlightActivityRestartReq = 2039; + public static final int FlightActivityRestartRsp = 2093; + public static final int FlightActivitySettleNotify = 2115; + public static final int FocusAvatarReq = 1712; + public static final int FocusAvatarRsp = 1604; + public static final int ForceAddPlayerFriendReq = 4004; + public static final int ForceAddPlayerFriendRsp = 4020; + public static final int ForceDragAvatarNotify = 3017; + public static final int ForceDragBackTransferNotify = 3245; + public static final int ForgeDataNotify = 603; + public static final int ForgeFormulaDataNotify = 606; + public static final int ForgeGetQueueDataReq = 618; + public static final int ForgeGetQueueDataRsp = 658; + public static final int ForgeQueueDataNotify = 625; + public static final int ForgeQueueManipulateReq = 602; + public static final int ForgeQueueManipulateRsp = 688; + public static final int ForgeStartReq = 605; + public static final int ForgeStartRsp = 671; + public static final int FoundationNotify = 861; + public static final int FoundationReq = 827; + public static final int FoundationRsp = 866; + public static final int FriendInfoChangeNotify = 4092; + public static final int FunitureMakeMakeInfoChangeNotify = 4588; + public static final int FurnitureCurModuleArrangeCountNotify = 4864; + public static final int FurnitureMakeBeHelpedNotify = 4694; + public static final int FurnitureMakeCancelReq = 4619; + public static final int FurnitureMakeCancelRsp = 4825; + public static final int FurnitureMakeFinishNotify = 4658; + public static final int FurnitureMakeHelpReq = 4851; + public static final int FurnitureMakeHelpRsp = 4841; + public static final int FurnitureMakeReq = 4681; + public static final int FurnitureMakeRsp = 4506; + public static final int FurnitureMakeStartReq = 4552; + public static final int FurnitureMakeStartRsp = 4487; + public static final int GMShowNavMeshReq = 2304; + public static final int GMShowNavMeshRsp = 2320; + public static final int GMShowObstacleReq = 2353; + public static final int GMShowObstacleRsp = 2338; + public static final int GachaOpenWishNotify = 1572; + public static final int GachaSimpleInfoNotify = 1582; + public static final int GachaWishReq = 1514; + public static final int GachaWishRsp = 1534; + public static final int GadgetAutoPickDropInfoNotify = 842; + public static final int GadgetChainLevelChangeNotify = 819; + public static final int GadgetChainLevelUpdateNotify = 823; + public static final int GadgetCustomTreeInfoNotify = 833; + public static final int GadgetGeneralRewardInfoNotify = 891; + public static final int GadgetInteractReq = 867; + public static final int GadgetInteractRsp = 875; + public static final int GadgetPlayDataNotify = 859; + public static final int GadgetPlayStartNotify = 865; + public static final int GadgetPlayStopNotify = 850; + public static final int GadgetPlayUidOpNotify = 807; + public static final int GadgetStateNotify = 854; + public static final int GadgetTalkChangeNotify = 856; + public static final int GalleryBalloonScoreNotify = 5554; + public static final int GalleryBalloonShootNotify = 5575; + public static final int GalleryBounceConjuringHitNotify = 5527; + public static final int GalleryBrokenFloorFallNotify = 5507; + public static final int GalleryBulletHitNotify = 5559; + public static final int GalleryFallCatchNotify = 5514; + public static final int GalleryFallScoreNotify = 5534; + public static final int GalleryFlowerCatchNotify = 5565; + public static final int GalleryPreStartNotify = 5550; + public static final int GalleryStartNotify = 5567; + public static final int GalleryStopNotify = 5564; + public static final int GallerySumoKillMonsterNotify = 5566; + public static final int GetActivityInfoReq = 2116; + public static final int GetActivityInfoRsp = 2140; + public static final int GetActivityScheduleReq = 2153; + public static final int GetActivityScheduleRsp = 2032; + public static final int GetActivityShopSheetInfoReq = 772; + public static final int GetActivityShopSheetInfoRsp = 782; + public static final int GetAllActivatedBargainDataReq = 413; + public static final int GetAllActivatedBargainDataRsp = 457; + public static final int GetAllH5ActivityInfoReq = 5693; + public static final int GetAllH5ActivityInfoRsp = 5698; + public static final int GetAllMailReq = 1459; + public static final int GetAllMailRsp = 1407; + public static final int GetAllSceneGalleryInfoReq = 5572; + public static final int GetAllSceneGalleryInfoRsp = 5582; + public static final int GetAllUnlockNameCardReq = 4046; + public static final int GetAllUnlockNameCardRsp = 4084; + public static final int GetAreaExplorePointReq = 258; + public static final int GetAreaExplorePointRsp = 205; + public static final int GetAuthSalesmanInfoReq = 2139; + public static final int GetAuthSalesmanInfoRsp = 2123; + public static final int GetAuthkeyReq = 1482; + public static final int GetAuthkeyRsp = 1465; + public static final int GetBargainDataReq = 441; + public static final int GetBargainDataRsp = 470; + public static final int GetBattlePassProductReq = 2639; + public static final int GetBattlePassProductRsp = 2631; + public static final int GetBlossomBriefInfoListReq = 2767; + public static final int GetBlossomBriefInfoListRsp = 2775; + public static final int GetBonusActivityRewardReq = 2529; + public static final int GetBonusActivityRewardRsp = 2527; + public static final int GetChatEmojiCollectionReq = 4021; + public static final int GetChatEmojiCollectionRsp = 4001; + public static final int GetCityHuntingOfferReq = 4309; + public static final int GetCityHuntingOfferRsp = 4346; + public static final int GetCityReputationInfoReq = 2867; + public static final int GetCityReputationInfoRsp = 2875; + public static final int GetCityReputationMapInfoReq = 2807; + public static final int GetCityReputationMapInfoRsp = 2891; + public static final int GetCompoundDataReq = 158; + public static final int GetCompoundDataRsp = 105; + public static final int GetDailyDungeonEntryInfoReq = 997; + public static final int GetDailyDungeonEntryInfoRsp = 940; + public static final int GetDungeonEntryExploreConditionReq = 3449; + public static final int GetDungeonEntryExploreConditionRsp = 3413; + public static final int GetExpeditionAssistInfoListReq = 2180; + public static final int GetExpeditionAssistInfoListRsp = 2197; + public static final int GetFriendShowAvatarInfoReq = 4060; + public static final int GetFriendShowAvatarInfoRsp = 4093; + public static final int GetFriendShowNameCardInfoReq = 4053; + public static final int GetFriendShowNameCardInfoRsp = 4038; + public static final int GetFurnitureCurModuleArrangeCountReq = 4899; + public static final int GetGachaInfoReq = 1567; + public static final int GetGachaInfoRsp = 1575; + public static final int GetHomeLevelUpRewardReq = 4821; + public static final int GetHomeLevelUpRewardRsp = 4585; + public static final int GetHuntingOfferRewardReq = 4336; + public static final int GetHuntingOfferRewardRsp = 4315; + public static final int GetInvestigationMonsterReq = 1909; + public static final int GetInvestigationMonsterRsp = 1923; + public static final int GetMailItemReq = 1464; + public static final int GetMailItemRsp = 1414; + public static final int GetMapAreaReq = 3084; + public static final int GetMapAreaRsp = 3458; + public static final int GetMapMarkTipsReq = 3342; + public static final int GetMapMarkTipsRsp = 3465; + public static final int GetMechanicusInfoReq = 3967; + public static final int GetMechanicusInfoRsp = 3975; + public static final int GetNextResourceInfoReq = 185; + public static final int GetNextResourceInfoRsp = 173; + public static final int GetOnlinePlayerInfoReq = 66; + public static final int GetOnlinePlayerInfoRsp = 61; + public static final int GetOnlinePlayerListReq = 82; + public static final int GetOnlinePlayerListRsp = 65; + public static final int GetOpActivityInfoReq = 5167; + public static final int GetOpActivityInfoRsp = 5175; + public static final int GetPlayerAskFriendListReq = 4079; + public static final int GetPlayerAskFriendListRsp = 4045; + public static final int GetPlayerBlacklistReq = 4005; + public static final int GetPlayerBlacklistRsp = 4071; + public static final int GetPlayerFriendListReq = 4067; + public static final int GetPlayerFriendListRsp = 4075; + public static final int GetPlayerHomeCompInfoReq = 4511; + public static final int GetPlayerMpModeAvailabilityReq = 1839; + public static final int GetPlayerMpModeAvailabilityRsp = 1831; + public static final int GetPlayerSocialDetailReq = 4065; + public static final int GetPlayerSocialDetailRsp = 4050; + public static final int GetPlayerTokenReq = 167; + public static final int GetPlayerTokenRsp = 175; + public static final int GetPushTipsRewardReq = 2246; + public static final int GetPushTipsRewardRsp = 2284; + public static final int GetQuestTalkHistoryReq = 482; + public static final int GetQuestTalkHistoryRsp = 465; + public static final int GetRecentMpPlayerListReq = 4026; + public static final int GetRecentMpPlayerListRsp = 4033; + public static final int GetRegionSearchReq = 5636; + public static final int GetReunionMissionInfoReq = 5089; + public static final int GetReunionMissionInfoRsp = 5081; + public static final int GetReunionPrivilegeInfoReq = 5076; + public static final int GetReunionPrivilegeInfoRsp = 5062; + public static final int GetReunionSignInInfoReq = 5086; + public static final int GetReunionSignInInfoRsp = 5065; + public static final int GetSceneAreaReq = 244; + public static final int GetSceneAreaRsp = 294; + public static final int GetSceneNpcPositionReq = 564; + public static final int GetSceneNpcPositionRsp = 514; + public static final int GetScenePerformanceReq = 3283; + public static final int GetScenePerformanceRsp = 3274; + public static final int GetScenePointReq = 242; + public static final int GetScenePointRsp = 229; + public static final int GetShopReq = 767; + public static final int GetShopRsp = 775; + public static final int GetShopmallDataReq = 714; + public static final int GetShopmallDataRsp = 734; + public static final int GetSignInRewardReq = 2514; + public static final int GetSignInRewardRsp = 2534; + public static final int GetWidgetSlotReq = 4255; + public static final int GetWidgetSlotRsp = 4266; + public static final int GetWorldMpInfoReq = 3479; + public static final int GetWorldMpInfoRsp = 3118; + public static final int GiveUpRoguelikeDungeonCardReq = 8292; + public static final int GiveUpRoguelikeDungeonCardRsp = 8752; + public static final int GivingRecordChangeNotify = 136; + public static final int GivingRecordNotify = 143; + public static final int GmTalkNotify = 84; + public static final int GmTalkReq = 75; + public static final int GmTalkRsp = 54; + public static final int GrantRewardNotify = 613; + public static final int GroupLinkAllNotify = 5798; + public static final int GroupLinkChangeNotify = 5793; + public static final int GroupLinkDeleteNotify = 5759; + public static final int GroupSuiteNotify = 3263; + public static final int GroupUnloadNotify = 3167; + public static final int GuestBeginEnterSceneNotify = 3195; + public static final int GuestPostEnterSceneNotify = 3012; + public static final int H5ActivityIdsNotify = 5659; + public static final int HideAndSeekPlayerReadyNotify = 5330; + public static final int HideAndSeekPlayerSetAvatarNotify = 5387; + public static final int HideAndSeekSelectAvatarReq = 5397; + public static final int HideAndSeekSelectAvatarRsp = 5340; + public static final int HideAndSeekSelectSkillReq = 8896; + public static final int HideAndSeekSelectSkillRsp = 8715; + public static final int HideAndSeekSetReadyReq = 5311; + public static final int HideAndSeekSetReadyRsp = 5360; + public static final int HideAndSeekSettleNotify = 5393; + public static final int HitClientTrivialNotify = 278; + public static final int HitTreeNotify = 3299; + public static final int HomeAvatarAllFinishRewardNotify = 4504; + public static final int HomeAvatarCostumeChangeNotify = 4651; + public static final int HomeAvatarRewardEventGetReq = 4859; + public static final int HomeAvatarRewardEventGetRsp = 4784; + public static final int HomeAvatarRewardEventNotify = 4682; + public static final int HomeAvatarSummonAllEventNotify = 4892; + public static final int HomeAvatarSummonEventReq = 4708; + public static final int HomeAvatarSummonEventRsp = 4633; + public static final int HomeAvatarSummonFinishReq = 4510; + public static final int HomeAvatarSummonFinishRsp = 4566; + public static final int HomeAvatarTalkFinishInfoNotify = 4517; + public static final int HomeAvatarTalkReq = 4603; + public static final int HomeAvatarTalkRsp = 4484; + public static final int HomeAvtarAllFinishRewardNotify = 4480; + public static final int HomeBasicInfoNotify = 4501; + public static final int HomeBlockNotify = 4857; + public static final int HomeChangeEditModeReq = 4533; + public static final int HomeChangeEditModeRsp = 4862; + public static final int HomeChangeModuleReq = 4789; + public static final int HomeChangeModuleRsp = 4876; + public static final int HomeChooseModuleReq = 4843; + public static final int HomeChooseModuleRsp = 4736; + public static final int HomeComfortInfoNotify = 4816; + public static final int HomeCustomFurnitureInfoNotify = 4647; + public static final int HomeEditCustomFurnitureReq = 4558; + public static final int HomeEditCustomFurnitureRsp = 4749; + public static final int HomeFishFarmingInfoNotify = 4807; + public static final int HomeGetArrangementInfoReq = 4538; + public static final int HomeGetArrangementInfoRsp = 4704; + public static final int HomeGetBasicInfoReq = 4817; + public static final int HomeGetFishFarmingInfoReq = 4575; + public static final int HomeGetFishFarmingInfoRsp = 4849; + public static final int HomeGetOnlineStatusReq = 4589; + public static final int HomeGetOnlineStatusRsp = 4642; + public static final int HomeKickPlayerReq = 4610; + public static final int HomeKickPlayerRsp = 4889; + public static final int HomeLimitedShopBuyGoodsReq = 4471; + public static final int HomeLimitedShopBuyGoodsRsp = 4883; + public static final int HomeLimitedShopGoodsListReq = 4769; + public static final int HomeLimitedShopGoodsListRsp = 4451; + public static final int HomeLimitedShopInfoChangeNotify = 4722; + public static final int HomeLimitedShopInfoNotify = 4584; + public static final int HomeLimitedShopInfoReq = 4476; + public static final int HomeLimitedShopInfoRsp = 4791; + public static final int HomeMarkPointNotify = 4697; + public static final int HomeModuleSeenReq = 4672; + public static final int HomeModuleSeenRsp = 4507; + public static final int HomeModuleUnlockNotify = 4700; + public static final int HomePlantFieldNotify = 4710; + public static final int HomePlantInfoNotify = 4545; + public static final int HomePlantInfoReq = 4645; + public static final int HomePlantInfoRsp = 4848; + public static final int HomePlantSeedReq = 4607; + public static final int HomePlantSeedRsp = 4546; + public static final int HomePlantWeedReq = 4614; + public static final int HomePlantWeedRsp = 4671; + public static final int HomePriorCheckNotify = 4872; + public static final int HomeResourceNotify = 4753; + public static final int HomeResourceTakeFetterExpReq = 4534; + public static final int HomeResourceTakeFetterExpRsp = 4808; + public static final int HomeResourceTakeHomeCoinReq = 4688; + public static final int HomeResourceTakeHomeCoinRsp = 4554; + public static final int HomeSceneInitFinishReq = 4900; + public static final int HomeSceneInitFinishRsp = 4780; + public static final int HomeSceneJumpReq = 4665; + public static final int HomeSceneJumpRsp = 4482; + public static final int HomeTransferReq = 4537; + public static final int HomeTransferRsp = 4623; + public static final int HomeUpdateArrangementInfoReq = 4840; + public static final int HomeUpdateArrangementInfoRsp = 4776; + public static final int HomeUpdateFishFarmingInfoReq = 4746; + public static final int HomeUpdateFishFarmingInfoRsp = 4551; + public static final int HostPlayerNotify = 354; + public static final int HuntingFailNotify = 4335; + public static final int HuntingGiveUpReq = 4301; + public static final int HuntingGiveUpRsp = 4302; + public static final int HuntingOngoingNotify = 4321; + public static final int HuntingRevealClueNotify = 4332; + public static final int HuntingRevealFinalNotify = 4339; + public static final int HuntingStartNotify = 4344; + public static final int HuntingSuccessNotify = 4331; + public static final int InBattleMechanicusBuildingPointsNotify = 5372; + public static final int InBattleMechanicusCardResultNotify = 5342; + public static final int InBattleMechanicusConfirmCardNotify = 5391; + public static final int InBattleMechanicusConfirmCardReq = 5359; + public static final int InBattleMechanicusConfirmCardRsp = 5307; + public static final int InBattleMechanicusEscapeMonsterNotify = 5320; + public static final int InBattleMechanicusLeftMonsterNotify = 5334; + public static final int InBattleMechanicusPickCardNotify = 5350; + public static final int InBattleMechanicusPickCardReq = 5382; + public static final int InBattleMechanicusPickCardRsp = 5365; + public static final int InBattleMechanicusSettleNotify = 5327; + public static final int InteractDailyDungeonInfoNotify = 987; + public static final int InterruptGalleryReq = 5591; + public static final int InterruptGalleryRsp = 5542; + public static final int InvestigationMonsterUpdateNotify = 1920; + public static final int ItemAddHintNotify = 614; + public static final int ItemCdGroupTimeNotify = 626; + public static final int ItemGivingReq = 108; + public static final int ItemGivingRsp = 179; + public static final int JoinHomeWorldFailNotify = 4847; + public static final int JoinPlayerFailNotify = 251; + public static final int JoinPlayerSceneReq = 285; + public static final int JoinPlayerSceneRsp = 273; + public static final int KeepAliveNotify = 67; + public static final int LeaveSceneReq = 275; + public static final int LeaveSceneRsp = 254; + public static final int LeaveWorldNotify = 3009; + public static final int LevelupCityReq = 243; + public static final int LevelupCityRsp = 236; + public static final int LifeStateChangeNotify = 1275; + public static final int LiveEndNotify = 886; + public static final int LiveStartNotify = 870; + public static final int LoadActivityTerrainNotify = 2146; + public static final int LuaEnvironmentEffectNotify = 3136; + public static final int LuaSetOptionNotify = 343; + public static final int LunaRiteAreaFinishNotify = 8956; + public static final int LunaRiteGroupBundleRegisterNotify = 8279; + public static final int LunaRiteHintPointRemoveNotify = 8793; + public static final int LunaRiteHintPointReq = 8114; + public static final int LunaRiteHintPointRsp = 8873; + public static final int LunaRiteSacrificeReq = 8182; + public static final int LunaRiteSacrificeRsp = 8159; + public static final int LunaRiteTakeSacrificeRewardReq = 8999; + public static final int LunaRiteTakeSacrificeRewardRsp = 8156; + public static final int MailChangeNotify = 1475; + public static final int MainCoopUpdateNotify = 1993; + public static final int MapAreaChangeNotify = 3284; + public static final int MarkEntityInMinMapNotify = 230; + public static final int MarkMapReq = 3087; + public static final int MarkMapRsp = 3193; + public static final int MarkNewNotify = 1207; + public static final int MarkTargetInvestigationMonsterNotify = 1916; + public static final int MassiveEntityElementOpBatchNotify = 304; + public static final int MassiveEntityStateChangedNotify = 360; + public static final int MaterialDeleteReturnNotify = 653; + public static final int MaterialDeleteUpdateNotify = 620; + public static final int McoinExchangeHcoinReq = 643; + public static final int McoinExchangeHcoinRsp = 636; + public static final int MechanicusCandidateTeamCreateReq = 3929; + public static final int MechanicusCandidateTeamCreateRsp = 3927; + public static final int MechanicusCloseNotify = 3934; + public static final int MechanicusCoinNotify = 3964; + public static final int MechanicusLevelupGearReq = 3965; + public static final int MechanicusLevelupGearRsp = 3950; + public static final int MechanicusOpenNotify = 3914; + public static final int MechanicusSequenceOpenNotify = 3954; + public static final int MechanicusUnlockGearReq = 3972; + public static final int MechanicusUnlockGearRsp = 3982; + public static final int MeetNpcReq = 572; + public static final int MeetNpcRsp = 582; + public static final int MetNpcIdListNotify = 534; + public static final int MiracleRingDataNotify = 5209; + public static final int MiracleRingDeliverItemReq = 5244; + public static final int MiracleRingDeliverItemRsp = 5232; + public static final int MiracleRingDestroyNotify = 5239; + public static final int MiracleRingDropResultNotify = 5215; + public static final int MiracleRingTakeRewardReq = 5246; + public static final int MiracleRingTakeRewardRsp = 5236; + public static final int MistTrialDunegonFailNotify = 8765; + public static final int MistTrialGetChallengeMissionReq = 8002; + public static final int MistTrialGetChallengeMissionRsp = 8558; + public static final int MistTrialSelectAvatarAndEnterDungeonReq = 8641; + public static final int MistTrialSelectAvatarAndEnterDungeonRsp = 8060; + public static final int MonsterAIConfigHashNotify = 3379; + public static final int MonsterAlertChangeNotify = 313; + public static final int MonsterForceAlertNotify = 357; + public static final int MonsterPointArrayRouteUpdateNotify = 3498; + public static final int MonsterSummonTagNotify = 1367; + public static final int MpBlockNotify = 1837; + public static final int MpPlayGuestReplyInviteReq = 1840; + public static final int MpPlayGuestReplyInviteRsp = 1822; + public static final int MpPlayGuestReplyNotify = 1810; + public static final int MpPlayInviteResultNotify = 1828; + public static final int MpPlayOwnerCheckReq = 1817; + public static final int MpPlayOwnerCheckRsp = 1826; + public static final int MpPlayOwnerInviteNotify = 1838; + public static final int MpPlayOwnerStartInviteReq = 1812; + public static final int MpPlayOwnerStartInviteRsp = 1825; + public static final int MpPlayPrepareInterruptNotify = 1818; + public static final int MpPlayPrepareNotify = 1807; + public static final int MultistagePlayEndNotify = 5312; + public static final int MultistagePlayFinishStageReq = 5375; + public static final int MultistagePlayFinishStageRsp = 5329; + public static final int MultistagePlayInfoNotify = 5367; + public static final int MultistagePlaySettleNotify = 5348; + public static final int MultistagePlayStageEndNotify = 5322; + public static final int GetUgcRsp = 6343; + public static final int MusicGameGetBeatmapRsp = 6309; + public static final int MusicGameSettleReq = 8278; + public static final int MusicGameSettleRsp = 8542; + public static final int MusicGameStartReq = 8103; + public static final int MusicGameStartRsp = 8334; + public static final int MusicGameCreateBeatmapRsp = 6347; + public static final int GetUgcReq = 6348; + public static final int MusicGameSearchBeatmapRsp = 6304; + public static final int MusicGameSearchBeatmapReq = 6343; + public static final int MusicGameStartToPlayOthersBeatmapReq = 6302; + public static final int MusicGameStartToPlayOthersBeatmapRsp = 6313; + public static final int NavMeshStatsNotify = 2343; + public static final int NormalUidOpNotify = 5748; + public static final int NpcTalkReq = 567; + public static final int NpcTalkRsp = 575; + public static final int ObstacleModifyNotify = 2354; + public static final int OfferingInteractReq = 2901; + public static final int OfferingInteractRsp = 2913; + public static final int OneofGatherPointDetectorDataNotify = 4297; + public static final int OpActivityDataNotify = 5154; + public static final int OpActivityStateNotify = 2567; + public static final int OpActivityUpdateNotify = 5164; + public static final int OpenBlossomCircleCampGuideNotify = 2772; + public static final int OpenStateChangeNotify = 146; + public static final int OpenStateUpdateNotify = 174; + public static final int OrderDisplayNotify = 4115; + public static final int OrderFinishNotify = 4109; + public static final int OtherPlayerEnterHomeNotify = 4771; + public static final int PSNBlackListNotify = 4008; + public static final int PSNFriendListNotify = 4036; + public static final int PSPlayerApplyEnterMpReq = 1801; + public static final int PSPlayerApplyEnterMpRsp = 1802; + public static final int PathfindingEnterSceneReq = 2314; + public static final int PathfindingEnterSceneRsp = 2334; + public static final int PathfindingPingNotify = 2364; + public static final int PersonalLineAllDataReq = 437; + public static final int PersonalLineAllDataRsp = 425; + public static final int PersonalLineNewUnlockNotify = 449; + public static final int PersonalSceneJumpReq = 298; + public static final int PersonalSceneJumpRsp = 203; + public static final int PingReq = 14; + public static final int PingRsp = 34; + public static final int PlantFlowerAcceptAllGiveFlowerReq = 8807; + public static final int PlantFlowerAcceptAllGiveFlowerRsp = 8040; + public static final int PlantFlowerAcceptGiveFlowerReq = 8989; + public static final int PlantFlowerAcceptGiveFlowerRsp = 8343; + public static final int PlantFlowerEditFlowerCombinationReq = 8301; + public static final int PlantFlowerEditFlowerCombinationRsp = 8975; + public static final int PlantFlowerGetCanGiveFriendFlowerReq = 8510; + public static final int PlantFlowerGetCanGiveFriendFlowerRsp = 8692; + public static final int PlantFlowerGetFriendFlowerWishListReq = 8828; + public static final int PlantFlowerGetFriendFlowerWishListRsp = 8375; + public static final int PlantFlowerGetRecvFlowerListReq = 8123; + public static final int PlantFlowerGetRecvFlowerListRsp = 8779; + public static final int PlantFlowerGetSeedInfoReq = 8055; + public static final int PlantFlowerGetSeedInfoRsp = 8797; + public static final int PlantFlowerGiveFriendFlowerReq = 8593; + public static final int PlantFlowerGiveFriendFlowerRsp = 8688; + public static final int PlantFlowerHaveRecvFlowerNotify = 8729; + public static final int PlantFlowerSetFlowerWishReq = 8997; + public static final int PlantFlowerSetFlowerWishRsp = 8034; + public static final int PlantFlowerTakeSeedRewardReq = 8851; + public static final int PlantFlowerTakeSeedRewardRsp = 8340; + public static final int PlatformChangeRouteNotify = 221; + public static final int PlatformStartRouteNotify = 279; + public static final int PlatformStopRouteNotify = 245; + public static final int PlayerAllowEnterMpAfterAgreeMatchNotify = 4181; + public static final int PlayerApplyEnterHomeNotify = 4757; + public static final int PlayerApplyEnterHomeResultNotify = 4568; + public static final int PlayerApplyEnterHomeResultReq = 4668; + public static final int PlayerApplyEnterHomeResultRsp = 4714; + public static final int PlayerApplyEnterMpAfterMatchAgreedNotify = 4171; + public static final int PlayerApplyEnterMpNotify = 1848; + public static final int PlayerApplyEnterMpReq = 1843; + public static final int PlayerApplyEnterMpResultNotify = 1846; + public static final int PlayerApplyEnterMpResultReq = 1836; + public static final int PlayerApplyEnterMpResultRsp = 1815; + public static final int PlayerApplyEnterMpRsp = 1809; + public static final int PlayerCancelMatchReq = 4196; + public static final int PlayerCancelMatchRsp = 4186; + public static final int PlayerChatCDNotify = 3354; + public static final int PlayerChatNotify = 3236; + public static final int PlayerChatReq = 3125; + public static final int PlayerChatRsp = 3070; + public static final int PlayerCompoundMaterialReq = 133; + public static final int PlayerCompoundMaterialRsp = 116; + public static final int PlayerConfirmMatchReq = 4182; + public static final int PlayerConfirmMatchRsp = 4189; + public static final int PlayerCookArgsReq = 145; + public static final int PlayerCookArgsRsp = 121; + public static final int PlayerCookReq = 184; + public static final int PlayerCookRsp = 141; + public static final int PlayerDataNotify = 182; + public static final int PlayerEnterDungeonReq = 954; + public static final int PlayerEnterDungeonRsp = 964; + public static final int PlayerEnterSceneInfoNotify = 289; + public static final int PlayerEnterSceneNotify = 267; + public static final int PlayerEyePointStateNotify = 3065; + public static final int PlayerFishingDataNotify = 5838; + public static final int PlayerForceExitReq = 106; + public static final int PlayerForceExitRsp = 190; + public static final int PlayerGameTimeNotify = 159; + public static final int PlayerGeneralMatchConfirmNotify = 4152; + public static final int PlayerGeneralMatchDismissNotify = 4151; + public static final int PlayerGetForceQuitBanInfoReq = 4167; + public static final int PlayerGetForceQuitBanInfoRsp = 4176; + public static final int PlayerHomeCompInfoNotify = 4886; + public static final int PlayerInjectFixNotify = 192; + public static final int PlayerInvestigationAllInfoNotify = 1911; + public static final int PlayerInvestigationNotify = 1901; + public static final int PlayerInvestigationTargetNotify = 1930; + public static final int PlayerLevelRewardUpdateNotify = 120; + public static final int PlayerLoginReq = 154; + public static final int PlayerLoginRsp = 164; + public static final int PlayerLogoutNotify = 172; + public static final int PlayerLogoutReq = 114; + public static final int PlayerLogoutRsp = 134; + public static final int PlayerLuaShellNotify = 101; + public static final int PlayerMatchAgreedResultNotify = 4185; + public static final int PlayerMatchInfoNotify = 4159; + public static final int PlayerMatchStopNotify = 4165; + public static final int PlayerMatchSuccNotify = 4194; + public static final int PlayerOfferingDataNotify = 2925; + public static final int PlayerOfferingReq = 2916; + public static final int PlayerOfferingRsp = 2924; + public static final int PlayerPreEnterMpNotify = 1832; + public static final int PlayerPropChangeNotify = 156; + public static final int PlayerPropChangeReasonNotify = 1250; + public static final int PlayerPropNotify = 107; + public static final int PlayerQuitDungeonReq = 914; + public static final int PlayerQuitDungeonRsp = 934; + public static final int PlayerQuitFromHomeNotify = 4837; + public static final int PlayerQuitFromMpNotify = 1844; + public static final int PlayerRandomCookReq = 170; + public static final int PlayerRandomCookRsp = 113; + public static final int PlayerRechargeDataNotify = 4136; + public static final int PlayerReportReq = 4002; + public static final int PlayerReportRsp = 4088; + public static final int PlayerRoutineDataNotify = 3548; + public static final int PlayerSetLanguageReq = 149; + public static final int PlayerSetLanguageRsp = 197; + public static final int PlayerSetOnlyMPWithPSPlayerReq = 1835; + public static final int PlayerSetOnlyMPWithPSPlayerRsp = 1821; + public static final int PlayerSetPauseReq = 102; + public static final int PlayerSetPauseRsp = 188; + public static final int PlayerStartMatchReq = 4198; + public static final int PlayerStartMatchRsp = 4193; + public static final int PlayerStoreNotify = 667; + public static final int PlayerTimeNotify = 171; + public static final int PlayerWorldSceneInfoListNotify = 3152; + public static final int PostEnterSceneReq = 3446; + public static final int PostEnterSceneRsp = 3030; + public static final int PrivateChatNotify = 5004; + public static final int PrivateChatReq = 5017; + public static final int PrivateChatRsp = 5025; + public static final int PrivateChatSetSequenceReq = 4985; + public static final int PrivateChatSetSequenceRsp = 4957; + public static final int ProfilePictureChangeNotify = 4043; + public static final int ProjectorOptionReq = 813; + public static final int ProjectorOptionRsp = 857; + public static final int ProudSkillChangeNotify = 1059; + public static final int ProudSkillExtraLevelNotify = 1029; + public static final int ProudSkillUpgradeReq = 1065; + public static final int ProudSkillUpgradeRsp = 1050; + public static final int PullPrivateChatReq = 4984; + public static final int PullPrivateChatRsp = 5022; + public static final int PullRecentChatReq = 5032; + public static final int PullRecentChatRsp = 5015; + public static final int PushTipsAllDataNotify = 2219; + public static final int PushTipsChangeNotify = 2244; + public static final int PushTipsReadFinishReq = 2294; + public static final int PushTipsReadFinishRsp = 2274; + public static final int QueryCodexMonsterBeKilledNumReq = 4208; + public static final int QueryCodexMonsterBeKilledNumRsp = 4201; + public static final int QueryPathReq = 2367; + public static final int QueryPathRsp = 2375; + public static final int QuestCreateEntityReq = 450; + public static final int QuestCreateEntityRsp = 459; + public static final int QuestDelNotify = 454; + public static final int QuestDestroyEntityReq = 407; + public static final int QuestDestroyEntityRsp = 491; + public static final int QuestDestroyNpcReq = 419; + public static final int QuestDestroyNpcRsp = 444; + public static final int QuestGlobalVarNotify = 426; + public static final int QuestListNotify = 467; + public static final int QuestListUpdateNotify = 475; + public static final int QuestProgressUpdateNotify = 466; + public static final int QuestTransmitReq = 433; + public static final int QuestTransmitRsp = 416; + public static final int QuestUpdateQuestTimeVarNotify = 488; + public static final int QuestUpdateQuestVarNotify = 423; + public static final int QuestUpdateQuestVarReq = 461; + public static final int QuestUpdateQuestVarRsp = 456; + public static final int QuickUseWidgetReq = 4281; + public static final int QuickUseWidgetRsp = 4285; + public static final int ReadMailNotify = 1454; + public static final int ReadPrivateChatReq = 5000; + public static final int ReadPrivateChatRsp = 5009; + public static final int ReceivedTrialAvatarActivityRewardReq = 2005; + public static final int ReceivedTrialAvatarActivityRewardRsp = 2009; + public static final int RechargeReq = 4148; + public static final int RechargeRsp = 4143; + public static final int RedeemLegendaryKeyReq = 418; + public static final int RedeemLegendaryKeyRsp = 458; + public static final int RefreshBackgroundAvatarReq = 1636; + public static final int RefreshBackgroundAvatarRsp = 1786; + public static final int RefreshRoguelikeDungeonCardReq = 8092; + public static final int RefreshRoguelikeDungeonCardRsp = 8721; + public static final int RegionSearchChangeRegionNotify = 5643; + public static final int RegionSearchNotify = 5648; + public static final int ReliquaryDecomposeReq = 631; + public static final int ReliquaryDecomposeRsp = 699; + public static final int ReliquaryPromoteReq = 646; + public static final int ReliquaryPromoteRsp = 684; + public static final int ReliquaryUpgradeReq = 694; + public static final int ReliquaryUpgradeRsp = 674; + public static final int RemoveBlacklistReq = 4013; + public static final int RemoveBlacklistRsp = 4057; + public static final int RemoveRandTaskInfoNotify = 153; + public static final int ReportFightAntiCheatNotify = 321; + public static final int ReportTrackingIOInfoNotify = 4144; + public static final int RequestLiveInfoReq = 884; + public static final int RequestLiveInfoRsp = 841; + public static final int ResinCardDataUpdateNotify = 4131; + public static final int ResinChangeNotify = 649; + public static final int RestartEffigyChallengeReq = 2188; + public static final int RestartEffigyChallengeRsp = 2137; + public static final int ReunionActivateNotify = 5088; + public static final int ReunionBriefInfoReq = 5098; + public static final int ReunionBriefInfoRsp = 5093; + public static final int ReunionDailyRefreshNotify = 5072; + public static final int ReunionPrivilegeChangeNotify = 5090; + public static final int ReunionSettleNotify = 5075; + public static final int RobotPushPlayerDataNotify = 42; + public static final int RogueCellUpdateNotify = 8624; + public static final int RogueDungeonPlayerCellChangeNotify = 8320; + public static final int RogueHealAvatarsReq = 8610; + public static final int RogueHealAvatarsRsp = 8941; + public static final int RogueResumeDungeonReq = 8029; + public static final int RogueResumeDungeonRsp = 8009; + public static final int RogueSwitchAvatarReq = 8770; + public static final int RogueSwitchAvatarRsp = 8259; + public static final int RoguelikeCardGachaNotify = 8494; + public static final int RoguelikeEffectDataNotify = 8556; + public static final int RoguelikeEffectViewReq = 8885; + public static final int RoguelikeEffectViewRsp = 8862; + public static final int RoguelikeGiveUpReq = 8061; + public static final int RoguelikeGiveUpRsp = 8868; + public static final int RoguelikeMistClearNotify = 8512; + public static final int RoguelikeRefreshCardCostUpdateNotify = 8266; + public static final int RoguelikeResourceBonusPropUpdateNotify = 8376; + public static final int RoguelikeRuneRecordUpdateNotify = 8950; + public static final int RoguelikeSelectAvatarAndEnterDungeonReq = 8863; + public static final int RoguelikeSelectAvatarAndEnterDungeonRsp = 8400; + public static final int RoguelikeTakeStageFirstPassRewardReq = 8541; + public static final int RoguelikeTakeStageFirstPassRewardRsp = 8530; + public static final int SalesmanDeliverItemReq = 2167; + public static final int SalesmanDeliverItemRsp = 2067; + public static final int SalesmanTakeRewardReq = 2062; + public static final int SalesmanTakeRewardRsp = 2070; + public static final int SalesmanTakeSpecialRewardReq = 2166; + public static final int SalesmanTakeSpecialRewardRsp = 2184; + public static final int SaveCoopDialogReq = 1972; + public static final int SaveCoopDialogRsp = 1960; + public static final int SaveMainCoopReq = 1959; + public static final int SaveMainCoopRsp = 1996; + public static final int SceneAreaUnlockNotify = 274; + public static final int SceneAreaWeatherNotify = 297; + public static final int SceneAudioNotify = 3412; + public static final int SceneAvatarStaminaStepReq = 250; + public static final int SceneAvatarStaminaStepRsp = 259; + public static final int SceneCreateEntityReq = 241; + public static final int SceneCreateEntityRsp = 270; + public static final int SceneDataNotify = 3210; + public static final int SceneDestroyEntityReq = 213; + public static final int SceneDestroyEntityRsp = 257; + public static final int SceneEntitiesMoveCombineNotify = 3188; + public static final int SceneEntitiesMovesReq = 222; + public static final int SceneEntitiesMovesRsp = 212; + public static final int SceneEntityAppearNotify = 234; + public static final int SceneEntityDisappearNotify = 272; + public static final int SceneEntityDrownReq = 246; + public static final int SceneEntityDrownRsp = 284; + public static final int SceneEntityMoveNotify = 207; + public static final int SceneEntityMoveReq = 282; + public static final int SceneEntityMoveRsp = 265; + public static final int SceneEntityUpdateNotify = 3095; + public static final int SceneForceLockNotify = 226; + public static final int SceneForceUnlockNotify = 286; + public static final int SceneGalleryInfoNotify = 5529; + public static final int SceneInitFinishReq = 264; + public static final int SceneInitFinishRsp = 214; + public static final int SceneKickPlayerNotify = 299; + public static final int SceneKickPlayerReq = 232; + public static final int SceneKickPlayerRsp = 231; + public static final int ScenePlayBattleInfoListNotify = 4379; + public static final int ScenePlayBattleInfoNotify = 4417; + public static final int ScenePlayBattleInterruptNotify = 4357; + public static final int ScenePlayBattleResultNotify = 4441; + public static final int ScenePlayBattleUidOpNotify = 4392; + public static final int ScenePlayGuestReplyInviteReq = 4422; + public static final int ScenePlayGuestReplyInviteRsp = 4432; + public static final int ScenePlayGuestReplyNotify = 4415; + public static final int ScenePlayInfoListNotify = 4409; + public static final int ScenePlayInviteResultNotify = 4400; + public static final int ScenePlayOutofRegionNotify = 4377; + public static final int ScenePlayOwnerCheckReq = 4425; + public static final int ScenePlayOwnerCheckRsp = 4404; + public static final int ScenePlayOwnerInviteNotify = 4384; + public static final int ScenePlayOwnerStartInviteReq = 4414; + public static final int ScenePlayOwnerStartInviteRsp = 4364; + public static final int ScenePlayerInfoNotify = 240; + public static final int ScenePlayerLocationNotify = 291; + public static final int ScenePlayerSoundNotify = 201; + public static final int ScenePointUnlockNotify = 261; + public static final int SceneRouteChangeNotify = 208; + public static final int SceneTeamUpdateNotify = 1762; + public static final int SceneTimeNotify = 210; + public static final int SceneTransToPointReq = 256; + public static final int SceneTransToPointRsp = 223; + public static final int SceneWeatherForcastReq = 3037; + public static final int SceneWeatherForcastRsp = 3257; + public static final int SeaLampCoinNotify = 2127; + public static final int SeaLampContributeItemReq = 2119; + public static final int SeaLampContributeItemRsp = 2138; + public static final int SeaLampFlyLampNotify = 2161; + public static final int SeaLampFlyLampReq = 2175; + public static final int SeaLampFlyLampRsp = 2152; + public static final int SeaLampPopularityNotify = 2087; + public static final int SeaLampTakeContributionRewardReq = 2149; + public static final int SeaLampTakeContributionRewardRsp = 2170; + public static final int SeaLampTakePhaseRewardReq = 2135; + public static final int SeaLampTakePhaseRewardRsp = 2085; + public static final int SealBattleBeginNotify = 206; + public static final int SealBattleEndNotify = 290; + public static final int SealBattleProgressNotify = 292; + public static final int SeeMonsterReq = 255; + public static final int SeeMonsterRsp = 209; + public static final int SelectAsterMidDifficultyReq = 2003; + public static final int SelectAsterMidDifficultyRsp = 2001; + public static final int SelectEffigyChallengeConditionReq = 2199; + public static final int SelectEffigyChallengeConditionRsp = 2081; + public static final int SelectRoguelikeDungeonCardReq = 8229; + public static final int SelectRoguelikeDungeonCardRsp = 8037; + public static final int SelectWorktopOptionReq = 814; + public static final int SelectWorktopOptionRsp = 834; + public static final int ServerAnnounceNotify = 2073; + public static final int ServerAnnounceRevokeNotify = 2103; + public static final int ServerBuffChangeNotify = 353; + public static final int ServerCondMeetQuestListUpdateNotify = 486; + public static final int ServerDisconnectClientNotify = 198; + public static final int ServerGlobalValueChangeNotify = 1142; + public static final int ServerLogNotify = 59; + public static final int ServerMessageNotify = 5743; + public static final int ServerTimeNotify = 50; + public static final int ServerUpdateGlobalValueNotify = 1191; + public static final int SetBattlePassViewedReq = 2601; + public static final int SetBattlePassViewedRsp = 2602; + public static final int SetChatEmojiCollectionReq = 4098; + public static final int SetChatEmojiCollectionRsp = 4003; + public static final int SetCoopChapterViewedReq = 1978; + public static final int SetCoopChapterViewedRsp = 1968; + public static final int SetCurExpeditionChallengeIdReq = 2168; + public static final int SetCurExpeditionChallengeIdRsp = 2052; + public static final int SetEntityClientDataNotify = 3457; + public static final int SetEquipLockStateReq = 645; + public static final int SetEquipLockStateRsp = 621; + public static final int SetFriendEnterHomeOptionReq = 4732; + public static final int SetFriendEnterHomeOptionRsp = 4835; + public static final int SetFriendRemarkNameReq = 4049; + public static final int SetFriendRemarkNameRsp = 4097; + public static final int SetH5ActivityRedDotTimestampReq = 5696; + public static final int SetH5ActivityRedDotTimestampRsp = 5686; + public static final int SetIsAutoUnlockSpecificEquipReq = 673; + public static final int SetIsAutoUnlockSpecificEquipRsp = 632; + public static final int SetLimitOptimizationNotify = 8431; + public static final int SetNameCardReq = 4094; + public static final int SetNameCardRsp = 4074; + public static final int SetOpenStateReq = 144; + public static final int SetOpenStateRsp = 194; + public static final int SetPlayerBirthdayReq = 4091; + public static final int SetPlayerBirthdayRsp = 4042; + public static final int SetPlayerBornDataReq = 127; + public static final int SetPlayerBornDataRsp = 166; + public static final int SetPlayerHeadImageReq = 4066; + public static final int SetPlayerHeadImageRsp = 4061; + public static final int SetPlayerNameReq = 123; + public static final int SetPlayerNameRsp = 119; + public static final int SetPlayerPropReq = 142; + public static final int SetPlayerPropRsp = 129; + public static final int SetPlayerSignatureReq = 4029; + public static final int SetPlayerSignatureRsp = 4027; + public static final int SetSceneWeatherAreaReq = 296; + public static final int SetSceneWeatherAreaRsp = 263; + public static final int SetUpAvatarTeamReq = 1638; + public static final int SetUpAvatarTeamRsp = 1628; + public static final int SetUpLunchBoxWidgetReq = 4282; + public static final int SetUpLunchBoxWidgetRsp = 4289; + public static final int SetWidgetSlotReq = 4297; + public static final int SetWidgetSlotRsp = 4270; + public static final int ShowClientGuideNotify = 3384; + public static final int ShowClientTutorialNotify = 3120; + public static final int ShowCommonTipsNotify = 3469; + public static final int ShowMessageNotify = 64; + public static final int ShowTemplateReminderNotify = 3186; + public static final int SignInInfoReq = 2554; + public static final int SignInInfoRsp = 2564; + public static final int SocialDataNotify = 4016; + public static final int SpringUseReq = 1788; + public static final int SpringUseRsp = 1737; + public static final int StartArenaChallengeLevelReq = 2194; + public static final int StartArenaChallengeLevelRsp = 2057; + public static final int StartBuoyantCombatGalleryReq = 8282; + public static final int StartBuoyantCombatGalleryRsp = 8916; + public static final int StartCoopPointReq = 1952; + public static final int StartCoopPointRsp = 1967; + public static final int StartEffigyChallengeReq = 2156; + public static final int StartEffigyChallengeRsp = 2021; + public static final int StartFishingReq = 5809; + public static final int StartFishingRsp = 5846; + public static final int StartRogueEliteCellChallengeReq = 8874; + public static final int StartRogueEliteCellChallengeRsp = 8759; + public static final int StartRogueNormalCellChallengeReq = 8809; + public static final int StartRogueNormalCellChallengeRsp = 8834; + public static final int StoreItemChangeNotify = 654; + public static final int StoreItemDelNotify = 664; + public static final int StoreWeightLimitNotify = 675; + public static final int SummerTimeFloatSignalPositionNotify = 8639; + public static final int SummerTimeFloatSignalUpdateNotify = 8576; + public static final int SummerTimeSprintBoatRestartReq = 8178; + public static final int SummerTimeSprintBoatRestartRsp = 8987; + public static final int SummerTimeSprintBoatSettleNotify = 8256; + public static final int SumoDungeonSettleNotify = 8665; + public static final int SumoEnterDungeonNotify = 8823; + public static final int SumoLeaveDungeonNotify = 8778; + public static final int SumoRestartDungeonReq = 8246; + public static final int SumoRestartDungeonRsp = 8249; + public static final int SumoSaveTeamReq = 8607; + public static final int SumoSaveTeamRsp = 8005; + public static final int SumoSelectTeamAndEnterDungeonReq = 8930; + public static final int SumoSelectTeamAndEnterDungeonRsp = 8131; + public static final int SumoSetNoSwitchPunishTimeNotify = 8536; + public static final int SumoSwitchTeamReq = 8384; + public static final int SumoSwitchTeamRsp = 8065; + public static final int SyncScenePlayTeamEntityNotify = 3362; + public static final int SyncTeamEntityNotify = 393; + public static final int TakeAchievementGoalRewardReq = 2686; + public static final int TakeAchievementGoalRewardRsp = 2665; + public static final int TakeAchievementRewardReq = 2659; + public static final int TakeAchievementRewardRsp = 2696; + public static final int TakeAsterSpecialRewardReq = 2061; + public static final int TakeAsterSpecialRewardRsp = 2026; + public static final int TakeBattlePassMissionPointReq = 2644; + public static final int TakeBattlePassMissionPointRsp = 2632; + public static final int TakeBattlePassRewardReq = 2636; + public static final int TakeBattlePassRewardRsp = 2615; + public static final int TakeCityReputationExploreRewardReq = 2842; + public static final int TakeCityReputationExploreRewardRsp = 2829; + public static final int TakeCityReputationLevelRewardReq = 2854; + public static final int TakeCityReputationLevelRewardRsp = 2864; + public static final int TakeCityReputationParentQuestReq = 2834; + public static final int TakeCityReputationParentQuestRsp = 2872; + public static final int TakeCompoundOutputReq = 137; + public static final int TakeCompoundOutputRsp = 125; + public static final int TakeCoopRewardReq = 1975; + public static final int TakeCoopRewardRsp = 1988; + public static final int TakeDeliveryDailyRewardReq = 2054; + public static final int TakeDeliveryDailyRewardRsp = 2029; + public static final int TakeEffigyFirstPassRewardReq = 2050; + public static final int TakeEffigyFirstPassRewardRsp = 2025; + public static final int TakeEffigyRewardReq = 2104; + public static final int TakeEffigyRewardRsp = 2089; + public static final int TakeFirstShareRewardReq = 4037; + public static final int TakeFirstShareRewardRsp = 4025; + public static final int TakeFurnitureMakeReq = 4713; + public static final int TakeFurnitureMakeRsp = 4630; + public static final int TakeHuntingOfferReq = 4348; + public static final int TakeHuntingOfferRsp = 4343; + public static final int TakeInvestigationRewardReq = 1928; + public static final int TakeInvestigationRewardRsp = 1910; + public static final int TakeInvestigationTargetRewardReq = 1926; + public static final int TakeInvestigationTargetRewardRsp = 1927; + public static final int TakeMaterialDeleteReturnReq = 638; + public static final int TakeMaterialDeleteReturnRsp = 604; + public static final int TakeOfferingLevelRewardReq = 2921; + public static final int TakeOfferingLevelRewardRsp = 2908; + public static final int TakePlayerLevelRewardReq = 138; + public static final int TakePlayerLevelRewardRsp = 104; + public static final int TakeRegionSearchRewardReq = 5609; + public static final int TakeRegionSearchRewardRsp = 5646; + public static final int TakeResinCardDailyRewardReq = 4132; + public static final int TakeResinCardDailyRewardRsp = 4139; + public static final int TakeReunionFirstGiftRewardReq = 5059; + public static final int TakeReunionFirstGiftRewardRsp = 5096; + public static final int TakeReunionMissionRewardReq = 5052; + public static final int TakeReunionMissionRewardRsp = 5067; + public static final int TakeReunionSignInRewardReq = 5094; + public static final int TakeReunionSignInRewardRsp = 5082; + public static final int TakeReunionWatcherRewardReq = 5085; + public static final int TakeReunionWatcherRewardRsp = 5071; + public static final int TakeoffEquipReq = 627; + public static final int TakeoffEquipRsp = 666; + public static final int TaskVarNotify = 176; + public static final int TeamResonanceChangeNotify = 1066; + public static final int TowerAllDataReq = 2482; + public static final int TowerAllDataRsp = 2465; + public static final int TowerBriefDataNotify = 2467; + public static final int TowerBuffSelectReq = 2491; + public static final int TowerBuffSelectRsp = 2442; + public static final int TowerCurLevelRecordChangeNotify = 2454; + public static final int TowerDailyRewardProgressChangeNotify = 2464; + public static final int TowerEnterLevelReq = 2459; + public static final int TowerEnterLevelRsp = 2407; + public static final int TowerFloorRecordChangeNotify = 2475; + public static final int TowerGetFloorStarRewardReq = 2494; + public static final int TowerGetFloorStarRewardRsp = 2474; + public static final int TowerLevelEndNotify = 2457; + public static final int TowerLevelStarCondNotify = 2486; + public static final int TowerMiddleLevelChangeTeamNotify = 2426; + public static final int TowerRecordHandbookReq = 2433; + public static final int TowerRecordHandbookRsp = 2416; + public static final int TowerSurrenderReq = 2419; + public static final int TowerSurrenderRsp = 2444; + public static final int TowerTeamSelectReq = 2434; + public static final int TowerTeamSelectRsp = 2472; + public static final int TreasureMapBonusChallengeNotify = 2163; + public static final int TreasureMapCurrencyNotify = 2046; + public static final int TreasureMapDetectorDataNotify = 4272; + public static final int TreasureMapGuideTaskDoneNotify = 2099; + public static final int TreasureMapHostInfoNotify = 8260; + public static final int TreasureMapMpChallengeNotify = 2071; + public static final int TreasureMapPreTaskDoneNotify = 2191; + public static final int TreasureMapRegionActiveNotify = 2148; + public static final int TreasureMapRegionInfoNotify = 2190; + public static final int TrialAvatarFirstPassDungeonNotify = 2105; + public static final int TrialAvatarInDungeonIndexNotify = 2109; + public static final int TriggerCreateGadgetToEquipPartNotify = 333; + public static final int TriggerRoguelikeCurseNotify = 8901; + public static final int TriggerRoguelikeRuneReq = 8053; + public static final int TriggerRoguelikeRuneRsp = 8631; + public static final int TryEnterHomeReq = 4729; + public static final int TryEnterHomeRsp = 4597; + public static final int UnfreezeGroupLimitNotify = 3464; + public static final int UnionCmdNotify = 27; + public static final int LastPacketPrintNotify = 41; + public static final int SalvagePreventSettleNotify = 8967; + public static final int HomeEnterEditModeFinishReq = 4676; + public static final int ReplayCustomDungeonRsp = 6234; + public static final int SpiceActivityFinishMakeSpiceRsp = 8004; + public static final int GachaActivityTakeRewardRsp = 8272; + public static final int MistTrialGetDungeonExhibitionDataRsp = 8058; + public static final int CrystalLinkEnterDungeonRsp = 8067; + public static final int ChangeCustomDungeonRoomRsp = 6239; + public static final int MistTrialGetDungeonExhibitionDataReq = 8931; + public static final int ActivityGetRecvGiftListRsp = 8791; + public static final int ReformFireworksReq = 6040; + public static final int CrystalLinkRestartDungeonReq = 8317; + public static final int LaunchFireworksReq = 6053; + public static final int WinterCampGetCanGiveFriendItemRsp = 8147; + public static final int PublishUgcReq = 6339; + public static final int GachaActivityCreateRobotReq = 8654; + public static final int GachaActivityCreateRobotRsp = 8808; + public static final int SpiceActivityProcessFoodReq = 8697; + public static final int PotionSaveDungeonResultReq = 8306; + public static final int WinterCampRecvItemNotify = 8740; + public static final int StartRogueDiaryPlayReq = 8804; + public static final int BartenderFinishLevelReq = 9000; + public static final int SalvageEscortSettleNotify = 8353; + public static final int HomeChangeBgmReq = 4806; + public static final int EvtBeingHealedNotify = 301; + public static final int GetCustomDungeonReq = 6247; + public static final int IrodoriChessEquipCardReq = 8511; + public static final int ResetRogueDiaryPlayRsp = 8336; + public static final int SpiceActivityProcessFoodRsp = 8075; + public static final int HomeBalloonGalleryScoreNotify = 4532; + public static final int PhotoActivityFinishRsp = 8713; + public static final int QuickOpenActivityReq = 8171; + public static final int LanternRiteDoFireworksReformReq = 8261; + public static final int RogueDiaryCoinAddNotify = 8059; + public static final int RogueDiaryRepairInfoNotify = 8835; + public static final int PhotoActivityFinishReq = 8473; + public static final int ViewLanternProjectionTipsRsp = 8108; + public static final int MichiaeMatsuriInteractStatueRsp = 8216; + public static final int TryEnterNextRogueDiaryDungeonReq = 8832; + public static final int ActivityAcceptGiveGiftRsp = 8915; + public static final int RogueDiaryDungeonInfoNotify = 8415; + public static final int StartRogueDiaryRoomReq = 8291; + public static final int LevelTagDataNotify = 3072; + public static final int StoreCustomDungeonReq = 6218; + public static final int WinterCampGetRecvItemListReq = 8547; + public static final int GachaActivityResetRsp = 8296; + public static final int WinterCampRaceScoreNotify = 8664; + public static final int MainCoopFailNotify = 1987; + public static final int CheckUgcStateReq = 6302; + public static final int WinterCampTakeBattleRewardRsp = 8573; + public static final int ActivityGetRecvGiftListReq = 8973; + public static final int SalvagePreventRestartRsp = 8030; + public static final int TryInterruptRogueDiaryDungeonRsp = 8655; + public static final int WinterCampGiveFriendItemRsp = 8781; + public static final int RogueFinishRepairRsp = 8024; + public static final int IrodoriChessUnequipCardRsp = 8825; + public static final int MichiaeMatsuriUnlockCrystalSkillRsp = 8845; + public static final int SaveUgcReq = 6344; + public static final int ResetRogueDiaryPlayReq = 8360; + public static final int CrystalLinkDungeonInfoNotify = 8925; + public static final int SaveCustomDungeonRoomRsp = 6246; + public static final int WinterCampEditSnowmanCombinationReq = 8743; + public static final int SearchCustomDungeonRsp = 6228; + public static final int BartenderCancelOrderReq = 8717; + public static final int WinterCampTriathlonSettleNotify = 8920; + public static final int ViewLanternProjectionLevelTipsRsp = 8134; + public static final int WinterCampTriathlonRestartReq = 8117; + public static final int ServerCombatEndNotify = 1127; + public static final int ReadSignatureAuditRsp = 4032; + public static final int GetGameplayRecommendationReq = 109; + public static final int TryInterruptRogueDiaryDungeonReq = 8362; + public static final int ResumeRogueDiaryDungeonReq = 8056; + public static final int EnterIrodoriChessDungeonReq = 8933; + public static final int GetRecommendCustomDungeonReq = 6238; + public static final int GachaActivityUpdateElemNotify = 8338; + public static final int ActivityHaveRecvGiftNotify = 8350; + public static final int WinterCampAcceptGiveItemReq = 8014; + public static final int MistTrialSettleNotify = 8559; + public static final int HomeRacingGallerySettleNotify = 4764; + public static final int QuickOpenActivityRsp = 8670; + public static final int SaveUgcRsp = 6332; + public static final int BartenderCancelOrderRsp = 8850; + public static final int MichiaeMatsuriRemoveChestMarkNotify = 8082; + public static final int GachaActivityResetReq = 8231; + public static final int GachaActivityNextStageRsp = 8304; + public static final int WinterCampSetWishListReq = 8405; + public static final int RetryCurRogueDiaryDungeonRsp = 8960; + public static final int BartenderStartLevelReq = 8460; + public static final int ResumeRogueDiaryDungeonRsp = 8712; + public static final int OutStuckCustomDungeonReq = 6227; + public static final int EnterIrodoriChessDungeonRsp = 8211; + public static final int RetryCurRogueDiaryDungeonReq = 8423; + public static final int WinterCampGetFriendWishListRsp = 8224; + public static final int HomeChangeBgmNotify = 4653; + public static final int GachaActivityPercentNotify = 8469; + public static final int RegionalPlayInfoNotify = 6298; + public static final int PotionEnterDungeonRsp = 8889; + public static final int LikeCustomDungeonReq = 6219; + public static final int ChangeCustomDungeonRoomReq = 6232; + public static final int GetRecommendCustomDungeonRsp = 6240; + public static final int CrystalLinkRestartDungeonRsp = 8748; + public static final int RemoveCustomDungeonReq = 6231; + public static final int BackPlayCustomDungeonOfficialRsp = 6216; + public static final int PlayerSignatureAuditDataNotify = 4076; + public static final int GalleryCrystalLinkKillMonsterNotify = 5561; + public static final int GetRogueDairyRepairInfoReq = 8633; + public static final int HomeClearGroupRecordRsp = 4846; + public static final int IrodoriChessPlayerInfoNotify = 5332; + public static final int LanternRiteDoFireworksReformRsp = 8564; + public static final int GetStoreCustomDungeonReq = 6222; + public static final int TryCustomDungeonRsp = 6201; + public static final int GetParentQuestVideoKeyRsp = 493; + public static final int IrodoriEditFlowerCombinationReq = 8746; + public static final int PotionSaveDungeonResultRsp = 8911; + public static final int PotionEnterDungeonReq = 8630; + public static final int WidgetUpdateExtraCDReq = 6005; + public static final int UgcNotify = 6301; + public static final int IrodoriChessUnequipCardReq = 8783; + public static final int EnterRogueDiaryDungeonRsp = 8515; + public static final int TryCustomDungeonReq = 6221; + public static final int RefreshRogueDiaryCardReq = 8849; + public static final int PhotoActivityClientViewReq = 8167; + public static final int ActivityAcceptGiveGiftReq = 8303; + public static final int SearchCustomDungeonReq = 6207; + public static final int UpdateSalvageBundleMarkReq = 8157; + public static final int ReadNicknameAuditRsp = 181; + public static final int AllShareCDDataNotify = 9067; + public static final int GetUgcBriefInfoReq = 6309; + public static final int IrodoriFillPoetryReq = 8228; + public static final int LanternRiteTakeSkinRewardReq = 8502; + public static final int RemoveCustomDungeonRsp = 6235; + public static final int CustomDungeonRecoverNotify = 6204; + public static final int SetCodexPushtipsReadRsp = 4202; + public static final int LanternRiteEndFireworksReformRsp = 8142; + public static final int ActivitySetGiftWishReq = 8848; + public static final int WinterCampGetFriendWishListReq = 8440; + public static final int FinishLanternProjectionRsp = 8016; + public static final int ActivitySetGiftWishRsp = 8764; + public static final int WinterCampTakeExploreRewardReq = 8750; + public static final int WidgetUpdateExtraCDRsp = 5925; + public static final int SignatureAuditConfigNotify = 4085; + public static final int BartenderCompleteOrderReq = 8327; + public static final int HomeGetGroupRecordReq = 4844; + public static final int MichiaeMatsuriDarkPressureLevelUpdateNotify = 8135; + public static final int RefreshRogueDiaryCardRsp = 8105; + public static final int ReplayCustomDungeonReq = 6242; + public static final int ReserveRogueDiaryAvatarRsp = 8457; + public static final int StartRogueDiaryRoomRsp = 8755; + public static final int BartenderStartLevelRsp = 8747; + public static final int IrodoriFillPoetryRsp = 8346; + public static final int EnterCustomDungeonRsp = 6243; + public static final int CheckUgcUpdateReq = 6335; + public static final int CrystalLinkEnterDungeonReq = 8861; + public static final int BartenderCancelLevelReq = 8161; + public static final int BartenderLevelProgressNotify = 8518; + public static final int LanternRiteEndFireworksReformReq = 8322; + public static final int GetParentQuestVideoKeyReq = 460; + public static final int SalvageEscortRestartRsp = 8118; + public static final int LuminanceStoneChallengeSettleNotify = 8895; + public static final int PublishCustomDungeonReq = 6202; + public static final int ActivityAcceptAllGiveGiftRsp = 8241; + public static final int FinishLanternProjectionReq = 8720; + public static final int ReformFireworksRsp = 5982; + public static final int HomePreChangeEditModeNotify = 4670; + public static final int SpiceActivityFinishMakeSpiceReq = 8032; + public static final int PlayerNicknameNotify = 139; + public static final int IrodoriMasterStartGalleryRsp = 8017; + public static final int LanternRiteStartFireworksReformRsp = 8546; + public static final int GetUgcBriefInfoRsp = 6346; + public static final int EnterCustomDungeonReq = 6248; + public static final int GlobalBuildingInfoNotify = 5373; + public static final int GetQuestLackingResourceReq = 440; + public static final int ExitCustomDungeonTryReq = 6226; + public static final int ActivityGiveFriendGiftRsp = 8524; + public static final int WidgetCaptureAnimalReq = 4274; + public static final int WinterCampEditSnowmanCombinationRsp = 8128; + public static final int WidgetCaptureAnimalRsp = 4261; + public static final int GetGameplayRecommendationRsp = 135; + public static final int IrodoriChessEquipCardRsp = 8145; + public static final int LanternRiteTakeSkinRewardRsp = 8356; + public static final int ClientRemoveCombatEndModifierNotify = 1166; + public static final int WinterCampTakeExploreRewardRsp = 8707; + public static final int HomeUpdatePictureFrameInfoRsp = 4748; + public static final int BartenderGetFormulaRsp = 8608; + public static final int SaveCustomDungeonRoomReq = 6209; + public static final int PlayerNicknameAuditDataNotify = 200; + public static final int HomeEnterEditModeFinishRsp = 4562; + public static final int ViewLanternProjectionTipsReq = 8818; + public static final int ActivityGetCanGiveFriendGiftRsp = 8186; + public static final int StoreCustomDungeonRsp = 6237; + public static final int ActivityBannerClearRsp = 2037; + public static final int EvtLocalGadgetOwnerLeaveSceneNotify = 398; + public static final int SetCodexPushtipsReadReq = 4210; + public static final int WinterCampAcceptGiveItemRsp = 8374; + public static final int RogueFinishRepairReq = 8749; + public static final int HomeGalleryInPlayingNotify = 5523; + public static final int HomeClearGroupRecordReq = 4870; + public static final int PotionRestartDungeonRsp = 8275; + public static final int PlayerSignatureNotify = 4089; + public static final int ReserveRogueDiaryAvatarReq = 8416; + public static final int TryEnterNextRogueDiaryDungeonRsp = 8223; + public static final int PublishUgcRsp = 6331; + public static final int ReadNicknameAuditReq = 169; + public static final int GetCustomDungeonRsp = 6220; + public static final int WinterCampAcceptAllGiveItemReq = 8251; + public static final int WinterCampGetCanGiveFriendItemReq = 8866; + public static final int ActivityAcceptAllGiveGiftReq = 8394; + public static final int GetQuestLackingResourceRsp = 411; + public static final int WinterCampStageInfoChangeNotify = 8531; + public static final int ActivityGetFriendGiftWishListRsp = 8777; + public static final int HomeSeekFurnitureGalleryScoreNotify = 4795; + public static final int WinterCampGiveFriendItemReq = 8187; + public static final int HomeAllUnlockedBgmIdListNotify = 4544; + public static final int LanternRiteStartFireworksReformReq = 8865; + public static final int GroupLinkMarkUpdateNotify = 5796; + public static final int FireworksReformDataNotify = 6080; + public static final int CheckUgcUpdateRsp = 6321; + public static final int RogueDiaryReviveAvatarReq = 8575; + public static final int ReadSignatureAuditReq = 4073; + public static final int HomeNewUnlockedBgmIdListNotify = 4612; + public static final int IrodoriChessLeftMonsterNotify = 5331; + public static final int MichiaeMatsuriStartDarkChallengeRsp = 8160; + public static final int MichiaeMatsuriUnlockCrystalSkillReq = 8949; + public static final int NicknameAuditConfigNotify = 115; + public static final int OutStuckCustomDungeonRsp = 6230; + public static final int BartenderGetFormulaReq = 8500; + public static final int PotionResetChallengeReq = 8958; + public static final int WinterCampTriathlonRestartRsp = 8258; + public static final int GetStoreCustomDungeonRsp = 6210; + public static final int NpcTalkStateNotify = 497; + public static final int SkyCrystalDetectorDataUpdateNotify = 4262; + public static final int IrodoriScanEntityRsp = 8730; + public static final int HomePictureFrameInfoNotify = 4895; + public static final int CustomDungeonOfficialNotify = 6250; + public static final int HomeUpdatePictureFrameInfoReq = 4813; + public static final int RogueDiaryTiredAvatarNotify = 8929; + public static final int ServerTryCancelGeneralMatchNotify = 4162; + public static final int GachaActivityNextStageReq = 8212; + public static final int LaunchFireworksRsp = 6011; + public static final int FireworksLaunchDataNotify = 6038; + public static final int SpiceActivityGivingRecordNotify = 8049; + public static final int IrodoriScanEntityReq = 8281; + public static final int IrodoriMasterGallerySettleNotify = 8379; + public static final int ActivityGetFriendGiftWishListReq = 8091; + public static final int CheckUgcStateRsp = 6317; + public static final int HomeBalloonGallerySettleNotify = 4618; + public static final int MichiaeMatsuriStartBossChallengeReq = 8225; + public static final int Unk2700_NGPMINKIOPK = 8956; + public static final int CustomDungeonBattleRecordNotify = 6233; + public static final int ActivityBannerNotify = 2018; + public static final int BartenderFinishLevelRsp = 8044; + public static final int UpdateSalvageBundleMarkRsp = 8732; + public static final int WinterCampAcceptAllGiveItemRsp = 8815; + public static final int WinterCampSetWishListRsp = 8985; + public static final int GachaActivityTakeRewardReq = 8796; + public static final int IrodoriMasterGalleryCgEndNotify = 8555; + public static final int EnterRogueDiaryDungeonReq = 8388; + public static final int GalleryCrystalLinkBuffInfoNotify = 5556; + public static final int HomeGetGroupRecordRsp = 4522; + public static final int MichiaeMatsuriRemoveChallengeMarkNotify = 8578; + public static final int MichiaeMatsuriGainCrystalExpUpdateNotify = 8289; + public static final int MichiaeMatsuriInteractStatueReq = 8836; + public static final int MichiaeMatsuriStartDarkChallengeReq = 8357; + public static final int PotionResetChallengeRsp = 8262; + public static final int BartenderCancelLevelRsp = 8701; + public static final int CustomDungeonUpdateNotify = 6225; + public static final int HomeChangeBgmRsp = 4815; + public static final int BartenderCompleteOrderRsp = 8709; + public static final int ActivityGiveFriendGiftReq = 8763; + public static final int ActivityBannerClearReq = 2114; + public static final int BackPlayCustomDungeonOfficialReq = 6205; + public static final int SalvageEscortRestartReq = 8020; + public static final int MichiaeMatsuriStartBossChallengeRsp = 8826; + public static final int RogueDiaryReviveAvatarRsp = 8812; + public static final int WinterCampTakeBattleRewardReq = 8495; + public static final int TanukiTravelFinishGuideQuestNotify = 8130; + public static final int ViewLanternProjectionLevelTipsReq = 8937; + public static final int GetRogueDairyRepairInfoRsp = 8433; + public static final int PublishCustomDungeonRsp = 6217; + public static final int IrodoriEditFlowerCombinationRsp = 8800; + public static final int ActivityGetCanGiveFriendGiftReq = 8934; + public static final int IrodoriMasterStartGalleryReq = 8344; + public static final int ExitCustomDungeonTryRsp = 6212; + public static final int PotionEnterDungeonNotify = 8295; + public static final int SalvagePreventRestartReq = 8439; + public static final int RogueDiaryDungeonSettleNotify = 8220; + public static final int WinterCampGetRecvItemListRsp = 8234; + public static final int PhotoActivityClientViewRsp = 8945; + public static final int StartRogueDiaryPlayRsp = 8169; + public static final int PotionRestartDungeonReq = 8613; + public static final int LikeCustomDungeonRsp = 6203; + public static final int GearActivityFinishPlayGearRsp = 20017; + public static final int NightCrowGadgetObservationMatchRsp = 818; + public static final int GearActivityStartPlayPictureReq = 24138; + public static final int ActivityReadPushTipsRsp = 8119; + public static final int IslandPartyRaftInfoNotify = 5544; + public static final int GearActivityStartPlayGearReq = 24337; + public static final int SummerTimeV2RestartDungeonReq = 8988; + public static final int NightCrowGadgetObservationMatchReq = 825; + public static final int InvestigationReadQuestDailyNotify = 1921; + public static final int InvestigationQuestDailyNotify = 1902; + public static final int GearActivityFinishPlayPictureRsp = 23580; + public static final int GearActivityStartPlayGearRsp = 22301; + public static final int IslandPartySettleNotify = 20411; + public static final int GearActivityStartPlayPictureRsp = 23136; + public static final int TakeBackGivingItemRsp = 110; + public static final int GalleryWillStartCountdownNotify = 5584; + public static final int ActivityPushTipsInfoNotify = 8419; + public static final int PersistentDungeonSwitchAvatarReq = 1720; + public static final int SummerTimeV2RestartBoatGalleryReq = 8676; + public static final int StopReminderNotify = 3241; + public static final int IslandPartySailInfoNotify = 5594; + public static final int SummerTimeV2RestartDungeonRsp = 8101; + public static final int GearActivityFinishPlayGearReq = 24069; + public static final int BackRebornGalleryReq = 5574; + public static final int PersistentDungeonSwitchAvatarRsp = 1656; + public static final int GalleryIslandPartyDownHillInfoNotify = 5519; + public static final int GadgetChangeLevelTagRsp = 837; + public static final int ActivityReadPushTipsReq = 8285; + public static final int BackRebornGalleryRsp = 5546; + public static final int SummerTimeV2RestartBoatGalleryRsp = 8599; + public static final int SummerTimeV2BoatSettleNotify = 8436; + public static final int TakeBackGivingItemReq = 152; + public static final int GadgetChangeLevelTagReq = 816; + public static final int GearActivityFinishPlayPictureReq = 21009; + public static final int HomeExchangeWoodRsp = 4582; + public static final int HomeExchangeWoodReq = 4716; + public static final int GravenInnocenceEditCarveCombinationRsp = 20912; + public static final int GetAllMailResultNotify = 1429; + public static final int MuqadasPotionRestartDungeonReq = 23633; + public static final int ToTheMoonRemoveObstacleRsp = 6165; + public static final int MuqadasPotionCaptureWeaknessReq = 23970; + public static final int GravenInnocenceEditCarveCombinationReq = 24190; + public static final int ParentQuestInferenceDataNotify = 430; + public static final int DelBackupAvatarTeamReq = 1608; + public static final int AssociateInferenceWordReq = 438; + public static final int AvatarTeamAllDataNotify = 1729; + public static final int InstableSprayGalleryInfoNotify = 5541; + public static final int PlayerCompoundMaterialBoostReq = 177; + public static final int GravenInnocencePhotoFinishReq = 23079; + public static final int InstableSpraySwitchTeamReq = 24932; + public static final int SubmitInferenceWordRsp = 443; + public static final int InstableSprayEnterDungeonRsp = 24557; + public static final int AllWidgetBackgroundActiveStateNotify = 6034; + public static final int GetHomeExchangeWoodInfoReq = 4852; + public static final int GetAllMailNotify = 1442; + public static final int GravenInnocenceRaceRestartRsp = 24201; + public static final int InstableSprayRestartDungeonReq = 23108; + public static final int ToTheMoonAddObstacleRsp = 6172; + public static final int GetHomeExchangeWoodInfoRsp = 4592; + public static final int WorldChestOpenNotify = 3279; + public static final int DeshretObeliskChestInfoNotify = 858; + public static final int MuqadasPotionRestartDungeonRsp = 20273; + public static final int RemotePlayerWidgetNotify = 6009; + public static final int GravenInnocencePhotoFinishRsp = 23629; + public static final int InstableSprayLevelFinishNotify = 23121; + public static final int ChangeWidgetBackgroundActiveStateRsp = 6042; + public static final int AddBackupAvatarTeamRsp = 1777; + public static final int MuqadasPotionActivityEnterDungeonRsp = 22334; + public static final int AddBackupAvatarTeamReq = 1602; + public static final int PlayerDeathZoneNotify = 6259; + public static final int PlayerCompoundMaterialBoostRsp = 162; + public static final int InstableSpraySwitchTeamRsp = 23402; + public static final int TreasureSeelieCollectOrbsNotify = 24055; + public static final int AranaraCollectionDataNotify = 6398; + public static final int AssociateInferenceWordRsp = 404; + public static final int MuqadasPotionCaptureWeaknessRsp = 23854; + public static final int DelBackupAvatarTeamRsp = 1615; + public static final int InterpretInferenceWordRsp = 453; + public static final int MuqadasPotionActivityEnterDungeonReq = 21504; + public static final int ToTheMoonRemoveObstacleReq = 6182; + public static final int CheckGroupReplacedReq = 3036; + public static final int ToTheMoonEnterSceneRsp = 6114; + public static final int CheckGroupReplacedRsp = 3190; + public static final int InstableSprayEnterDungeonReq = 23181; + public static final int ToTheMoonEnterSceneReq = 6164; + public static final int ToTheMoonQueryPathRsp = 6175; + public static final int InterpretInferenceWordReq = 487; + public static final int AreaPlayInfoNotify = 3472; + public static final int ToTheMoonAddObstacleReq = 6134; + public static final int MuqadasPotionDungeonSettleNotify = 20893; + public static final int ToTheMoonPingNotify = 6154; + public static final int InstableSprayRestartDungeonRsp = 20879; + public static final int ToTheMoonQueryPathReq = 6167; + public static final int DeathZoneInfoNotify = 6293; + public static final int WidgetQuickHitTreeReq = 3068; + public static final int AddAranaraCollectionNotify = 6393; + public static final int ChangeWidgetBackgroundActiveStateReq = 5953; + public static final int DeathZoneObserveNotify = 3232; + public static final int GravenInnocenceRaceRestartReq = 22616; + public static final int GravenInnocencePhotoReminderNotify = 24173; + public static final int WidgetQuickHitTreeRsp = 3174; + public static final int GravenInnocenceRaceSettleNotify = 24552; + public static final int WatcherEventStageNotify = 2214; + public static final int SubmitInferenceWordReq = 420; + public static final int UnlockAvatarTalentReq = 1067; + public static final int UnlockAvatarTalentRsp = 1075; + public static final int UnlockCoopChapterReq = 1985; + public static final int UnlockCoopChapterRsp = 1971; + public static final int UnlockNameCardNotify = 4086; + public static final int UnlockPersonalLineReq = 405; + public static final int UnlockPersonalLineRsp = 471; + public static final int UnlockTransPointReq = 3180; + public static final int UnlockTransPointRsp = 3311; + public static final int UnlockedFurnitureFormulaDataNotify = 4481; + public static final int UnlockedFurnitureSuiteDataNotify = 4684; + public static final int UnmarkEntityInMinMapNotify = 287; + public static final int UpdateAbilityCreatedMovingPlatformNotify = 829; + public static final int UpdatePS4BlockListReq = 4018; + public static final int UpdatePS4BlockListRsp = 4058; + public static final int UpdatePS4FriendListNotify = 4056; + public static final int UpdatePS4FriendListReq = 4006; + public static final int UpdatePS4FriendListRsp = 4090; + public static final int UpdatePlayerShowAvatarListReq = 4040; + public static final int UpdatePlayerShowAvatarListRsp = 4011; + public static final int UpdatePlayerShowNameCardListReq = 4030; + public static final int UpdatePlayerShowNameCardListRsp = 4087; + public static final int UpdateRedPointNotify = 74; + public static final int UpdateReunionWatcherNotify = 5051; + public static final int UpgradeRoguelikeShikigamiReq = 8907; + public static final int UpgradeRoguelikeShikigamiRsp = 8493; + public static final int UseItemReq = 682; + public static final int UseItemRsp = 665; + public static final int UseMiracleRingReq = 5248; + public static final int UseMiracleRingRsp = 5243; + public static final int UseWidgetCreateGadgetReq = 4292; + public static final int UseWidgetCreateGadgetRsp = 4284; + public static final int UseWidgetRetractGadgetReq = 4283; + public static final int UseWidgetRetractGadgetRsp = 4277; + public static final int VehicleInteractReq = 844; + public static final int VehicleInteractRsp = 894; + public static final int VehicleStaminaNotify = 826; + public static final int ViewCodexReq = 4206; + public static final int ViewCodexRsp = 4204; + public static final int WatcherAllDataNotify = 2267; + public static final int WatcherChangeNotify = 2275; + public static final int WatcherEventNotify = 2254; + public static final int WatcherEventTypeNotify = 2264; + public static final int WaterSpritePhaseFinishNotify = 2096; + public static final int WeaponAwakenReq = 657; + public static final int WeaponAwakenRsp = 686; + public static final int WeaponPromoteReq = 619; + public static final int WeaponPromoteRsp = 644; + public static final int WeaponUpgradeReq = 656; + public static final int WeaponUpgradeRsp = 623; + public static final int WearEquipReq = 642; + public static final int WearEquipRsp = 629; + public static final int WidgetActiveChangeNotify = 4264; + public static final int WidgetCoolDownNotify = 4271; + public static final int WidgetDoBagReq = 4299; + public static final int WidgetDoBagRsp = 4295; + public static final int WidgetGadgetAllDataNotify = 4280; + public static final int WidgetGadgetDataNotify = 4273; + public static final int WidgetGadgetDestroyNotify = 4263; + public static final int WidgetReportReq = 4251; + public static final int WidgetReportRsp = 4252; + public static final int WidgetSlotChangeNotify = 4254; + public static final int WidgetUseAttachAbilityGroupChangeNotify = 4291; + public static final int WindSeedClientNotify = 1150; + public static final int WorktopOptionNotify = 864; + public static final int WorldAllRoutineTypeNotify = 3543; + public static final int WorldDataNotify = 3357; + public static final int WorldOwnerBlossomBriefInfoNotify = 2764; + public static final int WorldOwnerBlossomScheduleInfoNotify = 2714; + public static final int WorldOwnerDailyTaskNotify = 130; + public static final int WorldPlayerDieNotify = 277; + public static final int WorldPlayerInfoNotify = 3247; + public static final int WorldPlayerLocationNotify = 211; + public static final int WorldPlayerRTTNotify = 19; + public static final int WorldPlayerReviveReq = 262; + public static final int WorldPlayerReviveRsp = 268; + public static final int WorldRoutineChangeNotify = 3546; + public static final int WorldRoutineTypeCloseNotify = 3536; + public static final int WorldRoutineTypeRefreshNotify = 3509; + public static final int SkipPlayerGameTimeReq = 163; + public static final int SkipPlayerGameTimeRsp = 196; +} diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java index 280940cb7..4a828ce99 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java @@ -1,72 +1,75 @@ -package emu.grasscutter.net.packet; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.utils.JsonUtils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.stream.Collectors; - -public class PacketOpcodesUtils { - public static final Set BANNED_PACKETS = Set.of( - PacketOpcodes.WindSeedClientNotify, - PacketOpcodes.PlayerLuaShellNotify - ); - public static final Set LOOP_PACKETS = Set.of( - PacketOpcodes.PingReq, - PacketOpcodes.PingRsp, - PacketOpcodes.WorldPlayerRTTNotify, - PacketOpcodes.UnionCmdNotify, - PacketOpcodes.QueryPathReq, - PacketOpcodes.QueryPathRsp, - - // Satiation sends these every tick - PacketOpcodes.PlayerTimeNotify, - PacketOpcodes.PlayerGameTimeNotify, - PacketOpcodes.AvatarPropNotify, - PacketOpcodes.AvatarSatiationDataNotify - ); - private static final Int2ObjectMap opcodeMap; - - static { - opcodeMap = new Int2ObjectOpenHashMap(); - - Field[] fields = PacketOpcodes.class.getFields(); - - for (Field f : fields) { - if (f.getType().equals(int.class)) { - try { - opcodeMap.put(f.getInt(null), f.getName()); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - public static String getOpcodeName(int opcode) { - if (opcode <= 0) return "UNKNOWN"; - return opcodeMap.getOrDefault(opcode, "UNKNOWN"); - } - - public static void dumpPacketIds() { - try (FileWriter writer = new FileWriter("./PacketIds_" + GameConstants.VERSION + ".json")) { - // Create sorted tree map - Map packetIds = opcodeMap.int2ObjectEntrySet().stream() - .filter(e -> e.getIntKey() > 0) - .collect(Collectors.toMap(Int2ObjectMap.Entry::getIntKey, Int2ObjectMap.Entry::getValue, (k, v) -> v, TreeMap::new)); - // Write to file - writer.write(JsonUtils.encode(packetIds)); - Grasscutter.getLogger().info("Dumped packet ids."); - } catch (IOException e) { - e.printStackTrace(); - } - } -} +package emu.grasscutter.net.packet; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.utils.JsonUtils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +public class PacketOpcodesUtils { + public static final Set BANNED_PACKETS = + Set.of(PacketOpcodes.WindSeedClientNotify, PacketOpcodes.PlayerLuaShellNotify); + public static final Set LOOP_PACKETS = + Set.of( + PacketOpcodes.PingReq, + PacketOpcodes.PingRsp, + PacketOpcodes.WorldPlayerRTTNotify, + PacketOpcodes.UnionCmdNotify, + PacketOpcodes.QueryPathReq, + PacketOpcodes.QueryPathRsp, + + // Satiation sends these every tick + PacketOpcodes.PlayerTimeNotify, + PacketOpcodes.PlayerGameTimeNotify, + PacketOpcodes.AvatarPropNotify, + PacketOpcodes.AvatarSatiationDataNotify); + private static final Int2ObjectMap opcodeMap; + + static { + opcodeMap = new Int2ObjectOpenHashMap(); + + Field[] fields = PacketOpcodes.class.getFields(); + + for (Field f : fields) { + if (f.getType().equals(int.class)) { + try { + opcodeMap.put(f.getInt(null), f.getName()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + public static String getOpcodeName(int opcode) { + if (opcode <= 0) return "UNKNOWN"; + return opcodeMap.getOrDefault(opcode, "UNKNOWN"); + } + + public static void dumpPacketIds() { + try (FileWriter writer = new FileWriter("./PacketIds_" + GameConstants.VERSION + ".json")) { + // Create sorted tree map + Map packetIds = + opcodeMap.int2ObjectEntrySet().stream() + .filter(e -> e.getIntKey() > 0) + .collect( + Collectors.toMap( + Int2ObjectMap.Entry::getIntKey, + Int2ObjectMap.Entry::getValue, + (k, v) -> v, + TreeMap::new)); + // Write to file + writer.write(JsonUtils.encode(packetIds)); + Grasscutter.getLogger().info("Dumped packet ids."); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/net/packet/PacketWriter.java b/src/main/java/emu/grasscutter/net/packet/PacketWriter.java index 645546c8d..6b98981f8 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketWriter.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketWriter.java @@ -1,177 +1,176 @@ -package emu.grasscutter.net.packet; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -public class PacketWriter { - // Little endian - private final ByteArrayOutputStream baos; - - public PacketWriter() { - this.baos = new ByteArrayOutputStream(128); - } - - public byte[] build() { - return baos.toByteArray(); - } - - // Writers - - public void writeEmpty(int i) { - while (i > 0) { - baos.write(0); - i--; - } - } - - public void writeMax(int i) { - while (i > 0) { - baos.write(0xFF); - i--; - } - } - - public void writeInt8(byte b) { - baos.write(b); - } - - public void writeInt8(int i) { - baos.write((byte) i); - } - - public void writeBoolean(boolean b) { - baos.write(b ? 1 : 0); - } - - public void writeUint8(byte b) { - // Unsigned byte - baos.write(b & 0xFF); - } - - public void writeUint8(int i) { - - baos.write((byte) i & 0xFF); - } - - public void writeUint16(int i) { - // Unsigned short - baos.write((byte) (i & 0xFF)); - baos.write((byte) ((i >>> 8) & 0xFF)); - } - - public void writeUint24(int i) { - // 24 bit integer - baos.write((byte) (i & 0xFF)); - baos.write((byte) ((i >>> 8) & 0xFF)); - baos.write((byte) ((i >>> 16) & 0xFF)); - } - - public void writeInt16(int i) { - // Signed short - baos.write((byte) i); - baos.write((byte) (i >>> 8)); - } - - public void writeUint32(int i) { - // Unsigned int - baos.write((byte) (i & 0xFF)); - baos.write((byte) ((i >>> 8) & 0xFF)); - baos.write((byte) ((i >>> 16) & 0xFF)); - baos.write((byte) ((i >>> 24) & 0xFF)); - } - - public void writeInt32(int i) { - // Signed int - baos.write((byte) i); - baos.write((byte) (i >>> 8)); - baos.write((byte) (i >>> 16)); - baos.write((byte) (i >>> 24)); - } - - public void writeUint32(long i) { - // Unsigned int (long) - baos.write((byte) (i & 0xFF)); - baos.write((byte) ((i >>> 8) & 0xFF)); - baos.write((byte) ((i >>> 16) & 0xFF)); - baos.write((byte) ((i >>> 24) & 0xFF)); - } - - public void writeFloat(float f) { - this.writeUint32(Float.floatToRawIntBits(f)); - } - - public void writeUint64(long l) { - baos.write((byte) (l & 0xFF)); - baos.write((byte) ((l >>> 8) & 0xFF)); - baos.write((byte) ((l >>> 16) & 0xFF)); - baos.write((byte) ((l >>> 24) & 0xFF)); - baos.write((byte) ((l >>> 32) & 0xFF)); - baos.write((byte) ((l >>> 40) & 0xFF)); - baos.write((byte) ((l >>> 48) & 0xFF)); - baos.write((byte) ((l >>> 56) & 0xFF)); - } - - public void writeDouble(double d) { - long l = Double.doubleToLongBits(d); - this.writeUint64(l); - } - - public void writeString16(String s) { - if (s == null) { - this.writeUint16(0); - return; - } - - this.writeUint16(s.length() * 2); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - this.writeUint16((short) c); - } - } - - public void writeString8(String s) { - if (s == null) { - this.writeUint16(0); - return; - } - - this.writeUint16(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - this.writeUint8((byte) c); - } - } - - public void writeDirectString8(String s, int expectedSize) { - if (s == null) { - return; - } - - for (int i = 0; i < expectedSize; i++) { - char c = i < s.length() ? s.charAt(i) : 0; - this.writeUint8((byte) c); - } - } - - public void writeBytes(byte[] bytes) { - try { - baos.write(bytes); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void writeBytes(int[] bytes) { - byte[] b = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) - b[i] = (byte) bytes[i]; - - try { - baos.write(b); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package emu.grasscutter.net.packet; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class PacketWriter { + // Little endian + private final ByteArrayOutputStream baos; + + public PacketWriter() { + this.baos = new ByteArrayOutputStream(128); + } + + public byte[] build() { + return baos.toByteArray(); + } + + // Writers + + public void writeEmpty(int i) { + while (i > 0) { + baos.write(0); + i--; + } + } + + public void writeMax(int i) { + while (i > 0) { + baos.write(0xFF); + i--; + } + } + + public void writeInt8(byte b) { + baos.write(b); + } + + public void writeInt8(int i) { + baos.write((byte) i); + } + + public void writeBoolean(boolean b) { + baos.write(b ? 1 : 0); + } + + public void writeUint8(byte b) { + // Unsigned byte + baos.write(b & 0xFF); + } + + public void writeUint8(int i) { + + baos.write((byte) i & 0xFF); + } + + public void writeUint16(int i) { + // Unsigned short + baos.write((byte) (i & 0xFF)); + baos.write((byte) ((i >>> 8) & 0xFF)); + } + + public void writeUint24(int i) { + // 24 bit integer + baos.write((byte) (i & 0xFF)); + baos.write((byte) ((i >>> 8) & 0xFF)); + baos.write((byte) ((i >>> 16) & 0xFF)); + } + + public void writeInt16(int i) { + // Signed short + baos.write((byte) i); + baos.write((byte) (i >>> 8)); + } + + public void writeUint32(int i) { + // Unsigned int + baos.write((byte) (i & 0xFF)); + baos.write((byte) ((i >>> 8) & 0xFF)); + baos.write((byte) ((i >>> 16) & 0xFF)); + baos.write((byte) ((i >>> 24) & 0xFF)); + } + + public void writeInt32(int i) { + // Signed int + baos.write((byte) i); + baos.write((byte) (i >>> 8)); + baos.write((byte) (i >>> 16)); + baos.write((byte) (i >>> 24)); + } + + public void writeUint32(long i) { + // Unsigned int (long) + baos.write((byte) (i & 0xFF)); + baos.write((byte) ((i >>> 8) & 0xFF)); + baos.write((byte) ((i >>> 16) & 0xFF)); + baos.write((byte) ((i >>> 24) & 0xFF)); + } + + public void writeFloat(float f) { + this.writeUint32(Float.floatToRawIntBits(f)); + } + + public void writeUint64(long l) { + baos.write((byte) (l & 0xFF)); + baos.write((byte) ((l >>> 8) & 0xFF)); + baos.write((byte) ((l >>> 16) & 0xFF)); + baos.write((byte) ((l >>> 24) & 0xFF)); + baos.write((byte) ((l >>> 32) & 0xFF)); + baos.write((byte) ((l >>> 40) & 0xFF)); + baos.write((byte) ((l >>> 48) & 0xFF)); + baos.write((byte) ((l >>> 56) & 0xFF)); + } + + public void writeDouble(double d) { + long l = Double.doubleToLongBits(d); + this.writeUint64(l); + } + + public void writeString16(String s) { + if (s == null) { + this.writeUint16(0); + return; + } + + this.writeUint16(s.length() * 2); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + this.writeUint16((short) c); + } + } + + public void writeString8(String s) { + if (s == null) { + this.writeUint16(0); + return; + } + + this.writeUint16(s.length()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + this.writeUint8((byte) c); + } + } + + public void writeDirectString8(String s, int expectedSize) { + if (s == null) { + return; + } + + for (int i = 0; i < expectedSize; i++) { + char c = i < s.length() ? s.charAt(i) : 0; + this.writeUint8((byte) c); + } + } + + public void writeBytes(byte[] bytes) { + try { + baos.write(bytes); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void writeBytes(int[] bytes) { + byte[] b = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) b[i] = (byte) bytes[i]; + + try { + baos.write(b); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/plugin/Plugin.java b/src/main/java/emu/grasscutter/plugin/Plugin.java index 78e77ee9c..389b703df 100644 --- a/src/main/java/emu/grasscutter/plugin/Plugin.java +++ b/src/main/java/emu/grasscutter/plugin/Plugin.java @@ -1,135 +1,124 @@ -package emu.grasscutter.plugin; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.plugin.api.ServerHook; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.utils.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.InputStream; -import java.net.URLClassLoader; - -/** - * The base class for all plugins to extend. - */ -public abstract class Plugin { - private final ServerHook server = ServerHook.getInstance(); - - private PluginIdentifier identifier; - private URLClassLoader classLoader; - private File dataFolder; - private Logger logger; - - /** - * This method is reflected into. - *

- * Set plugin variables. - * - * @param identifier The plugin's identifier. - */ - private void initializePlugin(PluginIdentifier identifier, URLClassLoader classLoader) { - if (this.identifier != null) { - Grasscutter.getLogger().warn(this.identifier.name + " had a reinitialization attempt."); - return; - } - - this.identifier = identifier; - this.classLoader = classLoader; - this.dataFolder = FileUtils.getPluginPath(identifier.name).toFile(); - this.logger = LoggerFactory.getLogger(identifier.name); - - if (!this.dataFolder.exists() && !this.dataFolder.mkdirs()) { - Grasscutter.getLogger().warn("Failed to create plugin data folder for " + this.identifier.name); - } - } - - /** - * The plugin's identifier instance. - * - * @return An instance of {@link PluginIdentifier}. - */ - public final PluginIdentifier getIdentifier() { - return this.identifier; - } - - /** - * Get the plugin's name. - */ - public final String getName() { - return this.identifier.name; - } - - /** - * Get the plugin's description. - */ - public final String getDescription() { - return this.identifier.description; - } - - /** - * Get the plugin's version. - */ - public final String getVersion() { - return this.identifier.version; - } - - /** - * Returns the server that initialized the plugin. - * - * @return A server instance. - */ - public final GameServer getServer() { - return this.server.getGameServer(); - } - - /** - * Returns an input stream for a resource in the JAR file. - * - * @param resourceName The name of the resource. - * @return An input stream. - */ - public final InputStream getResource(String resourceName) { - return this.classLoader.getResourceAsStream(resourceName); - } - - /** - * Returns a directory where plugins can store data files. - * - * @return A directory on the file system. - */ - public final File getDataFolder() { - return this.dataFolder; - } - - /** - * Returns the server hook. - * - * @return A server hook singleton. - */ - public final ServerHook getHandle() { - return this.server; - } - - /** - * Returns the plugin's logger. - * - * @return A SLF4J logger. - */ - public final Logger getLogger() { - return this.logger; - } - - /* Called when the plugin is first loaded. */ - public void onLoad() { - } - - /* Called after (most of) the server enables. */ - public void onEnable() { - } - - /* Called before the server disables. */ - public void onDisable() { - } -} +package emu.grasscutter.plugin; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.plugin.api.ServerHook; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.utils.FileUtils; +import java.io.File; +import java.io.InputStream; +import java.net.URLClassLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** The base class for all plugins to extend. */ +public abstract class Plugin { + private final ServerHook server = ServerHook.getInstance(); + + private PluginIdentifier identifier; + private URLClassLoader classLoader; + private File dataFolder; + private Logger logger; + + /** + * This method is reflected into. + * + *

Set plugin variables. + * + * @param identifier The plugin's identifier. + */ + private void initializePlugin(PluginIdentifier identifier, URLClassLoader classLoader) { + if (this.identifier != null) { + Grasscutter.getLogger().warn(this.identifier.name + " had a reinitialization attempt."); + return; + } + + this.identifier = identifier; + this.classLoader = classLoader; + this.dataFolder = FileUtils.getPluginPath(identifier.name).toFile(); + this.logger = LoggerFactory.getLogger(identifier.name); + + if (!this.dataFolder.exists() && !this.dataFolder.mkdirs()) { + Grasscutter.getLogger() + .warn("Failed to create plugin data folder for " + this.identifier.name); + } + } + + /** + * The plugin's identifier instance. + * + * @return An instance of {@link PluginIdentifier}. + */ + public final PluginIdentifier getIdentifier() { + return this.identifier; + } + + /** Get the plugin's name. */ + public final String getName() { + return this.identifier.name; + } + + /** Get the plugin's description. */ + public final String getDescription() { + return this.identifier.description; + } + + /** Get the plugin's version. */ + public final String getVersion() { + return this.identifier.version; + } + + /** + * Returns the server that initialized the plugin. + * + * @return A server instance. + */ + public final GameServer getServer() { + return this.server.getGameServer(); + } + + /** + * Returns an input stream for a resource in the JAR file. + * + * @param resourceName The name of the resource. + * @return An input stream. + */ + public final InputStream getResource(String resourceName) { + return this.classLoader.getResourceAsStream(resourceName); + } + + /** + * Returns a directory where plugins can store data files. + * + * @return A directory on the file system. + */ + public final File getDataFolder() { + return this.dataFolder; + } + + /** + * Returns the server hook. + * + * @return A server hook singleton. + */ + public final ServerHook getHandle() { + return this.server; + } + + /** + * Returns the plugin's logger. + * + * @return A SLF4J logger. + */ + public final Logger getLogger() { + return this.logger; + } + + /* Called when the plugin is first loaded. */ + public void onLoad() {} + + /* Called after (most of) the server enables. */ + public void onEnable() {} + + /* Called before the server disables. */ + public void onDisable() {} +} diff --git a/src/main/java/emu/grasscutter/plugin/PluginConfig.java b/src/main/java/emu/grasscutter/plugin/PluginConfig.java index c0339f5c6..8287b5da8 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginConfig.java +++ b/src/main/java/emu/grasscutter/plugin/PluginConfig.java @@ -1,21 +1,19 @@ -package emu.grasscutter.plugin; - -/** - * The data contained in the plugin's `plugin.json` file. - */ -public final class PluginConfig { - public String name, description, version; - public String mainClass; - public String[] authors; - public String[] loadAfter; - - /** - * Attempts to validate this config instance. - * - * @return True if the config is valid, false otherwise. - */ - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - public boolean validate() { - return name != null && description != null && mainClass != null; - } -} +package emu.grasscutter.plugin; + +/** The data contained in the plugin's `plugin.json` file. */ +public final class PluginConfig { + public String name, description, version; + public String mainClass; + public String[] authors; + public String[] loadAfter; + + /** + * Attempts to validate this config instance. + * + * @return True if the config is valid, false otherwise. + */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean validate() { + return name != null && description != null && mainClass != null; + } +} diff --git a/src/main/java/emu/grasscutter/plugin/PluginIdentifier.java b/src/main/java/emu/grasscutter/plugin/PluginIdentifier.java index dc3eb0988..2a4671e89 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginIdentifier.java +++ b/src/main/java/emu/grasscutter/plugin/PluginIdentifier.java @@ -1,29 +1,22 @@ -package emu.grasscutter.plugin; - -// TODO: Potentially replace with Lombok? -public final class PluginIdentifier { - public final String name, description, version; - public final String[] authors; - - public PluginIdentifier( - String name, String description, String version, - String[] authors - ) { - this.name = name; - this.description = description; - this.version = version; - this.authors = authors; - } - - /** - * Converts a {@link PluginConfig} into a {@link PluginIdentifier}. - */ - public static PluginIdentifier fromPluginConfig(PluginConfig config) { - if (!config.validate()) - throw new IllegalArgumentException("A valid plugin config is required to convert into a plugin identifier."); - return new PluginIdentifier( - config.name, config.description, config.version, - config.authors - ); - } -} +package emu.grasscutter.plugin; + +// TODO: Potentially replace with Lombok? +public final class PluginIdentifier { + public final String name, description, version; + public final String[] authors; + + public PluginIdentifier(String name, String description, String version, String[] authors) { + this.name = name; + this.description = description; + this.version = version; + this.authors = authors; + } + + /** Converts a {@link PluginConfig} into a {@link PluginIdentifier}. */ + public static PluginIdentifier fromPluginConfig(PluginConfig config) { + if (!config.validate()) + throw new IllegalArgumentException( + "A valid plugin config is required to convert into a plugin identifier."); + return new PluginIdentifier(config.name, config.description, config.version, config.authors); + } +} diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index 74c2561aa..9fbbbfb3b 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -1,319 +1,321 @@ -package emu.grasscutter.plugin; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.server.event.Event; -import emu.grasscutter.server.event.EventHandler; -import emu.grasscutter.server.event.HandlerPriority; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.JsonUtils; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import javax.annotation.Nullable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -import static emu.grasscutter.utils.Language.translate; - -/** - * Manages the server's plugins and the event system. - */ -public final class PluginManager { - /* All loaded plugins. */ - private final Map plugins = new LinkedHashMap<>(); - /* All currently registered listeners per plugin. */ - private final Map>> listeners = new LinkedHashMap<>(); - - public PluginManager() { - this.loadPlugins(); // Load all plugins from the plugins directory. - } - - /** - * Loads plugins from the config-specified directory. - */ - private void loadPlugins() { - File pluginsDir = FileUtils.getPluginPath("").toFile(); - if (!pluginsDir.exists() && !pluginsDir.mkdirs()) { - Grasscutter.getLogger().error(translate("plugin.directory_failed", pluginsDir.getAbsolutePath())); - return; - } - - File[] files = pluginsDir.listFiles(); - if (files == null) { - // The directory is empty, there aren't any plugins to load. - return; - } - - List plugins = Arrays.stream(files) - .filter(file -> file.getName().endsWith(".jar")) - .toList(); - - URL[] pluginNames = new URL[plugins.size()]; - plugins.forEach(plugin -> { - try { - pluginNames[plugins.indexOf(plugin)] = plugin.toURI().toURL(); - } catch (MalformedURLException exception) { - Grasscutter.getLogger().warn(translate("plugin.unable_to_load"), exception); - } - }); - - // Create a class loader for the plugins. - URLClassLoader classLoader = new URLClassLoader(pluginNames); - // Create a list of plugins that require dependencies. - List dependencies = new ArrayList<>(); - - // Initialize all plugins. - for (var plugin : plugins) { - try { - URL url = plugin.toURI().toURL(); - try (URLClassLoader loader = new URLClassLoader(new URL[]{url})) { - // Find the plugin.json file for each plugin. - URL configFile = loader.findResource("plugin.json"); - // Open the config file for reading. - InputStreamReader fileReader = new InputStreamReader(configFile.openStream()); - - // Create a plugin config instance from the config file. - PluginConfig pluginConfig = JsonUtils.loadToClass(fileReader, PluginConfig.class); - // Check if the plugin config is valid. - if (!pluginConfig.validate()) { - Grasscutter.getLogger().warn(translate("plugin.invalid_config", plugin.getName())); - return; - } - - // Create a JAR file instance from the plugin's URL. - JarFile jarFile = new JarFile(plugin); - // Load all class files from the JAR file. - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - if (entry.isDirectory() || !entry.getName().endsWith(".class") || entry.getName().contains("module-info")) - continue; - String className = entry.getName().replace(".class", "").replace("/", "."); - classLoader.loadClass(className); // Use the same class loader for ALL plugins. - } - - // Create a plugin instance. - Class pluginClass = classLoader.loadClass(pluginConfig.mainClass); - Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); - // Close the file reader. - fileReader.close(); - - // Check if the plugin has alternate dependencies. - if (pluginConfig.loadAfter != null && pluginConfig.loadAfter.length > 0) { - // Add the plugin to a "load later" list. - dependencies.add(new PluginData( - pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig), - loader, pluginConfig.loadAfter)); - continue; - } - - // Load the plugin. - this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig), loader); - } catch (ClassNotFoundException ignored) { - Grasscutter.getLogger().warn(translate("plugin.invalid_main_class", plugin.getName())); - } catch (FileNotFoundException ignored) { - Grasscutter.getLogger().warn(translate("plugin.missing_config", plugin.getName())); - } - } catch (Exception exception) { - Grasscutter.getLogger().error(translate("plugin.failed_to_load_plugin", plugin.getName()), exception); - } - } - - // Load plugins with dependencies. - int depth = 0; - final int maxDepth = 30; - while (!dependencies.isEmpty()) { - // Check if the depth is too high. - if (depth >= maxDepth) { - Grasscutter.getLogger().error(translate("plugin.failed_to_load_dependencies")); - break; - } - - try { - // Get the next plugin to load. - var pluginData = dependencies.get(0); - - // Check if the plugin's dependencies are loaded. - if (!this.plugins.keySet().containsAll(List.of(pluginData.getDependencies()))) { - depth++; // Increase depth counter. - continue; // Continue to next plugin. - } - - // Remove the plugin from the list of dependencies. - dependencies.remove(pluginData); - - // Load the plugin. - this.loadPlugin(pluginData.getPlugin(), pluginData.getIdentifier(), pluginData.getClassLoader()); - } catch (Exception exception) { - Grasscutter.getLogger().error(translate("plugin.failed_to_load"), exception); - depth++; - } - } - } - - /** - * Load the specified plugin. - * - * @param plugin The plugin instance. - */ - private void loadPlugin(Plugin plugin, PluginIdentifier identifier, URLClassLoader classLoader) { - Grasscutter.getLogger().info(translate("plugin.loading_plugin", identifier.name)); - - // Add the plugin's identifier. - try { - Class pluginClass = Plugin.class; - Method method = pluginClass.getDeclaredMethod("initializePlugin", PluginIdentifier.class, URLClassLoader.class); - method.setAccessible(true); - method.invoke(plugin, identifier, classLoader); - method.setAccessible(false); - } catch (Exception ignored) { - Grasscutter.getLogger().warn(translate("plugin.failed_add_id", identifier.name)); - } - - // Add the plugin to the list of loaded plugins. - this.plugins.put(identifier.name, plugin); - // Create a collection for the plugin's listeners. - this.listeners.put(plugin, new ArrayList<>()); - - // Call the plugin's onLoad method. - try { - plugin.onLoad(); - } catch (Throwable exception) { - Grasscutter.getLogger().error(translate("plugin.failed_to_load_plugin", identifier.name), exception); - } - } - - /** - * Enables all registered plugins. - */ - public void enablePlugins() { - this.plugins.forEach((name, plugin) -> { - Grasscutter.getLogger().info(translate("plugin.enabling_plugin", name)); - try { - plugin.onEnable(); - } catch (Throwable exception) { - Grasscutter.getLogger().error(translate("plugin.enabling_failed", name), exception); - } - }); - } - - /** - * Disables all registered plugins. - */ - public void disablePlugins() { - this.plugins.forEach((name, plugin) -> { - Grasscutter.getLogger().info(translate("plugin.disabling_plugin", name)); - this.disablePlugin(plugin); - }); - } - - /** - * Registers a plugin's event listener. - * - * @param plugin The plugin registering the listener. - * @param listener The event listener. - */ - public void registerListener(Plugin plugin, EventHandler listener) { - this.listeners.get(plugin).add(listener); - } - - /** - * Invoke the provided event on all registered event listeners. - * - * @param event The event to invoke. - */ - public void invokeEvent(Event event) { - EnumSet.allOf(HandlerPriority.class) - .forEach(priority -> this.checkAndFilter(event, priority)); - } - - /** - * Check an event to handlers for the priority. - * - * @param event The event being called. - * @param priority The priority to call for. - */ - private void checkAndFilter(Event event, HandlerPriority priority) { - // Add all listeners from every plugin. - this.listeners.values().stream() - .flatMap(Collection::stream) - // Filter the listeners by priority. - .filter(handler -> handler.handles().isInstance(event)) - .filter(handler -> handler.getPriority() == priority) - // Invoke the event. - .forEach(handler -> this.invokeHandler(event, handler)); - } - - /** - * Gets a plugin's instance by its name. - * - * @param name The name of the plugin. - * @return Either null, or the plugin's instance. - */ - @Nullable - public Plugin getPlugin(String name) { - return this.plugins.get(name); - } - - /** - * Enables a plugin. - * - * @param plugin The plugin to enable. - */ - public void enablePlugin(Plugin plugin) { - try { - // Call the plugin's onEnable method. - plugin.onEnable(); - } catch (Exception exception) { - Grasscutter.getLogger().error(translate("plugin.enabling_failed", plugin.getName()), exception); - } - } - - /** - * Disables a plugin. - * - * @param plugin The plugin to disable. - */ - public void disablePlugin(Plugin plugin) { - try { - // Call the plugin's onDisable method. - plugin.onDisable(); - } catch (Exception exception) { - Grasscutter.getLogger().error(translate("plugin.disabling_failed", plugin.getName()), exception); - } - - // Un-register all listeners. - this.listeners.remove(plugin); - } - - /** - * Performs logic checks then invokes the provided event handler. - * - * @param event The event passed through to the handler. - * @param handler The handler to invoke. - */ - @SuppressWarnings("unchecked") - private void invokeHandler(Event event, EventHandler handler) { - if (!event.isCanceled() || - (event.isCanceled() && handler.ignoresCanceled()) - ) handler.getCallback().consume((T) event); - } - - /* Data about an unloaded plugin. */ - @AllArgsConstructor - @Getter - static class PluginData { - private Plugin plugin; - private PluginIdentifier identifier; - private URLClassLoader classLoader; - private String[] dependencies; - } -} +package emu.grasscutter.plugin; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.server.event.Event; +import emu.grasscutter.server.event.EventHandler; +import emu.grasscutter.server.event.HandlerPriority; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.JsonUtils; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import javax.annotation.Nullable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** Manages the server's plugins and the event system. */ +public final class PluginManager { + /* All loaded plugins. */ + private final Map plugins = new LinkedHashMap<>(); + /* All currently registered listeners per plugin. */ + private final Map>> listeners = new LinkedHashMap<>(); + + public PluginManager() { + this.loadPlugins(); // Load all plugins from the plugins directory. + } + + /** Loads plugins from the config-specified directory. */ + private void loadPlugins() { + File pluginsDir = FileUtils.getPluginPath("").toFile(); + if (!pluginsDir.exists() && !pluginsDir.mkdirs()) { + Grasscutter.getLogger() + .error(translate("plugin.directory_failed", pluginsDir.getAbsolutePath())); + return; + } + + File[] files = pluginsDir.listFiles(); + if (files == null) { + // The directory is empty, there aren't any plugins to load. + return; + } + + List plugins = + Arrays.stream(files).filter(file -> file.getName().endsWith(".jar")).toList(); + + URL[] pluginNames = new URL[plugins.size()]; + plugins.forEach( + plugin -> { + try { + pluginNames[plugins.indexOf(plugin)] = plugin.toURI().toURL(); + } catch (MalformedURLException exception) { + Grasscutter.getLogger().warn(translate("plugin.unable_to_load"), exception); + } + }); + + // Create a class loader for the plugins. + URLClassLoader classLoader = new URLClassLoader(pluginNames); + // Create a list of plugins that require dependencies. + List dependencies = new ArrayList<>(); + + // Initialize all plugins. + for (var plugin : plugins) { + try { + URL url = plugin.toURI().toURL(); + try (URLClassLoader loader = new URLClassLoader(new URL[] {url})) { + // Find the plugin.json file for each plugin. + URL configFile = loader.findResource("plugin.json"); + // Open the config file for reading. + InputStreamReader fileReader = new InputStreamReader(configFile.openStream()); + + // Create a plugin config instance from the config file. + PluginConfig pluginConfig = JsonUtils.loadToClass(fileReader, PluginConfig.class); + // Check if the plugin config is valid. + if (!pluginConfig.validate()) { + Grasscutter.getLogger().warn(translate("plugin.invalid_config", plugin.getName())); + return; + } + + // Create a JAR file instance from the plugin's URL. + JarFile jarFile = new JarFile(plugin); + // Load all class files from the JAR file. + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() + || !entry.getName().endsWith(".class") + || entry.getName().contains("module-info")) continue; + String className = entry.getName().replace(".class", "").replace("/", "."); + classLoader.loadClass(className); // Use the same class loader for ALL plugins. + } + + // Create a plugin instance. + Class pluginClass = classLoader.loadClass(pluginConfig.mainClass); + Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); + // Close the file reader. + fileReader.close(); + + // Check if the plugin has alternate dependencies. + if (pluginConfig.loadAfter != null && pluginConfig.loadAfter.length > 0) { + // Add the plugin to a "load later" list. + dependencies.add( + new PluginData( + pluginInstance, + PluginIdentifier.fromPluginConfig(pluginConfig), + loader, + pluginConfig.loadAfter)); + continue; + } + + // Load the plugin. + this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig), loader); + } catch (ClassNotFoundException ignored) { + Grasscutter.getLogger().warn(translate("plugin.invalid_main_class", plugin.getName())); + } catch (FileNotFoundException ignored) { + Grasscutter.getLogger().warn(translate("plugin.missing_config", plugin.getName())); + } + } catch (Exception exception) { + Grasscutter.getLogger() + .error(translate("plugin.failed_to_load_plugin", plugin.getName()), exception); + } + } + + // Load plugins with dependencies. + int depth = 0; + final int maxDepth = 30; + while (!dependencies.isEmpty()) { + // Check if the depth is too high. + if (depth >= maxDepth) { + Grasscutter.getLogger().error(translate("plugin.failed_to_load_dependencies")); + break; + } + + try { + // Get the next plugin to load. + var pluginData = dependencies.get(0); + + // Check if the plugin's dependencies are loaded. + if (!this.plugins.keySet().containsAll(List.of(pluginData.getDependencies()))) { + depth++; // Increase depth counter. + continue; // Continue to next plugin. + } + + // Remove the plugin from the list of dependencies. + dependencies.remove(pluginData); + + // Load the plugin. + this.loadPlugin( + pluginData.getPlugin(), pluginData.getIdentifier(), pluginData.getClassLoader()); + } catch (Exception exception) { + Grasscutter.getLogger().error(translate("plugin.failed_to_load"), exception); + depth++; + } + } + } + + /** + * Load the specified plugin. + * + * @param plugin The plugin instance. + */ + private void loadPlugin(Plugin plugin, PluginIdentifier identifier, URLClassLoader classLoader) { + Grasscutter.getLogger().info(translate("plugin.loading_plugin", identifier.name)); + + // Add the plugin's identifier. + try { + Class pluginClass = Plugin.class; + Method method = + pluginClass.getDeclaredMethod( + "initializePlugin", PluginIdentifier.class, URLClassLoader.class); + method.setAccessible(true); + method.invoke(plugin, identifier, classLoader); + method.setAccessible(false); + } catch (Exception ignored) { + Grasscutter.getLogger().warn(translate("plugin.failed_add_id", identifier.name)); + } + + // Add the plugin to the list of loaded plugins. + this.plugins.put(identifier.name, plugin); + // Create a collection for the plugin's listeners. + this.listeners.put(plugin, new ArrayList<>()); + + // Call the plugin's onLoad method. + try { + plugin.onLoad(); + } catch (Throwable exception) { + Grasscutter.getLogger() + .error(translate("plugin.failed_to_load_plugin", identifier.name), exception); + } + } + + /** Enables all registered plugins. */ + public void enablePlugins() { + this.plugins.forEach( + (name, plugin) -> { + Grasscutter.getLogger().info(translate("plugin.enabling_plugin", name)); + try { + plugin.onEnable(); + } catch (Throwable exception) { + Grasscutter.getLogger().error(translate("plugin.enabling_failed", name), exception); + } + }); + } + + /** Disables all registered plugins. */ + public void disablePlugins() { + this.plugins.forEach( + (name, plugin) -> { + Grasscutter.getLogger().info(translate("plugin.disabling_plugin", name)); + this.disablePlugin(plugin); + }); + } + + /** + * Registers a plugin's event listener. + * + * @param plugin The plugin registering the listener. + * @param listener The event listener. + */ + public void registerListener(Plugin plugin, EventHandler listener) { + this.listeners.get(plugin).add(listener); + } + + /** + * Invoke the provided event on all registered event listeners. + * + * @param event The event to invoke. + */ + public void invokeEvent(Event event) { + EnumSet.allOf(HandlerPriority.class).forEach(priority -> this.checkAndFilter(event, priority)); + } + + /** + * Check an event to handlers for the priority. + * + * @param event The event being called. + * @param priority The priority to call for. + */ + private void checkAndFilter(Event event, HandlerPriority priority) { + // Add all listeners from every plugin. + this.listeners.values().stream() + .flatMap(Collection::stream) + // Filter the listeners by priority. + .filter(handler -> handler.handles().isInstance(event)) + .filter(handler -> handler.getPriority() == priority) + // Invoke the event. + .forEach(handler -> this.invokeHandler(event, handler)); + } + + /** + * Gets a plugin's instance by its name. + * + * @param name The name of the plugin. + * @return Either null, or the plugin's instance. + */ + @Nullable public Plugin getPlugin(String name) { + return this.plugins.get(name); + } + + /** + * Enables a plugin. + * + * @param plugin The plugin to enable. + */ + public void enablePlugin(Plugin plugin) { + try { + // Call the plugin's onEnable method. + plugin.onEnable(); + } catch (Exception exception) { + Grasscutter.getLogger() + .error(translate("plugin.enabling_failed", plugin.getName()), exception); + } + } + + /** + * Disables a plugin. + * + * @param plugin The plugin to disable. + */ + public void disablePlugin(Plugin plugin) { + try { + // Call the plugin's onDisable method. + plugin.onDisable(); + } catch (Exception exception) { + Grasscutter.getLogger() + .error(translate("plugin.disabling_failed", plugin.getName()), exception); + } + + // Un-register all listeners. + this.listeners.remove(plugin); + } + + /** + * Performs logic checks then invokes the provided event handler. + * + * @param event The event passed through to the handler. + * @param handler The handler to invoke. + */ + @SuppressWarnings("unchecked") + private void invokeHandler(Event event, EventHandler handler) { + if (!event.isCanceled() || (event.isCanceled() && handler.ignoresCanceled())) + handler.getCallback().consume((T) event); + } + + /* Data about an unloaded plugin. */ + @AllArgsConstructor + @Getter + static class PluginData { + private Plugin plugin; + private PluginIdentifier identifier; + private URLClassLoader classLoader; + private String[] dependencies; + } +} diff --git a/src/main/java/emu/grasscutter/plugin/api/Item.java b/src/main/java/emu/grasscutter/plugin/api/Item.java index 91b1a8a5c..6ecc10c8d 100644 --- a/src/main/java/emu/grasscutter/plugin/api/Item.java +++ b/src/main/java/emu/grasscutter/plugin/api/Item.java @@ -1,5 +1,5 @@ -package emu.grasscutter.plugin.api; - -public enum Item { - /* TODO: Use handbook to generate an Item enum. */ -} +package emu.grasscutter.plugin.api; + +public enum Item { +/* TODO: Use handbook to generate an Item enum. */ +} diff --git a/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java b/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java index 65f353c9a..028b93b7c 100644 --- a/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java +++ b/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java @@ -1,124 +1,122 @@ -package emu.grasscutter.plugin.api; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EnterReason; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; -import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify; -import emu.grasscutter.utils.Position; - -/** - * Hooks into the {@link Player} class, adding convenient ways to do certain things. - */ -public final class PlayerHook { - private final Player player; - - /** - * Hooks into the player. - * - * @param player The player to hook into. - */ - public PlayerHook(Player player) { - this.player = player; - } - - /** - * Kicks a player from the server. - * TODO: Refactor to kick using a packet. - */ - public void kick() { - this.player.getSession().close(); - } - - /** - * Sends a player to another scene. - * - * @param sceneId The scene to send the player to. - */ - public void changeScenes(int sceneId) { - this.player.getWorld().transferPlayerToScene(this.player, sceneId, this.player.getPosition()); - } - - /** - * Broadcasts an avatar property notify to all world players. - * - * @param property The property that was updated. - */ - public void updateFightProperty(FightProperty property) { - this.broadcastPacketToWorld(new PacketAvatarFightPropUpdateNotify(this.getCurrentAvatar(), property)); - } - - /** - * Broadcasts the packet sent to all world players. - * - * @param packet The packet to send. - */ - public void broadcastPacketToWorld(BasePacket packet) { - this.player.getWorld().broadcastPacket(packet); - } - - /** - * Set the currently equipped avatar's health. - * - * @param health The health to set the avatar to. - */ - public void setHealth(float health) { - this.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health); - this.updateFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - } - - /** - * Revives the specified avatar. - * - * @param avatar The avatar to revive. - */ - public void reviveAvatar(Avatar avatar) { - this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar)); - } - - /** - * Teleports a player to a position. - * This will **not** transfer the player to another scene. - * - * @param position The position to teleport the player to. - */ - public void teleport(Position position) { - this.player.getPosition().set(position); - this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player, - EnterType.ENTER_TYPE_JUMP, EnterReason.TransPoint, - this.player.getSceneId(), position - )); - } - - /** - * Gets the currently selected avatar's max health. - * - * @return The max health as a float. - */ - public float getMaxHealth() { - return this.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - } - - /** - * Gets the currently selected avatar in entity form. - * - * @return The avatar as an {@link EntityAvatar}. - */ - public EntityAvatar getCurrentAvatarEntity() { - return this.player.getTeamManager().getCurrentAvatarEntity(); - } - - /** - * Gets the currently selected avatar. - * - * @return The avatar as an {@link Avatar}. - */ - public Avatar getCurrentAvatar() { - return this.getCurrentAvatarEntity().getAvatar(); - } -} +package emu.grasscutter.plugin.api; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EnterReason; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; +import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; +import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; +import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify; +import emu.grasscutter.utils.Position; + +/** Hooks into the {@link Player} class, adding convenient ways to do certain things. */ +public final class PlayerHook { + private final Player player; + + /** + * Hooks into the player. + * + * @param player The player to hook into. + */ + public PlayerHook(Player player) { + this.player = player; + } + + /** Kicks a player from the server. TODO: Refactor to kick using a packet. */ + public void kick() { + this.player.getSession().close(); + } + + /** + * Sends a player to another scene. + * + * @param sceneId The scene to send the player to. + */ + public void changeScenes(int sceneId) { + this.player.getWorld().transferPlayerToScene(this.player, sceneId, this.player.getPosition()); + } + + /** + * Broadcasts an avatar property notify to all world players. + * + * @param property The property that was updated. + */ + public void updateFightProperty(FightProperty property) { + this.broadcastPacketToWorld( + new PacketAvatarFightPropUpdateNotify(this.getCurrentAvatar(), property)); + } + + /** + * Broadcasts the packet sent to all world players. + * + * @param packet The packet to send. + */ + public void broadcastPacketToWorld(BasePacket packet) { + this.player.getWorld().broadcastPacket(packet); + } + + /** + * Set the currently equipped avatar's health. + * + * @param health The health to set the avatar to. + */ + public void setHealth(float health) { + this.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health); + this.updateFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + } + + /** + * Revives the specified avatar. + * + * @param avatar The avatar to revive. + */ + public void reviveAvatar(Avatar avatar) { + this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar)); + } + + /** + * Teleports a player to a position. This will **not** transfer the player to another scene. + * + * @param position The position to teleport the player to. + */ + public void teleport(Position position) { + this.player.getPosition().set(position); + this.player.sendPacket( + new PacketPlayerEnterSceneNotify( + this.player, + EnterType.ENTER_TYPE_JUMP, + EnterReason.TransPoint, + this.player.getSceneId(), + position)); + } + + /** + * Gets the currently selected avatar's max health. + * + * @return The max health as a float. + */ + public float getMaxHealth() { + return this.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + } + + /** + * Gets the currently selected avatar in entity form. + * + * @return The avatar as an {@link EntityAvatar}. + */ + public EntityAvatar getCurrentAvatarEntity() { + return this.player.getTeamManager().getCurrentAvatarEntity(); + } + + /** + * Gets the currently selected avatar. + * + * @return The avatar as an {@link Avatar}. + */ + public Avatar getCurrentAvatar() { + return this.getCurrentAvatarEntity().getAvatar(); + } +} diff --git a/src/main/java/emu/grasscutter/plugin/api/ServerHook.java b/src/main/java/emu/grasscutter/plugin/api/ServerHook.java index cc53f5da1..8a116e3da 100644 --- a/src/main/java/emu/grasscutter/plugin/api/ServerHook.java +++ b/src/main/java/emu/grasscutter/plugin/api/ServerHook.java @@ -1,129 +1,126 @@ -package emu.grasscutter.plugin.api; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.auth.AuthenticationSystem; -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.command.PermissionHandler; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.game.GameServer; -import emu.grasscutter.server.http.HttpServer; -import emu.grasscutter.server.http.Router; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -/** - * Hooks into the {@link GameServer} class, adding convenient ways to do certain things. - */ -public final class ServerHook { - private static ServerHook instance; - private final GameServer gameServer; - private final HttpServer httpServer; - - /** - * Hooks into a server. - * - * @param gameServer The game server to hook into. - * @param httpServer The HTTP server to hook into. - */ - public ServerHook(GameServer gameServer, HttpServer httpServer) { - this.gameServer = gameServer; - this.httpServer = httpServer; - - instance = this; - } - - /** - * Gets the server hook instance. - * - * @return A {@link ServerHook} singleton. - */ - public static ServerHook getInstance() { - return instance; - } - - /** - * @return The game server. - */ - public GameServer getGameServer() { - return this.gameServer; - } - - /** - * @return The HTTP server. - */ - public HttpServer getHttpServer() { - return this.httpServer; - } - - /** - * Gets all online players. - * - * @return Players connected to the server. - */ - @Deprecated(forRemoval = true) - public List getOnlinePlayers() { - return new ArrayList<>(this.gameServer.getPlayers().values()); - } - - /** - * Gets all online players. - * - * @return Players connected to the server. - */ - public Stream getOnlinePlayersStream() { - return this.gameServer.getPlayers().values().stream(); - } - - /** - * Registers a command to the {@link emu.grasscutter.command.CommandMap}. - * - * @param handler The command handler. - */ - public void registerCommand(CommandHandler handler) { - Class clazz = handler.getClass(); - if (!clazz.isAnnotationPresent(Command.class)) - throw new IllegalArgumentException("Command handler must be annotated with @Command."); - Command commandData = clazz.getAnnotation(Command.class); - CommandMap.getInstance().registerCommand(commandData.label(), handler); - } - - /** - * Adds a router using an instance of a class. - * - * @param router A router instance. - */ - public void addRouter(Router router) { - this.addRouter(router.getClass()); - } - - /** - * Adds a router using a class. - * - * @param router The class of the router. - */ - public void addRouter(Class router) { - this.httpServer.addRouter(router); - } - - /** - * Sets the server's authentication system. - * - * @param authSystem An instance of the authentication system. - */ - public void setAuthSystem(AuthenticationSystem authSystem) { - Grasscutter.setAuthenticationSystem(authSystem); - } - - /** - * Sets the server's permission handler. - * - * @param permHandler An instance of the permission handler. - */ - public void setPermissionHandler(PermissionHandler permHandler) { - Grasscutter.setPermissionHandler(permHandler); - } -} +package emu.grasscutter.plugin.api; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.command.PermissionHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.http.HttpServer; +import emu.grasscutter.server.http.Router; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +/** Hooks into the {@link GameServer} class, adding convenient ways to do certain things. */ +public final class ServerHook { + private static ServerHook instance; + private final GameServer gameServer; + private final HttpServer httpServer; + + /** + * Hooks into a server. + * + * @param gameServer The game server to hook into. + * @param httpServer The HTTP server to hook into. + */ + public ServerHook(GameServer gameServer, HttpServer httpServer) { + this.gameServer = gameServer; + this.httpServer = httpServer; + + instance = this; + } + + /** + * Gets the server hook instance. + * + * @return A {@link ServerHook} singleton. + */ + public static ServerHook getInstance() { + return instance; + } + + /** + * @return The game server. + */ + public GameServer getGameServer() { + return this.gameServer; + } + + /** + * @return The HTTP server. + */ + public HttpServer getHttpServer() { + return this.httpServer; + } + + /** + * Gets all online players. + * + * @return Players connected to the server. + */ + @Deprecated(forRemoval = true) + public List getOnlinePlayers() { + return new ArrayList<>(this.gameServer.getPlayers().values()); + } + + /** + * Gets all online players. + * + * @return Players connected to the server. + */ + public Stream getOnlinePlayersStream() { + return this.gameServer.getPlayers().values().stream(); + } + + /** + * Registers a command to the {@link emu.grasscutter.command.CommandMap}. + * + * @param handler The command handler. + */ + public void registerCommand(CommandHandler handler) { + Class clazz = handler.getClass(); + if (!clazz.isAnnotationPresent(Command.class)) + throw new IllegalArgumentException("Command handler must be annotated with @Command."); + Command commandData = clazz.getAnnotation(Command.class); + CommandMap.getInstance().registerCommand(commandData.label(), handler); + } + + /** + * Adds a router using an instance of a class. + * + * @param router A router instance. + */ + public void addRouter(Router router) { + this.addRouter(router.getClass()); + } + + /** + * Adds a router using a class. + * + * @param router The class of the router. + */ + public void addRouter(Class router) { + this.httpServer.addRouter(router); + } + + /** + * Sets the server's authentication system. + * + * @param authSystem An instance of the authentication system. + */ + public void setAuthSystem(AuthenticationSystem authSystem) { + Grasscutter.setAuthenticationSystem(authSystem); + } + + /** + * Sets the server's permission handler. + * + * @param permHandler An instance of the permission handler. + */ + public void setPermissionHandler(PermissionHandler permHandler) { + Grasscutter.setPermissionHandler(permHandler); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/SceneIndexManager.java b/src/main/java/emu/grasscutter/scripts/SceneIndexManager.java index 1fe7e7e3c..c998fe53c 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneIndexManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneIndexManager.java @@ -1,35 +1,35 @@ -package emu.grasscutter.scripts; - -import com.github.davidmoten.rtreemulti.Entry; -import com.github.davidmoten.rtreemulti.RTree; -import com.github.davidmoten.rtreemulti.geometry.Geometry; -import com.github.davidmoten.rtreemulti.geometry.Rectangle; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.function.Function; - -public class SceneIndexManager { - - public static RTree buildIndex(int dimensions, Collection elements, Function extractor) { - RTree rtree = RTree.dimensions(dimensions).create(); - return rtree.add(elements.stream().map(e -> Entry.entry(e, extractor.apply(e))).toList()); - } - - public static List queryNeighbors(RTree tree, double[] position, int range) { - var result = new ArrayList(); - Rectangle rectangle = Rectangle.create(calRange(position, -range), calRange(position, range)); - var queryResult = tree.search(rectangle); - queryResult.forEach(q -> result.add(q.value())); - return result; - } - - private static double[] calRange(double[] position, int range) { - var newPos = position.clone(); - for (int i = 0; i < newPos.length; i++) { - newPos[i] += range; - } - return newPos; - } -} +package emu.grasscutter.scripts; + +import com.github.davidmoten.rtreemulti.Entry; +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import com.github.davidmoten.rtreemulti.geometry.Rectangle; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +public class SceneIndexManager { + + public static RTree buildIndex( + int dimensions, Collection elements, Function extractor) { + RTree rtree = RTree.dimensions(dimensions).create(); + return rtree.add(elements.stream().map(e -> Entry.entry(e, extractor.apply(e))).toList()); + } + + public static List queryNeighbors(RTree tree, double[] position, int range) { + var result = new ArrayList(); + Rectangle rectangle = Rectangle.create(calRange(position, -range), calRange(position, range)); + var queryResult = tree.search(rectangle); + queryResult.forEach(q -> result.add(q.value())); + return result; + } + + private static double[] calRange(double[] position, int range) { + var newPos = position.clone(); + for (int i = 0; i < newPos.length; i++) { + newPos[i] += range; + } + return newPos; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java index ceae96cf0..94d4bc295 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java @@ -1,528 +1,564 @@ -package emu.grasscutter.scripts; - -import com.github.davidmoten.rtreemulti.RTree; -import com.github.davidmoten.rtreemulti.geometry.Geometry; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.MonsterData; -import emu.grasscutter.data.excels.WorldLevelData; -import emu.grasscutter.game.entity.*; -import emu.grasscutter.game.props.EntityType; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.VisionTypeOuterClass; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.*; -import emu.grasscutter.scripts.service.ScriptMonsterSpawnService; -import emu.grasscutter.scripts.service.ScriptMonsterTideService; -import io.netty.util.concurrent.FastThreadLocalThread; -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.jse.CoerceJavaToLua; - -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.Collectors; - -public class SceneScriptManager { - public static final ExecutorService eventExecutor; - - static { - eventExecutor = new ThreadPoolExecutor(4, 4, - 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), - FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy()); - } - - private final Scene scene; - private final Map variables; - /** - * current triggers controlled by RefreshGroup - */ - private final Map> currentTriggers; - private final Map regions; // - private final Map sceneGroups; - /** - * blockid - loaded groupSet - */ - private final Map> loadedGroupSetPerBlock; - private SceneMeta meta; - private boolean isInit; - private ScriptMonsterTideService scriptMonsterTideService; - private final ScriptMonsterSpawnService scriptMonsterSpawnService; - - public SceneScriptManager(Scene scene) { - this.scene = scene; - this.currentTriggers = new ConcurrentHashMap<>(); - - this.regions = new ConcurrentHashMap<>(); - this.variables = new ConcurrentHashMap<>(); - this.sceneGroups = new ConcurrentHashMap<>(); - this.scriptMonsterSpawnService = new ScriptMonsterSpawnService(this); - this.loadedGroupSetPerBlock = new ConcurrentHashMap<>(); - - // TEMPORARY - if (this.getScene().getId() < 10 && !Grasscutter.getConfig().server.game.enableScriptInBigWorld) { - return; - } - - // Create - this.init(); - } - - public Scene getScene() { - return scene; - } - - public SceneConfig getConfig() { - if (!isInit) { - return null; - } - return meta.config; - } - - public Map getBlocks() { - return meta.blocks; - } - - public Map getVariables() { - return variables; - } - - public Set getTriggersByEvent(int eventId) { - return currentTriggers.computeIfAbsent(eventId, e -> new HashSet<>()); - } - - public void registerTrigger(List triggers) { - triggers.forEach(this::registerTrigger); - } - - public void registerTrigger(SceneTrigger trigger) { - getTriggersByEvent(trigger.event).add(trigger); - Grasscutter.getLogger().debug("Registered trigger {}", trigger.name); - } - - public void deregisterTrigger(List triggers) { - triggers.forEach(this::deregisterTrigger); - } - - public void deregisterTrigger(SceneTrigger trigger) { - getTriggersByEvent(trigger.event).remove(trigger); - } - - public void resetTriggers(int eventId) { - currentTriggers.put(eventId, new HashSet<>()); - } - - public void refreshGroup(SceneGroup group, int suiteIndex) { - if (group == null) { - return; - } - - var suite = group.getSuiteByIndex(suiteIndex); - if (suite == null) { - return; - } - - if (suite.sceneTriggers.size() > 0) { - for (var trigger : suite.sceneTriggers) { - resetTriggers(trigger.event); - this.currentTriggers.get(trigger.event).add(trigger); - } - } - - spawnMonstersInGroup(group, suite); - spawnGadgetsInGroup(group, suite); - } - - public EntityRegion getRegionById(int id) { - return regions.get(id); - } - - public void registerRegion(EntityRegion region) { - regions.put(region.getId(), region); - Grasscutter.getLogger().debug("Registered region {} from group {}", region.getMetaRegion().config_id, region.getGroupId()); - } - - public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite) { - suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region)) - .forEach(this::registerRegion); - } - - public synchronized void deregisterRegion(SceneRegion region) { - var instance = regions.values().stream() - .filter(r -> r.getConfigId() == region.config_id) - .findFirst(); - instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId())); - } - - public Map> getLoadedGroupSetPerBlock() { - return loadedGroupSetPerBlock; - } - - // TODO optimize - public SceneGroup getGroupById(int groupId) { - for (SceneBlock block : this.getScene().getLoadedBlocks()) { - var group = block.groups.get(groupId); - if (group == null) { - continue; - } - - if (!group.isLoaded()) { - getScene().onLoadGroup(List.of(group)); - } - return group; - } - return null; - } - - private void init() { - var meta = ScriptLoader.getSceneMeta(getScene().getId()); - if (meta == null) { - return; - } - this.meta = meta; - - // TEMP - this.isInit = true; - } - - public boolean isInit() { - return isInit; - } - - public void loadBlockFromScript(SceneBlock block) { - block.load(scene.getId(), meta.context); - } - - public void loadGroupFromScript(SceneGroup group) { - group.load(getScene().getId()); - - if (group.variables != null) { - group.variables.forEach(var -> this.getVariables().put(var.name, var.value)); - } - - this.sceneGroups.put(group.id, group); - } - - public void checkRegions() { - if (this.regions.size() == 0) { - return; - } - - for (var region : this.regions.values()) { - // currently all condition_ENTER_REGION Events check for avatar, so we have no necessary to add other types of entity - getScene().getEntities().values() - .stream() - .filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition())) - .forEach(region::addEntity); - - var players = region.getScene().getPlayers(); - int targetID = 0; - if (players.size() > 0) - targetID = players.get(0).getUid(); - - if (region.hasNewEntities()) { - Grasscutter.getLogger().trace("Call EVENT_ENTER_REGION_{}", region.getMetaRegion().config_id); - callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId()) - .setSourceEntityId(region.getId()) - .setTargetEntityId(targetID) - ); - - region.resetNewEntities(); - } - - for (int entityId : region.getEntities()) { - if (getScene().getEntityById(entityId) == null || !region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) { - region.removeEntity(entityId); - - } - } - if (region.entityLeave()) { - callEvent(EventType.EVENT_LEAVE_REGION, new ScriptArgs(region.getConfigId()) - .setSourceEntityId(region.getId()) - .setTargetEntityId(region.getFirstEntityId()) - ); - - region.resetNewEntities(); - } - } - } - - public List getGadgetsInGroupSuite(SceneGroup group, SceneSuite suite) { - return suite.sceneGadgets.stream() - .map(g -> createGadget(group.id, group.block_id, g)) - .filter(Objects::nonNull) - .toList(); - } - - public List getMonstersInGroupSuite(SceneGroup group, SceneSuite suite) { - return suite.sceneMonsters.stream() - .map(mob -> createMonster(group.id, group.block_id, mob)) - .filter(Objects::nonNull) - .toList(); - } - - public void addGroupSuite(SceneGroup group, SceneSuite suite) { - // we added trigger first - registerTrigger(suite.sceneTriggers); - - var toCreate = new ArrayList(); - toCreate.addAll(getGadgetsInGroupSuite(group, suite)); - toCreate.addAll(getMonstersInGroupSuite(group, suite)); - addEntities(toCreate); - - registerRegionInGroupSuite(group, suite); - } - - public void removeGroupSuite(SceneGroup group, SceneSuite suite) { - deregisterTrigger(suite.sceneTriggers); - removeMonstersInGroup(group, suite); - removeGadgetsInGroup(group, suite); - - suite.sceneRegions.forEach(this::deregisterRegion); - } - - public void spawnGadgetsInGroup(SceneGroup group, SceneSuite suite) { - var gadgets = group.gadgets.values(); - - if (suite != null) { - gadgets = suite.sceneGadgets; - } - - var toCreate = gadgets.stream() - .map(g -> createGadget(g.group.id, group.block_id, g)) - .filter(Objects::nonNull) - .toList(); - this.addEntities(toCreate); - } - - public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { - if (suite == null || suite.sceneMonsters.size() <= 0) { - return; - } - this.addEntities(suite.sceneMonsters.stream() - .map(mob -> createMonster(group.id, group.block_id, mob)).toList()); - } - - public void startMonsterTideInGroup(SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) { - this.scriptMonsterTideService = - new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId); - - } - - public void unloadCurrentMonsterTide() { - if (this.getScriptMonsterTideService() == null) { - return; - } - this.getScriptMonsterTideService().unload(); - } - - public void spawnMonstersByConfigId(SceneGroup group, int configId, int delayTime) { - // TODO delay - getScene().addEntity(createMonster(group.id, group.block_id, group.monsters.get(configId))); - } - - // Events - public void callEvent(int eventType, ScriptArgs params) { - /** - * We use ThreadLocal to trans SceneScriptManager context to ScriptLib, to avoid eval script for every groups' trigger in every scene instances. - * But when callEvent is called in a ScriptLib func, it may cause NPE because the inner call cleans the ThreadLocal so that outer call could not get it. - * e.g. CallEvent -> set -> ScriptLib.xxx -> CallEvent -> set -> remove -> NPE -> (remove) - * So we use thread pool to clean the stack to avoid this new issue. - */ - eventExecutor.submit(() -> this.realCallEvent(eventType, params)); - } - - private void realCallEvent(int eventType, ScriptArgs params) { - try { - ScriptLoader.getScriptLib().setSceneScriptManager(this); - Set relevantTriggers = new HashSet<>(); - if (eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) { - List relevantTriggersList = this.getTriggersByEvent(eventType).stream() - .filter(p -> p.condition.contains(String.valueOf(params.param1))).toList(); - relevantTriggers = new HashSet<>(relevantTriggersList); - } else { - relevantTriggers = this.getTriggersByEvent(eventType); - } - for (SceneTrigger trigger : relevantTriggers) { - try { - ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup); - LuaValue ret = this.callScriptFunc(trigger.condition, trigger.currentGroup, params); - Grasscutter.getLogger().trace("Call Condition Trigger {}, [{},{},{}]", trigger.condition, params.param1, params.source_eid, params.target_eid); - if (ret.isboolean() && ret.checkboolean()) { - // the SetGroupVariableValueByGroup in tower need the param to record the first stage time - this.callScriptFunc(trigger.action, trigger.currentGroup, params); - Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action); - if (trigger.event == EventType.EVENT_ENTER_REGION) { - EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0); - getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion())); - deregisterRegion(region.getMetaRegion()); - } else if (trigger.event == EventType.EVENT_LEAVE_REGION) { - EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0); - getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion())); - deregisterRegion(region.getMetaRegion()); - } - deregisterTrigger(trigger); - } else { - Grasscutter.getLogger().debug("Condition Trigger {} returned {}", trigger.condition, ret); - } - //TODO some ret do not bool - } finally { - ScriptLoader.getScriptLib().removeCurrentGroup(); - } - } - } finally { - // make sure it is removed - ScriptLoader.getScriptLib().removeSceneScriptManager(); - } - } - - private LuaValue callScriptFunc(String funcName, SceneGroup group, ScriptArgs params) { - LuaValue funcLua = null; - if (funcName != null && !funcName.isEmpty()) { - funcLua = (LuaValue) group.getBindings().get(funcName); - } - - LuaValue ret = LuaValue.TRUE; - - if (funcLua != null) { - LuaValue args = LuaValue.NIL; - - if (params != null) { - args = CoerceJavaToLua.coerce(params); - } - - ret = safetyCall(funcName, funcLua, args); - } - return ret; - } - - public LuaValue safetyCall(String name, LuaValue func, LuaValue args) { - try { - return func.call(ScriptLoader.getScriptLibLua(), args); - } catch (LuaError error) { - ScriptLib.logger.error("[LUA] call trigger failed {},{}", name, args, error); - return LuaValue.valueOf(-1); - } - } - - public ScriptMonsterTideService getScriptMonsterTideService() { - return scriptMonsterTideService; - } - - public ScriptMonsterSpawnService getScriptMonsterSpawnService() { - return scriptMonsterSpawnService; - } - - public EntityGadget createGadget(int groupId, int blockId, SceneGadget g) { - if (g.isOneoff) { - var hasEntity = getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityGadget) - .filter(e -> e.getGroupId() == g.group.id) - .filter(e -> e.getConfigId() == g.config_id) - .findFirst(); - if (hasEntity.isPresent()) { - return null; - } - } - EntityGadget entity = new EntityGadget(getScene(), g.gadget_id, g.pos); - - if (entity.getGadgetData() == null) { - return null; - } - - entity.setBlockId(blockId); - entity.setConfigId(g.config_id); - entity.setGroupId(groupId); - entity.getRotation().set(g.rot); - entity.setState(g.state); - entity.setPointType(g.point_type); - entity.setMetaGadget(g); - entity.buildContent(); - - return entity; - } - - public EntityNPC createNPC(SceneNPC npc, int blockId, int suiteId) { - return new EntityNPC(getScene(), npc, blockId, suiteId); - } - - public EntityMonster createMonster(int groupId, int blockId, SceneMonster monster) { - if (monster == null) { - return null; - } - - MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); - - if (data == null) { - return null; - } - - // Calculate level - int level = monster.level; - - if (getScene().getDungeonData() != null) { - level = getScene().getDungeonData().getShowLevel(); - } else if (getScene().getWorld().getWorldLevel() > 0) { - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); - - if (worldLevelData != null) { - level = worldLevelData.getMonsterLevel(); - } - } - - // Spawn mob - EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level); - entity.getRotation().set(monster.rot); - entity.setGroupId(groupId); - entity.setBlockId(blockId); - entity.setConfigId(monster.config_id); - entity.setPoseId(monster.pose_id); - - this.getScriptMonsterSpawnService() - .onMonsterCreatedListener.forEach(action -> action.onNotify(entity)); - - return entity; - } - - public void addEntity(GameEntity gameEntity) { - getScene().addEntity(gameEntity); - } - - public void meetEntities(List gameEntity) { - getScene().addEntities(gameEntity, VisionTypeOuterClass.VisionType.VISION_TYPE_MEET); - } - - public void addEntities(List gameEntity) { - getScene().addEntities(gameEntity); - } - - public RTree getBlocksIndex() { - return meta.sceneBlockIndex; - } - - public void removeMonstersInGroup(SceneGroup group, SceneSuite suite) { - var configSet = suite.sceneMonsters.stream() - .map(m -> m.config_id) - .collect(Collectors.toSet()); - var toRemove = getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityMonster) - .filter(e -> e.getGroupId() == group.id) - .filter(e -> configSet.contains(e.getConfigId())) - .toList(); - - getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS); - } - - public void removeGadgetsInGroup(SceneGroup group, SceneSuite suite) { - var configSet = suite.sceneGadgets.stream() - .map(m -> m.config_id) - .collect(Collectors.toSet()); - var toRemove = getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityGadget) - .filter(e -> e.getGroupId() == group.id) - .filter(e -> configSet.contains(e.getConfigId())) - .toList(); - - getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS); - } -} +package emu.grasscutter.scripts; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.WorldLevelData; +import emu.grasscutter.game.entity.*; +import emu.grasscutter.game.props.EntityType; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.VisionTypeOuterClass; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.*; +import emu.grasscutter.scripts.service.ScriptMonsterSpawnService; +import emu.grasscutter.scripts.service.ScriptMonsterTideService; +import io.netty.util.concurrent.FastThreadLocalThread; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jse.CoerceJavaToLua; + +public class SceneScriptManager { + public static final ExecutorService eventExecutor; + + static { + eventExecutor = + new ThreadPoolExecutor( + 4, + 4, + 60, + TimeUnit.SECONDS, + new LinkedBlockingDeque<>(1000), + FastThreadLocalThread::new, + new ThreadPoolExecutor.AbortPolicy()); + } + + private final Scene scene; + private final Map variables; + /** current triggers controlled by RefreshGroup */ + private final Map> currentTriggers; + + private final Map regions; // + private final Map sceneGroups; + /** blockid - loaded groupSet */ + private final Map> loadedGroupSetPerBlock; + + private SceneMeta meta; + private boolean isInit; + private ScriptMonsterTideService scriptMonsterTideService; + private final ScriptMonsterSpawnService scriptMonsterSpawnService; + + public SceneScriptManager(Scene scene) { + this.scene = scene; + this.currentTriggers = new ConcurrentHashMap<>(); + + this.regions = new ConcurrentHashMap<>(); + this.variables = new ConcurrentHashMap<>(); + this.sceneGroups = new ConcurrentHashMap<>(); + this.scriptMonsterSpawnService = new ScriptMonsterSpawnService(this); + this.loadedGroupSetPerBlock = new ConcurrentHashMap<>(); + + // TEMPORARY + if (this.getScene().getId() < 10 + && !Grasscutter.getConfig().server.game.enableScriptInBigWorld) { + return; + } + + // Create + this.init(); + } + + public Scene getScene() { + return scene; + } + + public SceneConfig getConfig() { + if (!isInit) { + return null; + } + return meta.config; + } + + public Map getBlocks() { + return meta.blocks; + } + + public Map getVariables() { + return variables; + } + + public Set getTriggersByEvent(int eventId) { + return currentTriggers.computeIfAbsent(eventId, e -> new HashSet<>()); + } + + public void registerTrigger(List triggers) { + triggers.forEach(this::registerTrigger); + } + + public void registerTrigger(SceneTrigger trigger) { + getTriggersByEvent(trigger.event).add(trigger); + Grasscutter.getLogger().debug("Registered trigger {}", trigger.name); + } + + public void deregisterTrigger(List triggers) { + triggers.forEach(this::deregisterTrigger); + } + + public void deregisterTrigger(SceneTrigger trigger) { + getTriggersByEvent(trigger.event).remove(trigger); + } + + public void resetTriggers(int eventId) { + currentTriggers.put(eventId, new HashSet<>()); + } + + public void refreshGroup(SceneGroup group, int suiteIndex) { + if (group == null) { + return; + } + + var suite = group.getSuiteByIndex(suiteIndex); + if (suite == null) { + return; + } + + if (suite.sceneTriggers.size() > 0) { + for (var trigger : suite.sceneTriggers) { + resetTriggers(trigger.event); + this.currentTriggers.get(trigger.event).add(trigger); + } + } + + spawnMonstersInGroup(group, suite); + spawnGadgetsInGroup(group, suite); + } + + public EntityRegion getRegionById(int id) { + return regions.get(id); + } + + public void registerRegion(EntityRegion region) { + regions.put(region.getId(), region); + Grasscutter.getLogger() + .debug( + "Registered region {} from group {}", + region.getMetaRegion().config_id, + region.getGroupId()); + } + + public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite) { + suite.sceneRegions.stream() + .map(region -> new EntityRegion(this.getScene(), region)) + .forEach(this::registerRegion); + } + + public synchronized void deregisterRegion(SceneRegion region) { + var instance = + regions.values().stream().filter(r -> r.getConfigId() == region.config_id).findFirst(); + instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId())); + } + + public Map> getLoadedGroupSetPerBlock() { + return loadedGroupSetPerBlock; + } + + // TODO optimize + public SceneGroup getGroupById(int groupId) { + for (SceneBlock block : this.getScene().getLoadedBlocks()) { + var group = block.groups.get(groupId); + if (group == null) { + continue; + } + + if (!group.isLoaded()) { + getScene().onLoadGroup(List.of(group)); + } + return group; + } + return null; + } + + private void init() { + var meta = ScriptLoader.getSceneMeta(getScene().getId()); + if (meta == null) { + return; + } + this.meta = meta; + + // TEMP + this.isInit = true; + } + + public boolean isInit() { + return isInit; + } + + public void loadBlockFromScript(SceneBlock block) { + block.load(scene.getId(), meta.context); + } + + public void loadGroupFromScript(SceneGroup group) { + group.load(getScene().getId()); + + if (group.variables != null) { + group.variables.forEach(var -> this.getVariables().put(var.name, var.value)); + } + + this.sceneGroups.put(group.id, group); + } + + public void checkRegions() { + if (this.regions.size() == 0) { + return; + } + + for (var region : this.regions.values()) { + // currently all condition_ENTER_REGION Events check for avatar, so we have no necessary to + // add other types of entity + getScene().getEntities().values().stream() + .filter( + e -> + e.getEntityType() == EntityType.Avatar.getValue() + && region.getMetaRegion().contains(e.getPosition())) + .forEach(region::addEntity); + + var players = region.getScene().getPlayers(); + int targetID = 0; + if (players.size() > 0) targetID = players.get(0).getUid(); + + if (region.hasNewEntities()) { + Grasscutter.getLogger() + .trace("Call EVENT_ENTER_REGION_{}", region.getMetaRegion().config_id); + callEvent( + EventType.EVENT_ENTER_REGION, + new ScriptArgs(region.getConfigId()) + .setSourceEntityId(region.getId()) + .setTargetEntityId(targetID)); + + region.resetNewEntities(); + } + + for (int entityId : region.getEntities()) { + if (getScene().getEntityById(entityId) == null + || !region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) { + region.removeEntity(entityId); + } + } + if (region.entityLeave()) { + callEvent( + EventType.EVENT_LEAVE_REGION, + new ScriptArgs(region.getConfigId()) + .setSourceEntityId(region.getId()) + .setTargetEntityId(region.getFirstEntityId())); + + region.resetNewEntities(); + } + } + } + + public List getGadgetsInGroupSuite(SceneGroup group, SceneSuite suite) { + return suite.sceneGadgets.stream() + .map(g -> createGadget(group.id, group.block_id, g)) + .filter(Objects::nonNull) + .toList(); + } + + public List getMonstersInGroupSuite(SceneGroup group, SceneSuite suite) { + return suite.sceneMonsters.stream() + .map(mob -> createMonster(group.id, group.block_id, mob)) + .filter(Objects::nonNull) + .toList(); + } + + public void addGroupSuite(SceneGroup group, SceneSuite suite) { + // we added trigger first + registerTrigger(suite.sceneTriggers); + + var toCreate = new ArrayList(); + toCreate.addAll(getGadgetsInGroupSuite(group, suite)); + toCreate.addAll(getMonstersInGroupSuite(group, suite)); + addEntities(toCreate); + + registerRegionInGroupSuite(group, suite); + } + + public void removeGroupSuite(SceneGroup group, SceneSuite suite) { + deregisterTrigger(suite.sceneTriggers); + removeMonstersInGroup(group, suite); + removeGadgetsInGroup(group, suite); + + suite.sceneRegions.forEach(this::deregisterRegion); + } + + public void spawnGadgetsInGroup(SceneGroup group, SceneSuite suite) { + var gadgets = group.gadgets.values(); + + if (suite != null) { + gadgets = suite.sceneGadgets; + } + + var toCreate = + gadgets.stream() + .map(g -> createGadget(g.group.id, group.block_id, g)) + .filter(Objects::nonNull) + .toList(); + this.addEntities(toCreate); + } + + public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { + if (suite == null || suite.sceneMonsters.size() <= 0) { + return; + } + this.addEntities( + suite.sceneMonsters.stream() + .map(mob -> createMonster(group.id, group.block_id, mob)) + .toList()); + } + + public void startMonsterTideInGroup( + SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) { + this.scriptMonsterTideService = + new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId); + } + + public void unloadCurrentMonsterTide() { + if (this.getScriptMonsterTideService() == null) { + return; + } + this.getScriptMonsterTideService().unload(); + } + + public void spawnMonstersByConfigId(SceneGroup group, int configId, int delayTime) { + // TODO delay + getScene().addEntity(createMonster(group.id, group.block_id, group.monsters.get(configId))); + } + + // Events + public void callEvent(int eventType, ScriptArgs params) { + /** + * We use ThreadLocal to trans SceneScriptManager context to ScriptLib, to avoid eval script for + * every groups' trigger in every scene instances. But when callEvent is called in a ScriptLib + * func, it may cause NPE because the inner call cleans the ThreadLocal so that outer call could + * not get it. e.g. CallEvent -> set -> ScriptLib.xxx -> CallEvent -> set -> remove -> NPE -> + * (remove) So we use thread pool to clean the stack to avoid this new issue. + */ + eventExecutor.submit(() -> this.realCallEvent(eventType, params)); + } + + private void realCallEvent(int eventType, ScriptArgs params) { + try { + ScriptLoader.getScriptLib().setSceneScriptManager(this); + Set relevantTriggers = new HashSet<>(); + if (eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) { + List relevantTriggersList = + this.getTriggersByEvent(eventType).stream() + .filter(p -> p.condition.contains(String.valueOf(params.param1))) + .toList(); + relevantTriggers = new HashSet<>(relevantTriggersList); + } else { + relevantTriggers = this.getTriggersByEvent(eventType); + } + for (SceneTrigger trigger : relevantTriggers) { + try { + ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup); + LuaValue ret = this.callScriptFunc(trigger.condition, trigger.currentGroup, params); + Grasscutter.getLogger() + .trace( + "Call Condition Trigger {}, [{},{},{}]", + trigger.condition, + params.param1, + params.source_eid, + params.target_eid); + if (ret.isboolean() && ret.checkboolean()) { + // the SetGroupVariableValueByGroup in tower need the param to record the first stage + // time + this.callScriptFunc(trigger.action, trigger.currentGroup, params); + Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action); + if (trigger.event == EventType.EVENT_ENTER_REGION) { + EntityRegion region = + this.regions.values().stream() + .filter(p -> p.getConfigId() == params.param1) + .toList() + .get(0); + getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion())); + deregisterRegion(region.getMetaRegion()); + } else if (trigger.event == EventType.EVENT_LEAVE_REGION) { + EntityRegion region = + this.regions.values().stream() + .filter(p -> p.getConfigId() == params.param1) + .toList() + .get(0); + getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion())); + deregisterRegion(region.getMetaRegion()); + } + deregisterTrigger(trigger); + } else { + Grasscutter.getLogger() + .debug("Condition Trigger {} returned {}", trigger.condition, ret); + } + // TODO some ret do not bool + } finally { + ScriptLoader.getScriptLib().removeCurrentGroup(); + } + } + } finally { + // make sure it is removed + ScriptLoader.getScriptLib().removeSceneScriptManager(); + } + } + + private LuaValue callScriptFunc(String funcName, SceneGroup group, ScriptArgs params) { + LuaValue funcLua = null; + if (funcName != null && !funcName.isEmpty()) { + funcLua = (LuaValue) group.getBindings().get(funcName); + } + + LuaValue ret = LuaValue.TRUE; + + if (funcLua != null) { + LuaValue args = LuaValue.NIL; + + if (params != null) { + args = CoerceJavaToLua.coerce(params); + } + + ret = safetyCall(funcName, funcLua, args); + } + return ret; + } + + public LuaValue safetyCall(String name, LuaValue func, LuaValue args) { + try { + return func.call(ScriptLoader.getScriptLibLua(), args); + } catch (LuaError error) { + ScriptLib.logger.error("[LUA] call trigger failed {},{}", name, args, error); + return LuaValue.valueOf(-1); + } + } + + public ScriptMonsterTideService getScriptMonsterTideService() { + return scriptMonsterTideService; + } + + public ScriptMonsterSpawnService getScriptMonsterSpawnService() { + return scriptMonsterSpawnService; + } + + public EntityGadget createGadget(int groupId, int blockId, SceneGadget g) { + if (g.isOneoff) { + var hasEntity = + getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityGadget) + .filter(e -> e.getGroupId() == g.group.id) + .filter(e -> e.getConfigId() == g.config_id) + .findFirst(); + if (hasEntity.isPresent()) { + return null; + } + } + EntityGadget entity = new EntityGadget(getScene(), g.gadget_id, g.pos); + + if (entity.getGadgetData() == null) { + return null; + } + + entity.setBlockId(blockId); + entity.setConfigId(g.config_id); + entity.setGroupId(groupId); + entity.getRotation().set(g.rot); + entity.setState(g.state); + entity.setPointType(g.point_type); + entity.setMetaGadget(g); + entity.buildContent(); + + return entity; + } + + public EntityNPC createNPC(SceneNPC npc, int blockId, int suiteId) { + return new EntityNPC(getScene(), npc, blockId, suiteId); + } + + public EntityMonster createMonster(int groupId, int blockId, SceneMonster monster) { + if (monster == null) { + return null; + } + + MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); + + if (data == null) { + return null; + } + + // Calculate level + int level = monster.level; + + if (getScene().getDungeonData() != null) { + level = getScene().getDungeonData().getShowLevel(); + } else if (getScene().getWorld().getWorldLevel() > 0) { + WorldLevelData worldLevelData = + GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); + + if (worldLevelData != null) { + level = worldLevelData.getMonsterLevel(); + } + } + + // Spawn mob + EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level); + entity.getRotation().set(monster.rot); + entity.setGroupId(groupId); + entity.setBlockId(blockId); + entity.setConfigId(monster.config_id); + entity.setPoseId(monster.pose_id); + + this.getScriptMonsterSpawnService() + .onMonsterCreatedListener + .forEach(action -> action.onNotify(entity)); + + return entity; + } + + public void addEntity(GameEntity gameEntity) { + getScene().addEntity(gameEntity); + } + + public void meetEntities(List gameEntity) { + getScene().addEntities(gameEntity, VisionTypeOuterClass.VisionType.VISION_TYPE_MEET); + } + + public void addEntities(List gameEntity) { + getScene().addEntities(gameEntity); + } + + public RTree getBlocksIndex() { + return meta.sceneBlockIndex; + } + + public void removeMonstersInGroup(SceneGroup group, SceneSuite suite) { + var configSet = suite.sceneMonsters.stream().map(m -> m.config_id).collect(Collectors.toSet()); + var toRemove = + getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityMonster) + .filter(e -> e.getGroupId() == group.id) + .filter(e -> configSet.contains(e.getConfigId())) + .toList(); + + getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS); + } + + public void removeGadgetsInGroup(SceneGroup group, SceneSuite suite) { + var configSet = suite.sceneGadgets.stream().map(m -> m.config_id).collect(Collectors.toSet()); + var toRemove = + getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityGadget) + .filter(e -> e.getGroupId() == group.id) + .filter(e -> configSet.contains(e.getConfigId())) + .toList(); + + getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 964890104..58be1a38b 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1,577 +1,597 @@ -package emu.grasscutter.scripts; - -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; -import emu.grasscutter.game.dungeons.challenge.factory.ChallengeFactory; -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.entity.gadget.GadgetWorktop; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.EntityType; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; -import emu.grasscutter.server.packet.send.PacketDungeonShowReminderNotify; -import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify; -import io.netty.util.concurrent.FastThreadLocal; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; - -public class ScriptLib { - public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class); - private final FastThreadLocal sceneScriptManager; - private final FastThreadLocal currentGroup; - - public ScriptLib() { - this.sceneScriptManager = new FastThreadLocal<>(); - this.currentGroup = new FastThreadLocal<>(); - } - - public void removeSceneScriptManager() { - this.sceneScriptManager.remove(); - } - - public SceneScriptManager getSceneScriptManager() { - // normally not null - return Optional.of(sceneScriptManager.get()).get(); - } - - public void setSceneScriptManager(SceneScriptManager sceneScriptManager) { - this.sceneScriptManager.set(sceneScriptManager); - } - - private String printTable(LuaTable table) { - StringBuilder sb = new StringBuilder(); - sb.append("{"); - for (var meta : table.keys()) { - sb.append(meta).append(":").append(table.get(meta)).append(","); - } - sb.append("}"); - return sb.toString(); - } - - public Optional getCurrentGroup() { - return Optional.of(this.currentGroup.get()); - } - - public void setCurrentGroup(SceneGroup currentGroup) { - this.currentGroup.set(currentGroup); - } - - public void removeCurrentGroup() { - this.currentGroup.remove(); - } - - public int SetGadgetStateByConfigId(int configId, int gadgetState) { - logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}", - configId, gadgetState); - Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e.getConfigId() == configId).findFirst(); - - if (entity.isEmpty()) { - return 1; - } - - if (entity.get() instanceof EntityGadget entityGadget) { - entityGadget.updateState(gadgetState); - return 0; - } - - return 1; - } - - public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) { - logger.debug("[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}", - groupId, configId, gadgetState); - - getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e.getGroupId() == groupId) - .filter(e -> e instanceof EntityGadget) - .map(e -> (EntityGadget) e) - .forEach(e -> e.updateState(gadgetState)); - - return 0; - } - - public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) { - logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}", - groupId, configId, options); - - Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); - - - if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) { - return 1; - } - - if (!(gadget.getContent() instanceof GadgetWorktop worktop)) { - return 1; - } - - worktop.addWorktopOptions(options); - getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget)); - - return 0; - } - - public int SetWorktopOptions(LuaTable table) { - logger.debug("[LUA] Call SetWorktopOptions with {}", printTable(table)); - // TODO - return 0; - } - - public int DelWorktopOptionByGroupId(int groupId, int configId, int option) { - logger.debug("[LUA] Call DelWorktopOptionByGroupId with {},{},{}", groupId, configId, option); - - Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); - - if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) { - return 1; - } - - if (!(gadget.getContent() instanceof GadgetWorktop worktop)) { - return 1; - } - - worktop.removeWorktopOption(option); - getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget)); - - return 0; - } - - // Some fields are guessed - public int AutoMonsterTide(int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6) { - logger.debug("[LUA] Call AutoMonsterTide with {},{},{},{},{},{}", - challengeIndex, groupId, ordersConfigId, tideCount, sceneLimit, param6); - - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - - if (group == null || group.monsters == null) { - return 1; - } - - this.getSceneScriptManager().startMonsterTideInGroup(group, ordersConfigId, tideCount, sceneLimit); - - return 0; - } - - public int AddExtraGroupSuite(int groupId, int suite) { - logger.debug("[LUA] Call AddExtraGroupSuite with {},{}", - groupId, suite); - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - - if (group == null || group.monsters == null) { - return 1; - } - var suiteData = group.getSuiteByIndex(suite); - if (suiteData == null) { - return 1; - } - // avoid spawn wrong monster - if (getSceneScriptManager().getScene().getChallenge() != null) - if (!getSceneScriptManager().getScene().getChallenge().inProgress() || - getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId) { - return 0; - } - this.getSceneScriptManager().addGroupSuite(group, suiteData); - - return 0; - } - - public int GoToGroupSuite(int groupId, int suite) { - logger.debug("[LUA] Call GoToGroupSuite with {},{}", - groupId, suite); - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - if (group == null || group.monsters == null) { - return 1; - } - var suiteData = group.getSuiteByIndex(suite); - if (suiteData == null) { - return 1; - } - - for (var suiteItem : group.suites) { - if (suiteData == suiteItem) { - continue; - } - this.getSceneScriptManager().removeGroupSuite(group, suiteItem); - } - this.getSceneScriptManager().addGroupSuite(group, suiteData); - - return 0; - } - - public int RemoveExtraGroupSuite(int groupId, int suite) { - logger.debug("[LUA] Call RemoveExtraGroupSuite with {},{}", - groupId, suite); - - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - if (group == null || group.monsters == null) { - return 1; - } - var suiteData = group.getSuiteByIndex(suite); - if (suiteData == null) { - return 1; - } - - this.getSceneScriptManager().removeGroupSuite(group, suiteData); - - return 0; - } - - public int KillExtraGroupSuite(int groupId, int suite) { - logger.debug("[LUA] Call KillExtraGroupSuite with {},{}", - groupId, suite); - - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - if (group == null || group.monsters == null) { - return 1; - } - var suiteData = group.getSuiteByIndex(suite); - if (suiteData == null) { - return 1; - } - - this.getSceneScriptManager().removeGroupSuite(group, suiteData); - - return 0; - } - - // param3 (probably time limit for timed dungeons) - public int ActiveChallenge(int challengeId, int challengeIndex, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5) { - logger.debug("[LUA] Call ActiveChallenge with {},{},{},{},{},{}", - challengeId, challengeIndex, timeLimitOrGroupId, groupId, objectiveKills, param5); - - var challenge = ChallengeFactory.getChallenge( - challengeId, - challengeIndex, - timeLimitOrGroupId, - groupId, - objectiveKills, - param5, - getSceneScriptManager().getScene(), - getCurrentGroup().get() - ); - - if (challenge == null) { - return 1; - } - - if (challenge instanceof DungeonChallenge dungeonChallenge) { - // set if tower first stage (6-1) - dungeonChallenge.setStage(getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0); - } - - getSceneScriptManager().getScene().setChallenge(challenge); - challenge.start(); - return 0; - } - - public int GetGroupMonsterCountByGroupId(int groupId) { - logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}", - groupId); - return (int) getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId) - .count(); - } - - public int GetGroupVariableValue(String var) { - logger.debug("[LUA] Call GetGroupVariableValue with {}", - var); - return getSceneScriptManager().getVariables().getOrDefault(var, 0); - } - - public int SetGroupVariableValue(String var, int value) { - logger.debug("[LUA] Call SetGroupVariableValue with {},{}", - var, value); - getSceneScriptManager().getVariables().put(var, value); - return 0; - } - - public LuaValue ChangeGroupVariableValue(String var, int value) { - logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}", - var, value); - - getSceneScriptManager().getVariables().put(var, getSceneScriptManager().getVariables().get(var) + value); - return LuaValue.ZERO; - } - - /** - * Set the actions and triggers to designated group - */ - public int RefreshGroup(LuaTable table) { - logger.debug("[LUA] Call RefreshGroup with {}", - printTable(table)); - // Kill and Respawn? - int groupId = table.get("group_id").toint(); - int suite = table.get("suite").toint(); - - SceneGroup group = getSceneScriptManager().getGroupById(groupId); - - if (group == null || group.monsters == null) { - return 1; - } - - getSceneScriptManager().refreshGroup(group, suite); - - return 0; - } - - public int GetRegionEntityCount(LuaTable table) { - logger.debug("[LUA] Call GetRegionEntityCount with {}", - printTable(table)); - int regionId = table.get("region_eid").toint(); - int entityType = table.get("entity_type").toint(); - - var region = this.getSceneScriptManager().getRegionById(regionId); - - if (region == null) { - return 0; - } - - return (int) region.getEntities().stream().filter(e -> e >> 24 == entityType).count(); - } - - public void PrintContextLog(String msg) { - logger.info("[LUA] " + msg); - } - - public int TowerCountTimeStatus(int isDone, int var2) { - logger.debug("[LUA] Call TowerCountTimeStatus with {},{}", - isDone, var2); - // TODO record time - return 0; - } - - public int GetGroupMonsterCount() { - logger.debug("[LUA] Call GetGroupMonsterCount "); - - return (int) getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityMonster && - e.getGroupId() == getCurrentGroup().map(sceneGroup -> sceneGroup.id).orElse(-1)) - .count(); - } - - public int SetMonsterBattleByGroup(int var1, int var2, int var3) { - logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}", - var1, var2, var3); - // TODO - return 0; - } - - public int CauseDungeonFail(int var1) { - logger.debug("[LUA] Call CauseDungeonFail with {}", - var1); - - return 0; - } - - public int GetGroupVariableValueByGroup(String name, int groupId) { - logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}", - name, groupId); - - return getSceneScriptManager().getVariables().getOrDefault(name, 0); - } - - public int SetIsAllowUseSkill(int canUse, int var2) { - logger.debug("[LUA] Call SetIsAllowUseSkill with {},{}", - canUse, var2); - - getSceneScriptManager().getScene().broadcastPacket(new PacketCanUseSkillNotify(canUse == 1)); - return 0; - } - - public int KillEntityByConfigId(LuaTable table) { - logger.debug("[LUA] Call KillEntityByConfigId with {}", - printTable(table)); - var configId = table.get("config_id"); - if (configId == LuaValue.NIL) { - return 1; - } - - var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint()); - if (entity == null) { - return 0; - } - getSceneScriptManager().getScene().killEntity(entity, 0); - return 0; - } - - public int SetGroupVariableValueByGroup(String key, int value, int groupId) { - logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}", - key, value, groupId); - - getSceneScriptManager().getVariables().put(key, value); - return 0; - } - - public int CreateMonster(LuaTable table) { - logger.debug("[LUA] Call CreateMonster with {}", - printTable(table)); - var configId = table.get("config_id").toint(); - var delayTime = table.get("delay_time").toint(); - - if (getCurrentGroup().isEmpty()) { - return 1; - } - - getSceneScriptManager().spawnMonstersByConfigId(getCurrentGroup().get(), configId, delayTime); - return 0; - } - - public int TowerMirrorTeamSetUp(int team, int var1) { - logger.debug("[LUA] Call TowerMirrorTeamSetUp with {},{}", - team, var1); - - getSceneScriptManager().unloadCurrentMonsterTide(); - getSceneScriptManager().getScene().getPlayers().get(0).getTowerManager().mirrorTeamSetUp(team - 1); - - return 0; - } - - public int CreateGadget(LuaTable table) { - logger.debug("[LUA] Call CreateGadget with {}", - printTable(table)); - var configId = table.get("config_id").toint(); - - var group = getCurrentGroup(); - - if (group.isEmpty()) { - return 1; - } - - var gadget = group.get().gadgets.get(configId); - var entity = getSceneScriptManager().createGadget(group.get().id, group.get().block_id, gadget); - - getSceneScriptManager().addEntity(entity); - - return 0; - } - - public int CheckRemainGadgetCountByGroupId(LuaTable table) { - logger.debug("[LUA] Call CheckRemainGadgetCountByGroupId with {}", - printTable(table)); - var groupId = table.get("group_id").toint(); - - var count = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == groupId) - .count(); - return (int) count; - } - - public int GetGadgetStateByConfigId(int groupId, int configId) { - logger.debug("[LUA] Call GetGadgetStateByConfigId with {},{}", - groupId, configId); - - if (groupId == 0) { - groupId = getCurrentGroup().get().id; - } - final int realGroupId = groupId; - var gadget = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == realGroupId) - .filter(g -> g.getConfigId() == configId) - .findFirst(); - if (gadget.isEmpty()) { - return 1; - } - return ((EntityGadget) gadget.get()).getState(); - } - - public int MarkPlayerAction(int var1, int var2, int var3, int var4) { - logger.debug("[LUA] Call MarkPlayerAction with {},{},{},{}", - var1, var2, var3, var4); - - return 0; - } - - public int AddQuestProgress(String var1) { - logger.debug("[LUA] Call AddQuestProgress with {}", - var1); - - for (var player : getSceneScriptManager().getScene().getPlayers()) { - player.getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_LUA_NOTIFY, var1); - player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY, var1); - } - - return 0; - } - - /** - * change the state of gadget - */ - public int ChangeGroupGadget(LuaTable table) { - logger.debug("[LUA] Call ChangeGroupGadget with {}", - printTable(table)); - var configId = table.get("config_id").toint(); - var state = table.get("state").toint(); - - var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId); - if (entity == null) { - return 1; - } - - if (entity instanceof EntityGadget entityGadget) { - entityGadget.updateState(state); - return 0; - } - - return 1; - } - - public int GetEntityType(int entityId) { - var entity = getSceneScriptManager().getScene().getEntityById(entityId); - if (entity == null) { - // check players - Player player = DatabaseHelper.getPlayerByUid(entityId); - if (player != null) { - return EntityType.Avatar.getValue(); - } - - return EntityType.None.getValue(); - } - - return entity.getEntityType(); - } - - public int GetQuestState(int entityId, int questId) { - var player = getSceneScriptManager().getScene().getWorld().getHost(); - - var quest = player.getQuestManager().getQuestById(questId); - if (quest == null) { - return QuestState.QUEST_STATE_NONE.getValue(); - } - - return quest.getState().getValue(); - } - - public int ShowReminder(int reminderId) { - getSceneScriptManager().getScene().broadcastPacket(new PacketDungeonShowReminderNotify(reminderId)); - return 0; - } - - public int RemoveEntityByConfigId(int groupId, int entityType, int configId) { - logger.debug("[LUA] Call RemoveEntityByConfigId"); - - var entity = getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e.getGroupId() == groupId) - .filter(e -> e.getEntityType() == entityType) - .filter(e -> e.getConfigId() == configId) - .findFirst(); - - if (entity.isEmpty()) { - return 1; - } - - getSceneScriptManager().getScene().removeEntity(entity.get()); - - return 0; - } -} +package emu.grasscutter.scripts; + +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; +import emu.grasscutter.game.dungeons.challenge.factory.ChallengeFactory; +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.entity.gadget.GadgetWorktop; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.EntityType; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; +import emu.grasscutter.server.packet.send.PacketDungeonShowReminderNotify; +import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify; +import io.netty.util.concurrent.FastThreadLocal; +import java.util.Optional; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ScriptLib { + public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class); + private final FastThreadLocal sceneScriptManager; + private final FastThreadLocal currentGroup; + + public ScriptLib() { + this.sceneScriptManager = new FastThreadLocal<>(); + this.currentGroup = new FastThreadLocal<>(); + } + + public void removeSceneScriptManager() { + this.sceneScriptManager.remove(); + } + + public SceneScriptManager getSceneScriptManager() { + // normally not null + return Optional.of(sceneScriptManager.get()).get(); + } + + public void setSceneScriptManager(SceneScriptManager sceneScriptManager) { + this.sceneScriptManager.set(sceneScriptManager); + } + + private String printTable(LuaTable table) { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for (var meta : table.keys()) { + sb.append(meta).append(":").append(table.get(meta)).append(","); + } + sb.append("}"); + return sb.toString(); + } + + public Optional getCurrentGroup() { + return Optional.of(this.currentGroup.get()); + } + + public void setCurrentGroup(SceneGroup currentGroup) { + this.currentGroup.set(currentGroup); + } + + public void removeCurrentGroup() { + this.currentGroup.remove(); + } + + public int SetGadgetStateByConfigId(int configId, int gadgetState) { + logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}", configId, gadgetState); + Optional entity = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e.getConfigId() == configId) + .findFirst(); + + if (entity.isEmpty()) { + return 1; + } + + if (entity.get() instanceof EntityGadget entityGadget) { + entityGadget.updateState(gadgetState); + return 0; + } + + return 1; + } + + public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) { + logger.debug( + "[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}", groupId, configId, gadgetState); + + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e.getGroupId() == groupId) + .filter(e -> e instanceof EntityGadget) + .map(e -> (EntityGadget) e) + .forEach(e -> e.updateState(gadgetState)); + + return 0; + } + + public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) { + logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}", groupId, configId, options); + + Optional entity = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId) + .findFirst(); + + if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) { + return 1; + } + + if (!(gadget.getContent() instanceof GadgetWorktop worktop)) { + return 1; + } + + worktop.addWorktopOptions(options); + getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget)); + + return 0; + } + + public int SetWorktopOptions(LuaTable table) { + logger.debug("[LUA] Call SetWorktopOptions with {}", printTable(table)); + // TODO + return 0; + } + + public int DelWorktopOptionByGroupId(int groupId, int configId, int option) { + logger.debug("[LUA] Call DelWorktopOptionByGroupId with {},{},{}", groupId, configId, option); + + Optional entity = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId) + .findFirst(); + + if (entity.isEmpty() || !(entity.get() instanceof EntityGadget gadget)) { + return 1; + } + + if (!(gadget.getContent() instanceof GadgetWorktop worktop)) { + return 1; + } + + worktop.removeWorktopOption(option); + getSceneScriptManager().getScene().broadcastPacket(new PacketWorktopOptionNotify(gadget)); + + return 0; + } + + // Some fields are guessed + public int AutoMonsterTide( + int challengeIndex, + int groupId, + Integer[] ordersConfigId, + int tideCount, + int sceneLimit, + int param6) { + logger.debug( + "[LUA] Call AutoMonsterTide with {},{},{},{},{},{}", + challengeIndex, + groupId, + ordersConfigId, + tideCount, + sceneLimit, + param6); + + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + + if (group == null || group.monsters == null) { + return 1; + } + + this.getSceneScriptManager() + .startMonsterTideInGroup(group, ordersConfigId, tideCount, sceneLimit); + + return 0; + } + + public int AddExtraGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call AddExtraGroupSuite with {},{}", groupId, suite); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + + if (group == null || group.monsters == null) { + return 1; + } + var suiteData = group.getSuiteByIndex(suite); + if (suiteData == null) { + return 1; + } + // avoid spawn wrong monster + if (getSceneScriptManager().getScene().getChallenge() != null) + if (!getSceneScriptManager().getScene().getChallenge().inProgress() + || getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId) { + return 0; + } + this.getSceneScriptManager().addGroupSuite(group, suiteData); + + return 0; + } + + public int GoToGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call GoToGroupSuite with {},{}", groupId, suite); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + if (group == null || group.monsters == null) { + return 1; + } + var suiteData = group.getSuiteByIndex(suite); + if (suiteData == null) { + return 1; + } + + for (var suiteItem : group.suites) { + if (suiteData == suiteItem) { + continue; + } + this.getSceneScriptManager().removeGroupSuite(group, suiteItem); + } + this.getSceneScriptManager().addGroupSuite(group, suiteData); + + return 0; + } + + public int RemoveExtraGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call RemoveExtraGroupSuite with {},{}", groupId, suite); + + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + if (group == null || group.monsters == null) { + return 1; + } + var suiteData = group.getSuiteByIndex(suite); + if (suiteData == null) { + return 1; + } + + this.getSceneScriptManager().removeGroupSuite(group, suiteData); + + return 0; + } + + public int KillExtraGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call KillExtraGroupSuite with {},{}", groupId, suite); + + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + if (group == null || group.monsters == null) { + return 1; + } + var suiteData = group.getSuiteByIndex(suite); + if (suiteData == null) { + return 1; + } + + this.getSceneScriptManager().removeGroupSuite(group, suiteData); + + return 0; + } + + // param3 (probably time limit for timed dungeons) + public int ActiveChallenge( + int challengeId, + int challengeIndex, + int timeLimitOrGroupId, + int groupId, + int objectiveKills, + int param5) { + logger.debug( + "[LUA] Call ActiveChallenge with {},{},{},{},{},{}", + challengeId, + challengeIndex, + timeLimitOrGroupId, + groupId, + objectiveKills, + param5); + + var challenge = + ChallengeFactory.getChallenge( + challengeId, + challengeIndex, + timeLimitOrGroupId, + groupId, + objectiveKills, + param5, + getSceneScriptManager().getScene(), + getCurrentGroup().get()); + + if (challenge == null) { + return 1; + } + + if (challenge instanceof DungeonChallenge dungeonChallenge) { + // set if tower first stage (6-1) + dungeonChallenge.setStage( + getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0); + } + + getSceneScriptManager().getScene().setChallenge(challenge); + challenge.start(); + return 0; + } + + public int GetGroupMonsterCountByGroupId(int groupId) { + logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}", groupId); + return (int) + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId) + .count(); + } + + public int GetGroupVariableValue(String var) { + logger.debug("[LUA] Call GetGroupVariableValue with {}", var); + return getSceneScriptManager().getVariables().getOrDefault(var, 0); + } + + public int SetGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call SetGroupVariableValue with {},{}", var, value); + getSceneScriptManager().getVariables().put(var, value); + return 0; + } + + public LuaValue ChangeGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}", var, value); + + getSceneScriptManager() + .getVariables() + .put(var, getSceneScriptManager().getVariables().get(var) + value); + return LuaValue.ZERO; + } + + /** Set the actions and triggers to designated group */ + public int RefreshGroup(LuaTable table) { + logger.debug("[LUA] Call RefreshGroup with {}", printTable(table)); + // Kill and Respawn? + int groupId = table.get("group_id").toint(); + int suite = table.get("suite").toint(); + + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + + if (group == null || group.monsters == null) { + return 1; + } + + getSceneScriptManager().refreshGroup(group, suite); + + return 0; + } + + public int GetRegionEntityCount(LuaTable table) { + logger.debug("[LUA] Call GetRegionEntityCount with {}", printTable(table)); + int regionId = table.get("region_eid").toint(); + int entityType = table.get("entity_type").toint(); + + var region = this.getSceneScriptManager().getRegionById(regionId); + + if (region == null) { + return 0; + } + + return (int) region.getEntities().stream().filter(e -> e >> 24 == entityType).count(); + } + + public void PrintContextLog(String msg) { + logger.info("[LUA] " + msg); + } + + public int TowerCountTimeStatus(int isDone, int var2) { + logger.debug("[LUA] Call TowerCountTimeStatus with {},{}", isDone, var2); + // TODO record time + return 0; + } + + public int GetGroupMonsterCount() { + logger.debug("[LUA] Call GetGroupMonsterCount "); + + return (int) + getSceneScriptManager().getScene().getEntities().values().stream() + .filter( + e -> + e instanceof EntityMonster + && e.getGroupId() + == getCurrentGroup().map(sceneGroup -> sceneGroup.id).orElse(-1)) + .count(); + } + + public int SetMonsterBattleByGroup(int var1, int var2, int var3) { + logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}", var1, var2, var3); + // TODO + return 0; + } + + public int CauseDungeonFail(int var1) { + logger.debug("[LUA] Call CauseDungeonFail with {}", var1); + + return 0; + } + + public int GetGroupVariableValueByGroup(String name, int groupId) { + logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}", name, groupId); + + return getSceneScriptManager().getVariables().getOrDefault(name, 0); + } + + public int SetIsAllowUseSkill(int canUse, int var2) { + logger.debug("[LUA] Call SetIsAllowUseSkill with {},{}", canUse, var2); + + getSceneScriptManager().getScene().broadcastPacket(new PacketCanUseSkillNotify(canUse == 1)); + return 0; + } + + public int KillEntityByConfigId(LuaTable table) { + logger.debug("[LUA] Call KillEntityByConfigId with {}", printTable(table)); + var configId = table.get("config_id"); + if (configId == LuaValue.NIL) { + return 1; + } + + var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint()); + if (entity == null) { + return 0; + } + getSceneScriptManager().getScene().killEntity(entity, 0); + return 0; + } + + public int SetGroupVariableValueByGroup(String key, int value, int groupId) { + logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}", key, value, groupId); + + getSceneScriptManager().getVariables().put(key, value); + return 0; + } + + public int CreateMonster(LuaTable table) { + logger.debug("[LUA] Call CreateMonster with {}", printTable(table)); + var configId = table.get("config_id").toint(); + var delayTime = table.get("delay_time").toint(); + + if (getCurrentGroup().isEmpty()) { + return 1; + } + + getSceneScriptManager().spawnMonstersByConfigId(getCurrentGroup().get(), configId, delayTime); + return 0; + } + + public int TowerMirrorTeamSetUp(int team, int var1) { + logger.debug("[LUA] Call TowerMirrorTeamSetUp with {},{}", team, var1); + + getSceneScriptManager().unloadCurrentMonsterTide(); + getSceneScriptManager() + .getScene() + .getPlayers() + .get(0) + .getTowerManager() + .mirrorTeamSetUp(team - 1); + + return 0; + } + + public int CreateGadget(LuaTable table) { + logger.debug("[LUA] Call CreateGadget with {}", printTable(table)); + var configId = table.get("config_id").toint(); + + var group = getCurrentGroup(); + + if (group.isEmpty()) { + return 1; + } + + var gadget = group.get().gadgets.get(configId); + var entity = getSceneScriptManager().createGadget(group.get().id, group.get().block_id, gadget); + + getSceneScriptManager().addEntity(entity); + + return 0; + } + + public int CheckRemainGadgetCountByGroupId(LuaTable table) { + logger.debug("[LUA] Call CheckRemainGadgetCountByGroupId with {}", printTable(table)); + var groupId = table.get("group_id").toint(); + + var count = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter( + g -> g instanceof EntityGadget entityGadget && entityGadget.getGroupId() == groupId) + .count(); + return (int) count; + } + + public int GetGadgetStateByConfigId(int groupId, int configId) { + logger.debug("[LUA] Call GetGadgetStateByConfigId with {},{}", groupId, configId); + + if (groupId == 0) { + groupId = getCurrentGroup().get().id; + } + final int realGroupId = groupId; + var gadget = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter( + g -> + g instanceof EntityGadget entityGadget + && entityGadget.getGroupId() == realGroupId) + .filter(g -> g.getConfigId() == configId) + .findFirst(); + if (gadget.isEmpty()) { + return 1; + } + return ((EntityGadget) gadget.get()).getState(); + } + + public int MarkPlayerAction(int var1, int var2, int var3, int var4) { + logger.debug("[LUA] Call MarkPlayerAction with {},{},{},{}", var1, var2, var3, var4); + + return 0; + } + + public int AddQuestProgress(String var1) { + logger.debug("[LUA] Call AddQuestProgress with {}", var1); + + for (var player : getSceneScriptManager().getScene().getPlayers()) { + player.getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_LUA_NOTIFY, var1); + player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY, var1); + } + + return 0; + } + + /** change the state of gadget */ + public int ChangeGroupGadget(LuaTable table) { + logger.debug("[LUA] Call ChangeGroupGadget with {}", printTable(table)); + var configId = table.get("config_id").toint(); + var state = table.get("state").toint(); + + var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId); + if (entity == null) { + return 1; + } + + if (entity instanceof EntityGadget entityGadget) { + entityGadget.updateState(state); + return 0; + } + + return 1; + } + + public int GetEntityType(int entityId) { + var entity = getSceneScriptManager().getScene().getEntityById(entityId); + if (entity == null) { + // check players + Player player = DatabaseHelper.getPlayerByUid(entityId); + if (player != null) { + return EntityType.Avatar.getValue(); + } + + return EntityType.None.getValue(); + } + + return entity.getEntityType(); + } + + public int GetQuestState(int entityId, int questId) { + var player = getSceneScriptManager().getScene().getWorld().getHost(); + + var quest = player.getQuestManager().getQuestById(questId); + if (quest == null) { + return QuestState.QUEST_STATE_NONE.getValue(); + } + + return quest.getState().getValue(); + } + + public int ShowReminder(int reminderId) { + getSceneScriptManager() + .getScene() + .broadcastPacket(new PacketDungeonShowReminderNotify(reminderId)); + return 0; + } + + public int RemoveEntityByConfigId(int groupId, int entityType, int configId) { + logger.debug("[LUA] Call RemoveEntityByConfigId"); + + var entity = + getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e.getGroupId() == groupId) + .filter(e -> e.getEntityType() == entityType) + .filter(e -> e.getConfigId() == configId) + .findFirst(); + + if (entity.isEmpty()) { + return 1; + } + + getSceneScriptManager().getScene().removeEntity(entity.get()); + + return 0; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLoader.java b/src/main/java/emu/grasscutter/scripts/ScriptLoader.java index 8caac465e..d3dd8ca9d 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLoader.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLoader.java @@ -1,150 +1,152 @@ -package emu.grasscutter.scripts; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.props.EntityType; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.constants.ScriptGadgetState; -import emu.grasscutter.scripts.constants.ScriptRegionShape; -import emu.grasscutter.scripts.data.SceneMeta; -import emu.grasscutter.scripts.serializer.LuaSerializer; -import emu.grasscutter.scripts.serializer.Serializer; -import emu.grasscutter.utils.FileUtils; -import lombok.Getter; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.OneArgFunction; -import org.luaj.vm2.lib.jse.CoerceJavaToLua; -import org.luaj.vm2.script.LuajContext; - -import javax.script.*; -import java.io.File; -import java.io.FileReader; -import java.lang.ref.SoftReference; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -public class ScriptLoader { - private static ScriptEngineManager sm; - @Getter - private static ScriptEngine engine; - private static ScriptEngineFactory factory; - @Getter - private static Serializer serializer; - @Getter - private static ScriptLib scriptLib; - @Getter - private static LuaValue scriptLibLua; - /** - * suggest GC to remove it if the memory is less - */ - private static final Map> scriptsCache = new ConcurrentHashMap<>(); - /** - * sceneId - SceneMeta - */ - private static final Map> sceneMetaCache = new ConcurrentHashMap<>(); - - public synchronized static void init() throws Exception { - if (sm != null) { - throw new Exception("Script loader already initialized"); - } - - // Create script engine - sm = new ScriptEngineManager(); - engine = sm.getEngineByName("luaj"); - factory = getEngine().getFactory(); - - // Lua stuff - serializer = new LuaSerializer(); - - // Set engine to replace require as a temporary fix to missing scripts - LuajContext ctx = (LuajContext) engine.getContext(); - ctx.globals.set("require", new OneArgFunction() { - @Override - public LuaValue call(LuaValue arg0) { - return LuaValue.ZERO; - } - }); - - LuaTable table = new LuaTable(); - Arrays.stream(EntityType.values()).forEach(e -> table.set(e.name().toUpperCase(), e.getValue())); - ctx.globals.set("EntityType", table); - - LuaTable table1 = new LuaTable(); - Arrays.stream(QuestState.values()).forEach(e -> table1.set(e.name().toUpperCase(), e.getValue())); - ctx.globals.set("QuestState", table1); - - ctx.globals.set("EventType", CoerceJavaToLua.coerce(new EventType())); // TODO - make static class to avoid instantiating a new class every scene - ctx.globals.set("GadgetState", CoerceJavaToLua.coerce(new ScriptGadgetState())); - ctx.globals.set("RegionShape", CoerceJavaToLua.coerce(new ScriptRegionShape())); - - scriptLib = new ScriptLib(); - scriptLibLua = CoerceJavaToLua.coerce(scriptLib); - ctx.globals.set("ScriptLib", scriptLibLua); - } - - public static Optional tryGet(SoftReference softReference) { - try { - return Optional.ofNullable(softReference.get()); - } catch (NullPointerException npe) { - return Optional.empty(); - } - } - - @Deprecated(forRemoval = true) - public static CompiledScript getScriptByPath(String path) { - var sc = tryGet(scriptsCache.get(path)); - if (sc.isPresent()) { - return sc.get(); - } - - Grasscutter.getLogger().debug("Loading script " + path); - - File file = new File(path); - - if (!file.exists()) return null; - - try (FileReader fr = new FileReader(file)) { - var script = ((Compilable) getEngine()).compile(fr); - scriptsCache.put(path, new SoftReference<>(script)); - return script; - } catch (Exception e) { - Grasscutter.getLogger().error("Loading script {} failed!", path, e); - return null; - } - - } - - public static CompiledScript getScript(String path) { - var sc = tryGet(scriptsCache.get(path)); - if (sc.isPresent()) { - return sc.get(); - } - - Grasscutter.getLogger().debug("Loading script " + path); - final Path scriptPath = FileUtils.getScriptPath(path); - if (!Files.exists(scriptPath)) return null; - - try { - var script = ((Compilable) getEngine()).compile(Files.newBufferedReader(scriptPath)); - scriptsCache.put(path, new SoftReference<>(script)); - return script; - } catch (Exception e) { - Grasscutter.getLogger().error("Loading script {} failed! - {}", path, e.getLocalizedMessage()); - return null; - } - } - - public static SceneMeta getSceneMeta(int sceneId) { - return tryGet(sceneMetaCache.get(sceneId)).orElseGet(() -> { - var instance = SceneMeta.of(sceneId); - sceneMetaCache.put(sceneId, new SoftReference<>(instance)); - return instance; - }); - } - -} +package emu.grasscutter.scripts; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.props.EntityType; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.constants.ScriptGadgetState; +import emu.grasscutter.scripts.constants.ScriptRegionShape; +import emu.grasscutter.scripts.data.SceneMeta; +import emu.grasscutter.scripts.serializer.LuaSerializer; +import emu.grasscutter.scripts.serializer.Serializer; +import emu.grasscutter.utils.FileUtils; +import java.io.File; +import java.io.FileReader; +import java.lang.ref.SoftReference; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import javax.script.*; +import lombok.Getter; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.jse.CoerceJavaToLua; +import org.luaj.vm2.script.LuajContext; + +public class ScriptLoader { + private static ScriptEngineManager sm; + @Getter private static ScriptEngine engine; + private static ScriptEngineFactory factory; + @Getter private static Serializer serializer; + @Getter private static ScriptLib scriptLib; + @Getter private static LuaValue scriptLibLua; + /** suggest GC to remove it if the memory is less */ + private static final Map> scriptsCache = + new ConcurrentHashMap<>(); + /** sceneId - SceneMeta */ + private static final Map> sceneMetaCache = + new ConcurrentHashMap<>(); + + public static synchronized void init() throws Exception { + if (sm != null) { + throw new Exception("Script loader already initialized"); + } + + // Create script engine + sm = new ScriptEngineManager(); + engine = sm.getEngineByName("luaj"); + factory = getEngine().getFactory(); + + // Lua stuff + serializer = new LuaSerializer(); + + // Set engine to replace require as a temporary fix to missing scripts + LuajContext ctx = (LuajContext) engine.getContext(); + ctx.globals.set( + "require", + new OneArgFunction() { + @Override + public LuaValue call(LuaValue arg0) { + return LuaValue.ZERO; + } + }); + + LuaTable table = new LuaTable(); + Arrays.stream(EntityType.values()) + .forEach(e -> table.set(e.name().toUpperCase(), e.getValue())); + ctx.globals.set("EntityType", table); + + LuaTable table1 = new LuaTable(); + Arrays.stream(QuestState.values()) + .forEach(e -> table1.set(e.name().toUpperCase(), e.getValue())); + ctx.globals.set("QuestState", table1); + + ctx.globals.set( + "EventType", + CoerceJavaToLua.coerce( + new EventType())); // TODO - make static class to avoid instantiating a new class every + // scene + ctx.globals.set("GadgetState", CoerceJavaToLua.coerce(new ScriptGadgetState())); + ctx.globals.set("RegionShape", CoerceJavaToLua.coerce(new ScriptRegionShape())); + + scriptLib = new ScriptLib(); + scriptLibLua = CoerceJavaToLua.coerce(scriptLib); + ctx.globals.set("ScriptLib", scriptLibLua); + } + + public static Optional tryGet(SoftReference softReference) { + try { + return Optional.ofNullable(softReference.get()); + } catch (NullPointerException npe) { + return Optional.empty(); + } + } + + @Deprecated(forRemoval = true) + public static CompiledScript getScriptByPath(String path) { + var sc = tryGet(scriptsCache.get(path)); + if (sc.isPresent()) { + return sc.get(); + } + + Grasscutter.getLogger().debug("Loading script " + path); + + File file = new File(path); + + if (!file.exists()) return null; + + try (FileReader fr = new FileReader(file)) { + var script = ((Compilable) getEngine()).compile(fr); + scriptsCache.put(path, new SoftReference<>(script)); + return script; + } catch (Exception e) { + Grasscutter.getLogger().error("Loading script {} failed!", path, e); + return null; + } + } + + public static CompiledScript getScript(String path) { + var sc = tryGet(scriptsCache.get(path)); + if (sc.isPresent()) { + return sc.get(); + } + + Grasscutter.getLogger().debug("Loading script " + path); + final Path scriptPath = FileUtils.getScriptPath(path); + if (!Files.exists(scriptPath)) return null; + + try { + var script = ((Compilable) getEngine()).compile(Files.newBufferedReader(scriptPath)); + scriptsCache.put(path, new SoftReference<>(script)); + return script; + } catch (Exception e) { + Grasscutter.getLogger() + .error("Loading script {} failed! - {}", path, e.getLocalizedMessage()); + return null; + } + } + + public static SceneMeta getSceneMeta(int sceneId) { + return tryGet(sceneMetaCache.get(sceneId)) + .orElseGet( + () -> { + var instance = SceneMeta.of(sceneId); + sceneMetaCache.put(sceneId, new SoftReference<>(instance)); + return instance; + }); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/ScriptUtils.java b/src/main/java/emu/grasscutter/scripts/ScriptUtils.java index 0a601c7cd..d646cf59a 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptUtils.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptUtils.java @@ -1,27 +1,26 @@ -package emu.grasscutter.scripts; - -import emu.grasscutter.Grasscutter; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -import java.util.HashMap; - -public class ScriptUtils { - - public static HashMap toMap(LuaTable table) { - HashMap map = new HashMap<>(); - LuaValue[] rootKeys = table.keys(); - for (LuaValue k : rootKeys) { - if (table.get(k).istable()) { - map.put(k, toMap(table.get(k).checktable())); - } else { - map.put(k, table.get(k)); - } - } - return map; - } - - public static void print(LuaTable table) { - Grasscutter.getLogger().info(toMap(table).toString()); - } -} +package emu.grasscutter.scripts; + +import emu.grasscutter.Grasscutter; +import java.util.HashMap; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; + +public class ScriptUtils { + + public static HashMap toMap(LuaTable table) { + HashMap map = new HashMap<>(); + LuaValue[] rootKeys = table.keys(); + for (LuaValue k : rootKeys) { + if (table.get(k).istable()) { + map.put(k, toMap(table.get(k).checktable())); + } else { + map.put(k, table.get(k)); + } + } + return map; + } + + public static void print(LuaTable table) { + Grasscutter.getLogger().info(toMap(table).toString()); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/constants/EventType.java b/src/main/java/emu/grasscutter/scripts/constants/EventType.java index 5e7ad7599..5c5015126 100644 --- a/src/main/java/emu/grasscutter/scripts/constants/EventType.java +++ b/src/main/java/emu/grasscutter/scripts/constants/EventType.java @@ -1,127 +1,126 @@ -package emu.grasscutter.scripts.constants; - -public class EventType { - public static final int EVENT_NONE = 0; - /** - * param1: monster.configId - */ - public static final int EVENT_ANY_MONSTER_DIE = 1; - public static final int EVENT_ANY_GADGET_DIE = 2; - public static final int EVENT_VARIABLE_CHANGE = 3; - public static final int EVENT_ENTER_REGION = 4; - public static final int EVENT_LEAVE_REGION = 5; - public static final int EVENT_GADGET_CREATE = 6; - public static final int EVENT_GADGET_STATE_CHANGE = 7; - public static final int EVENT_DUNGEON_SETTLE = 8; - public static final int EVENT_SELECT_OPTION = 9; - public static final int EVENT_CLIENT_EXECUTE = 10; - public static final int EVENT_ANY_MONSTER_LIVE = 11; - public static final int EVENT_SPECIFIC_MONSTER_HP_CHANGE = 12; - public static final int EVENT_CITY_LEVELUP_UNLOCK_DUNGEON_ENTRY = 13; - public static final int EVENT_DUNGEON_BROADCAST_ONTIMER = 14; - public static final int EVENT_TIMER_EVENT = 15; - public static final int EVENT_CHALLENGE_SUCCESS = 16; - public static final int EVENT_CHALLENGE_FAIL = 17; - public static final int EVENT_SEAL_BATTLE_BEGIN = 18; - public static final int EVENT_SEAL_BATTLE_END = 19; - public static final int EVENT_GATHER = 20; - public static final int EVENT_QUEST_FINISH = 21; - public static final int EVENT_MONSTER_BATTLE = 22; - public static final int EVENT_CITY_LEVELUP = 23; - public static final int EVENT_CUTSCENE_END = 24; - public static final int EVENT_AVATAR_NEAR_PLATFORM = 25; - public static final int EVENT_PLATFORM_REACH_POINT = 26; - public static final int EVENT_UNLOCK_TRANS_POINT = 27; - public static final int EVENT_QUEST_START = 28; - public static final int EVENT_GROUP_LOAD = 29; - public static final int EVENT_GROUP_WILL_UNLOAD = 30; - public static final int EVENT_GROUP_WILL_REFRESH = 31; - public static final int EVENT_GROUP_REFRESH = 32; - public static final int EVENT_DUNGEON_REWARD_GET = 33; - public static final int EVENT_SPECIFIC_GADGET_HP_CHANGE = 34; - public static final int EVENT_MONSTER_TIDE_OVER = 35; - public static final int EVENT_MONSTER_TIDE_CREATE = 36; - public static final int EVENT_MONSTER_TIDE_DIE = 37; - public static final int EVENT_SEALAMP_PHASE_CHANGE = 38; - public static final int EVENT_BLOSSOM_PROGRESS_FINISH = 39; - public static final int EVENT_BLOSSOM_CHEST_DIE = 40; - public static final int EVENT_GADGET_PLAY_START = 41; - public static final int EVENT_GADGET_PLAY_START_CD = 42; - public static final int EVENT_GADGET_PLAY_STOP = 43; - public static final int EVENT_GADGET_LUA_NOTIFY = 44; - public static final int EVENT_MP_PLAY_PREPARE = 45; - public static final int EVENT_MP_PLAY_BATTLE = 46; - public static final int EVENT_MP_PLAY_PREPARE_INTERRUPT = 47; - public static final int EVENT_SELECT_DIFFICULTY = 48; - public static final int EVENT_SCENE_MP_PLAY_BATTLE_STATE = 49; - public static final int EVENT_SCENE_MP_PLAY_BATTLE_STAGE_CHANGE = 50; - public static final int EVENT_SCENE_MP_PLAY_BATTLE_RESULT = 51; - public static final int EVENT_SEAL_BATTLE_PROGRESS_DECREASE = 52; - public static final int EVENT_GENERAL_REWARD_DIE = 53; - public static final int EVENT_SCENE_MP_PLAY_BATTLE_INTERRUPT = 54; - public static final int EVENT_MONSTER_DIE_BEFORE_LEAVE_SCENE = 55; - public static final int EVENT_SCENE_MP_PLAY_OPEN = 56; - public static final int EVENT_OFFERING_LEVELUP = 57; - public static final int EVENT_DUNGEON_REVIVE = 58; - public static final int EVENT_SCENE_MP_PLAY_ALL_AVATAR_DIE = 59; - public static final int EVENT_DUNGEON_ALL_AVATAR_DIE = 60; - public static final int EVENT_GENERAL_REWARD_TAKEN = 61; - public static final int EVENT_PLATFORM_REACH_ARRAYPOINT = 62; - public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_END = 63; - public static final int EVENT_SCENE_MULTISTAGE_PLAY_END_STAGE_REQ = 64; - public static final int EVENT_MECHANICUS_PICKED_CARD = 65; - public static final int EVENT_POOL_MONSTER_TIDE_OVER = 66; - public static final int EVENT_POOL_MONSTER_TIDE_CREATE = 67; - public static final int EVENT_POOL_MONSTER_TIDE_DIE = 68; - public static final int EVENT_DUNGEON_AVATAR_SLIP_DIE = 69; - public static final int EVENT_GALLERY_START = 70; - public static final int EVENT_GALLERY_STOP = 71; - public static final int EVENT_TIME_AXIS_PASS = 72; - public static final int EVENT_FLEUR_FAIR_DUNGEON_ALL_PLAYER_ENTER = 73; - public static final int EVENT_GADGETTALK_DONE = 74; - public static final int EVENT_SET_GAME_TIME = 75; - public static final int EVENT_HIDE_AND_SEEK_PLAYER_QUIT = 76; - public static final int EVENT_AVATAR_DIE = 77; - public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_START = 78; - public static final int EVENT_GALLERY_PROGRESS_PASS = 79; - public static final int EVENT_GALLERY_PROGRESS_EMPTY = 80; - public static final int EVENT_GALLERY_PROGRESS_FULL = 81; - public static final int EVENT_HUNTING_FINISH_FINAL = 82; - public static final int EVENT_USE_WIDGET_TOY_FOX_CAMERA = 83; - public static final int EVENT_LUNA_RITE_SACRIFICE = 84; - public static final int EVENT_SUMO_SWITCH_TEAM_EVENT = 85; - public static final int EVENT_FISHING_START = 86; - public static final int EVENT_FISHING_STOP = 87; - public static final int EVENT_FISHING_QTE_FINISH = 88; - public static final int EVENT_FISHING_TIMEOUT_FLEE = 89; - public static final int EVENT_ROGUE_CELL_STATE_CHANGE = 90; - public static final int EVENT_ROGUE_CELL_CONSTRUCT = 91; - public static final int EVENT_ROGUE_CELL_FINISH_SELECT_CARD = 92; - public static final int EVENT_ANY_MONSTER_CAPTURE = 93; - public static final int EVENT_ACTIVITY_INTERACT_GADGET = 94; - public static final int EVENT_CHALLENGE_PAUSE = 95; - public static final int EVENT_LEVEL_TAG_CHANGE = 96; - public static final int EVENT_CUSTOM_DUNGEON_START = 97; - public static final int EVENT_CUSTOM_DUNGEON_RESTART = 98; - public static final int EVENT_CUSTOM_DUNGEON_REACTIVE = 99; - public static final int EVENT_CUSTOM_DUNGEON_OUT_STUCK = 100; - public static final int EVENT_CUSTOM_DUNGEON_EXIT_TRY = 101; - public static final int EVENT_CUSTOM_DUNGEON_OFFICIAL_RESTART = 102; - public static final int EVENT_ANY_MONSTER_CAPTURE_AND_DISAPPEAR = 103; - public static final int EVENT_MICHIAE_INTERACT = 104; - public static final int EVENT_SELECT_UIINTERACT = 105; - public static final int EVENT_LUA_NOTIFY = 106; - public static final int EVENT_PHOTO_FINISH = 107; - public static final int EVENT_IRODORI_MASTER_READY = 108; - public static final int EVENT_ROGUE_START_FIGHT = 109; - public static final int EVENT_ROGUE_CREAGE_FIGHT_GADGET = 110; - public static final int EVENT_ROGUE_CREAGE_REPAIR_GADGET = 111; - public static final int EVENT_ROGUE_OPEN_ACCESS = 112; - public static final int EVENT_GADGET_GIVING_FINISHED = 113; - public static final int EVENT_OBSERVATION_POINT_NOTIFY = 114; - public static final int EVENT_GADGET_GIVING_TAKEBACK = 115; - public static final int EVENT_ECHO_SHELL_INTERACT = 116; - public static final int EVENT_PLATFORM_ARRIVAL = 2701; - public static final int EVENT_PLAYER_BACK_GALLERY_REVIVE_POINT = 2800; - public static final int EVENT_GALLERY_CANNOT_START_AFTER_COUNTDOWN = 2801; -} +package emu.grasscutter.scripts.constants; + +public class EventType { + public static final int EVENT_NONE = 0; + /** param1: monster.configId */ + public static final int EVENT_ANY_MONSTER_DIE = 1; + + public static final int EVENT_ANY_GADGET_DIE = 2; + public static final int EVENT_VARIABLE_CHANGE = 3; + public static final int EVENT_ENTER_REGION = 4; + public static final int EVENT_LEAVE_REGION = 5; + public static final int EVENT_GADGET_CREATE = 6; + public static final int EVENT_GADGET_STATE_CHANGE = 7; + public static final int EVENT_DUNGEON_SETTLE = 8; + public static final int EVENT_SELECT_OPTION = 9; + public static final int EVENT_CLIENT_EXECUTE = 10; + public static final int EVENT_ANY_MONSTER_LIVE = 11; + public static final int EVENT_SPECIFIC_MONSTER_HP_CHANGE = 12; + public static final int EVENT_CITY_LEVELUP_UNLOCK_DUNGEON_ENTRY = 13; + public static final int EVENT_DUNGEON_BROADCAST_ONTIMER = 14; + public static final int EVENT_TIMER_EVENT = 15; + public static final int EVENT_CHALLENGE_SUCCESS = 16; + public static final int EVENT_CHALLENGE_FAIL = 17; + public static final int EVENT_SEAL_BATTLE_BEGIN = 18; + public static final int EVENT_SEAL_BATTLE_END = 19; + public static final int EVENT_GATHER = 20; + public static final int EVENT_QUEST_FINISH = 21; + public static final int EVENT_MONSTER_BATTLE = 22; + public static final int EVENT_CITY_LEVELUP = 23; + public static final int EVENT_CUTSCENE_END = 24; + public static final int EVENT_AVATAR_NEAR_PLATFORM = 25; + public static final int EVENT_PLATFORM_REACH_POINT = 26; + public static final int EVENT_UNLOCK_TRANS_POINT = 27; + public static final int EVENT_QUEST_START = 28; + public static final int EVENT_GROUP_LOAD = 29; + public static final int EVENT_GROUP_WILL_UNLOAD = 30; + public static final int EVENT_GROUP_WILL_REFRESH = 31; + public static final int EVENT_GROUP_REFRESH = 32; + public static final int EVENT_DUNGEON_REWARD_GET = 33; + public static final int EVENT_SPECIFIC_GADGET_HP_CHANGE = 34; + public static final int EVENT_MONSTER_TIDE_OVER = 35; + public static final int EVENT_MONSTER_TIDE_CREATE = 36; + public static final int EVENT_MONSTER_TIDE_DIE = 37; + public static final int EVENT_SEALAMP_PHASE_CHANGE = 38; + public static final int EVENT_BLOSSOM_PROGRESS_FINISH = 39; + public static final int EVENT_BLOSSOM_CHEST_DIE = 40; + public static final int EVENT_GADGET_PLAY_START = 41; + public static final int EVENT_GADGET_PLAY_START_CD = 42; + public static final int EVENT_GADGET_PLAY_STOP = 43; + public static final int EVENT_GADGET_LUA_NOTIFY = 44; + public static final int EVENT_MP_PLAY_PREPARE = 45; + public static final int EVENT_MP_PLAY_BATTLE = 46; + public static final int EVENT_MP_PLAY_PREPARE_INTERRUPT = 47; + public static final int EVENT_SELECT_DIFFICULTY = 48; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_STATE = 49; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_STAGE_CHANGE = 50; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_RESULT = 51; + public static final int EVENT_SEAL_BATTLE_PROGRESS_DECREASE = 52; + public static final int EVENT_GENERAL_REWARD_DIE = 53; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_INTERRUPT = 54; + public static final int EVENT_MONSTER_DIE_BEFORE_LEAVE_SCENE = 55; + public static final int EVENT_SCENE_MP_PLAY_OPEN = 56; + public static final int EVENT_OFFERING_LEVELUP = 57; + public static final int EVENT_DUNGEON_REVIVE = 58; + public static final int EVENT_SCENE_MP_PLAY_ALL_AVATAR_DIE = 59; + public static final int EVENT_DUNGEON_ALL_AVATAR_DIE = 60; + public static final int EVENT_GENERAL_REWARD_TAKEN = 61; + public static final int EVENT_PLATFORM_REACH_ARRAYPOINT = 62; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_END = 63; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_END_STAGE_REQ = 64; + public static final int EVENT_MECHANICUS_PICKED_CARD = 65; + public static final int EVENT_POOL_MONSTER_TIDE_OVER = 66; + public static final int EVENT_POOL_MONSTER_TIDE_CREATE = 67; + public static final int EVENT_POOL_MONSTER_TIDE_DIE = 68; + public static final int EVENT_DUNGEON_AVATAR_SLIP_DIE = 69; + public static final int EVENT_GALLERY_START = 70; + public static final int EVENT_GALLERY_STOP = 71; + public static final int EVENT_TIME_AXIS_PASS = 72; + public static final int EVENT_FLEUR_FAIR_DUNGEON_ALL_PLAYER_ENTER = 73; + public static final int EVENT_GADGETTALK_DONE = 74; + public static final int EVENT_SET_GAME_TIME = 75; + public static final int EVENT_HIDE_AND_SEEK_PLAYER_QUIT = 76; + public static final int EVENT_AVATAR_DIE = 77; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_START = 78; + public static final int EVENT_GALLERY_PROGRESS_PASS = 79; + public static final int EVENT_GALLERY_PROGRESS_EMPTY = 80; + public static final int EVENT_GALLERY_PROGRESS_FULL = 81; + public static final int EVENT_HUNTING_FINISH_FINAL = 82; + public static final int EVENT_USE_WIDGET_TOY_FOX_CAMERA = 83; + public static final int EVENT_LUNA_RITE_SACRIFICE = 84; + public static final int EVENT_SUMO_SWITCH_TEAM_EVENT = 85; + public static final int EVENT_FISHING_START = 86; + public static final int EVENT_FISHING_STOP = 87; + public static final int EVENT_FISHING_QTE_FINISH = 88; + public static final int EVENT_FISHING_TIMEOUT_FLEE = 89; + public static final int EVENT_ROGUE_CELL_STATE_CHANGE = 90; + public static final int EVENT_ROGUE_CELL_CONSTRUCT = 91; + public static final int EVENT_ROGUE_CELL_FINISH_SELECT_CARD = 92; + public static final int EVENT_ANY_MONSTER_CAPTURE = 93; + public static final int EVENT_ACTIVITY_INTERACT_GADGET = 94; + public static final int EVENT_CHALLENGE_PAUSE = 95; + public static final int EVENT_LEVEL_TAG_CHANGE = 96; + public static final int EVENT_CUSTOM_DUNGEON_START = 97; + public static final int EVENT_CUSTOM_DUNGEON_RESTART = 98; + public static final int EVENT_CUSTOM_DUNGEON_REACTIVE = 99; + public static final int EVENT_CUSTOM_DUNGEON_OUT_STUCK = 100; + public static final int EVENT_CUSTOM_DUNGEON_EXIT_TRY = 101; + public static final int EVENT_CUSTOM_DUNGEON_OFFICIAL_RESTART = 102; + public static final int EVENT_ANY_MONSTER_CAPTURE_AND_DISAPPEAR = 103; + public static final int EVENT_MICHIAE_INTERACT = 104; + public static final int EVENT_SELECT_UIINTERACT = 105; + public static final int EVENT_LUA_NOTIFY = 106; + public static final int EVENT_PHOTO_FINISH = 107; + public static final int EVENT_IRODORI_MASTER_READY = 108; + public static final int EVENT_ROGUE_START_FIGHT = 109; + public static final int EVENT_ROGUE_CREAGE_FIGHT_GADGET = 110; + public static final int EVENT_ROGUE_CREAGE_REPAIR_GADGET = 111; + public static final int EVENT_ROGUE_OPEN_ACCESS = 112; + public static final int EVENT_GADGET_GIVING_FINISHED = 113; + public static final int EVENT_OBSERVATION_POINT_NOTIFY = 114; + public static final int EVENT_GADGET_GIVING_TAKEBACK = 115; + public static final int EVENT_ECHO_SHELL_INTERACT = 116; + public static final int EVENT_PLATFORM_ARRIVAL = 2701; + public static final int EVENT_PLAYER_BACK_GALLERY_REVIVE_POINT = 2800; + public static final int EVENT_GALLERY_CANNOT_START_AFTER_COUNTDOWN = 2801; +} diff --git a/src/main/java/emu/grasscutter/scripts/constants/ScriptGadgetState.java b/src/main/java/emu/grasscutter/scripts/constants/ScriptGadgetState.java index 187299a01..043278643 100644 --- a/src/main/java/emu/grasscutter/scripts/constants/ScriptGadgetState.java +++ b/src/main/java/emu/grasscutter/scripts/constants/ScriptGadgetState.java @@ -1,24 +1,24 @@ -package emu.grasscutter.scripts.constants; - -public class ScriptGadgetState { - public static final int Default = 0; - public static final int GatherDrop = 1; - public static final int ChestLocked = 101; - public static final int ChestOpened = 102; - public static final int ChestTrap = 103; - public static final int ChestBramble = 104; - public static final int ChestFrozen = 105; - public static final int ChestRock = 106; - public static final int GearStart = 201; - public static final int GearStop = 202; - public static final int GearAction1 = 203; - public static final int GearAction2 = 204; - public static final int CrystalResonate1 = 301; - public static final int CrystalResonate2 = 302; - public static final int CrystalExplode = 303; - public static final int CrystalDrain = 304; - public static final int StatueActive = 401; - public static final int Action01 = 901; - public static final int Action02 = 902; - public static final int Action03 = 903; -} +package emu.grasscutter.scripts.constants; + +public class ScriptGadgetState { + public static final int Default = 0; + public static final int GatherDrop = 1; + public static final int ChestLocked = 101; + public static final int ChestOpened = 102; + public static final int ChestTrap = 103; + public static final int ChestBramble = 104; + public static final int ChestFrozen = 105; + public static final int ChestRock = 106; + public static final int GearStart = 201; + public static final int GearStop = 202; + public static final int GearAction1 = 203; + public static final int GearAction2 = 204; + public static final int CrystalResonate1 = 301; + public static final int CrystalResonate2 = 302; + public static final int CrystalExplode = 303; + public static final int CrystalDrain = 304; + public static final int StatueActive = 401; + public static final int Action01 = 901; + public static final int Action02 = 902; + public static final int Action03 = 903; +} diff --git a/src/main/java/emu/grasscutter/scripts/constants/ScriptRegionShape.java b/src/main/java/emu/grasscutter/scripts/constants/ScriptRegionShape.java index 31e1f7f63..eb983df97 100644 --- a/src/main/java/emu/grasscutter/scripts/constants/ScriptRegionShape.java +++ b/src/main/java/emu/grasscutter/scripts/constants/ScriptRegionShape.java @@ -1,9 +1,9 @@ -package emu.grasscutter.scripts.constants; - -public class ScriptRegionShape { - public static final int NONE = 0; - public static final int SPHERE = 1; - public static final int CUBIC = 2; - public static final int CYLINDER = 3; - public static final int POLYGON = 4; -} +package emu.grasscutter.scripts.constants; + +public class ScriptRegionShape { + public static final int NONE = 0; + public static final int SPHERE = 1; + public static final int CUBIC = 2; + public static final int CYLINDER = 3; + public static final int POLYGON = 4; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneBlock.java b/src/main/java/emu/grasscutter/scripts/data/SceneBlock.java index 772a71030..639574ff7 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneBlock.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneBlock.java @@ -1,78 +1,86 @@ -package emu.grasscutter.scripts.data; - -import com.github.davidmoten.rtreemulti.RTree; -import com.github.davidmoten.rtreemulti.geometry.Geometry; -import com.github.davidmoten.rtreemulti.geometry.Rectangle; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.scripts.SceneIndexManager; -import emu.grasscutter.scripts.ScriptLoader; -import emu.grasscutter.utils.Position; -import lombok.Setter; -import lombok.ToString; - -import javax.script.Bindings; -import javax.script.CompiledScript; -import javax.script.ScriptException; -import java.util.Map; -import java.util.stream.Collectors; - -@ToString -@Setter -public class SceneBlock { - public int id; - public Position max; - public Position min; - - public int sceneId; - public Map groups; - public RTree sceneGroupIndex; - - private transient boolean loaded; // Not an actual variable in the scripts either - - public boolean isLoaded() { - return this.loaded; - } - - public void setLoaded(boolean loaded) { - this.loaded = loaded; - } - - public boolean contains(Position pos) { - return pos.getX() <= this.max.getX() && pos.getX() >= this.min.getX() && - pos.getZ() <= this.max.getZ() && pos.getZ() >= this.min.getZ(); - } - - public SceneBlock load(int sceneId, Bindings bindings) { - if (this.loaded) { - return this; - } - this.sceneId = sceneId; - this.setLoaded(true); - - CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_block" + this.id + ".lua"); - - if (cs == null) { - return null; - } - - // Eval script - try { - cs.eval(bindings); - - // Set groups - this.groups = ScriptLoader.getSerializer().toList(SceneGroup.class, bindings.get("groups")).stream() - .collect(Collectors.toMap(x -> x.id, y -> y, (a, b) -> a)); - - this.groups.values().forEach(g -> g.block_id = this.id); - this.sceneGroupIndex = SceneIndexManager.buildIndex(3, this.groups.values(), g -> g.pos.toPoint()); - } catch (ScriptException exception) { - Grasscutter.getLogger().error("An error occurred while loading block " + this.id + " in scene " + sceneId, exception); - } - Grasscutter.getLogger().debug("Successfully loaded block {} in scene {}.", this.id, sceneId); - return this; - } - - public Rectangle toRectangle() { - return Rectangle.create(this.min.toXZDoubleArray(), this.max.toXZDoubleArray()); - } -} +package emu.grasscutter.scripts.data; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import com.github.davidmoten.rtreemulti.geometry.Rectangle; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.scripts.ScriptLoader; +import emu.grasscutter.utils.Position; +import java.util.Map; +import java.util.stream.Collectors; +import javax.script.Bindings; +import javax.script.CompiledScript; +import javax.script.ScriptException; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneBlock { + public int id; + public Position max; + public Position min; + + public int sceneId; + public Map groups; + public RTree sceneGroupIndex; + + private transient boolean loaded; // Not an actual variable in the scripts either + + public boolean isLoaded() { + return this.loaded; + } + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + + public boolean contains(Position pos) { + return pos.getX() <= this.max.getX() + && pos.getX() >= this.min.getX() + && pos.getZ() <= this.max.getZ() + && pos.getZ() >= this.min.getZ(); + } + + public SceneBlock load(int sceneId, Bindings bindings) { + if (this.loaded) { + return this; + } + this.sceneId = sceneId; + this.setLoaded(true); + + CompiledScript cs = + ScriptLoader.getScript( + "Scene/" + sceneId + "/scene" + sceneId + "_block" + this.id + ".lua"); + + if (cs == null) { + return null; + } + + // Eval script + try { + cs.eval(bindings); + + // Set groups + this.groups = + ScriptLoader.getSerializer().toList(SceneGroup.class, bindings.get("groups")).stream() + .collect(Collectors.toMap(x -> x.id, y -> y, (a, b) -> a)); + + this.groups.values().forEach(g -> g.block_id = this.id); + this.sceneGroupIndex = + SceneIndexManager.buildIndex(3, this.groups.values(), g -> g.pos.toPoint()); + } catch (ScriptException exception) { + Grasscutter.getLogger() + .error( + "An error occurred while loading block " + this.id + " in scene " + sceneId, + exception); + } + Grasscutter.getLogger().debug("Successfully loaded block {} in scene {}.", this.id, sceneId); + return this; + } + + public Rectangle toRectangle() { + return Rectangle.create(this.min.toXZDoubleArray(), this.max.toXZDoubleArray()); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneBusiness.java b/src/main/java/emu/grasscutter/scripts/data/SceneBusiness.java index 2609f9b5d..e5a61e5dd 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneBusiness.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneBusiness.java @@ -1,10 +1,10 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneBusiness { - public int type; -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneBusiness { + public int type; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneConfig.java b/src/main/java/emu/grasscutter/scripts/data/SceneConfig.java index f152df6d0..8fe47c63f 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneConfig.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneConfig.java @@ -1,15 +1,15 @@ -package emu.grasscutter.scripts.data; - -import emu.grasscutter.utils.Position; -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneConfig { - public Position vision_anchor; - public Position born_pos; - public Position born_rot; - public Position begin_pos; - public Position size; -} +package emu.grasscutter.scripts.data; + +import emu.grasscutter.utils.Position; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneConfig { + public Position vision_anchor; + public Position born_pos; + public Position born_rot; + public Position begin_pos; + public Position size; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java b/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java index 108fa7100..d5de2beff 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGadget.java @@ -1,27 +1,27 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneGadget extends SceneObject { - public int gadget_id; - public int state; - public int point_type; - public SceneBossChest boss_chest; - public int interact_id; - public boolean isOneoff; - public int draft_id; - public String drop_tag; - public boolean persistent; - public int mark_flag; - public int route_id; - public Explore explore; - public int trigger_count; - public boolean showcutscene; - - public void setIsOneoff(boolean isOneoff) { - this.isOneoff = isOneoff; - } -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneGadget extends SceneObject { + public int gadget_id; + public int state; + public int point_type; + public SceneBossChest boss_chest; + public int interact_id; + public boolean isOneoff; + public int draft_id; + public String drop_tag; + public boolean persistent; + public int mark_flag; + public int route_id; + public Explore explore; + public int trigger_count; + public boolean showcutscene; + + public void setIsOneoff(boolean isOneoff) { + this.isOneoff = isOneoff; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGarbage.java b/src/main/java/emu/grasscutter/scripts/data/SceneGarbage.java index 268941c3a..edefd1253 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGarbage.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGarbage.java @@ -1,12 +1,11 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -import java.util.List; - -@ToString -@Setter -public class SceneGarbage { - public List gadgets; -} +package emu.grasscutter.scripts.data; + +import java.util.List; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneGarbage { + public List gadgets; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java index 08697e985..330ef80b1 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java @@ -1,148 +1,170 @@ -package emu.grasscutter.scripts.data; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.scripts.ScriptLoader; -import emu.grasscutter.utils.Position; -import lombok.Setter; -import lombok.ToString; -import org.luaj.vm2.LuaValue; - -import javax.script.Bindings; -import javax.script.CompiledScript; -import javax.script.ScriptException; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -@ToString -@Setter -public class SceneGroup { - public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference - - public int id; - public int refresh_id; - public Position pos; - - public Map monsters; // - public Map gadgets; // - public Map triggers; - public Map regions; - public List suites; - public List variables; - - public SceneBusiness business; - public SceneGarbage garbages; - public SceneInitConfig init_config; - - private transient boolean loaded; // Not an actual variable in the scripts either - private transient CompiledScript script; - private transient Bindings bindings; - - public static SceneGroup of(int groupId) { - var group = new SceneGroup(); - group.id = groupId; - return group; - } - - public boolean isLoaded() { - return this.loaded; - } - - public void setLoaded(boolean loaded) { - this.loaded = loaded; - } - - public int getBusinessType() { - return this.business == null ? 0 : this.business.type; - } - - public List getGarbageGadgets() { - return this.garbages == null ? null : this.garbages.gadgets; - } - - public CompiledScript getScript() { - return this.script; - } - - public SceneSuite getSuiteByIndex(int index) { - return this.suites.get(index - 1); - } - - public Bindings getBindings() { - return this.bindings; - } - - public synchronized SceneGroup load(int sceneId) { - if (this.loaded) { - return this; - } - // Set flag here so if there is no script, we don't call this function over and over again. - this.setLoaded(true); - - this.bindings = ScriptLoader.getEngine().createBindings(); - - CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua"); - - if (cs == null) { - return this; - } - - this.script = cs; - - // Eval script - try { - cs.eval(this.bindings); - - // Set - this.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, this.bindings.get("monsters")).stream() - .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); - this.monsters.values().forEach(m -> m.group = this); - - this.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, this.bindings.get("gadgets")).stream() - .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); - this.gadgets.values().forEach(m -> m.group = this); - - this.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, this.bindings.get("triggers")).stream() - .collect(Collectors.toMap(x -> x.name, y -> y, (a, b) -> a)); - this.triggers.values().forEach(t -> t.currentGroup = this); - - this.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites")); - this.regions = ScriptLoader.getSerializer().toList(SceneRegion.class, this.bindings.get("regions")).stream() - .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); - this.regions.values().forEach(m -> m.group = this); - - this.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, this.bindings.get("init_config")); - - // Garbages // TODO: fix properly later - Object garbagesValue = this.bindings.get("garbages"); - if (garbagesValue instanceof LuaValue garbagesTable) { - this.garbages = new SceneGarbage(); - if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) { - this.garbages.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable()); - this.garbages.gadgets.forEach(m -> m.group = this); - } - } - - // Add variables to suite - this.variables = ScriptLoader.getSerializer().toList(SceneVar.class, this.bindings.get("variables")); - - // Add monsters and gadgets to suite - this.suites.forEach(i -> i.init(this)); - - } catch (ScriptException e) { - Grasscutter.getLogger().error("An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e); - } - - Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId); - return this; - } - - public Optional searchBossChestInGroup() { - return this.gadgets.values().stream() - .filter(g -> g.boss_chest != null && g.boss_chest.monster_config_id > 0) - .map(g -> g.boss_chest) - .findFirst(); - } - -} +package emu.grasscutter.scripts.data; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.scripts.ScriptLoader; +import emu.grasscutter.utils.Position; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.script.Bindings; +import javax.script.CompiledScript; +import javax.script.ScriptException; +import lombok.Setter; +import lombok.ToString; +import org.luaj.vm2.LuaValue; + +@ToString +@Setter +public class SceneGroup { + public transient int + block_id; // Not an actual variable in the scripts but we will keep it here for reference + + public int id; + public int refresh_id; + public Position pos; + + public Map monsters; // + public Map gadgets; // + public Map triggers; + public Map regions; + public List suites; + public List variables; + + public SceneBusiness business; + public SceneGarbage garbages; + public SceneInitConfig init_config; + + private transient boolean loaded; // Not an actual variable in the scripts either + private transient CompiledScript script; + private transient Bindings bindings; + + public static SceneGroup of(int groupId) { + var group = new SceneGroup(); + group.id = groupId; + return group; + } + + public boolean isLoaded() { + return this.loaded; + } + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + + public int getBusinessType() { + return this.business == null ? 0 : this.business.type; + } + + public List getGarbageGadgets() { + return this.garbages == null ? null : this.garbages.gadgets; + } + + public CompiledScript getScript() { + return this.script; + } + + public SceneSuite getSuiteByIndex(int index) { + return this.suites.get(index - 1); + } + + public Bindings getBindings() { + return this.bindings; + } + + public synchronized SceneGroup load(int sceneId) { + if (this.loaded) { + return this; + } + // Set flag here so if there is no script, we don't call this function over and over again. + this.setLoaded(true); + + this.bindings = ScriptLoader.getEngine().createBindings(); + + CompiledScript cs = + ScriptLoader.getScript( + "Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua"); + + if (cs == null) { + return this; + } + + this.script = cs; + + // Eval script + try { + cs.eval(this.bindings); + + // Set + this.monsters = + ScriptLoader.getSerializer() + .toList(SceneMonster.class, this.bindings.get("monsters")) + .stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.monsters.values().forEach(m -> m.group = this); + + this.gadgets = + ScriptLoader.getSerializer() + .toList(SceneGadget.class, this.bindings.get("gadgets")) + .stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.gadgets.values().forEach(m -> m.group = this); + + this.triggers = + ScriptLoader.getSerializer() + .toList(SceneTrigger.class, this.bindings.get("triggers")) + .stream() + .collect(Collectors.toMap(x -> x.name, y -> y, (a, b) -> a)); + this.triggers.values().forEach(t -> t.currentGroup = this); + + this.suites = + ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites")); + this.regions = + ScriptLoader.getSerializer() + .toList(SceneRegion.class, this.bindings.get("regions")) + .stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.regions.values().forEach(m -> m.group = this); + + this.init_config = + ScriptLoader.getSerializer() + .toObject(SceneInitConfig.class, this.bindings.get("init_config")); + + // Garbages // TODO: fix properly later + Object garbagesValue = this.bindings.get("garbages"); + if (garbagesValue instanceof LuaValue garbagesTable) { + this.garbages = new SceneGarbage(); + if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) { + this.garbages.gadgets = + ScriptLoader.getSerializer() + .toList( + SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable()); + this.garbages.gadgets.forEach(m -> m.group = this); + } + } + + // Add variables to suite + this.variables = + ScriptLoader.getSerializer().toList(SceneVar.class, this.bindings.get("variables")); + + // Add monsters and gadgets to suite + this.suites.forEach(i -> i.init(this)); + + } catch (ScriptException e) { + Grasscutter.getLogger() + .error( + "An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e); + } + + Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId); + return this; + } + + public Optional searchBossChestInGroup() { + return this.gadgets.values().stream() + .filter(g -> g.boss_chest != null && g.boss_chest.monster_config_id > 0) + .map(g -> g.boss_chest) + .findFirst(); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneInitConfig.java b/src/main/java/emu/grasscutter/scripts/data/SceneInitConfig.java index 307989b33..22632ed50 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneInitConfig.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneInitConfig.java @@ -1,12 +1,12 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneInitConfig { - public int suite; - public int end_suite; - public boolean rand_suite; -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneInitConfig { + public int suite; + public int end_suite; + public boolean rand_suite; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneMeta.java b/src/main/java/emu/grasscutter/scripts/data/SceneMeta.java index 878d9bea1..668cf627a 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneMeta.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneMeta.java @@ -1,72 +1,74 @@ -package emu.grasscutter.scripts.data; - -import com.github.davidmoten.rtreemulti.RTree; -import com.github.davidmoten.rtreemulti.geometry.Geometry; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.scripts.SceneIndexManager; -import emu.grasscutter.scripts.ScriptLoader; -import lombok.Setter; -import lombok.ToString; - -import javax.script.Bindings; -import javax.script.CompiledScript; -import javax.script.ScriptException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@ToString -@Setter -public class SceneMeta { - - public SceneConfig config; - public Map blocks; - - public Bindings context; - - public RTree sceneBlockIndex; - - public static SceneMeta of(int sceneId) { - return new SceneMeta().load(sceneId); - } - - public SceneMeta load(int sceneId) { - // Get compiled script if cached - CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + ".lua"); - - if (cs == null) { - Grasscutter.getLogger().warn("No script found for scene " + sceneId); - return null; - } - - // Create bindings - this.context = ScriptLoader.getEngine().createBindings(); - - // Eval script - try { - cs.eval(this.context); - - this.config = ScriptLoader.getSerializer().toObject(SceneConfig.class, this.context.get("scene_config")); - - // TODO optimize later - // Create blocks - List blockIds = ScriptLoader.getSerializer().toList(Integer.class, this.context.get("blocks")); - List blocks = ScriptLoader.getSerializer().toList(SceneBlock.class, this.context.get("block_rects")); - - for (int i = 0; i < blocks.size(); i++) { - SceneBlock block = blocks.get(i); - block.id = blockIds.get(i); - - } - - this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b, (a, b) -> a)); - this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle); - - } catch (ScriptException exception) { - Grasscutter.getLogger().error("An error occurred while running a script.", exception); - return null; - } - Grasscutter.getLogger().debug("Successfully loaded metadata in scene {}.", sceneId); - return this; - } -} +package emu.grasscutter.scripts.data; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.scripts.SceneIndexManager; +import emu.grasscutter.scripts.ScriptLoader; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.script.Bindings; +import javax.script.CompiledScript; +import javax.script.ScriptException; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneMeta { + + public SceneConfig config; + public Map blocks; + + public Bindings context; + + public RTree sceneBlockIndex; + + public static SceneMeta of(int sceneId) { + return new SceneMeta().load(sceneId); + } + + public SceneMeta load(int sceneId) { + // Get compiled script if cached + CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + ".lua"); + + if (cs == null) { + Grasscutter.getLogger().warn("No script found for scene " + sceneId); + return null; + } + + // Create bindings + this.context = ScriptLoader.getEngine().createBindings(); + + // Eval script + try { + cs.eval(this.context); + + this.config = + ScriptLoader.getSerializer() + .toObject(SceneConfig.class, this.context.get("scene_config")); + + // TODO optimize later + // Create blocks + List blockIds = + ScriptLoader.getSerializer().toList(Integer.class, this.context.get("blocks")); + List blocks = + ScriptLoader.getSerializer().toList(SceneBlock.class, this.context.get("block_rects")); + + for (int i = 0; i < blocks.size(); i++) { + SceneBlock block = blocks.get(i); + block.id = blockIds.get(i); + } + + this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b, (a, b) -> a)); + this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle); + + } catch (ScriptException exception) { + Grasscutter.getLogger().error("An error occurred while running a script.", exception); + return null; + } + Grasscutter.getLogger().debug("Successfully loaded metadata in scene {}.", sceneId); + return this; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneMonster.java b/src/main/java/emu/grasscutter/scripts/data/SceneMonster.java index 3fa718b71..260dd3996 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneMonster.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneMonster.java @@ -1,19 +1,19 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneMonster extends SceneObject { - public int monster_id; - public int pose_id; - public int drop_id; - public int special_name_id; - public String drop_tag; - public int climate_area_id; - public boolean disableWander; - public int title_id; - public int[] affix; - public int mark_flag; -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneMonster extends SceneObject { + public int monster_id; + public int pose_id; + public int drop_id; + public int special_name_id; + public String drop_tag; + public int climate_area_id; + public boolean disableWander; + public int title_id; + public int[] affix; + public int mark_flag; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneNPC.java b/src/main/java/emu/grasscutter/scripts/data/SceneNPC.java index 1dfb44211..00edef640 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneNPC.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneNPC.java @@ -1,10 +1,10 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneNPC extends SceneObject { - public int npc_id; -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneNPC extends SceneObject { + public int npc_id; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneObject.java b/src/main/java/emu/grasscutter/scripts/data/SceneObject.java index eb1f42d8c..011dc2c52 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneObject.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneObject.java @@ -1,20 +1,18 @@ -package emu.grasscutter.scripts.data; - -import emu.grasscutter.utils.Position; -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneObject { - public int level; - public int config_id; - public int area_id; - - public Position pos; - public Position rot; - /** - * not set by lua - */ - public transient SceneGroup group; -} +package emu.grasscutter.scripts.data; + +import emu.grasscutter.utils.Position; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneObject { + public int level; + public int config_id; + public int area_id; + + public Position pos; + public Position rot; + /** not set by lua */ + public transient SceneGroup group; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneRegion.java b/src/main/java/emu/grasscutter/scripts/data/SceneRegion.java index 978a0fd7c..f0d2bfd57 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneRegion.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneRegion.java @@ -1,41 +1,38 @@ -package emu.grasscutter.scripts.data; - -import emu.grasscutter.scripts.constants.ScriptRegionShape; -import emu.grasscutter.utils.Position; -import lombok.Setter; - -import java.util.List; - - -@Setter -public class SceneRegion { - public int config_id; - public int shape; - public Position pos; - // for CUBIC - public Position size; - // for SPHERE - public int radius; - public int area_id; - public float height; - public List point_array; - - public transient SceneGroup group; - - public boolean contains(Position position) { - switch (shape) { - case ScriptRegionShape.CUBIC: - return (Math.abs(pos.getX() - position.getX()) <= size.getX()) && - (Math.abs(pos.getY() - position.getY()) <= size.getY()) && - (Math.abs(pos.getZ() - position.getZ()) <= size.getZ()); - case ScriptRegionShape.SPHERE: - var x = Math.pow(pos.getX() - position.getX(), 2); - var y = Math.pow(pos.getY() - position.getY(), 2); - var z = Math.pow(pos.getZ() - position.getZ(), 2); - // ^ means XOR in java! - return x + y + z <= (radius * radius); - } - return false; - } - -} +package emu.grasscutter.scripts.data; + +import emu.grasscutter.scripts.constants.ScriptRegionShape; +import emu.grasscutter.utils.Position; +import java.util.List; +import lombok.Setter; + +@Setter +public class SceneRegion { + public int config_id; + public int shape; + public Position pos; + // for CUBIC + public Position size; + // for SPHERE + public int radius; + public int area_id; + public float height; + public List point_array; + + public transient SceneGroup group; + + public boolean contains(Position position) { + switch (shape) { + case ScriptRegionShape.CUBIC: + return (Math.abs(pos.getX() - position.getX()) <= size.getX()) + && (Math.abs(pos.getY() - position.getY()) <= size.getY()) + && (Math.abs(pos.getZ() - position.getZ()) <= size.getZ()); + case ScriptRegionShape.SPHERE: + var x = Math.pow(pos.getX() - position.getX(), 2); + var y = Math.pow(pos.getY() - position.getY(), 2); + var z = Math.pow(pos.getZ() - position.getZ(), 2); + // ^ means XOR in java! + return x + y + z <= (radius * radius); + } + return false; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneSuite.java b/src/main/java/emu/grasscutter/scripts/data/SceneSuite.java index 593970cbd..5ef52db2d 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneSuite.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneSuite.java @@ -1,62 +1,60 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -import java.util.ArrayList; -import java.util.List; - -@ToString -@Setter -public class SceneSuite { - // make it refer the default empty list to avoid NPE caused by some group - public List monsters = List.of(); - public List gadgets = List.of(); - public List triggers = List.of(); - public List regions = List.of(); - public int rand_weight; - public int[] npcs; - - public transient List sceneMonsters = List.of(); - public transient List sceneGadgets = List.of(); - public transient List sceneTriggers = List.of(); - public transient List sceneRegions = List.of(); - - public void init(SceneGroup sceneGroup) { - if (sceneGroup.monsters != null && this.monsters != null) { - this.sceneMonsters = new ArrayList<>( - this.monsters.stream() - .filter(sceneGroup.monsters::containsKey) - .map(sceneGroup.monsters::get) - .toList() - ); - } - - if (sceneGroup.gadgets != null && this.gadgets != null) { - this.sceneGadgets = new ArrayList<>( - this.gadgets.stream() - .filter(sceneGroup.gadgets::containsKey) - .map(sceneGroup.gadgets::get) - .toList() - ); - } - - if (sceneGroup.triggers != null && this.triggers != null) { - this.sceneTriggers = new ArrayList<>( - this.triggers.stream() - .filter(sceneGroup.triggers::containsKey) - .map(sceneGroup.triggers::get) - .toList() - ); - } - if (sceneGroup.regions != null && this.regions != null) { - this.sceneRegions = new ArrayList<>( - this.regions.stream() - .filter(sceneGroup.regions::containsKey) - .map(sceneGroup.regions::get) - .toList() - ); - } - - } -} +package emu.grasscutter.scripts.data; + +import java.util.ArrayList; +import java.util.List; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneSuite { + // make it refer the default empty list to avoid NPE caused by some group + public List monsters = List.of(); + public List gadgets = List.of(); + public List triggers = List.of(); + public List regions = List.of(); + public int rand_weight; + public int[] npcs; + + public transient List sceneMonsters = List.of(); + public transient List sceneGadgets = List.of(); + public transient List sceneTriggers = List.of(); + public transient List sceneRegions = List.of(); + + public void init(SceneGroup sceneGroup) { + if (sceneGroup.monsters != null && this.monsters != null) { + this.sceneMonsters = + new ArrayList<>( + this.monsters.stream() + .filter(sceneGroup.monsters::containsKey) + .map(sceneGroup.monsters::get) + .toList()); + } + + if (sceneGroup.gadgets != null && this.gadgets != null) { + this.sceneGadgets = + new ArrayList<>( + this.gadgets.stream() + .filter(sceneGroup.gadgets::containsKey) + .map(sceneGroup.gadgets::get) + .toList()); + } + + if (sceneGroup.triggers != null && this.triggers != null) { + this.sceneTriggers = + new ArrayList<>( + this.triggers.stream() + .filter(sceneGroup.triggers::containsKey) + .map(sceneGroup.triggers::get) + .toList()); + } + if (sceneGroup.regions != null && this.regions != null) { + this.sceneRegions = + new ArrayList<>( + this.regions.stream() + .filter(sceneGroup.regions::containsKey) + .map(sceneGroup.regions::get) + .toList()); + } + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java index 10da92dc7..1e477b13b 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java @@ -1,45 +1,59 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; - -@Setter -public class SceneTrigger { - public String name; - public int config_id; - public int event; - public String source; - public String condition; - public String action; - public boolean forbid_guest; - public int trigger_count; - public String tlog_tag; - - public transient SceneGroup currentGroup; - - @Override - public boolean equals(Object obj) { - if (obj instanceof SceneTrigger sceneTrigger) { - return this.name.equals(sceneTrigger.name); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public String toString() { - return "SceneTrigger{" + - "name='" + name + '\'' + - ", config_id=" + config_id + - ", event=" + event + - ", source='" + source + '\'' + - ", condition='" + condition + '\'' + - ", action='" + action + '\'' + - ", forbid_guest='" + forbid_guest + '\'' + - ", trigger_count='" + trigger_count + '\'' + - '}'; - } -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; + +@Setter +public class SceneTrigger { + public String name; + public int config_id; + public int event; + public String source; + public String condition; + public String action; + public boolean forbid_guest; + public int trigger_count; + public String tlog_tag; + + public transient SceneGroup currentGroup; + + @Override + public boolean equals(Object obj) { + if (obj instanceof SceneTrigger sceneTrigger) { + return this.name.equals(sceneTrigger.name); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return "SceneTrigger{" + + "name='" + + name + + '\'' + + ", config_id=" + + config_id + + ", event=" + + event + + ", source='" + + source + + '\'' + + ", condition='" + + condition + + '\'' + + ", action='" + + action + + '\'' + + ", forbid_guest='" + + forbid_guest + + '\'' + + ", trigger_count='" + + trigger_count + + '\'' + + '}'; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneVar.java b/src/main/java/emu/grasscutter/scripts/data/SceneVar.java index 5e9fb4d4c..c0664f234 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneVar.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneVar.java @@ -1,13 +1,13 @@ -package emu.grasscutter.scripts.data; - -import lombok.Setter; -import lombok.ToString; - -@ToString -@Setter -public class SceneVar { - public String name; - public int value; - public boolean no_refresh; - public int configId; -} +package emu.grasscutter.scripts.data; + +import lombok.Setter; +import lombok.ToString; + +@ToString +@Setter +public class SceneVar { + public String name; + public int value; + public boolean no_refresh; + public int configId; +} diff --git a/src/main/java/emu/grasscutter/scripts/data/ScriptArgs.java b/src/main/java/emu/grasscutter/scripts/data/ScriptArgs.java index 92143bae6..0c7903a2d 100644 --- a/src/main/java/emu/grasscutter/scripts/data/ScriptArgs.java +++ b/src/main/java/emu/grasscutter/scripts/data/ScriptArgs.java @@ -1,67 +1,65 @@ -package emu.grasscutter.scripts.data; - -public class ScriptArgs { - public int param1; - public int param2; - public int param3; - public int source_eid; // Source entity - public int target_eid; - - public ScriptArgs() { - - } - - public ScriptArgs(int param1) { - this.param1 = param1; - } - - public ScriptArgs(int param1, int param2) { - this.param1 = param1; - this.param2 = param2; - } - - public int getParam1() { - return param1; - } - - public ScriptArgs setParam1(int param1) { - this.param1 = param1; - return this; - } - - public int getParam2() { - return param2; - } - - public ScriptArgs setParam2(int param2) { - this.param2 = param2; - return this; - } - - public int getParam3() { - return param3; - } - - public ScriptArgs setParam3(int param3) { - this.param3 = param3; - return this; - } - - public int getSourceEntityId() { - return source_eid; - } - - public ScriptArgs setSourceEntityId(int source_eid) { - this.source_eid = source_eid; - return this; - } - - public int getTargetEntityId() { - return target_eid; - } - - public ScriptArgs setTargetEntityId(int target_eid) { - this.target_eid = target_eid; - return this; - } -} +package emu.grasscutter.scripts.data; + +public class ScriptArgs { + public int param1; + public int param2; + public int param3; + public int source_eid; // Source entity + public int target_eid; + + public ScriptArgs() {} + + public ScriptArgs(int param1) { + this.param1 = param1; + } + + public ScriptArgs(int param1, int param2) { + this.param1 = param1; + this.param2 = param2; + } + + public int getParam1() { + return param1; + } + + public ScriptArgs setParam1(int param1) { + this.param1 = param1; + return this; + } + + public int getParam2() { + return param2; + } + + public ScriptArgs setParam2(int param2) { + this.param2 = param2; + return this; + } + + public int getParam3() { + return param3; + } + + public ScriptArgs setParam3(int param3) { + this.param3 = param3; + return this; + } + + public int getSourceEntityId() { + return source_eid; + } + + public ScriptArgs setSourceEntityId(int source_eid) { + this.source_eid = source_eid; + return this; + } + + public int getTargetEntityId() { + return target_eid; + } + + public ScriptArgs setTargetEntityId(int target_eid) { + this.target_eid = target_eid; + return this; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java b/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java index 4498c1615..36df2380c 100644 --- a/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java +++ b/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java @@ -1,239 +1,246 @@ -package emu.grasscutter.scripts.serializer; - -import com.esotericsoftware.reflectasm.ConstructorAccess; -import com.esotericsoftware.reflectasm.MethodAccess; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.scripts.ScriptUtils; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.experimental.FieldDefaults; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -public class LuaSerializer implements Serializer { - - private final static Map, MethodAccess> methodAccessCache = new ConcurrentHashMap<>(); - private final static Map, ConstructorAccess> constructorCache = new ConcurrentHashMap<>(); - private final static Map, Map> fieldMetaCache = new ConcurrentHashMap<>(); - - @Override - public List toList(Class type, Object obj) { - return serializeList(type, (LuaTable) obj); - } - - @Override - public T toObject(Class type, Object obj) { - return serialize(type, (LuaTable) obj); - } - - @Override - public Map toMap(Class type, Object obj) { - return serializeMap(type, (LuaTable) obj); - } - - private Map serializeMap(Class type, LuaTable table) { - Map map = new HashMap<>(); - - if (table == null) { - return map; - } - - try { - LuaValue[] keys = table.keys(); - for (LuaValue k : keys) { - try { - LuaValue keyValue = table.get(k); - - T object = null; - - if (keyValue.istable()) { - object = serialize(type, keyValue.checktable()); - } else if (keyValue.isint()) { - object = (T) (Integer) keyValue.toint(); - } else if (keyValue.isnumber()) { - object = (T) (Float) keyValue.tofloat(); // terrible... - } else if (keyValue.isstring()) { - object = (T) keyValue.tojstring(); - } else if (keyValue.isboolean()) { - object = (T) (Boolean) keyValue.toboolean(); - } else { - object = (T) keyValue; - } - - if (object != null) { - map.put(String.valueOf(k), object); - } - } catch (Exception ex) { - - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return map; - } - - public List serializeList(Class type, LuaTable table) { - List list = new ArrayList<>(); - - if (table == null) { - return list; - } - - try { - LuaValue[] keys = table.keys(); - for (LuaValue k : keys) { - try { - LuaValue keyValue = table.get(k); - - T object = null; - - if (keyValue.istable()) { - object = serialize(type, keyValue.checktable()); - } else if (keyValue.isint()) { - object = (T) (Integer) keyValue.toint(); - } else if (keyValue.isnumber()) { - object = (T) (Float) keyValue.tofloat(); // terrible... - } else if (keyValue.isstring()) { - object = (T) keyValue.tojstring(); - } else if (keyValue.isboolean()) { - object = (T) (Boolean) keyValue.toboolean(); - } else { - object = (T) keyValue; - } - - if (object != null) { - list.add(object); - } - } catch (Exception ex) { - - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return list; - } - - public T serialize(Class type, LuaTable table) { - T object = null; - - if (type == List.class) { - try { - Class listType = (Class) type.getTypeParameters()[0].getClass(); - return (T) serializeList(listType, table); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - try { - if (!methodAccessCache.containsKey(type)) { - cacheType(type); - } - var methodAccess = methodAccessCache.get(type); - var fieldMetaMap = fieldMetaCache.get(type); - - object = (T) constructorCache.get(type).newInstance(); - - if (table == null) { - return object; - } - - LuaValue[] keys = table.keys(); - for (LuaValue k : keys) { - try { - var keyName = k.checkjstring(); - if (!fieldMetaMap.containsKey(keyName)) { - continue; - } - var fieldMeta = fieldMetaMap.get(keyName); - LuaValue keyValue = table.get(k); - - if (keyValue.istable()) { - methodAccess.invoke(object, fieldMeta.index, serialize(fieldMeta.getType(), keyValue.checktable())); - } else if (fieldMeta.getType().equals(float.class)) { - methodAccess.invoke(object, fieldMeta.index, keyValue.tofloat()); - } else if (fieldMeta.getType().equals(int.class)) { - methodAccess.invoke(object, fieldMeta.index, keyValue.toint()); - } else if (fieldMeta.getType().equals(String.class)) { - methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring()); - } else if (fieldMeta.getType().equals(boolean.class)) { - methodAccess.invoke(object, fieldMeta.index, keyValue.toboolean()); - } else { - methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring()); - } - } catch (Exception ex) { - //ex.printStackTrace(); - continue; - } - } - } catch (Exception e) { - Grasscutter.getLogger().debug(ScriptUtils.toMap(table).toString()); - e.printStackTrace(); - } - - return object; - } - - public Map cacheType(Class type) { - if (fieldMetaCache.containsKey(type)) { - return fieldMetaCache.get(type); - } - if (!constructorCache.containsKey(type)) { - constructorCache.putIfAbsent(type, ConstructorAccess.get(type)); - } - var methodAccess = Optional.ofNullable(methodAccessCache.get(type)).orElse(MethodAccess.get(type)); - methodAccessCache.putIfAbsent(type, methodAccess); - - var fieldMetaMap = new HashMap(); - var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList()); - - Arrays.stream(type.getDeclaredFields()) - .filter(field -> methodNameSet.contains(getSetterName(field.getName()))) - .forEach(field -> { - var setter = getSetterName(field.getName()); - var index = methodAccess.getIndex(setter); - fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType())); - }); - - Arrays.stream(type.getFields()) - .filter(field -> !fieldMetaMap.containsKey(field.getName())) - .filter(field -> methodNameSet.contains(getSetterName(field.getName()))) - .forEach(field -> { - var setter = getSetterName(field.getName()); - var index = methodAccess.getIndex(setter); - fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType())); - }); - - fieldMetaCache.put(type, fieldMetaMap); - return fieldMetaMap; - } - - public String getSetterName(String fieldName) { - if (fieldName == null || fieldName.length() == 0) { - return null; - } - if (fieldName.length() == 1) { - return "set" + fieldName.toUpperCase(); - } - return "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); - } - - @Data - @AllArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE) - static class FieldMeta { - String name; - String setter; - int index; - Class type; - } -} +package emu.grasscutter.scripts.serializer; + +import com.esotericsoftware.reflectasm.ConstructorAccess; +import com.esotericsoftware.reflectasm.MethodAccess; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.scripts.ScriptUtils; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.FieldDefaults; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; + +public class LuaSerializer implements Serializer { + + private static final Map, MethodAccess> methodAccessCache = new ConcurrentHashMap<>(); + private static final Map, ConstructorAccess> constructorCache = + new ConcurrentHashMap<>(); + private static final Map, Map> fieldMetaCache = + new ConcurrentHashMap<>(); + + @Override + public List toList(Class type, Object obj) { + return serializeList(type, (LuaTable) obj); + } + + @Override + public T toObject(Class type, Object obj) { + return serialize(type, (LuaTable) obj); + } + + @Override + public Map toMap(Class type, Object obj) { + return serializeMap(type, (LuaTable) obj); + } + + private Map serializeMap(Class type, LuaTable table) { + Map map = new HashMap<>(); + + if (table == null) { + return map; + } + + try { + LuaValue[] keys = table.keys(); + for (LuaValue k : keys) { + try { + LuaValue keyValue = table.get(k); + + T object = null; + + if (keyValue.istable()) { + object = serialize(type, keyValue.checktable()); + } else if (keyValue.isint()) { + object = (T) (Integer) keyValue.toint(); + } else if (keyValue.isnumber()) { + object = (T) (Float) keyValue.tofloat(); // terrible... + } else if (keyValue.isstring()) { + object = (T) keyValue.tojstring(); + } else if (keyValue.isboolean()) { + object = (T) (Boolean) keyValue.toboolean(); + } else { + object = (T) keyValue; + } + + if (object != null) { + map.put(String.valueOf(k), object); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + return map; + } + + public List serializeList(Class type, LuaTable table) { + List list = new ArrayList<>(); + + if (table == null) { + return list; + } + + try { + LuaValue[] keys = table.keys(); + for (LuaValue k : keys) { + try { + LuaValue keyValue = table.get(k); + + T object = null; + + if (keyValue.istable()) { + object = serialize(type, keyValue.checktable()); + } else if (keyValue.isint()) { + object = (T) (Integer) keyValue.toint(); + } else if (keyValue.isnumber()) { + object = (T) (Float) keyValue.tofloat(); // terrible... + } else if (keyValue.isstring()) { + object = (T) keyValue.tojstring(); + } else if (keyValue.isboolean()) { + object = (T) (Boolean) keyValue.toboolean(); + } else { + object = (T) keyValue; + } + + if (object != null) { + list.add(object); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + return list; + } + + public T serialize(Class type, LuaTable table) { + T object = null; + + if (type == List.class) { + try { + Class listType = (Class) type.getTypeParameters()[0].getClass(); + return (T) serializeList(listType, table); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + try { + if (!methodAccessCache.containsKey(type)) { + cacheType(type); + } + var methodAccess = methodAccessCache.get(type); + var fieldMetaMap = fieldMetaCache.get(type); + + object = (T) constructorCache.get(type).newInstance(); + + if (table == null) { + return object; + } + + LuaValue[] keys = table.keys(); + for (LuaValue k : keys) { + try { + var keyName = k.checkjstring(); + if (!fieldMetaMap.containsKey(keyName)) { + continue; + } + var fieldMeta = fieldMetaMap.get(keyName); + LuaValue keyValue = table.get(k); + + if (keyValue.istable()) { + methodAccess.invoke( + object, fieldMeta.index, serialize(fieldMeta.getType(), keyValue.checktable())); + } else if (fieldMeta.getType().equals(float.class)) { + methodAccess.invoke(object, fieldMeta.index, keyValue.tofloat()); + } else if (fieldMeta.getType().equals(int.class)) { + methodAccess.invoke(object, fieldMeta.index, keyValue.toint()); + } else if (fieldMeta.getType().equals(String.class)) { + methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring()); + } else if (fieldMeta.getType().equals(boolean.class)) { + methodAccess.invoke(object, fieldMeta.index, keyValue.toboolean()); + } else { + methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring()); + } + } catch (Exception ex) { + // ex.printStackTrace(); + continue; + } + } + } catch (Exception e) { + Grasscutter.getLogger().debug(ScriptUtils.toMap(table).toString()); + e.printStackTrace(); + } + + return object; + } + + public Map cacheType(Class type) { + if (fieldMetaCache.containsKey(type)) { + return fieldMetaCache.get(type); + } + if (!constructorCache.containsKey(type)) { + constructorCache.putIfAbsent(type, ConstructorAccess.get(type)); + } + var methodAccess = + Optional.ofNullable(methodAccessCache.get(type)).orElse(MethodAccess.get(type)); + methodAccessCache.putIfAbsent(type, methodAccess); + + var fieldMetaMap = new HashMap(); + var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList()); + + Arrays.stream(type.getDeclaredFields()) + .filter(field -> methodNameSet.contains(getSetterName(field.getName()))) + .forEach( + field -> { + var setter = getSetterName(field.getName()); + var index = methodAccess.getIndex(setter); + fieldMetaMap.put( + field.getName(), new FieldMeta(field.getName(), setter, index, field.getType())); + }); + + Arrays.stream(type.getFields()) + .filter(field -> !fieldMetaMap.containsKey(field.getName())) + .filter(field -> methodNameSet.contains(getSetterName(field.getName()))) + .forEach( + field -> { + var setter = getSetterName(field.getName()); + var index = methodAccess.getIndex(setter); + fieldMetaMap.put( + field.getName(), new FieldMeta(field.getName(), setter, index, field.getType())); + }); + + fieldMetaCache.put(type, fieldMetaMap); + return fieldMetaMap; + } + + public String getSetterName(String fieldName) { + if (fieldName == null || fieldName.length() == 0) { + return null; + } + if (fieldName.length() == 1) { + return "set" + fieldName.toUpperCase(); + } + return "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); + } + + @Data + @AllArgsConstructor + @FieldDefaults(level = AccessLevel.PRIVATE) + static class FieldMeta { + String name; + String setter; + int index; + Class type; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/serializer/LuaTableJacksonSerializer.java b/src/main/java/emu/grasscutter/scripts/serializer/LuaTableJacksonSerializer.java index ea2f314f1..1fcd4e4d1 100644 --- a/src/main/java/emu/grasscutter/scripts/serializer/LuaTableJacksonSerializer.java +++ b/src/main/java/emu/grasscutter/scripts/serializer/LuaTableJacksonSerializer.java @@ -1,183 +1,195 @@ -package emu.grasscutter.scripts.serializer; - -import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.annotation.Nulls; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.type.CollectionType; -import com.fasterxml.jackson.databind.type.MapType; -import emu.grasscutter.Grasscutter; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -import java.io.IOException; -import java.util.*; - -public class LuaTableJacksonSerializer extends JsonSerializer implements Serializer { - - private static ObjectMapper objectMapper; - - public LuaTableJacksonSerializer() { - if (objectMapper == null) { - objectMapper = new ObjectMapper(); - objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true); - // Some properties in Lua table but not in java field - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - objectMapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)); - SimpleModule luaSerializeModule = new SimpleModule(); - luaSerializeModule.addSerializer(LuaTable.class, this); - objectMapper.registerModule(luaSerializeModule); - } - } - - @Override - public void serialize(LuaTable value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - if (value == null || value.isnil()) { - gen.writeNull(); - return; - } - - // Detect table type - boolean isArray = false; - LuaValue[] keys = value.keys(); - if (keys.length == 0) { - gen.writeNull(); - return; - } - - int count = 0; - for (int i = 0; i < keys.length; i++) { - if (!keys[i].isint() || (i + 1) != keys[i].toint()) { - break; - } else { - count++; - } - } - - if (count == keys.length) { - isArray = true; - } - - if (isArray) { - gen.writeStartArray(); - for (LuaValue key : keys) { - LuaValue luaValue = value.get(key); - if (luaValue.isnil()) { - gen.writeNull(); - } else if (luaValue.isboolean()) { - gen.writeBoolean(luaValue.toboolean()); - } else if (luaValue.isint()) { - gen.writeNumber(luaValue.toint()); - } else if (luaValue.islong()) { - gen.writeNumber(luaValue.tolong()); - } else if (luaValue.isnumber()) { - gen.writeNumber(luaValue.tofloat()); - } else if (luaValue.isstring()) { - gen.writeString(luaValue.tojstring()); - } else if (luaValue.istable()) { - serialize(luaValue.checktable(), gen, serializers); - } - } - gen.writeEndArray(); - } else { - gen.writeStartObject(); - for (LuaValue key : keys) { - String keyStr = key.toString(); - LuaValue luaValue = value.get(key); - if (luaValue.isnil()) { - gen.writeNullField(keyStr); - } else if (luaValue.isboolean()) { - gen.writeBooleanField(keyStr, luaValue.toboolean()); - } else if (luaValue.isint()) { - gen.writeNumberField(keyStr, luaValue.toint()); - } else if (luaValue.islong()) { - gen.writeNumberField(keyStr, luaValue.tolong()); - } else if (luaValue.isnumber()) { - gen.writeNumberField(keyStr, luaValue.tofloat()); - } else if (luaValue.isstring()) { - gen.writeStringField(keyStr, luaValue.tojstring()); - } else if (luaValue.istable()) { - gen.writeFieldName(keyStr); - serialize(luaValue.checktable(), gen, serializers); - } - } - gen.writeEndObject(); - } - - gen.flush(); - gen.close(); - } - - @Override - public List toList(Class type, Object obj) { - List list = new ArrayList<>(); - if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { - return list; - } - - CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); - JsonNode jsonNode = objectMapper.valueToTree(luaTable); - Grasscutter.getLogger().trace("[LuaTableToList] className={},data={}", type.getCanonicalName(), jsonNode.toString()); - if (jsonNode.isEmpty()) { - return list; - } - if (jsonNode.isArray()) { - try { - Object o = objectMapper.treeToValue(jsonNode, collectionType); - if (o != null) { - list = (ArrayList) o; - } - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - } else if (jsonNode.isObject()) { - Iterator> fields = jsonNode.fields(); - List nodes = new ArrayList<>(); - while (fields.hasNext()) { - Map.Entry next = fields.next(); - nodes.add(next.getValue()); - } - list = objectMapper.convertValue(nodes, collectionType); - } - return list; - } - - @Override - public T toObject(Class type, Object obj) { - if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { - return null; - } - - JsonNode jsonNode = objectMapper.valueToTree(luaTable); - Grasscutter.getLogger().trace("[LuaTableToObject] className={},data={}", type.getCanonicalName(), jsonNode.toString()); - try { - return objectMapper.treeToValue(jsonNode, type); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Map toMap(Class type, Object obj) { - HashMap map = new HashMap<>(); - if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { - return map; - } - - MapType mapStringType = objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, type); - JsonNode jsonNode = objectMapper.valueToTree(luaTable); - Grasscutter.getLogger().trace("[LuaTableToMap] className={},data={}", type.getCanonicalName(), jsonNode.toString()); - try { - Object o = objectMapper.treeToValue(jsonNode, mapStringType); - if (o != null) { - return (HashMap) o; - } - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return map; - } -} +package emu.grasscutter.scripts.serializer; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.fasterxml.jackson.databind.type.MapType; +import emu.grasscutter.Grasscutter; +import java.io.IOException; +import java.util.*; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; + +public class LuaTableJacksonSerializer extends JsonSerializer implements Serializer { + + private static ObjectMapper objectMapper; + + public LuaTableJacksonSerializer() { + if (objectMapper == null) { + objectMapper = new ObjectMapper(); + objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true); + // Some properties in Lua table but not in java field + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper + .configOverride(List.class) + .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)); + SimpleModule luaSerializeModule = new SimpleModule(); + luaSerializeModule.addSerializer(LuaTable.class, this); + objectMapper.registerModule(luaSerializeModule); + } + } + + @Override + public void serialize(LuaTable value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + if (value == null || value.isnil()) { + gen.writeNull(); + return; + } + + // Detect table type + boolean isArray = false; + LuaValue[] keys = value.keys(); + if (keys.length == 0) { + gen.writeNull(); + return; + } + + int count = 0; + for (int i = 0; i < keys.length; i++) { + if (!keys[i].isint() || (i + 1) != keys[i].toint()) { + break; + } else { + count++; + } + } + + if (count == keys.length) { + isArray = true; + } + + if (isArray) { + gen.writeStartArray(); + for (LuaValue key : keys) { + LuaValue luaValue = value.get(key); + if (luaValue.isnil()) { + gen.writeNull(); + } else if (luaValue.isboolean()) { + gen.writeBoolean(luaValue.toboolean()); + } else if (luaValue.isint()) { + gen.writeNumber(luaValue.toint()); + } else if (luaValue.islong()) { + gen.writeNumber(luaValue.tolong()); + } else if (luaValue.isnumber()) { + gen.writeNumber(luaValue.tofloat()); + } else if (luaValue.isstring()) { + gen.writeString(luaValue.tojstring()); + } else if (luaValue.istable()) { + serialize(luaValue.checktable(), gen, serializers); + } + } + gen.writeEndArray(); + } else { + gen.writeStartObject(); + for (LuaValue key : keys) { + String keyStr = key.toString(); + LuaValue luaValue = value.get(key); + if (luaValue.isnil()) { + gen.writeNullField(keyStr); + } else if (luaValue.isboolean()) { + gen.writeBooleanField(keyStr, luaValue.toboolean()); + } else if (luaValue.isint()) { + gen.writeNumberField(keyStr, luaValue.toint()); + } else if (luaValue.islong()) { + gen.writeNumberField(keyStr, luaValue.tolong()); + } else if (luaValue.isnumber()) { + gen.writeNumberField(keyStr, luaValue.tofloat()); + } else if (luaValue.isstring()) { + gen.writeStringField(keyStr, luaValue.tojstring()); + } else if (luaValue.istable()) { + gen.writeFieldName(keyStr); + serialize(luaValue.checktable(), gen, serializers); + } + } + gen.writeEndObject(); + } + + gen.flush(); + gen.close(); + } + + @Override + public List toList(Class type, Object obj) { + List list = new ArrayList<>(); + if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { + return list; + } + + CollectionType collectionType = + objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type); + JsonNode jsonNode = objectMapper.valueToTree(luaTable); + Grasscutter.getLogger() + .trace( + "[LuaTableToList] className={},data={}", type.getCanonicalName(), jsonNode.toString()); + if (jsonNode.isEmpty()) { + return list; + } + if (jsonNode.isArray()) { + try { + Object o = objectMapper.treeToValue(jsonNode, collectionType); + if (o != null) { + list = (ArrayList) o; + } + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } else if (jsonNode.isObject()) { + Iterator> fields = jsonNode.fields(); + List nodes = new ArrayList<>(); + while (fields.hasNext()) { + Map.Entry next = fields.next(); + nodes.add(next.getValue()); + } + list = objectMapper.convertValue(nodes, collectionType); + } + return list; + } + + @Override + public T toObject(Class type, Object obj) { + if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { + return null; + } + + JsonNode jsonNode = objectMapper.valueToTree(luaTable); + Grasscutter.getLogger() + .trace( + "[LuaTableToObject] className={},data={}", + type.getCanonicalName(), + jsonNode.toString()); + try { + return objectMapper.treeToValue(jsonNode, type); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Map toMap(Class type, Object obj) { + HashMap map = new HashMap<>(); + if (!(obj instanceof LuaTable luaTable) || luaTable.isnil()) { + return map; + } + + MapType mapStringType = + objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, type); + JsonNode jsonNode = objectMapper.valueToTree(luaTable); + Grasscutter.getLogger() + .trace( + "[LuaTableToMap] className={},data={}", type.getCanonicalName(), jsonNode.toString()); + try { + Object o = objectMapper.treeToValue(jsonNode, mapStringType); + if (o != null) { + return (HashMap) o; + } + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return map; + } +} diff --git a/src/main/java/emu/grasscutter/scripts/serializer/Serializer.java b/src/main/java/emu/grasscutter/scripts/serializer/Serializer.java index d9ea2d6ec..f67b926f2 100644 --- a/src/main/java/emu/grasscutter/scripts/serializer/Serializer.java +++ b/src/main/java/emu/grasscutter/scripts/serializer/Serializer.java @@ -1,14 +1,13 @@ -package emu.grasscutter.scripts.serializer; - -import java.util.List; -import java.util.Map; - - -public interface Serializer { - - List toList(Class type, Object obj); - - T toObject(Class type, Object obj); - - Map toMap(Class type, Object obj); -} +package emu.grasscutter.scripts.serializer; + +import java.util.List; +import java.util.Map; + +public interface Serializer { + + List toList(Class type, Object obj); + + T toObject(Class type, Object obj); + + Map toMap(Class type, Object obj); +} diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java index df5d4d3bc..1708149ac 100644 --- a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java @@ -1,40 +1,38 @@ -package emu.grasscutter.scripts.service; - -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.scripts.SceneScriptManager; -import emu.grasscutter.scripts.listener.ScriptMonsterListener; - -import java.util.ArrayList; -import java.util.List; - -public class ScriptMonsterSpawnService { - - public final List onMonsterCreatedListener = new ArrayList<>(); - public final List onMonsterDeadListener = new ArrayList<>(); - private final SceneScriptManager sceneScriptManager; - - public ScriptMonsterSpawnService(SceneScriptManager sceneScriptManager) { - this.sceneScriptManager = sceneScriptManager; - } - - public void addMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener) { - onMonsterCreatedListener.add(scriptMonsterListener); - } - - public void addMonsterDeadListener(ScriptMonsterListener scriptMonsterListener) { - onMonsterDeadListener.add(scriptMonsterListener); - } - - public void removeMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener) { - onMonsterCreatedListener.remove(scriptMonsterListener); - } - - public void removeMonsterDeadListener(ScriptMonsterListener scriptMonsterListener) { - onMonsterDeadListener.remove(scriptMonsterListener); - } - - public void onMonsterDead(EntityMonster entityMonster) { - onMonsterDeadListener.forEach(l -> l.onNotify(entityMonster)); - } - -} +package emu.grasscutter.scripts.service; + +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.scripts.SceneScriptManager; +import emu.grasscutter.scripts.listener.ScriptMonsterListener; +import java.util.ArrayList; +import java.util.List; + +public class ScriptMonsterSpawnService { + + public final List onMonsterCreatedListener = new ArrayList<>(); + public final List onMonsterDeadListener = new ArrayList<>(); + private final SceneScriptManager sceneScriptManager; + + public ScriptMonsterSpawnService(SceneScriptManager sceneScriptManager) { + this.sceneScriptManager = sceneScriptManager; + } + + public void addMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener) { + onMonsterCreatedListener.add(scriptMonsterListener); + } + + public void addMonsterDeadListener(ScriptMonsterListener scriptMonsterListener) { + onMonsterDeadListener.add(scriptMonsterListener); + } + + public void removeMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener) { + onMonsterCreatedListener.remove(scriptMonsterListener); + } + + public void removeMonsterDeadListener(ScriptMonsterListener scriptMonsterListener) { + onMonsterDeadListener.remove(scriptMonsterListener); + } + + public void onMonsterDead(EntityMonster entityMonster) { + onMonsterDeadListener.forEach(l -> l.onNotify(entityMonster)); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java index e093fdf0f..ba04d6cb9 100644 --- a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java @@ -1,89 +1,99 @@ -package emu.grasscutter.scripts.service; - -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.scripts.SceneScriptManager; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.SceneMonster; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.scripts.listener.ScriptMonsterListener; - -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; - -public class ScriptMonsterTideService { - private final SceneScriptManager sceneScriptManager; - private final SceneGroup currentGroup; - private final AtomicInteger monsterAlive; - private final AtomicInteger monsterTideCount; - private final AtomicInteger monsterKillCount; - private final int monsterSceneLimit; - private final ConcurrentLinkedQueue monsterConfigOrders; - private final OnMonsterCreated onMonsterCreated = new OnMonsterCreated(); - private final OnMonsterDead onMonsterDead = new OnMonsterDead(); - - public ScriptMonsterTideService(SceneScriptManager sceneScriptManager, - SceneGroup group, int tideCount, int monsterSceneLimit, Integer[] ordersConfigId) { - this.sceneScriptManager = sceneScriptManager; - this.currentGroup = group; - this.monsterSceneLimit = monsterSceneLimit; - this.monsterTideCount = new AtomicInteger(tideCount); - this.monsterKillCount = new AtomicInteger(0); - this.monsterAlive = new AtomicInteger(0); - this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); - - this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(onMonsterCreated); - this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(onMonsterDead); - // spawn the first turn - for (int i = 0; i < this.monsterSceneLimit; i++) { - sceneScriptManager.addEntity(this.sceneScriptManager.createMonster(group.id, group.block_id, getNextMonster())); - } - } - - public SceneMonster getNextMonster() { - var nextId = this.monsterConfigOrders.poll(); - if (currentGroup.monsters.containsKey(nextId)) { - return currentGroup.monsters.get(nextId); - } - // TODO some monster config_id do not exist in groups, so temporarily set it to the first - return currentGroup.monsters.values().stream().findFirst().orElse(null); - } - - public void unload() { - this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterCreatedListener(onMonsterCreated); - this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead); - } - - public class OnMonsterCreated implements ScriptMonsterListener { - @Override - public void onNotify(EntityMonster sceneMonster) { - if (monsterSceneLimit > 0) { - monsterAlive.incrementAndGet(); - monsterTideCount.decrementAndGet(); - } - } - } - - public class OnMonsterDead implements ScriptMonsterListener { - @Override - public void onNotify(EntityMonster sceneMonster) { - if (monsterSceneLimit <= 0) { - return; - } - if (monsterAlive.decrementAndGet() >= monsterSceneLimit) { - // maybe not happen - return; - } - monsterKillCount.incrementAndGet(); - if (monsterTideCount.get() > 0) { - // add more - sceneScriptManager.addEntity(sceneScriptManager.createMonster(currentGroup.id, currentGroup.block_id, getNextMonster())); - } - // spawn the last turn of monsters - // fix the 5-2 - sceneScriptManager.callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(monsterKillCount.get())); - } - - } -} +package emu.grasscutter.scripts.service; + +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.scripts.SceneScriptManager; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.SceneMonster; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.scripts.listener.ScriptMonsterListener; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; + +public class ScriptMonsterTideService { + private final SceneScriptManager sceneScriptManager; + private final SceneGroup currentGroup; + private final AtomicInteger monsterAlive; + private final AtomicInteger monsterTideCount; + private final AtomicInteger monsterKillCount; + private final int monsterSceneLimit; + private final ConcurrentLinkedQueue monsterConfigOrders; + private final OnMonsterCreated onMonsterCreated = new OnMonsterCreated(); + private final OnMonsterDead onMonsterDead = new OnMonsterDead(); + + public ScriptMonsterTideService( + SceneScriptManager sceneScriptManager, + SceneGroup group, + int tideCount, + int monsterSceneLimit, + Integer[] ordersConfigId) { + this.sceneScriptManager = sceneScriptManager; + this.currentGroup = group; + this.monsterSceneLimit = monsterSceneLimit; + this.monsterTideCount = new AtomicInteger(tideCount); + this.monsterKillCount = new AtomicInteger(0); + this.monsterAlive = new AtomicInteger(0); + this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); + + this.sceneScriptManager + .getScriptMonsterSpawnService() + .addMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(onMonsterDead); + // spawn the first turn + for (int i = 0; i < this.monsterSceneLimit; i++) { + sceneScriptManager.addEntity( + this.sceneScriptManager.createMonster(group.id, group.block_id, getNextMonster())); + } + } + + public SceneMonster getNextMonster() { + var nextId = this.monsterConfigOrders.poll(); + if (currentGroup.monsters.containsKey(nextId)) { + return currentGroup.monsters.get(nextId); + } + // TODO some monster config_id do not exist in groups, so temporarily set it to the first + return currentGroup.monsters.values().stream().findFirst().orElse(null); + } + + public void unload() { + this.sceneScriptManager + .getScriptMonsterSpawnService() + .removeMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead); + } + + public class OnMonsterCreated implements ScriptMonsterListener { + @Override + public void onNotify(EntityMonster sceneMonster) { + if (monsterSceneLimit > 0) { + monsterAlive.incrementAndGet(); + monsterTideCount.decrementAndGet(); + } + } + } + + public class OnMonsterDead implements ScriptMonsterListener { + @Override + public void onNotify(EntityMonster sceneMonster) { + if (monsterSceneLimit <= 0) { + return; + } + if (monsterAlive.decrementAndGet() >= monsterSceneLimit) { + // maybe not happen + return; + } + monsterKillCount.incrementAndGet(); + if (monsterTideCount.get() > 0) { + // add more + sceneScriptManager.addEntity( + sceneScriptManager.createMonster( + currentGroup.id, currentGroup.block_id, getNextMonster())); + } + // spawn the last turn of monsters + // fix the 5-2 + sceneScriptManager.callEvent( + EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(monsterKillCount.get())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/event/Cancellable.java b/src/main/java/emu/grasscutter/server/event/Cancellable.java index 0296f0b36..462db7e00 100644 --- a/src/main/java/emu/grasscutter/server/event/Cancellable.java +++ b/src/main/java/emu/grasscutter/server/event/Cancellable.java @@ -1,8 +1,6 @@ -package emu.grasscutter.server.event; - -/** - * Implementing this interface marks an event as cancellable. - */ -public interface Cancellable { - void cancel(); -} +package emu.grasscutter.server.event; + +/** Implementing this interface marks an event as cancellable. */ +public interface Cancellable { + void cancel(); +} diff --git a/src/main/java/emu/grasscutter/server/event/Event.java b/src/main/java/emu/grasscutter/server/event/Event.java index 8e32ed78f..a5f4827e3 100644 --- a/src/main/java/emu/grasscutter/server/event/Event.java +++ b/src/main/java/emu/grasscutter/server/event/Event.java @@ -1,32 +1,23 @@ -package emu.grasscutter.server.event; - -import emu.grasscutter.Grasscutter; - -/** - * A generic server event. - */ -public abstract class Event { - private boolean cancelled = false; - - /** - * Return the cancelled state of the event. - */ - public boolean isCanceled() { - return this.cancelled; - } - - /** - * Cancels the event if possible. - */ - public void cancel() { - if (this instanceof Cancellable) - this.cancelled = true; - } - - /** - * Pushes this event to all listeners. - */ - public void call() { - Grasscutter.getPluginManager().invokeEvent(this); - } -} +package emu.grasscutter.server.event; + +import emu.grasscutter.Grasscutter; + +/** A generic server event. */ +public abstract class Event { + private boolean cancelled = false; + + /** Return the cancelled state of the event. */ + public boolean isCanceled() { + return this.cancelled; + } + + /** Cancels the event if possible. */ + public void cancel() { + if (this instanceof Cancellable) this.cancelled = true; + } + + /** Pushes this event to all listeners. */ + public void call() { + Grasscutter.getPluginManager().invokeEvent(this); + } +} diff --git a/src/main/java/emu/grasscutter/server/event/EventHandler.java b/src/main/java/emu/grasscutter/server/event/EventHandler.java index 00bd2ace0..373a5074e 100644 --- a/src/main/java/emu/grasscutter/server/event/EventHandler.java +++ b/src/main/java/emu/grasscutter/server/event/EventHandler.java @@ -1,92 +1,90 @@ -package emu.grasscutter.server.event; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.plugin.Plugin; -import emu.grasscutter.utils.EventConsumer; - -public final class EventHandler { - private final Class eventClass; - private EventConsumer listener; - private HandlerPriority priority; - private boolean handleCanceled; - - public EventHandler(Class eventClass) { - this.eventClass = eventClass; - } - - /** - * Gets which event this handler is handling. - * - * @return An event class. - */ - public Class handles() { - return this.eventClass; - } - - /** - * Returns the callback for the handler. - * - * @return A consumer callback. - */ - public EventConsumer getCallback() { - return this.listener; - } - - /** - * Returns the handler's priority. - * - * @return The priority of the handler. - */ - public HandlerPriority getPriority() { - return this.priority; - } - - /** - * Returns if the handler will ignore cancelled events. - * - * @return The ignore cancelled state. - */ - public boolean ignoresCanceled() { - return this.handleCanceled; - } - - /** - * Sets the callback method for when the event is invoked. - * - * @param listener An event handler method. - * @return Method chaining. - */ - public EventHandler listener(EventConsumer listener) { - this.listener = listener; - return this; - } - - /** - * Changes the handler's priority in handling events. - * - * @param priority The priority of the handler. - * @return Method chaining. - */ - public EventHandler priority(HandlerPriority priority) { - this.priority = priority; - return this; - } - - /** - * Sets if the handler will ignore cancelled events. - * - * @param ignore If the handler should ignore cancelled events. - * @return Method chaining. - */ - public EventHandler ignore(boolean ignore) { - this.handleCanceled = ignore; - return this; - } - - /** - * Registers the handler into the PluginManager. - */ - public void register(Plugin plugin) { - Grasscutter.getPluginManager().registerListener(plugin, this); - } -} +package emu.grasscutter.server.event; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.plugin.Plugin; +import emu.grasscutter.utils.EventConsumer; + +public final class EventHandler { + private final Class eventClass; + private EventConsumer listener; + private HandlerPriority priority; + private boolean handleCanceled; + + public EventHandler(Class eventClass) { + this.eventClass = eventClass; + } + + /** + * Gets which event this handler is handling. + * + * @return An event class. + */ + public Class handles() { + return this.eventClass; + } + + /** + * Returns the callback for the handler. + * + * @return A consumer callback. + */ + public EventConsumer getCallback() { + return this.listener; + } + + /** + * Returns the handler's priority. + * + * @return The priority of the handler. + */ + public HandlerPriority getPriority() { + return this.priority; + } + + /** + * Returns if the handler will ignore cancelled events. + * + * @return The ignore cancelled state. + */ + public boolean ignoresCanceled() { + return this.handleCanceled; + } + + /** + * Sets the callback method for when the event is invoked. + * + * @param listener An event handler method. + * @return Method chaining. + */ + public EventHandler listener(EventConsumer listener) { + this.listener = listener; + return this; + } + + /** + * Changes the handler's priority in handling events. + * + * @param priority The priority of the handler. + * @return Method chaining. + */ + public EventHandler priority(HandlerPriority priority) { + this.priority = priority; + return this; + } + + /** + * Sets if the handler will ignore cancelled events. + * + * @param ignore If the handler should ignore cancelled events. + * @return Method chaining. + */ + public EventHandler ignore(boolean ignore) { + this.handleCanceled = ignore; + return this; + } + + /** Registers the handler into the PluginManager. */ + public void register(Plugin plugin) { + Grasscutter.getPluginManager().registerListener(plugin, this); + } +} diff --git a/src/main/java/emu/grasscutter/server/event/HandlerPriority.java b/src/main/java/emu/grasscutter/server/event/HandlerPriority.java index 18891879f..29e252851 100644 --- a/src/main/java/emu/grasscutter/server/event/HandlerPriority.java +++ b/src/main/java/emu/grasscutter/server/event/HandlerPriority.java @@ -1,18 +1,12 @@ -package emu.grasscutter.server.event; - -public enum HandlerPriority { - /** - * The handler will be called before every other handler. - */ - HIGH, - - /** - * The handler will be called the same time as other handlers. - */ - NORMAL, - - /** - * The handler will be called after every other handler. - */ - LOW -} +package emu.grasscutter.server.event; + +public enum HandlerPriority { + /** The handler will be called before every other handler. */ + HIGH, + + /** The handler will be called the same time as other handlers. */ + NORMAL, + + /** The handler will be called after every other handler. */ + LOW +} diff --git a/src/main/java/emu/grasscutter/server/event/dispatch/QueryAllRegionsEvent.java b/src/main/java/emu/grasscutter/server/event/dispatch/QueryAllRegionsEvent.java index 937f9f8f7..e231e32ca 100644 --- a/src/main/java/emu/grasscutter/server/event/dispatch/QueryAllRegionsEvent.java +++ b/src/main/java/emu/grasscutter/server/event/dispatch/QueryAllRegionsEvent.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.event.dispatch; - -import emu.grasscutter.server.event.types.ServerEvent; - -public final class QueryAllRegionsEvent extends ServerEvent { - private String regionList; - - public QueryAllRegionsEvent(String regionList) { - super(Type.DISPATCH); - - this.regionList = regionList; - } - - public String getRegionList() { - return this.regionList; - } - - public void setRegionList(String regionList) { - this.regionList = regionList; - } -} +package emu.grasscutter.server.event.dispatch; + +import emu.grasscutter.server.event.types.ServerEvent; + +public final class QueryAllRegionsEvent extends ServerEvent { + private String regionList; + + public QueryAllRegionsEvent(String regionList) { + super(Type.DISPATCH); + + this.regionList = regionList; + } + + public String getRegionList() { + return this.regionList; + } + + public void setRegionList(String regionList) { + this.regionList = regionList; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/dispatch/QueryCurrentRegionEvent.java b/src/main/java/emu/grasscutter/server/event/dispatch/QueryCurrentRegionEvent.java index 6ae59362d..7adb29900 100644 --- a/src/main/java/emu/grasscutter/server/event/dispatch/QueryCurrentRegionEvent.java +++ b/src/main/java/emu/grasscutter/server/event/dispatch/QueryCurrentRegionEvent.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.event.dispatch; - -import emu.grasscutter.server.event.types.ServerEvent; - -public final class QueryCurrentRegionEvent extends ServerEvent { - private String regionInfo; - - public QueryCurrentRegionEvent(String regionInfo) { - super(Type.DISPATCH); - - this.regionInfo = regionInfo; - } - - public String getRegionInfo() { - return this.regionInfo; - } - - public void setRegionInfo(String regionInfo) { - this.regionInfo = regionInfo; - } -} +package emu.grasscutter.server.event.dispatch; + +import emu.grasscutter.server.event.types.ServerEvent; + +public final class QueryCurrentRegionEvent extends ServerEvent { + private String regionInfo; + + public QueryCurrentRegionEvent(String regionInfo) { + super(Type.DISPATCH); + + this.regionInfo = regionInfo; + } + + public String getRegionInfo() { + return this.regionInfo; + } + + public void setRegionInfo(String regionInfo) { + this.regionInfo = regionInfo; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/entity/EntityDamageEvent.java b/src/main/java/emu/grasscutter/server/event/entity/EntityDamageEvent.java index 58eb802da..a27586afc 100644 --- a/src/main/java/emu/grasscutter/server/event/entity/EntityDamageEvent.java +++ b/src/main/java/emu/grasscutter/server/event/entity/EntityDamageEvent.java @@ -1,33 +1,30 @@ -package emu.grasscutter.server.event.entity; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.EntityEvent; - -import javax.annotation.Nullable; - -public final class EntityDamageEvent extends EntityEvent implements Cancellable { - @Nullable - private final GameEntity damager; - private float damage; - - public EntityDamageEvent(GameEntity entity, float damage, @Nullable GameEntity damager) { - super(entity); - - this.damage = damage; - this.damager = damager; - } - - public float getDamage() { - return this.damage; - } - - public void setDamage(float damage) { - this.damage = damage; - } - - @Nullable - public GameEntity getDamager() { - return this.damager; - } -} +package emu.grasscutter.server.event.entity; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.EntityEvent; +import javax.annotation.Nullable; + +public final class EntityDamageEvent extends EntityEvent implements Cancellable { + @Nullable private final GameEntity damager; + private float damage; + + public EntityDamageEvent(GameEntity entity, float damage, @Nullable GameEntity damager) { + super(entity); + + this.damage = damage; + this.damager = damager; + } + + public float getDamage() { + return this.damage; + } + + public void setDamage(float damage) { + this.damage = damage; + } + + @Nullable public GameEntity getDamager() { + return this.damager; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/entity/EntityDeathEvent.java b/src/main/java/emu/grasscutter/server/event/entity/EntityDeathEvent.java index ead999907..d25dda588 100644 --- a/src/main/java/emu/grasscutter/server/event/entity/EntityDeathEvent.java +++ b/src/main/java/emu/grasscutter/server/event/entity/EntityDeathEvent.java @@ -1,23 +1,19 @@ -package emu.grasscutter.server.event.entity; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.server.event.types.EntityEvent; -import emu.grasscutter.utils.Location; -import lombok.Getter; - -import javax.annotation.Nullable; - -public final class EntityDeathEvent extends EntityEvent { - @Getter - private final Location deathLocation; - @Getter - @Nullable - private final GameEntity killer; - - public EntityDeathEvent(GameEntity entity, int killerId) { - super(entity); - - this.deathLocation = new Location(entity.getScene(), entity.getPosition()); - this.killer = entity.getScene().getEntityById(killerId); - } -} +package emu.grasscutter.server.event.entity; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.server.event.types.EntityEvent; +import emu.grasscutter.utils.Location; +import javax.annotation.Nullable; +import lombok.Getter; + +public final class EntityDeathEvent extends EntityEvent { + @Getter private final Location deathLocation; + @Getter @Nullable private final GameEntity killer; + + public EntityDeathEvent(GameEntity entity, int killerId) { + super(entity); + + this.deathLocation = new Location(entity.getScene(), entity.getPosition()); + this.killer = entity.getScene().getEntityById(killerId); + } +} diff --git a/src/main/java/emu/grasscutter/server/event/entity/EntityMoveEvent.java b/src/main/java/emu/grasscutter/server/event/entity/EntityMoveEvent.java index a1583455d..2049d1440 100644 --- a/src/main/java/emu/grasscutter/server/event/entity/EntityMoveEvent.java +++ b/src/main/java/emu/grasscutter/server/event/entity/EntityMoveEvent.java @@ -1,31 +1,32 @@ -package emu.grasscutter.server.event.entity; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; -import emu.grasscutter.server.event.types.EntityEvent; -import emu.grasscutter.utils.Position; - -public final class EntityMoveEvent extends EntityEvent { - private final Position position, rotation; - private final MotionState motionState; - - public EntityMoveEvent(GameEntity entity, Position position, Position rotation, MotionState motionState) { - super(entity); - - this.position = position; - this.rotation = rotation; - this.motionState = motionState; - } - - public Position getPosition() { - return this.position; - } - - public Position getRotation() { - return this.rotation; - } - - public MotionState getMotionState() { - return this.motionState; - } -} +package emu.grasscutter.server.event.entity; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.server.event.types.EntityEvent; +import emu.grasscutter.utils.Position; + +public final class EntityMoveEvent extends EntityEvent { + private final Position position, rotation; + private final MotionState motionState; + + public EntityMoveEvent( + GameEntity entity, Position position, Position rotation, MotionState motionState) { + super(entity); + + this.position = position; + this.rotation = rotation; + this.motionState = motionState; + } + + public Position getPosition() { + return this.position; + } + + public Position getRotation() { + return this.rotation; + } + + public MotionState getMotionState() { + return this.motionState; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/game/PlayerCreationEvent.java b/src/main/java/emu/grasscutter/server/event/game/PlayerCreationEvent.java index 24cf09235..e6a3b8482 100644 --- a/src/main/java/emu/grasscutter/server/event/game/PlayerCreationEvent.java +++ b/src/main/java/emu/grasscutter/server/event/game/PlayerCreationEvent.java @@ -1,27 +1,27 @@ -package emu.grasscutter.server.event.game; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.types.GameEvent; -import emu.grasscutter.server.game.GameSession; - -public final class PlayerCreationEvent extends GameEvent { - private final GameSession session; - private Class playerClass; - - public PlayerCreationEvent(GameSession session, Class playerClass) { - this.session = session; - this.playerClass = playerClass; - } - - public GameSession getSession() { - return this.session; - } - - public Class getPlayerClass() { - return this.playerClass; - } - - public void setPlayerClass(Class playerClass) { - this.playerClass = playerClass; - } -} +package emu.grasscutter.server.event.game; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.types.GameEvent; +import emu.grasscutter.server.game.GameSession; + +public final class PlayerCreationEvent extends GameEvent { + private final GameSession session; + private Class playerClass; + + public PlayerCreationEvent(GameSession session, Class playerClass) { + this.session = session; + this.playerClass = playerClass; + } + + public GameSession getSession() { + return this.session; + } + + public Class getPlayerClass() { + return this.playerClass; + } + + public void setPlayerClass(Class playerClass) { + this.playerClass = playerClass; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/game/ReceiveCommandFeedbackEvent.java b/src/main/java/emu/grasscutter/server/event/game/ReceiveCommandFeedbackEvent.java index 31a6a33c8..61c3bb395 100644 --- a/src/main/java/emu/grasscutter/server/event/game/ReceiveCommandFeedbackEvent.java +++ b/src/main/java/emu/grasscutter/server/event/game/ReceiveCommandFeedbackEvent.java @@ -1,33 +1,30 @@ -package emu.grasscutter.server.event.game; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.ServerEvent; - -import javax.annotation.Nullable; - -public final class ReceiveCommandFeedbackEvent extends ServerEvent implements Cancellable { - @Nullable - private final Player player; - private String message; - - public ReceiveCommandFeedbackEvent(@Nullable Player player, String message) { - super(Type.GAME); - - this.player = player; - this.message = message; - } - - public String getMessage() { - return this.message; - } - - public void setMessage(String message) { - this.message = message; - } - - @Nullable - public Player getPlayer() { - return this.player; - } -} +package emu.grasscutter.server.event.game; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.ServerEvent; +import javax.annotation.Nullable; + +public final class ReceiveCommandFeedbackEvent extends ServerEvent implements Cancellable { + @Nullable private final Player player; + private String message; + + public ReceiveCommandFeedbackEvent(@Nullable Player player, String message) { + super(Type.GAME); + + this.player = player; + this.message = message; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Nullable public Player getPlayer() { + return this.player; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/game/ReceivePacketEvent.java b/src/main/java/emu/grasscutter/server/event/game/ReceivePacketEvent.java index 4f21297cf..db8003ce1 100644 --- a/src/main/java/emu/grasscutter/server/event/game/ReceivePacketEvent.java +++ b/src/main/java/emu/grasscutter/server/event/game/ReceivePacketEvent.java @@ -1,35 +1,35 @@ -package emu.grasscutter.server.event.game; - -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.ServerEvent; -import emu.grasscutter.server.game.GameSession; - -public final class ReceivePacketEvent extends ServerEvent implements Cancellable { - private final GameSession gameSession; - private final int packetId; - private byte[] packetData; - - public ReceivePacketEvent(GameSession gameSession, int packetId, byte[] packetData) { - super(Type.GAME); - - this.gameSession = gameSession; - this.packetId = packetId; - this.packetData = packetData; - } - - public GameSession getGameSession() { - return this.gameSession; - } - - public int getPacketId() { - return this.packetId; - } - - public byte[] getPacketData() { - return this.packetData; - } - - public void setPacketData(byte[] packetData) { - this.packetData = packetData; - } -} +package emu.grasscutter.server.event.game; + +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.ServerEvent; +import emu.grasscutter.server.game.GameSession; + +public final class ReceivePacketEvent extends ServerEvent implements Cancellable { + private final GameSession gameSession; + private final int packetId; + private byte[] packetData; + + public ReceivePacketEvent(GameSession gameSession, int packetId, byte[] packetData) { + super(Type.GAME); + + this.gameSession = gameSession; + this.packetId = packetId; + this.packetData = packetData; + } + + public GameSession getGameSession() { + return this.gameSession; + } + + public int getPacketId() { + return this.packetId; + } + + public byte[] getPacketData() { + return this.packetData; + } + + public void setPacketData(byte[] packetData) { + this.packetData = packetData; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/game/SendPacketEvent.java b/src/main/java/emu/grasscutter/server/event/game/SendPacketEvent.java index 7a6125ba7..111daef57 100644 --- a/src/main/java/emu/grasscutter/server/event/game/SendPacketEvent.java +++ b/src/main/java/emu/grasscutter/server/event/game/SendPacketEvent.java @@ -1,30 +1,30 @@ -package emu.grasscutter.server.event.game; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.ServerEvent; -import emu.grasscutter.server.game.GameSession; - -public final class SendPacketEvent extends ServerEvent implements Cancellable { - private final GameSession gameSession; - private BasePacket packet; - - public SendPacketEvent(GameSession gameSession, BasePacket packet) { - super(Type.GAME); - - this.gameSession = gameSession; - this.packet = packet; - } - - public GameSession getGameSession() { - return this.gameSession; - } - - public BasePacket getPacket() { - return this.packet; - } - - public void setPacket(BasePacket packet) { - this.packet = packet; - } -} +package emu.grasscutter.server.event.game; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.ServerEvent; +import emu.grasscutter.server.game.GameSession; + +public final class SendPacketEvent extends ServerEvent implements Cancellable { + private final GameSession gameSession; + private BasePacket packet; + + public SendPacketEvent(GameSession gameSession, BasePacket packet) { + super(Type.GAME); + + this.gameSession = gameSession; + this.packet = packet; + } + + public GameSession getGameSession() { + return this.gameSession; + } + + public BasePacket getPacket() { + return this.packet; + } + + public void setPacket(BasePacket packet) { + this.packet = packet; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/game/ServerTickEvent.java b/src/main/java/emu/grasscutter/server/event/game/ServerTickEvent.java index 1762997de..8ca3b1298 100644 --- a/src/main/java/emu/grasscutter/server/event/game/ServerTickEvent.java +++ b/src/main/java/emu/grasscutter/server/event/game/ServerTickEvent.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.event.game; - -import emu.grasscutter.server.event.types.ServerEvent; - -import java.time.Instant; - -public final class ServerTickEvent extends ServerEvent { - private final Instant start, end; - - public ServerTickEvent(Instant start, Instant end) { - super(Type.GAME); - - this.start = start; - this.end = end; - } - - public Instant getTickStart() { - return this.start; - } - - public Instant getTickEnd() { - return this.end; - } -} +package emu.grasscutter.server.event.game; + +import emu.grasscutter.server.event.types.ServerEvent; +import java.time.Instant; + +public final class ServerTickEvent extends ServerEvent { + private final Instant start, end; + + public ServerTickEvent(Instant start, Instant end) { + super(Type.GAME); + + this.start = start; + this.end = end; + } + + public Instant getTickStart() { + return this.start; + } + + public Instant getTickEnd() { + return this.end; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/internal/ServerStartEvent.java b/src/main/java/emu/grasscutter/server/event/internal/ServerStartEvent.java index 31294d96c..943c0cf24 100644 --- a/src/main/java/emu/grasscutter/server/event/internal/ServerStartEvent.java +++ b/src/main/java/emu/grasscutter/server/event/internal/ServerStartEvent.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.event.internal; - -import emu.grasscutter.server.event.types.ServerEvent; - -import java.time.OffsetDateTime; - -public final class ServerStartEvent extends ServerEvent { - private final OffsetDateTime startTime; - - public ServerStartEvent(Type type, OffsetDateTime startTime) { - super(type); - - this.startTime = startTime; - } - - public OffsetDateTime getStartTime() { - return this.startTime; - } -} +package emu.grasscutter.server.event.internal; + +import emu.grasscutter.server.event.types.ServerEvent; +import java.time.OffsetDateTime; + +public final class ServerStartEvent extends ServerEvent { + private final OffsetDateTime startTime; + + public ServerStartEvent(Type type, OffsetDateTime startTime) { + super(type); + + this.startTime = startTime; + } + + public OffsetDateTime getStartTime() { + return this.startTime; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/internal/ServerStopEvent.java b/src/main/java/emu/grasscutter/server/event/internal/ServerStopEvent.java index c4e7ca8cf..2fdb1bfb9 100644 --- a/src/main/java/emu/grasscutter/server/event/internal/ServerStopEvent.java +++ b/src/main/java/emu/grasscutter/server/event/internal/ServerStopEvent.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.event.internal; - -import emu.grasscutter.server.event.types.ServerEvent; - -import java.time.OffsetDateTime; - -public final class ServerStopEvent extends ServerEvent { - private final OffsetDateTime stopTime; - - public ServerStopEvent(Type type, OffsetDateTime stopTime) { - super(type); - - this.stopTime = stopTime; - } - - public OffsetDateTime getStopTime() { - return this.stopTime; - } -} +package emu.grasscutter.server.event.internal; + +import emu.grasscutter.server.event.types.ServerEvent; +import java.time.OffsetDateTime; + +public final class ServerStopEvent extends ServerEvent { + private final OffsetDateTime stopTime; + + public ServerStopEvent(Type type, OffsetDateTime stopTime) { + super(type); + + this.stopTime = stopTime; + } + + public OffsetDateTime getStopTime() { + return this.stopTime; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerMoveEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerMoveEvent.java index b6aba5c14..595162624 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerMoveEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerMoveEvent.java @@ -1,46 +1,40 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.types.PlayerEvent; -import emu.grasscutter.utils.Position; - -/** - * TODO: Allow plugins to change the position of the player. - */ -public final class PlayerMoveEvent extends PlayerEvent { - private final MoveType type; - private final Position from; - private final Position to; - - public PlayerMoveEvent(Player player, MoveType type, Position from, Position to) { - super(player); - - this.type = type; - this.from = from; - this.to = to; - } - - public MoveType getMoveType() { - return this.type; - } - - public Position getSource() { - return this.from; - } - - public Position getDestination() { - return this.to; - } - - public enum MoveType { - /** - * The player has sent a combat invocation to move. - */ - PLAYER, - - /** - * The server has requested that the player moves. - */ - SERVER - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.types.PlayerEvent; +import emu.grasscutter.utils.Position; + +/** TODO: Allow plugins to change the position of the player. */ +public final class PlayerMoveEvent extends PlayerEvent { + private final MoveType type; + private final Position from; + private final Position to; + + public PlayerMoveEvent(Player player, MoveType type, Position from, Position to) { + super(player); + + this.type = type; + this.from = from; + this.to = to; + } + + public MoveType getMoveType() { + return this.type; + } + + public Position getSource() { + return this.from; + } + + public Position getDestination() { + return this.to; + } + + public enum MoveType { + /** The player has sent a combat invocation to move. */ + PLAYER, + + /** The server has requested that the player moves. */ + SERVER + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerQuitEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerQuitEvent.java index b2d4b382a..b3cbf4bd4 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerQuitEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerQuitEvent.java @@ -1,10 +1,10 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.types.PlayerEvent; - -public final class PlayerQuitEvent extends PlayerEvent { - public PlayerQuitEvent(Player player) { - super(player); - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.types.PlayerEvent; + +public final class PlayerQuitEvent extends PlayerEvent { + public PlayerQuitEvent(Player player) { + super(player); + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerReceiveMailEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerReceiveMailEvent.java index c008a9783..deaea0707 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerReceiveMailEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerReceiveMailEvent.java @@ -1,24 +1,24 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.PlayerEvent; - -public final class PlayerReceiveMailEvent extends PlayerEvent implements Cancellable { - private Mail message; - - public PlayerReceiveMailEvent(Player player, Mail message) { - super(player); - - this.message = message; - } - - public Mail getMessage() { - return this.message; - } - - public void setMessage(Mail message) { - this.message = message; - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.PlayerEvent; + +public final class PlayerReceiveMailEvent extends PlayerEvent implements Cancellable { + private Mail message; + + public PlayerReceiveMailEvent(Player player, Mail message) { + super(player); + + this.message = message; + } + + public Mail getMessage() { + return this.message; + } + + public void setMessage(Mail message) { + this.message = message; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerTeamDeathEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerTeamDeathEvent.java index 2a2f98603..c7258ad28 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerTeamDeathEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerTeamDeathEvent.java @@ -1,21 +1,20 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.types.PlayerEvent; -import lombok.Getter; - -/** - * This event is invoked when the ENTIRE TEAM dies. - * To listen for one player death, use {@link emu.grasscutter.server.event.entity.EntityDeathEvent}. - */ -public final class PlayerTeamDeathEvent extends PlayerEvent { - @Getter - private final EntityAvatar selectedAvatar; - - public PlayerTeamDeathEvent(Player player, EntityAvatar selectedAvatar) { - super(player); - - this.selectedAvatar = selectedAvatar; - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.types.PlayerEvent; +import lombok.Getter; + +/** + * This event is invoked when the ENTIRE TEAM dies. To listen for one player death, use {@link + * emu.grasscutter.server.event.entity.EntityDeathEvent}. + */ +public final class PlayerTeamDeathEvent extends PlayerEvent { + @Getter private final EntityAvatar selectedAvatar; + + public PlayerTeamDeathEvent(Player player, EntityAvatar selectedAvatar) { + super(player); + + this.selectedAvatar = selectedAvatar; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerTeleportEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerTeleportEvent.java index 52b2f7f5b..ea82b0e11 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerTeleportEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerTeleportEvent.java @@ -1,63 +1,53 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.PlayerEvent; -import emu.grasscutter.utils.Position; - -public final class PlayerTeleportEvent extends PlayerEvent implements Cancellable { - private final TeleportType type; - private final Position from; - private Position to; - - public PlayerTeleportEvent(Player player, TeleportType type, Position from, Position to) { - super(player); - - this.type = type; - this.from = from; - this.to = to; - } - - public TeleportType getTeleportType() { - return this.type; - } - - public Position getSource() { - return this.from; - } - - public Position getDestination() { - return this.to; - } - - public void setDestination(Position to) { - this.to = to; - } - - public enum TeleportType { - /** - * There is no specified reason to teleport. - */ - INTERNAL, - - /** - * The player has asked to teleport to a waypoint. - */ - WAYPOINT, - - /** - * The player has asked to teleport using the map. - */ - MAP, - - /** - * The player has asked to teleport into a dungeon. - */ - DUNGEON, - - /** - * The player has asked to teleport using the command. - */ - COMMAND - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.PlayerEvent; +import emu.grasscutter.utils.Position; + +public final class PlayerTeleportEvent extends PlayerEvent implements Cancellable { + private final TeleportType type; + private final Position from; + private Position to; + + public PlayerTeleportEvent(Player player, TeleportType type, Position from, Position to) { + super(player); + + this.type = type; + this.from = from; + this.to = to; + } + + public TeleportType getTeleportType() { + return this.type; + } + + public Position getSource() { + return this.from; + } + + public Position getDestination() { + return this.to; + } + + public void setDestination(Position to) { + this.to = to; + } + + public enum TeleportType { + /** There is no specified reason to teleport. */ + INTERNAL, + + /** The player has asked to teleport to a waypoint. */ + WAYPOINT, + + /** The player has asked to teleport using the map. */ + MAP, + + /** The player has asked to teleport into a dungeon. */ + DUNGEON, + + /** The player has asked to teleport using the command. */ + COMMAND + } +} diff --git a/src/main/java/emu/grasscutter/server/event/player/PlayerUseFoodEvent.java b/src/main/java/emu/grasscutter/server/event/player/PlayerUseFoodEvent.java index 9ab9678a7..c70c63b58 100644 --- a/src/main/java/emu/grasscutter/server/event/player/PlayerUseFoodEvent.java +++ b/src/main/java/emu/grasscutter/server/event/player/PlayerUseFoodEvent.java @@ -1,27 +1,22 @@ -package emu.grasscutter.server.event.player; - -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.Cancellable; -import emu.grasscutter.server.event.types.PlayerEvent; -import lombok.Getter; -import lombok.Setter; - -/** - * This event is invoked when the player uses food on an avatar. - */ -public final class PlayerUseFoodEvent extends PlayerEvent implements Cancellable { - @Getter - private final EntityAvatar selectedAvatar; - @Getter - @Setter - private ItemData foodUsed; - - public PlayerUseFoodEvent(Player player, ItemData foodUsed, EntityAvatar selectedAvatar) { - super(player); - - this.foodUsed = foodUsed; - this.selectedAvatar = selectedAvatar; - } -} +package emu.grasscutter.server.event.player; + +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.Cancellable; +import emu.grasscutter.server.event.types.PlayerEvent; +import lombok.Getter; +import lombok.Setter; + +/** This event is invoked when the player uses food on an avatar. */ +public final class PlayerUseFoodEvent extends PlayerEvent implements Cancellable { + @Getter private final EntityAvatar selectedAvatar; + @Getter @Setter private ItemData foodUsed; + + public PlayerUseFoodEvent(Player player, ItemData foodUsed, EntityAvatar selectedAvatar) { + super(player); + + this.foodUsed = foodUsed; + this.selectedAvatar = selectedAvatar; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/types/EntityEvent.java b/src/main/java/emu/grasscutter/server/event/types/EntityEvent.java index 141e8ccf2..a42fd8a94 100644 --- a/src/main/java/emu/grasscutter/server/event/types/EntityEvent.java +++ b/src/main/java/emu/grasscutter/server/event/types/EntityEvent.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.event.types; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.server.event.Event; - -/** - * An event that is related to entity interactions. - */ -public abstract class EntityEvent extends Event { - protected final GameEntity entity; - - public EntityEvent(GameEntity player) { - this.entity = player; - } - - public GameEntity getEntity() { - return this.entity; - } -} +package emu.grasscutter.server.event.types; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.server.event.Event; + +/** An event that is related to entity interactions. */ +public abstract class EntityEvent extends Event { + protected final GameEntity entity; + + public EntityEvent(GameEntity player) { + this.entity = player; + } + + public GameEntity getEntity() { + return this.entity; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/types/GameEvent.java b/src/main/java/emu/grasscutter/server/event/types/GameEvent.java index aabd64427..3e2501f11 100644 --- a/src/main/java/emu/grasscutter/server/event/types/GameEvent.java +++ b/src/main/java/emu/grasscutter/server/event/types/GameEvent.java @@ -1,10 +1,6 @@ -package emu.grasscutter.server.event.types; - -import emu.grasscutter.server.event.Event; - -/** - * An event that is related to the game. - */ -public abstract class GameEvent extends Event { - -} +package emu.grasscutter.server.event.types; + +import emu.grasscutter.server.event.Event; + +/** An event that is related to the game. */ +public abstract class GameEvent extends Event {} diff --git a/src/main/java/emu/grasscutter/server/event/types/PlayerEvent.java b/src/main/java/emu/grasscutter/server/event/types/PlayerEvent.java index eb55f2d58..6e5f99a12 100644 --- a/src/main/java/emu/grasscutter/server/event/types/PlayerEvent.java +++ b/src/main/java/emu/grasscutter/server/event/types/PlayerEvent.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.event.types; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.Event; - -/** - * An event that is related to player interactions. - */ -public abstract class PlayerEvent extends Event { - protected final Player player; - - public PlayerEvent(Player player) { - this.player = player; - } - - public Player getPlayer() { - return this.player; - } -} +package emu.grasscutter.server.event.types; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.Event; + +/** An event that is related to player interactions. */ +public abstract class PlayerEvent extends Event { + protected final Player player; + + public PlayerEvent(Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/types/ServerEvent.java b/src/main/java/emu/grasscutter/server/event/types/ServerEvent.java index 5cf0d41f6..aeba37ab1 100644 --- a/src/main/java/emu/grasscutter/server/event/types/ServerEvent.java +++ b/src/main/java/emu/grasscutter/server/event/types/ServerEvent.java @@ -1,23 +1,21 @@ -package emu.grasscutter.server.event.types; - -import emu.grasscutter.server.event.Event; - -/** - * An event that is related to the internals of the server. - */ -public abstract class ServerEvent extends Event { - protected final Type type; - - public ServerEvent(Type type) { - this.type = type; - } - - public Type getServerType() { - return this.type; - } - - public enum Type { - DISPATCH, - GAME - } -} +package emu.grasscutter.server.event.types; + +import emu.grasscutter.server.event.Event; + +/** An event that is related to the internals of the server. */ +public abstract class ServerEvent extends Event { + protected final Type type; + + public ServerEvent(Type type) { + this.type = type; + } + + public Type getServerType() { + return this.type; + } + + public enum Type { + DISPATCH, + GAME + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 6396804fb..8bd5ce48f 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -1,275 +1,281 @@ -package emu.grasscutter.server.game; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.battlepass.BattlePassSystem; -import emu.grasscutter.game.chat.ChatSystem; -import emu.grasscutter.game.chat.ChatSystemHandler; -import emu.grasscutter.game.combine.CombineManger; -import emu.grasscutter.game.drop.DropSystem; -import emu.grasscutter.game.dungeons.DungeonSystem; -import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; -import emu.grasscutter.game.expedition.ExpeditionSystem; -import emu.grasscutter.game.gacha.GachaSystem; -import emu.grasscutter.game.managers.cooking.CookingCompoundManager; -import emu.grasscutter.game.managers.cooking.CookingManager; -import emu.grasscutter.game.managers.energy.EnergyManager; -import emu.grasscutter.game.managers.stamina.StaminaManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.QuestSystem; -import emu.grasscutter.game.shop.ShopSystem; -import emu.grasscutter.game.systems.AnnouncementSystem; -import emu.grasscutter.game.systems.InventorySystem; -import emu.grasscutter.game.systems.MultiplayerSystem; -import emu.grasscutter.game.tower.TowerSystem; -import emu.grasscutter.game.world.World; -import emu.grasscutter.game.world.WorldDataSystem; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; -import emu.grasscutter.server.event.game.ServerTickEvent; -import emu.grasscutter.server.event.internal.ServerStartEvent; -import emu.grasscutter.server.event.internal.ServerStopEvent; -import emu.grasscutter.server.event.types.ServerEvent; -import emu.grasscutter.server.scheduler.ServerTaskScheduler; -import emu.grasscutter.task.TaskMap; -import kcp.highway.ChannelConfig; -import kcp.highway.KcpServer; -import lombok.Getter; - -import java.net.InetSocketAddress; -import java.time.Instant; -import java.time.OffsetDateTime; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import static emu.grasscutter.config.Configuration.GAME_INFO; -import static emu.grasscutter.utils.Language.translate; - -@Getter -public final class GameServer extends KcpServer { - // Game server base - private final InetSocketAddress address; - private final GameServerPacketHandler packetHandler; - private final Map players; - private final Set worlds; - - // Server systems - private final InventorySystem inventorySystem; - private final GachaSystem gachaSystem; - private final ShopSystem shopSystem; - private final MultiplayerSystem multiplayerSystem; - private final DungeonSystem dungeonSystem; - private final ExpeditionSystem expeditionSystem; - private final DropSystem dropSystem; - private final WorldDataSystem worldDataSystem; - private final BattlePassSystem battlePassSystem; - private final CombineManger combineSystem; - private final TowerSystem towerSystem; - private final AnnouncementSystem announcementSystem; - private final QuestSystem questSystem; - - // Extra - private final ServerTaskScheduler scheduler; - private final TaskMap taskMap; - - private ChatSystemHandler chatManager; - - public GameServer() { - this(getAdapterInetSocketAddress()); - } - - public GameServer(InetSocketAddress address) { - ChannelConfig channelConfig = new ChannelConfig(); - channelConfig.nodelay(true, GAME_INFO.kcpInterval, 2, true); - channelConfig.setMtu(1400); - channelConfig.setSndwnd(256); - channelConfig.setRcvwnd(256); - channelConfig.setTimeoutMillis(30 * 1000);//30s - channelConfig.setUseConvChannel(true); - channelConfig.setAckNoDelay(false); - - this.init(GameSessionManager.getListener(), channelConfig, address); - - DungeonChallenge.initialize(); - EnergyManager.initialize(); - StaminaManager.initialize(); - CookingManager.initialize(); - CookingCompoundManager.initialize(); - CombineManger.initialize(); - - // Game Server base - this.address = address; - this.packetHandler = new GameServerPacketHandler(PacketHandler.class); - this.players = new ConcurrentHashMap<>(); - this.worlds = Collections.synchronizedSet(new HashSet<>()); - - // Extra - this.scheduler = new ServerTaskScheduler(); - this.taskMap = new TaskMap(true); - - // Create game systems - this.inventorySystem = new InventorySystem(this); - this.gachaSystem = new GachaSystem(this); - this.shopSystem = new ShopSystem(this); - this.multiplayerSystem = new MultiplayerSystem(this); - this.dungeonSystem = new DungeonSystem(this); - this.dropSystem = new DropSystem(this); - this.expeditionSystem = new ExpeditionSystem(this); - this.combineSystem = new CombineManger(this); - this.towerSystem = new TowerSystem(this); - this.worldDataSystem = new WorldDataSystem(this); - this.battlePassSystem = new BattlePassSystem(this); - this.announcementSystem = new AnnouncementSystem(this); - this.questSystem = new QuestSystem(this); - - // Chata manager - this.chatManager = new ChatSystem(this); - - // Hook into shutdown event. - Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown)); - } - - private static InetSocketAddress getAdapterInetSocketAddress() { - InetSocketAddress inetSocketAddress; - if (GAME_INFO.bindAddress.equals("")) { - inetSocketAddress = new InetSocketAddress(GAME_INFO.bindPort); - } else { - inetSocketAddress = new InetSocketAddress( - GAME_INFO.bindAddress, - GAME_INFO.bindPort - ); - } - return inetSocketAddress; - } - - @Deprecated - public ChatSystemHandler getChatManager() { - return chatManager; - } - - @Deprecated - public void setChatManager(ChatSystemHandler chatManager) { - this.chatManager = chatManager; - } - - public ChatSystemHandler getChatSystem() { - return chatManager; - } - - public void setChatSystem(ChatSystemHandler chatManager) { - this.chatManager = chatManager; - } - - public void registerPlayer(Player player) { - getPlayers().put(player.getUid(), player); - } - - public Player getPlayerByUid(int id) { - return this.getPlayerByUid(id, false); - } - - public Player getPlayerByUid(int id, boolean allowOfflinePlayers) { - // Console check - if (id == GameConstants.SERVER_CONSOLE_UID) { - return null; - } - - // Get from online players - Player player = this.getPlayers().get(id); - - if (!allowOfflinePlayers) { - return player; - } - - // Check database if character isnt here - if (player == null) { - player = DatabaseHelper.getPlayerByUid(id); - } - - return player; - } - - public Player getPlayerByAccountId(String accountId) { - Optional playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getId().equals(accountId)).findFirst(); - return playerOpt.orElse(null); - } - - public SocialDetail.Builder getSocialDetailByUid(int id) { - // Get from online players - Player player = this.getPlayerByUid(id, true); - - if (player == null) { - return null; - } - - return player.getSocialDetail(); - } - - public Account getAccountByName(String username) { - Optional playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getUsername().equals(username)).findFirst(); - if (playerOpt.isPresent()) { - return playerOpt.get().getAccount(); - } - return DatabaseHelper.getAccountByName(username); - } - - public synchronized void onTick() { - var tickStart = Instant.now(); - - // Tick worlds. - this.worlds.removeIf(World::onTick); - - // Tick players. - this.players.values().forEach(Player::onTick); - - // Tick scheduler. - this.getScheduler().runTasks(); - - // Call server tick event. - ServerTickEvent event = new ServerTickEvent(tickStart, Instant.now()); - event.call(); - } - - public void registerWorld(World world) { - this.getWorlds().add(world); - } - - public void deregisterWorld(World world) { - // TODO Auto-generated method stub - - } - - public void start() { - // Schedule game loop. - Timer gameLoop = new Timer(); - gameLoop.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - try { - onTick(); - } catch (Exception e) { - Grasscutter.getLogger().error(translate("messages.game.game_update_error"), e); - } - } - }, new Date(), 1000L); - Grasscutter.getLogger().info(translate("messages.status.free_software")); - Grasscutter.getLogger().info(translate("messages.game.address_bind", GAME_INFO.accessAddress, address.getPort())); - ServerStartEvent event = new ServerStartEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); - event.call(); - } - - public void onServerShutdown() { - ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); - event.call(); - - // Kick and save all players - List list = new ArrayList<>(this.getPlayers().size()); - list.addAll(this.getPlayers().values()); - - for (Player player : list) { - player.getSession().close(); - } - } -} +package emu.grasscutter.server.game; + +import static emu.grasscutter.config.Configuration.GAME_INFO; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.battlepass.BattlePassSystem; +import emu.grasscutter.game.chat.ChatSystem; +import emu.grasscutter.game.chat.ChatSystemHandler; +import emu.grasscutter.game.combine.CombineManger; +import emu.grasscutter.game.drop.DropSystem; +import emu.grasscutter.game.dungeons.DungeonSystem; +import emu.grasscutter.game.dungeons.challenge.DungeonChallenge; +import emu.grasscutter.game.expedition.ExpeditionSystem; +import emu.grasscutter.game.gacha.GachaSystem; +import emu.grasscutter.game.managers.cooking.CookingCompoundManager; +import emu.grasscutter.game.managers.cooking.CookingManager; +import emu.grasscutter.game.managers.energy.EnergyManager; +import emu.grasscutter.game.managers.stamina.StaminaManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.QuestSystem; +import emu.grasscutter.game.shop.ShopSystem; +import emu.grasscutter.game.systems.AnnouncementSystem; +import emu.grasscutter.game.systems.InventorySystem; +import emu.grasscutter.game.systems.MultiplayerSystem; +import emu.grasscutter.game.tower.TowerSystem; +import emu.grasscutter.game.world.World; +import emu.grasscutter.game.world.WorldDataSystem; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; +import emu.grasscutter.server.event.game.ServerTickEvent; +import emu.grasscutter.server.event.internal.ServerStartEvent; +import emu.grasscutter.server.event.internal.ServerStopEvent; +import emu.grasscutter.server.event.types.ServerEvent; +import emu.grasscutter.server.scheduler.ServerTaskScheduler; +import emu.grasscutter.task.TaskMap; +import java.net.InetSocketAddress; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import kcp.highway.ChannelConfig; +import kcp.highway.KcpServer; +import lombok.Getter; + +@Getter +public final class GameServer extends KcpServer { + // Game server base + private final InetSocketAddress address; + private final GameServerPacketHandler packetHandler; + private final Map players; + private final Set worlds; + + // Server systems + private final InventorySystem inventorySystem; + private final GachaSystem gachaSystem; + private final ShopSystem shopSystem; + private final MultiplayerSystem multiplayerSystem; + private final DungeonSystem dungeonSystem; + private final ExpeditionSystem expeditionSystem; + private final DropSystem dropSystem; + private final WorldDataSystem worldDataSystem; + private final BattlePassSystem battlePassSystem; + private final CombineManger combineSystem; + private final TowerSystem towerSystem; + private final AnnouncementSystem announcementSystem; + private final QuestSystem questSystem; + + // Extra + private final ServerTaskScheduler scheduler; + private final TaskMap taskMap; + + private ChatSystemHandler chatManager; + + public GameServer() { + this(getAdapterInetSocketAddress()); + } + + public GameServer(InetSocketAddress address) { + ChannelConfig channelConfig = new ChannelConfig(); + channelConfig.nodelay(true, GAME_INFO.kcpInterval, 2, true); + channelConfig.setMtu(1400); + channelConfig.setSndwnd(256); + channelConfig.setRcvwnd(256); + channelConfig.setTimeoutMillis(30 * 1000); // 30s + channelConfig.setUseConvChannel(true); + channelConfig.setAckNoDelay(false); + + this.init(GameSessionManager.getListener(), channelConfig, address); + + DungeonChallenge.initialize(); + EnergyManager.initialize(); + StaminaManager.initialize(); + CookingManager.initialize(); + CookingCompoundManager.initialize(); + CombineManger.initialize(); + + // Game Server base + this.address = address; + this.packetHandler = new GameServerPacketHandler(PacketHandler.class); + this.players = new ConcurrentHashMap<>(); + this.worlds = Collections.synchronizedSet(new HashSet<>()); + + // Extra + this.scheduler = new ServerTaskScheduler(); + this.taskMap = new TaskMap(true); + + // Create game systems + this.inventorySystem = new InventorySystem(this); + this.gachaSystem = new GachaSystem(this); + this.shopSystem = new ShopSystem(this); + this.multiplayerSystem = new MultiplayerSystem(this); + this.dungeonSystem = new DungeonSystem(this); + this.dropSystem = new DropSystem(this); + this.expeditionSystem = new ExpeditionSystem(this); + this.combineSystem = new CombineManger(this); + this.towerSystem = new TowerSystem(this); + this.worldDataSystem = new WorldDataSystem(this); + this.battlePassSystem = new BattlePassSystem(this); + this.announcementSystem = new AnnouncementSystem(this); + this.questSystem = new QuestSystem(this); + + // Chata manager + this.chatManager = new ChatSystem(this); + + // Hook into shutdown event. + Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown)); + } + + private static InetSocketAddress getAdapterInetSocketAddress() { + InetSocketAddress inetSocketAddress; + if (GAME_INFO.bindAddress.equals("")) { + inetSocketAddress = new InetSocketAddress(GAME_INFO.bindPort); + } else { + inetSocketAddress = new InetSocketAddress(GAME_INFO.bindAddress, GAME_INFO.bindPort); + } + return inetSocketAddress; + } + + @Deprecated + public ChatSystemHandler getChatManager() { + return chatManager; + } + + @Deprecated + public void setChatManager(ChatSystemHandler chatManager) { + this.chatManager = chatManager; + } + + public ChatSystemHandler getChatSystem() { + return chatManager; + } + + public void setChatSystem(ChatSystemHandler chatManager) { + this.chatManager = chatManager; + } + + public void registerPlayer(Player player) { + getPlayers().put(player.getUid(), player); + } + + public Player getPlayerByUid(int id) { + return this.getPlayerByUid(id, false); + } + + public Player getPlayerByUid(int id, boolean allowOfflinePlayers) { + // Console check + if (id == GameConstants.SERVER_CONSOLE_UID) { + return null; + } + + // Get from online players + Player player = this.getPlayers().get(id); + + if (!allowOfflinePlayers) { + return player; + } + + // Check database if character isnt here + if (player == null) { + player = DatabaseHelper.getPlayerByUid(id); + } + + return player; + } + + public Player getPlayerByAccountId(String accountId) { + Optional playerOpt = + getPlayers().values().stream() + .filter(player -> player.getAccount().getId().equals(accountId)) + .findFirst(); + return playerOpt.orElse(null); + } + + public SocialDetail.Builder getSocialDetailByUid(int id) { + // Get from online players + Player player = this.getPlayerByUid(id, true); + + if (player == null) { + return null; + } + + return player.getSocialDetail(); + } + + public Account getAccountByName(String username) { + Optional playerOpt = + getPlayers().values().stream() + .filter(player -> player.getAccount().getUsername().equals(username)) + .findFirst(); + if (playerOpt.isPresent()) { + return playerOpt.get().getAccount(); + } + return DatabaseHelper.getAccountByName(username); + } + + public synchronized void onTick() { + var tickStart = Instant.now(); + + // Tick worlds. + this.worlds.removeIf(World::onTick); + + // Tick players. + this.players.values().forEach(Player::onTick); + + // Tick scheduler. + this.getScheduler().runTasks(); + + // Call server tick event. + ServerTickEvent event = new ServerTickEvent(tickStart, Instant.now()); + event.call(); + } + + public void registerWorld(World world) { + this.getWorlds().add(world); + } + + public void deregisterWorld(World world) { + // TODO Auto-generated method stub + + } + + public void start() { + // Schedule game loop. + Timer gameLoop = new Timer(); + gameLoop.scheduleAtFixedRate( + new TimerTask() { + @Override + public void run() { + try { + onTick(); + } catch (Exception e) { + Grasscutter.getLogger().error(translate("messages.game.game_update_error"), e); + } + } + }, + new Date(), + 1000L); + Grasscutter.getLogger().info(translate("messages.status.free_software")); + Grasscutter.getLogger() + .info(translate("messages.game.address_bind", GAME_INFO.accessAddress, address.getPort())); + ServerStartEvent event = new ServerStartEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); + event.call(); + } + + public void onServerShutdown() { + ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); + event.call(); + + // Kick and save all players + List list = new ArrayList<>(this.getPlayers().size()); + list.addAll(this.getPlayers().values()); + + for (Player player : list) { + player.getSession().close(); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java index 9fee490d4..ffab7b525 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java +++ b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java @@ -1,104 +1,110 @@ -package emu.grasscutter.server.game; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerDebugMode; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.event.game.ReceivePacketEvent; -import emu.grasscutter.server.game.GameSession.SessionState; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import org.reflections.Reflections; - -import java.util.Set; - -import static emu.grasscutter.config.Configuration.GAME_INFO; - -@SuppressWarnings("unchecked") -public class GameServerPacketHandler { - private final Int2ObjectMap handlers; - - public GameServerPacketHandler(Class handlerClass) { - this.handlers = new Int2ObjectOpenHashMap<>(); - - this.registerHandlers(handlerClass); - } - - public void registerPacketHandler(Class handlerClass) { - try { - Opcodes opcode = handlerClass.getAnnotation(Opcodes.class); - - if (opcode == null || opcode.disabled() || opcode.value() <= 0) { - return; - } - - PacketHandler packetHandler = handlerClass.getDeclaredConstructor().newInstance(); - - this.handlers.put(opcode.value(), packetHandler); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void registerHandlers(Class handlerClass) { - Reflections reflections = new Reflections("emu.grasscutter.server.packet"); - Set handlerClasses = reflections.getSubTypesOf(handlerClass); - - for (Object obj : handlerClasses) { - this.registerPacketHandler((Class) obj); - } - - // Debug - Grasscutter.getLogger().debug("Registered " + this.handlers.size() + " " + handlerClass.getSimpleName() + "s"); - } - - public void handle(GameSession session, int opcode, byte[] header, byte[] payload) { - PacketHandler handler = this.handlers.get(opcode); - - if (handler != null) { - try { - // Make sure session is ready for packets - SessionState state = session.getState(); - - if (opcode == PacketOpcodes.PingReq) { - // Always continue if packet is ping request - } else if (opcode == PacketOpcodes.GetPlayerTokenReq) { - if (state != SessionState.WAITING_FOR_TOKEN) { - return; - } - } else if (state == SessionState.ACCOUNT_BANNED) { - session.close(); - return; - } else if (opcode == PacketOpcodes.PlayerLoginReq) { - if (state != SessionState.WAITING_FOR_LOGIN) { - return; - } - } else if (opcode == PacketOpcodes.SetPlayerBornDataReq) { - if (state != SessionState.PICKING_CHARACTER) { - return; - } - } else { - if (state != SessionState.ACTIVE) { - return; - } - } - - // Invoke event. - ReceivePacketEvent event = new ReceivePacketEvent(session, opcode, payload); - event.call(); - if (!event.isCanceled()) // If event is not canceled, continue. - handler.handle(session, header, event.getPacketData()); - } catch (Exception ex) { - // TODO Remove this when no more needed - ex.printStackTrace(); - } - return; // Packet successfully handled - } - - // Log unhandled packets - if (GAME_INFO.logPackets == ServerDebugMode.MISSING || GAME_INFO.logPackets == ServerDebugMode.ALL) { - Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode)); - } - } -} +package emu.grasscutter.server.game; + +import static emu.grasscutter.config.Configuration.GAME_INFO; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerDebugMode; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.event.game.ReceivePacketEvent; +import emu.grasscutter.server.game.GameSession.SessionState; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.util.Set; +import org.reflections.Reflections; + +@SuppressWarnings("unchecked") +public class GameServerPacketHandler { + private final Int2ObjectMap handlers; + + public GameServerPacketHandler(Class handlerClass) { + this.handlers = new Int2ObjectOpenHashMap<>(); + + this.registerHandlers(handlerClass); + } + + public void registerPacketHandler(Class handlerClass) { + try { + Opcodes opcode = handlerClass.getAnnotation(Opcodes.class); + + if (opcode == null || opcode.disabled() || opcode.value() <= 0) { + return; + } + + PacketHandler packetHandler = handlerClass.getDeclaredConstructor().newInstance(); + + this.handlers.put(opcode.value(), packetHandler); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void registerHandlers(Class handlerClass) { + Reflections reflections = new Reflections("emu.grasscutter.server.packet"); + Set handlerClasses = reflections.getSubTypesOf(handlerClass); + + for (Object obj : handlerClasses) { + this.registerPacketHandler((Class) obj); + } + + // Debug + Grasscutter.getLogger() + .debug("Registered " + this.handlers.size() + " " + handlerClass.getSimpleName() + "s"); + } + + public void handle(GameSession session, int opcode, byte[] header, byte[] payload) { + PacketHandler handler = this.handlers.get(opcode); + + if (handler != null) { + try { + // Make sure session is ready for packets + SessionState state = session.getState(); + + if (opcode == PacketOpcodes.PingReq) { + // Always continue if packet is ping request + } else if (opcode == PacketOpcodes.GetPlayerTokenReq) { + if (state != SessionState.WAITING_FOR_TOKEN) { + return; + } + } else if (state == SessionState.ACCOUNT_BANNED) { + session.close(); + return; + } else if (opcode == PacketOpcodes.PlayerLoginReq) { + if (state != SessionState.WAITING_FOR_LOGIN) { + return; + } + } else if (opcode == PacketOpcodes.SetPlayerBornDataReq) { + if (state != SessionState.PICKING_CHARACTER) { + return; + } + } else { + if (state != SessionState.ACTIVE) { + return; + } + } + + // Invoke event. + ReceivePacketEvent event = new ReceivePacketEvent(session, opcode, payload); + event.call(); + if (!event.isCanceled()) // If event is not canceled, continue. + handler.handle(session, header, event.getPacketData()); + } catch (Exception ex) { + // TODO Remove this when no more needed + ex.printStackTrace(); + } + return; // Packet successfully handled + } + + // Log unhandled packets + if (GAME_INFO.logPackets == ServerDebugMode.MISSING + || GAME_INFO.logPackets == ServerDebugMode.ALL) { + Grasscutter.getLogger() + .info( + "Unhandled packet (" + + opcode + + "): " + + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index da51b3baa..98a2f4256 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -1,276 +1,270 @@ -package emu.grasscutter.server.game; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerDebugMode; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.packet.PacketOpcodesUtils; -import emu.grasscutter.server.event.game.SendPacketEvent; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import lombok.Getter; -import lombok.Setter; - -import java.io.File; -import java.net.InetSocketAddress; -import java.nio.file.Path; - -import static emu.grasscutter.config.Configuration.GAME_INFO; -import static emu.grasscutter.config.Configuration.SERVER; -import static emu.grasscutter.utils.Language.translate; - -public class GameSession implements GameSessionManager.KcpChannel { - private final GameServer server; - private GameSessionManager.KcpTunnel tunnel; - - @Getter - @Setter - private Account account; - @Getter - private Player player; - - @Setter - private boolean useSecretKey; - @Getter - @Setter - private SessionState state; - - @Getter - private int clientTime; - @Getter - private long lastPingTime; - private int lastClientSeq = 10; - - public GameSession(GameServer server) { - this.server = server; - this.state = SessionState.WAITING_FOR_TOKEN; - this.lastPingTime = System.currentTimeMillis(); - } - - public GameServer getServer() { - return server; - } - - public InetSocketAddress getAddress() { - try { - return tunnel.getAddress(); - } catch (Throwable ignore) { - return null; - } - } - - public boolean useSecretKey() { - return useSecretKey; - } - - public String getAccountId() { - return this.getAccount().getId(); - } - - public synchronized void setPlayer(Player player) { - this.player = player; - this.player.setSession(this); - this.player.setAccount(this.getAccount()); - } - - public boolean isLoggedIn() { - return this.getPlayer() != null; - } - - public void updateLastPingTime(int clientTime) { - this.clientTime = clientTime; - this.lastPingTime = System.currentTimeMillis(); - } - - public int getNextClientSequence() { - return ++lastClientSeq; - } - - public void replayPacket(int opcode, String name) { - Path filePath = FileUtils.getPluginPath(name); - File p = filePath.toFile(); - - if (!p.exists()) return; - - byte[] packet = FileUtils.read(p); - - BasePacket basePacket = new BasePacket(opcode); - basePacket.setData(packet); - - send(basePacket); - } - - public void logPacket(String sendOrRecv, int opcode, byte[] payload) { - Grasscutter.getLogger().info(sendOrRecv + ": " + PacketOpcodesUtils.getOpcodeName(opcode) + " (" + opcode + ")"); - if (GAME_INFO.isShowPacketPayload) - System.out.println(Utils.bytesToHex(payload)); - } - - public void send(BasePacket packet) { - // Test - if (packet.getOpcode() <= 0) { - Grasscutter.getLogger().warn("Tried to send packet with missing cmd id!"); - return; - } - - // DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can) - // Stop WindSeedClientNotify from being sent for security purposes. - if (PacketOpcodesUtils.BANNED_PACKETS.contains(packet.getOpcode())) { - return; - } - - // Header - if (packet.shouldBuildHeader()) { - packet.buildHeader(this.getNextClientSequence()); - } - - // Log - switch (GAME_INFO.logPackets) { - case ALL -> { - if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode()) || GAME_INFO.isShowLoopPackets) { - logPacket("SEND", packet.getOpcode(), packet.getData()); - } - } - case WHITELIST -> { - if (SERVER.debugWhitelist.contains(packet.getOpcode())) { - logPacket("SEND", packet.getOpcode(), packet.getData()); - } - } - case BLACKLIST -> { - if (!SERVER.debugBlacklist.contains(packet.getOpcode())) { - logPacket("SEND", packet.getOpcode(), packet.getData()); - } - } - default -> { - } - } - - // Invoke event. - SendPacketEvent event = new SendPacketEvent(this, packet); - event.call(); - if (!event.isCanceled()) { // If event is not cancelled, continue. - tunnel.writeData(event.getPacket().build()); - } - } - - @Override - public void onConnected(GameSessionManager.KcpTunnel tunnel) { - this.tunnel = tunnel; - Grasscutter.getLogger().info(translate("messages.game.connect", this.getAddress().toString())); - } - - @Override - public void handleReceive(byte[] bytes) { - // Decrypt and turn back into a packet - Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY); - ByteBuf packet = Unpooled.wrappedBuffer(bytes); - - // Log - //logPacket(packet); - // Handle - try { - boolean allDebug = GAME_INFO.logPackets == ServerDebugMode.ALL; - while (packet.readableBytes() > 0) { - // Length - if (packet.readableBytes() < 12) { - return; - } - // Packet sanity check - int const1 = packet.readShort(); - if (const1 != 17767) { - if (allDebug) { - Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect 17767", const1); - } - return; // Bad packet - } - // Data - int opcode = packet.readShort(); - int headerLength = packet.readShort(); - int payloadLength = packet.readInt(); - byte[] header = new byte[headerLength]; - byte[] payload = new byte[payloadLength]; - - packet.readBytes(header); - packet.readBytes(payload); - // Sanity check #2 - int const2 = packet.readShort(); - if (const2 != -30293) { - if (allDebug) { - Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect -30293", const2); - } - return; // Bad packet - } - - // Log packet - switch (GAME_INFO.logPackets) { - case ALL -> { - if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode) || GAME_INFO.isShowLoopPackets) { - logPacket("RECV", opcode, payload); - } - } - case WHITELIST -> { - if (SERVER.debugWhitelist.contains(opcode)) { - logPacket("RECV", opcode, payload); - } - } - case BLACKLIST -> { - if (!(SERVER.debugBlacklist.contains(opcode))) { - logPacket("RECV", opcode, payload); - } - } - default -> { - } - } - - // Handle - getServer().getPacketHandler().handle(this, opcode, header, payload); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - //byteBuf.release(); //Needn't - packet.release(); - } - } - - @Override - public void handleClose() { - setState(SessionState.INACTIVE); - //send disconnection pack in case of reconnection - Grasscutter.getLogger().info(translate("messages.game.disconnect", this.getAddress().toString())); - // Save after disconnecting - if (this.isLoggedIn()) { - Player player = getPlayer(); - // Call logout event. - player.onLogout(); - } - try { - send(new BasePacket(PacketOpcodes.ServerDisconnectClientNotify)); - } catch (Throwable ignore) { - Grasscutter.getLogger().warn("closing {} error", getAddress().getAddress().getHostAddress()); - } - tunnel = null; - } - - public void close() { - tunnel.close(); - } - - public boolean isActive() { - return getState() == SessionState.ACTIVE; - } - - public enum SessionState { - INACTIVE, - WAITING_FOR_TOKEN, - WAITING_FOR_LOGIN, - PICKING_CHARACTER, - ACTIVE, - ACCOUNT_BANNED - } -} +package emu.grasscutter.server.game; + +import static emu.grasscutter.config.Configuration.GAME_INFO; +import static emu.grasscutter.config.Configuration.SERVER; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerDebugMode; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.packet.PacketOpcodesUtils; +import emu.grasscutter.server.event.game.SendPacketEvent; +import emu.grasscutter.utils.Crypto; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.io.File; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import lombok.Getter; +import lombok.Setter; + +public class GameSession implements GameSessionManager.KcpChannel { + private final GameServer server; + private GameSessionManager.KcpTunnel tunnel; + + @Getter @Setter private Account account; + @Getter private Player player; + + @Setter private boolean useSecretKey; + @Getter @Setter private SessionState state; + + @Getter private int clientTime; + @Getter private long lastPingTime; + private int lastClientSeq = 10; + + public GameSession(GameServer server) { + this.server = server; + this.state = SessionState.WAITING_FOR_TOKEN; + this.lastPingTime = System.currentTimeMillis(); + } + + public GameServer getServer() { + return server; + } + + public InetSocketAddress getAddress() { + try { + return tunnel.getAddress(); + } catch (Throwable ignore) { + return null; + } + } + + public boolean useSecretKey() { + return useSecretKey; + } + + public String getAccountId() { + return this.getAccount().getId(); + } + + public synchronized void setPlayer(Player player) { + this.player = player; + this.player.setSession(this); + this.player.setAccount(this.getAccount()); + } + + public boolean isLoggedIn() { + return this.getPlayer() != null; + } + + public void updateLastPingTime(int clientTime) { + this.clientTime = clientTime; + this.lastPingTime = System.currentTimeMillis(); + } + + public int getNextClientSequence() { + return ++lastClientSeq; + } + + public void replayPacket(int opcode, String name) { + Path filePath = FileUtils.getPluginPath(name); + File p = filePath.toFile(); + + if (!p.exists()) return; + + byte[] packet = FileUtils.read(p); + + BasePacket basePacket = new BasePacket(opcode); + basePacket.setData(packet); + + send(basePacket); + } + + public void logPacket(String sendOrRecv, int opcode, byte[] payload) { + Grasscutter.getLogger() + .info(sendOrRecv + ": " + PacketOpcodesUtils.getOpcodeName(opcode) + " (" + opcode + ")"); + if (GAME_INFO.isShowPacketPayload) System.out.println(Utils.bytesToHex(payload)); + } + + public void send(BasePacket packet) { + // Test + if (packet.getOpcode() <= 0) { + Grasscutter.getLogger().warn("Tried to send packet with missing cmd id!"); + return; + } + + // DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't + // think we can) + // Stop WindSeedClientNotify from being sent for security purposes. + if (PacketOpcodesUtils.BANNED_PACKETS.contains(packet.getOpcode())) { + return; + } + + // Header + if (packet.shouldBuildHeader()) { + packet.buildHeader(this.getNextClientSequence()); + } + + // Log + switch (GAME_INFO.logPackets) { + case ALL -> { + if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode()) + || GAME_INFO.isShowLoopPackets) { + logPacket("SEND", packet.getOpcode(), packet.getData()); + } + } + case WHITELIST -> { + if (SERVER.debugWhitelist.contains(packet.getOpcode())) { + logPacket("SEND", packet.getOpcode(), packet.getData()); + } + } + case BLACKLIST -> { + if (!SERVER.debugBlacklist.contains(packet.getOpcode())) { + logPacket("SEND", packet.getOpcode(), packet.getData()); + } + } + default -> {} + } + + // Invoke event. + SendPacketEvent event = new SendPacketEvent(this, packet); + event.call(); + if (!event.isCanceled()) { // If event is not cancelled, continue. + tunnel.writeData(event.getPacket().build()); + } + } + + @Override + public void onConnected(GameSessionManager.KcpTunnel tunnel) { + this.tunnel = tunnel; + Grasscutter.getLogger().info(translate("messages.game.connect", this.getAddress().toString())); + } + + @Override + public void handleReceive(byte[] bytes) { + // Decrypt and turn back into a packet + Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY); + ByteBuf packet = Unpooled.wrappedBuffer(bytes); + + // Log + // logPacket(packet); + // Handle + try { + boolean allDebug = GAME_INFO.logPackets == ServerDebugMode.ALL; + while (packet.readableBytes() > 0) { + // Length + if (packet.readableBytes() < 12) { + return; + } + // Packet sanity check + int const1 = packet.readShort(); + if (const1 != 17767) { + if (allDebug) { + Grasscutter.getLogger() + .error("Bad Data Package Received: got {} ,expect 17767", const1); + } + return; // Bad packet + } + // Data + int opcode = packet.readShort(); + int headerLength = packet.readShort(); + int payloadLength = packet.readInt(); + byte[] header = new byte[headerLength]; + byte[] payload = new byte[payloadLength]; + + packet.readBytes(header); + packet.readBytes(payload); + // Sanity check #2 + int const2 = packet.readShort(); + if (const2 != -30293) { + if (allDebug) { + Grasscutter.getLogger() + .error("Bad Data Package Received: got {} ,expect -30293", const2); + } + return; // Bad packet + } + + // Log packet + switch (GAME_INFO.logPackets) { + case ALL -> { + if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode) || GAME_INFO.isShowLoopPackets) { + logPacket("RECV", opcode, payload); + } + } + case WHITELIST -> { + if (SERVER.debugWhitelist.contains(opcode)) { + logPacket("RECV", opcode, payload); + } + } + case BLACKLIST -> { + if (!(SERVER.debugBlacklist.contains(opcode))) { + logPacket("RECV", opcode, payload); + } + } + default -> {} + } + + // Handle + getServer().getPacketHandler().handle(this, opcode, header, payload); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + // byteBuf.release(); //Needn't + packet.release(); + } + } + + @Override + public void handleClose() { + setState(SessionState.INACTIVE); + // send disconnection pack in case of reconnection + Grasscutter.getLogger() + .info(translate("messages.game.disconnect", this.getAddress().toString())); + // Save after disconnecting + if (this.isLoggedIn()) { + Player player = getPlayer(); + // Call logout event. + player.onLogout(); + } + try { + send(new BasePacket(PacketOpcodes.ServerDisconnectClientNotify)); + } catch (Throwable ignore) { + Grasscutter.getLogger().warn("closing {} error", getAddress().getAddress().getHostAddress()); + } + tunnel = null; + } + + public void close() { + tunnel.close(); + } + + public boolean isActive() { + return getState() == SessionState.ACTIVE; + } + + public enum SessionState { + INACTIVE, + WAITING_FOR_TOKEN, + WAITING_FOR_LOGIN, + PICKING_CHARACTER, + ACTIVE, + ACCOUNT_BANNED + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameSessionManager.java b/src/main/java/emu/grasscutter/server/game/GameSessionManager.java index 62b4b717c..185ad2c0a 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSessionManager.java +++ b/src/main/java/emu/grasscutter/server/game/GameSessionManager.java @@ -1,115 +1,115 @@ -package emu.grasscutter.server.game; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.utils.Utils; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.DefaultEventLoop; -import kcp.highway.KcpListener; -import kcp.highway.Ukcp; - -import java.net.InetSocketAddress; -import java.util.concurrent.ConcurrentHashMap; - -public class GameSessionManager { - private static final DefaultEventLoop logicThread = new DefaultEventLoop(); - private static final ConcurrentHashMap sessions = new ConcurrentHashMap<>(); - private static final KcpListener listener = new KcpListener() { - @Override - public void onConnected(Ukcp ukcp) { - int times = 0; - GameServer server = Grasscutter.getGameServer(); - while (server == null) {//Waiting server to establish - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - ukcp.close(); - return; - } - if (times++ > 5) { - Grasscutter.getLogger().error("Service is not available!"); - ukcp.close(); - return; - } - server = Grasscutter.getGameServer(); - } - GameSession conversation = new GameSession(server); - conversation.onConnected(new KcpTunnel() { - @Override - public InetSocketAddress getAddress() { - return ukcp.user().getRemoteAddress(); - } - - @Override - public void writeData(byte[] bytes) { - ByteBuf buf = Unpooled.wrappedBuffer(bytes); - ukcp.write(buf); - buf.release(); - } - - @Override - public void close() { - ukcp.close(); - } - - @Override - public int getSrtt() { - return ukcp.srtt(); - } - }); - sessions.put(ukcp, conversation); - } - - @Override - public void handleReceive(ByteBuf buf, Ukcp kcp) { - byte[] byteData = Utils.byteBufToArray(buf); - logicThread.execute(() -> { - try { - GameSession conversation = sessions.get(kcp); - if (conversation != null) { - conversation.handleReceive(byteData); - } - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - @Override - public void handleException(Throwable ex, Ukcp ukcp) { - - } - - @Override - public void handleClose(Ukcp ukcp) { - GameSession conversation = sessions.get(ukcp); - if (conversation != null) { - conversation.handleClose(); - sessions.remove(ukcp); - } - } - }; - - public static KcpListener getListener() { - return listener; - } - - interface KcpTunnel { - InetSocketAddress getAddress(); - - void writeData(byte[] bytes); - - void close(); - - int getSrtt(); - } - - interface KcpChannel { - void onConnected(KcpTunnel tunnel); - - void handleClose(); - - void handleReceive(byte[] bytes); - } -} +package emu.grasscutter.server.game; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.utils.Utils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.DefaultEventLoop; +import java.net.InetSocketAddress; +import java.util.concurrent.ConcurrentHashMap; +import kcp.highway.KcpListener; +import kcp.highway.Ukcp; + +public class GameSessionManager { + private static final DefaultEventLoop logicThread = new DefaultEventLoop(); + private static final ConcurrentHashMap sessions = new ConcurrentHashMap<>(); + private static final KcpListener listener = + new KcpListener() { + @Override + public void onConnected(Ukcp ukcp) { + int times = 0; + GameServer server = Grasscutter.getGameServer(); + while (server == null) { // Waiting server to establish + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + ukcp.close(); + return; + } + if (times++ > 5) { + Grasscutter.getLogger().error("Service is not available!"); + ukcp.close(); + return; + } + server = Grasscutter.getGameServer(); + } + GameSession conversation = new GameSession(server); + conversation.onConnected( + new KcpTunnel() { + @Override + public InetSocketAddress getAddress() { + return ukcp.user().getRemoteAddress(); + } + + @Override + public void writeData(byte[] bytes) { + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + ukcp.write(buf); + buf.release(); + } + + @Override + public void close() { + ukcp.close(); + } + + @Override + public int getSrtt() { + return ukcp.srtt(); + } + }); + sessions.put(ukcp, conversation); + } + + @Override + public void handleReceive(ByteBuf buf, Ukcp kcp) { + byte[] byteData = Utils.byteBufToArray(buf); + logicThread.execute( + () -> { + try { + GameSession conversation = sessions.get(kcp); + if (conversation != null) { + conversation.handleReceive(byteData); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + @Override + public void handleException(Throwable ex, Ukcp ukcp) {} + + @Override + public void handleClose(Ukcp ukcp) { + GameSession conversation = sessions.get(ukcp); + if (conversation != null) { + conversation.handleClose(); + sessions.remove(ukcp); + } + } + }; + + public static KcpListener getListener() { + return listener; + } + + interface KcpTunnel { + InetSocketAddress getAddress(); + + void writeData(byte[] bytes); + + void close(); + + int getSrtt(); + } + + interface KcpChannel { + void onConnected(KcpTunnel tunnel); + + void handleClose(); + + void handleReceive(byte[] bytes); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/Router.java b/src/main/java/emu/grasscutter/server/http/Router.java index 22811de7c..3aedb39e3 100644 --- a/src/main/java/emu/grasscutter/server/http/Router.java +++ b/src/main/java/emu/grasscutter/server/http/Router.java @@ -1,35 +1,33 @@ -package emu.grasscutter.server.http; - -import io.javalin.Javalin; -import io.javalin.http.Handler; - -/** - * Defines routes for an {@link Javalin} instance. - */ -public interface Router { - - /** - * Called when the router is initialized by Express. - * - * @param javalin A Javalin instance. - */ - void applyRoutes(Javalin javalin); - - /** - * Applies this handler to all endpoint types - * - * @param javalin A Javalin instance. - * @param path - * @param ctx - * @return The Javalin instance. - */ - default Javalin allRoutes(Javalin javalin, String path, Handler ctx) { - javalin.get(path, ctx); - javalin.post(path, ctx); - javalin.put(path, ctx); - javalin.patch(path, ctx); - javalin.delete(path, ctx); - - return javalin; - } -} +package emu.grasscutter.server.http; + +import io.javalin.Javalin; +import io.javalin.http.Handler; + +/** Defines routes for an {@link Javalin} instance. */ +public interface Router { + + /** + * Called when the router is initialized by Express. + * + * @param javalin A Javalin instance. + */ + void applyRoutes(Javalin javalin); + + /** + * Applies this handler to all endpoint types + * + * @param javalin A Javalin instance. + * @param path + * @param ctx + * @return The Javalin instance. + */ + default Javalin allRoutes(Javalin javalin, String path, Handler ctx) { + javalin.get(path, ctx); + javalin.post(path, ctx); + javalin.put(path, ctx); + javalin.patch(path, ctx); + javalin.delete(path, ctx); + + return javalin; + } +} diff --git a/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java b/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java index 09dcb2ec7..23b512eed 100644 --- a/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java +++ b/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java @@ -1,130 +1,160 @@ -package emu.grasscutter.server.http.dispatch; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.auth.AuthenticationSystem; -import emu.grasscutter.auth.OAuthAuthenticator.ClientType; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.server.http.objects.ComboTokenReqJson; -import emu.grasscutter.server.http.objects.ComboTokenReqJson.LoginTokenData; -import emu.grasscutter.server.http.objects.LoginAccountRequestJson; -import emu.grasscutter.server.http.objects.LoginTokenRequestJson; -import emu.grasscutter.utils.JsonUtils; -import io.javalin.Javalin; -import io.javalin.http.Context; - -import static emu.grasscutter.utils.Language.translate; - -/** - * Handles requests related to authentication. (aka dispatch) - */ -public final class DispatchHandler implements Router { - /** - * @route /hk4e_global/mdk/shield/api/login - */ - private static void clientLogin(Context ctx) { - // Parse body data. - String rawBodyData = ctx.body(); - var bodyData = JsonUtils.decode(rawBodyData, LoginAccountRequestJson.class); - - // Validate body data. - if (bodyData == null) - return; - - // Pass data to authentication handler. - var responseData = Grasscutter.getAuthenticationSystem() - .getPasswordAuthenticator() - .authenticate(AuthenticationSystem.fromPasswordRequest(ctx, bodyData)); - // Send response. - ctx.json(responseData); - - // Log to console. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); - } - - /** - * @route /hk4e_global/mdk/shield/api/verify - */ - private static void tokenLogin(Context ctx) { - // Parse body data. - String rawBodyData = ctx.body(); - var bodyData = JsonUtils.decode(rawBodyData, LoginTokenRequestJson.class); - - // Validate body data. - if (bodyData == null) - return; - - // Pass data to authentication handler. - var responseData = Grasscutter.getAuthenticationSystem() - .getTokenAuthenticator() - .authenticate(AuthenticationSystem.fromTokenRequest(ctx, bodyData)); - // Send response. - ctx.json(responseData); - - // Log to console. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); - } - - /** - * @route /hk4e_global/combo/granter/login/v2/login - */ - private static void sessionKeyLogin(Context ctx) { - // Parse body data. - String rawBodyData = ctx.body(); - var bodyData = JsonUtils.decode(rawBodyData, ComboTokenReqJson.class); - - // Validate body data. - if (bodyData == null || bodyData.data == null) - return; - - // Decode additional body data. - var tokenData = JsonUtils.decode(bodyData.data, LoginTokenData.class); - - // Pass data to authentication handler. - var responseData = Grasscutter.getAuthenticationSystem() - .getSessionKeyAuthenticator() - .authenticate(AuthenticationSystem.fromComboTokenRequest(ctx, bodyData, tokenData)); - // Send response. - ctx.json(responseData); - - // Log to console. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); - } - - @Override - public void applyRoutes(Javalin javalin) { - // OS - // Username & Password login (from client). - javalin.post("/hk4e_global/mdk/shield/api/login", DispatchHandler::clientLogin); - // Cached token login (from registry). - javalin.post("/hk4e_global/mdk/shield/api/verify", DispatchHandler::tokenLogin); - // Combo token login (from session key). - javalin.post("/hk4e_global/combo/granter/login/v2/login", DispatchHandler::sessionKeyLogin); - - // CN - // Username & Password login (from client). - javalin.post("/hk4e_cn/mdk/shield/api/login", DispatchHandler::clientLogin); - // Cached token login (from registry). - javalin.post("/hk4e_cn/mdk/shield/api/verify", DispatchHandler::tokenLogin); - // Combo token login (from session key). - javalin.post("/hk4e_cn/combo/granter/login/v2/login", DispatchHandler::sessionKeyLogin); - - // External login (from other clients). - javalin.get("/authentication/type", ctx -> ctx.result(Grasscutter.getAuthenticationSystem().getClass().getSimpleName())); - javalin.post("/authentication/login", ctx -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() - .handleLogin(AuthenticationSystem.fromExternalRequest(ctx))); - javalin.post("/authentication/register", ctx -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() - .handleAccountCreation(AuthenticationSystem.fromExternalRequest(ctx))); - javalin.post("/authentication/change_password", ctx -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() - .handlePasswordReset(AuthenticationSystem.fromExternalRequest(ctx))); - - // External login (from OAuth2). - javalin.post("/hk4e_global/mdk/shield/api/loginByThirdparty", ctx -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() - .handleLogin(AuthenticationSystem.fromExternalRequest(ctx))); - javalin.get("/authentication/openid/redirect", ctx -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() - .handleTokenProcess(AuthenticationSystem.fromExternalRequest(ctx))); - javalin.get("/Api/twitter_login", ctx -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() - .handleRedirection(AuthenticationSystem.fromExternalRequest(ctx), ClientType.DESKTOP)); - javalin.get("/sdkTwitterLogin.html", ctx -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() - .handleRedirection(AuthenticationSystem.fromExternalRequest(ctx), ClientType.MOBILE)); - } -} +package emu.grasscutter.server.http.dispatch; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem; +import emu.grasscutter.auth.OAuthAuthenticator.ClientType; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.ComboTokenReqJson; +import emu.grasscutter.server.http.objects.ComboTokenReqJson.LoginTokenData; +import emu.grasscutter.server.http.objects.LoginAccountRequestJson; +import emu.grasscutter.server.http.objects.LoginTokenRequestJson; +import emu.grasscutter.utils.JsonUtils; +import io.javalin.Javalin; +import io.javalin.http.Context; + +/** Handles requests related to authentication. (aka dispatch) */ +public final class DispatchHandler implements Router { + /** + * @route /hk4e_global/mdk/shield/api/login + */ + private static void clientLogin(Context ctx) { + // Parse body data. + String rawBodyData = ctx.body(); + var bodyData = JsonUtils.decode(rawBodyData, LoginAccountRequestJson.class); + + // Validate body data. + if (bodyData == null) return; + + // Pass data to authentication handler. + var responseData = + Grasscutter.getAuthenticationSystem() + .getPasswordAuthenticator() + .authenticate(AuthenticationSystem.fromPasswordRequest(ctx, bodyData)); + // Send response. + ctx.json(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); + } + + /** + * @route /hk4e_global/mdk/shield/api/verify + */ + private static void tokenLogin(Context ctx) { + // Parse body data. + String rawBodyData = ctx.body(); + var bodyData = JsonUtils.decode(rawBodyData, LoginTokenRequestJson.class); + + // Validate body data. + if (bodyData == null) return; + + // Pass data to authentication handler. + var responseData = + Grasscutter.getAuthenticationSystem() + .getTokenAuthenticator() + .authenticate(AuthenticationSystem.fromTokenRequest(ctx, bodyData)); + // Send response. + ctx.json(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); + } + + /** + * @route /hk4e_global/combo/granter/login/v2/login + */ + private static void sessionKeyLogin(Context ctx) { + // Parse body data. + String rawBodyData = ctx.body(); + var bodyData = JsonUtils.decode(rawBodyData, ComboTokenReqJson.class); + + // Validate body data. + if (bodyData == null || bodyData.data == null) return; + + // Decode additional body data. + var tokenData = JsonUtils.decode(bodyData.data, LoginTokenData.class); + + // Pass data to authentication handler. + var responseData = + Grasscutter.getAuthenticationSystem() + .getSessionKeyAuthenticator() + .authenticate(AuthenticationSystem.fromComboTokenRequest(ctx, bodyData, tokenData)); + // Send response. + ctx.json(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", ctx.ip())); + } + + @Override + public void applyRoutes(Javalin javalin) { + // OS + // Username & Password login (from client). + javalin.post("/hk4e_global/mdk/shield/api/login", DispatchHandler::clientLogin); + // Cached token login (from registry). + javalin.post("/hk4e_global/mdk/shield/api/verify", DispatchHandler::tokenLogin); + // Combo token login (from session key). + javalin.post("/hk4e_global/combo/granter/login/v2/login", DispatchHandler::sessionKeyLogin); + + // CN + // Username & Password login (from client). + javalin.post("/hk4e_cn/mdk/shield/api/login", DispatchHandler::clientLogin); + // Cached token login (from registry). + javalin.post("/hk4e_cn/mdk/shield/api/verify", DispatchHandler::tokenLogin); + // Combo token login (from session key). + javalin.post("/hk4e_cn/combo/granter/login/v2/login", DispatchHandler::sessionKeyLogin); + + // External login (from other clients). + javalin.get( + "/authentication/type", + ctx -> ctx.result(Grasscutter.getAuthenticationSystem().getClass().getSimpleName())); + javalin.post( + "/authentication/login", + ctx -> + Grasscutter.getAuthenticationSystem() + .getExternalAuthenticator() + .handleLogin(AuthenticationSystem.fromExternalRequest(ctx))); + javalin.post( + "/authentication/register", + ctx -> + Grasscutter.getAuthenticationSystem() + .getExternalAuthenticator() + .handleAccountCreation(AuthenticationSystem.fromExternalRequest(ctx))); + javalin.post( + "/authentication/change_password", + ctx -> + Grasscutter.getAuthenticationSystem() + .getExternalAuthenticator() + .handlePasswordReset(AuthenticationSystem.fromExternalRequest(ctx))); + + // External login (from OAuth2). + javalin.post( + "/hk4e_global/mdk/shield/api/loginByThirdparty", + ctx -> + Grasscutter.getAuthenticationSystem() + .getOAuthAuthenticator() + .handleLogin(AuthenticationSystem.fromExternalRequest(ctx))); + javalin.get( + "/authentication/openid/redirect", + ctx -> + Grasscutter.getAuthenticationSystem() + .getOAuthAuthenticator() + .handleTokenProcess(AuthenticationSystem.fromExternalRequest(ctx))); + javalin.get( + "/Api/twitter_login", + ctx -> + Grasscutter.getAuthenticationSystem() + .getOAuthAuthenticator() + .handleRedirection( + AuthenticationSystem.fromExternalRequest(ctx), ClientType.DESKTOP)); + javalin.get( + "/sdkTwitterLogin.html", + ctx -> + Grasscutter.getAuthenticationSystem() + .getOAuthAuthenticator() + .handleRedirection( + AuthenticationSystem.fromExternalRequest(ctx), ClientType.MOBILE)); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java b/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java index 76ca1b800..87e81e60d 100644 --- a/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java +++ b/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java @@ -1,304 +1,330 @@ -package emu.grasscutter.server.http.dispatch; - -import com.google.protobuf.ByteString; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp; -import emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp; -import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; -import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo; -import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent; -import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.server.http.objects.QueryCurRegionRspJson; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.Utils; -import io.javalin.Javalin; -import io.javalin.http.Context; -import org.slf4j.Logger; - -import javax.crypto.Cipher; -import java.io.ByteArrayOutputStream; -import java.security.Signature; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; - -import static emu.grasscutter.config.Configuration.*; - -/** - * Handles requests related to region queries. - */ -public final class RegionHandler implements Router { - private static final Map regions = new ConcurrentHashMap<>(); - private static String regionListResponse; - private static String regionListResponsecn; - - public RegionHandler() { - try { // Read & initialize region data. - this.initialize(); - } catch (Exception exception) { - Grasscutter.getLogger().error("Failed to initialize region data.", exception); - } - } - - /** - * Handle query region list request. - * - * @param ctx The context object for handling the request. - * @route /query_region_list - */ - private static void queryRegionList(Context ctx) { - // Get logger and query parameters. - Logger logger = Grasscutter.getLogger(); - if (ctx.queryParamMap().containsKey("version") && ctx.queryParamMap().containsKey("platform")) { - String versionName = ctx.queryParam("version"); - String versionCode = versionName.replaceAll("[/.0-9]*", ""); - String platformName = ctx.queryParam("platform"); - - // Determine the region list to use based on the version and platform. - if ("CNRELiOS".equals(versionCode) || "CNRELWin".equals(versionCode) - || "CNRELAndroid".equals(versionCode)) { - // Use the CN region list. - QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponsecn); - event.call(); - logger.debug("Connect to Chinese version"); - - // Respond with the event result. - ctx.result(event.getRegionList()); - } else if ("OSRELiOS".equals(versionCode) || "OSRELWin".equals(versionCode) - || "OSRELAndroid".equals(versionCode)) { - // Use the OS region list. - QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); - event.call(); - logger.debug("Connect to global version"); - - // Respond with the event result. - ctx.result(event.getRegionList()); - } else { - /* - * String regionListResponse = "CP///////////wE="; - * QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); - * event.call(); - * ctx.result(event.getRegionList()); - * return; - */ - // Use the default region list. - QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); - event.call(); - logger.debug("Connect to global version"); - - // Respond with the event result. - ctx.result(event.getRegionList()); - } - } else { - // Use the default region list. - QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); - event.call(); - logger.debug("Connect to global version"); - - // Respond with the event result. - ctx.result(event.getRegionList()); - } - // Log the request to the console. - Grasscutter.getLogger().info(String.format("[Dispatch] Client %s request: query_region_list", ctx.ip())); - } - - /** - * @route /query_cur_region/{region} - */ - private static void queryCurrentRegion(Context ctx) { - // Get region to query. - String regionName = ctx.pathParam("region"); - String versionName = ctx.queryParam("version"); - var region = regions.get(regionName); - - // Get region data. - String regionData = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="; - if (ctx.queryParamMap().values().size() > 0) { - if (region != null) - regionData = region.getBase64(); - } - - String[] versionCode = versionName.replaceAll(Pattern.compile("[a-zA-Z]").pattern(), "").split("\\."); - int versionMajor = Integer.parseInt(versionCode[0]); - int versionMinor = Integer.parseInt(versionCode[1]); - int versionFix = Integer.parseInt(versionCode[2]); - - if (versionMajor >= 3 || (versionMajor == 2 && versionMinor == 7 && versionFix >= 50) || (versionMajor == 2 && versionMinor == 8)) { - try { - QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(regionData); - event.call(); - - if (ctx.queryParam("dispatchSeed") == null) { - // More love for UA Patch players - var rsp = new QueryCurRegionRspJson(); - - rsp.content = event.getRegionInfo(); - rsp.sign = "TW9yZSBsb3ZlIGZvciBVQSBQYXRjaCBwbGF5ZXJz"; - - ctx.json(rsp); - return; - } - - String key_id = ctx.queryParam("key_id"); - - if (key_id == null) - throw new Exception("Key ID was not set"); - - Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(Integer.valueOf(key_id))); - var regionInfo = Utils.base64Decode(event.getRegionInfo()); - - //Encrypt regionInfo in chunks - ByteArrayOutputStream encryptedRegionInfoStream = new ByteArrayOutputStream(); - - //Thank you so much GH Copilot - int chunkSize = 256 - 11; - int regionInfoLength = regionInfo.length; - int numChunks = (int) Math.ceil(regionInfoLength / (double) chunkSize); - - for (int i = 0; i < numChunks; i++) { - byte[] chunk = Arrays.copyOfRange(regionInfo, i * chunkSize, Math.min((i + 1) * chunkSize, regionInfoLength)); - byte[] encryptedChunk = cipher.doFinal(chunk); - encryptedRegionInfoStream.write(encryptedChunk); - } - - Signature privateSignature = Signature.getInstance("SHA256withRSA"); - privateSignature.initSign(Crypto.CUR_SIGNING_KEY); - privateSignature.update(regionInfo); - - var rsp = new QueryCurRegionRspJson(); - - rsp.content = Utils.base64Encode(encryptedRegionInfoStream.toByteArray()); - rsp.sign = Utils.base64Encode(privateSignature.sign()); - - ctx.json(rsp); - } catch (Exception e) { - Grasscutter.getLogger().error("An error occurred while handling query_cur_region.", e); - } - } else { - // Invoke event. - QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(regionData); - event.call(); - // Respond with event result. - ctx.result(event.getRegionInfo()); - } - // Log to console. - Grasscutter.getLogger().info(String.format("Client %s request: query_cur_region/%s", ctx.ip(), regionName)); - } - - /** - * Gets the current region query. - * - * @return A {@link QueryCurrRegionHttpRsp} object. - */ - public static QueryCurrRegionHttpRsp getCurrentRegion() { - return SERVER.runMode == ServerRunMode.HYBRID ? regions.get("os_usa").getRegionQuery() : null; - } - - /** - * Configures region data according to configuration. - */ - private void initialize() { - String dispatchDomain = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" - + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" - + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); - - // Create regions. - List servers = new ArrayList<>(); - List usedNames = new ArrayList<>(); // List to check for potential naming conflicts. - - var configuredRegions = new ArrayList<>(List.of(DISPATCH_INFO.regions)); - if (SERVER.runMode != ServerRunMode.HYBRID && configuredRegions.size() == 0) { - Grasscutter.getLogger().error("[Dispatch] There are no game servers available. Exiting due to unplayable state."); - System.exit(1); - } else if (configuredRegions.size() == 0) - configuredRegions.add(new Region("os_usa", DISPATCH_INFO.defaultName, - lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress), - lr(GAME_INFO.accessPort, GAME_INFO.bindPort))); - - configuredRegions.forEach(region -> { - if (usedNames.contains(region.Name)) { - Grasscutter.getLogger().error("Region name already in use."); - return; - } - - // Create a region identifier. - var identifier = RegionSimpleInfo.newBuilder() - .setName(region.Name).setTitle(region.Title).setType("DEV_PUBLIC") - .setDispatchUrl(dispatchDomain + "/query_cur_region/" + region.Name) - .build(); - usedNames.add(region.Name); - servers.add(identifier); - - // Create a region info object. - var regionInfo = RegionInfo.newBuilder() - .setGateserverIp(region.Ip).setGateserverPort(region.Port) - .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) - .build(); - // Create an updated region query. - var updatedQuery = QueryCurrRegionHttpRsp.newBuilder().setRegionInfo(regionInfo).build(); - regions.put(region.Name, new RegionData(updatedQuery, Utils.base64Encode(updatedQuery.toByteString().toByteArray()))); - }); - - // Create a config object. - byte[] customConfig = "{\"sdkenv\":\"2\",\"checkdevice\":\"false\",\"loadPatch\":\"false\",\"showexception\":\"false\",\"regionConfig\":\"pm|fk|add\",\"downloadMode\":\"0\"}".getBytes(); - Crypto.xor(customConfig, Crypto.DISPATCH_KEY); // XOR the config with the key. - - // Create an updated region list. - QueryRegionListHttpRsp updatedRegionList = QueryRegionListHttpRsp.newBuilder() - .addAllRegionList(servers) - .setClientSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) - .setClientCustomConfigEncrypted(ByteString.copyFrom(customConfig)) - .setEnableLoginPc(true).build(); - - // Set the region list response. - regionListResponse = Utils.base64Encode(updatedRegionList.toByteString().toByteArray()); - - // CN - // Create a config object. - byte[] customConfigcn = "{\"sdkenv\":\"0\",\"checkdevice\":\"true\",\"loadPatch\":\"false\",\"showexception\":\"false\",\"regionConfig\":\"pm|fk|add\",\"downloadMode\":\"0\"}".getBytes(); - Crypto.xor(customConfigcn, Crypto.DISPATCH_KEY); // XOR the config with the key. - - // Create an updated region list. - QueryRegionListHttpRsp updatedRegionListcn = QueryRegionListHttpRsp.newBuilder() - .addAllRegionList(servers) - .setClientSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) - .setClientCustomConfigEncrypted(ByteString.copyFrom(customConfigcn)) - .setEnableLoginPc(true).build(); - - // Set the region list response. - regionListResponsecn = Utils.base64Encode(updatedRegionListcn.toByteString().toByteArray()); - } - - @Override - public void applyRoutes(Javalin javalin) { - javalin.get("/query_region_list", RegionHandler::queryRegionList); - javalin.get("/query_cur_region/{region}", RegionHandler::queryCurrentRegion); - } - - /** - * Region data container. - */ - public static class RegionData { - private final QueryCurrRegionHttpRsp regionQuery; - private final String base64; - - public RegionData(QueryCurrRegionHttpRsp prq, String b64) { - this.regionQuery = prq; - this.base64 = b64; - } - - public QueryCurrRegionHttpRsp getRegionQuery() { - return this.regionQuery; - } - - public String getBase64() { - return this.base64; - } - } -} +package emu.grasscutter.server.http.dispatch; + +import static emu.grasscutter.config.Configuration.*; + +import com.google.protobuf.ByteString; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp; +import emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp; +import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; +import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo; +import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent; +import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.QueryCurRegionRspJson; +import emu.grasscutter.utils.Crypto; +import emu.grasscutter.utils.Utils; +import io.javalin.Javalin; +import io.javalin.http.Context; +import java.io.ByteArrayOutputStream; +import java.security.Signature; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; +import javax.crypto.Cipher; +import org.slf4j.Logger; + +/** Handles requests related to region queries. */ +public final class RegionHandler implements Router { + private static final Map regions = new ConcurrentHashMap<>(); + private static String regionListResponse; + private static String regionListResponsecn; + + public RegionHandler() { + try { // Read & initialize region data. + this.initialize(); + } catch (Exception exception) { + Grasscutter.getLogger().error("Failed to initialize region data.", exception); + } + } + + /** + * Handle query region list request. + * + * @param ctx The context object for handling the request. + * @route /query_region_list + */ + private static void queryRegionList(Context ctx) { + // Get logger and query parameters. + Logger logger = Grasscutter.getLogger(); + if (ctx.queryParamMap().containsKey("version") && ctx.queryParamMap().containsKey("platform")) { + String versionName = ctx.queryParam("version"); + String versionCode = versionName.replaceAll("[/.0-9]*", ""); + String platformName = ctx.queryParam("platform"); + + // Determine the region list to use based on the version and platform. + if ("CNRELiOS".equals(versionCode) + || "CNRELWin".equals(versionCode) + || "CNRELAndroid".equals(versionCode)) { + // Use the CN region list. + QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponsecn); + event.call(); + logger.debug("Connect to Chinese version"); + + // Respond with the event result. + ctx.result(event.getRegionList()); + } else if ("OSRELiOS".equals(versionCode) + || "OSRELWin".equals(versionCode) + || "OSRELAndroid".equals(versionCode)) { + // Use the OS region list. + QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); + event.call(); + logger.debug("Connect to global version"); + + // Respond with the event result. + ctx.result(event.getRegionList()); + } else { + /* + * String regionListResponse = "CP///////////wE="; + * QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); + * event.call(); + * ctx.result(event.getRegionList()); + * return; + */ + // Use the default region list. + QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); + event.call(); + logger.debug("Connect to global version"); + + // Respond with the event result. + ctx.result(event.getRegionList()); + } + } else { + // Use the default region list. + QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); + event.call(); + logger.debug("Connect to global version"); + + // Respond with the event result. + ctx.result(event.getRegionList()); + } + // Log the request to the console. + Grasscutter.getLogger() + .info(String.format("[Dispatch] Client %s request: query_region_list", ctx.ip())); + } + + /** + * @route /query_cur_region/{region} + */ + private static void queryCurrentRegion(Context ctx) { + // Get region to query. + String regionName = ctx.pathParam("region"); + String versionName = ctx.queryParam("version"); + var region = regions.get(regionName); + + // Get region data. + String regionData = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="; + if (ctx.queryParamMap().values().size() > 0) { + if (region != null) regionData = region.getBase64(); + } + + String[] versionCode = + versionName.replaceAll(Pattern.compile("[a-zA-Z]").pattern(), "").split("\\."); + int versionMajor = Integer.parseInt(versionCode[0]); + int versionMinor = Integer.parseInt(versionCode[1]); + int versionFix = Integer.parseInt(versionCode[2]); + + if (versionMajor >= 3 + || (versionMajor == 2 && versionMinor == 7 && versionFix >= 50) + || (versionMajor == 2 && versionMinor == 8)) { + try { + QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(regionData); + event.call(); + + if (ctx.queryParam("dispatchSeed") == null) { + // More love for UA Patch players + var rsp = new QueryCurRegionRspJson(); + + rsp.content = event.getRegionInfo(); + rsp.sign = "TW9yZSBsb3ZlIGZvciBVQSBQYXRjaCBwbGF5ZXJz"; + + ctx.json(rsp); + return; + } + + String key_id = ctx.queryParam("key_id"); + + if (key_id == null) throw new Exception("Key ID was not set"); + + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(Integer.valueOf(key_id))); + var regionInfo = Utils.base64Decode(event.getRegionInfo()); + + // Encrypt regionInfo in chunks + ByteArrayOutputStream encryptedRegionInfoStream = new ByteArrayOutputStream(); + + // Thank you so much GH Copilot + int chunkSize = 256 - 11; + int regionInfoLength = regionInfo.length; + int numChunks = (int) Math.ceil(regionInfoLength / (double) chunkSize); + + for (int i = 0; i < numChunks; i++) { + byte[] chunk = + Arrays.copyOfRange( + regionInfo, i * chunkSize, Math.min((i + 1) * chunkSize, regionInfoLength)); + byte[] encryptedChunk = cipher.doFinal(chunk); + encryptedRegionInfoStream.write(encryptedChunk); + } + + Signature privateSignature = Signature.getInstance("SHA256withRSA"); + privateSignature.initSign(Crypto.CUR_SIGNING_KEY); + privateSignature.update(regionInfo); + + var rsp = new QueryCurRegionRspJson(); + + rsp.content = Utils.base64Encode(encryptedRegionInfoStream.toByteArray()); + rsp.sign = Utils.base64Encode(privateSignature.sign()); + + ctx.json(rsp); + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while handling query_cur_region.", e); + } + } else { + // Invoke event. + QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(regionData); + event.call(); + // Respond with event result. + ctx.result(event.getRegionInfo()); + } + // Log to console. + Grasscutter.getLogger() + .info(String.format("Client %s request: query_cur_region/%s", ctx.ip(), regionName)); + } + + /** + * Gets the current region query. + * + * @return A {@link QueryCurrRegionHttpRsp} object. + */ + public static QueryCurrRegionHttpRsp getCurrentRegion() { + return SERVER.runMode == ServerRunMode.HYBRID ? regions.get("os_usa").getRegionQuery() : null; + } + + /** Configures region data according to configuration. */ + private void initialize() { + String dispatchDomain = + "http" + + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); + + // Create regions. + List servers = new ArrayList<>(); + List usedNames = new ArrayList<>(); // List to check for potential naming conflicts. + + var configuredRegions = new ArrayList<>(List.of(DISPATCH_INFO.regions)); + if (SERVER.runMode != ServerRunMode.HYBRID && configuredRegions.size() == 0) { + Grasscutter.getLogger() + .error( + "[Dispatch] There are no game servers available. Exiting due to unplayable state."); + System.exit(1); + } else if (configuredRegions.size() == 0) + configuredRegions.add( + new Region( + "os_usa", + DISPATCH_INFO.defaultName, + lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress), + lr(GAME_INFO.accessPort, GAME_INFO.bindPort))); + + configuredRegions.forEach( + region -> { + if (usedNames.contains(region.Name)) { + Grasscutter.getLogger().error("Region name already in use."); + return; + } + + // Create a region identifier. + var identifier = + RegionSimpleInfo.newBuilder() + .setName(region.Name) + .setTitle(region.Title) + .setType("DEV_PUBLIC") + .setDispatchUrl(dispatchDomain + "/query_cur_region/" + region.Name) + .build(); + usedNames.add(region.Name); + servers.add(identifier); + + // Create a region info object. + var regionInfo = + RegionInfo.newBuilder() + .setGateserverIp(region.Ip) + .setGateserverPort(region.Port) + .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .build(); + // Create an updated region query. + var updatedQuery = QueryCurrRegionHttpRsp.newBuilder().setRegionInfo(regionInfo).build(); + regions.put( + region.Name, + new RegionData( + updatedQuery, Utils.base64Encode(updatedQuery.toByteString().toByteArray()))); + }); + + // Create a config object. + byte[] customConfig = + "{\"sdkenv\":\"2\",\"checkdevice\":\"false\",\"loadPatch\":\"false\",\"showexception\":\"false\",\"regionConfig\":\"pm|fk|add\",\"downloadMode\":\"0\"}" + .getBytes(); + Crypto.xor(customConfig, Crypto.DISPATCH_KEY); // XOR the config with the key. + + // Create an updated region list. + QueryRegionListHttpRsp updatedRegionList = + QueryRegionListHttpRsp.newBuilder() + .addAllRegionList(servers) + .setClientSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .setClientCustomConfigEncrypted(ByteString.copyFrom(customConfig)) + .setEnableLoginPc(true) + .build(); + + // Set the region list response. + regionListResponse = Utils.base64Encode(updatedRegionList.toByteString().toByteArray()); + + // CN + // Create a config object. + byte[] customConfigcn = + "{\"sdkenv\":\"0\",\"checkdevice\":\"true\",\"loadPatch\":\"false\",\"showexception\":\"false\",\"regionConfig\":\"pm|fk|add\",\"downloadMode\":\"0\"}" + .getBytes(); + Crypto.xor(customConfigcn, Crypto.DISPATCH_KEY); // XOR the config with the key. + + // Create an updated region list. + QueryRegionListHttpRsp updatedRegionListcn = + QueryRegionListHttpRsp.newBuilder() + .addAllRegionList(servers) + .setClientSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .setClientCustomConfigEncrypted(ByteString.copyFrom(customConfigcn)) + .setEnableLoginPc(true) + .build(); + + // Set the region list response. + regionListResponsecn = Utils.base64Encode(updatedRegionListcn.toByteString().toByteArray()); + } + + @Override + public void applyRoutes(Javalin javalin) { + javalin.get("/query_region_list", RegionHandler::queryRegionList); + javalin.get("/query_cur_region/{region}", RegionHandler::queryCurrentRegion); + } + + /** Region data container. */ + public static class RegionData { + private final QueryCurrRegionHttpRsp regionQuery; + private final String base64; + + public RegionData(QueryCurrRegionHttpRsp prq, String b64) { + this.regionQuery = prq; + this.base64 = b64; + } + + public QueryCurrRegionHttpRsp getRegionQuery() { + return this.regionQuery; + } + + public String getBase64() { + return this.base64; + } + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java index 1d38fbfc6..c34cfaaa0 100644 --- a/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java +++ b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java @@ -1,20 +1,20 @@ -package emu.grasscutter.server.http.documentation; - -import emu.grasscutter.server.http.Router; -import io.javalin.Javalin; - -public final class DocumentationServerHandler implements Router { - - @Override - public void applyRoutes(Javalin javalin) { - final RootRequestHandler root = new RootRequestHandler(); - final HandbookRequestHandler handbook = new HandbookRequestHandler(); - final GachaMappingRequestHandler gachaMapping = new GachaMappingRequestHandler(); - - // TODO: Removal - // TODO: Forward /documentation requests to https://grasscutter.io/wiki - javalin.get("/documentation/handbook", handbook::handle); - javalin.get("/documentation/gachamapping", gachaMapping::handle); - javalin.get("/documentation", root::handle); - } -} +package emu.grasscutter.server.http.documentation; + +import emu.grasscutter.server.http.Router; +import io.javalin.Javalin; + +public final class DocumentationServerHandler implements Router { + + @Override + public void applyRoutes(Javalin javalin) { + final RootRequestHandler root = new RootRequestHandler(); + final HandbookRequestHandler handbook = new HandbookRequestHandler(); + final GachaMappingRequestHandler gachaMapping = new GachaMappingRequestHandler(); + + // TODO: Removal + // TODO: Forward /documentation requests to https://grasscutter.io/wiki + javalin.get("/documentation/handbook", handbook::handle); + javalin.get("/documentation/gachamapping", gachaMapping::handle); + javalin.get("/documentation", root::handle); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java index 6bd26ffba..1ec9c35b9 100644 --- a/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java +++ b/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java @@ -1,24 +1,26 @@ -package emu.grasscutter.server.http.documentation; - -import emu.grasscutter.tools.Tools; -import emu.grasscutter.utils.Language; -import io.javalin.http.ContentType; -import io.javalin.http.Context; - -import java.util.List; - -import static emu.grasscutter.config.Configuration.DOCUMENT_LANGUAGE; - -final class GachaMappingRequestHandler implements DocumentationHandler { - private final List gachaJsons; - - GachaMappingRequestHandler() { - this.gachaJsons = Tools.createGachaMappingJsons(); - } - - @Override - public void handle(Context ctx) { - final int langIdx = Language.TextStrings.MAP_LANGUAGES.getOrDefault(DOCUMENT_LANGUAGE, 0); // TODO: This should really be based off the client language somehow - ctx.contentType(ContentType.APPLICATION_JSON).result(gachaJsons.get(langIdx)); - } -} +package emu.grasscutter.server.http.documentation; + +import static emu.grasscutter.config.Configuration.DOCUMENT_LANGUAGE; + +import emu.grasscutter.tools.Tools; +import emu.grasscutter.utils.Language; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import java.util.List; + +final class GachaMappingRequestHandler implements DocumentationHandler { + private final List gachaJsons; + + GachaMappingRequestHandler() { + this.gachaJsons = Tools.createGachaMappingJsons(); + } + + @Override + public void handle(Context ctx) { + final int langIdx = + Language.TextStrings.MAP_LANGUAGES.getOrDefault( + DOCUMENT_LANGUAGE, + 0); // TODO: This should really be based off the client language somehow + ctx.contentType(ContentType.APPLICATION_JSON).result(gachaJsons.get(langIdx)); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java index 30ddd25eb..f4737df50 100644 --- a/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java +++ b/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java @@ -1,148 +1,204 @@ -package emu.grasscutter.server.http.documentation; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.data.excels.MonsterData; -import emu.grasscutter.data.excels.SceneData; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Language; -import io.javalin.http.ContentType; -import io.javalin.http.Context; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -final class HandbookRequestHandler implements DocumentationHandler { - private List handbookHtmls; - - public HandbookRequestHandler() { - var templatePath = FileUtils.getDataPath("documentation/handbook.html"); - try { - this.handbookHtmls = generateHandbookHtmls(Files.readString(templatePath)); - } catch (IOException ignored) { - Grasscutter.getLogger().warn("File does not exist: " + templatePath); - } - } - - @Override - public void handle(Context ctx) { - int langIdx = 0; - String acceptLanguage = ctx.header("Accept-Language"); - if (acceptLanguage != null) { - Pattern localePattern = Pattern.compile("[a-z]+-[A-Z]+"); - Matcher matcher = localePattern.matcher(acceptLanguage); - if (matcher.find()) { - String lang = matcher.group(0); - langIdx = Language.TextStrings.MAP_GC_LANGUAGES.getOrDefault(lang, 0); - } - } - - if (this.handbookHtmls == null) { - ctx.status(500); - } else { - if (langIdx <= this.handbookHtmls.size() - 1) { - ctx.contentType(ContentType.TEXT_HTML); - ctx.result(this.handbookHtmls.get(langIdx)); - } - } - } - - private List generateHandbookHtmls(String template) { - final int NUM_LANGUAGES = Language.TextStrings.NUM_LANGUAGES; - final List output = new ArrayList<>(NUM_LANGUAGES); - final List languages = Language.TextStrings.getLanguages(); - final List sbs = new ArrayList<>(NUM_LANGUAGES); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.add(new StringBuilder()); - - // Commands table - CommandMap.getInstance().getHandlersAsList().forEach(cmd -> { - String label = cmd.getLabel(); - String descKey = cmd.getDescriptionKey(); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.get(langIdx).append("" + label + "" + languages.get(langIdx).get(descKey) + "\n"); - }); - sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n - final List cmdsTable = sbs.stream().map(StringBuilder::toString).toList(); - - // Avatars table - final Int2ObjectMap avatarMap = GameData.getAvatarDataMap(); - sbs.forEach(sb -> sb.setLength(0)); - avatarMap.keySet().intStream().sorted().mapToObj(avatarMap::get).forEach(data -> { - int id = data.getId(); - Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.get(langIdx).append("" + id + "" + name.get(langIdx) + "\n"); - }); - sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n - final List avatarsTable = sbs.stream().map(StringBuilder::toString).toList(); - - // Items table - final Int2ObjectMap itemMap = GameData.getItemDataMap(); - sbs.forEach(sb -> sb.setLength(0)); - itemMap.keySet().intStream().sorted().mapToObj(itemMap::get).forEach(data -> { - int id = data.getId(); - Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.get(langIdx).append("" + id + "" + name.get(langIdx) + "\n"); - }); - sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n - final List itemsTable = sbs.stream().map(StringBuilder::toString).toList(); - - // Scenes table - final Int2ObjectMap sceneMap = GameData.getSceneDataMap(); - sceneMap.keySet().intStream().sorted().mapToObj(sceneMap::get).forEach(data -> { - int id = data.getId(); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.get(langIdx).append("" + id + "" + data.getScriptData() + "\n"); - }); - sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n - final List scenesTable = sbs.stream().map(StringBuilder::toString).toList(); - - // Monsters table - final Int2ObjectMap monsterMap = GameData.getMonsterDataMap(); - monsterMap.keySet().intStream().sorted().mapToObj(monsterMap::get).forEach(data -> { - int id = data.getId(); - Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.get(langIdx).append("" + id + "" + name.get(langIdx) + "\n"); - }); - sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n - final List monstersTable = sbs.stream().map(StringBuilder::toString).toList(); - - // Add translated title etc. to the page. - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { - Language lang = languages.get(langIdx); - output.add(template - .replace("{{TITLE}}", lang.get("documentation.handbook.title")) - .replace("{{TITLE_COMMANDS}}", lang.get("documentation.handbook.title_commands")) - .replace("{{TITLE_AVATARS}}", lang.get("documentation.handbook.title_avatars")) - .replace("{{TITLE_ITEMS}}", lang.get("documentation.handbook.title_items")) - .replace("{{TITLE_SCENES}}", lang.get("documentation.handbook.title_scenes")) - .replace("{{TITLE_MONSTERS}}", lang.get("documentation.handbook.title_monsters")) - .replace("{{HEADER_ID}}", lang.get("documentation.handbook.header_id")) - .replace("{{HEADER_COMMAND}}", lang.get("documentation.handbook.header_command")) - .replace("{{HEADER_DESCRIPTION}}", lang.get("documentation.handbook.header_description")) - .replace("{{HEADER_AVATAR}}", lang.get("documentation.handbook.header_avatar")) - .replace("{{HEADER_ITEM}}", lang.get("documentation.handbook.header_item")) - .replace("{{HEADER_SCENE}}", lang.get("documentation.handbook.header_scene")) - .replace("{{HEADER_MONSTER}}", lang.get("documentation.handbook.header_monster")) - // Commands table - .replace("{{COMMANDS_TABLE}}", cmdsTable.get(langIdx)) - .replace("{{AVATARS_TABLE}}", avatarsTable.get(langIdx)) - .replace("{{ITEMS_TABLE}}", itemsTable.get(langIdx)) - .replace("{{SCENES_TABLE}}", scenesTable.get(langIdx)) - .replace("{{MONSTERS_TABLE}}", monstersTable.get(langIdx)) - ); - } - return output; - } -} +package emu.grasscutter.server.http.documentation; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.SceneData; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Language; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +final class HandbookRequestHandler implements DocumentationHandler { + private List handbookHtmls; + + public HandbookRequestHandler() { + var templatePath = FileUtils.getDataPath("documentation/handbook.html"); + try { + this.handbookHtmls = generateHandbookHtmls(Files.readString(templatePath)); + } catch (IOException ignored) { + Grasscutter.getLogger().warn("File does not exist: " + templatePath); + } + } + + @Override + public void handle(Context ctx) { + int langIdx = 0; + String acceptLanguage = ctx.header("Accept-Language"); + if (acceptLanguage != null) { + Pattern localePattern = Pattern.compile("[a-z]+-[A-Z]+"); + Matcher matcher = localePattern.matcher(acceptLanguage); + if (matcher.find()) { + String lang = matcher.group(0); + langIdx = Language.TextStrings.MAP_GC_LANGUAGES.getOrDefault(lang, 0); + } + } + + if (this.handbookHtmls == null) { + ctx.status(500); + } else { + if (langIdx <= this.handbookHtmls.size() - 1) { + ctx.contentType(ContentType.TEXT_HTML); + ctx.result(this.handbookHtmls.get(langIdx)); + } + } + } + + private List generateHandbookHtmls(String template) { + final int NUM_LANGUAGES = Language.TextStrings.NUM_LANGUAGES; + final List output = new ArrayList<>(NUM_LANGUAGES); + final List languages = Language.TextStrings.getLanguages(); + final List sbs = new ArrayList<>(NUM_LANGUAGES); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) sbs.add(new StringBuilder()); + + // Commands table + CommandMap.getInstance() + .getHandlersAsList() + .forEach( + cmd -> { + String label = cmd.getLabel(); + String descKey = cmd.getDescriptionKey(); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.get(langIdx) + .append( + "" + + label + + "" + + languages.get(langIdx).get(descKey) + + "\n"); + }); + sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n + final List cmdsTable = sbs.stream().map(StringBuilder::toString).toList(); + + // Avatars table + final Int2ObjectMap avatarMap = GameData.getAvatarDataMap(); + sbs.forEach(sb -> sb.setLength(0)); + avatarMap + .keySet() + .intStream() + .sorted() + .mapToObj(avatarMap::get) + .forEach( + data -> { + int id = data.getId(); + Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.get(langIdx) + .append( + "" + + id + + "" + + name.get(langIdx) + + "\n"); + }); + sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n + final List avatarsTable = sbs.stream().map(StringBuilder::toString).toList(); + + // Items table + final Int2ObjectMap itemMap = GameData.getItemDataMap(); + sbs.forEach(sb -> sb.setLength(0)); + itemMap + .keySet() + .intStream() + .sorted() + .mapToObj(itemMap::get) + .forEach( + data -> { + int id = data.getId(); + Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.get(langIdx) + .append( + "" + + id + + "" + + name.get(langIdx) + + "\n"); + }); + sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n + final List itemsTable = sbs.stream().map(StringBuilder::toString).toList(); + + // Scenes table + final Int2ObjectMap sceneMap = GameData.getSceneDataMap(); + sceneMap + .keySet() + .intStream() + .sorted() + .mapToObj(sceneMap::get) + .forEach( + data -> { + int id = data.getId(); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.get(langIdx) + .append( + "" + + id + + "" + + data.getScriptData() + + "\n"); + }); + sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n + final List scenesTable = sbs.stream().map(StringBuilder::toString).toList(); + + // Monsters table + final Int2ObjectMap monsterMap = GameData.getMonsterDataMap(); + monsterMap + .keySet() + .intStream() + .sorted() + .mapToObj(monsterMap::get) + .forEach( + data -> { + int id = data.getId(); + Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash()); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.get(langIdx) + .append( + "" + + id + + "" + + name.get(langIdx) + + "\n"); + }); + sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n + final List monstersTable = sbs.stream().map(StringBuilder::toString).toList(); + + // Add translated title etc. to the page. + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { + Language lang = languages.get(langIdx); + output.add( + template + .replace("{{TITLE}}", lang.get("documentation.handbook.title")) + .replace("{{TITLE_COMMANDS}}", lang.get("documentation.handbook.title_commands")) + .replace("{{TITLE_AVATARS}}", lang.get("documentation.handbook.title_avatars")) + .replace("{{TITLE_ITEMS}}", lang.get("documentation.handbook.title_items")) + .replace("{{TITLE_SCENES}}", lang.get("documentation.handbook.title_scenes")) + .replace("{{TITLE_MONSTERS}}", lang.get("documentation.handbook.title_monsters")) + .replace("{{HEADER_ID}}", lang.get("documentation.handbook.header_id")) + .replace("{{HEADER_COMMAND}}", lang.get("documentation.handbook.header_command")) + .replace( + "{{HEADER_DESCRIPTION}}", lang.get("documentation.handbook.header_description")) + .replace("{{HEADER_AVATAR}}", lang.get("documentation.handbook.header_avatar")) + .replace("{{HEADER_ITEM}}", lang.get("documentation.handbook.header_item")) + .replace("{{HEADER_SCENE}}", lang.get("documentation.handbook.header_scene")) + .replace("{{HEADER_MONSTER}}", lang.get("documentation.handbook.header_monster")) + // Commands table + .replace("{{COMMANDS_TABLE}}", cmdsTable.get(langIdx)) + .replace("{{AVATARS_TABLE}}", avatarsTable.get(langIdx)) + .replace("{{ITEMS_TABLE}}", itemsTable.get(langIdx)) + .replace("{{SCENES_TABLE}}", scenesTable.get(langIdx)) + .replace("{{MONSTERS_TABLE}}", monstersTable.get(langIdx))); + } + return output; + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java index 70a5122a1..19515387e 100644 --- a/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java +++ b/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java @@ -1,41 +1,42 @@ -package emu.grasscutter.server.http.documentation; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.utils.FileUtils; -import io.javalin.http.ContentType; -import io.javalin.http.Context; - -import java.io.IOException; -import java.nio.file.Files; - -import static emu.grasscutter.utils.Language.translate; - -final class RootRequestHandler implements DocumentationHandler { - - private final String template; - - public RootRequestHandler() { - var templatePath = FileUtils.getDataPath("documentation/index.html"); - String t = null; - try { - t = Files.readString(templatePath); - } catch (IOException ignored) { - Grasscutter.getLogger().warn("File does not exist: " + templatePath); - } - this.template = t; - } - - @Override - public void handle(Context ctx) { - if (template == null) { - ctx.status(500); - return; - } - - String content = template.replace("{{TITLE}}", translate("documentation.index.title")) - .replace("{{ITEM_HANDBOOK}}", translate("documentation.index.handbook")) - .replace("{{ITEM_GACHA_MAPPING}}", translate("documentation.index.gacha_mapping")); - ctx.contentType(ContentType.TEXT_HTML); - ctx.result(content); - } -} +package emu.grasscutter.server.http.documentation; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.utils.FileUtils; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import java.io.IOException; +import java.nio.file.Files; + +final class RootRequestHandler implements DocumentationHandler { + + private final String template; + + public RootRequestHandler() { + var templatePath = FileUtils.getDataPath("documentation/index.html"); + String t = null; + try { + t = Files.readString(templatePath); + } catch (IOException ignored) { + Grasscutter.getLogger().warn("File does not exist: " + templatePath); + } + this.template = t; + } + + @Override + public void handle(Context ctx) { + if (template == null) { + ctx.status(500); + return; + } + + String content = + template + .replace("{{TITLE}}", translate("documentation.index.title")) + .replace("{{ITEM_HANDBOOK}}", translate("documentation.index.handbook")) + .replace("{{ITEM_GACHA_MAPPING}}", translate("documentation.index.gacha_mapping")); + ctx.contentType(ContentType.TEXT_HTML); + ctx.result(content); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java index 8963f18e7..40ea55bd6 100644 --- a/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java +++ b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java @@ -1,98 +1,121 @@ -package emu.grasscutter.server.http.handlers; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.DataLoader; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.server.http.objects.HttpJsonResponse; -import emu.grasscutter.utils.FileUtils; -import io.javalin.Javalin; -import io.javalin.http.ContentType; -import io.javalin.http.Context; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; -import java.util.StringJoiner; - -import static emu.grasscutter.config.Configuration.*; - -/** - * Handles requests related to the announcements page. - */ -public final class AnnouncementsHandler implements Router { - private static void getAnnouncement(Context ctx) { - String data = ""; - if (Objects.equals(ctx.endpointHandlerPath(), "/common/hk4e_global/announcement/api/getAnnContent")) { - try { - data = FileUtils.readToString(DataLoader.load("GameAnnouncement.json")); - } catch (Exception e) { - if (e.getClass() == IOException.class) { - Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); - } - } - } else if (Objects.equals(ctx.endpointHandlerPath(), "/common/hk4e_global/announcement/api/getAnnList")) { - try { - data = FileUtils.readToString(DataLoader.load("GameAnnouncementList.json")); - } catch (Exception e) { - if (e.getClass() == IOException.class) { - Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); - } - } - } else { - ctx.result("{\"retcode\":404,\"message\":\"Unknown request path\"}"); - } - - if (data.isEmpty()) { - ctx.result("{\"retcode\":500,\"message\":\"Unable to fetch requsted content\"}"); - return; - } - - String dispatchDomain = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" - + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" - + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); - - data = data - .replace("{{DISPATCH_PUBLIC}}", dispatchDomain) - .replace("{{SYSTEM_TIME}}", String.valueOf(System.currentTimeMillis())); - ctx.result("{\"retcode\":0,\"message\":\"OK\",\"data\": " + data + "}"); - } - - private static void getPageResources(Context ctx) { - // Re-process the path - remove the first slash and prevent directory traversal - // (the first slash will act as root path when resolving local path) - String[] path = ctx.path().split("/"); - StringJoiner stringJoiner = new StringJoiner("/"); - for (String pathName : path) { - // Filter the illegal payload to prevent directory traversal - if (!pathName.isEmpty() && !pathName.equals("..") && !pathName.contains("\\")) { - stringJoiner.add(pathName); - } - } - try (InputStream filestream = DataLoader.load(stringJoiner.toString())) { - String possibleFilename = ctx.path(); - - ContentType fromExtension = ContentType.getContentTypeByExtension(possibleFilename.substring(possibleFilename.lastIndexOf(".") + 1)); - ctx.contentType(fromExtension != null ? fromExtension : ContentType.APPLICATION_OCTET_STREAM); - ctx.result(filestream.readAllBytes()); - } catch (Exception e) { - Grasscutter.getLogger().warn("File does not exist: " + ctx.path()); - ctx.status(404); - } - } - - @Override - public void applyRoutes(Javalin javalin) { - // hk4e-api-os.hoyoverse.com - this.allRoutes(javalin, "/common/hk4e_global/announcement/api/getAlertPic", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")); - // hk4e-api-os.hoyoverse.com - this.allRoutes(javalin, "/common/hk4e_global/announcement/api/getAlertAnn", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}")); - // hk4e-api-os.hoyoverse.com - this.allRoutes(javalin, "/common/hk4e_global/announcement/api/getAnnList", AnnouncementsHandler::getAnnouncement); - // hk4e-api-os-static.hoyoverse.com - this.allRoutes(javalin, "/common/hk4e_global/announcement/api/getAnnContent", AnnouncementsHandler::getAnnouncement); - // hk4e-sdk-os.hoyoverse.com - this.allRoutes(javalin, "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")); - - javalin.get("/hk4e/announcement/*", AnnouncementsHandler::getPageResources); - } -} +package emu.grasscutter.server.http.handlers; + +import static emu.grasscutter.config.Configuration.*; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.HttpJsonResponse; +import emu.grasscutter.utils.FileUtils; +import io.javalin.Javalin; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; +import java.util.StringJoiner; + +/** Handles requests related to the announcements page. */ +public final class AnnouncementsHandler implements Router { + private static void getAnnouncement(Context ctx) { + String data = ""; + if (Objects.equals( + ctx.endpointHandlerPath(), "/common/hk4e_global/announcement/api/getAnnContent")) { + try { + data = FileUtils.readToString(DataLoader.load("GameAnnouncement.json")); + } catch (Exception e) { + if (e.getClass() == IOException.class) { + Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); + } + } + } else if (Objects.equals( + ctx.endpointHandlerPath(), "/common/hk4e_global/announcement/api/getAnnList")) { + try { + data = FileUtils.readToString(DataLoader.load("GameAnnouncementList.json")); + } catch (Exception e) { + if (e.getClass() == IOException.class) { + Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); + } + } + } else { + ctx.result("{\"retcode\":404,\"message\":\"Unknown request path\"}"); + } + + if (data.isEmpty()) { + ctx.result("{\"retcode\":500,\"message\":\"Unable to fetch requsted content\"}"); + return; + } + + String dispatchDomain = + "http" + + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); + + data = + data.replace("{{DISPATCH_PUBLIC}}", dispatchDomain) + .replace("{{SYSTEM_TIME}}", String.valueOf(System.currentTimeMillis())); + ctx.result("{\"retcode\":0,\"message\":\"OK\",\"data\": " + data + "}"); + } + + private static void getPageResources(Context ctx) { + // Re-process the path - remove the first slash and prevent directory traversal + // (the first slash will act as root path when resolving local path) + String[] path = ctx.path().split("/"); + StringJoiner stringJoiner = new StringJoiner("/"); + for (String pathName : path) { + // Filter the illegal payload to prevent directory traversal + if (!pathName.isEmpty() && !pathName.equals("..") && !pathName.contains("\\")) { + stringJoiner.add(pathName); + } + } + try (InputStream filestream = DataLoader.load(stringJoiner.toString())) { + String possibleFilename = ctx.path(); + + ContentType fromExtension = + ContentType.getContentTypeByExtension( + possibleFilename.substring(possibleFilename.lastIndexOf(".") + 1)); + ctx.contentType(fromExtension != null ? fromExtension : ContentType.APPLICATION_OCTET_STREAM); + ctx.result(filestream.readAllBytes()); + } catch (Exception e) { + Grasscutter.getLogger().warn("File does not exist: " + ctx.path()); + ctx.status(404); + } + } + + @Override + public void applyRoutes(Javalin javalin) { + // hk4e-api-os.hoyoverse.com + this.allRoutes( + javalin, + "/common/hk4e_global/announcement/api/getAlertPic", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")); + // hk4e-api-os.hoyoverse.com + this.allRoutes( + javalin, + "/common/hk4e_global/announcement/api/getAlertAnn", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}")); + // hk4e-api-os.hoyoverse.com + this.allRoutes( + javalin, + "/common/hk4e_global/announcement/api/getAnnList", + AnnouncementsHandler::getAnnouncement); + // hk4e-api-os-static.hoyoverse.com + this.allRoutes( + javalin, + "/common/hk4e_global/announcement/api/getAnnContent", + AnnouncementsHandler::getAnnouncement); + // hk4e-sdk-os.hoyoverse.com + this.allRoutes( + javalin, + "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")); + + javalin.get("/hk4e/announcement/*", AnnouncementsHandler::getPageResources); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java index 7fd79a0f9..dbef3a852 100644 --- a/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java +++ b/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java @@ -1,140 +1,153 @@ -package emu.grasscutter.server.http.handlers; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.gacha.GachaBanner; -import emu.grasscutter.game.gacha.GachaSystem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; -import io.javalin.Javalin; -import io.javalin.http.ContentType; -import io.javalin.http.Context; -import io.javalin.http.staticfiles.Location; -import lombok.Getter; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.LinkedHashSet; -import java.util.Set; - -import static emu.grasscutter.utils.Language.translate; - -/** - * Handles all gacha-related HTTP requests. - */ -public final class GachaHandler implements Router { - @Getter - private static final Path gachaMappingsPath = FileUtils.getDataUserPath("gacha/mappings.js"); - @Deprecated(forRemoval = true) - public static final String gachaMappings = gachaMappingsPath.toString(); - - private static void gachaRecords(Context ctx) { - String sessionKey = ctx.queryParam("s"); - Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); - if (account == null) { - ctx.status(403).result("Requested account was not found"); - return; - } - Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); - if (player == null) { - ctx.status(403).result("No player associated with requested account"); - return; - } - - int page = 0, gachaType = 0; - if (ctx.queryParam("p") != null) - page = Integer.parseInt(ctx.queryParam("p")); - if (ctx.queryParam("gachaType") != null) - gachaType = Integer.parseInt(ctx.queryParam("gachaType")); - - String records = DatabaseHelper.getGachaRecords(player.getUid(), page, gachaType).toString(); - long maxPage = DatabaseHelper.getGachaRecordsMaxPage(player.getUid(), page, gachaType); - - String template = new String(FileUtils.read(FileUtils.getDataPath("gacha/records.html")), StandardCharsets.UTF_8) - .replace("{{REPLACE_RECORDS}}", records) - .replace("{{REPLACE_MAXPAGE}}", String.valueOf(maxPage)) - .replace("{{TITLE}}", translate(player, "gacha.records.title")) - .replace("{{DATE}}", translate(player, "gacha.records.date")) - .replace("{{ITEM}}", translate(player, "gacha.records.item")) - .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); - ctx.contentType(ContentType.TEXT_HTML); - ctx.result(template); - } - - private static void gachaDetails(Context ctx) { - Path detailsTemplate = FileUtils.getDataPath("gacha/details.html"); - String sessionKey = ctx.queryParam("s"); - Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); - if (account == null) { - ctx.status(403).result("Requested account was not found"); - return; - } - Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); - if (player == null) { - ctx.status(403).result("No player associated with requested account"); - return; - } - - String template; - try { - template = Files.readString(detailsTemplate); - } catch (IOException e) { - Grasscutter.getLogger().warn("Failed to read data/gacha/details.html"); - ctx.status(500); - return; - } - - // Add translated title etc. to the page. - template = template.replace("{{TITLE}}", translate(player, "gacha.details.title")) - .replace("{{AVAILABLE_FIVE_STARS}}", translate(player, "gacha.details.available_five_stars")) - .replace("{{AVAILABLE_FOUR_STARS}}", translate(player, "gacha.details.available_four_stars")) - .replace("{{AVAILABLE_THREE_STARS}}", translate(player, "gacha.details.available_three_stars")) - .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); - - // Get the banner info for the banner we want. - int scheduleId = Integer.parseInt(ctx.queryParam("scheduleId")); - GachaSystem manager = Grasscutter.getGameServer().getGachaSystem(); - GachaBanner banner = manager.getGachaBanners().get(scheduleId); - - // Add 5-star items. - Set fiveStarItems = new LinkedHashSet<>(); - - Arrays.stream(banner.getRateUpItems5()).forEach(i -> fiveStarItems.add(Integer.toString(i))); - Arrays.stream(banner.getFallbackItems5Pool1()).forEach(i -> fiveStarItems.add(Integer.toString(i))); - Arrays.stream(banner.getFallbackItems5Pool2()).forEach(i -> fiveStarItems.add(Integer.toString(i))); - - template = template.replace("{{FIVE_STARS}}", "[" + String.join(",", fiveStarItems) + "]"); - - // Add 4-star items. - Set fourStarItems = new LinkedHashSet<>(); - - Arrays.stream(banner.getRateUpItems4()).forEach(i -> fourStarItems.add(Integer.toString(i))); - Arrays.stream(banner.getFallbackItems4Pool1()).forEach(i -> fourStarItems.add(Integer.toString(i))); - Arrays.stream(banner.getFallbackItems4Pool2()).forEach(i -> fourStarItems.add(Integer.toString(i))); - - template = template.replace("{{FOUR_STARS}}", "[" + String.join(",", fourStarItems) + "]"); - - // Add 3-star items. - Set threeStarItems = new LinkedHashSet<>(); - Arrays.stream(banner.getFallbackItems3()).forEach(i -> threeStarItems.add(Integer.toString(i))); - template = template.replace("{{THREE_STARS}}", "[" + String.join(",", threeStarItems) + "]"); - - // Done. - ctx.contentType(ContentType.TEXT_HTML); - ctx.result(template); - } - - @Override - public void applyRoutes(Javalin javalin) { - javalin.get("/gacha", GachaHandler::gachaRecords); - javalin.get("/gacha/details", GachaHandler::gachaDetails); - - javalin._conf.addSinglePageRoot("/gacha/mappings", gachaMappingsPath.toString(), Location.EXTERNAL); // TODO: This ***must*** be changed to take the Path not a String. This might involve upgrading Javalin. - } -} +package emu.grasscutter.server.http.handlers; + +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.gacha.GachaBanner; +import emu.grasscutter.game.gacha.GachaSystem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import io.javalin.Javalin; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import io.javalin.http.staticfiles.Location; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; +import lombok.Getter; + +/** Handles all gacha-related HTTP requests. */ +public final class GachaHandler implements Router { + @Getter + private static final Path gachaMappingsPath = FileUtils.getDataUserPath("gacha/mappings.js"); + + @Deprecated(forRemoval = true) + public static final String gachaMappings = gachaMappingsPath.toString(); + + private static void gachaRecords(Context ctx) { + String sessionKey = ctx.queryParam("s"); + Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); + if (account == null) { + ctx.status(403).result("Requested account was not found"); + return; + } + Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (player == null) { + ctx.status(403).result("No player associated with requested account"); + return; + } + + int page = 0, gachaType = 0; + if (ctx.queryParam("p") != null) page = Integer.parseInt(ctx.queryParam("p")); + if (ctx.queryParam("gachaType") != null) + gachaType = Integer.parseInt(ctx.queryParam("gachaType")); + + String records = DatabaseHelper.getGachaRecords(player.getUid(), page, gachaType).toString(); + long maxPage = DatabaseHelper.getGachaRecordsMaxPage(player.getUid(), page, gachaType); + + String template = + new String( + FileUtils.read(FileUtils.getDataPath("gacha/records.html")), StandardCharsets.UTF_8) + .replace("{{REPLACE_RECORDS}}", records) + .replace("{{REPLACE_MAXPAGE}}", String.valueOf(maxPage)) + .replace("{{TITLE}}", translate(player, "gacha.records.title")) + .replace("{{DATE}}", translate(player, "gacha.records.date")) + .replace("{{ITEM}}", translate(player, "gacha.records.item")) + .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); + ctx.contentType(ContentType.TEXT_HTML); + ctx.result(template); + } + + private static void gachaDetails(Context ctx) { + Path detailsTemplate = FileUtils.getDataPath("gacha/details.html"); + String sessionKey = ctx.queryParam("s"); + Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); + if (account == null) { + ctx.status(403).result("Requested account was not found"); + return; + } + Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (player == null) { + ctx.status(403).result("No player associated with requested account"); + return; + } + + String template; + try { + template = Files.readString(detailsTemplate); + } catch (IOException e) { + Grasscutter.getLogger().warn("Failed to read data/gacha/details.html"); + ctx.status(500); + return; + } + + // Add translated title etc. to the page. + template = + template + .replace("{{TITLE}}", translate(player, "gacha.details.title")) + .replace( + "{{AVAILABLE_FIVE_STARS}}", translate(player, "gacha.details.available_five_stars")) + .replace( + "{{AVAILABLE_FOUR_STARS}}", translate(player, "gacha.details.available_four_stars")) + .replace( + "{{AVAILABLE_THREE_STARS}}", + translate(player, "gacha.details.available_three_stars")) + .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); + + // Get the banner info for the banner we want. + int scheduleId = Integer.parseInt(ctx.queryParam("scheduleId")); + GachaSystem manager = Grasscutter.getGameServer().getGachaSystem(); + GachaBanner banner = manager.getGachaBanners().get(scheduleId); + + // Add 5-star items. + Set fiveStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems5()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems5Pool1()) + .forEach(i -> fiveStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems5Pool2()) + .forEach(i -> fiveStarItems.add(Integer.toString(i))); + + template = template.replace("{{FIVE_STARS}}", "[" + String.join(",", fiveStarItems) + "]"); + + // Add 4-star items. + Set fourStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems4()).forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems4Pool1()) + .forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems4Pool2()) + .forEach(i -> fourStarItems.add(Integer.toString(i))); + + template = template.replace("{{FOUR_STARS}}", "[" + String.join(",", fourStarItems) + "]"); + + // Add 3-star items. + Set threeStarItems = new LinkedHashSet<>(); + Arrays.stream(banner.getFallbackItems3()).forEach(i -> threeStarItems.add(Integer.toString(i))); + template = template.replace("{{THREE_STARS}}", "[" + String.join(",", threeStarItems) + "]"); + + // Done. + ctx.contentType(ContentType.TEXT_HTML); + ctx.result(template); + } + + @Override + public void applyRoutes(Javalin javalin) { + javalin.get("/gacha", GachaHandler::gachaRecords); + javalin.get("/gacha/details", GachaHandler::gachaDetails); + + javalin._conf.addSinglePageRoot( + "/gacha/mappings", + gachaMappingsPath.toString(), + Location.EXTERNAL); // TODO: This ***must*** be changed to take the Path not a String. This + // might involve upgrading Javalin. + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java index ff15a96d5..6ea0d7154 100644 --- a/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java +++ b/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java @@ -1,57 +1,85 @@ -package emu.grasscutter.server.http.handlers; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.server.http.objects.HttpJsonResponse; -import emu.grasscutter.server.http.objects.WebStaticVersionResponse; -import io.javalin.Javalin; -import io.javalin.http.Context; - -import static emu.grasscutter.config.Configuration.ACCOUNT; - -/** - * Handles all generic, hard-coded responses. - */ -public final class GenericHandler implements Router { - private static void serverStatus(Context ctx) { - int playerCount = Grasscutter.getGameServer().getPlayers().size(); - int maxPlayer = ACCOUNT.maxPlayer; - String version = GameConstants.VERSION; - - ctx.result("{\"retcode\":0,\"status\":{\"playerCount\":" + playerCount + ",\"maxPlayer\":" + maxPlayer + ",\"version\":\"" + version + "\"}}"); - } - - @Override - public void applyRoutes(Javalin javalin) { - // hk4e-sdk-os.hoyoverse.com - javalin.get("/hk4e_global/mdk/agreement/api/getAgreementInfos", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}")); - // hk4e-sdk-os.hoyoverse.com (this could be either GET or POST based on the observation of different clients) - this.allRoutes(javalin, "/hk4e_global/combo/granter/api/compareProtocolVersion", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}")); - - // api-account-os.hoyoverse.com - javalin.post("/account/risky/api/check", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}")); - - // sdk-os-static.hoyoverse.com - javalin.get("/combo/box/api/config/sdk/combo", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}")); - // hk4e-sdk-os-static.hoyoverse.com - javalin.get("/hk4e_global/combo/granter/api/getConfig", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")); - // hk4e-sdk-os-static.hoyoverse.com - javalin.get("/hk4e_global/mdk/shield/api/loadConfig", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")); - // Test api? - // abtest-api-data-sg.hoyoverse.com - javalin.post("/data_abtest_api/config/experiment/list", new HttpJsonResponse("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")); - - // log-upload-os.mihoyo.com - this.allRoutes(javalin, "/log/sdk/upload", new HttpJsonResponse("{\"code\":0}")); - this.allRoutes(javalin, "/sdk/upload", new HttpJsonResponse("{\"code\":0}")); - javalin.post("/sdk/dataUpload", new HttpJsonResponse("{\"code\":0}")); - // /perf/config/verify?device_id=xxx&platform=x&name=xxx - this.allRoutes(javalin, "/perf/config/verify", new HttpJsonResponse("{\"code\":0}")); - - // webstatic-sea.hoyoverse.com - javalin.get("/admin/mi18n/plat_oversea/*", new WebStaticVersionResponse()); - - javalin.get("/status/server", GenericHandler::serverStatus); - } -} +package emu.grasscutter.server.http.handlers; + +import static emu.grasscutter.config.Configuration.ACCOUNT; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.HttpJsonResponse; +import emu.grasscutter.server.http.objects.WebStaticVersionResponse; +import io.javalin.Javalin; +import io.javalin.http.Context; + +/** Handles all generic, hard-coded responses. */ +public final class GenericHandler implements Router { + private static void serverStatus(Context ctx) { + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + int maxPlayer = ACCOUNT.maxPlayer; + String version = GameConstants.VERSION; + + ctx.result( + "{\"retcode\":0,\"status\":{\"playerCount\":" + + playerCount + + ",\"maxPlayer\":" + + maxPlayer + + ",\"version\":\"" + + version + + "\"}}"); + } + + @Override + public void applyRoutes(Javalin javalin) { + // hk4e-sdk-os.hoyoverse.com + javalin.get( + "/hk4e_global/mdk/agreement/api/getAgreementInfos", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}")); + // hk4e-sdk-os.hoyoverse.com (this could be either GET or POST based on the observation of + // different clients) + this.allRoutes( + javalin, + "/hk4e_global/combo/granter/api/compareProtocolVersion", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}")); + + // api-account-os.hoyoverse.com + javalin.post( + "/account/risky/api/check", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}")); + + // sdk-os-static.hoyoverse.com + javalin.get( + "/combo/box/api/config/sdk/combo", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}")); + // hk4e-sdk-os-static.hoyoverse.com + javalin.get( + "/hk4e_global/combo/granter/api/getConfig", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")); + // hk4e-sdk-os-static.hoyoverse.com + javalin.get( + "/hk4e_global/mdk/shield/api/loadConfig", + new HttpJsonResponse( + "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")); + // Test api? + // abtest-api-data-sg.hoyoverse.com + javalin.post( + "/data_abtest_api/config/experiment/list", + new HttpJsonResponse( + "{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")); + + // log-upload-os.mihoyo.com + this.allRoutes(javalin, "/log/sdk/upload", new HttpJsonResponse("{\"code\":0}")); + this.allRoutes(javalin, "/sdk/upload", new HttpJsonResponse("{\"code\":0}")); + javalin.post("/sdk/dataUpload", new HttpJsonResponse("{\"code\":0}")); + // /perf/config/verify?device_id=xxx&platform=x&name=xxx + this.allRoutes(javalin, "/perf/config/verify", new HttpJsonResponse("{\"code\":0}")); + + // webstatic-sea.hoyoverse.com + javalin.get("/admin/mi18n/plat_oversea/*", new WebStaticVersionResponse()); + + javalin.get("/status/server", GenericHandler::serverStatus); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java index 39f23e527..ab4c5b125 100644 --- a/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java +++ b/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java @@ -1,23 +1,21 @@ -package emu.grasscutter.server.http.handlers; - -import emu.grasscutter.server.http.Router; -import io.javalin.Javalin; -import io.javalin.http.Context; - -/** - * Handles logging requests made to the server. - */ -public final class LogHandler implements Router { - private static void log(Context ctx) { - // TODO: Figure out how to dump request body and log to file. - ctx.result("{\"code\":0}"); - } - - @Override - public void applyRoutes(Javalin javalin) { - // overseauspider.yuanshen.com - javalin.post("/log", LogHandler::log); - // log-upload-os.mihoyo.com - javalin.post("/crash/dataUpload", LogHandler::log); - } -} +package emu.grasscutter.server.http.handlers; + +import emu.grasscutter.server.http.Router; +import io.javalin.Javalin; +import io.javalin.http.Context; + +/** Handles logging requests made to the server. */ +public final class LogHandler implements Router { + private static void log(Context ctx) { + // TODO: Figure out how to dump request body and log to file. + ctx.result("{\"code\":0}"); + } + + @Override + public void applyRoutes(Javalin javalin) { + // overseauspider.yuanshen.com + javalin.post("/log", LogHandler::log); + // log-upload-os.mihoyo.com + javalin.post("/crash/dataUpload", LogHandler::log); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java index 07cde5906..4f371c2da 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java @@ -1,15 +1,15 @@ -package emu.grasscutter.server.http.objects; - -public class ComboTokenReqJson { - public int app_id; - public int channel_id; - public String data; - public String device; - public String sign; - - public static class LoginTokenData { - public String uid; - public String token; - public boolean guest; - } -} +package emu.grasscutter.server.http.objects; + +public class ComboTokenReqJson { + public int app_id; + public int channel_id; + public String data; + public String device; + public String sign; + + public static class LoginTokenData { + public String uid; + public String token; + public boolean guest; + } +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java index c229a1e19..03dad809e 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java @@ -1,17 +1,17 @@ -package emu.grasscutter.server.http.objects; - -public class ComboTokenResJson { - public String message; - public int retcode; - public LoginData data = new LoginData(); - - public static class LoginData { - public int account_type = 1; - public boolean heartbeat; - public String combo_id; - public String combo_token; - public String open_id; - public String data = "{\"guest\":false}"; - public String fatigue_remind = null; // ? - } -} +package emu.grasscutter.server.http.objects; + +public class ComboTokenResJson { + public String message; + public int retcode; + public LoginData data = new LoginData(); + + public static class LoginData { + public int account_type = 1; + public boolean heartbeat; + public String combo_id; + public String combo_token; + public String open_id; + public String data = "{\"guest\":false}"; + public String fatigue_remind = null; // ? + } +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java b/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java index d457cbe76..757f34b7c 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java +++ b/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java @@ -1,42 +1,52 @@ -package emu.grasscutter.server.http.objects; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerDebugMode; -import io.javalin.http.Context; -import io.javalin.http.Handler; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Objects; - -import static emu.grasscutter.config.Configuration.DISPATCH_INFO; -import static emu.grasscutter.utils.Language.translate; - -public final class HttpJsonResponse implements Handler { - private final String response; - private final String[] missingRoutes = { // TODO: When http requests for theses routes are found please remove it from this list and update the route request type in the DispatchServer - "/common/hk4e_global/announcement/api/getAlertPic", - "/common/hk4e_global/announcement/api/getAlertAnn", - "/common/hk4e_global/announcement/api/getAnnList", - "/common/hk4e_global/announcement/api/getAnnContent", - "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", - "/log/sdk/upload", - "/sdk/upload", - "/perf/config/verify", - "/log", - "/crash/dataUpload" - }; - - public HttpJsonResponse(String response) { - this.response = response; - } - - @Override - public void handle(@NotNull Context ctx) throws Exception { - // Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled - if (DISPATCH_INFO.logRequests == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> Objects.equals(x, ctx.endpointHandlerPath()))) { - Grasscutter.getLogger().info(translate("messages.dispatch.request", ctx.ip(), ctx.method(), ctx.endpointHandlerPath()) + (DISPATCH_INFO.logRequests == ServerDebugMode.MISSING ? "(MISSING)" : "")); - } - ctx.result(response); - } -} +package emu.grasscutter.server.http.objects; + +import static emu.grasscutter.config.Configuration.DISPATCH_INFO; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerDebugMode; +import io.javalin.http.Context; +import io.javalin.http.Handler; +import java.util.Arrays; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; + +public final class HttpJsonResponse implements Handler { + private final String response; + private final String[] + missingRoutes = { // TODO: When http requests for theses routes are found please remove it + // from this list and update the route request type in the DispatchServer + "/common/hk4e_global/announcement/api/getAlertPic", + "/common/hk4e_global/announcement/api/getAlertAnn", + "/common/hk4e_global/announcement/api/getAnnList", + "/common/hk4e_global/announcement/api/getAnnContent", + "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", + "/log/sdk/upload", + "/sdk/upload", + "/perf/config/verify", + "/log", + "/crash/dataUpload" + }; + + public HttpJsonResponse(String response) { + this.response = response; + } + + @Override + public void handle(@NotNull Context ctx) throws Exception { + // Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled + if (DISPATCH_INFO.logRequests == ServerDebugMode.MISSING + && Arrays.stream(missingRoutes) + .anyMatch(x -> Objects.equals(x, ctx.endpointHandlerPath()))) { + Grasscutter.getLogger() + .info( + translate( + "messages.dispatch.request", + ctx.ip(), + ctx.method(), + ctx.endpointHandlerPath()) + + (DISPATCH_INFO.logRequests == ServerDebugMode.MISSING ? "(MISSING)" : "")); + } + ctx.result(response); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java index d0bd1c143..8e71cf02a 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java @@ -1,7 +1,7 @@ -package emu.grasscutter.server.http.objects; - -public class LoginAccountRequestJson { - public String account; - public String password; - public boolean is_crypto; -} +package emu.grasscutter.server.http.objects; + +public class LoginAccountRequestJson { + public String account; + public String password; + public boolean is_crypto; +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java index 0557c9c05..dd6fdd1cf 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java @@ -1,38 +1,38 @@ -package emu.grasscutter.server.http.objects; - -public class LoginResultJson { - public String message; - public int retcode; - public VerifyData data = new VerifyData(); - - public static class VerifyData { - public VerifyAccountData account = new VerifyAccountData(); - public boolean device_grant_required = false; - public String realname_operation = "NONE"; - public boolean realperson_required = false; - public boolean safe_mobile_required = false; - } - - public static class VerifyAccountData { - public String uid; - public String name = ""; - public String email = ""; - public String mobile = ""; - public String is_email_verify = "0"; - public String realname = ""; - public String identity_card = ""; - public String token; - public String safe_mobile = ""; - public String facebook_name = ""; - public String twitter_name = ""; - public String game_center_name = ""; - public String google_name = ""; - public String apple_name = ""; - public String sony_name = ""; - public String tap_name = ""; - public String country = "US"; - public String reactivate_ticket = ""; - public String area_code = "**"; - public String device_grant_ticket = ""; - } -} +package emu.grasscutter.server.http.objects; + +public class LoginResultJson { + public String message; + public int retcode; + public VerifyData data = new VerifyData(); + + public static class VerifyData { + public VerifyAccountData account = new VerifyAccountData(); + public boolean device_grant_required = false; + public String realname_operation = "NONE"; + public boolean realperson_required = false; + public boolean safe_mobile_required = false; + } + + public static class VerifyAccountData { + public String uid; + public String name = ""; + public String email = ""; + public String mobile = ""; + public String is_email_verify = "0"; + public String realname = ""; + public String identity_card = ""; + public String token; + public String safe_mobile = ""; + public String facebook_name = ""; + public String twitter_name = ""; + public String game_center_name = ""; + public String google_name = ""; + public String apple_name = ""; + public String sony_name = ""; + public String tap_name = ""; + public String country = "US"; + public String reactivate_ticket = ""; + public String area_code = "**"; + public String device_grant_ticket = ""; + } +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java index 2ab624d9e..216c86bfe 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java @@ -1,6 +1,6 @@ -package emu.grasscutter.server.http.objects; - -public class LoginTokenRequestJson { - public String uid; - public String token; -} +package emu.grasscutter.server.http.objects; + +public class LoginTokenRequestJson { + public String uid; + public String token; +} diff --git a/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java b/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java index 11d08236c..4ef451c50 100644 --- a/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java +++ b/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java @@ -1,35 +1,35 @@ -package emu.grasscutter.server.http.objects; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.utils.FileUtils; -import io.javalin.http.ContentType; -import io.javalin.http.Context; -import io.javalin.http.Handler; - -import java.io.IOException; -import java.io.InputStream; - -import static emu.grasscutter.config.Configuration.DISPATCH_INFO; - -public class WebStaticVersionResponse implements Handler { - - private static void getPageResources(String path, Context ctx) { - try (InputStream filestream = FileUtils.readResourceAsStream(path)) { - ContentType fromExtension = ContentType.getContentTypeByExtension(path.substring(path.lastIndexOf(".") + 1)); - ctx.contentType(fromExtension != null ? fromExtension : ContentType.APPLICATION_OCTET_STREAM); - ctx.result(filestream.readAllBytes()); - } catch (Exception e) { - if (DISPATCH_INFO.logRequests == Grasscutter.ServerDebugMode.MISSING) { - Grasscutter.getLogger().warn("Webstatic File Missing: " + path); - } - ctx.status(404); - } - } - - @Override - public void handle(Context ctx) throws IOException { - String requestFor = ctx.path().substring(ctx.path().lastIndexOf("-") + 1); - - getPageResources("/webstatic/" + requestFor, ctx); - } -} +package emu.grasscutter.server.http.objects; + +import static emu.grasscutter.config.Configuration.DISPATCH_INFO; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.utils.FileUtils; +import io.javalin.http.ContentType; +import io.javalin.http.Context; +import io.javalin.http.Handler; +import java.io.IOException; +import java.io.InputStream; + +public class WebStaticVersionResponse implements Handler { + + private static void getPageResources(String path, Context ctx) { + try (InputStream filestream = FileUtils.readResourceAsStream(path)) { + ContentType fromExtension = + ContentType.getContentTypeByExtension(path.substring(path.lastIndexOf(".") + 1)); + ctx.contentType(fromExtension != null ? fromExtension : ContentType.APPLICATION_OCTET_STREAM); + ctx.result(filestream.readAllBytes()); + } catch (Exception e) { + if (DISPATCH_INFO.logRequests == Grasscutter.ServerDebugMode.MISSING) { + Grasscutter.getLogger().warn("Webstatic File Missing: " + path); + } + ctx.status(404); + } + } + + @Override + public void handle(Context ctx) throws IOException { + String requestFor = ctx.path().substring(ctx.path().lastIndexOf("-") + 1); + + getPageResources("/webstatic/" + requestFor, ctx); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/Handler.java b/src/main/java/emu/grasscutter/server/packet/recv/Handler.java index 6eed61c54..2ed64a1aa 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/Handler.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/Handler.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.NONE) -public class Handler extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.NONE) +public class Handler extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java index d47143efe..ada634c55 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java @@ -1,25 +1,24 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AbilityInvocationsNotify) -public class HandlerAbilityInvocationsNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload); - - Player player = session.getPlayer(); - for (AbilityInvokeEntry entry : notif.getInvokesList()) { - player.getAbilityManager().onAbilityInvoke(entry); - player.getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AbilityInvocationsNotify) +public class HandlerAbilityInvocationsNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload); + + Player player = session.getPlayer(); + for (AbilityInvokeEntry entry : notif.getInvokesList()) { + player.getAbilityManager().onAbilityInvoke(entry); + player.getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerActivityTakeWatcherRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerActivityTakeWatcherRewardReq.java index 5545cbb86..8bc92ee45 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerActivityTakeWatcherRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerActivityTakeWatcherRewardReq.java @@ -1,25 +1,29 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityTakeWatcherRewardReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketActivityTakeWatcherRewardRsp; - -import java.util.Optional; - -@Opcodes(PacketOpcodes.ActivityTakeWatcherRewardReq) -public class HandlerActivityTakeWatcherRewardReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = ActivityTakeWatcherRewardReqOuterClass.ActivityTakeWatcherRewardReq.parseFrom(payload); - - Optional.ofNullable(session.getPlayer().getActivityManager().getPlayerActivityDataMap().get(req.getActivityId())) - .ifPresent(x -> x.takeWatcherReward(req.getWatcherId())); - - session.send(new PacketActivityTakeWatcherRewardRsp(req.getActivityId(), req.getWatcherId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityTakeWatcherRewardReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketActivityTakeWatcherRewardRsp; +import java.util.Optional; + +@Opcodes(PacketOpcodes.ActivityTakeWatcherRewardReq) +public class HandlerActivityTakeWatcherRewardReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + ActivityTakeWatcherRewardReqOuterClass.ActivityTakeWatcherRewardReq.parseFrom(payload); + + Optional.ofNullable( + session + .getPlayer() + .getActivityManager() + .getPlayerActivityDataMap() + .get(req.getActivityId())) + .ifPresent(x -> x.takeWatcherReward(req.getWatcherId())); + + session.send(new PacketActivityTakeWatcherRewardRsp(req.getActivityId(), req.getWatcherId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddBackupAvatarTeamReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddBackupAvatarTeamReq.java index ca481971c..cae92aca0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddBackupAvatarTeamReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddBackupAvatarTeamReq.java @@ -1,14 +1,14 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AddBackupAvatarTeamReq) -public class HandlerAddBackupAvatarTeamReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getTeamManager().addNewCustomTeam(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AddBackupAvatarTeamReq) +public class HandlerAddBackupAvatarTeamReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getTeamManager().addNewCustomTeam(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddQuestContentProgressReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddQuestContentProgressReq.java index ee9ba7080..d32623e3f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddQuestContentProgressReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAddQuestContentProgressReq.java @@ -1,33 +1,41 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.QuestData.QuestCondition; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp; - -import java.util.List; -import java.util.stream.Stream; - -@Opcodes(PacketOpcodes.AddQuestContentProgressReq) -public class HandlerAddQuestContentProgressReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload); - //Find all conditions in quest that are the same as the given one - Stream finishCond = GameData.getQuestDataMap().get(req.getParam()).getFinishCond().stream(); - Stream acceptCond = GameData.getQuestDataMap().get(req.getParam()).getAcceptCond().stream(); - Stream failCond = GameData.getQuestDataMap().get(req.getParam()).getFailCond().stream(); - List allCondMatch = Stream.concat(Stream.concat(acceptCond, failCond), finishCond).filter(p -> p.getType().getValue() == req.getContentType()).toList(); - for (QuestCondition cond : allCondMatch) { - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), cond.getParam()); - } - session.send(new PacketAddQuestContentProgressRsp(req.getContentType())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp; +import java.util.List; +import java.util.stream.Stream; + +@Opcodes(PacketOpcodes.AddQuestContentProgressReq) +public class HandlerAddQuestContentProgressReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload); + // Find all conditions in quest that are the same as the given one + Stream finishCond = + GameData.getQuestDataMap().get(req.getParam()).getFinishCond().stream(); + Stream acceptCond = + GameData.getQuestDataMap().get(req.getParam()).getAcceptCond().stream(); + Stream failCond = + GameData.getQuestDataMap().get(req.getParam()).getFailCond().stream(); + List allCondMatch = + Stream.concat(Stream.concat(acceptCond, failCond), finishCond) + .filter(p -> p.getType().getValue() == req.getContentType()) + .toList(); + for (QuestCondition cond : allCondMatch) { + session + .getPlayer() + .getQuestManager() + .triggerEvent( + QuestTrigger.getContentTriggerByValue(req.getContentType()), cond.getParam()); + } + session.send(new PacketAddQuestContentProgressRsp(req.getContentType())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAskAddFriendReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAskAddFriendReq.java index cc16d625b..4354d57d7 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAskAddFriendReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAskAddFriendReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AskAddFriendReqOuterClass.AskAddFriendReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AskAddFriendReq) -public class HandlerAskAddFriendReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AskAddFriendReq req = AskAddFriendReq.parseFrom(payload); - - session.getPlayer().getFriendsList().sendFriendRequest(req.getTargetUid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AskAddFriendReqOuterClass.AskAddFriendReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AskAddFriendReq) +public class HandlerAskAddFriendReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AskAddFriendReq req = AskAddFriendReq.parseFrom(payload); + + session.getPlayer().getFriendsList().sendFriendRequest(req.getTargetUid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeCostumeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeCostumeReq.java index 0c925b344..89530ba85 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeCostumeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeCostumeReq.java @@ -1,26 +1,28 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarChangeCostumeReqOuterClass.AvatarChangeCostumeReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeRsp; - -@Opcodes(PacketOpcodes.AvatarChangeCostumeReq) -public class HandlerAvatarChangeCostumeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarChangeCostumeReq req = AvatarChangeCostumeReq.parseFrom(payload); - - boolean success = session.getPlayer().getAvatars().changeCostume(req.getAvatarGuid(), req.getCostumeId()); - - if (success) { - session.getPlayer().sendPacket(new PacketAvatarChangeCostumeRsp(req.getAvatarGuid(), req.getCostumeId())); - } else { - session.getPlayer().sendPacket(new PacketAvatarChangeCostumeRsp()); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeCostumeReqOuterClass.AvatarChangeCostumeReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeRsp; + +@Opcodes(PacketOpcodes.AvatarChangeCostumeReq) +public class HandlerAvatarChangeCostumeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarChangeCostumeReq req = AvatarChangeCostumeReq.parseFrom(payload); + + boolean success = + session.getPlayer().getAvatars().changeCostume(req.getAvatarGuid(), req.getCostumeId()); + + if (success) { + session + .getPlayer() + .sendPacket(new PacketAvatarChangeCostumeRsp(req.getAvatarGuid(), req.getCostumeId())); + } else { + session.getPlayer().sendPacket(new PacketAvatarChangeCostumeRsp()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java index 6222ae1c0..b942a491f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java @@ -1,67 +1,69 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.AvatarSkillDepotData; -import emu.grasscutter.data.excels.WorldAreaData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarChangeElementTypeReqOuterClass.AvatarChangeElementTypeReq; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify; -import emu.grasscutter.server.packet.send.PacketAvatarChangeElementTypeRsp; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify; -import emu.grasscutter.server.packet.send.PacketAvatarSkillDepotChangeNotify; - -@Opcodes(PacketOpcodes.AvatarChangeElementTypeReq) -public class HandlerAvatarChangeElementTypeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarChangeElementTypeReq req = AvatarChangeElementTypeReq.parseFrom(payload); - - WorldAreaData area = GameData.getWorldAreaDataMap().get(req.getAreaId()); - - if (area == null || area.getElementType() == null || area.getElementType().getDepotValue() <= 0) { - session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); - return; - } - - // Get current avatar, should be one of the main characters - EntityAvatar mainCharacterEntity = session.getPlayer().getTeamManager().getCurrentAvatarEntity(); - Avatar mainCharacter = mainCharacterEntity.getAvatar(); - - int skillDepotId = area.getElementType().getDepotValue(); - switch (mainCharacter.getAvatarId()) { - case GameConstants.MAIN_CHARACTER_MALE -> skillDepotId += 500; - case GameConstants.MAIN_CHARACTER_FEMALE -> skillDepotId += 700; - default -> { - session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); - return; - } - } - - // Sanity checks for skill depots - AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(skillDepotId); - if (skillDepot == null || skillDepot.getId() == mainCharacter.getSkillDepotId()) { - session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); - return; - } - - // Set skill depot - mainCharacter.setSkillDepotData(skillDepot); - - // Success - session.send(new PacketAvatarChangeElementTypeRsp()); - - // Ability change packet - session.send(new PacketAvatarSkillDepotChangeNotify(mainCharacter)); - session.send(new PacketAbilityChangeNotify(mainCharacterEntity)); - session.send(new PacketAvatarFightPropNotify(mainCharacter)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.WorldAreaData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeElementTypeReqOuterClass.AvatarChangeElementTypeReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify; +import emu.grasscutter.server.packet.send.PacketAvatarChangeElementTypeRsp; +import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify; +import emu.grasscutter.server.packet.send.PacketAvatarSkillDepotChangeNotify; + +@Opcodes(PacketOpcodes.AvatarChangeElementTypeReq) +public class HandlerAvatarChangeElementTypeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarChangeElementTypeReq req = AvatarChangeElementTypeReq.parseFrom(payload); + + WorldAreaData area = GameData.getWorldAreaDataMap().get(req.getAreaId()); + + if (area == null + || area.getElementType() == null + || area.getElementType().getDepotValue() <= 0) { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + + // Get current avatar, should be one of the main characters + EntityAvatar mainCharacterEntity = + session.getPlayer().getTeamManager().getCurrentAvatarEntity(); + Avatar mainCharacter = mainCharacterEntity.getAvatar(); + + int skillDepotId = area.getElementType().getDepotValue(); + switch (mainCharacter.getAvatarId()) { + case GameConstants.MAIN_CHARACTER_MALE -> skillDepotId += 500; + case GameConstants.MAIN_CHARACTER_FEMALE -> skillDepotId += 700; + default -> { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + } + + // Sanity checks for skill depots + AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(skillDepotId); + if (skillDepot == null || skillDepot.getId() == mainCharacter.getSkillDepotId()) { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + + // Set skill depot + mainCharacter.setSkillDepotData(skillDepot); + + // Success + session.send(new PacketAvatarChangeElementTypeRsp()); + + // Ability change packet + session.send(new PacketAvatarSkillDepotChangeNotify(mainCharacter)); + session.send(new PacketAbilityChangeNotify(mainCharacterEntity)); + session.send(new PacketAvatarFightPropNotify(mainCharacter)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarDieAnimationEndReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarDieAnimationEndReq.java index 46f586259..19a972aad 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarDieAnimationEndReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarDieAnimationEndReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarDieAnimationEndReqOuterClass.AvatarDieAnimationEndReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AvatarDieAnimationEndReq) -public class HandlerAvatarDieAnimationEndReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarDieAnimationEndReq req = AvatarDieAnimationEndReq.parseFrom(payload); - - session.getPlayer().getTeamManager().onAvatarDie(req.getDieGuid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarDieAnimationEndReqOuterClass.AvatarDieAnimationEndReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AvatarDieAnimationEndReq) +public class HandlerAvatarDieAnimationEndReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarDieAnimationEndReq req = AvatarDieAnimationEndReq.parseFrom(payload); + + session.getPlayer().getTeamManager().onAvatarDie(req.getDieGuid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionAllDataReq.java index eadb0f40a..ee01a564b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionAllDataReq.java @@ -1,16 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarExpeditionAllDataRsp; - -@Opcodes(PacketOpcodes.AvatarExpeditionAllDataReq) -public class HandlerAvatarExpeditionAllDataReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var player = session.getPlayer(); - session.send(new PacketAvatarExpeditionAllDataRsp(player.getExpeditionInfo(), player.getExpeditionLimit())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAvatarExpeditionAllDataRsp; + +@Opcodes(PacketOpcodes.AvatarExpeditionAllDataReq) +public class HandlerAvatarExpeditionAllDataReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var player = session.getPlayer(); + session.send( + new PacketAvatarExpeditionAllDataRsp( + player.getExpeditionInfo(), player.getExpeditionLimit())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionGetRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionGetRewardReq.java index fe57bc180..e6df45fa4 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionGetRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionGetRewardReq.java @@ -1,44 +1,47 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.game.expedition.ExpeditionRewardDataList; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionGetRewardReqOuterClass.AvatarExpeditionGetRewardReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarExpeditionGetRewardRsp; -import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; - -import java.util.ArrayList; -import java.util.List; - -@Opcodes(PacketOpcodes.AvatarExpeditionGetRewardReq) -public class HandlerAvatarExpeditionGetRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarExpeditionGetRewardReq req = AvatarExpeditionGetRewardReq.parseFrom(payload); - var player = session.getPlayer(); - - ExpeditionInfo expInfo = player.getExpeditionInfo(req.getAvatarGuid()); - List items = new ArrayList<>(); - List expeditionRewardDataLists = session.getServer().getExpeditionSystem().getExpeditionRewardDataList().get(expInfo.getExpId()); - - if (expeditionRewardDataLists != null) { - expeditionRewardDataLists.stream() - .filter(r -> r.getHourTime() == expInfo.getHourTime()) - .map(ExpeditionRewardDataList::getRewards) - .forEach(items::addAll); - } - - player.getInventory().addItems(items); - player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.ExpeditionReward)); - - player.removeExpeditionInfo(req.getAvatarGuid()); - player.save(); - session.send(new PacketAvatarExpeditionGetRewardRsp(player.getExpeditionInfo(), items)); - } -} - +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.game.expedition.ExpeditionRewardDataList; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionGetRewardReqOuterClass.AvatarExpeditionGetRewardReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAvatarExpeditionGetRewardRsp; +import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; +import java.util.ArrayList; +import java.util.List; + +@Opcodes(PacketOpcodes.AvatarExpeditionGetRewardReq) +public class HandlerAvatarExpeditionGetRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarExpeditionGetRewardReq req = AvatarExpeditionGetRewardReq.parseFrom(payload); + var player = session.getPlayer(); + + ExpeditionInfo expInfo = player.getExpeditionInfo(req.getAvatarGuid()); + List items = new ArrayList<>(); + List expeditionRewardDataLists = + session + .getServer() + .getExpeditionSystem() + .getExpeditionRewardDataList() + .get(expInfo.getExpId()); + + if (expeditionRewardDataLists != null) { + expeditionRewardDataLists.stream() + .filter(r -> r.getHourTime() == expInfo.getHourTime()) + .map(ExpeditionRewardDataList::getRewards) + .forEach(items::addAll); + } + + player.getInventory().addItems(items); + player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.ExpeditionReward)); + + player.removeExpeditionInfo(req.getAvatarGuid()); + player.save(); + session.send(new PacketAvatarExpeditionGetRewardRsp(player.getExpeditionInfo(), items)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java index 63c3ce526..34237acc9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java @@ -1,53 +1,55 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.RewardData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarDataNotify; -import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify; -import emu.grasscutter.server.packet.send.PacketAvatarFetterLevelRewardRsp; -import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify; - -@Opcodes(PacketOpcodes.AvatarFetterLevelRewardReq) -public class HandlerAvatarFetterLevelRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarFetterLevelRewardReq req = AvatarFetterLevelRewardReq.parseFrom(payload); - if (req.getFetterLevel() < 10) { - // You don't have a full level of fetter level, why do you want to get a divorce certificate? - session.send(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel())); - } else { - long avatarGuid = req.getAvatarGuid(); - - Avatar avatar = session - .getPlayer() - .getAvatars() - .getAvatarByGuid(avatarGuid); - - int rewardId = avatar.getNameCardRewardId(); - - RewardData card = GameData.getRewardDataMap().get(rewardId); - int cardId = card.getRewardItemList().get(0).getItemId(); - - if (session.getPlayer().getNameCardList().contains(cardId)) { - // Already got divorce certificate. - session.getPlayer().sendPacket(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel(), rewardId)); - return; - } - - GameItem item = new GameItem(cardId); - session.getPlayer().getInventory().addItem(item, ActionReason.FetterLevelReward); - session.getPlayer().sendPacket(new PacketUnlockNameCardNotify(cardId)); - session.send(new PacketAvatarFetterDataNotify(avatar)); - session.send(new PacketAvatarDataNotify(avatar.getPlayer())); - session.send(new PacketAvatarFetterLevelRewardRsp(avatarGuid, req.getFetterLevel(), rewardId)); - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.RewardData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAvatarDataNotify; +import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify; +import emu.grasscutter.server.packet.send.PacketAvatarFetterLevelRewardRsp; +import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify; + +@Opcodes(PacketOpcodes.AvatarFetterLevelRewardReq) +public class HandlerAvatarFetterLevelRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarFetterLevelRewardReq req = AvatarFetterLevelRewardReq.parseFrom(payload); + if (req.getFetterLevel() < 10) { + // You don't have a full level of fetter level, why do you want to get a divorce certificate? + session.send(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel())); + } else { + long avatarGuid = req.getAvatarGuid(); + + Avatar avatar = session.getPlayer().getAvatars().getAvatarByGuid(avatarGuid); + + int rewardId = avatar.getNameCardRewardId(); + + RewardData card = GameData.getRewardDataMap().get(rewardId); + int cardId = card.getRewardItemList().get(0).getItemId(); + + if (session.getPlayer().getNameCardList().contains(cardId)) { + // Already got divorce certificate. + session + .getPlayer() + .sendPacket( + new PacketAvatarFetterLevelRewardRsp( + req.getAvatarGuid(), req.getFetterLevel(), rewardId)); + return; + } + + GameItem item = new GameItem(cardId); + session.getPlayer().getInventory().addItem(item, ActionReason.FetterLevelReward); + session.getPlayer().sendPacket(new PacketUnlockNameCardNotify(cardId)); + session.send(new PacketAvatarFetterDataNotify(avatar)); + session.send(new PacketAvatarDataNotify(avatar.getPlayer())); + session.send( + new PacketAvatarFetterLevelRewardRsp(avatarGuid, req.getFetterLevel(), rewardId)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarPromoteReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarPromoteReq.java index 7ee1b5467..1cb3d9df3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarPromoteReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarPromoteReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarPromoteReqOuterClass.AvatarPromoteReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AvatarPromoteReq) -public class HandlerAvatarPromoteReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarPromoteReq req = AvatarPromoteReq.parseFrom(payload); - - // Ascend avatar - session.getServer().getInventorySystem().promoteAvatar(session.getPlayer(), req.getGuid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarPromoteReqOuterClass.AvatarPromoteReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AvatarPromoteReq) +public class HandlerAvatarPromoteReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarPromoteReq req = AvatarPromoteReq.parseFrom(payload); + + // Ascend avatar + session.getServer().getInventorySystem().promoteAvatar(session.getPlayer(), req.getGuid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarSkillUpgradeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarSkillUpgradeReq.java index 9cc09e771..c0655b980 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarSkillUpgradeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarSkillUpgradeReq.java @@ -1,22 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillUpgradeReqOuterClass.AvatarSkillUpgradeReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AvatarSkillUpgradeReq) -public class HandlerAvatarSkillUpgradeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarSkillUpgradeReq req = AvatarSkillUpgradeReq.parseFrom(payload); - - // Sanity checks - var avatar = session.getPlayer().getAvatars().getAvatarByGuid(req.getAvatarGuid()); - if (avatar == null) return; - // Level up avatar talent - avatar.upgradeSkill(req.getAvatarSkillId()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillUpgradeReqOuterClass.AvatarSkillUpgradeReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AvatarSkillUpgradeReq) +public class HandlerAvatarSkillUpgradeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarSkillUpgradeReq req = AvatarSkillUpgradeReq.parseFrom(payload); + + // Sanity checks + var avatar = session.getPlayer().getAvatars().getAvatarByGuid(req.getAvatarGuid()); + if (avatar == null) return; + // Level up avatar talent + avatar.upgradeSkill(req.getAvatarSkillId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarUpgradeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarUpgradeReq.java index f8d09e8cf..7e509a00a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarUpgradeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarUpgradeReq.java @@ -1,25 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarUpgradeReqOuterClass.AvatarUpgradeReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.AvatarUpgradeReq) -public class HandlerAvatarUpgradeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarUpgradeReq req = AvatarUpgradeReq.parseFrom(payload); - - // Level up avatar - session.getServer().getInventorySystem().upgradeAvatar( - session.getPlayer(), - req.getAvatarGuid(), - req.getItemId(), - req.getCount() - ); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarUpgradeReqOuterClass.AvatarUpgradeReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.AvatarUpgradeReq) +public class HandlerAvatarUpgradeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarUpgradeReq req = AvatarUpgradeReq.parseFrom(payload); + + // Level up avatar + session + .getServer() + .getInventorySystem() + .upgradeAvatar(session.getPlayer(), req.getAvatarGuid(), req.getItemId(), req.getCount()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarWearFlycloakReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarWearFlycloakReq.java index 3cd9ff7dd..cb02e4b83 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarWearFlycloakReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarWearFlycloakReq.java @@ -1,24 +1,27 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarWearFlycloakReqOuterClass.AvatarWearFlycloakReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarWearFlycloakRsp; - -@Opcodes(PacketOpcodes.AvatarWearFlycloakReq) -public class HandlerAvatarWearFlycloakReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - AvatarWearFlycloakReq req = AvatarWearFlycloakReq.parseFrom(payload); - - boolean success = session.getPlayer().getAvatars().wearFlycloak(req.getAvatarGuid(), req.getFlycloakId()); - - if (success) { - session.getPlayer().sendPacket(new PacketAvatarWearFlycloakRsp(req.getAvatarGuid(), req.getFlycloakId())); - } else { - session.getPlayer().sendPacket(new PacketAvatarWearFlycloakRsp()); - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarWearFlycloakReqOuterClass.AvatarWearFlycloakReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAvatarWearFlycloakRsp; + +@Opcodes(PacketOpcodes.AvatarWearFlycloakReq) +public class HandlerAvatarWearFlycloakReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarWearFlycloakReq req = AvatarWearFlycloakReq.parseFrom(payload); + + boolean success = + session.getPlayer().getAvatars().wearFlycloak(req.getAvatarGuid(), req.getFlycloakId()); + + if (success) { + session + .getPlayer() + .sendPacket(new PacketAvatarWearFlycloakRsp(req.getAvatarGuid(), req.getFlycloakId())); + } else { + session.getPlayer().sendPacket(new PacketAvatarWearFlycloakRsp()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBackMyWorldReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBackMyWorldReq.java index 012e4d11f..8ce17741e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBackMyWorldReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBackMyWorldReq.java @@ -1,33 +1,35 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketBackMyWorldRsp; - -@Opcodes(PacketOpcodes.BackMyWorldReq) -public class HandlerBackMyWorldReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - Scene scene = session.getPlayer().getScene(); - int prevScene = scene.getPrevScene(); - - // Sanity check for switching between teapot realms - if (prevScene >= 2000 && prevScene <= 2400) { - prevScene = 3; - } - - session.getPlayer().getWorld().transferPlayerToScene( - session.getPlayer(), - prevScene, - TeleportType.WAYPOINT, - session.getPlayer().getPrevPos()); - - session.send(new PacketBackMyWorldRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketBackMyWorldRsp; + +@Opcodes(PacketOpcodes.BackMyWorldReq) +public class HandlerBackMyWorldReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + Scene scene = session.getPlayer().getScene(); + int prevScene = scene.getPrevScene(); + + // Sanity check for switching between teapot realms + if (prevScene >= 2000 && prevScene <= 2400) { + prevScene = 3; + } + + session + .getPlayer() + .getWorld() + .transferPlayerToScene( + session.getPlayer(), + prevScene, + TeleportType.WAYPOINT, + session.getPlayer().getPrevPos()); + + session.send(new PacketBackMyWorldRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyBattlePassLevelReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyBattlePassLevelReq.java index 97d572668..cc8240fe3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyBattlePassLevelReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyBattlePassLevelReq.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BuyBattlePassLevelReqOuterClass.BuyBattlePassLevelReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketBuyBattlePassLevelRsp; - -@Opcodes(PacketOpcodes.BuyBattlePassLevelReq) -public class HandlerBuyBattlePassLevelReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - BuyBattlePassLevelReq req = BuyBattlePassLevelReq.parseFrom(payload); - - int buyLevel = session.getPlayer().getBattlePassManager().buyLevels(req.getBuyLevel()); - - session.send(new PacketBuyBattlePassLevelRsp(buyLevel)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyBattlePassLevelReqOuterClass.BuyBattlePassLevelReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketBuyBattlePassLevelRsp; + +@Opcodes(PacketOpcodes.BuyBattlePassLevelReq) +public class HandlerBuyBattlePassLevelReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + BuyBattlePassLevelReq req = BuyBattlePassLevelReq.parseFrom(payload); + + int buyLevel = session.getPlayer().getBattlePassManager().buyLevels(req.getBuyLevel()); + + session.send(new PacketBuyBattlePassLevelRsp(buyLevel)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java index 973eac9f7..4a177a642 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java @@ -1,73 +1,87 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.game.shop.ShopInfo; -import emu.grasscutter.game.shop.ShopLimit; -import emu.grasscutter.game.shop.ShopSystem; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BuyGoodsReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketBuyGoodsRsp; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -@Opcodes(PacketOpcodes.BuyGoodsReq) -public class HandlerBuyGoodsReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - BuyGoodsReqOuterClass.BuyGoodsReq buyGoodsReq = BuyGoodsReqOuterClass.BuyGoodsReq.parseFrom(payload); - List configShop = session.getServer().getShopSystem().getShopData().get(buyGoodsReq.getShopType()); - if (configShop == null) - return; - - // Don't trust your users' input - var player = session.getPlayer(); - List targetShopGoodsId = List.of(buyGoodsReq.getGoods().getGoodsId()); - for (int goodsId : targetShopGoodsId) { - Optional sg2 = configShop.stream().filter(x -> x.getGoodsId() == goodsId).findFirst(); - if (sg2.isEmpty()) - continue; - ShopInfo sg = sg2.get(); - - int currentTs = Utils.getCurrentSeconds(); - ShopLimit shopLimit = player.getGoodsLimit(sg.getGoodsId()); - int bought = 0; - if (shopLimit != null) { - if (currentTs > shopLimit.getNextRefreshTime()) { - shopLimit.setNextRefreshTime(ShopSystem.getShopNextRefreshTime(sg)); - } else { - bought = shopLimit.getHasBoughtInPeriod(); - } - player.save(); - } - - if ((bought + buyGoodsReq.getBuyCount() > sg.getBuyLimit()) && sg.getBuyLimit() != 0) { - return; - } - - List costs = new ArrayList(sg.getCostItemList()); // Can this even be null? - costs.add(new ItemParamData(202, sg.getScoin())); - costs.add(new ItemParamData(201, sg.getHcoin())); - costs.add(new ItemParamData(203, sg.getMcoin())); - if (!player.getInventory().payItems(costs, buyGoodsReq.getBuyCount())) { - return; - } - - player.addShopLimit(sg.getGoodsId(), buyGoodsReq.getBuyCount(), ShopSystem.getShopNextRefreshTime(sg)); - GameItem item = new GameItem(sg.getGoodsItem().getId(), buyGoodsReq.getBuyCount() * sg.getGoodsItem().getCount()); - player.getInventory().addItem(item, ActionReason.Shop, true); // fix: not notify when got virtual item from shop - session.send(new PacketBuyGoodsRsp(buyGoodsReq.getShopType(), player.getGoodsLimit(sg.getGoodsId()).getHasBoughtInPeriod(), Stream.of(buyGoodsReq.getGoods()).filter(x -> x.getGoodsId() == goodsId).findFirst().get())); - } - - player.save(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.shop.ShopInfo; +import emu.grasscutter.game.shop.ShopLimit; +import emu.grasscutter.game.shop.ShopSystem; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyGoodsReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketBuyGoodsRsp; +import emu.grasscutter.utils.Utils; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +@Opcodes(PacketOpcodes.BuyGoodsReq) +public class HandlerBuyGoodsReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + BuyGoodsReqOuterClass.BuyGoodsReq buyGoodsReq = + BuyGoodsReqOuterClass.BuyGoodsReq.parseFrom(payload); + List configShop = + session.getServer().getShopSystem().getShopData().get(buyGoodsReq.getShopType()); + if (configShop == null) return; + + // Don't trust your users' input + var player = session.getPlayer(); + List targetShopGoodsId = List.of(buyGoodsReq.getGoods().getGoodsId()); + for (int goodsId : targetShopGoodsId) { + Optional sg2 = + configShop.stream().filter(x -> x.getGoodsId() == goodsId).findFirst(); + if (sg2.isEmpty()) continue; + ShopInfo sg = sg2.get(); + + int currentTs = Utils.getCurrentSeconds(); + ShopLimit shopLimit = player.getGoodsLimit(sg.getGoodsId()); + int bought = 0; + if (shopLimit != null) { + if (currentTs > shopLimit.getNextRefreshTime()) { + shopLimit.setNextRefreshTime(ShopSystem.getShopNextRefreshTime(sg)); + } else { + bought = shopLimit.getHasBoughtInPeriod(); + } + player.save(); + } + + if ((bought + buyGoodsReq.getBuyCount() > sg.getBuyLimit()) && sg.getBuyLimit() != 0) { + return; + } + + List costs = + new ArrayList(sg.getCostItemList()); // Can this even be null? + costs.add(new ItemParamData(202, sg.getScoin())); + costs.add(new ItemParamData(201, sg.getHcoin())); + costs.add(new ItemParamData(203, sg.getMcoin())); + if (!player.getInventory().payItems(costs, buyGoodsReq.getBuyCount())) { + return; + } + + player.addShopLimit( + sg.getGoodsId(), buyGoodsReq.getBuyCount(), ShopSystem.getShopNextRefreshTime(sg)); + GameItem item = + new GameItem( + sg.getGoodsItem().getId(), buyGoodsReq.getBuyCount() * sg.getGoodsItem().getCount()); + player + .getInventory() + .addItem( + item, ActionReason.Shop, true); // fix: not notify when got virtual item from shop + session.send( + new PacketBuyGoodsRsp( + buyGoodsReq.getShopType(), + player.getGoodsLimit(sg.getGoodsId()).getHasBoughtInPeriod(), + Stream.of(buyGoodsReq.getGoods()) + .filter(x -> x.getGoodsId() == goodsId) + .findFirst() + .get())); + } + + player.save(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCalcWeaponUpgradeReturnItemsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCalcWeaponUpgradeReturnItemsReq.java index 9eb5f2c25..531cea93f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCalcWeaponUpgradeReturnItemsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCalcWeaponUpgradeReturnItemsReq.java @@ -1,34 +1,36 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsReqOuterClass.CalcWeaponUpgradeReturnItemsReq; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketCalcWeaponUpgradeReturnItemsRsp; - -import java.util.List; - -@Opcodes(PacketOpcodes.CalcWeaponUpgradeReturnItemsReq) -public class HandlerCalcWeaponUpgradeReturnItemsReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - CalcWeaponUpgradeReturnItemsReq req = CalcWeaponUpgradeReturnItemsReq.parseFrom(payload); - - List returnOres = session.getServer().getInventorySystem().calcWeaponUpgradeReturnItems( - session.getPlayer(), - req.getTargetWeaponGuid(), - req.getFoodWeaponGuidListList(), - req.getItemParamListList() - ); - - if (returnOres != null) { - session.send(new PacketCalcWeaponUpgradeReturnItemsRsp(req.getTargetWeaponGuid(), returnOres)); - } else { - session.send(new PacketCalcWeaponUpgradeReturnItemsRsp()); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsReqOuterClass.CalcWeaponUpgradeReturnItemsReq; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCalcWeaponUpgradeReturnItemsRsp; +import java.util.List; + +@Opcodes(PacketOpcodes.CalcWeaponUpgradeReturnItemsReq) +public class HandlerCalcWeaponUpgradeReturnItemsReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CalcWeaponUpgradeReturnItemsReq req = CalcWeaponUpgradeReturnItemsReq.parseFrom(payload); + + List returnOres = + session + .getServer() + .getInventorySystem() + .calcWeaponUpgradeReturnItems( + session.getPlayer(), + req.getTargetWeaponGuid(), + req.getFoodWeaponGuidListList(), + req.getItemParamListList()); + + if (returnOres != null) { + session.send( + new PacketCalcWeaponUpgradeReturnItemsRsp(req.getTargetWeaponGuid(), returnOres)); + } else { + session.send(new PacketCalcWeaponUpgradeReturnItemsRsp()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeAvatarReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeAvatarReq.java index 8088758d2..059630e9d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeAvatarReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeAvatarReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeAvatarReqOuterClass.ChangeAvatarReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ChangeAvatarReq) -public class HandlerChangeAvatarReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChangeAvatarReq req = ChangeAvatarReq.parseFrom(payload); - - session.getPlayer().getTeamManager().changeAvatar(req.getGuid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeAvatarReqOuterClass.ChangeAvatarReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ChangeAvatarReq) +public class HandlerChangeAvatarReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChangeAvatarReq req = ChangeAvatarReq.parseFrom(payload); + + session.getPlayer().getTeamManager().changeAvatar(req.getGuid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeGameTimeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeGameTimeReq.java index 0bc477046..3081aff75 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeGameTimeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeGameTimeReq.java @@ -1,25 +1,28 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeGameTimeReqOuterClass.ChangeGameTimeReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketChangeGameTimeRsp; - -@Opcodes(PacketOpcodes.ChangeGameTimeReq) -public class HandlerChangeGameTimeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChangeGameTimeReq req = ChangeGameTimeReq.parseFrom(payload); - - session.getPlayer().getScene().changeTime(req.getGameTime()); - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_GAME_TIME_TICK, - req.getGameTime() / 60, // hours - req.getExtraDays()); //days - session.getPlayer().sendPacket(new PacketChangeGameTimeRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeGameTimeReqOuterClass.ChangeGameTimeReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketChangeGameTimeRsp; + +@Opcodes(PacketOpcodes.ChangeGameTimeReq) +public class HandlerChangeGameTimeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChangeGameTimeReq req = ChangeGameTimeReq.parseFrom(payload); + + session.getPlayer().getScene().changeTime(req.getGameTime()); + session + .getPlayer() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_CONTENT_GAME_TIME_TICK, + req.getGameTime() / 60, // hours + req.getExtraDays()); // days + session.getPlayer().sendPacket(new PacketChangeGameTimeRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMailStarNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMailStarNotify.java index dd5fa0093..56e66f4c9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMailStarNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMailStarNotify.java @@ -1,34 +1,34 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeMailStarNotifyOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketMailChangeNotify; - -import java.util.ArrayList; -import java.util.List; - -@Opcodes(PacketOpcodes.ChangeMailStarNotify) -public class HandlerChangeMailStarNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChangeMailStarNotifyOuterClass.ChangeMailStarNotify req = ChangeMailStarNotifyOuterClass.ChangeMailStarNotify.parseFrom(payload); - - List updatedMail = new ArrayList<>(); - - for (int mailId : req.getMailIdListList()) { - Mail message = session.getPlayer().getMail(mailId); - - message.importance = req.getIsStar() ? 1 : 0; - - session.getPlayer().replaceMailByIndex(mailId, message); - updatedMail.add(message); - } - - session.send(new PacketMailChangeNotify(session.getPlayer(), updatedMail)); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeMailStarNotifyOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketMailChangeNotify; +import java.util.ArrayList; +import java.util.List; + +@Opcodes(PacketOpcodes.ChangeMailStarNotify) +public class HandlerChangeMailStarNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChangeMailStarNotifyOuterClass.ChangeMailStarNotify req = + ChangeMailStarNotifyOuterClass.ChangeMailStarNotify.parseFrom(payload); + + List updatedMail = new ArrayList<>(); + + for (int mailId : req.getMailIdListList()) { + Mail message = session.getPlayer().getMail(mailId); + + message.importance = req.getIsStar() ? 1 : 0; + + session.getPlayer().replaceMailByIndex(mailId, message); + updatedMail.add(message); + } + + session.send(new PacketMailChangeNotify(session.getPlayer(), updatedMail)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMpTeamAvatarReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMpTeamAvatarReq.java index 8a12cea12..99c3d1981 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMpTeamAvatarReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMpTeamAvatarReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeMpTeamAvatarReqOuterClass.ChangeMpTeamAvatarReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ChangeMpTeamAvatarReq) -public class HandlerChangeMpTeamAvatarReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChangeMpTeamAvatarReq req = ChangeMpTeamAvatarReq.parseFrom(payload); - - session.getPlayer().getTeamManager().setupMpTeam(req.getAvatarGuidListList()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeMpTeamAvatarReqOuterClass.ChangeMpTeamAvatarReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ChangeMpTeamAvatarReq) +public class HandlerChangeMpTeamAvatarReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChangeMpTeamAvatarReq req = ChangeMpTeamAvatarReq.parseFrom(payload); + + session.getPlayer().getTeamManager().setupMpTeam(req.getAvatarGuidListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeTeamNameReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeTeamNameReq.java index 852694acd..281a02ff0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeTeamNameReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeTeamNameReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeTeamNameReqOuterClass.ChangeTeamNameReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ChangeTeamNameReq) -public class HandlerChangeTeamNameReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChangeTeamNameReq req = ChangeTeamNameReq.parseFrom(payload); - - session.getPlayer().getTeamManager().setTeamName(req.getTeamId(), req.getTeamName()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeTeamNameReqOuterClass.ChangeTeamNameReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ChangeTeamNameReq) +public class HandlerChangeTeamNameReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChangeTeamNameReq req = ChangeTeamNameReq.parseFrom(payload); + + session.getPlayer().getTeamManager().setTeamName(req.getTeamId(), req.getTeamName()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChooseCurAvatarTeamReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChooseCurAvatarTeamReq.java index f53d60e0e..264425554 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerChooseCurAvatarTeamReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerChooseCurAvatarTeamReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChooseCurAvatarTeamReqOuterClass.ChooseCurAvatarTeamReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ChooseCurAvatarTeamReq) -public class HandlerChooseCurAvatarTeamReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ChooseCurAvatarTeamReq req = ChooseCurAvatarTeamReq.parseFrom(payload); - - session.getPlayer().getTeamManager().setCurrentTeam(req.getTeamId()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChooseCurAvatarTeamReqOuterClass.ChooseCurAvatarTeamReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ChooseCurAvatarTeamReq) +public class HandlerChooseCurAvatarTeamReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ChooseCurAvatarTeamReq req = ChooseCurAvatarTeamReq.parseFrom(payload); + + session.getPlayer().getTeamManager().setCurrentTeam(req.getTeamId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java index fa534ac23..23c5ab6da 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java @@ -1,32 +1,32 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify) -public class HandlerClientAbilityInitFinishNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload); - - Player player = session.getPlayer(); - - // Call skill end in the player's ability manager. - player.getAbilityManager().onSkillEnd(player); - - for (AbilityInvokeEntry entry : notif.getInvokesList()) { - player.getAbilityManager().onAbilityInvoke(entry); - player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry); - } - - if (notif.getInvokesList().size() > 0) { - session.getPlayer().getClientAbilityInitFinishHandler().update(session.getPlayer()); - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify) +public class HandlerClientAbilityInitFinishNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload); + + Player player = session.getPlayer(); + + // Call skill end in the player's ability manager. + player.getAbilityManager().onSkillEnd(player); + + for (AbilityInvokeEntry entry : notif.getInvokesList()) { + player.getAbilityManager().onAbilityInvoke(entry); + player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry); + } + + if (notif.getInvokesList().size() > 0) { + session.getPlayer().getClientAbilityInitFinishHandler().update(session.getPlayer()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java index d88726d71..1bbddceed 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java @@ -1,160 +1,191 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; -import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; -import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; -import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; -import emu.grasscutter.net.proto.EvtAnimatorParameterInfoOuterClass.EvtAnimatorParameterInfo; -import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; -import emu.grasscutter.server.event.entity.EntityMoveEvent; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.CombatInvocationsNotify) -public class HandlerCombatInvocationsNotify extends PacketHandler { - - private float cachedLandingSpeed = 0; - private long cachedLandingTimeMillisecond = 0; - private boolean monitorLandingEvent = false; - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); - for (CombatInvokeEntry entry : notif.getInvokeListList()) { - // Handle combat invoke - switch (entry.getArgumentType()) { - case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT -> { - EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); - AttackResult attackResult = hitInfo.getAttackResult(); - Player player = session.getPlayer(); - - // Check if the player is invulnerable. - if ( - attackResult.getAttackerId() != player.getTeamManager().getCurrentAvatarEntity().getId() && - player.getAbilityManager().isAbilityInvulnerable() - ) break; - - // Handle damage - player.getAttackResults().add(attackResult); - player.getEnergyManager().handleAttackHit(hitInfo); - } - case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE -> { - // Handle movement - EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); - GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); - if (entity != null) { - // Move player - MotionInfo motionInfo = moveInfo.getMotionInfo(); - MotionState motionState = motionInfo.getState(); - - // Call entity move event. - EntityMoveEvent event = new EntityMoveEvent( - entity, new Position(motionInfo.getPos()), - new Position(motionInfo.getRot()), motionState); - event.call(); - - entity.move(event.getPosition(), event.getRotation()); - entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); - entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); - entity.setMotionState(motionState); - - session.getPlayer().getStaminaManager().handleCombatInvocationsNotify(session, moveInfo, entity); - - // TODO: handle MOTION_FIGHT landing which has a different damage factor - // Also, for plunge attacks, LAND_SPEED is always -30 and is not useful. - // May need the height when starting plunge attack. - - // MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets. - // Cache land speed for later use. - if (motionState == MotionState.MOTION_STATE_LAND_SPEED) { - cachedLandingSpeed = motionInfo.getSpeed().getY(); - cachedLandingTimeMillisecond = System.currentTimeMillis(); - monitorLandingEvent = true; - } - if (monitorLandingEvent) { - if (motionState == MotionState.MOTION_STATE_FALL_ON_GROUND) { - monitorLandingEvent = false; - handleFallOnGround(session, entity, motionState); - } - } - - // MOTION_STATE_NOTIFY = Dont send to other players - if (motionState == MotionState.MOTION_STATE_NOTIFY) { - continue; - } - } - } - case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED -> { - EvtAnimatorParameterInfo paramInfo = EvtAnimatorParameterInfo.parseFrom(entry.getCombatData()); - if (paramInfo.getIsServerCache()) { - paramInfo = paramInfo.toBuilder().setIsServerCache(false).build(); - entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build(); - } - } - default -> { - } - } - - session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); - } - } - - private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) { - if (session.getPlayer().inGodmode()) { - return; - } - // People have reported that after plunge attack (client sends a FIGHT instead of FALL_ON_GROUND) they will die - // if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping again. - // A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet. - // 200ms seems to be a reasonable delay. - int maxDelay = 200; - long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond; - Grasscutter.getLogger().trace("MOTION_FALL_ON_GROUND received after " + actualDelay + "/" + maxDelay + "ms." + (actualDelay > maxDelay ? " Discard" : "")); - if (actualDelay > maxDelay) { - return; - } - float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - float damageFactor = 0; - if (cachedLandingSpeed < -23.5) { - damageFactor = 0.33f; - } - if (cachedLandingSpeed < -25) { - damageFactor = 0.5f; - } - if (cachedLandingSpeed < -26.5) { - damageFactor = 0.66f; - } - if (cachedLandingSpeed < -28) { - damageFactor = 1f; - } - float damage = maxHP * damageFactor; - float newHP = currentHP - damage; - if (newHP < 0) { - newHP = 0; - } - if (damageFactor > 0) { - Grasscutter.getLogger().debug(currentHP + "/" + maxHP + "\tLandingSpeed: " + cachedLandingSpeed + - "\tDamageFactor: " + damageFactor + "\tDamage: " + damage + "\tNewHP: " + newHP); - } else { - Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage"); - } - entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); - entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); - if (newHP == 0) { - session.getPlayer().getStaminaManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_TYPE_FALL); - } - cachedLandingSpeed = 0; - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; +import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; +import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; +import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; +import emu.grasscutter.net.proto.EvtAnimatorParameterInfoOuterClass.EvtAnimatorParameterInfo; +import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; +import emu.grasscutter.server.event.entity.EntityMoveEvent; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.CombatInvocationsNotify) +public class HandlerCombatInvocationsNotify extends PacketHandler { + + private float cachedLandingSpeed = 0; + private long cachedLandingTimeMillisecond = 0; + private boolean monitorLandingEvent = false; + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); + for (CombatInvokeEntry entry : notif.getInvokeListList()) { + // Handle combat invoke + switch (entry.getArgumentType()) { + case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT -> { + EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); + AttackResult attackResult = hitInfo.getAttackResult(); + Player player = session.getPlayer(); + + // Check if the player is invulnerable. + if (attackResult.getAttackerId() + != player.getTeamManager().getCurrentAvatarEntity().getId() + && player.getAbilityManager().isAbilityInvulnerable()) break; + + // Handle damage + player.getAttackResults().add(attackResult); + player.getEnergyManager().handleAttackHit(hitInfo); + } + case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE -> { + // Handle movement + EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); + GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); + if (entity != null) { + // Move player + MotionInfo motionInfo = moveInfo.getMotionInfo(); + MotionState motionState = motionInfo.getState(); + + // Call entity move event. + EntityMoveEvent event = + new EntityMoveEvent( + entity, + new Position(motionInfo.getPos()), + new Position(motionInfo.getRot()), + motionState); + event.call(); + + entity.move(event.getPosition(), event.getRotation()); + entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); + entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); + entity.setMotionState(motionState); + + session + .getPlayer() + .getStaminaManager() + .handleCombatInvocationsNotify(session, moveInfo, entity); + + // TODO: handle MOTION_FIGHT landing which has a different damage factor + // Also, for plunge attacks, LAND_SPEED is always -30 and is not useful. + // May need the height when starting plunge attack. + + // MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets. + // Cache land speed for later use. + if (motionState == MotionState.MOTION_STATE_LAND_SPEED) { + cachedLandingSpeed = motionInfo.getSpeed().getY(); + cachedLandingTimeMillisecond = System.currentTimeMillis(); + monitorLandingEvent = true; + } + if (monitorLandingEvent) { + if (motionState == MotionState.MOTION_STATE_FALL_ON_GROUND) { + monitorLandingEvent = false; + handleFallOnGround(session, entity, motionState); + } + } + + // MOTION_STATE_NOTIFY = Dont send to other players + if (motionState == MotionState.MOTION_STATE_NOTIFY) { + continue; + } + } + } + case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED -> { + EvtAnimatorParameterInfo paramInfo = + EvtAnimatorParameterInfo.parseFrom(entry.getCombatData()); + if (paramInfo.getIsServerCache()) { + paramInfo = paramInfo.toBuilder().setIsServerCache(false).build(); + entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build(); + } + } + default -> {} + } + + session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); + } + } + + private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) { + if (session.getPlayer().inGodmode()) { + return; + } + // People have reported that after plunge attack (client sends a FIGHT instead of + // FALL_ON_GROUND) they will die + // if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping + // again. + // A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet. + // 200ms seems to be a reasonable delay. + int maxDelay = 200; + long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond; + Grasscutter.getLogger() + .trace( + "MOTION_FALL_ON_GROUND received after " + + actualDelay + + "/" + + maxDelay + + "ms." + + (actualDelay > maxDelay ? " Discard" : "")); + if (actualDelay > maxDelay) { + return; + } + float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + float damageFactor = 0; + if (cachedLandingSpeed < -23.5) { + damageFactor = 0.33f; + } + if (cachedLandingSpeed < -25) { + damageFactor = 0.5f; + } + if (cachedLandingSpeed < -26.5) { + damageFactor = 0.66f; + } + if (cachedLandingSpeed < -28) { + damageFactor = 1f; + } + float damage = maxHP * damageFactor; + float newHP = currentHP - damage; + if (newHP < 0) { + newHP = 0; + } + if (damageFactor > 0) { + Grasscutter.getLogger() + .debug( + currentHP + + "/" + + maxHP + + "\tLandingSpeed: " + + cachedLandingSpeed + + "\tDamageFactor: " + + damageFactor + + "\tDamage: " + + damage + + "\tNewHP: " + + newHP); + } else { + Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage"); + } + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); + entity + .getWorld() + .broadcastPacket( + new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + if (newHP == 0) { + session + .getPlayer() + .getStaminaManager() + .killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_TYPE_FALL); + } + cachedLandingSpeed = 0; + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java index 0837c5d7e..803c918eb 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java @@ -1,46 +1,52 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CombineReqOuterClass; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketCombineRsp; - -import java.util.List; -import java.util.stream.Collectors; - -@Opcodes(PacketOpcodes.CombineReq) -public class HandlerCombineReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - - CombineReqOuterClass.CombineReq req = CombineReqOuterClass.CombineReq.parseFrom(payload); - - var result = session.getServer().getCombineSystem() - .combineItem(session.getPlayer(), req.getCombineId(), req.getCombineCount()); - - if (result == null) { - return; - } - - session.send(new PacketCombineRsp(req, - toItemParamList(result.getMaterial()), - toItemParamList(result.getResult()), - toItemParamList(result.getExtra()), - toItemParamList(result.getBack()), - toItemParamList(result.getBack()))); - } - - private List toItemParamList(List list) { - return list.stream() - .map(item -> ItemParamOuterClass.ItemParam.newBuilder() - .setItemId(item.getId()) - .setCount(item.getCount()) - .build()) - .collect(Collectors.toList()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CombineReqOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCombineRsp; +import java.util.List; +import java.util.stream.Collectors; + +@Opcodes(PacketOpcodes.CombineReq) +public class HandlerCombineReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + + CombineReqOuterClass.CombineReq req = CombineReqOuterClass.CombineReq.parseFrom(payload); + + var result = + session + .getServer() + .getCombineSystem() + .combineItem(session.getPlayer(), req.getCombineId(), req.getCombineCount()); + + if (result == null) { + return; + } + + session.send( + new PacketCombineRsp( + req, + toItemParamList(result.getMaterial()), + toItemParamList(result.getResult()), + toItemParamList(result.getExtra()), + toItemParamList(result.getBack()), + toItemParamList(result.getBack()))); + } + + private List toItemParamList(List list) { + return list.stream() + .map( + item -> + ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(item.getId()) + .setCount(item.getCount()) + .build()) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java index c8345db0e..609d711cb 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java @@ -1,19 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CreateVehicleReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketCreateVehicleRsp; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.CreateVehicleReq) -public class HandlerCreateVehicleReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - CreateVehicleReqOuterClass.CreateVehicleReq req = CreateVehicleReqOuterClass.CreateVehicleReq.parseFrom(payload); - session.send(new PacketCreateVehicleRsp(session.getPlayer(), req.getVehicleId(), req.getScenePointId(), new Position(req.getPos()), new Position(req.getRot()))); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CreateVehicleReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCreateVehicleRsp; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.CreateVehicleReq) +public class HandlerCreateVehicleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CreateVehicleReqOuterClass.CreateVehicleReq req = + CreateVehicleReqOuterClass.CreateVehicleReq.parseFrom(payload); + session.send( + new PacketCreateVehicleRsp( + session.getPlayer(), + req.getVehicleId(), + req.getScenePointId(), + new Position(req.getPos()), + new Position(req.getRot()))); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDealAddFriendReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDealAddFriendReq.java index 93619dc2f..0419f8167 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDealAddFriendReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDealAddFriendReq.java @@ -1,19 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DealAddFriendReqOuterClass.DealAddFriendReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DealAddFriendReq) -public class HandlerDealAddFriendReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DealAddFriendReq req = DealAddFriendReq.parseFrom(payload); - - session.getPlayer().getFriendsList().handleFriendRequest(req.getTargetUid(), req.getDealAddFriendResult()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DealAddFriendReqOuterClass.DealAddFriendReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DealAddFriendReq) +public class HandlerDealAddFriendReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DealAddFriendReq req = DealAddFriendReq.parseFrom(payload); + + session + .getPlayer() + .getFriendsList() + .handleFriendRequest(req.getTargetUid(), req.getDealAddFriendResult()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelBackupAvatarTeamReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelBackupAvatarTeamReq.java index 63362a1a2..e4d1af26b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelBackupAvatarTeamReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelBackupAvatarTeamReq.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DelBackupAvatarTeamReqOuterClass.DelBackupAvatarTeamReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DelBackupAvatarTeamReq) -public class HandlerDelBackupAvatarTeamReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DelBackupAvatarTeamReq req = DelBackupAvatarTeamReq.parseFrom(payload); - session.getPlayer().getTeamManager().removeCustomTeam(req.getBackupAvatarTeamId()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelBackupAvatarTeamReqOuterClass.DelBackupAvatarTeamReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DelBackupAvatarTeamReq) +public class HandlerDelBackupAvatarTeamReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DelBackupAvatarTeamReq req = DelBackupAvatarTeamReq.parseFrom(payload); + session.getPlayer().getTeamManager().removeCustomTeam(req.getBackupAvatarTeamId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java index 88c202982..3162e16a7 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DelMailReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DelMailReq) -public class HandlerDelMailReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DelMailReqOuterClass.DelMailReq req = DelMailReqOuterClass.DelMailReq.parseFrom(payload); - - session.getPlayer().getMailHandler().deleteMail(req.getMailIdListList()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelMailReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DelMailReq) +public class HandlerDelMailReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DelMailReqOuterClass.DelMailReq req = DelMailReqOuterClass.DelMailReq.parseFrom(payload); + + session.getPlayer().getMailHandler().deleteMail(req.getMailIdListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDeleteFriendReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDeleteFriendReq.java index 241c96543..84c960979 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDeleteFriendReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDeleteFriendReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DeleteFriendReqOuterClass.DeleteFriendReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DeleteFriendReq) -public class HandlerDeleteFriendReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DeleteFriendReq req = DeleteFriendReq.parseFrom(payload); - - session.getPlayer().getFriendsList().deleteFriend(req.getTargetUid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DeleteFriendReqOuterClass.DeleteFriendReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DeleteFriendReq) +public class HandlerDeleteFriendReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DeleteFriendReq req = DeleteFriendReq.parseFrom(payload); + + session.getPlayer().getFriendsList().deleteFriend(req.getTargetUid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDestroyMaterialReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDestroyMaterialReq.java index b4bbe7388..7089b5981 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDestroyMaterialReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDestroyMaterialReq.java @@ -1,18 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DestroyMaterialReqOuterClass.DestroyMaterialReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DestroyMaterialReq) -public class HandlerDestroyMaterialReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DestroyMaterialReq req = DestroyMaterialReq.parseFrom(payload); - - // Delete items - session.getServer().getInventorySystem().destroyMaterial(session.getPlayer(), req.getMaterialListList()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DestroyMaterialReqOuterClass.DestroyMaterialReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DestroyMaterialReq) +public class HandlerDestroyMaterialReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DestroyMaterialReq req = DestroyMaterialReq.parseFrom(payload); + + // Delete items + session + .getServer() + .getInventorySystem() + .destroyMaterial(session.getPlayer(), req.getMaterialListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java index 3ff67444f..7d4630201 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java @@ -1,17 +1,20 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DoGachaReqOuterClass.DoGachaReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DoGachaReq) -public class HandlerDoGachaReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DoGachaReq req = DoGachaReq.parseFrom(payload); - - session.getServer().getGachaSystem().doPulls(session.getPlayer(), req.getGachaScheduleId(), req.getGachaTimes()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DoGachaReqOuterClass.DoGachaReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DoGachaReq) +public class HandlerDoGachaReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DoGachaReq req = DoGachaReq.parseFrom(payload); + + session + .getServer() + .getGachaSystem() + .doPulls(session.getPlayer(), req.getGachaScheduleId(), req.getGachaTimes()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java index e011efadd..052aed0bf 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.DungeonEntryInfoReq) -public class HandlerDungeonEntryInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - DungeonEntryInfoReq req = DungeonEntryInfoReq.parseFrom(payload); - - session.getServer().getDungeonSystem().getEntryInfo(session.getPlayer(), req.getPointId()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.DungeonEntryInfoReq) +public class HandlerDungeonEntryInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DungeonEntryInfoReq req = DungeonEntryInfoReq.parseFrom(payload); + + session.getServer().getDungeonSystem().getEntryInfo(session.getPlayer(), req.getPointId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java index 102ec0e90..9e0156e1c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java @@ -1,50 +1,54 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.*; - -@Opcodes(PacketOpcodes.EnterSceneDoneReq) -public class HandlerEnterSceneDoneReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Finished loading - session.getPlayer().setSceneLoadState(SceneLoadState.LOADED); - - // Done - - session.send(new PacketPlayerTimeNotify(session.getPlayer())); // Probably not the right place - - // Spawn player in world - session.getPlayer().getScene().spawnPlayer(session.getPlayer()); - - // Spawn other entites already in world - session.getPlayer().getScene().showOtherEntities(session.getPlayer()); - - // Locations - session.send(new PacketWorldPlayerLocationNotify(session.getPlayer().getWorld())); - session.send(new PacketScenePlayerLocationNotify(session.getPlayer().getScene())); - session.send(new PacketWorldPlayerRTTNotify(session.getPlayer().getWorld())); - - // spawn NPC - session.getPlayer().getScene().loadNpcForPlayerEnter(session.getPlayer()); - - // notify client to load the npc for quest - var questGroupSuites = session.getPlayer().getQuestManager().getSceneGroupSuite(session.getPlayer().getSceneId()); - - session.getPlayer().getScene().loadGroupForQuest(questGroupSuites); - Grasscutter.getLogger().debug("Loaded Scene {} Quest(s) Groupsuite(s): {}", session.getPlayer().getSceneId(), questGroupSuites); - session.send(new PacketGroupSuiteNotify(questGroupSuites)); - - // Reset timer for sending player locations - session.getPlayer().resetSendPlayerLocTime(); - //Rsp - session.send(new PacketEnterSceneDoneRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player.SceneLoadState; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.*; + +@Opcodes(PacketOpcodes.EnterSceneDoneReq) +public class HandlerEnterSceneDoneReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Finished loading + session.getPlayer().setSceneLoadState(SceneLoadState.LOADED); + + // Done + + session.send(new PacketPlayerTimeNotify(session.getPlayer())); // Probably not the right place + + // Spawn player in world + session.getPlayer().getScene().spawnPlayer(session.getPlayer()); + + // Spawn other entites already in world + session.getPlayer().getScene().showOtherEntities(session.getPlayer()); + + // Locations + session.send(new PacketWorldPlayerLocationNotify(session.getPlayer().getWorld())); + session.send(new PacketScenePlayerLocationNotify(session.getPlayer().getScene())); + session.send(new PacketWorldPlayerRTTNotify(session.getPlayer().getWorld())); + + // spawn NPC + session.getPlayer().getScene().loadNpcForPlayerEnter(session.getPlayer()); + + // notify client to load the npc for quest + var questGroupSuites = + session.getPlayer().getQuestManager().getSceneGroupSuite(session.getPlayer().getSceneId()); + + session.getPlayer().getScene().loadGroupForQuest(questGroupSuites); + Grasscutter.getLogger() + .debug( + "Loaded Scene {} Quest(s) Groupsuite(s): {}", + session.getPlayer().getSceneId(), + questGroupSuites); + session.send(new PacketGroupSuiteNotify(questGroupSuites)); + + // Reset timer for sending player locations + session.getPlayer().resetSendPlayerLocTime(); + // Rsp + session.send(new PacketEnterSceneDoneRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneReadyReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneReadyReq.java index 9a9efccb2..534c44a8a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneReadyReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneReadyReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEnterScenePeerNotify; -import emu.grasscutter.server.packet.send.PacketEnterSceneReadyRsp; - -@Opcodes(PacketOpcodes.EnterSceneReadyReq) -public class HandlerEnterSceneReadyReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) { - session.send(new PacketEnterScenePeerNotify(session.getPlayer())); - session.send(new PacketEnterSceneReadyRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEnterScenePeerNotify; +import emu.grasscutter.server.packet.send.PacketEnterSceneReadyRsp; + +@Opcodes(PacketOpcodes.EnterSceneReadyReq) +public class HandlerEnterSceneReadyReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) { + session.send(new PacketEnterScenePeerNotify(session.getPlayer())); + session.send(new PacketEnterSceneReadyRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java index 5d60c3b99..1875ac20f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java @@ -1,14 +1,14 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.EnterTransPointRegionNotify) -public class HandlerEnterTransPointRegionNotify extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getSotsManager().handleEnterTransPointRegionNotify(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EnterTransPointRegionNotify) +public class HandlerEnterTransPointRegionNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getSotsManager().handleEnterTransPointRegionNotify(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterWorldAreaReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterWorldAreaReq.java index 330a8eb9a..3ccbb62ea 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterWorldAreaReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterWorldAreaReq.java @@ -1,23 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterWorldAreaReqOuterClass.EnterWorldAreaReq; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEnterWorldAreaRsp; - -@Opcodes(PacketOpcodes.EnterWorldAreaReq) -public class HandlerEnterWorldAreaReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PacketHead head = PacketHead.parseFrom(header); - EnterWorldAreaReq enterWorld = EnterWorldAreaReq.parseFrom(payload); - - session.send(new PacketEnterWorldAreaRsp(head.getClientSequenceId(), enterWorld)); - //session.send(new PacketScenePlayerLocationNotify(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterWorldAreaReqOuterClass.EnterWorldAreaReq; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEnterWorldAreaRsp; + +@Opcodes(PacketOpcodes.EnterWorldAreaReq) +public class HandlerEnterWorldAreaReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PacketHead head = PacketHead.parseFrom(header); + EnterWorldAreaReq enterWorld = EnterWorldAreaReq.parseFrom(payload); + + session.send(new PacketEnterWorldAreaRsp(head.getClientSequenceId(), enterWorld)); + // session.send(new PacketScenePlayerLocationNotify(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiSyncNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiSyncNotify.java index 6182114ea..d5c88579c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiSyncNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiSyncNotify.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EntityAiSyncNotifyOuterClass.EntityAiSyncNotify; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEntityAiSyncNotify; - -@Opcodes(PacketOpcodes.EntityAiSyncNotify) -public class HandlerEntityAiSyncNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - EntityAiSyncNotify notify = EntityAiSyncNotify.parseFrom(payload); - - if (notify.getLocalAvatarAlertedMonsterListCount() > 0) { - session.getPlayer().getScene().broadcastPacket(new PacketEntityAiSyncNotify(notify)); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EntityAiSyncNotifyOuterClass.EntityAiSyncNotify; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEntityAiSyncNotify; + +@Opcodes(PacketOpcodes.EntityAiSyncNotify) +public class HandlerEntityAiSyncNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + EntityAiSyncNotify notify = EntityAiSyncNotify.parseFrom(payload); + + if (notify.getLocalAvatarAlertedMonsterListCount() > 0) { + session.getPlayer().getScene().broadcastPacket(new PacketEntityAiSyncNotify(notify)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncCombatThreatInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncCombatThreatInfoNotify.java index e92de89e5..194bc99fd 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncCombatThreatInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncCombatThreatInfoNotify.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.EvtAiSyncCombatThreatInfoNotify) -public class HandlerEvtAiSyncCombatThreatInfoNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EvtAiSyncCombatThreatInfoNotify) +public class HandlerEvtAiSyncCombatThreatInfoNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncSkillCdNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncSkillCdNotify.java index cba71a170..369e58177 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncSkillCdNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAiSyncSkillCdNotify.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.EvtAiSyncSkillCdNotify) -public class HandlerEvtAiSyncSkillCdNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EvtAiSyncSkillCdNotify) +public class HandlerEvtAiSyncSkillCdNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarLockChairReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarLockChairReq.java index 2a325b438..77ee78fd6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarLockChairReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarLockChairReq.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarLockChairReqOuterClass.EvtAvatarLockChairReq; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEvtAvatarLockChairRsp; - -@Opcodes(PacketOpcodes.EvtAvatarLockChairReq) -public class HandlerEvtAvatarLockChairReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PacketHead head = PacketHead.parseFrom(header); - EvtAvatarLockChairReq lockChairReq = EvtAvatarLockChairReq.parseFrom(payload); - - EntityAvatar entityAvatar = session.getPlayer().getTeamManager().getCurrentAvatarEntity(); - - session.send(new PacketEvtAvatarLockChairRsp(head.getClientSequenceId(), entityAvatar, lockChairReq)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarLockChairReqOuterClass.EvtAvatarLockChairReq; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEvtAvatarLockChairRsp; + +@Opcodes(PacketOpcodes.EvtAvatarLockChairReq) +public class HandlerEvtAvatarLockChairReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PacketHead head = PacketHead.parseFrom(header); + EvtAvatarLockChairReq lockChairReq = EvtAvatarLockChairReq.parseFrom(payload); + + EntityAvatar entityAvatar = session.getPlayer().getTeamManager().getCurrentAvatarEntity(); + + session.send( + new PacketEvtAvatarLockChairRsp(head.getClientSequenceId(), entityAvatar, lockChairReq)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarSitDownNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarSitDownNotify.java index 91b774240..cfae90de8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarSitDownNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarSitDownNotify.java @@ -1,21 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarSitDownNotifyOuterClass.EvtAvatarSitDownNotify; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEvtAvatarSitDownNotify; - -@Opcodes(PacketOpcodes.EvtAvatarSitDownNotify) -public class HandlerEvtAvatarSitDownNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - EvtAvatarSitDownNotify notify = EvtAvatarSitDownNotify.parseFrom(payload); - - session.getPlayer().getScene().broadcastPacket(new PacketEvtAvatarSitDownNotify(notify)); - } - -} - +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarSitDownNotifyOuterClass.EvtAvatarSitDownNotify; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEvtAvatarSitDownNotify; + +@Opcodes(PacketOpcodes.EvtAvatarSitDownNotify) +public class HandlerEvtAvatarSitDownNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + EvtAvatarSitDownNotify notify = EvtAvatarSitDownNotify.parseFrom(payload); + + session.getPlayer().getScene().broadcastPacket(new PacketEvtAvatarSitDownNotify(notify)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarStandUpNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarStandUpNotify.java index ebb02c41e..4cab5406f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarStandUpNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtAvatarStandUpNotify.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarStandUpNotifyOuterClass.EvtAvatarStandUpNotify; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEvtAvatarStandUpNotify; - -@Opcodes(PacketOpcodes.EvtAvatarStandUpNotify) -public class HandlerEvtAvatarStandUpNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - EvtAvatarStandUpNotify notify = EvtAvatarStandUpNotify.parseFrom(payload); - - session.getPlayer().getScene().broadcastPacket(new PacketEvtAvatarStandUpNotify(notify)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarStandUpNotifyOuterClass.EvtAvatarStandUpNotify; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEvtAvatarStandUpNotify; + +@Opcodes(PacketOpcodes.EvtAvatarStandUpNotify) +public class HandlerEvtAvatarStandUpNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + EvtAvatarStandUpNotify notify = EvtAvatarStandUpNotify.parseFrom(payload); + + session.getPlayer().getScene().broadcastPacket(new PacketEvtAvatarStandUpNotify(notify)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java index 6d4be1408..d8b38c08b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java @@ -1,37 +1,38 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.EntityClientGadget; -import emu.grasscutter.game.entity.EntitySolarIsotomaClientGadget; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.EvtCreateGadgetNotify) -public class HandlerEvtCreateGadgetNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - EvtCreateGadgetNotify notify = EvtCreateGadgetNotify.parseFrom(payload); - - // Sanity check - dont add duplicate entities - if (session.getPlayer().getScene().getEntityById(notify.getEntityId()) != null) { - return; - } - - // Create entity and summon in world - var gadgetId = notify.getConfigId(); - EntityClientGadget gadget = switch (gadgetId) { - //Solar Isotoma. - case EntitySolarIsotomaClientGadget.GADGET_ID -> - new EntitySolarIsotomaClientGadget(session.getPlayer().getScene(), session.getPlayer(), notify); - - //Default. - default -> new EntityClientGadget(session.getPlayer().getScene(), session.getPlayer(), notify); - }; - - session.getPlayer().getScene().onPlayerCreateGadget(gadget); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.EntityClientGadget; +import emu.grasscutter.game.entity.EntitySolarIsotomaClientGadget; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EvtCreateGadgetNotify) +public class HandlerEvtCreateGadgetNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + EvtCreateGadgetNotify notify = EvtCreateGadgetNotify.parseFrom(payload); + + // Sanity check - dont add duplicate entities + if (session.getPlayer().getScene().getEntityById(notify.getEntityId()) != null) { + return; + } + + // Create entity and summon in world + var gadgetId = notify.getConfigId(); + EntityClientGadget gadget = + switch (gadgetId) { + // Solar Isotoma. + case EntitySolarIsotomaClientGadget.GADGET_ID -> new EntitySolarIsotomaClientGadget( + session.getPlayer().getScene(), session.getPlayer(), notify); + + // Default. + default -> new EntityClientGadget( + session.getPlayer().getScene(), session.getPlayer(), notify); + }; + + session.getPlayer().getScene().onPlayerCreateGadget(gadget); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java index 8cb697dfc..bafc30dc6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtDestroyGadgetNotifyOuterClass.EvtDestroyGadgetNotify; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.EvtDestroyGadgetNotify) -public class HandlerEvtDestroyGadgetNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - EvtDestroyGadgetNotify notify = EvtDestroyGadgetNotify.parseFrom(payload); - - session.getPlayer().getScene().onPlayerDestroyGadget(notify.getEntityId()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtDestroyGadgetNotifyOuterClass.EvtDestroyGadgetNotify; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.EvtDestroyGadgetNotify) +public class HandlerEvtDestroyGadgetNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + EvtDestroyGadgetNotify notify = EvtDestroyGadgetNotify.parseFrom(payload); + + session.getPlayer().getScene().onPlayerDestroyGadget(notify.getEntityId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtEntityRenderersChangedNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtEntityRenderersChangedNotify.java index 172d04c38..91b08a599 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtEntityRenderersChangedNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtEntityRenderersChangedNotify.java @@ -1,28 +1,37 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtEntityRenderersChangedNotifyOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketEvtEntityRenderersChangedNotify; - -@Opcodes(PacketOpcodes.EvtEntityRenderersChangedNotify) -public class HandlerEvtEntityRenderersChangedNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = EvtEntityRenderersChangedNotifyOuterClass.EvtEntityRenderersChangedNotify.parseFrom(payload); - - switch (req.getForwardType()) { - case FORWARD_TYPE_TO_ALL -> - session.getPlayer().getScene().broadcastPacket(new PacketEvtEntityRenderersChangedNotify(req)); - case FORWARD_TYPE_TO_ALL_EXCEPT_CUR -> - session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), new PacketEvtEntityRenderersChangedNotify(req)); - case FORWARD_TYPE_TO_HOST -> - session.getPlayer().getScene().getWorld().getHost().sendPacket(new PacketEvtEntityRenderersChangedNotify(req)); - } - - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtEntityRenderersChangedNotifyOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEvtEntityRenderersChangedNotify; + +@Opcodes(PacketOpcodes.EvtEntityRenderersChangedNotify) +public class HandlerEvtEntityRenderersChangedNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + EvtEntityRenderersChangedNotifyOuterClass.EvtEntityRenderersChangedNotify.parseFrom( + payload); + + switch (req.getForwardType()) { + case FORWARD_TYPE_TO_ALL -> session + .getPlayer() + .getScene() + .broadcastPacket(new PacketEvtEntityRenderersChangedNotify(req)); + case FORWARD_TYPE_TO_ALL_EXCEPT_CUR -> session + .getPlayer() + .getScene() + .broadcastPacketToOthers( + session.getPlayer(), new PacketEvtEntityRenderersChangedNotify(req)); + case FORWARD_TYPE_TO_HOST -> session + .getPlayer() + .getScene() + .getWorld() + .getHost() + .sendPacket(new PacketEvtEntityRenderersChangedNotify(req)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java index ecb41bdd5..8814f1fcc 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java @@ -1,14 +1,14 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ExitTransPointRegionNotify) -public class HandlerExitTransPointRegionNotify extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getSotsManager().handleExitTransPointRegionNotify(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ExitTransPointRegionNotify) +public class HandlerExitTransPointRegionNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getSotsManager().handleExitTransPointRegionNotify(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeGetQueueDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeGetQueueDataReq.java index 1be6a8b2e..d0291d3ba 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeGetQueueDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeGetQueueDataReq.java @@ -1,14 +1,14 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ForgeGetQueueDataReq) -public class HandlerForgeGetQueueDataReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getForgingManager().handleForgeGetQueueDataReq(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ForgeGetQueueDataReq) +public class HandlerForgeGetQueueDataReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getForgingManager().handleForgeGetQueueDataReq(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeQueueManipulateReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeQueueManipulateReq.java index b6891613c..2006dbf8a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeQueueManipulateReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeQueueManipulateReq.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeQueueManipulateReqOuterClass.ForgeQueueManipulateReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ForgeQueueManipulateReq) -public class HandlerForgeQueueManipulateReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ForgeQueueManipulateReq req = ForgeQueueManipulateReq.parseFrom(payload); - session.getPlayer().getForgingManager().handleForgeQueueManipulateReq(req); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeQueueManipulateReqOuterClass.ForgeQueueManipulateReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ForgeQueueManipulateReq) +public class HandlerForgeQueueManipulateReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ForgeQueueManipulateReq req = ForgeQueueManipulateReq.parseFrom(payload); + session.getPlayer().getForgingManager().handleForgeQueueManipulateReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeStartReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeStartReq.java index e8a8134c2..5e11866d2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeStartReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerForgeStartReq.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeStartReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ForgeStartReq) -public class HandlerForgeStartReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ForgeStartReqOuterClass.ForgeStartReq req = ForgeStartReqOuterClass.ForgeStartReq.parseFrom(payload); - session.getPlayer().getForgingManager().handleForgeStartReq(req); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeStartReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ForgeStartReq) +public class HandlerForgeStartReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ForgeStartReqOuterClass.ForgeStartReq req = + ForgeStartReqOuterClass.ForgeStartReq.parseFrom(payload); + session.getPlayer().getForgingManager().handleForgeStartReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java index 774b6c848..f996c8424 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeReq.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.FurnitureMakeReq) -public class HandlerFurnitureMakeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getFurnitureManager().queryStatus(); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.FurnitureMakeReq) +public class HandlerFurnitureMakeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getFurnitureManager().queryStatus(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java index eb074af89..08041c893 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerFurnitureMakeStartReq.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FurnitureMakeStartReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.FurnitureMakeStartReq) -public class HandlerFurnitureMakeStartReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = FurnitureMakeStartReqOuterClass.FurnitureMakeStartReq.parseFrom(payload); - - session.getPlayer().getFurnitureManager().startMake(req.getMakeId(), req.getAvatarId()); - - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeStartReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.FurnitureMakeStartReq) +public class HandlerFurnitureMakeStartReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = FurnitureMakeStartReqOuterClass.FurnitureMakeStartReq.parseFrom(payload); + + session.getPlayer().getFurnitureManager().startMake(req.getMakeId(), req.getAvatarId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGachaWishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGachaWishReq.java index ff0e68944..45b913f43 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGachaWishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGachaWishReq.java @@ -1,28 +1,34 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.gacha.GachaBanner; -import emu.grasscutter.game.gacha.PlayerGachaBannerInfo; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GachaWishReqOuterClass.GachaWishReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGachaWishRsp; - -@Opcodes(PacketOpcodes.GachaWishReq) -public class HandlerGachaWishReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GachaWishReq req = GachaWishReq.parseFrom(payload); - - GachaBanner banner = session.getServer().getGachaSystem().getGachaBanners().get(req.getGachaScheduleId()); - PlayerGachaBannerInfo gachaInfo = session.getPlayer().getGachaInfo().getBannerInfo(banner); - - gachaInfo.setFailedChosenItemPulls(0); - gachaInfo.setWishItemId(req.getItemId()); - - session.send(new PacketGachaWishRsp(req.getGachaType(), req.getGachaScheduleId(), req.getItemId(), 0, banner.getWishMaxProgress())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.gacha.GachaBanner; +import emu.grasscutter.game.gacha.PlayerGachaBannerInfo; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GachaWishReqOuterClass.GachaWishReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGachaWishRsp; + +@Opcodes(PacketOpcodes.GachaWishReq) +public class HandlerGachaWishReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GachaWishReq req = GachaWishReq.parseFrom(payload); + + GachaBanner banner = + session.getServer().getGachaSystem().getGachaBanners().get(req.getGachaScheduleId()); + PlayerGachaBannerInfo gachaInfo = session.getPlayer().getGachaInfo().getBannerInfo(banner); + + gachaInfo.setFailedChosenItemPulls(0); + gachaInfo.setWishItemId(req.getItemId()); + + session.send( + new PacketGachaWishRsp( + req.getGachaType(), + req.getGachaScheduleId(), + req.getItemId(), + 0, + banner.getWishMaxProgress())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java index c61942323..91be3e59c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGadgetInteractReq.java @@ -1,21 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.GadgetInteractReq) -public class HandlerGadgetInteractReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GadgetInteractReq req = GadgetInteractReq.parseFrom(payload); - - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_INTERACT_GADGET, req.getGadgetId()); - session.getPlayer().interactWith(req.getGadgetEntityId(), req); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.GadgetInteractReq) +public class HandlerGadgetInteractReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GadgetInteractReq req = GadgetInteractReq.parseFrom(payload); + + session + .getPlayer() + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_INTERACT_GADGET, req.getGadgetId()); + session.getPlayer().interactWith(req.getGadgetEntityId(), req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityInfoReq.java index b87dab46f..7c93b8d35 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityInfoReq.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetActivityInfoReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetActivityInfoRsp; - -import java.util.HashSet; - -@Opcodes(PacketOpcodes.GetActivityInfoReq) -public class HandlerGetActivityInfoReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = GetActivityInfoReqOuterClass.GetActivityInfoReq.parseFrom(payload); - - session.send(new PacketGetActivityInfoRsp( - new HashSet<>(req.getActivityIdListList()), - session.getPlayer().getActivityManager())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetActivityInfoReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetActivityInfoRsp; +import java.util.HashSet; + +@Opcodes(PacketOpcodes.GetActivityInfoReq) +public class HandlerGetActivityInfoReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = GetActivityInfoReqOuterClass.GetActivityInfoReq.parseFrom(payload); + + session.send( + new PacketGetActivityInfoRsp( + new HashSet<>(req.getActivityIdListList()), session.getPlayer().getActivityManager())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityShopSheetInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityShopSheetInfoReq.java index 858660fdb..459a6a6c9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityShopSheetInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetActivityShopSheetInfoReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetActivityShopSheetInfoReqOuterClass.GetActivityShopSheetInfoReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetActivityShopSheetInfoRsp; - -@Opcodes(PacketOpcodes.GetActivityShopSheetInfoReq) -public class HandlerGetActivityShopSheetInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetActivityShopSheetInfoReq req = GetActivityShopSheetInfoReq.parseFrom(payload); - session.getPlayer().sendPacket(new PacketGetActivityShopSheetInfoRsp(req.getShopType())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetActivityShopSheetInfoReqOuterClass.GetActivityShopSheetInfoReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetActivityShopSheetInfoRsp; + +@Opcodes(PacketOpcodes.GetActivityShopSheetInfoReq) +public class HandlerGetActivityShopSheetInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetActivityShopSheetInfoReq req = GetActivityShopSheetInfoReq.parseFrom(payload); + session.getPlayer().sendPacket(new PacketGetActivityShopSheetInfoRsp(req.getShopType())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllH5ActivityInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllH5ActivityInfoReq.java index 54e0fe360..068b341fd 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllH5ActivityInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllH5ActivityInfoReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketH5ActivityIdsNotify; - -@Opcodes(PacketOpcodes.GetAllH5ActivityInfoReq) -public class HandlerGetAllH5ActivityInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketH5ActivityIdsNotify()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketH5ActivityIdsNotify; + +@Opcodes(PacketOpcodes.GetAllH5ActivityInfoReq) +public class HandlerGetAllH5ActivityInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketH5ActivityIdsNotify()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java index 93db71aba..5c05ab3d1 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java @@ -1,18 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetAllMailReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetAllMailRsp; - -@Opcodes(PacketOpcodes.GetAllMailReq) -public class HandlerGetAllMailReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetAllMailReqOuterClass.GetAllMailReq req = GetAllMailReqOuterClass.GetAllMailReq.parseFrom(payload); - session.send(new PacketGetAllMailRsp(session.getPlayer(), req.getIsCollected())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetAllMailReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetAllMailRsp; + +@Opcodes(PacketOpcodes.GetAllMailReq) +public class HandlerGetAllMailReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetAllMailReqOuterClass.GetAllMailReq req = + GetAllMailReqOuterClass.GetAllMailReq.parseFrom(payload); + session.send(new PacketGetAllMailRsp(session.getPlayer(), req.getIsCollected())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllUnlockNameCardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllUnlockNameCardReq.java index 27509fd8d..7b401636c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllUnlockNameCardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllUnlockNameCardReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetAllUnlockNameCardRsp; - -@Opcodes(PacketOpcodes.GetAllUnlockNameCardReq) -public class HandlerGetAllUnlockNameCardReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketGetAllUnlockNameCardRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetAllUnlockNameCardRsp; + +@Opcodes(PacketOpcodes.GetAllUnlockNameCardReq) +public class HandlerGetAllUnlockNameCardReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketGetAllUnlockNameCardRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAuthkeyReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAuthkeyReq.java index 1384e4af3..605410817 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAuthkeyReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAuthkeyReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetAuthkeyRsp; - -@Opcodes(PacketOpcodes.GetAuthkeyReq) -public class HandlerGetAuthkeyReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketGetAuthkeyRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetAuthkeyRsp; + +@Opcodes(PacketOpcodes.GetAuthkeyReq) +public class HandlerGetAuthkeyReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketGetAuthkeyRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetDailyDungeonEntryInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetDailyDungeonEntryInfoReq.java index 20701744d..e4405ac55 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetDailyDungeonEntryInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetDailyDungeonEntryInfoReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetDailyDungeonEntryInfoReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetDailyDungeonEntryInfoRsp; - -@Opcodes(PacketOpcodes.GetDailyDungeonEntryInfoReq) -public class HandlerGetDailyDungeonEntryInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = - GetDailyDungeonEntryInfoReqOuterClass.GetDailyDungeonEntryInfoReq.parseFrom(payload); - - session.send(new PacketGetDailyDungeonEntryInfoRsp(req.getSceneId())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetDailyDungeonEntryInfoReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetDailyDungeonEntryInfoRsp; + +@Opcodes(PacketOpcodes.GetDailyDungeonEntryInfoReq) +public class HandlerGetDailyDungeonEntryInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = GetDailyDungeonEntryInfoReqOuterClass.GetDailyDungeonEntryInfoReq.parseFrom(payload); + + session.send(new PacketGetDailyDungeonEntryInfoRsp(req.getSceneId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowAvatarInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowAvatarInfoReq.java index 52d0cfce2..f2db90c87 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowAvatarInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowAvatarInfoReq.java @@ -1,26 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetFriendShowAvatarInfoReqOuterClass.GetFriendShowAvatarInfoReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetFriendShowAvatarInfoRsp; - -@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoReq) -public class HandlerGetFriendShowAvatarInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetFriendShowAvatarInfoReq req = GetFriendShowAvatarInfoReq.parseFrom(payload); - - int targetUid = req.getUid(); - Player targetPlayer = session.getServer().getPlayerByUid(targetUid, true); - - if (targetPlayer.isShowAvatars()) { - session.send(new PacketGetFriendShowAvatarInfoRsp(targetUid, targetPlayer.getShowAvatarInfoList())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetFriendShowAvatarInfoReqOuterClass.GetFriendShowAvatarInfoReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetFriendShowAvatarInfoRsp; + +@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoReq) +public class HandlerGetFriendShowAvatarInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetFriendShowAvatarInfoReq req = GetFriendShowAvatarInfoReq.parseFrom(payload); + + int targetUid = req.getUid(); + Player targetPlayer = session.getServer().getPlayerByUid(targetUid, true); + + if (targetPlayer.isShowAvatars()) { + session.send( + new PacketGetFriendShowAvatarInfoRsp(targetUid, targetPlayer.getShowAvatarInfoList())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowNameCardInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowNameCardInfoReq.java index f301ff4de..93d5645b6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowNameCardInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFriendShowNameCardInfoReq.java @@ -1,22 +1,24 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetFriendShowNameCardInfoReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetFriendShowNameCardInfoRsp; - -@Opcodes(PacketOpcodes.GetFriendShowNameCardInfoReq) -public class HandlerGetFriendShowNameCardInfoReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = GetFriendShowNameCardInfoReqOuterClass.GetFriendShowNameCardInfoReq.parseFrom(payload); - - int targetUid = req.getUid(); - Player target = session.getServer().getPlayerByUid(targetUid, true); - - session.send(new PacketGetFriendShowNameCardInfoRsp(targetUid, target.getShowNameCardInfoList())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetFriendShowNameCardInfoReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetFriendShowNameCardInfoRsp; + +@Opcodes(PacketOpcodes.GetFriendShowNameCardInfoReq) +public class HandlerGetFriendShowNameCardInfoReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + GetFriendShowNameCardInfoReqOuterClass.GetFriendShowNameCardInfoReq.parseFrom(payload); + + int targetUid = req.getUid(); + Player target = session.getServer().getPlayerByUid(targetUid, true); + + session.send( + new PacketGetFriendShowNameCardInfoRsp(targetUid, target.getShowNameCardInfoList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFurnitureCurModuleArrangeCountReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFurnitureCurModuleArrangeCountReq.java index 747974cb9..6ca662014 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFurnitureCurModuleArrangeCountReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetFurnitureCurModuleArrangeCountReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketFurnitureCurModuleArrangeCountNotify; - -@Opcodes(PacketOpcodes.GetFurnitureCurModuleArrangeCountReq) -public class HandlerGetFurnitureCurModuleArrangeCountReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketFurnitureCurModuleArrangeCountNotify()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketFurnitureCurModuleArrangeCountNotify; + +@Opcodes(PacketOpcodes.GetFurnitureCurModuleArrangeCountReq) +public class HandlerGetFurnitureCurModuleArrangeCountReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketFurnitureCurModuleArrangeCountNotify()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetGachaInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetGachaInfoReq.java index 87a66323a..e1262c28e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetGachaInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetGachaInfoReq.java @@ -1,17 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetGachaInfoRsp; - -@Opcodes(PacketOpcodes.GetGachaInfoReq) -public class HandlerGetGachaInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketGetGachaInfoRsp(session.getServer().getGachaSystem(), session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetGachaInfoRsp; + +@Opcodes(PacketOpcodes.GetGachaInfoReq) +public class HandlerGetGachaInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send( + new PacketGetGachaInfoRsp(session.getServer().getGachaSystem(), session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetHomeLevelUpRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetHomeLevelUpRewardReq.java index 2c8bc4cc9..0bcd1fac4 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetHomeLevelUpRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetHomeLevelUpRewardReq.java @@ -1,41 +1,41 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetHomeLevelUpRewardReqOuterClass.GetHomeLevelUpRewardReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetHomeLevelUpRewardRsp; - -import java.util.List; -import java.util.Set; - -@Opcodes(PacketOpcodes.GetHomeLevelUpRewardReq) -public class HandlerGetHomeLevelUpRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Replica of TakePlayerLevelReward for adv rank rewards - Player pl = session.getPlayer(); - synchronized (pl) { - GetHomeLevelUpRewardReq req = GetHomeLevelUpRewardReq.parseFrom(payload); - int level = req.getLevel(); - Set homeRewardedLevels = session.getPlayer().getHomeRewardedLevels(); - if (!homeRewardedLevels.contains(level)) {// No duplicated reward - int rewardId = GameData.getHomeWorldLevelDataMap().get(level).getRewardId(); - if (rewardId != 0) { - List rewardItems = GameData.getRewardDataMap().get(rewardId).getRewardItemList(); - pl.getInventory().addItemParamDatas(rewardItems, ActionReason.GetHomeLevelupReward); - homeRewardedLevels.add(level); - pl.setHomeRewardedLevels(homeRewardedLevels); - pl.save(); - pl.getHome().onClaimReward(pl); - session.send(new PacketGetHomeLevelUpRewardRsp(level, rewardId)); - } - } - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetHomeLevelUpRewardReqOuterClass.GetHomeLevelUpRewardReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetHomeLevelUpRewardRsp; +import java.util.List; +import java.util.Set; + +@Opcodes(PacketOpcodes.GetHomeLevelUpRewardReq) +public class HandlerGetHomeLevelUpRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Replica of TakePlayerLevelReward for adv rank rewards + Player pl = session.getPlayer(); + synchronized (pl) { + GetHomeLevelUpRewardReq req = GetHomeLevelUpRewardReq.parseFrom(payload); + int level = req.getLevel(); + Set homeRewardedLevels = session.getPlayer().getHomeRewardedLevels(); + if (!homeRewardedLevels.contains(level)) { // No duplicated reward + int rewardId = GameData.getHomeWorldLevelDataMap().get(level).getRewardId(); + if (rewardId != 0) { + List rewardItems = + GameData.getRewardDataMap().get(rewardId).getRewardItemList(); + pl.getInventory().addItemParamDatas(rewardItems, ActionReason.GetHomeLevelupReward); + homeRewardedLevels.add(level); + pl.setHomeRewardedLevels(homeRewardedLevels); + pl.save(); + pl.getHome().onClaimReward(pl); + session.send(new PacketGetHomeLevelUpRewardRsp(level, rewardId)); + } + } + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java index 885724638..015420850 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetInvestigationMonsterReq.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetInvestigationMonsterReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetInvestigationMonsterRsp; - -@Opcodes(PacketOpcodes.GetInvestigationMonsterReq) -public class HandlerGetInvestigationMonsterReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = GetInvestigationMonsterReqOuterClass.GetInvestigationMonsterReq.parseFrom(payload); - - session.send(new PacketGetInvestigationMonsterRsp( - session.getPlayer(), - session.getServer().getWorldDataSystem(), - req.getCityIdListList())); - - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetInvestigationMonsterReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetInvestigationMonsterRsp; + +@Opcodes(PacketOpcodes.GetInvestigationMonsterReq) +public class HandlerGetInvestigationMonsterReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = GetInvestigationMonsterReqOuterClass.GetInvestigationMonsterReq.parseFrom(payload); + + session.send( + new PacketGetInvestigationMonsterRsp( + session.getPlayer(), + session.getServer().getWorldDataSystem(), + req.getCityIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetMailItemReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetMailItemReq.java index 38e2f47c0..1eed668ef 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetMailItemReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetMailItemReq.java @@ -1,19 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetMailItemReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetMailItemRsp; - -@Opcodes(PacketOpcodes.GetMailItemReq) -public class HandlerGetMailItemReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetMailItemReqOuterClass.GetMailItemReq req = GetMailItemReqOuterClass.GetMailItemReq.parseFrom(payload); - session.send(new PacketGetMailItemRsp(session.getPlayer(), req.getMailIdListList())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetMailItemReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetMailItemRsp; + +@Opcodes(PacketOpcodes.GetMailItemReq) +public class HandlerGetMailItemReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetMailItemReqOuterClass.GetMailItemReq req = + GetMailItemReqOuterClass.GetMailItemReq.parseFrom(payload); + session.send(new PacketGetMailItemRsp(session.getPlayer(), req.getMailIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerBlacklistReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerBlacklistReq.java index 8e53e0be4..fee70dd9d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerBlacklistReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerBlacklistReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.GetPlayerBlacklistReq) -public class HandlerGetPlayerBlacklistReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new BasePacket(PacketOpcodes.GetPlayerBlacklistRsp).buildHeader(3)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.GetPlayerBlacklistReq) +public class HandlerGetPlayerBlacklistReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new BasePacket(PacketOpcodes.GetPlayerBlacklistRsp).buildHeader(3)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerFriendListReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerFriendListReq.java index 8c705d6cc..6d4fc40f1 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerFriendListReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerFriendListReq.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetPlayerFriendListRsp; - -@Opcodes(PacketOpcodes.GetPlayerFriendListReq) -public class HandlerGetPlayerFriendListReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - //session.send(new PacketGetPlayerAskFriendListRsp(session.getPlayer())); - session.send(new PacketGetPlayerFriendListRsp(session.getPlayer())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetPlayerFriendListRsp; + +@Opcodes(PacketOpcodes.GetPlayerFriendListReq) +public class HandlerGetPlayerFriendListReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // session.send(new PacketGetPlayerAskFriendListRsp(session.getPlayer())); + session.send(new PacketGetPlayerFriendListRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerHomeCompInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerHomeCompInfoReq.java index 5365669f3..d7cb0ddb3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerHomeCompInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerHomeCompInfoReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; - -@Opcodes(PacketOpcodes.GetPlayerHomeCompInfoReq) -public class HandlerGetPlayerHomeCompInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; + +@Opcodes(PacketOpcodes.GetPlayerHomeCompInfoReq) +public class HandlerGetPlayerHomeCompInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerSocialDetailReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerSocialDetailReq.java index 0655d95f2..c2832f3df 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerSocialDetailReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerSocialDetailReq.java @@ -1,26 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetPlayerSocialDetailReqOuterClass.GetPlayerSocialDetailReq; -import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetPlayerSocialDetailRsp; - -@Opcodes(PacketOpcodes.GetPlayerSocialDetailReq) -public class HandlerGetPlayerSocialDetailReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetPlayerSocialDetailReq req = GetPlayerSocialDetailReq.parseFrom(payload); - - SocialDetail.Builder detail = session.getServer().getSocialDetailByUid(req.getUid()); - - if (detail != null) { - detail.setIsFriend(session.getPlayer().getFriendsList().isFriendsWith(req.getUid())); - } - - session.send(new PacketGetPlayerSocialDetailRsp(detail)); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetPlayerSocialDetailReqOuterClass.GetPlayerSocialDetailReq; +import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetPlayerSocialDetailRsp; + +@Opcodes(PacketOpcodes.GetPlayerSocialDetailReq) +public class HandlerGetPlayerSocialDetailReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetPlayerSocialDetailReq req = GetPlayerSocialDetailReq.parseFrom(payload); + + SocialDetail.Builder detail = session.getServer().getSocialDetailByUid(req.getUid()); + + if (detail != null) { + detail.setIsFriend(session.getPlayer().getFriendsList().isFriendsWith(req.getUid())); + } + + session.send(new PacketGetPlayerSocialDetailRsp(detail)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java index bcc9816f3..496a8e95d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java @@ -1,138 +1,146 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetPlayerTokenReqOuterClass.GetPlayerTokenReq; -import emu.grasscutter.server.event.game.PlayerCreationEvent; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.game.GameSession.SessionState; -import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp; -import emu.grasscutter.utils.ByteHelper; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.Utils; - -import javax.crypto.Cipher; -import java.nio.ByteBuffer; -import java.security.Signature; - -import static emu.grasscutter.config.Configuration.ACCOUNT; - -@Opcodes(PacketOpcodes.GetPlayerTokenReq) -public class HandlerGetPlayerTokenReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetPlayerTokenReq req = GetPlayerTokenReq.parseFrom(payload); - - // Authenticate - Account account = DatabaseHelper.getAccountById(req.getAccountUid()); - if (account == null || !account.getToken().equals(req.getAccountToken())) { - return; - } - - // Set account - session.setAccount(account); - - // Check if player object exists in server - // NOTE: CHECKING MUST SITUATED HERE (BEFORE getPlayerByUid)! because to save firstly ,to load secondly !!! - // TODO - optimize - boolean kicked = false; - Player exists = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); - if (exists != null) { - GameSession existsSession = exists.getSession(); - if (existsSession != session) {// No self-kicking - exists.onLogout();//must save immediately , or the below will load old data - existsSession.close(); - Grasscutter.getLogger().warn("Player {} was kicked due to duplicated login", account.getUsername()); - kicked = true; - } - } - - //NOTE: If there are 5 online players, max count of player is 5, - // a new client want to login by kicking one of them , - // I think it should be allowed - if (!kicked) { - // Max players limit - if (ACCOUNT.maxPlayer > -1 && Grasscutter.getGameServer().getPlayers().size() >= ACCOUNT.maxPlayer) { - session.close(); - return; - } - } - - // Call creation event. - PlayerCreationEvent event = new PlayerCreationEvent(session, Player.class); - event.call(); - - // Get player. - Player player = DatabaseHelper.getPlayerByAccount(account, event.getPlayerClass()); - - if (player == null) { - int nextPlayerUid = DatabaseHelper.getNextPlayerId(session.getAccount().getReservedPlayerUid()); - - // Create player instance from event. - player = event.getPlayerClass().getDeclaredConstructor(GameSession.class).newInstance(session); - - // Save to db - DatabaseHelper.generatePlayerUid(player, nextPlayerUid); - } - - // Set player object for session - session.setPlayer(player); - - // Checks if the player is banned - if (session.getAccount().isBanned()) { - session.setState(SessionState.ACCOUNT_BANNED); - session.send(new PacketGetPlayerTokenRsp(session, 21, "FORBID_CHEATING_PLUGINS", session.getAccount().getBanEndTime())); - return; - } - - // Load player from database - player.loadFromDatabase(); - - // Set session state - session.setUseSecretKey(true); - session.setState(SessionState.WAITING_FOR_LOGIN); - - // Only >= 2.7.50 has this - if (req.getKeyId() > 0) { - try { - Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - cipher.init(Cipher.DECRYPT_MODE, Crypto.CUR_SIGNING_KEY); - - var client_seed_encrypted = Utils.base64Decode(req.getClientRandKey()); - var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted)) - .getLong(); - - byte[] seed_bytes = ByteBuffer.wrap(new byte[8]) - .putLong(Crypto.ENCRYPT_SEED ^ client_seed) - .array(); - - cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(req.getKeyId())); - var seed_encrypted = cipher.doFinal(seed_bytes); - - Signature privateSignature = Signature.getInstance("SHA256withRSA"); - privateSignature.initSign(Crypto.CUR_SIGNING_KEY); - privateSignature.update(seed_bytes); - - session.send(new PacketGetPlayerTokenRsp(session, Utils.base64Encode(seed_encrypted), Utils.base64Encode(privateSignature.sign()))); - } catch (Exception ignore) { - // Only UA Patch users will have exception - byte[] clientBytes = Utils.base64Decode(req.getClientRandKey()); - byte[] seed = ByteHelper.longToBytes(Crypto.ENCRYPT_SEED); - Crypto.xor(clientBytes, seed); - - String base64str = Utils.base64Encode(clientBytes); - - session.send(new PacketGetPlayerTokenRsp(session, base64str, "bm90aGluZyBoZXJl")); - } - } else { - // Send packet - session.send(new PacketGetPlayerTokenRsp(session)); - } - } -} +package emu.grasscutter.server.packet.recv; + +import static emu.grasscutter.config.Configuration.ACCOUNT; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetPlayerTokenReqOuterClass.GetPlayerTokenReq; +import emu.grasscutter.server.event.game.PlayerCreationEvent; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.game.GameSession.SessionState; +import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp; +import emu.grasscutter.utils.ByteHelper; +import emu.grasscutter.utils.Crypto; +import emu.grasscutter.utils.Utils; +import java.nio.ByteBuffer; +import java.security.Signature; +import javax.crypto.Cipher; + +@Opcodes(PacketOpcodes.GetPlayerTokenReq) +public class HandlerGetPlayerTokenReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetPlayerTokenReq req = GetPlayerTokenReq.parseFrom(payload); + + // Authenticate + Account account = DatabaseHelper.getAccountById(req.getAccountUid()); + if (account == null || !account.getToken().equals(req.getAccountToken())) { + return; + } + + // Set account + session.setAccount(account); + + // Check if player object exists in server + // NOTE: CHECKING MUST SITUATED HERE (BEFORE getPlayerByUid)! because to save firstly ,to load + // secondly !!! + // TODO - optimize + boolean kicked = false; + Player exists = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (exists != null) { + GameSession existsSession = exists.getSession(); + if (existsSession != session) { // No self-kicking + exists.onLogout(); // must save immediately , or the below will load old data + existsSession.close(); + Grasscutter.getLogger() + .warn("Player {} was kicked due to duplicated login", account.getUsername()); + kicked = true; + } + } + + // NOTE: If there are 5 online players, max count of player is 5, + // a new client want to login by kicking one of them , + // I think it should be allowed + if (!kicked) { + // Max players limit + if (ACCOUNT.maxPlayer > -1 + && Grasscutter.getGameServer().getPlayers().size() >= ACCOUNT.maxPlayer) { + session.close(); + return; + } + } + + // Call creation event. + PlayerCreationEvent event = new PlayerCreationEvent(session, Player.class); + event.call(); + + // Get player. + Player player = DatabaseHelper.getPlayerByAccount(account, event.getPlayerClass()); + + if (player == null) { + int nextPlayerUid = + DatabaseHelper.getNextPlayerId(session.getAccount().getReservedPlayerUid()); + + // Create player instance from event. + player = + event.getPlayerClass().getDeclaredConstructor(GameSession.class).newInstance(session); + + // Save to db + DatabaseHelper.generatePlayerUid(player, nextPlayerUid); + } + + // Set player object for session + session.setPlayer(player); + + // Checks if the player is banned + if (session.getAccount().isBanned()) { + session.setState(SessionState.ACCOUNT_BANNED); + session.send( + new PacketGetPlayerTokenRsp( + session, 21, "FORBID_CHEATING_PLUGINS", session.getAccount().getBanEndTime())); + return; + } + + // Load player from database + player.loadFromDatabase(); + + // Set session state + session.setUseSecretKey(true); + session.setState(SessionState.WAITING_FOR_LOGIN); + + // Only >= 2.7.50 has this + if (req.getKeyId() > 0) { + try { + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.DECRYPT_MODE, Crypto.CUR_SIGNING_KEY); + + var client_seed_encrypted = Utils.base64Decode(req.getClientRandKey()); + var client_seed = ByteBuffer.wrap(cipher.doFinal(client_seed_encrypted)).getLong(); + + byte[] seed_bytes = + ByteBuffer.wrap(new byte[8]).putLong(Crypto.ENCRYPT_SEED ^ client_seed).array(); + + cipher.init(Cipher.ENCRYPT_MODE, Crypto.EncryptionKeys.get(req.getKeyId())); + var seed_encrypted = cipher.doFinal(seed_bytes); + + Signature privateSignature = Signature.getInstance("SHA256withRSA"); + privateSignature.initSign(Crypto.CUR_SIGNING_KEY); + privateSignature.update(seed_bytes); + + session.send( + new PacketGetPlayerTokenRsp( + session, + Utils.base64Encode(seed_encrypted), + Utils.base64Encode(privateSignature.sign()))); + } catch (Exception ignore) { + // Only UA Patch users will have exception + byte[] clientBytes = Utils.base64Decode(req.getClientRandKey()); + byte[] seed = ByteHelper.longToBytes(Crypto.ENCRYPT_SEED); + Crypto.xor(clientBytes, seed); + + String base64str = Utils.base64Encode(clientBytes); + + session.send(new PacketGetPlayerTokenRsp(session, base64str, "bm90aGluZyBoZXJl")); + } + } else { + // Send packet + session.send(new PacketGetPlayerTokenRsp(session)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetRegionSearchReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetRegionSearchReq.java index 18f29f952..d87e3462f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetRegionSearchReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetRegionSearchReq.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.GetRegionSearchReq) -public class HandlerGetRegionSearchReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.GetRegionSearchReq) +public class HandlerGetRegionSearchReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetSceneAreaReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetSceneAreaReq.java index 7f30ff5e3..9524a73e8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetSceneAreaReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetSceneAreaReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetSceneAreaReqOuterClass.GetSceneAreaReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetSceneAreaRsp; - -@Opcodes(PacketOpcodes.GetSceneAreaReq) -public class HandlerGetSceneAreaReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetSceneAreaReq req = GetSceneAreaReq.parseFrom(payload); - - session.send(new PacketGetSceneAreaRsp(session.getPlayer(), req.getSceneId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetSceneAreaReqOuterClass.GetSceneAreaReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetSceneAreaRsp; + +@Opcodes(PacketOpcodes.GetSceneAreaReq) +public class HandlerGetSceneAreaReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetSceneAreaReq req = GetSceneAreaReq.parseFrom(payload); + + session.send(new PacketGetSceneAreaRsp(session.getPlayer(), req.getSceneId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetScenePointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetScenePointReq.java index 18047df53..fcb395aa9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetScenePointReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetScenePointReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetScenePointReqOuterClass.GetScenePointReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetScenePointRsp; - -@Opcodes(PacketOpcodes.GetScenePointReq) -public class HandlerGetScenePointReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetScenePointReq req = GetScenePointReq.parseFrom(payload); - - session.send(new PacketGetScenePointRsp(session.getPlayer(), req.getSceneId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetScenePointReqOuterClass.GetScenePointReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetScenePointRsp; + +@Opcodes(PacketOpcodes.GetScenePointReq) +public class HandlerGetScenePointReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetScenePointReq req = GetScenePointReq.parseFrom(payload); + + session.send(new PacketGetScenePointRsp(session.getPlayer(), req.getSceneId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java index c0accac1b..2be1381bc 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopReq.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetShopReqOuterClass.GetShopReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetShopRsp; - -@Opcodes(PacketOpcodes.GetShopReq) -public class HandlerGetShopReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - GetShopReq req = GetShopReq.parseFrom(payload); - - session.send(new PacketGetShopRsp(session.getPlayer(), req.getShopType())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetShopReqOuterClass.GetShopReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetShopRsp; + +@Opcodes(PacketOpcodes.GetShopReq) +public class HandlerGetShopReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetShopReq req = GetShopReq.parseFrom(payload); + + session.send(new PacketGetShopRsp(session.getPlayer(), req.getShopType())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopmallDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopmallDataReq.java index fd4d482d7..5d4362c86 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopmallDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetShopmallDataReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetShopmallDataRsp; - -@Opcodes(PacketOpcodes.GetShopmallDataReq) -public class HandlerGetShopmallDataReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // TODO add the correct shops - session.send(new PacketGetShopmallDataRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetShopmallDataRsp; + +@Opcodes(PacketOpcodes.GetShopmallDataReq) +public class HandlerGetShopmallDataReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // TODO add the correct shops + session.send(new PacketGetShopmallDataRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java index 5f2be1ebe..a9e145cd8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetWidgetSlotRsp; - -@Opcodes(PacketOpcodes.GetWidgetSlotReq) -public class HandlerGetWidgetSlotReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - Player player = session.getPlayer(); - session.send(new PacketGetWidgetSlotRsp(player)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetWidgetSlotRsp; + +@Opcodes(PacketOpcodes.GetWidgetSlotReq) +public class HandlerGetWidgetSlotReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + Player player = session.getPlayer(); + session.send(new PacketGetWidgetSlotRsp(player)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWorldMpInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWorldMpInfoReq.java index dcba93111..780fb4559 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWorldMpInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWorldMpInfoReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetWorldMpInfoRsp; - -@Opcodes(PacketOpcodes.GetWorldMpInfoReq) -public class HandlerGetWorldMpInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketGetWorldMpInfoRsp(session.getPlayer().getWorld())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetWorldMpInfoRsp; + +@Opcodes(PacketOpcodes.GetWorldMpInfoReq) +public class HandlerGetWorldMpInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketGetWorldMpInfoRsp(session.getPlayer().getWorld())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java index 331fd7f09..b9e665541 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HitTreeNotifyOuterClass.HitTreeNotify; -import emu.grasscutter.server.game.GameSession; - -/** - * Implement Deforestation Function - */ -@Opcodes(PacketOpcodes.HitTreeNotify) -public class HandlerHitTreeNotify extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - HitTreeNotify hit = HitTreeNotify.parseFrom(payload); - session.getPlayer().getDeforestationManager().onDeforestationInvoke(hit); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HitTreeNotifyOuterClass.HitTreeNotify; +import emu.grasscutter.server.game.GameSession; + +/** Implement Deforestation Function */ +@Opcodes(PacketOpcodes.HitTreeNotify) +public class HandlerHitTreeNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + HitTreeNotify hit = HitTreeNotify.parseFrom(payload); + session.getPlayer().getDeforestationManager().onDeforestationInvoke(hit); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java index 08b8bc4ec..c18bb3b5d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeEditModeReq.java @@ -1,27 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeEditModeReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; -import emu.grasscutter.server.packet.send.PacketHomeChangeEditModeRsp; -import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; -import emu.grasscutter.server.packet.send.PacketHomePreChangeEditModeNotify; - -@Opcodes(PacketOpcodes.HomeChangeEditModeReq) -public class HandlerHomeChangeEditModeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = HomeChangeEditModeReqOuterClass.HomeChangeEditModeReq.parseFrom(payload); - - session.send(new PacketHomePreChangeEditModeNotify(req.getIsEnterEditMode())); - session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), req.getIsEnterEditMode())); - session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); - - session.send(new PacketHomeChangeEditModeRsp(req.getIsEnterEditMode())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeEditModeReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; +import emu.grasscutter.server.packet.send.PacketHomeChangeEditModeRsp; +import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; +import emu.grasscutter.server.packet.send.PacketHomePreChangeEditModeNotify; + +@Opcodes(PacketOpcodes.HomeChangeEditModeReq) +public class HandlerHomeChangeEditModeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = HomeChangeEditModeReqOuterClass.HomeChangeEditModeReq.parseFrom(payload); + + session.send(new PacketHomePreChangeEditModeNotify(req.getIsEnterEditMode())); + session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), req.getIsEnterEditMode())); + session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); + + session.send(new PacketHomeChangeEditModeRsp(req.getIsEnterEditMode())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java index 2e50cc070..24d8e7a6d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChangeModuleReq.java @@ -1,37 +1,37 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeModuleReqOuterClass; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeChangeModuleRsp; -import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; -import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.HomeChangeModuleReq) -public class HandlerHomeChangeModuleReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - HomeChangeModuleReqOuterClass.HomeChangeModuleReq req = - HomeChangeModuleReqOuterClass.HomeChangeModuleReq.parseFrom(payload); - session.getPlayer().setCurrentRealmId(req.getTargetModuleId()); - session.send(new PacketHomeChangeModuleRsp(req.getTargetModuleId())); - session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); - session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); - - int realmId = 2000 + req.getTargetModuleId(); - - Scene scene = session.getPlayer().getWorld().getSceneById(realmId); - Position pos = scene.getScriptManager().getConfig().born_pos; - - session.getPlayer().getWorld().transferPlayerToScene( - session.getPlayer(), realmId, - TeleportType.WAYPOINT, pos - ); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeModuleReqOuterClass; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeChangeModuleRsp; +import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; +import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.HomeChangeModuleReq) +public class HandlerHomeChangeModuleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + HomeChangeModuleReqOuterClass.HomeChangeModuleReq req = + HomeChangeModuleReqOuterClass.HomeChangeModuleReq.parseFrom(payload); + session.getPlayer().setCurrentRealmId(req.getTargetModuleId()); + session.send(new PacketHomeChangeModuleRsp(req.getTargetModuleId())); + session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); + session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); + + int realmId = 2000 + req.getTargetModuleId(); + + Scene scene = session.getPlayer().getWorld().getSceneById(realmId); + Position pos = scene.getScriptManager().getConfig().born_pos; + + session + .getPlayer() + .getWorld() + .transferPlayerToScene(session.getPlayer(), realmId, TeleportType.WAYPOINT, pos); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java index 30b7bd16c..9d25e4e2c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java @@ -1,26 +1,25 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChooseModuleReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeChooseModuleRsp; -import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; -import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; - - -@Opcodes(PacketOpcodes.HomeChooseModuleReq) -public class HandlerHomeChooseModuleReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - HomeChooseModuleReqOuterClass.HomeChooseModuleReq req = - HomeChooseModuleReqOuterClass.HomeChooseModuleReq.parseFrom(payload); - session.getPlayer().addRealmList(req.getModuleId()); - session.getPlayer().setCurrentRealmId(req.getModuleId()); - session.send(new PacketHomeChooseModuleRsp(req.getModuleId())); - session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); - session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChooseModuleReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeChooseModuleRsp; +import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; +import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; + +@Opcodes(PacketOpcodes.HomeChooseModuleReq) +public class HandlerHomeChooseModuleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + HomeChooseModuleReqOuterClass.HomeChooseModuleReq req = + HomeChooseModuleReqOuterClass.HomeChooseModuleReq.parseFrom(payload); + session.getPlayer().addRealmList(req.getModuleId()); + session.getPlayer().setCurrentRealmId(req.getModuleId()); + session.send(new PacketHomeChooseModuleRsp(req.getModuleId())); + session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); + session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java index 5639cccd0..f6b26ae6c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeEnterEditModeFinishReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeEnterEditModeFinishRsp; - -@Opcodes(PacketOpcodes.HomeEnterEditModeFinishReq) -public class HandlerHomeEnterEditModeFinishReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - /* - * This packet is about the edit mode - */ - session.send(new PacketHomeEnterEditModeFinishRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeEnterEditModeFinishRsp; + +@Opcodes(PacketOpcodes.HomeEnterEditModeFinishReq) +public class HandlerHomeEnterEditModeFinishReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + /* + * This packet is about the edit mode + */ + session.send(new PacketHomeEnterEditModeFinishRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetArrangementInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetArrangementInfoReq.java index ae5f7ca67..b2d3574c7 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetArrangementInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetArrangementInfoReq.java @@ -1,20 +1,20 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeGetArrangementInfoReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeGetArrangementInfoRsp; - -@Opcodes(PacketOpcodes.HomeGetArrangementInfoReq) -public class HandlerHomeGetArrangementInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = HomeGetArrangementInfoReqOuterClass.HomeGetArrangementInfoReq.parseFrom(payload); - - session.send(new PacketHomeGetArrangementInfoRsp(session.getPlayer(), req.getSceneIdListList())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeGetArrangementInfoReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeGetArrangementInfoRsp; + +@Opcodes(PacketOpcodes.HomeGetArrangementInfoReq) +public class HandlerHomeGetArrangementInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = HomeGetArrangementInfoReqOuterClass.HomeGetArrangementInfoReq.parseFrom(payload); + + session.send( + new PacketHomeGetArrangementInfoRsp(session.getPlayer(), req.getSceneIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetBasicInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetBasicInfoReq.java index 5af3acf6a..6f6ac91b2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetBasicInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeGetBasicInfoReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; - -@Opcodes(PacketOpcodes.HomeGetBasicInfoReq) -public class HandlerHomeGetBasicInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - - session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), false)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeBasicInfoNotify; + +@Opcodes(PacketOpcodes.HomeGetBasicInfoReq) +public class HandlerHomeGetBasicInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + + session.send(new PacketHomeBasicInfoNotify(session.getPlayer(), false)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeFetterExpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeFetterExpReq.java index ccd173a4a..b9d00bec2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeFetterExpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeFetterExpReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeResourceTakeFetterExpRsp; - -@Opcodes(PacketOpcodes.HomeResourceTakeFetterExpReq) -public class HandlerHomeResourceTakeFetterExpReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - - session.send(new PacketHomeResourceTakeFetterExpRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeResourceTakeFetterExpRsp; + +@Opcodes(PacketOpcodes.HomeResourceTakeFetterExpReq) +public class HandlerHomeResourceTakeFetterExpReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + + session.send(new PacketHomeResourceTakeFetterExpRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeHomeCoinReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeHomeCoinReq.java index 013ae7f11..6562169ea 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeHomeCoinReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeResourceTakeHomeCoinReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeResourceTakeHomeCoinRsp; - -@Opcodes(PacketOpcodes.HomeResourceTakeHomeCoinReq) -public class HandlerHomeResourceTakeHomeCoinReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - - session.send(new PacketHomeResourceTakeHomeCoinRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeResourceTakeHomeCoinRsp; + +@Opcodes(PacketOpcodes.HomeResourceTakeHomeCoinReq) +public class HandlerHomeResourceTakeHomeCoinReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + + session.send(new PacketHomeResourceTakeHomeCoinRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneInitFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneInitFinishReq.java index 7b835b080..23ee974cb 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneInitFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneInitFinishReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeSceneInitFinishRsp; - -@Opcodes(PacketOpcodes.HomeSceneInitFinishReq) -public class HandlerHomeSceneInitFinishReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketHomeSceneInitFinishRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeSceneInitFinishRsp; + +@Opcodes(PacketOpcodes.HomeSceneInitFinishReq) +public class HandlerHomeSceneInitFinishReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send(new PacketHomeSceneInitFinishRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java index 832da5d75..a34f04766 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeSceneJumpReq.java @@ -1,46 +1,51 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeSceneJumpReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeSceneJumpRsp; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.HomeSceneJumpReq) -public class HandlerHomeSceneJumpReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = HomeSceneJumpReqOuterClass.HomeSceneJumpReq.parseFrom(payload); - - int realmId = 2000 + session.getPlayer().getCurrentRealmId(); - - var home = session.getPlayer().getHome(); - var homeScene = home.getHomeSceneItem(realmId); - home.save(); - - Scene scene = session.getPlayer().getWorld().getSceneById(req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId); - Position pos = scene.getScriptManager().getConfig().born_pos; - Position rot = home.getSceneMap().get(scene.getId()).getBornRot(); - - // Make player face correct direction when entering or exiting - session.getPlayer().getRotation().set(rot); - - // Make player exit to front of main house - if (!req.getIsEnterRoomScene()) { - pos = home.getSceneMap().get(realmId).getBornPos(); - } - - session.getPlayer().getWorld().transferPlayerToScene( - session.getPlayer(), - req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId, - pos - ); - - session.send(new PacketHomeSceneJumpRsp(req.getIsEnterRoomScene())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeSceneJumpReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeSceneJumpRsp; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.HomeSceneJumpReq) +public class HandlerHomeSceneJumpReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = HomeSceneJumpReqOuterClass.HomeSceneJumpReq.parseFrom(payload); + + int realmId = 2000 + session.getPlayer().getCurrentRealmId(); + + var home = session.getPlayer().getHome(); + var homeScene = home.getHomeSceneItem(realmId); + home.save(); + + Scene scene = + session + .getPlayer() + .getWorld() + .getSceneById(req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId); + Position pos = scene.getScriptManager().getConfig().born_pos; + Position rot = home.getSceneMap().get(scene.getId()).getBornRot(); + + // Make player face correct direction when entering or exiting + session.getPlayer().getRotation().set(rot); + + // Make player exit to front of main house + if (!req.getIsEnterRoomScene()) { + pos = home.getSceneMap().get(realmId).getBornPos(); + } + + session + .getPlayer() + .getWorld() + .transferPlayerToScene( + session.getPlayer(), + req.getIsEnterRoomScene() ? homeScene.getRoomSceneId() : realmId, + pos); + + session.send(new PacketHomeSceneJumpRsp(req.getIsEnterRoomScene())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java index 5a880cfd2..a3f6833f0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeUpdateArrangementInfoReq.java @@ -1,27 +1,27 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeUpdateArrangementInfoReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketHomeUpdateArrangementInfoRsp; - -@Opcodes(PacketOpcodes.HomeUpdateArrangementInfoReq) -public class HandlerHomeUpdateArrangementInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = HomeUpdateArrangementInfoReqOuterClass.HomeUpdateArrangementInfoReq.parseFrom(payload); - - var homeScene = session.getPlayer().getHome() - .getHomeSceneItem(session.getPlayer().getSceneId()); - - homeScene.update(req.getSceneArrangementInfo()); - - session.getPlayer().getHome().save(); - - session.send(new PacketHomeUpdateArrangementInfoRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeUpdateArrangementInfoReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeUpdateArrangementInfoRsp; + +@Opcodes(PacketOpcodes.HomeUpdateArrangementInfoReq) +public class HandlerHomeUpdateArrangementInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + HomeUpdateArrangementInfoReqOuterClass.HomeUpdateArrangementInfoReq.parseFrom(payload); + + var homeScene = + session.getPlayer().getHome().getHomeSceneItem(session.getPlayer().getSceneId()); + + homeScene.update(req.getSceneArrangementInfo()); + + session.getPlayer().getHome().save(); + + session.send(new PacketHomeUpdateArrangementInfoRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java index 65551d759..82d8e2471 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java @@ -1,17 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.MarkMapReq) -public class HandlerMarkMapReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - MarkMapReq req = MarkMapReq.parseFrom(payload); - session.getPlayer().getMapMarksManager().handleMapMarkReq(req); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.MarkMapReq) +public class HandlerMarkMapReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + MarkMapReq req = MarkMapReq.parseFrom(payload); + session.getPlayer().getMapMarksManager().handleMapMarkReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java index e5ab20adb..83fe33315 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java @@ -1,28 +1,31 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.McoinExchangeHcoinReqOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketMcoinExchangeHcoinRsp; - -@Opcodes(PacketOpcodes.McoinExchangeHcoinReq) -public class HandlerMcoinExchangeHcoinReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq exchangeReq = McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq.parseFrom(payload); - - if (session.getPlayer().getCrystals() < exchangeReq.getMcoinCost() && exchangeReq.getMcoinCost() == exchangeReq.getHcoin()) { - session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_UNKNOWN_ERROR_VALUE)); - return; - } - - session.getPlayer().setCrystals(session.getPlayer().getCrystals() - exchangeReq.getMcoinCost()); - session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() + exchangeReq.getHcoin()); - session.getPlayer().save(); - session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.McoinExchangeHcoinReqOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketMcoinExchangeHcoinRsp; + +@Opcodes(PacketOpcodes.McoinExchangeHcoinReq) +public class HandlerMcoinExchangeHcoinReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq exchangeReq = + McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq.parseFrom(payload); + + if (session.getPlayer().getCrystals() < exchangeReq.getMcoinCost() + && exchangeReq.getMcoinCost() == exchangeReq.getHcoin()) { + session.send( + new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_UNKNOWN_ERROR_VALUE)); + return; + } + + session.getPlayer().setCrystals(session.getPlayer().getCrystals() - exchangeReq.getMcoinCost()); + session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() + exchangeReq.getHcoin()); + session.getPlayer().save(); + session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMonsterAIConfigHashNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMonsterAIConfigHashNotify.java index 9bed8c3eb..702df8640 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMonsterAIConfigHashNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMonsterAIConfigHashNotify.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.MonsterAIConfigHashNotify) -public class HandlerMonsterAIConfigHashNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.MonsterAIConfigHashNotify) +public class HandlerMonsterAIConfigHashNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameCreateBeatmapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameCreateBeatmapReq.java index b81a5286a..83f9aba6b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameCreateBeatmapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameCreateBeatmapReq.java @@ -1,66 +1,68 @@ -//package emu.grasscutter.server.packet.recv; -// -//import emu.grasscutter.database.DatabaseHelper; -//import emu.grasscutter.game.activity.musicgame.MusicGameActivityHandler; -//import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; -//import emu.grasscutter.game.activity.musicgame.MusicGamePlayerData; -//import emu.grasscutter.game.props.ActivityType; -//import emu.grasscutter.net.packet.Opcodes; -//import emu.grasscutter.net.packet.PacketHandler; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameCreateBeatmapReqOuterClass; -//import emu.grasscutter.server.game.GameSession; -//import emu.grasscutter.server.packet.send.PacketActivityInfoNotify; -//import emu.grasscutter.server.packet.send.PacketMusicGameCreateBeatmapRsp; -//import emu.grasscutter.utils.Utils; -// -//import java.util.Objects; -// -//@Opcodes(PacketOpcodes.MusicGameCreateBeatmapReq) -//public class HandlerMusicGameCreateBeatmapReq extends PacketHandler { -// -// @Override -// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { -// var req = MusicGameCreateBeatmapReqOuterClass.MusicGameCreateBeatmapReq.parseFrom(payload); -// -// var musicGameBeatmap = MusicGameBeatmap.of() -// .musicId(req.getMusicBriefInfo().getMusicId()) -// .musicNoteCount(req.getMusicBriefInfo().getMusicNoteCount()) -// .savePosition(req.getMusicBriefInfo().getPosition()) -// .maxScore(req.getMusicBriefInfo().getMaxScore()) -// .authorUid(session.getPlayer().getUid()) -// .beatmap(MusicGameBeatmap.parse(req.getMusicRecord().getBeatmapItemListList())) -// .createTime(Utils.getCurrentSeconds()) -// .build(); -// -// musicGameBeatmap.save(); -// -// var playerData = session.getPlayer().getActivityManager().getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); -// if(playerData.isEmpty()){ -// return; -// } -// -// var handler = (MusicGameActivityHandler) playerData.get().getActivityHandler(); -// var musicGamePlayerData = handler.getMusicGamePlayerData(playerData.get()); -// -// var oldBeatmap = musicGamePlayerData.getPersonalCustomBeatmapRecord().values().stream() -// .map(MusicGamePlayerData.CustomBeatmapRecord::getMusicShareId) -// .map(DatabaseHelper::getMusicGameBeatmap) -// .filter(Objects::nonNull) -// .filter(item -> item.getAuthorUid() == session.getPlayer().getUid()) -// .filter(item -> item.getMusicId() == req.getMusicBriefInfo().getMusicId()) -// .filter(item -> item.getSavePosition() == req.getMusicBriefInfo().getPosition()) -// .findFirst(); -// -// // delete old beatmap for player -// // the old beatmap is still in database so that others can still play. -// oldBeatmap.ifPresent(i -> handler.removePersonalBeatmap(playerData.get(), i)); -// -// // link this beatmap to player's personal data -// handler.addPersonalBeatmap(playerData.get(), musicGameBeatmap); -// -// session.send(new PacketActivityInfoNotify(handler.toProto(playerData.get()))); -// session.send(new PacketMusicGameCreateBeatmapRsp(musicGameBeatmap.getMusicShareId(), req.getUnknownEnum1())); -// } -// -//} +// package emu.grasscutter.server.packet.recv; +// +// import emu.grasscutter.database.DatabaseHelper; +// import emu.grasscutter.game.activity.musicgame.MusicGameActivityHandler; +// import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; +// import emu.grasscutter.game.activity.musicgame.MusicGamePlayerData; +// import emu.grasscutter.game.props.ActivityType; +// import emu.grasscutter.net.packet.Opcodes; +// import emu.grasscutter.net.packet.PacketHandler; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameCreateBeatmapReqOuterClass; +// import emu.grasscutter.server.game.GameSession; +// import emu.grasscutter.server.packet.send.PacketActivityInfoNotify; +// import emu.grasscutter.server.packet.send.PacketMusicGameCreateBeatmapRsp; +// import emu.grasscutter.utils.Utils; +// +// import java.util.Objects; +// +// @Opcodes(PacketOpcodes.MusicGameCreateBeatmapReq) +// public class HandlerMusicGameCreateBeatmapReq extends PacketHandler { +// +// @Override +// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { +// var req = MusicGameCreateBeatmapReqOuterClass.MusicGameCreateBeatmapReq.parseFrom(payload); +// +// var musicGameBeatmap = MusicGameBeatmap.of() +// .musicId(req.getMusicBriefInfo().getMusicId()) +// .musicNoteCount(req.getMusicBriefInfo().getMusicNoteCount()) +// .savePosition(req.getMusicBriefInfo().getPosition()) +// .maxScore(req.getMusicBriefInfo().getMaxScore()) +// .authorUid(session.getPlayer().getUid()) +// .beatmap(MusicGameBeatmap.parse(req.getMusicRecord().getBeatmapItemListList())) +// .createTime(Utils.getCurrentSeconds()) +// .build(); +// +// musicGameBeatmap.save(); +// +// var playerData = +// session.getPlayer().getActivityManager().getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); +// if(playerData.isEmpty()){ +// return; +// } +// +// var handler = (MusicGameActivityHandler) playerData.get().getActivityHandler(); +// var musicGamePlayerData = handler.getMusicGamePlayerData(playerData.get()); +// +// var oldBeatmap = musicGamePlayerData.getPersonalCustomBeatmapRecord().values().stream() +// .map(MusicGamePlayerData.CustomBeatmapRecord::getMusicShareId) +// .map(DatabaseHelper::getMusicGameBeatmap) +// .filter(Objects::nonNull) +// .filter(item -> item.getAuthorUid() == session.getPlayer().getUid()) +// .filter(item -> item.getMusicId() == req.getMusicBriefInfo().getMusicId()) +// .filter(item -> item.getSavePosition() == req.getMusicBriefInfo().getPosition()) +// .findFirst(); +// +// // delete old beatmap for player +// // the old beatmap is still in database so that others can still play. +// oldBeatmap.ifPresent(i -> handler.removePersonalBeatmap(playerData.get(), i)); +// +// // link this beatmap to player's personal data +// handler.addPersonalBeatmap(playerData.get(), musicGameBeatmap); +// +// session.send(new PacketActivityInfoNotify(handler.toProto(playerData.get()))); +// session.send(new PacketMusicGameCreateBeatmapRsp(musicGameBeatmap.getMusicShareId(), +// req.getUnknownEnum1())); +// } +// +// } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameGetBeatmapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameGetBeatmapReq.java index aeadd8f3c..77a05e808 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameGetBeatmapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameGetBeatmapReq.java @@ -1,31 +1,31 @@ -//package emu.grasscutter.server.packet.recv; -// -//import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; -//import emu.grasscutter.net.packet.Opcodes; -//import emu.grasscutter.net.packet.PacketHandler; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameGetBeatmapReqOuterClass; -//import emu.grasscutter.server.game.GameSession; -//import emu.grasscutter.server.packet.send.PacketMusicGameGetBeatmapRsp; -// -//@Opcodes(PacketOpcodes.MusicGameGetBeatmapReq) -//public class HandlerMusicGameGetBeatmapReq extends PacketHandler { -// -// @Override -// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { -// var req = MusicGameGetBeatmapReqOuterClass.MusicGameGetBeatmapReq.parseFrom(payload); -// -// var musicGameBeatmap = MusicGameBeatmap.getByShareId(req.getMusicShareId()); -// -// if(musicGameBeatmap == null){ -// return; -// } -// -// session.send(new PacketMusicGameGetBeatmapRsp( -// musicGameBeatmap.toBriefProto().build(), -// musicGameBeatmap.toProto(), -// req -// )); -// } -// -//} +// package emu.grasscutter.server.packet.recv; +// +// import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; +// import emu.grasscutter.net.packet.Opcodes; +// import emu.grasscutter.net.packet.PacketHandler; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameGetBeatmapReqOuterClass; +// import emu.grasscutter.server.game.GameSession; +// import emu.grasscutter.server.packet.send.PacketMusicGameGetBeatmapRsp; +// +// @Opcodes(PacketOpcodes.MusicGameGetBeatmapReq) +// public class HandlerMusicGameGetBeatmapReq extends PacketHandler { +// +// @Override +// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { +// var req = MusicGameGetBeatmapReqOuterClass.MusicGameGetBeatmapReq.parseFrom(payload); +// +// var musicGameBeatmap = MusicGameBeatmap.getByShareId(req.getMusicShareId()); +// +// if(musicGameBeatmap == null){ +// return; +// } +// +// session.send(new PacketMusicGameGetBeatmapRsp( +// musicGameBeatmap.toBriefProto().build(), +// musicGameBeatmap.toProto(), +// req +// )); +// } +// +// } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSearchBeatmapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSearchBeatmapReq.java index 1cfafb2a1..70366e42b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSearchBeatmapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSearchBeatmapReq.java @@ -1,28 +1,29 @@ -//package emu.grasscutter.server.packet.recv; -// -//import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; -//import emu.grasscutter.net.packet.Opcodes; -//import emu.grasscutter.net.packet.PacketHandler; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameSearchBeatmapReqOuterClass; -//import emu.grasscutter.server.game.GameSession; -//import emu.grasscutter.server.packet.send.PacketMusicGameSearchBeatmapRsp; -// -//@Opcodes(PacketOpcodes.MusicGameSearchBeatmapReq) -//public class HandlerMusicGameSearchBeatmapReq extends PacketHandler { -// -// @Override -// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { -// var req = MusicGameSearchBeatmapReqOuterClass.MusicGameSearchBeatmapReq.parseFrom(payload); -// -// var musicGameBeatmap = MusicGameBeatmap.getByShareId(req.getMusicShareId()); -// -// if(musicGameBeatmap == null){ -// session.send(new PacketMusicGameSearchBeatmapRsp(11153, req.getUnknownEnum1())); -// return; -// } -// -// session.send(new PacketMusicGameSearchBeatmapRsp(musicGameBeatmap.toBriefProto().build(), req.getUnknownEnum1())); -// } -// -//} +// package emu.grasscutter.server.packet.recv; +// +// import emu.grasscutter.game.activity.musicgame.MusicGameBeatmap; +// import emu.grasscutter.net.packet.Opcodes; +// import emu.grasscutter.net.packet.PacketHandler; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameSearchBeatmapReqOuterClass; +// import emu.grasscutter.server.game.GameSession; +// import emu.grasscutter.server.packet.send.PacketMusicGameSearchBeatmapRsp; +// +// @Opcodes(PacketOpcodes.MusicGameSearchBeatmapReq) +// public class HandlerMusicGameSearchBeatmapReq extends PacketHandler { +// +// @Override +// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { +// var req = MusicGameSearchBeatmapReqOuterClass.MusicGameSearchBeatmapReq.parseFrom(payload); +// +// var musicGameBeatmap = MusicGameBeatmap.getByShareId(req.getMusicShareId()); +// +// if(musicGameBeatmap == null){ +// session.send(new PacketMusicGameSearchBeatmapRsp(11153, req.getUnknownEnum1())); +// return; +// } +// +// session.send(new PacketMusicGameSearchBeatmapRsp(musicGameBeatmap.toBriefProto().build(), +// req.getUnknownEnum1())); +// } +// +// } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSettleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSettleReq.java index 1514d27e6..460d6dfbe 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSettleReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameSettleReq.java @@ -1,59 +1,67 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.activity.musicgame.MusicGameActivityHandler; -import emu.grasscutter.game.activity.musicgame.MusicGamePlayerData; -import emu.grasscutter.game.props.ActivityType; -import emu.grasscutter.game.props.WatcherTriggerType; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MusicGameSettleReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketActivityInfoNotify; -import emu.grasscutter.server.packet.send.PacketMusicGameSettleRsp; - -@Opcodes(PacketOpcodes.MusicGameSettleReq) -public class HandlerMusicGameSettleReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = MusicGameSettleReqOuterClass.MusicGameSettleReq.parseFrom(payload); - - var playerData = session.getPlayer().getActivityManager().getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); - if (playerData.isEmpty()) { - return; - } - var handler = (MusicGameActivityHandler) playerData.get().getActivityHandler(); - boolean isNewRecord = false; - // check if custom beatmap - - if (req.getUgcGuid() == 0) { - session.getPlayer().getActivityManager().triggerWatcher( - WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE, - String.valueOf(req.getMusicBasicId()), - String.valueOf(req.getScore()) - ); - - isNewRecord = handler.setMusicGameRecord(playerData.get(), - MusicGamePlayerData.MusicGameRecord.of() - .musicId(req.getMusicBasicId()) - .maxCombo(req.getMaxCombo()) - .maxScore(req.getScore()) - .build()); - - // update activity info - session.send(new PacketActivityInfoNotify(handler.toProto(playerData.get()))); - } else { - handler.setMusicGameCustomBeatmapRecord(playerData.get(), - MusicGamePlayerData.CustomBeatmapRecord.of() - .musicShareId(req.getUgcGuid()) - .score(req.getMaxCombo()) -// .settle(req.getSuccess()) - .build()); - } - - - session.send(new PacketMusicGameSettleRsp(req.getMusicBasicId(), req.getUgcGuid(), isNewRecord)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.activity.musicgame.MusicGameActivityHandler; +import emu.grasscutter.game.activity.musicgame.MusicGamePlayerData; +import emu.grasscutter.game.props.ActivityType; +import emu.grasscutter.game.props.WatcherTriggerType; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MusicGameSettleReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketActivityInfoNotify; +import emu.grasscutter.server.packet.send.PacketMusicGameSettleRsp; + +@Opcodes(PacketOpcodes.MusicGameSettleReq) +public class HandlerMusicGameSettleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = MusicGameSettleReqOuterClass.MusicGameSettleReq.parseFrom(payload); + + var playerData = + session + .getPlayer() + .getActivityManager() + .getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); + if (playerData.isEmpty()) { + return; + } + var handler = (MusicGameActivityHandler) playerData.get().getActivityHandler(); + boolean isNewRecord = false; + // check if custom beatmap + + if (req.getUgcGuid() == 0) { + session + .getPlayer() + .getActivityManager() + .triggerWatcher( + WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE, + String.valueOf(req.getMusicBasicId()), + String.valueOf(req.getScore())); + + isNewRecord = + handler.setMusicGameRecord( + playerData.get(), + MusicGamePlayerData.MusicGameRecord.of() + .musicId(req.getMusicBasicId()) + .maxCombo(req.getMaxCombo()) + .maxScore(req.getScore()) + .build()); + + // update activity info + session.send(new PacketActivityInfoNotify(handler.toProto(playerData.get()))); + } else { + handler.setMusicGameCustomBeatmapRecord( + playerData.get(), + MusicGamePlayerData.CustomBeatmapRecord.of() + .musicShareId(req.getUgcGuid()) + .score(req.getMaxCombo()) + // .settle(req.getSuccess()) + .build()); + } + + session.send( + new PacketMusicGameSettleRsp(req.getMusicBasicId(), req.getUgcGuid(), isNewRecord)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartReq.java index 84cbb60e2..6a800d267 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartReq.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MusicGameStartReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketMusicGameStartRsp; - -@Opcodes(PacketOpcodes.MusicGameStartReq) -public class HandlerMusicGameStartReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = MusicGameStartReqOuterClass.MusicGameStartReq.parseFrom(payload); - - session.send(new PacketMusicGameStartRsp(req.getMusicBasicId(), req.getUgcGuid())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MusicGameStartReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketMusicGameStartRsp; + +@Opcodes(PacketOpcodes.MusicGameStartReq) +public class HandlerMusicGameStartReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = MusicGameStartReqOuterClass.MusicGameStartReq.parseFrom(payload); + + session.send(new PacketMusicGameStartRsp(req.getMusicBasicId(), req.getUgcGuid())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartToPlayOthersBeatmapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartToPlayOthersBeatmapReq.java index 389aabce7..d003307b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartToPlayOthersBeatmapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameStartToPlayOthersBeatmapReq.java @@ -1,20 +1,21 @@ -//package emu.grasscutter.server.packet.recv; -// -//import emu.grasscutter.net.packet.Opcodes; -//import emu.grasscutter.net.packet.PacketHandler; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameStartToPlayOthersBeatmapReqOuterClass; -//import emu.grasscutter.server.game.GameSession; -//import emu.grasscutter.server.packet.send.PacketMusicGameStartToPlayOthersBeatmapRsp; -// -//@Opcodes(PacketOpcodes.MusicGameStartToPlayOthersBeatmapReq) -//public class HandlerMusicGameStartToPlayOthersBeatmapReq extends PacketHandler { -// -// @Override -// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { -// var req = MusicGameStartToPlayOthersBeatmapReqOuterClass.MusicGameStartToPlayOthersBeatmapReq.parseFrom(payload); -// -// session.send(new PacketMusicGameStartToPlayOthersBeatmapRsp(req.getUnknownEnum1())); -// } -// -//} +// package emu.grasscutter.server.packet.recv; +// +// import emu.grasscutter.net.packet.Opcodes; +// import emu.grasscutter.net.packet.PacketHandler; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameStartToPlayOthersBeatmapReqOuterClass; +// import emu.grasscutter.server.game.GameSession; +// import emu.grasscutter.server.packet.send.PacketMusicGameStartToPlayOthersBeatmapRsp; +// +// @Opcodes(PacketOpcodes.MusicGameStartToPlayOthersBeatmapReq) +// public class HandlerMusicGameStartToPlayOthersBeatmapReq extends PacketHandler { +// +// @Override +// public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { +// var req = +// MusicGameStartToPlayOthersBeatmapReqOuterClass.MusicGameStartToPlayOthersBeatmapReq.parseFrom(payload); +// +// session.send(new PacketMusicGameStartToPlayOthersBeatmapRsp(req.getUnknownEnum1())); +// } +// +// } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java index 29e833366..a95cd8c14 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java @@ -1,52 +1,67 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.MainQuestData; -import emu.grasscutter.data.binout.MainQuestData.TalkData; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketNpcTalkRsp; - -@Opcodes(PacketOpcodes.NpcTalkReq) -public class HandlerNpcTalkReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - NpcTalkReq req = NpcTalkReq.parseFrom(payload); - - //Check if mainQuest exists - //remove last 2 digits to get a mainQuestId - int talkId = req.getTalkId(); - int mainQuestId = talkId / 100; - MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(mainQuestId); - - if (mainQuestData != null) { - // This talk is associated with a quest. Handle it. - // If the quest has no talk data defined on it, create one. - TalkData talkForQuest = new TalkData(talkId, ""); - if (mainQuestData.getTalks() != null) { - var talks = mainQuestData.getTalks().stream().filter(p -> p.getId() == talkId).toList(); - - if (talks.size() > 0) { - talkForQuest = talks.get(0); - } - } - - // Add to the list of done talks for this quest. - var mainQuest = session.getPlayer().getQuestManager().getMainQuestById(mainQuestId); - if (mainQuest != null) { - session.getPlayer().getQuestManager().getMainQuestById(mainQuestId).getTalks().put(talkId, talkForQuest); - } - - // Fire quest triggers. - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK, String.valueOf(req.getTalkId()), 0, 0); - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId(), 0); - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_FINISH_PLOT, req.getTalkId(), 0); - } - - session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.binout.MainQuestData.TalkData; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketNpcTalkRsp; + +@Opcodes(PacketOpcodes.NpcTalkReq) +public class HandlerNpcTalkReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + NpcTalkReq req = NpcTalkReq.parseFrom(payload); + + // Check if mainQuest exists + // remove last 2 digits to get a mainQuestId + int talkId = req.getTalkId(); + int mainQuestId = talkId / 100; + MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(mainQuestId); + + if (mainQuestData != null) { + // This talk is associated with a quest. Handle it. + // If the quest has no talk data defined on it, create one. + TalkData talkForQuest = new TalkData(talkId, ""); + if (mainQuestData.getTalks() != null) { + var talks = mainQuestData.getTalks().stream().filter(p -> p.getId() == talkId).toList(); + + if (talks.size() > 0) { + talkForQuest = talks.get(0); + } + } + + // Add to the list of done talks for this quest. + var mainQuest = session.getPlayer().getQuestManager().getMainQuestById(mainQuestId); + if (mainQuest != null) { + session + .getPlayer() + .getQuestManager() + .getMainQuestById(mainQuestId) + .getTalks() + .put(talkId, talkForQuest); + } + + // Fire quest triggers. + session + .getPlayer() + .getQuestManager() + .triggerEvent( + QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK, String.valueOf(req.getTalkId()), 0, 0); + session + .getPlayer() + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId(), 0); + session + .getPlayer() + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_FINISH_PLOT, req.getTalkId(), 0); + } + + session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerObstacleModifyNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerObstacleModifyNotify.java index 586e4c664..74dbbf729 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerObstacleModifyNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerObstacleModifyNotify.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ObstacleModifyNotify) -public class HandlerObstacleModifyNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ObstacleModifyNotify) +public class HandlerObstacleModifyNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPathfindingEnterSceneReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPathfindingEnterSceneReq.java index ce0e9039f..c0d59e708 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPathfindingEnterSceneReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPathfindingEnterSceneReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPathfindingEnterSceneRsp; - -@Opcodes(PacketOpcodes.PathfindingEnterSceneReq) -public class HandlerPathfindingEnterSceneReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PacketHead head = PacketHead.parseFrom(header); - session.send(new PacketPathfindingEnterSceneRsp(head.getClientSequenceId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPathfindingEnterSceneRsp; + +@Opcodes(PacketOpcodes.PathfindingEnterSceneReq) +public class HandlerPathfindingEnterSceneReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PacketHead head = PacketHead.parseFrom(header); + session.send(new PacketPathfindingEnterSceneRsp(head.getClientSequenceId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java index c8faa96d2..2ffdd93bd 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java @@ -1,17 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp; - -@Opcodes(PacketOpcodes.PersonalLineAllDataReq) -public class HandlerPersonalLineAllDataReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketPersonalLineAllDataRsp(session.getPlayer().getQuestManager().getMainQuests().values())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp; + +@Opcodes(PacketOpcodes.PersonalLineAllDataReq) +public class HandlerPersonalLineAllDataReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send( + new PacketPersonalLineAllDataRsp( + session.getPlayer().getQuestManager().getMainQuests().values())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java index 75425ad53..a46ced9cd 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java @@ -1,35 +1,34 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ScenePointEntry; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PersonalSceneJumpReqOuterClass.PersonalSceneJumpReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPersonalSceneJumpRsp; -import emu.grasscutter.utils.Position; - - -@Opcodes(PacketOpcodes.PersonalSceneJumpReq) -public class HandlerPersonalSceneJumpReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PersonalSceneJumpReq req = PersonalSceneJumpReq.parseFrom(payload); - var player = session.getPlayer(); - - // get the scene point - ScenePointEntry scenePointEntry = GameData.getScenePointEntryById(player.getSceneId(), req.getPointId()); - - if (scenePointEntry != null) { - Position pos = scenePointEntry.getPointData().getTranPos().clone(); // This might not need cloning - int sceneId = scenePointEntry.getPointData().getTranSceneId(); - - player.getWorld().transferPlayerToScene(player, sceneId, pos); - session.send(new PacketPersonalSceneJumpRsp(sceneId, pos)); - } - - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PersonalSceneJumpReqOuterClass.PersonalSceneJumpReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPersonalSceneJumpRsp; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.PersonalSceneJumpReq) +public class HandlerPersonalSceneJumpReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PersonalSceneJumpReq req = PersonalSceneJumpReq.parseFrom(payload); + var player = session.getPlayer(); + + // get the scene point + ScenePointEntry scenePointEntry = + GameData.getScenePointEntryById(player.getSceneId(), req.getPointId()); + + if (scenePointEntry != null) { + Position pos = + scenePointEntry.getPointData().getTranPos().clone(); // This might not need cloning + int sceneId = scenePointEntry.getPointData().getTranSceneId(); + + player.getWorld().transferPlayerToScene(player, sceneId, pos); + session.send(new PacketPersonalSceneJumpRsp(sceneId, pos)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPingReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPingReq.java index d59215cf7..6fbb63124 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPingReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPingReq.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.net.proto.PingReqOuterClass.PingReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPingRsp; - -@Opcodes(PacketOpcodes.PingReq) -public class HandlerPingReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PacketHead head = PacketHead.parseFrom(header); - PingReq ping = PingReq.parseFrom(payload); - - session.updateLastPingTime(ping.getClientTime()); - - session.send(new PacketPingRsp(head.getClientSequenceId(), ping.getClientTime())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.net.proto.PingReqOuterClass.PingReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPingRsp; + +@Opcodes(PacketOpcodes.PingReq) +public class HandlerPingReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PacketHead head = PacketHead.parseFrom(header); + PingReq ping = PingReq.parseFrom(payload); + + session.updateLastPingTime(ping.getClientTime()); + + session.send(new PacketPingRsp(head.getClientSequenceId(), ping.getClientTime())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpReq.java index da634f06e..b5f74e50a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpReq.java @@ -1,21 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpReqOuterClass.PlayerApplyEnterMpReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpRsp; - -@Opcodes(PacketOpcodes.PlayerApplyEnterMpReq) -public class HandlerPlayerApplyEnterMpReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PlayerApplyEnterMpReq req = PlayerApplyEnterMpReq.parseFrom(payload); - - session.getServer().getMultiplayerSystem().applyEnterMp(session.getPlayer(), req.getTargetUid()); - session.send(new PacketPlayerApplyEnterMpRsp(req.getTargetUid())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpReqOuterClass.PlayerApplyEnterMpReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpRsp; + +@Opcodes(PacketOpcodes.PlayerApplyEnterMpReq) +public class HandlerPlayerApplyEnterMpReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PlayerApplyEnterMpReq req = PlayerApplyEnterMpReq.parseFrom(payload); + + session + .getServer() + .getMultiplayerSystem() + .applyEnterMp(session.getPlayer(), req.getTargetUid()); + session.send(new PacketPlayerApplyEnterMpRsp(req.getTargetUid())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpResultReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpResultReq.java index fe5492261..8750e4b6e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpResultReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerApplyEnterMpResultReq.java @@ -1,21 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpResultReqOuterClass.PlayerApplyEnterMpResultReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultRsp; - -@Opcodes(PacketOpcodes.PlayerApplyEnterMpResultReq) -public class HandlerPlayerApplyEnterMpResultReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PlayerApplyEnterMpResultReq req = PlayerApplyEnterMpResultReq.parseFrom(payload); - - session.getServer().getMultiplayerSystem().applyEnterMpReply(session.getPlayer(), req.getApplyUid(), req.getIsAgreed()); - session.send(new PacketPlayerApplyEnterMpResultRsp(req.getApplyUid(), req.getIsAgreed())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpResultReqOuterClass.PlayerApplyEnterMpResultReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultRsp; + +@Opcodes(PacketOpcodes.PlayerApplyEnterMpResultReq) +public class HandlerPlayerApplyEnterMpResultReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PlayerApplyEnterMpResultReq req = PlayerApplyEnterMpResultReq.parseFrom(payload); + + session + .getServer() + .getMultiplayerSystem() + .applyEnterMpReply(session.getPlayer(), req.getApplyUid(), req.getIsAgreed()); + session.send(new PacketPlayerApplyEnterMpResultRsp(req.getApplyUid(), req.getIsAgreed())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerChatReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerChatReq.java index 9966cb961..fd17f7996 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerChatReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerChatReq.java @@ -1,28 +1,33 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.net.proto.PlayerChatReqOuterClass.PlayerChatReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerChatRsp; - -@Opcodes(PacketOpcodes.PlayerChatReq) -public class HandlerPlayerChatReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PlayerChatReq req = PlayerChatReq.parseFrom(payload); - ChatInfo.ContentCase content = req.getChatInfo().getContentCase(); - - if (content == ChatInfo.ContentCase.TEXT) { - session.getServer().getChatSystem().sendTeamMessage(session.getPlayer(), req.getChannelId(), req.getChatInfo().getText()); - } else if (content == ChatInfo.ContentCase.ICON) { - session.getServer().getChatSystem().sendTeamMessage(session.getPlayer(), req.getChannelId(), req.getChatInfo().getIcon()); - } - - session.send(new PacketPlayerChatRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.net.proto.PlayerChatReqOuterClass.PlayerChatReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerChatRsp; + +@Opcodes(PacketOpcodes.PlayerChatReq) +public class HandlerPlayerChatReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PlayerChatReq req = PlayerChatReq.parseFrom(payload); + ChatInfo.ContentCase content = req.getChatInfo().getContentCase(); + + if (content == ChatInfo.ContentCase.TEXT) { + session + .getServer() + .getChatSystem() + .sendTeamMessage(session.getPlayer(), req.getChannelId(), req.getChatInfo().getText()); + } else if (content == ChatInfo.ContentCase.ICON) { + session + .getServer() + .getChatSystem() + .sendTeamMessage(session.getPlayer(), req.getChannelId(), req.getChatInfo().getIcon()); + } + + session.send(new PacketPlayerChatRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCompoundMaterialReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCompoundMaterialReq.java index b7de57944..14441a0d5 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCompoundMaterialReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCompoundMaterialReq.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerCompoundMaterialReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerCompoundMaterialReq) -public class HandlerPlayerCompoundMaterialReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = PlayerCompoundMaterialReqOuterClass.PlayerCompoundMaterialReq.parseFrom(payload); - session.getPlayer().getCookingCompoundManager().handlePlayerCompoundMaterialReq(req); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerCompoundMaterialReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerCompoundMaterialReq) +public class HandlerPlayerCompoundMaterialReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = PlayerCompoundMaterialReqOuterClass.PlayerCompoundMaterialReq.parseFrom(payload); + session.getPlayer().getCookingCompoundManager().handlePlayerCompoundMaterialReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookArgsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookArgsReq.java index c55dca3be..5cced6396 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookArgsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookArgsReq.java @@ -1,16 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerCookArgsReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerCookArgsReq) -public class HandlerPlayerCookArgsReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PlayerCookArgsReqOuterClass.PlayerCookArgsReq req = PlayerCookArgsReqOuterClass.PlayerCookArgsReq.parseFrom(payload); - session.getPlayer().getCookingManager().handleCookArgsReq(req); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerCookArgsReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerCookArgsReq) +public class HandlerPlayerCookArgsReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PlayerCookArgsReqOuterClass.PlayerCookArgsReq req = + PlayerCookArgsReqOuterClass.PlayerCookArgsReq.parseFrom(payload); + session.getPlayer().getCookingManager().handleCookArgsReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookReq.java index 462083508..ac92bbdb2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerCookReq.java @@ -1,16 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerCookReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerCookReq) -public class HandlerPlayerCookReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PlayerCookReqOuterClass.PlayerCookReq req = PlayerCookReqOuterClass.PlayerCookReq.parseFrom(payload); - session.getPlayer().getCookingManager().handlePlayerCookReq(req); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerCookReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerCookReq) +public class HandlerPlayerCookReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PlayerCookReqOuterClass.PlayerCookReq req = + PlayerCookReqOuterClass.PlayerCookReq.parseFrom(payload); + session.getPlayer().getCookingManager().handlePlayerCookReq(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerEnterDungeonReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerEnterDungeonReq.java index ae5541883..427451628 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerEnterDungeonReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerEnterDungeonReq.java @@ -1,20 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerEnterDungeonReqOuterClass.PlayerEnterDungeonReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerEnterDungeonReq) -public class HandlerPlayerEnterDungeonReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - PlayerEnterDungeonReq req = PlayerEnterDungeonReq.parseFrom(payload); - - session.getServer().getDungeonSystem().enterDungeon(session.getPlayer(), req.getPointId(), req.getDungeonId()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerEnterDungeonReqOuterClass.PlayerEnterDungeonReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerEnterDungeonReq) +public class HandlerPlayerEnterDungeonReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + PlayerEnterDungeonReq req = PlayerEnterDungeonReq.parseFrom(payload); + + session + .getServer() + .getDungeonSystem() + .enterDungeon(session.getPlayer(), req.getPointId(), req.getDungeonId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerForceExitReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerForceExitReq.java index 6da2ff68a..3a53b0a8a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerForceExitReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerForceExitReq.java @@ -1,28 +1,28 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerForceExitReq) -public class HandlerPlayerForceExitReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Client should auto disconnect right now - session.send(new BasePacket(PacketOpcodes.PlayerForceExitRsp)); - new Thread() { - @Override - public void run() { - try { - Thread.sleep(1000);// disconnect after 1 seconds - } catch (InterruptedException e) { - e.printStackTrace(); - } - session.close(); - super.run(); - } - }.start(); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerForceExitReq) +public class HandlerPlayerForceExitReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Client should auto disconnect right now + session.send(new BasePacket(PacketOpcodes.PlayerForceExitRsp)); + new Thread() { + @Override + public void run() { + try { + Thread.sleep(1000); // disconnect after 1 seconds + } catch (InterruptedException e) { + e.printStackTrace(); + } + session.close(); + super.run(); + } + }.start(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerGetForceQuitBanInfoReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerGetForceQuitBanInfoReq.java index e35265560..1931ec03a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerGetForceQuitBanInfoReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerGetForceQuitBanInfoReq.java @@ -1,25 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerGetForceQuitBanInfoRsp; - -@Opcodes(PacketOpcodes.PlayerGetForceQuitBanInfoReq) -public class HandlerPlayerGetForceQuitBanInfoReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - - if (session.getServer().getMultiplayerSystem().leaveCoop(session.getPlayer())) { - // Success - session.send(new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)); - } else { - // Fail - session.send(new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerGetForceQuitBanInfoRsp; + +@Opcodes(PacketOpcodes.PlayerGetForceQuitBanInfoReq) +public class HandlerPlayerGetForceQuitBanInfoReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + + if (session.getServer().getMultiplayerSystem().leaveCoop(session.getPlayer())) { + // Success + session.send( + new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)); + } else { + // Fail + session.send( + new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java index 873531a94..f5d90172b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java @@ -1,52 +1,51 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerLoginReqOuterClass.PlayerLoginReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.game.GameSession.SessionState; -import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp; -import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardReq; - -@Opcodes(PacketOpcodes.PlayerLoginReq) // Sends initial data packets -public class HandlerPlayerLoginReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Check - if (session.getAccount() == null) { - session.close(); - return; - } - - // Parse request - PlayerLoginReq req = PlayerLoginReq.parseFrom(payload); - - // Authenticate session - if (!req.getToken().equals(session.getAccount().getToken())) { - session.close(); - return; - } - - // Load character from db - Player player = session.getPlayer(); - - // Show opening cutscene if player has no avatars - if (player.getAvatars().getAvatarCount() == 0) { - // Pick character - session.setState(SessionState.PICKING_CHARACTER); - session.send(new BasePacket(PacketOpcodes.DoSetPlayerBornDataNotify)); - } else { - // Login done - session.getPlayer().onLogin(); - } - - // Final packet to tell client logging in is done - session.send(new PacketPlayerLoginRsp(session)); - session.send(new PacketTakeAchievementRewardReq(session)); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerLoginReqOuterClass.PlayerLoginReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.game.GameSession.SessionState; +import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp; +import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardReq; + +@Opcodes(PacketOpcodes.PlayerLoginReq) // Sends initial data packets +public class HandlerPlayerLoginReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Check + if (session.getAccount() == null) { + session.close(); + return; + } + + // Parse request + PlayerLoginReq req = PlayerLoginReq.parseFrom(payload); + + // Authenticate session + if (!req.getToken().equals(session.getAccount().getToken())) { + session.close(); + return; + } + + // Load character from db + Player player = session.getPlayer(); + + // Show opening cutscene if player has no avatars + if (player.getAvatars().getAvatarCount() == 0) { + // Pick character + session.setState(SessionState.PICKING_CHARACTER); + session.send(new BasePacket(PacketOpcodes.DoSetPlayerBornDataNotify)); + } else { + // Login done + session.getPlayer().onLogin(); + } + + // Final packet to tell client logging in is done + session.send(new PacketPlayerLoginRsp(session)); + session.send(new PacketTakeAchievementRewardReq(session)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerQuitDungeonReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerQuitDungeonReq.java index 5a3cc8a4b..3337c4d25 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerQuitDungeonReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerQuitDungeonReq.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PlayerQuitDungeonReq) -public class HandlerPlayerQuitDungeonReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getServer().getDungeonSystem().exitDungeon(session.getPlayer()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PlayerQuitDungeonReq) +public class HandlerPlayerQuitDungeonReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getServer().getDungeonSystem().exitDungeon(session.getPlayer()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerSetPauseReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerSetPauseReq.java index 3abbc0824..4a018f134 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerSetPauseReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerSetPauseReq.java @@ -1,28 +1,27 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; -import emu.grasscutter.net.proto.PlayerSetPauseReqOuterClass.PlayerSetPauseReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlayerSetPauseRsp; -import emu.grasscutter.server.packet.send.PacketPlayerTimeNotify; -import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; - -@Opcodes(PacketOpcodes.PlayerSetPauseReq) -public class HandlerPlayerSetPauseReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PacketHead head = PacketHead.parseFrom(header); - PlayerSetPauseReq req = PlayerSetPauseReq.parseFrom(payload); - - session.send(new PacketPlayerSetPauseRsp(head.getClientSequenceId())); - session.getPlayer().setPaused(req.getIsPaused()); - - session.send(new PacketPlayerTimeNotify(session.getPlayer())); - session.send(new PacketSceneTimeNotify(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; +import emu.grasscutter.net.proto.PlayerSetPauseReqOuterClass.PlayerSetPauseReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlayerSetPauseRsp; +import emu.grasscutter.server.packet.send.PacketPlayerTimeNotify; +import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; + +@Opcodes(PacketOpcodes.PlayerSetPauseReq) +public class HandlerPlayerSetPauseReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PacketHead head = PacketHead.parseFrom(header); + PlayerSetPauseReq req = PlayerSetPauseReq.parseFrom(payload); + + session.send(new PacketPlayerSetPauseRsp(head.getClientSequenceId())); + session.getPlayer().setPaused(req.getIsPaused()); + + session.send(new PacketPlayerTimeNotify(session.getPlayer())); + session.send(new PacketSceneTimeNotify(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPostEnterSceneReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPostEnterSceneReq.java index b3307718f..e6a1618e7 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPostEnterSceneReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPostEnterSceneReq.java @@ -1,23 +1,25 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.props.SceneType; -import emu.grasscutter.game.quest.enums.QuestTrigger; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPostEnterSceneRsp; - -@Opcodes(PacketOpcodes.PostEnterSceneReq) -public class HandlerPostEnterSceneReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - if (session.getPlayer().getScene().getSceneType() == SceneType.SCENE_ROOM) { - session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_ROOM, session.getPlayer().getSceneId(), 0); - } - - session.send(new PacketPostEnterSceneRsp(session.getPlayer())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPostEnterSceneRsp; + +@Opcodes(PacketOpcodes.PostEnterSceneReq) +public class HandlerPostEnterSceneReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + if (session.getPlayer().getScene().getSceneType() == SceneType.SCENE_ROOM) { + session + .getPlayer() + .getQuestManager() + .triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_ROOM, session.getPlayer().getSceneId(), 0); + } + + session.send(new PacketPostEnterSceneRsp(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPrivateChatReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPrivateChatReq.java index 01142bf6a..47ab5ee09 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPrivateChatReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPrivateChatReq.java @@ -1,24 +1,29 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PrivateChatReqOuterClass.PrivateChatReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PrivateChatReq) -public class HandlerPrivateChatReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PrivateChatReq req = PrivateChatReq.parseFrom(payload); - PrivateChatReq.ContentCase content = req.getContentCase(); - - if (content == PrivateChatReq.ContentCase.TEXT) { - session.getServer().getChatSystem().sendPrivateMessage(session.getPlayer(), req.getTargetUid(), req.getText()); - } else if (content == PrivateChatReq.ContentCase.ICON) { - session.getServer().getChatSystem().sendPrivateMessage(session.getPlayer(), req.getTargetUid(), req.getIcon()); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PrivateChatReqOuterClass.PrivateChatReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PrivateChatReq) +public class HandlerPrivateChatReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PrivateChatReq req = PrivateChatReq.parseFrom(payload); + PrivateChatReq.ContentCase content = req.getContentCase(); + + if (content == PrivateChatReq.ContentCase.TEXT) { + session + .getServer() + .getChatSystem() + .sendPrivateMessage(session.getPlayer(), req.getTargetUid(), req.getText()); + } else if (content == PrivateChatReq.ContentCase.ICON) { + session + .getServer() + .getChatSystem() + .sendPrivateMessage(session.getPlayer(), req.getTargetUid(), req.getIcon()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullPrivateChatReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullPrivateChatReq.java index eb489d3a2..75282bb96 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullPrivateChatReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullPrivateChatReq.java @@ -1,21 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PullPrivateChatReqOuterClass.PullPrivateChatReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PullPrivateChatReq) -public class HandlerPullPrivateChatReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - PullPrivateChatReq req = PullPrivateChatReq.parseFrom(payload); - - session.getServer().getChatSystem().handlePullPrivateChatReq(session.getPlayer(), req.getTargetUid()); - - // session.send(new PacketPullPrivateChatRsp(req.getTargetUid())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PullPrivateChatReqOuterClass.PullPrivateChatReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PullPrivateChatReq) +public class HandlerPullPrivateChatReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PullPrivateChatReq req = PullPrivateChatReq.parseFrom(payload); + + session + .getServer() + .getChatSystem() + .handlePullPrivateChatReq(session.getPlayer(), req.getTargetUid()); + + // session.send(new PacketPullPrivateChatRsp(req.getTargetUid())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullRecentChatReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullRecentChatReq.java index 8e7ee378b..1af88edd1 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullRecentChatReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPullRecentChatReq.java @@ -1,14 +1,14 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.PullRecentChatReq) -public class HandlerPullRecentChatReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getServer().getChatSystem().handlePullRecentChatReq(session.getPlayer()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.PullRecentChatReq) +public class HandlerPullRecentChatReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getServer().getChatSystem().handlePullRecentChatReq(session.getPlayer()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java index 991b7a87a..f8035ac9e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java @@ -1,19 +1,19 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumReqOuterClass.QueryCodexMonsterBeKilledNumReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketQueryCodexMonsterBeKilledNumRsp; - -@Opcodes(PacketOpcodes.QueryCodexMonsterBeKilledNumReq) -public class HandlerQueryCodexMonsterBeKilledNumReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - QueryCodexMonsterBeKilledNumReq req = QueryCodexMonsterBeKilledNumReq.parseFrom(payload); - session.send(new PacketQueryCodexMonsterBeKilledNumRsp(session.getPlayer(), req.getCodexIdListList())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumReqOuterClass.QueryCodexMonsterBeKilledNumReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketQueryCodexMonsterBeKilledNumRsp; + +@Opcodes(PacketOpcodes.QueryCodexMonsterBeKilledNumReq) +public class HandlerQueryCodexMonsterBeKilledNumReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + QueryCodexMonsterBeKilledNumReq req = QueryCodexMonsterBeKilledNumReq.parseFrom(payload); + session.send( + new PacketQueryCodexMonsterBeKilledNumRsp(session.getPlayer(), req.getCodexIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryPathReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryPathReq.java index 0cc8bd2c1..b7ebf298c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryPathReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryPathReq.java @@ -1,26 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QueryPathReqOuterClass.QueryPathReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketQueryPathRsp; - -@Opcodes(PacketOpcodes.QueryPathReq) -public class HandlerQueryPathReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = QueryPathReq.parseFrom(payload); - - /** - * It is not the actual work - */ - - if (req.getDestinationPosList().size() > 0) { - session.send(new PacketQueryPathRsp(req)); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QueryPathReqOuterClass.QueryPathReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketQueryPathRsp; + +@Opcodes(PacketOpcodes.QueryPathReq) +public class HandlerQueryPathReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = QueryPathReq.parseFrom(payload); + + /** It is not the actual work */ + if (req.getDestinationPosList().size() > 0) { + session.send(new PacketQueryPathRsp(req)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuestUpdateQuestVarReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuestUpdateQuestVarReq.java index baa23810a..f3cc1068c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuestUpdateQuestVarReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuestUpdateQuestVarReq.java @@ -1,45 +1,45 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuestUpdateQuestVarReqOuterClass; -import emu.grasscutter.net.proto.QuestVarOpOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketQuestUpdateQuestVarRsp; - -import java.util.List; - -@Opcodes(PacketOpcodes.QuestUpdateQuestVarReq) -public class HandlerQuestUpdateQuestVarReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - //Client sends packets. One with the value, and one with the index and the new value to set/inc/dec - var req = QuestUpdateQuestVarReqOuterClass.QuestUpdateQuestVarReq.parseFrom(payload); - GameMainQuest mainQuest = session.getPlayer().getQuestManager().getMainQuestById(req.getQuestId() / 100); - List questVars = req.getQuestVarOpListList(); - if (mainQuest.getQuestVarsUpdate().size() == 0) { - for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) { - mainQuest.getQuestVarsUpdate().add(questVar.getValue()); - } - } else { - for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) { - if (questVar.getIsAdd()) { - if (questVar.getValue() >= 0) { - mainQuest.incQuestVar(questVar.getIndex(), questVar.getValue()); - } else { - mainQuest.decQuestVar(questVar.getIndex(), questVar.getValue()); - } - } else { - mainQuest.setQuestVar(questVar.getIndex(), mainQuest.getQuestVarsUpdate().get(0)); - } - //remove the first element from the update list - mainQuest.getQuestVarsUpdate().remove(0); - } - } - session.send(new PacketQuestUpdateQuestVarRsp(req.getQuestId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestUpdateQuestVarReqOuterClass; +import emu.grasscutter.net.proto.QuestVarOpOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketQuestUpdateQuestVarRsp; +import java.util.List; + +@Opcodes(PacketOpcodes.QuestUpdateQuestVarReq) +public class HandlerQuestUpdateQuestVarReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Client sends packets. One with the value, and one with the index and the new value to + // set/inc/dec + var req = QuestUpdateQuestVarReqOuterClass.QuestUpdateQuestVarReq.parseFrom(payload); + GameMainQuest mainQuest = + session.getPlayer().getQuestManager().getMainQuestById(req.getQuestId() / 100); + List questVars = req.getQuestVarOpListList(); + if (mainQuest.getQuestVarsUpdate().size() == 0) { + for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) { + mainQuest.getQuestVarsUpdate().add(questVar.getValue()); + } + } else { + for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) { + if (questVar.getIsAdd()) { + if (questVar.getValue() >= 0) { + mainQuest.incQuestVar(questVar.getIndex(), questVar.getValue()); + } else { + mainQuest.decQuestVar(questVar.getIndex(), questVar.getValue()); + } + } else { + mainQuest.setQuestVar(questVar.getIndex(), mainQuest.getQuestVarsUpdate().get(0)); + } + // remove the first element from the update list + mainQuest.getQuestVarsUpdate().remove(0); + } + } + session.send(new PacketQuestUpdateQuestVarRsp(req.getQuestId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java index c72799966..2d4ae0790 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java @@ -1,53 +1,53 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.inventory.Inventory; -import emu.grasscutter.game.inventory.InventoryTab; -import emu.grasscutter.game.inventory.ItemType; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuickUseWidgetRspOuterClass.QuickUseWidgetRsp; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.QuickUseWidgetReq) -public class HandlerQuickUseWidgetReq extends PacketHandler { - /* - * WARNING: with the consuming of material widget ( Example: bomb ), - * this is just a implement designed to the decreasing of count - * - * ### Known Bug: No effects after using item but decrease. ### - * - * If you know which Packet could make the effects, feel free to contribute! - * */ - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - QuickUseWidgetRsp.Builder proto = QuickUseWidgetRsp.newBuilder(); - Player pl = session.getPlayer(); - synchronized (pl) { - int materialId = pl.getWidgetId(); - Inventory inventory = session.getPlayer().getInventory(); - InventoryTab inventoryTab = inventory.getInventoryTab(ItemType.ITEM_MATERIAL); - GameItem item = inventoryTab.getItemById(materialId); - int remain = item.getCount(); - if (remain > 0) { - remain--; - if (remain <= 0) { - proto.setRetcode(1); - } else { - proto.setRetcode(0); - } - proto.setMaterialId(materialId); - inventory.removeItem(item, 1);// decrease count - BasePacket rsp = new BasePacket(PacketOpcodes.QuickUseWidgetRsp); - rsp.setData(proto); - session.send(rsp); - Grasscutter.getLogger().warn("class has no effects in the game, feel free to implement it"); - // but no effects in the game, feel free to implement it! - } - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.Inventory; +import emu.grasscutter.game.inventory.InventoryTab; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuickUseWidgetRspOuterClass.QuickUseWidgetRsp; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.QuickUseWidgetReq) +public class HandlerQuickUseWidgetReq extends PacketHandler { + /* + * WARNING: with the consuming of material widget ( Example: bomb ), + * this is just a implement designed to the decreasing of count + * + * ### Known Bug: No effects after using item but decrease. ### + * + * If you know which Packet could make the effects, feel free to contribute! + * */ + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + QuickUseWidgetRsp.Builder proto = QuickUseWidgetRsp.newBuilder(); + Player pl = session.getPlayer(); + synchronized (pl) { + int materialId = pl.getWidgetId(); + Inventory inventory = session.getPlayer().getInventory(); + InventoryTab inventoryTab = inventory.getInventoryTab(ItemType.ITEM_MATERIAL); + GameItem item = inventoryTab.getItemById(materialId); + int remain = item.getCount(); + if (remain > 0) { + remain--; + if (remain <= 0) { + proto.setRetcode(1); + } else { + proto.setRetcode(0); + } + proto.setMaterialId(materialId); + inventory.removeItem(item, 1); // decrease count + BasePacket rsp = new BasePacket(PacketOpcodes.QuickUseWidgetRsp); + rsp.setData(proto); + session.send(rsp); + Grasscutter.getLogger().warn("class has no effects in the game, feel free to implement it"); + // but no effects in the game, feel free to implement it! + } + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReadMailNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReadMailNotify.java index 636a9499c..8b863b470 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReadMailNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReadMailNotify.java @@ -1,34 +1,34 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ReadMailNotifyOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketMailChangeNotify; - -import java.util.ArrayList; -import java.util.List; - -@Opcodes(PacketOpcodes.ReadMailNotify) -public class HandlerReadMailNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ReadMailNotifyOuterClass.ReadMailNotify req = ReadMailNotifyOuterClass.ReadMailNotify.parseFrom(payload); - - List updatedMail = new ArrayList<>(); - - for (int mailId : req.getMailIdListList()) { - Mail message = session.getPlayer().getMail(mailId); - - message.isRead = true; - - session.getPlayer().replaceMailByIndex(mailId, message); - updatedMail.add(message); - } - - session.send(new PacketMailChangeNotify(session.getPlayer(), updatedMail)); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ReadMailNotifyOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketMailChangeNotify; +import java.util.ArrayList; +import java.util.List; + +@Opcodes(PacketOpcodes.ReadMailNotify) +public class HandlerReadMailNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ReadMailNotifyOuterClass.ReadMailNotify req = + ReadMailNotifyOuterClass.ReadMailNotify.parseFrom(payload); + + List updatedMail = new ArrayList<>(); + + for (int mailId : req.getMailIdListList()) { + Mail message = session.getPlayer().getMail(mailId); + + message.isRead = true; + + session.getPlayer().replaceMailByIndex(mailId, message); + updatedMail.add(message); + } + + session.send(new PacketMailChangeNotify(session.getPlayer(), updatedMail)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryDecomposeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryDecomposeReq.java index c81cfc41e..e56b2e151 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryDecomposeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryDecomposeReq.java @@ -1,16 +1,20 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ReliquaryDecomposeReqOuterClass.ReliquaryDecomposeReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ReliquaryDecomposeReq) -public class HandlerReliquaryDecomposeReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ReliquaryDecomposeReq req = ReliquaryDecomposeReq.parseFrom(payload); - session.getServer().getCombineSystem().decomposeReliquaries(session.getPlayer(), req.getConfigId(), req.getTargetCount(), req.getGuidListList()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ReliquaryDecomposeReqOuterClass.ReliquaryDecomposeReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ReliquaryDecomposeReq) +public class HandlerReliquaryDecomposeReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ReliquaryDecomposeReq req = ReliquaryDecomposeReq.parseFrom(payload); + session + .getServer() + .getCombineSystem() + .decomposeReliquaries( + session.getPlayer(), req.getConfigId(), req.getTargetCount(), req.getGuidListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryUpgradeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryUpgradeReq.java index 6d3459fa1..17fb15cc3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryUpgradeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerReliquaryUpgradeReq.java @@ -1,19 +1,25 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ReliquaryUpgradeReqOuterClass.ReliquaryUpgradeReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.ReliquaryUpgradeReq) -public class HandlerReliquaryUpgradeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - ReliquaryUpgradeReq req = ReliquaryUpgradeReq.parseFrom(payload); - - session.getServer().getInventorySystem().upgradeRelic(session.getPlayer(), req.getTargetReliquaryGuid(), req.getFoodReliquaryGuidListList(), req.getItemParamListList()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ReliquaryUpgradeReqOuterClass.ReliquaryUpgradeReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.ReliquaryUpgradeReq) +public class HandlerReliquaryUpgradeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + ReliquaryUpgradeReq req = ReliquaryUpgradeReq.parseFrom(payload); + + session + .getServer() + .getInventorySystem() + .upgradeRelic( + session.getPlayer(), + req.getTargetReliquaryGuid(), + req.getFoodReliquaryGuidListList(), + req.getItemParamListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneEntityDrownReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneEntityDrownReq.java index 9583999d2..014f666ad 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneEntityDrownReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneEntityDrownReq.java @@ -1,34 +1,36 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneEntityDrownReqOuterClass.SceneEntityDrownReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSceneEntityDrownRsp; - -@Opcodes(PacketOpcodes.SceneEntityDrownReq) -public class HandlerSceneEntityDrownReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SceneEntityDrownReq req = SceneEntityDrownReq.parseFrom(payload); - - GameEntity entity = session.getPlayer().getScene().getEntityById(req.getEntityId()); - - if (entity == null || !(entity instanceof EntityMonster || entity instanceof EntityAvatar)) { - return; - } - - entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); - - //TODO: make a list somewhere of all entities to remove per tick rather than one by one - session.getPlayer().getScene().killEntity(entity, 0); - session.getPlayer().getScene().broadcastPacket(new PacketSceneEntityDrownRsp(req.getEntityId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneEntityDrownReqOuterClass.SceneEntityDrownReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSceneEntityDrownRsp; + +@Opcodes(PacketOpcodes.SceneEntityDrownReq) +public class HandlerSceneEntityDrownReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SceneEntityDrownReq req = SceneEntityDrownReq.parseFrom(payload); + + GameEntity entity = session.getPlayer().getScene().getEntityById(req.getEntityId()); + + if (entity == null || !(entity instanceof EntityMonster || entity instanceof EntityAvatar)) { + return; + } + + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); + + // TODO: make a list somewhere of all entities to remove per tick rather than one by one + session.getPlayer().getScene().killEntity(entity, 0); + session + .getPlayer() + .getScene() + .broadcastPacket(new PacketSceneEntityDrownRsp(req.getEntityId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java index 20a9137ef..0a2bf571d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java @@ -1,40 +1,40 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.*; - -@Opcodes(PacketOpcodes.SceneInitFinishReq) -public class HandlerSceneInitFinishReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Info packets - session.send(new PacketServerTimeNotify()); - session.send(new PacketWorldPlayerInfoNotify(session.getPlayer().getWorld())); - session.send(new PacketWorldDataNotify(session.getPlayer().getWorld())); - session.send(new PacketPlayerWorldSceneInfoListNotify()); - session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); - session.send(new PacketHostPlayerNotify(session.getPlayer().getWorld())); - - session.send(new PacketSceneTimeNotify(session.getPlayer())); - session.send(new PacketPlayerGameTimeNotify(session.getPlayer())); - session.send(new PacketPlayerEnterSceneInfoNotify(session.getPlayer())); - session.send(new PacketSceneAreaWeatherNotify(session.getPlayer())); - session.send(new PacketScenePlayerInfoNotify(session.getPlayer().getWorld())); - session.send(new PacketSceneTeamUpdateNotify(session.getPlayer())); - - session.send(new PacketSyncTeamEntityNotify(session.getPlayer())); - session.send(new PacketSyncScenePlayTeamEntityNotify(session.getPlayer())); - - // Done Packet - session.send(new PacketSceneInitFinishRsp(session.getPlayer())); - - // Set state - session.getPlayer().setSceneLoadState(SceneLoadState.INIT); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player.SceneLoadState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.*; + +@Opcodes(PacketOpcodes.SceneInitFinishReq) +public class HandlerSceneInitFinishReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Info packets + session.send(new PacketServerTimeNotify()); + session.send(new PacketWorldPlayerInfoNotify(session.getPlayer().getWorld())); + session.send(new PacketWorldDataNotify(session.getPlayer().getWorld())); + session.send(new PacketPlayerWorldSceneInfoListNotify()); + session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); + session.send(new PacketHostPlayerNotify(session.getPlayer().getWorld())); + + session.send(new PacketSceneTimeNotify(session.getPlayer())); + session.send(new PacketPlayerGameTimeNotify(session.getPlayer())); + session.send(new PacketPlayerEnterSceneInfoNotify(session.getPlayer())); + session.send(new PacketSceneAreaWeatherNotify(session.getPlayer())); + session.send(new PacketScenePlayerInfoNotify(session.getPlayer().getWorld())); + session.send(new PacketSceneTeamUpdateNotify(session.getPlayer())); + + session.send(new PacketSyncTeamEntityNotify(session.getPlayer())); + session.send(new PacketSyncScenePlayTeamEntityNotify(session.getPlayer())); + + // Done Packet + session.send(new PacketSceneInitFinishRsp(session.getPlayer())); + + // Set state + session.getPlayer().setSceneLoadState(SceneLoadState.INIT); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneKickPlayerReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneKickPlayerReq.java index f228e4748..ea5d8142d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneKickPlayerReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneKickPlayerReq.java @@ -1,26 +1,28 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneKickPlayerReqOuterClass.SceneKickPlayerReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSceneKickPlayerRsp; - -@Opcodes(PacketOpcodes.SceneKickPlayerReq) -public class HandlerSceneKickPlayerReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SceneKickPlayerReq req = SceneKickPlayerReq.parseFrom(payload); - - if (session.getServer().getMultiplayerSystem().kickPlayer(session.getPlayer(), req.getTargetUid())) { - // Success - session.send(new PacketSceneKickPlayerRsp(req.getTargetUid())); - } else { - // Fail - session.send(new PacketSceneKickPlayerRsp()); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneKickPlayerReqOuterClass.SceneKickPlayerReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSceneKickPlayerRsp; + +@Opcodes(PacketOpcodes.SceneKickPlayerReq) +public class HandlerSceneKickPlayerReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SceneKickPlayerReq req = SceneKickPlayerReq.parseFrom(payload); + + if (session + .getServer() + .getMultiplayerSystem() + .kickPlayer(session.getPlayer(), req.getTargetUid())) { + // Success + session.send(new PacketSceneKickPlayerRsp(req.getTargetUid())); + } else { + // Fail + session.send(new PacketSceneKickPlayerRsp()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java index 8278fa144..90d7a6df2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java @@ -1,33 +1,39 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.binout.ScenePointEntry; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSceneTransToPointRsp; - -@Opcodes(PacketOpcodes.SceneTransToPointReq) -public class HandlerSceneTransToPointReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SceneTransToPointReq req = SceneTransToPointReq.parseFrom(payload); - var player = session.getPlayer(); - - ScenePointEntry scenePointEntry = GameData.getScenePointEntryById(req.getSceneId(), req.getPointId()); - - if (scenePointEntry != null) { - if (player.getWorld().transferPlayerToScene(player, req.getSceneId(), TeleportType.WAYPOINT, scenePointEntry.getPointData().getTranPos().clone())) { - session.send(new PacketSceneTransToPointRsp(player, req.getPointId(), req.getSceneId())); - return; - } - } - - session.send(new PacketSceneTransToPointRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSceneTransToPointRsp; + +@Opcodes(PacketOpcodes.SceneTransToPointReq) +public class HandlerSceneTransToPointReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SceneTransToPointReq req = SceneTransToPointReq.parseFrom(payload); + var player = session.getPlayer(); + + ScenePointEntry scenePointEntry = + GameData.getScenePointEntryById(req.getSceneId(), req.getPointId()); + + if (scenePointEntry != null) { + if (player + .getWorld() + .transferPlayerToScene( + player, + req.getSceneId(), + TeleportType.WAYPOINT, + scenePointEntry.getPointData().getTranPos().clone())) { + session.send(new PacketSceneTransToPointRsp(player, req.getPointId(), req.getSceneId())); + return; + } + } + + session.send(new PacketSceneTransToPointRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSelectWorktopOptionReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSelectWorktopOptionReq.java index 15e53e2ae..e0137841b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSelectWorktopOptionReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSelectWorktopOptionReq.java @@ -1,38 +1,40 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq; -import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.data.ScriptArgs; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSelectWorktopOptionRsp; - -@Opcodes(PacketOpcodes.SelectWorktopOptionReq) -public class HandlerSelectWorktopOptionReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SelectWorktopOptionReq req = SelectWorktopOptionReq.parseFrom(payload); - - try { - GameEntity entity = session.getPlayer().getScene().getEntityById(req.getGadgetEntityId()); - - if (!(entity instanceof EntityGadget)) { - return; - } - session.getPlayer().getScene().selectWorktopOptionWith(req); - session.getPlayer().getScene().getScriptManager().callEvent( - EventType.EVENT_SELECT_OPTION, - new ScriptArgs(entity.getConfigId(), req.getOptionId()) - ); - } finally { - // Always send packet - session.send(new PacketSelectWorktopOptionRsp(req.getGadgetEntityId(), req.getOptionId())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSelectWorktopOptionRsp; + +@Opcodes(PacketOpcodes.SelectWorktopOptionReq) +public class HandlerSelectWorktopOptionReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SelectWorktopOptionReq req = SelectWorktopOptionReq.parseFrom(payload); + + try { + GameEntity entity = session.getPlayer().getScene().getEntityById(req.getGadgetEntityId()); + + if (!(entity instanceof EntityGadget)) { + return; + } + session.getPlayer().getScene().selectWorktopOptionWith(req); + session + .getPlayer() + .getScene() + .getScriptManager() + .callEvent( + EventType.EVENT_SELECT_OPTION, + new ScriptArgs(entity.getConfigId(), req.getOptionId())); + } finally { + // Always send packet + session.send(new PacketSelectWorktopOptionRsp(req.getGadgetEntityId(), req.getOptionId())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java index 2218044d9..1811c6562 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java @@ -1,29 +1,28 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetEntityClientDataNotifyOuterClass.SetEntityClientDataNotify; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.SetEntityClientDataNotify) -public class HandlerSetEntityClientDataNotify extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Skip if there is no one to broadcast it too - if (session.getPlayer().getScene().getPlayerCount() <= 1) { - return; - } - - // Make sure packet is a valid proto before replaying it to the other players - SetEntityClientDataNotify notif = SetEntityClientDataNotify.parseFrom(payload); - - BasePacket packet = new BasePacket(PacketOpcodes.SetEntityClientDataNotify, true); - packet.setData(notif); - - session.getPlayer().getScene().broadcastPacket(packet); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetEntityClientDataNotifyOuterClass.SetEntityClientDataNotify; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.SetEntityClientDataNotify) +public class HandlerSetEntityClientDataNotify extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Skip if there is no one to broadcast it too + if (session.getPlayer().getScene().getPlayerCount() <= 1) { + return; + } + + // Make sure packet is a valid proto before replaying it to the other players + SetEntityClientDataNotify notif = SetEntityClientDataNotify.parseFrom(payload); + + BasePacket packet = new BasePacket(PacketOpcodes.SetEntityClientDataNotify, true); + packet.setData(notif); + + session.getPlayer().getScene().broadcastPacket(packet); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEquipLockStateReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEquipLockStateReq.java index 625300caf..6434478dc 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEquipLockStateReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEquipLockStateReq.java @@ -1,19 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetEquipLockStateReqOuterClass.SetEquipLockStateReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.SetEquipLockStateReq) -public class HandlerSetEquipLockStateReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetEquipLockStateReq req = SetEquipLockStateReq.parseFrom(payload); - - session.getServer().getInventorySystem().lockEquip(session.getPlayer(), req.getTargetEquipGuid(), req.getIsLocked()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetEquipLockStateReqOuterClass.SetEquipLockStateReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.SetEquipLockStateReq) +public class HandlerSetEquipLockStateReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetEquipLockStateReq req = SetEquipLockStateReq.parseFrom(payload); + + session + .getServer() + .getInventorySystem() + .lockEquip(session.getPlayer(), req.getTargetEquipGuid(), req.getIsLocked()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetNameCardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetNameCardReq.java index d89793f51..4ff035460 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetNameCardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetNameCardReq.java @@ -1,17 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetNameCardReqOuterClass.SetNameCardReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.SetNameCardReq) -public class HandlerSetNameCardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetNameCardReq req = SetNameCardReq.parseFrom(payload); - - session.getPlayer().setNameCard(req.getNameCardId()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetNameCardReqOuterClass.SetNameCardReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.SetNameCardReq) +public class HandlerSetNameCardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetNameCardReq req = SetNameCardReq.parseFrom(payload); + + session.getPlayer().setNameCard(req.getNameCardId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBirthdayReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBirthdayReq.java index d2e7cd495..a758b29d6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBirthdayReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBirthdayReq.java @@ -1,67 +1,66 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerBirthdayReqOuterClass.SetPlayerBirthdayReq; -import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketGetPlayerSocialDetailRsp; -import emu.grasscutter.server.packet.send.PacketSetPlayerBirthdayRsp; - -@Opcodes(PacketOpcodes.SetPlayerBirthdayReq) -public class HandlerSetPlayerBirthdayReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetPlayerBirthdayReq req = SetPlayerBirthdayReq.parseFrom(payload); - - // RET_BIRTHDAY_CANNOT_BE_SET_TWICE = 7009 - if (session.getPlayer().hasBirthday()) { - session.send(new PacketSetPlayerBirthdayRsp(7009)); - return; - } - - int month = req.getBirthday().getMonth(); - int day = req.getBirthday().getDay(); - - // RET_BIRTHDAY_FORMAT_ERROR = 7022 - if (!isValidBirthday(month, day)) { - session.send(new PacketSetPlayerBirthdayRsp(7022)); - return; - } - - // Update birthday value - session.getPlayer().setBirthday(day, month); - - // Save birthday month and day - session.getPlayer().save(); - SocialDetail.Builder detail = session.getPlayer().getSocialDetail(); - - session.send(new PacketSetPlayerBirthdayRsp(session.getPlayer())); - session.send(new PacketGetPlayerSocialDetailRsp(detail)); - } - - private boolean isValidBirthday(int month, int day) { - - switch (month) { - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - return day > 0 & day <= 31; - case 4: - case 6: - case 9: - case 11: - return day > 0 && day <= 30; - case 2: - return day > 0 & day <= 29; - } - - return false; - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerBirthdayReqOuterClass.SetPlayerBirthdayReq; +import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetPlayerSocialDetailRsp; +import emu.grasscutter.server.packet.send.PacketSetPlayerBirthdayRsp; + +@Opcodes(PacketOpcodes.SetPlayerBirthdayReq) +public class HandlerSetPlayerBirthdayReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetPlayerBirthdayReq req = SetPlayerBirthdayReq.parseFrom(payload); + + // RET_BIRTHDAY_CANNOT_BE_SET_TWICE = 7009 + if (session.getPlayer().hasBirthday()) { + session.send(new PacketSetPlayerBirthdayRsp(7009)); + return; + } + + int month = req.getBirthday().getMonth(); + int day = req.getBirthday().getDay(); + + // RET_BIRTHDAY_FORMAT_ERROR = 7022 + if (!isValidBirthday(month, day)) { + session.send(new PacketSetPlayerBirthdayRsp(7022)); + return; + } + + // Update birthday value + session.getPlayer().setBirthday(day, month); + + // Save birthday month and day + session.getPlayer().save(); + SocialDetail.Builder detail = session.getPlayer().getSocialDetail(); + + session.send(new PacketSetPlayerBirthdayRsp(session.getPlayer())); + session.send(new PacketGetPlayerSocialDetailRsp(detail)); + } + + private boolean isValidBirthday(int month, int day) { + + switch (month) { + case 1: + case 3: + case 5: + case 7: + case 8: + case 10: + case 12: + return day > 0 & day <= 31; + case 4: + case 6: + case 9: + case 11: + return day > 0 && day <= 30; + case 2: + return day > 0 & day <= 29; + } + + return false; + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java index dcd0c1b70..bfee8ec68 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java @@ -1,81 +1,89 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.commands.SendMailCommand.MailBuilder; -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerBornDataReqOuterClass.SetPlayerBornDataReq; -import emu.grasscutter.server.game.GameSession; - -import java.util.Arrays; - -import static emu.grasscutter.config.Configuration.GAME_INFO; - -@Opcodes(PacketOpcodes.SetPlayerBornDataReq) -public class HandlerSetPlayerBornDataReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetPlayerBornDataReq req = SetPlayerBornDataReq.parseFrom(payload); - - // Sanity checks - int avatarId = req.getAvatarId(); - int startingSkillDepot; - if (avatarId == GameConstants.MAIN_CHARACTER_MALE) { - startingSkillDepot = 504; - } else if (avatarId == GameConstants.MAIN_CHARACTER_FEMALE) { - startingSkillDepot = 704; - } else { - return; - } - - // Make sure resources folder is set - if (!GameData.getAvatarDataMap().containsKey(avatarId)) { - Grasscutter.getLogger().error("No avatar data found! Please check your ExcelBinOutput folder."); - session.close(); - return; - } - - // Get player object - Player player = session.getPlayer(); - player.setNickname(req.getNickName()); - - // Create avatar - if (player.getAvatars().getAvatarCount() == 0) { - Avatar mainCharacter = new Avatar(avatarId); - mainCharacter.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(startingSkillDepot)); - // Manually handle adding to team - player.addAvatar(mainCharacter, false); - player.setMainCharacterId(avatarId); - player.setHeadImage(avatarId); - player.getTeamManager().getCurrentSinglePlayerTeamInfo().getAvatars().add(mainCharacter.getAvatarId()); - player.save(); // TODO save player team in different object - } else { - return; - } - - // Login done - session.getPlayer().onLogin(); - - // Born resp packet - session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp)); - - // Default mail - var welcomeMail = GAME_INFO.joinOptions.welcomeMail; - MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail()); - mailBuilder.mail.mailContent.title = welcomeMail.title; - mailBuilder.mail.mailContent.sender = welcomeMail.sender; - // Please credit Grasscutter if changing something here. We don't condone commercial use of the project. - mailBuilder.mail.mailContent.content = welcomeMail.content + "\n"; - mailBuilder.mail.itemList.addAll(Arrays.asList(welcomeMail.items)); - mailBuilder.mail.importance = 1; - player.sendMail(mailBuilder.mail); - } -} +package emu.grasscutter.server.packet.recv; + +import static emu.grasscutter.config.Configuration.GAME_INFO; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.commands.SendMailCommand.MailBuilder; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerBornDataReqOuterClass.SetPlayerBornDataReq; +import emu.grasscutter.server.game.GameSession; +import java.util.Arrays; + +@Opcodes(PacketOpcodes.SetPlayerBornDataReq) +public class HandlerSetPlayerBornDataReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetPlayerBornDataReq req = SetPlayerBornDataReq.parseFrom(payload); + + // Sanity checks + int avatarId = req.getAvatarId(); + int startingSkillDepot; + if (avatarId == GameConstants.MAIN_CHARACTER_MALE) { + startingSkillDepot = 504; + } else if (avatarId == GameConstants.MAIN_CHARACTER_FEMALE) { + startingSkillDepot = 704; + } else { + return; + } + + // Make sure resources folder is set + if (!GameData.getAvatarDataMap().containsKey(avatarId)) { + Grasscutter.getLogger() + .error("No avatar data found! Please check your ExcelBinOutput folder."); + session.close(); + return; + } + + // Get player object + Player player = session.getPlayer(); + player.setNickname(req.getNickName()); + + // Create avatar + if (player.getAvatars().getAvatarCount() == 0) { + Avatar mainCharacter = new Avatar(avatarId); + mainCharacter.setSkillDepotData( + GameData.getAvatarSkillDepotDataMap().get(startingSkillDepot)); + // Manually handle adding to team + player.addAvatar(mainCharacter, false); + player.setMainCharacterId(avatarId); + player.setHeadImage(avatarId); + player + .getTeamManager() + .getCurrentSinglePlayerTeamInfo() + .getAvatars() + .add(mainCharacter.getAvatarId()); + player.save(); // TODO save player team in different object + } else { + return; + } + + // Login done + session.getPlayer().onLogin(); + + // Born resp packet + session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp)); + + // Default mail + var welcomeMail = GAME_INFO.joinOptions.welcomeMail; + MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail()); + mailBuilder.mail.mailContent.title = welcomeMail.title; + mailBuilder.mail.mailContent.sender = welcomeMail.sender; + // Please credit Grasscutter if changing something here. We don't condone commercial use of the + // project. + mailBuilder.mail.mailContent.content = + welcomeMail.content + + "\n"; + mailBuilder.mail.itemList.addAll(Arrays.asList(welcomeMail.items)); + mailBuilder.mail.importance = 1; + player.sendMail(mailBuilder.mail); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerHeadImageReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerHeadImageReq.java index dca919192..55494dc28 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerHeadImageReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerHeadImageReq.java @@ -1,23 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerHeadImageReqOuterClass.SetPlayerHeadImageReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetPlayerHeadImageRsp; - -@Opcodes(PacketOpcodes.SetPlayerHeadImageReq) -public class HandlerSetPlayerHeadImageReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetPlayerHeadImageReq req = SetPlayerHeadImageReq.parseFrom(payload); - - int id = req.getAvatarId(); - - if (session.getPlayer().getAvatars().hasAvatar(id)) { - session.getPlayer().setHeadImage(id); - session.send(new PacketSetPlayerHeadImageRsp(session.getPlayer())); - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerHeadImageReqOuterClass.SetPlayerHeadImageReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetPlayerHeadImageRsp; + +@Opcodes(PacketOpcodes.SetPlayerHeadImageReq) +public class HandlerSetPlayerHeadImageReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetPlayerHeadImageReq req = SetPlayerHeadImageReq.parseFrom(payload); + + int id = req.getAvatarId(); + + if (session.getPlayer().getAvatars().hasAvatar(id)) { + session.getPlayer().setHeadImage(id); + session.send(new PacketSetPlayerHeadImageRsp(session.getPlayer())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerNameReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerNameReq.java index d66a3e639..6b9b316c9 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerNameReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerNameReq.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerNameReqOuterClass.SetPlayerNameReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetPlayerNameRsp; - -@Opcodes(PacketOpcodes.SetPlayerNameReq) -public class HandlerSetPlayerNameReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - SetPlayerNameReq req = SetPlayerNameReq.parseFrom(payload); - - if (req.getNickName() != null && req.getNickName().length() > 0) { - session.getPlayer().setNickname(req.getNickName()); - session.send(new PacketSetPlayerNameRsp(session.getPlayer())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerNameReqOuterClass.SetPlayerNameReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetPlayerNameRsp; + +@Opcodes(PacketOpcodes.SetPlayerNameReq) +public class HandlerSetPlayerNameReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + SetPlayerNameReq req = SetPlayerNameReq.parseFrom(payload); + + if (req.getNickName() != null && req.getNickName().length() > 0) { + session.getPlayer().setNickname(req.getNickName()); + session.send(new PacketSetPlayerNameRsp(session.getPlayer())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerPropReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerPropReq.java index 57366ef75..e39cef120 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerPropReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerPropReq.java @@ -1,35 +1,33 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; -import emu.grasscutter.net.proto.SetPlayerPropReqOuterClass.SetPlayerPropReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetPlayerPropRsp; - -@Opcodes(PacketOpcodes.SetPlayerPropReq) -public class HandlerSetPlayerPropReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - SetPlayerPropReq req = SetPlayerPropReq.parseFrom(payload); - Player player = session.getPlayer(); - for (PropValue p : req.getPropListList()) { - PlayerProperty prop = PlayerProperty.getPropById(p.getType()); - if (prop == PlayerProperty.PROP_IS_MP_MODE_AVAILABLE) { - if (!player.setProperty(prop, (int) p.getVal(), false)) { - session.send(new PacketSetPlayerPropRsp(1)); - return; - } - } - } - player.save(); - session.send(new PacketSetPlayerPropRsp(0)); - } - - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; +import emu.grasscutter.net.proto.SetPlayerPropReqOuterClass.SetPlayerPropReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetPlayerPropRsp; + +@Opcodes(PacketOpcodes.SetPlayerPropReq) +public class HandlerSetPlayerPropReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + SetPlayerPropReq req = SetPlayerPropReq.parseFrom(payload); + Player player = session.getPlayer(); + for (PropValue p : req.getPropListList()) { + PlayerProperty prop = PlayerProperty.getPropById(p.getType()); + if (prop == PlayerProperty.PROP_IS_MP_MODE_AVAILABLE) { + if (!player.setProperty(prop, (int) p.getVal(), false)) { + session.send(new PacketSetPlayerPropRsp(1)); + return; + } + } + } + player.save(); + session.send(new PacketSetPlayerPropRsp(0)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerSignatureReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerSignatureReq.java index fb3d03181..139dff1c2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerSignatureReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerSignatureReq.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerSignatureReqOuterClass.SetPlayerSignatureReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetPlayerSignatureRsp; - -@Opcodes(PacketOpcodes.SetPlayerSignatureReq) -public class HandlerSetPlayerSignatureReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Auto template - SetPlayerSignatureReq req = SetPlayerSignatureReq.parseFrom(payload); - - if (req.getSignature() != null && req.getSignature().length() > 0) { - session.getPlayer().setSignature(req.getSignature()); - session.send(new PacketSetPlayerSignatureRsp(session.getPlayer())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerSignatureReqOuterClass.SetPlayerSignatureReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetPlayerSignatureRsp; + +@Opcodes(PacketOpcodes.SetPlayerSignatureReq) +public class HandlerSetPlayerSignatureReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + // Auto template + SetPlayerSignatureReq req = SetPlayerSignatureReq.parseFrom(payload); + + if (req.getSignature() != null && req.getSignature().length() > 0) { + session.getPlayer().setSignature(req.getSignature()); + session.send(new PacketSetPlayerSignatureRsp(session.getPlayer())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpAvatarTeamReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpAvatarTeamReq.java index 3197d8c81..1b3334674 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpAvatarTeamReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpAvatarTeamReq.java @@ -1,19 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetUpAvatarTeamReqOuterClass.SetUpAvatarTeamReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.SetUpAvatarTeamReq) -public class HandlerSetUpAvatarTeamReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetUpAvatarTeamReq req = SetUpAvatarTeamReq.parseFrom(payload); - - session.getPlayer().getTeamManager().setupAvatarTeam(req.getTeamId(), req.getAvatarTeamGuidListList()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetUpAvatarTeamReqOuterClass.SetUpAvatarTeamReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.SetUpAvatarTeamReq) +public class HandlerSetUpAvatarTeamReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetUpAvatarTeamReq req = SetUpAvatarTeamReq.parseFrom(payload); + + session + .getPlayer() + .getTeamManager() + .setupAvatarTeam(req.getTeamId(), req.getAvatarTeamGuidListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpLunchBoxWidgetReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpLunchBoxWidgetReq.java index 917aece7e..37d95e5e3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpLunchBoxWidgetReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetUpLunchBoxWidgetReq.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetUpLunchBoxWidgetReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetUpLunchBoxWidgetRsp; - -@Opcodes(PacketOpcodes.SetUpLunchBoxWidgetReq) -public class HandlerSetUpLunchBoxWidgetReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req - = SetUpLunchBoxWidgetReqOuterClass.SetUpLunchBoxWidgetReq.parseFrom(payload); - - session.send(new PacketSetUpLunchBoxWidgetRsp(req.getLunchBoxData())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetUpLunchBoxWidgetReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetUpLunchBoxWidgetRsp; + +@Opcodes(PacketOpcodes.SetUpLunchBoxWidgetReq) +public class HandlerSetUpLunchBoxWidgetReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = SetUpLunchBoxWidgetReqOuterClass.SetUpLunchBoxWidgetReq.parseFrom(payload); + + session.send(new PacketSetUpLunchBoxWidgetRsp(req.getLunchBoxData())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java index a803e1950..401e7f192 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java @@ -1,36 +1,38 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetWidgetSlotReqOuterClass; -import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketSetWidgetSlotRsp; -import emu.grasscutter.server.packet.send.PacketWidgetSlotChangeNotify; - -@Opcodes(PacketOpcodes.SetWidgetSlotReq) -public class HandlerSetWidgetSlotReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - SetWidgetSlotReqOuterClass.SetWidgetSlotReq req = SetWidgetSlotReqOuterClass.SetWidgetSlotReq.parseFrom(payload); - - Player player = session.getPlayer(); - player.setWidgetId(req.getMaterialId()); - - // WidgetSlotChangeNotify op & slot key - session.send(new PacketWidgetSlotChangeNotify(WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_DETACH)); - - //only attaching the widget can set it - if (req.getOp() == WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_ATTACH) { - // WidgetSlotChangeNotify slot - session.send(new PacketWidgetSlotChangeNotify(req.getMaterialId())); - } - - // SetWidgetSlotRsp - session.send(new PacketSetWidgetSlotRsp(req.getMaterialId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetWidgetSlotReqOuterClass; +import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetWidgetSlotRsp; +import emu.grasscutter.server.packet.send.PacketWidgetSlotChangeNotify; + +@Opcodes(PacketOpcodes.SetWidgetSlotReq) +public class HandlerSetWidgetSlotReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetWidgetSlotReqOuterClass.SetWidgetSlotReq req = + SetWidgetSlotReqOuterClass.SetWidgetSlotReq.parseFrom(payload); + + Player player = session.getPlayer(); + player.setWidgetId(req.getMaterialId()); + + // WidgetSlotChangeNotify op & slot key + session.send( + new PacketWidgetSlotChangeNotify( + WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_DETACH)); + + // only attaching the widget can set it + if (req.getOp() == WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_ATTACH) { + // WidgetSlotChangeNotify slot + session.send(new PacketWidgetSlotChangeNotify(req.getMaterialId())); + } + + // SetWidgetSlotRsp + session.send(new PacketSetWidgetSlotRsp(req.getMaterialId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeAchievementGoalRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeAchievementGoalRewardReq.java index 533e6a150..d20ef4ba4 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeAchievementGoalRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeAchievementGoalRewardReq.java @@ -1,16 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeAchievementGoalRewardReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.TakeAchievementGoalRewardReq) -public class HandlerTakeAchievementGoalRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = TakeAchievementGoalRewardReqOuterClass.TakeAchievementGoalRewardReq.parseFrom(payload); - session.getPlayer().getAchievements().takeGoalReward(req.getIdListList()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeAchievementGoalRewardReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TakeAchievementGoalRewardReq) +public class HandlerTakeAchievementGoalRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + TakeAchievementGoalRewardReqOuterClass.TakeAchievementGoalRewardReq.parseFrom(payload); + session.getPlayer().getAchievements().takeGoalReward(req.getIdListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeBattlePassRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeBattlePassRewardReq.java index b201f6570..e1b290547 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeBattlePassRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeBattlePassRewardReq.java @@ -1,17 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeBattlePassRewardReqOuterClass.TakeBattlePassRewardReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.TakeBattlePassRewardReq) -public class HandlerTakeBattlePassRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = TakeBattlePassRewardReq.parseFrom(payload); - - session.getPlayer().getBattlePassManager().takeReward(req.getTakeOptionListList()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeBattlePassRewardReqOuterClass.TakeBattlePassRewardReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TakeBattlePassRewardReq) +public class HandlerTakeBattlePassRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = TakeBattlePassRewardReq.parseFrom(payload); + + session.getPlayer().getBattlePassManager().takeReward(req.getTakeOptionListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java index 206179eb2..8706bff1d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeFurnitureMakeReq.java @@ -1,19 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeFurnitureMakeReqOuterClass; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.TakeFurnitureMakeReq) -public class HandlerTakeFurnitureMakeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = TakeFurnitureMakeReqOuterClass.TakeFurnitureMakeReq.parseFrom(payload); - - session.getPlayer().getFurnitureManager().take(req.getIndex(), req.getMakeId(), req.getIsFastFinish()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeFurnitureMakeReqOuterClass; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TakeFurnitureMakeReq) +public class HandlerTakeFurnitureMakeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = TakeFurnitureMakeReqOuterClass.TakeFurnitureMakeReq.parseFrom(payload); + + session + .getPlayer() + .getFurnitureManager() + .take(req.getIndex(), req.getMakeId(), req.getIsFastFinish()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java index 9d7ddb771..eafa180f2 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java @@ -1,39 +1,39 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakePlayerLevelRewardReqOuterClass.TakePlayerLevelRewardReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketTakePlayerLevelRewardRsp; - -import java.util.List; -import java.util.Set; - -@Opcodes(PacketOpcodes.TakePlayerLevelRewardReq) -public class HandlerTakePlayerLevelRewardReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - Player pl = session.getPlayer(); - synchronized (pl) { - TakePlayerLevelRewardReq req = TakePlayerLevelRewardReq.parseFrom(payload); - int level = req.getLevel(); - Set rewardedLevels = session.getPlayer().getRewardedLevels(); - if (!rewardedLevels.contains(level)) {// No duplicated reward - int rewardId = GameData.getPlayerLevelDataMap().get(level).getRewardId(); - if (rewardId != 0) { - List rewardItems = GameData.getRewardDataMap().get(rewardId).getRewardItemList(); - pl.getInventory().addItemParamDatas(rewardItems, ActionReason.PlayerUpgradeReward); - rewardedLevels.add(level); - pl.setRewardedLevels(rewardedLevels); - pl.save(); - session.send(new PacketTakePlayerLevelRewardRsp(level, rewardId)); - } - } - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakePlayerLevelRewardReqOuterClass.TakePlayerLevelRewardReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTakePlayerLevelRewardRsp; +import java.util.List; +import java.util.Set; + +@Opcodes(PacketOpcodes.TakePlayerLevelRewardReq) +public class HandlerTakePlayerLevelRewardReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + Player pl = session.getPlayer(); + synchronized (pl) { + TakePlayerLevelRewardReq req = TakePlayerLevelRewardReq.parseFrom(payload); + int level = req.getLevel(); + Set rewardedLevels = session.getPlayer().getRewardedLevels(); + if (!rewardedLevels.contains(level)) { // No duplicated reward + int rewardId = GameData.getPlayerLevelDataMap().get(level).getRewardId(); + if (rewardId != 0) { + List rewardItems = + GameData.getRewardDataMap().get(rewardId).getRewardItemList(); + pl.getInventory().addItemParamDatas(rewardItems, ActionReason.PlayerUpgradeReward); + rewardedLevels.add(level); + pl.setRewardedLevels(rewardedLevels); + pl.save(); + session.send(new PacketTakePlayerLevelRewardRsp(level, rewardId)); + } + } + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeoffEquipReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeoffEquipReq.java index cf55da9a1..ebc052b13 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeoffEquipReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakeoffEquipReq.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeoffEquipReqOuterClass.TakeoffEquipReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketTakeoffEquipRsp; - -@Opcodes(PacketOpcodes.TakeoffEquipReq) -public class HandlerTakeoffEquipReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - TakeoffEquipReq req = TakeoffEquipReq.parseFrom(payload); - - if (session.getPlayer().getInventory().unequipItem(req.getAvatarGuid(), req.getSlot())) { - session.send(new PacketTakeoffEquipRsp(req.getAvatarGuid(), req.getSlot())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeoffEquipReqOuterClass.TakeoffEquipReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTakeoffEquipRsp; + +@Opcodes(PacketOpcodes.TakeoffEquipReq) +public class HandlerTakeoffEquipReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TakeoffEquipReq req = TakeoffEquipReq.parseFrom(payload); + + if (session.getPlayer().getInventory().unequipItem(req.getAvatarGuid(), req.getSlot())) { + session.send(new PacketTakeoffEquipRsp(req.getAvatarGuid(), req.getSlot())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java index f2048d8b7..0e4d3cb87 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketTowerAllDataRsp; - -@Opcodes(PacketOpcodes.TowerAllDataReq) -public class HandlerTowerAllDataReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketTowerAllDataRsp( - session.getServer().getTowerSystem(), - session.getPlayer().getTowerManager() - )); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTowerAllDataRsp; + +@Opcodes(PacketOpcodes.TowerAllDataReq) +public class HandlerTowerAllDataReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.send( + new PacketTowerAllDataRsp( + session.getServer().getTowerSystem(), session.getPlayer().getTowerManager())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java index 1c4471119..f39ffc3fe 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerEnterLevelReqOuterClass.TowerEnterLevelReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.TowerEnterLevelReq) -public class HandlerTowerEnterLevelReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - TowerEnterLevelReq req = TowerEnterLevelReq.parseFrom(payload); - - //session.send(new PacketTowerCurLevelRecordChangeNotify()); - session.getPlayer().getTowerManager().enterLevel(req.getEnterPointId()); - - //session.send(new PacketTowerLevelStarCondNotify()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerEnterLevelReqOuterClass.TowerEnterLevelReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TowerEnterLevelReq) +public class HandlerTowerEnterLevelReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TowerEnterLevelReq req = TowerEnterLevelReq.parseFrom(payload); + + // session.send(new PacketTowerCurLevelRecordChangeNotify()); + session.getPlayer().getTowerManager().enterLevel(req.getEnterPointId()); + + // session.send(new PacketTowerLevelStarCondNotify()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java index 0246ed7ad..ff5c21da8 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerTeamOuterClass; -import emu.grasscutter.net.proto.TowerTeamSelectReqOuterClass.TowerTeamSelectReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketTowerTeamSelectRsp; - -@Opcodes(PacketOpcodes.TowerTeamSelectReq) -public class HandlerTowerTeamSelectReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - TowerTeamSelectReq req = TowerTeamSelectReq.parseFrom(payload); - - var towerTeams = req.getTowerTeamListList().stream() - .map(TowerTeamOuterClass.TowerTeam::getAvatarGuidListList) - .toList(); - - session.getPlayer().getTowerManager().teamSelect(req.getFloorId(), towerTeams); - - session.send(new PacketTowerTeamSelectRsp()); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerTeamOuterClass; +import emu.grasscutter.net.proto.TowerTeamSelectReqOuterClass.TowerTeamSelectReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTowerTeamSelectRsp; + +@Opcodes(PacketOpcodes.TowerTeamSelectReq) +public class HandlerTowerTeamSelectReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TowerTeamSelectReq req = TowerTeamSelectReq.parseFrom(payload); + + var towerTeams = + req.getTowerTeamListList().stream() + .map(TowerTeamOuterClass.TowerTeam::getAvatarGuidListList) + .toList(); + + session.getPlayer().getTowerManager().teamSelect(req.getFloorId(), towerTeams); + + session.send(new PacketTowerTeamSelectRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java index 108a349b5..47e882687 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java @@ -1,62 +1,72 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.home.GameHome; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.TryEnterHomeReqOuterClass; -import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketTryEnterHomeRsp; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.TryEnterHomeReq) -public class HandlerTryEnterHomeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = TryEnterHomeReqOuterClass.TryEnterHomeReq.parseFrom(payload); - var targetPlayer = session.getServer().getPlayerByUid(req.getTargetUid(), true); - - if (req.getTargetUid() != session.getPlayer().getUid()) { - // I hope that tomorrow there will be a hero who can support multiplayer mode and write code like a poem - var targetHome = GameHome.getByUid(req.getTargetUid()); - switch (targetHome.getEnterHomeOption()) { - case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption.FRIEND_ENTER_HOME_OPTION_NEED_CONFIRM_VALUE: - if (!targetPlayer.isOnline()) { - session.send(new PacketTryEnterHomeRsp(RetcodeOuterClass.Retcode.RET_HOME_OWNER_OFFLINE_VALUE, req.getTargetUid())); - return; - } - break; - case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption.FRIEND_ENTER_HOME_OPTION_REFUSE_VALUE: - session.send(new PacketTryEnterHomeRsp(RetcodeOuterClass.Retcode.RET_HOME_HOME_REFUSE_GUEST_ENTER_VALUE, req.getTargetUid())); - return; - case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption.FRIEND_ENTER_HOME_OPTION_DIRECT_VALUE: - break; - } - - session.send(new PacketTryEnterHomeRsp()); - return; - } - - int realmId = 2000 + session.getPlayer().getCurrentRealmId(); - - var home = session.getPlayer().getHome(); - - // prepare the default arrangement for first come in - var homeScene = home.getHomeSceneItem(realmId); - home.save(); - - Scene scene = session.getPlayer().getWorld().getSceneById(realmId); - Position pos = scene.getScriptManager().getConfig().born_pos; - - boolean result = session.getPlayer().getWorld().transferPlayerToScene( - session.getPlayer(), realmId, - TeleportType.WAYPOINT, pos - ); - if (result) session.send(new PacketTryEnterHomeRsp(req.getTargetUid())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.home.GameHome; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.TryEnterHomeReqOuterClass; +import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTryEnterHomeRsp; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.TryEnterHomeReq) +public class HandlerTryEnterHomeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = TryEnterHomeReqOuterClass.TryEnterHomeReq.parseFrom(payload); + var targetPlayer = session.getServer().getPlayerByUid(req.getTargetUid(), true); + + if (req.getTargetUid() != session.getPlayer().getUid()) { + // I hope that tomorrow there will be a hero who can support multiplayer mode and write code + // like a poem + var targetHome = GameHome.getByUid(req.getTargetUid()); + switch (targetHome.getEnterHomeOption()) { + case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption + .FRIEND_ENTER_HOME_OPTION_NEED_CONFIRM_VALUE: + if (!targetPlayer.isOnline()) { + session.send( + new PacketTryEnterHomeRsp( + RetcodeOuterClass.Retcode.RET_HOME_OWNER_OFFLINE_VALUE, req.getTargetUid())); + return; + } + break; + case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption + .FRIEND_ENTER_HOME_OPTION_REFUSE_VALUE: + session.send( + new PacketTryEnterHomeRsp( + RetcodeOuterClass.Retcode.RET_HOME_HOME_REFUSE_GUEST_ENTER_VALUE, + req.getTargetUid())); + return; + case FriendEnterHomeOptionOuterClass.FriendEnterHomeOption + .FRIEND_ENTER_HOME_OPTION_DIRECT_VALUE: + break; + } + + session.send(new PacketTryEnterHomeRsp()); + return; + } + + int realmId = 2000 + session.getPlayer().getCurrentRealmId(); + + var home = session.getPlayer().getHome(); + + // prepare the default arrangement for first come in + var homeScene = home.getHomeSceneItem(realmId); + home.save(); + + Scene scene = session.getPlayer().getWorld().getSceneById(realmId); + Position pos = scene.getScriptManager().getConfig().born_pos; + + boolean result = + session + .getPlayer() + .getWorld() + .transferPlayerToScene(session.getPlayer(), realmId, TeleportType.WAYPOINT, pos); + if (result) session.send(new PacketTryEnterHomeRsp(req.getTargetUid())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java index a56eb5c07..9276f712f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java @@ -1,40 +1,45 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.Grasscutter.ServerDebugMode; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnionCmdNotifyOuterClass.UnionCmdNotify; -import emu.grasscutter.net.proto.UnionCmdOuterClass.UnionCmd; -import emu.grasscutter.server.game.GameSession; - -import static emu.grasscutter.config.Configuration.GAME_INFO; -import static emu.grasscutter.config.Configuration.SERVER; - -@Opcodes(PacketOpcodes.UnionCmdNotify) -public class HandlerUnionCmdNotify extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - UnionCmdNotify req = UnionCmdNotify.parseFrom(payload); - for (UnionCmd cmd : req.getCmdListList()) { - int cmdOpcode = cmd.getMessageId(); - byte[] cmdPayload = cmd.getBody().toByteArray(); - if (GAME_INFO.logPackets == ServerDebugMode.WHITELIST && SERVER.debugWhitelist.contains(cmd.getMessageId())) { - session.logPacket("RECV in Union", cmdOpcode, cmdPayload); - } else if (GAME_INFO.logPackets == ServerDebugMode.BLACKLIST && !SERVER.debugBlacklist.contains(cmd.getMessageId())) { - session.logPacket("RECV in Union", cmdOpcode, cmdPayload); - } - //debugLevel ALL ignores UnionCmdNotify, so we will also ignore the contained opcodes - session.getServer().getPacketHandler().handle(session, cmd.getMessageId(), EMPTY_BYTE_ARRAY, cmd.getBody().toByteArray()); - } - - // Update - session.getPlayer().getCombatInvokeHandler().update(session.getPlayer()); - session.getPlayer().getAbilityInvokeHandler().update(session.getPlayer()); - - // Handle attack results last - while (!session.getPlayer().getAttackResults().isEmpty()) { - session.getPlayer().getScene().handleAttack(session.getPlayer().getAttackResults().poll()); - } - } -} +package emu.grasscutter.server.packet.recv; + +import static emu.grasscutter.config.Configuration.GAME_INFO; +import static emu.grasscutter.config.Configuration.SERVER; + +import emu.grasscutter.Grasscutter.ServerDebugMode; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnionCmdNotifyOuterClass.UnionCmdNotify; +import emu.grasscutter.net.proto.UnionCmdOuterClass.UnionCmd; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.UnionCmdNotify) +public class HandlerUnionCmdNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + UnionCmdNotify req = UnionCmdNotify.parseFrom(payload); + for (UnionCmd cmd : req.getCmdListList()) { + int cmdOpcode = cmd.getMessageId(); + byte[] cmdPayload = cmd.getBody().toByteArray(); + if (GAME_INFO.logPackets == ServerDebugMode.WHITELIST + && SERVER.debugWhitelist.contains(cmd.getMessageId())) { + session.logPacket("RECV in Union", cmdOpcode, cmdPayload); + } else if (GAME_INFO.logPackets == ServerDebugMode.BLACKLIST + && !SERVER.debugBlacklist.contains(cmd.getMessageId())) { + session.logPacket("RECV in Union", cmdOpcode, cmdPayload); + } + // debugLevel ALL ignores UnionCmdNotify, so we will also ignore the contained opcodes + session + .getServer() + .getPacketHandler() + .handle(session, cmd.getMessageId(), EMPTY_BYTE_ARRAY, cmd.getBody().toByteArray()); + } + + // Update + session.getPlayer().getCombatInvokeHandler().update(session.getPlayer()); + session.getPlayer().getAbilityInvokeHandler().update(session.getPlayer()); + + // Handle attack results last + while (!session.getPlayer().getAttackResults().isEmpty()) { + session.getPlayer().getScene().handleAttack(session.getPlayer().getAttackResults().poll()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockAvatarTalentReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockAvatarTalentReq.java index 8ee470fb0..ef465bc01 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockAvatarTalentReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockAvatarTalentReq.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockAvatarTalentReqOuterClass.UnlockAvatarTalentReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.UnlockAvatarTalentReq) -public class HandlerUnlockAvatarTalentReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - UnlockAvatarTalentReq req = UnlockAvatarTalentReq.parseFrom(payload); - - // Unlock avatar const - var avatar = session.getPlayer().getAvatars().getAvatarByGuid(req.getAvatarGuid()); - if (avatar == null) return; - avatar.unlockConstellation(req.getTalentId()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockAvatarTalentReqOuterClass.UnlockAvatarTalentReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.UnlockAvatarTalentReq) +public class HandlerUnlockAvatarTalentReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + UnlockAvatarTalentReq req = UnlockAvatarTalentReq.parseFrom(payload); + + // Unlock avatar const + var avatar = session.getPlayer().getAvatars().getAvatarByGuid(req.getAvatarGuid()); + if (avatar == null) return; + avatar.unlockConstellation(req.getTalentId()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockPersonalLineReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockPersonalLineReq.java index 3ba034ed4..4e4aa384d 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockPersonalLineReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockPersonalLineReq.java @@ -1,28 +1,27 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockPersonalLineReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketUnlockPersonalLineRsp; - -@Opcodes(PacketOpcodes.UnlockPersonalLineReq) -public class HandlerUnlockPersonalLineReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = UnlockPersonalLineReqOuterClass.UnlockPersonalLineReq.parseFrom(payload); - var data = GameData.getPersonalLineDataMap().get(req.getPersonalLineId()); - if (data == null) { - return; - } - - session.getPlayer().getQuestManager().addQuest(data.getStartQuestId()); - session.getPlayer().useLegendaryKey(1); - - session.send(new PacketUnlockPersonalLineRsp(data.getId(), 1, data.getChapterId())); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockPersonalLineReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketUnlockPersonalLineRsp; + +@Opcodes(PacketOpcodes.UnlockPersonalLineReq) +public class HandlerUnlockPersonalLineReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = UnlockPersonalLineReqOuterClass.UnlockPersonalLineReq.parseFrom(payload); + var data = GameData.getPersonalLineDataMap().get(req.getPersonalLineId()); + if (data == null) { + return; + } + + session.getPlayer().getQuestManager().addQuest(data.getStartQuestId()); + session.getPlayer().useLegendaryKey(1); + + session.send(new PacketUnlockPersonalLineRsp(data.getId(), 1, data.getChapterId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockTransPointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockTransPointReq.java index 2b56e78a8..79ba77681 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockTransPointReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnlockTransPointReq.java @@ -1,19 +1,29 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.UnlockTransPointReqOuterClass.UnlockTransPointReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketUnlockTransPointRsp; - -@Opcodes(PacketOpcodes.UnlockTransPointReq) -public class HandlerUnlockTransPointReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - UnlockTransPointReq req = UnlockTransPointReq.parseFrom(payload); - boolean unlocked = session.getPlayer().getProgressManager().unlockTransPoint(req.getSceneId(), req.getPointId(), false); - session.getPlayer().sendPacket(new PacketUnlockTransPointRsp(unlocked ? RetcodeOuterClass.Retcode.RET_SUCC : RetcodeOuterClass.Retcode.RET_FAIL)); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.UnlockTransPointReqOuterClass.UnlockTransPointReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketUnlockTransPointRsp; + +@Opcodes(PacketOpcodes.UnlockTransPointReq) +public class HandlerUnlockTransPointReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + UnlockTransPointReq req = UnlockTransPointReq.parseFrom(payload); + boolean unlocked = + session + .getPlayer() + .getProgressManager() + .unlockTransPoint(req.getSceneId(), req.getPointId(), false); + session + .getPlayer() + .sendPacket( + new PacketUnlockTransPointRsp( + unlocked + ? RetcodeOuterClass.Retcode.RET_SUCC + : RetcodeOuterClass.Retcode.RET_FAIL)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdateAbilityCreatedMovingPlatformNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdateAbilityCreatedMovingPlatformNotify.java index f67a6cf3a..0b69fe145 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdateAbilityCreatedMovingPlatformNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdateAbilityCreatedMovingPlatformNotify.java @@ -1,32 +1,34 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.platform.EntityPlatform; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UpdateAbilityCreatedMovingPlatformNotifyOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketPlatformStartRouteNotify; -import emu.grasscutter.server.packet.send.PacketPlatformStopRouteNotify; - -@Opcodes(PacketOpcodes.UpdateAbilityCreatedMovingPlatformNotify) -public class HandlerUpdateAbilityCreatedMovingPlatformNotify extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var notify = UpdateAbilityCreatedMovingPlatformNotifyOuterClass.UpdateAbilityCreatedMovingPlatformNotify.parseFrom(payload); - var entity = session.getPlayer().getScene().getEntityById(notify.getEntityId()); - - if (!(entity instanceof EntityPlatform)) { - return; - } - - var scene = ((EntityPlatform) entity).getOwner().getScene(); - - switch (notify.getOpType()) { - case OP_TYPE_ACTIVATE -> - scene.broadcastPacket(new PacketPlatformStartRouteNotify((EntityPlatform) entity, scene)); - case OP_TYPE_DEACTIVATE -> - scene.broadcastPacket(new PacketPlatformStopRouteNotify((EntityPlatform) entity, scene)); - } - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.platform.EntityPlatform; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UpdateAbilityCreatedMovingPlatformNotifyOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPlatformStartRouteNotify; +import emu.grasscutter.server.packet.send.PacketPlatformStopRouteNotify; + +@Opcodes(PacketOpcodes.UpdateAbilityCreatedMovingPlatformNotify) +public class HandlerUpdateAbilityCreatedMovingPlatformNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var notify = + UpdateAbilityCreatedMovingPlatformNotifyOuterClass.UpdateAbilityCreatedMovingPlatformNotify + .parseFrom(payload); + var entity = session.getPlayer().getScene().getEntityById(notify.getEntityId()); + + if (!(entity instanceof EntityPlatform)) { + return; + } + + var scene = ((EntityPlatform) entity).getOwner().getScene(); + + switch (notify.getOpType()) { + case OP_TYPE_ACTIVATE -> scene.broadcastPacket( + new PacketPlatformStartRouteNotify((EntityPlatform) entity, scene)); + case OP_TYPE_DEACTIVATE -> scene.broadcastPacket( + new PacketPlatformStopRouteNotify((EntityPlatform) entity, scene)); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowAvatarListReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowAvatarListReq.java index 47e88aa12..0dbdf130a 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowAvatarListReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowAvatarListReq.java @@ -1,21 +1,24 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UpdatePlayerShowAvatarListReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketUpdatePlayerShowAvatarListRsp; - -@Opcodes(PacketOpcodes.UpdatePlayerShowAvatarListReq) -public class HandlerUpdatePlayerShowAvatarListReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - UpdatePlayerShowAvatarListReqOuterClass.UpdatePlayerShowAvatarListReq req = UpdatePlayerShowAvatarListReqOuterClass.UpdatePlayerShowAvatarListReq.parseFrom(payload); - - session.getPlayer().setShowAvatars(req.getIsShowAvatar()); - session.getPlayer().setShowAvatarList(req.getShowAvatarIdListList()); - - session.send(new PacketUpdatePlayerShowAvatarListRsp(req.getIsShowAvatar(), req.getShowAvatarIdListList())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UpdatePlayerShowAvatarListReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketUpdatePlayerShowAvatarListRsp; + +@Opcodes(PacketOpcodes.UpdatePlayerShowAvatarListReq) +public class HandlerUpdatePlayerShowAvatarListReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + UpdatePlayerShowAvatarListReqOuterClass.UpdatePlayerShowAvatarListReq req = + UpdatePlayerShowAvatarListReqOuterClass.UpdatePlayerShowAvatarListReq.parseFrom(payload); + + session.getPlayer().setShowAvatars(req.getIsShowAvatar()); + session.getPlayer().setShowAvatarList(req.getShowAvatarIdListList()); + + session.send( + new PacketUpdatePlayerShowAvatarListRsp( + req.getIsShowAvatar(), req.getShowAvatarIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowNameCardListReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowNameCardListReq.java index 6d5242b97..919e1f6ec 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowNameCardListReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUpdatePlayerShowNameCardListReq.java @@ -1,20 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UpdatePlayerShowNameCardListReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketUpdatePlayerShowNameCardListRsp; - -@Opcodes(PacketOpcodes.UpdatePlayerShowNameCardListReq) -public class HandlerUpdatePlayerShowNameCardListReq extends PacketHandler { - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - var req = UpdatePlayerShowNameCardListReqOuterClass.UpdatePlayerShowNameCardListReq.parseFrom(payload); - - session.getPlayer().setShowNameCardList(req.getShowNameCardIdListList()); - - session.send(new PacketUpdatePlayerShowNameCardListRsp(req.getShowNameCardIdListList())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UpdatePlayerShowNameCardListReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketUpdatePlayerShowNameCardListRsp; + +@Opcodes(PacketOpcodes.UpdatePlayerShowNameCardListReq) +public class HandlerUpdatePlayerShowNameCardListReq extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + var req = + UpdatePlayerShowNameCardListReqOuterClass.UpdatePlayerShowNameCardListReq.parseFrom( + payload); + + session.getPlayer().setShowNameCardList(req.getShowNameCardIdListList()); + + session.send(new PacketUpdatePlayerShowNameCardListRsp(req.getShowNameCardIdListList())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java index 171c2d77c..3c0fa93a4 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUseItemReq.java @@ -1,26 +1,35 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UseItemReqOuterClass.UseItemReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketUseItemRsp; - -@Opcodes(PacketOpcodes.UseItemReq) -public class HandlerUseItemReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - UseItemReq req = UseItemReq.parseFrom(payload); - - GameItem useItem = session.getServer().getInventorySystem().useItem(session.getPlayer(), req.getTargetGuid(), req.getGuid(), req.getCount(), req.getOptionIdx(), req.getIsEnterMpDungeonTeam()); - if (useItem != null) { - session.send(new PacketUseItemRsp(req.getTargetGuid(), useItem)); - } else { - session.send(new PacketUseItemRsp()); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UseItemReqOuterClass.UseItemReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketUseItemRsp; + +@Opcodes(PacketOpcodes.UseItemReq) +public class HandlerUseItemReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + UseItemReq req = UseItemReq.parseFrom(payload); + + GameItem useItem = + session + .getServer() + .getInventorySystem() + .useItem( + session.getPlayer(), + req.getTargetGuid(), + req.getGuid(), + req.getCount(), + req.getOptionIdx(), + req.getIsEnterMpDungeonTeam()); + if (useItem != null) { + session.send(new PacketUseItemRsp(req.getTargetGuid(), useItem)); + } else { + session.send(new PacketUseItemRsp()); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java index ba55bbc0f..c8a4e6ba5 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java @@ -1,19 +1,25 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.VehicleInteractReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketVehicleInteractRsp; - -@Opcodes(PacketOpcodes.VehicleInteractReq) -public class HandlerVehicleInteractReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - VehicleInteractReqOuterClass.VehicleInteractReq req = VehicleInteractReqOuterClass.VehicleInteractReq.parseFrom(payload); - session.getPlayer().getStaminaManager().handleVehicleInteractReq(session, req.getEntityId(), req.getInteractType()); - session.send(new PacketVehicleInteractRsp(session.getPlayer(), req.getEntityId(), req.getInteractType())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VehicleInteractReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketVehicleInteractRsp; + +@Opcodes(PacketOpcodes.VehicleInteractReq) +public class HandlerVehicleInteractReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + VehicleInteractReqOuterClass.VehicleInteractReq req = + VehicleInteractReqOuterClass.VehicleInteractReq.parseFrom(payload); + session + .getPlayer() + .getStaminaManager() + .handleVehicleInteractReq(session, req.getEntityId(), req.getInteractType()); + session.send( + new PacketVehicleInteractRsp( + session.getPlayer(), req.getEntityId(), req.getInteractType())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponAwakenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponAwakenReq.java index 56b0b7166..80078bbb3 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponAwakenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponAwakenReq.java @@ -1,20 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WeaponAwakenReqOuterClass.WeaponAwakenReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.WeaponAwakenReq) -public class HandlerWeaponAwakenReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - WeaponAwakenReq req = WeaponAwakenReq.parseFrom(payload); - - // Weapon refinement - session.getServer().getInventorySystem().refineWeapon(session.getPlayer(), req.getTargetWeaponGuid(), req.getItemGuid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WeaponAwakenReqOuterClass.WeaponAwakenReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.WeaponAwakenReq) +public class HandlerWeaponAwakenReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WeaponAwakenReq req = WeaponAwakenReq.parseFrom(payload); + + // Weapon refinement + session + .getServer() + .getInventorySystem() + .refineWeapon(session.getPlayer(), req.getTargetWeaponGuid(), req.getItemGuid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponPromoteReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponPromoteReq.java index ac631f5fc..1c2b5d927 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponPromoteReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponPromoteReq.java @@ -1,20 +1,22 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WeaponPromoteReqOuterClass.WeaponPromoteReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.WeaponPromoteReq) -public class HandlerWeaponPromoteReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - WeaponPromoteReq req = WeaponPromoteReq.parseFrom(payload); - - // Ascend weapon - session.getServer().getInventorySystem().promoteWeapon(session.getPlayer(), req.getTargetWeaponGuid()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WeaponPromoteReqOuterClass.WeaponPromoteReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.WeaponPromoteReq) +public class HandlerWeaponPromoteReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WeaponPromoteReq req = WeaponPromoteReq.parseFrom(payload); + + // Ascend weapon + session + .getServer() + .getInventorySystem() + .promoteWeapon(session.getPlayer(), req.getTargetWeaponGuid()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponUpgradeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponUpgradeReq.java index 047d0e221..cc99dbb5f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponUpgradeReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWeaponUpgradeReq.java @@ -1,25 +1,26 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WeaponUpgradeReqOuterClass.WeaponUpgradeReq; -import emu.grasscutter.server.game.GameSession; - -@Opcodes(PacketOpcodes.WeaponUpgradeReq) -public class HandlerWeaponUpgradeReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - WeaponUpgradeReq req = WeaponUpgradeReq.parseFrom(payload); - - // Level up weapon - session.getServer().getInventorySystem().upgradeWeapon( - session.getPlayer(), - req.getTargetWeaponGuid(), - req.getFoodWeaponGuidListList(), - req.getItemParamListList() - ); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WeaponUpgradeReqOuterClass.WeaponUpgradeReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.WeaponUpgradeReq) +public class HandlerWeaponUpgradeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WeaponUpgradeReq req = WeaponUpgradeReq.parseFrom(payload); + + // Level up weapon + session + .getServer() + .getInventorySystem() + .upgradeWeapon( + session.getPlayer(), + req.getTargetWeaponGuid(), + req.getFoodWeaponGuidListList(), + req.getItemParamListList()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWearEquipReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWearEquipReq.java index c6eee8bb3..2af2fbe45 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWearEquipReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWearEquipReq.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WearEquipReqOuterClass.WearEquipReq; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketWearEquipRsp; - -@Opcodes(PacketOpcodes.WearEquipReq) -public class HandlerWearEquipReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - WearEquipReq req = WearEquipReq.parseFrom(payload); - - if (session.getPlayer().getInventory().equipItem(req.getAvatarGuid(), req.getEquipGuid())) { - session.send(new PacketWearEquipRsp(req.getAvatarGuid(), req.getEquipGuid())); - } - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WearEquipReqOuterClass.WearEquipReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketWearEquipRsp; + +@Opcodes(PacketOpcodes.WearEquipReq) +public class HandlerWearEquipReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WearEquipReq req = WearEquipReq.parseFrom(payload); + + if (session.getPlayer().getInventory().equipItem(req.getAvatarGuid(), req.getEquipGuid())) { + session.send(new PacketWearEquipRsp(req.getAvatarGuid(), req.getEquipGuid())); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java index a9b9d0966..1fe08a42c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java @@ -1,43 +1,44 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.game.entity.EntityVehicle; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WidgetDoBagReqOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketWidgetCoolDownNotify; -import emu.grasscutter.server.packet.send.PacketWidgetDoBagRsp; -import emu.grasscutter.server.packet.send.PacketWidgetGadgetDataNotify; -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.WidgetDoBagReq) -public class HandlerWidgetDoBagReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - WidgetDoBagReqOuterClass.WidgetDoBagReq req = WidgetDoBagReqOuterClass.WidgetDoBagReq.parseFrom(payload); - var locationInfo = req.getWidgetCreatorInfo().getLocationInfo(); - Position pos = new Position(locationInfo.getPos()); - Position rot = new Position(locationInfo.getRot()); - switch (req.getMaterialId()) { - case 220026 -> { - this.spawnVehicle(session, 70500025, pos, rot); - session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); - session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); - } - case 220047 -> this.spawnVehicle(session, 70800058, pos, rot); - default -> { - } - } - session.send(new PacketWidgetDoBagRsp()); - } - - private void spawnVehicle(GameSession session, int gadgetId, Position pos, Position rot) throws Exception { - var player = session.getPlayer(); - var scene = player.getScene(); - var entity = new EntityVehicle(scene, player, gadgetId, 0, pos, rot); - scene.addEntity(entity); - session.send(new PacketWidgetGadgetDataNotify(gadgetId, entity.getId())); - } -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetDoBagReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketWidgetCoolDownNotify; +import emu.grasscutter.server.packet.send.PacketWidgetDoBagRsp; +import emu.grasscutter.server.packet.send.PacketWidgetGadgetDataNotify; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.WidgetDoBagReq) +public class HandlerWidgetDoBagReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WidgetDoBagReqOuterClass.WidgetDoBagReq req = + WidgetDoBagReqOuterClass.WidgetDoBagReq.parseFrom(payload); + var locationInfo = req.getWidgetCreatorInfo().getLocationInfo(); + Position pos = new Position(locationInfo.getPos()); + Position rot = new Position(locationInfo.getRot()); + switch (req.getMaterialId()) { + case 220026 -> { + this.spawnVehicle(session, 70500025, pos, rot); + session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); + session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); + } + case 220047 -> this.spawnVehicle(session, 70800058, pos, rot); + default -> {} + } + session.send(new PacketWidgetDoBagRsp()); + } + + private void spawnVehicle(GameSession session, int gadgetId, Position pos, Position rot) + throws Exception { + var player = session.getPlayer(); + var scene = player.getScene(); + var entity = new EntityVehicle(scene, player, gadgetId, 0, pos, rot); + scene.addEntity(entity); + session.send(new PacketWidgetGadgetDataNotify(gadgetId, entity.getId())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWorldPlayerReviveReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWorldPlayerReviveReq.java index 1b52e695e..b5d4f1b01 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWorldPlayerReviveReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWorldPlayerReviveReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketWorldPlayerReviveRsp; - -@Opcodes(PacketOpcodes.WorldPlayerReviveReq) -public class HandlerWorldPlayerReviveReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.getPlayer().getTeamManager().respawnTeam(); - session.send(new PacketWorldPlayerReviveRsp()); - } - -} +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketWorldPlayerReviveRsp; + +@Opcodes(PacketOpcodes.WorldPlayerReviveReq) +public class HandlerWorldPlayerReviveReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + session.getPlayer().getTeamManager().respawnTeam(); + session.send(new PacketWorldPlayerReviveRsp()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PackageTakeCompoundOutputRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PackageTakeCompoundOutputRsp.java index 0ac763bc0..df187ccdd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PackageTakeCompoundOutputRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PackageTakeCompoundOutputRsp.java @@ -1,17 +1,15 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.TakeCompoundOutputRspOuterClass.TakeCompoundOutputRsp; - -public class PackageTakeCompoundOutputRsp extends BasePacket { - - public PackageTakeCompoundOutputRsp(Iterable itemList, int retcode) { - super(PacketOpcodes.TakeCompoundOutputRsp); - var builder = TakeCompoundOutputRsp.newBuilder() - .addAllItemList(itemList) - .setRetcode(retcode); - setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.TakeCompoundOutputRspOuterClass.TakeCompoundOutputRsp; + +public class PackageTakeCompoundOutputRsp extends BasePacket { + + public PackageTakeCompoundOutputRsp(Iterable itemList, int retcode) { + super(PacketOpcodes.TakeCompoundOutputRsp); + var builder = TakeCompoundOutputRsp.newBuilder().addAllItemList(itemList).setRetcode(retcode); + setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/Packet.java b/src/main/java/emu/grasscutter/server/packet/send/Packet.java index 89e459375..d9007f8a2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/Packet.java +++ b/src/main/java/emu/grasscutter/server/packet/send/Packet.java @@ -1,12 +1,11 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class Packet extends BasePacket { - - public Packet() { - super(PacketOpcodes.NONE); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class Packet extends BasePacket { + + public Packet() { + super(PacketOpcodes.NONE); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java index 0a863cc09..b00c0dd67 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityChangeNotifyOuterClass.AbilityChangeNotify; - -public class PacketAbilityChangeNotify extends BasePacket { - - public PacketAbilityChangeNotify(EntityAvatar entity) { - super(PacketOpcodes.AbilityChangeNotify, true); - - AbilityChangeNotify proto = AbilityChangeNotify.newBuilder() - .setEntityId(entity.getId()) - .setAbilityControlBlock(entity.getAbilityControlBlock()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityChangeNotifyOuterClass.AbilityChangeNotify; + +public class PacketAbilityChangeNotify extends BasePacket { + + public PacketAbilityChangeNotify(EntityAvatar entity) { + super(PacketOpcodes.AbilityChangeNotify, true); + + AbilityChangeNotify proto = + AbilityChangeNotify.newBuilder() + .setEntityId(entity.getId()) + .setAbilityControlBlock(entity.getAbilityControlBlock()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityInvocationsNotify.java index 3b97ce10a..3cc4dfe83 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityInvocationsNotify.java @@ -1,32 +1,28 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; - -import java.util.List; - -public class PacketAbilityInvocationsNotify extends BasePacket { - - public PacketAbilityInvocationsNotify(AbilityInvokeEntry entry) { - super(PacketOpcodes.AbilityInvocationsNotify, true); - - AbilityInvocationsNotify proto = AbilityInvocationsNotify.newBuilder() - .addInvokes(entry) - .build(); - - this.setData(proto); - } - - public PacketAbilityInvocationsNotify(List entries) { - super(PacketOpcodes.AbilityInvocationsNotify, true); - - AbilityInvocationsNotify proto = AbilityInvocationsNotify.newBuilder() - .addAllInvokes(entries) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import java.util.List; + +public class PacketAbilityInvocationsNotify extends BasePacket { + + public PacketAbilityInvocationsNotify(AbilityInvokeEntry entry) { + super(PacketOpcodes.AbilityInvocationsNotify, true); + + AbilityInvocationsNotify proto = + AbilityInvocationsNotify.newBuilder().addInvokes(entry).build(); + + this.setData(proto); + } + + public PacketAbilityInvocationsNotify(List entries) { + super(PacketOpcodes.AbilityInvocationsNotify, true); + + AbilityInvocationsNotify proto = + AbilityInvocationsNotify.newBuilder().addAllInvokes(entries).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementAllDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementAllDataNotify.java index 912c03a29..422f35e27 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementAllDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementAllDataNotify.java @@ -1,21 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.achievement.Achievement; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AchievementAllDataNotifyOuterClass; - -public class PacketAchievementAllDataNotify extends BasePacket { - public PacketAchievementAllDataNotify(Player player) { - super(PacketOpcodes.AchievementAllDataNotify); - - var achievements = player.getAchievements(); - var notify = AchievementAllDataNotifyOuterClass.AchievementAllDataNotify.newBuilder() - .addAllAchievementList(achievements.getAchievementList().values().stream().map(Achievement::toProto).toList()) - .addAllRewardTakenGoalIdList(achievements.getTakenGoalRewardIdList()) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.achievement.Achievement; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AchievementAllDataNotifyOuterClass; + +public class PacketAchievementAllDataNotify extends BasePacket { + public PacketAchievementAllDataNotify(Player player) { + super(PacketOpcodes.AchievementAllDataNotify); + + var achievements = player.getAchievements(); + var notify = + AchievementAllDataNotifyOuterClass.AchievementAllDataNotify.newBuilder() + .addAllAchievementList( + achievements.getAchievementList().values().stream() + .map(Achievement::toProto) + .toList()) + .addAllRewardTakenGoalIdList(achievements.getTakenGoalRewardIdList()) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementUpdateNotify.java index c9bd7196c..8eb02570d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAchievementUpdateNotify.java @@ -1,20 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.achievement.Achievement; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AchievementUpdateNotifyOuterClass; - -import java.util.List; - -public class PacketAchievementUpdateNotify extends BasePacket { - public PacketAchievementUpdateNotify(List achievements) { - super(PacketOpcodes.AchievementUpdateNotify); - - var notify = AchievementUpdateNotifyOuterClass.AchievementUpdateNotify.newBuilder() - .addAllAchievementList(achievements.stream().map(Achievement::toProto).toList()) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.achievement.Achievement; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AchievementUpdateNotifyOuterClass; +import java.util.List; + +public class PacketAchievementUpdateNotify extends BasePacket { + public PacketAchievementUpdateNotify(List achievements) { + super(PacketOpcodes.AchievementUpdateNotify); + + var notify = + AchievementUpdateNotifyOuterClass.AchievementUpdateNotify.newBuilder() + .addAllAchievementList(achievements.stream().map(Achievement::toProto).toList()) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityInfoNotify.java index a11e6ec51..d6b014b5d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityInfoNotify.java @@ -1,19 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityInfoNotifyOuterClass; -import emu.grasscutter.net.proto.ActivityInfoOuterClass; - -public class PacketActivityInfoNotify extends BasePacket { - - public PacketActivityInfoNotify(ActivityInfoOuterClass.ActivityInfo activityInfo) { - super(PacketOpcodes.ActivityInfoNotify); - - var proto = ActivityInfoNotifyOuterClass.ActivityInfoNotify.newBuilder(); - - proto.setActivityInfo(activityInfo); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityInfoNotifyOuterClass; +import emu.grasscutter.net.proto.ActivityInfoOuterClass; + +public class PacketActivityInfoNotify extends BasePacket { + + public PacketActivityInfoNotify(ActivityInfoOuterClass.ActivityInfo activityInfo) { + super(PacketOpcodes.ActivityInfoNotify); + + var proto = ActivityInfoNotifyOuterClass.ActivityInfoNotify.newBuilder(); + + proto.setActivityInfo(activityInfo); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityScheduleInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityScheduleInfoNotify.java index bdeba61da..4b78eba53 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityScheduleInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityScheduleInfoNotify.java @@ -1,31 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.activity.ActivityConfigItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityScheduleInfoNotifyOuterClass; -import emu.grasscutter.net.proto.ActivityScheduleInfoOuterClass; -import emu.grasscutter.utils.DateHelper; - -import java.util.Collection; - -public class PacketActivityScheduleInfoNotify extends BasePacket { - - public PacketActivityScheduleInfoNotify(Collection activityConfigItemList) { - super(PacketOpcodes.ActivityScheduleInfoNotify); - - var proto = ActivityScheduleInfoNotifyOuterClass.ActivityScheduleInfoNotify.newBuilder(); - - activityConfigItemList.forEach(item -> { - proto.addActivityScheduleList(ActivityScheduleInfoOuterClass.ActivityScheduleInfo.newBuilder() - .setActivityId(item.getActivityId()) - .setScheduleId(item.getScheduleId()) - .setIsOpen(true) - .setBeginTime(DateHelper.getUnixTime(item.getBeginTime())) - .setEndTime(DateHelper.getUnixTime(item.getEndTime())) - .build()); - }); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.activity.ActivityConfigItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityScheduleInfoNotifyOuterClass; +import emu.grasscutter.net.proto.ActivityScheduleInfoOuterClass; +import emu.grasscutter.utils.DateHelper; +import java.util.Collection; + +public class PacketActivityScheduleInfoNotify extends BasePacket { + + public PacketActivityScheduleInfoNotify(Collection activityConfigItemList) { + super(PacketOpcodes.ActivityScheduleInfoNotify); + + var proto = ActivityScheduleInfoNotifyOuterClass.ActivityScheduleInfoNotify.newBuilder(); + + activityConfigItemList.forEach( + item -> { + proto.addActivityScheduleList( + ActivityScheduleInfoOuterClass.ActivityScheduleInfo.newBuilder() + .setActivityId(item.getActivityId()) + .setScheduleId(item.getScheduleId()) + .setIsOpen(true) + .setBeginTime(DateHelper.getUnixTime(item.getBeginTime())) + .setEndTime(DateHelper.getUnixTime(item.getEndTime())) + .build()); + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityTakeWatcherRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityTakeWatcherRewardRsp.java index 69439045a..e723a225d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityTakeWatcherRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityTakeWatcherRewardRsp.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityTakeWatcherRewardRspOuterClass; - -public class PacketActivityTakeWatcherRewardRsp extends BasePacket { - - public PacketActivityTakeWatcherRewardRsp(int activityId, int watcherId) { - super(PacketOpcodes.ActivityTakeWatcherRewardRsp); - - var proto = ActivityTakeWatcherRewardRspOuterClass.ActivityTakeWatcherRewardRsp.newBuilder(); - - proto.setActivityId(activityId) - .setWatcherId(watcherId); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityTakeWatcherRewardRspOuterClass; + +public class PacketActivityTakeWatcherRewardRsp extends BasePacket { + + public PacketActivityTakeWatcherRewardRsp(int activityId, int watcherId) { + super(PacketOpcodes.ActivityTakeWatcherRewardRsp); + + var proto = ActivityTakeWatcherRewardRspOuterClass.ActivityTakeWatcherRewardRsp.newBuilder(); + + proto.setActivityId(activityId).setWatcherId(watcherId); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityUpdateWatcherNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityUpdateWatcherNotify.java index fc0720ca8..0a5c3b205 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketActivityUpdateWatcherNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketActivityUpdateWatcherNotify.java @@ -1,20 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.activity.PlayerActivityData; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityUpdateWatcherNotifyOuterClass; - -public class PacketActivityUpdateWatcherNotify extends BasePacket { - - public PacketActivityUpdateWatcherNotify(int activityId, PlayerActivityData.WatcherInfo watcherInfo) { - super(PacketOpcodes.ActivityUpdateWatcherNotify); - - var proto = ActivityUpdateWatcherNotifyOuterClass.ActivityUpdateWatcherNotify.newBuilder(); - - proto.setActivityId(activityId) - .setWatcherInfo(watcherInfo.toProto()); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.activity.PlayerActivityData; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityUpdateWatcherNotifyOuterClass; + +public class PacketActivityUpdateWatcherNotify extends BasePacket { + + public PacketActivityUpdateWatcherNotify( + int activityId, PlayerActivityData.WatcherInfo watcherInfo) { + super(PacketOpcodes.ActivityUpdateWatcherNotify); + + var proto = ActivityUpdateWatcherNotifyOuterClass.ActivityUpdateWatcherNotify.newBuilder(); + + proto.setActivityId(activityId).setWatcherInfo(watcherInfo.toProto()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAddBackupAvatarTeamRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAddBackupAvatarTeamRsp.java index 630994149..10f3bbd4d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAddBackupAvatarTeamRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAddBackupAvatarTeamRsp.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AddBackupAvatarTeamRspOuterClass.AddBackupAvatarTeamRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -public class PacketAddBackupAvatarTeamRsp extends BasePacket { - public PacketAddBackupAvatarTeamRsp(Retcode retcode) { - super(PacketOpcodes.AddBackupAvatarTeamRsp); - - AddBackupAvatarTeamRsp proto = AddBackupAvatarTeamRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(proto); - } - - public PacketAddBackupAvatarTeamRsp() { - this(Retcode.RET_SUCC); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AddBackupAvatarTeamRspOuterClass.AddBackupAvatarTeamRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; + +public class PacketAddBackupAvatarTeamRsp extends BasePacket { + public PacketAddBackupAvatarTeamRsp(Retcode retcode) { + super(PacketOpcodes.AddBackupAvatarTeamRsp); + + AddBackupAvatarTeamRsp proto = + AddBackupAvatarTeamRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } + + public PacketAddBackupAvatarTeamRsp() { + this(Retcode.RET_SUCC); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAddQuestContentProgressRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAddQuestContentProgressRsp.java index 3221db7b4..0405052b1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAddQuestContentProgressRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAddQuestContentProgressRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AddQuestContentProgressRspOuterClass; - -public class PacketAddQuestContentProgressRsp extends BasePacket { - - public PacketAddQuestContentProgressRsp(int contentType) { - super(PacketOpcodes.AddQuestContentProgressRsp); - - var proto = AddQuestContentProgressRspOuterClass.AddQuestContentProgressRsp.newBuilder(); - - proto.setContentType(contentType); - - this.setData(proto); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AddQuestContentProgressRspOuterClass; + +public class PacketAddQuestContentProgressRsp extends BasePacket { + + public PacketAddQuestContentProgressRsp(int contentType) { + super(PacketOpcodes.AddQuestContentProgressRsp); + + var proto = AddQuestContentProgressRspOuterClass.AddQuestContentProgressRsp.newBuilder(); + + proto.setContentType(contentType); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java index 07d35bc24..0b2466c72 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java @@ -1,58 +1,55 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AllWidgetDataNotifyOuterClass.AllWidgetDataNotify; -import emu.grasscutter.net.proto.LunchBoxDataOuterClass; -import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; -import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; - -import java.util.List; - -public class PacketAllWidgetDataNotify extends BasePacket { - - public PacketAllWidgetDataNotify(Player player) { - super(PacketOpcodes.AllWidgetDataNotify); - - // TODO: Implement this - - AllWidgetDataNotify.Builder proto = AllWidgetDataNotify.newBuilder() - // If you want to implement this, feel free to do so. :) - .setLunchBoxData( - LunchBoxDataOuterClass.LunchBoxData.newBuilder().build() - ) - // Maybe it's a little difficult, or it makes you upset :( - .addAllOneoffGatherPointDetectorDataList(List.of()) - // So, goodbye, and hopefully sometime in the future o(* ̄▽ ̄*)ブ - .addAllCoolDownGroupDataList(List.of()) - // I'll see your PR with a title that says (・∀・(・∀・(・∀・*) - .addAllAnchorPointList(List.of()) - // "Complete implementation of widget functionality" b( ̄▽ ̄)d  - .addAllClientCollectorDataList(List.of()) - // Good luck, my boy. - .addAllNormalCoolDownDataList(List.of()); - - if (player.getWidgetId() == 0) { // TODO: check this logic later, it was null-checking an int before which made it dead code - proto.addAllSlotList(List.of()); - } else { - proto.addSlotList( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setIsActive(true) - .setMaterialId(player.getWidgetId()) - .build() - ); - - proto.addSlotList( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) - .build() - ); - } - - AllWidgetDataNotify protoData = proto.build(); - - this.setData(protoData); - } -} - +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AllWidgetDataNotifyOuterClass.AllWidgetDataNotify; +import emu.grasscutter.net.proto.LunchBoxDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; +import java.util.List; + +public class PacketAllWidgetDataNotify extends BasePacket { + + public PacketAllWidgetDataNotify(Player player) { + super(PacketOpcodes.AllWidgetDataNotify); + + // TODO: Implement this + + AllWidgetDataNotify.Builder proto = + AllWidgetDataNotify.newBuilder() + // If you want to implement this, feel free to do so. :) + .setLunchBoxData(LunchBoxDataOuterClass.LunchBoxData.newBuilder().build()) + // Maybe it's a little difficult, or it makes you upset :( + .addAllOneoffGatherPointDetectorDataList(List.of()) + // So, goodbye, and hopefully sometime in the future o(* ̄▽ ̄*)ブ + .addAllCoolDownGroupDataList(List.of()) + // I'll see your PR with a title that says (・∀・(・∀・(・∀・*) + .addAllAnchorPointList(List.of()) + // "Complete implementation of widget functionality" b( ̄▽ ̄)d + .addAllClientCollectorDataList(List.of()) + // Good luck, my boy. + .addAllNormalCoolDownDataList(List.of()); + + if (player.getWidgetId() + == 0) { // TODO: check this logic later, it was null-checking an int before which made it + // dead code + proto.addAllSlotList(List.of()); + } else { + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(player.getWidgetId()) + .build()); + + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) + .build()); + } + + AllWidgetDataNotify protoData = proto.build(); + + this.setData(protoData); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendNotify.java index 4d8186106..bd8b80069 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.friends.Friendship; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AskAddFriendNotifyOuterClass.AskAddFriendNotify; - -public class PacketAskAddFriendNotify extends BasePacket { - - public PacketAskAddFriendNotify(Friendship friendship) { - super(PacketOpcodes.AskAddFriendNotify); - - AskAddFriendNotify proto = AskAddFriendNotify.newBuilder() - .setTargetUid(friendship.getFriendId()) - .setTargetFriendBrief(friendship.toProto()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.friends.Friendship; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AskAddFriendNotifyOuterClass.AskAddFriendNotify; + +public class PacketAskAddFriendNotify extends BasePacket { + + public PacketAskAddFriendNotify(Friendship friendship) { + super(PacketOpcodes.AskAddFriendNotify); + + AskAddFriendNotify proto = + AskAddFriendNotify.newBuilder() + .setTargetUid(friendship.getFriendId()) + .setTargetFriendBrief(friendship.toProto()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendRsp.java index 255de6c68..3765baeb6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAskAddFriendRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AskAddFriendRspOuterClass.AskAddFriendRsp; - -public class PacketAskAddFriendRsp extends BasePacket { - - public PacketAskAddFriendRsp(int targetUid) { - super(PacketOpcodes.AskAddFriendRsp); - - AskAddFriendRsp proto = AskAddFriendRsp.newBuilder() - .setTargetUid(targetUid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AskAddFriendRspOuterClass.AskAddFriendRsp; + +public class PacketAskAddFriendRsp extends BasePacket { + + public PacketAskAddFriendRsp(int targetUid) { + super(PacketOpcodes.AskAddFriendRsp); + + AskAddFriendRsp proto = AskAddFriendRsp.newBuilder().setTargetUid(targetUid).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarAddNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarAddNotify.java index f44370de8..83736363f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarAddNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarAddNotify.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarAddNotifyOuterClass.AvatarAddNotify; - -public class PacketAvatarAddNotify extends BasePacket { - - public PacketAvatarAddNotify(Avatar avatar, boolean addedToTeam) { - super(PacketOpcodes.AvatarAddNotify); - - AvatarAddNotify proto = AvatarAddNotify.newBuilder() - .setAvatar(avatar.toProto()) - .setIsInTeam(addedToTeam) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarAddNotifyOuterClass.AvatarAddNotify; + +public class PacketAvatarAddNotify extends BasePacket { + + public PacketAvatarAddNotify(Avatar avatar, boolean addedToTeam) { + super(PacketOpcodes.AvatarAddNotify); + + AvatarAddNotify proto = + AvatarAddNotify.newBuilder().setAvatar(avatar.toProto()).setIsInTeam(addedToTeam).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeNotify.java index 5b15765fd..f5ee35b86 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeNotify.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarChangeCostumeNotifyOuterClass.AvatarChangeCostumeNotify; - -public class PacketAvatarChangeCostumeNotify extends BasePacket { - - public PacketAvatarChangeCostumeNotify(EntityAvatar entity) { - super(PacketOpcodes.AvatarChangeCostumeNotify); - - AvatarChangeCostumeNotify proto = AvatarChangeCostumeNotify.newBuilder() - .setEntityInfo(entity.toProto()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeCostumeNotifyOuterClass.AvatarChangeCostumeNotify; + +public class PacketAvatarChangeCostumeNotify extends BasePacket { + + public PacketAvatarChangeCostumeNotify(EntityAvatar entity) { + super(PacketOpcodes.AvatarChangeCostumeNotify); + + AvatarChangeCostumeNotify proto = + AvatarChangeCostumeNotify.newBuilder().setEntityInfo(entity.toProto()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeRsp.java index abf40cad6..a4752da07 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeCostumeRsp.java @@ -1,30 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarChangeCostumeRspOuterClass.AvatarChangeCostumeRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketAvatarChangeCostumeRsp extends BasePacket { - - public PacketAvatarChangeCostumeRsp(long avatarGuid, int costumeId) { - super(PacketOpcodes.AvatarChangeCostumeRsp); - - AvatarChangeCostumeRsp proto = AvatarChangeCostumeRsp.newBuilder() - .setAvatarGuid(avatarGuid) - .setCostumeId(costumeId) - .build(); - - this.setData(proto); - } - - public PacketAvatarChangeCostumeRsp() { - super(PacketOpcodes.AvatarChangeCostumeRsp); - - AvatarChangeCostumeRsp proto = AvatarChangeCostumeRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeCostumeRspOuterClass.AvatarChangeCostumeRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketAvatarChangeCostumeRsp extends BasePacket { + + public PacketAvatarChangeCostumeRsp(long avatarGuid, int costumeId) { + super(PacketOpcodes.AvatarChangeCostumeRsp); + + AvatarChangeCostumeRsp proto = + AvatarChangeCostumeRsp.newBuilder() + .setAvatarGuid(avatarGuid) + .setCostumeId(costumeId) + .build(); + + this.setData(proto); + } + + public PacketAvatarChangeCostumeRsp() { + super(PacketOpcodes.AvatarChangeCostumeRsp); + + AvatarChangeCostumeRsp proto = + AvatarChangeCostumeRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java index ddd3bc396..6e4af0e82 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarChangeElementTypeRspOuterClass.AvatarChangeElementTypeRsp; - -public class PacketAvatarChangeElementTypeRsp extends BasePacket { - - public PacketAvatarChangeElementTypeRsp() { - super(PacketOpcodes.AvatarChangeElementTypeRsp); - } - - public PacketAvatarChangeElementTypeRsp(int retcode) { - super(PacketOpcodes.AvatarChangeElementTypeRsp); - - if (retcode > 0) { - AvatarChangeElementTypeRsp proto = AvatarChangeElementTypeRsp.newBuilder() - .setRetcode(retcode) - .build(); - - this.setData(proto); - } - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeElementTypeRspOuterClass.AvatarChangeElementTypeRsp; + +public class PacketAvatarChangeElementTypeRsp extends BasePacket { + + public PacketAvatarChangeElementTypeRsp() { + super(PacketOpcodes.AvatarChangeElementTypeRsp); + } + + public PacketAvatarChangeElementTypeRsp(int retcode) { + super(PacketOpcodes.AvatarChangeElementTypeRsp); + + if (retcode > 0) { + AvatarChangeElementTypeRsp proto = + AvatarChangeElementTypeRsp.newBuilder().setRetcode(retcode).build(); + + this.setData(proto); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDataNotify.java index 2bf5c4fa6..a7fe8e845 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDataNotify.java @@ -1,38 +1,42 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarDataNotifyOuterClass.AvatarDataNotify; - -public class PacketAvatarDataNotify extends BasePacket { - - public PacketAvatarDataNotify(Player player) { - super(PacketOpcodes.AvatarDataNotify, true); - - AvatarDataNotify.Builder proto = AvatarDataNotify.newBuilder() - .setCurAvatarTeamId(player.getTeamManager().getCurrentTeamId()) - .setChooseAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()) - .addAllOwnedFlycloakList(player.getFlyCloakList()) - .addAllOwnedCostumeList(player.getCostumeList()); - - player.getAvatars().forEach(avatar -> proto.addAvatarList(avatar.toProto())); - - player.getTeamManager().getTeams().forEach((id, teamInfo) -> { - proto.putAvatarTeamMap(id, teamInfo.toProto(player)); - if (id > 4) { // Add the id list for custom teams. - proto.addBackupAvatarTeamOrderList(id); - } - }); - - // Set main character - Avatar mainCharacter = player.getAvatars().getAvatarById(player.getMainCharacterId()); - if (mainCharacter != null) { - proto.setChooseAvatarGuid(mainCharacter.getGuid()); - } - - this.setData(proto.build()); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarDataNotifyOuterClass.AvatarDataNotify; + +public class PacketAvatarDataNotify extends BasePacket { + + public PacketAvatarDataNotify(Player player) { + super(PacketOpcodes.AvatarDataNotify, true); + + AvatarDataNotify.Builder proto = + AvatarDataNotify.newBuilder() + .setCurAvatarTeamId(player.getTeamManager().getCurrentTeamId()) + .setChooseAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()) + .addAllOwnedFlycloakList(player.getFlyCloakList()) + .addAllOwnedCostumeList(player.getCostumeList()); + + player.getAvatars().forEach(avatar -> proto.addAvatarList(avatar.toProto())); + + player + .getTeamManager() + .getTeams() + .forEach( + (id, teamInfo) -> { + proto.putAvatarTeamMap(id, teamInfo.toProto(player)); + if (id > 4) { // Add the id list for custom teams. + proto.addBackupAvatarTeamOrderList(id); + } + }); + + // Set main character + Avatar mainCharacter = player.getAvatars().getAvatarById(player.getMainCharacterId()); + if (mainCharacter != null) { + proto.setChooseAvatarGuid(mainCharacter.getGuid()); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDieAnimationEndRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDieAnimationEndRsp.java index a118eb395..75f6f0480 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDieAnimationEndRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarDieAnimationEndRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarDieAnimationEndRspOuterClass.AvatarDieAnimationEndRsp; - -public class PacketAvatarDieAnimationEndRsp extends BasePacket { - - public PacketAvatarDieAnimationEndRsp(long dieGuid, int skillId) { - super(PacketOpcodes.AvatarDieAnimationEndRsp); - - AvatarDieAnimationEndRsp proto = AvatarDieAnimationEndRsp.newBuilder() - .setDieGuid(dieGuid) - .setSkillId(skillId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarDieAnimationEndRspOuterClass.AvatarDieAnimationEndRsp; + +public class PacketAvatarDieAnimationEndRsp extends BasePacket { + + public PacketAvatarDieAnimationEndRsp(long dieGuid, int skillId) { + super(PacketOpcodes.AvatarDieAnimationEndRsp); + + AvatarDieAnimationEndRsp proto = + AvatarDieAnimationEndRsp.newBuilder().setDieGuid(dieGuid).setSkillId(skillId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarEquipChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarEquipChangeNotify.java index 7304ccac3..410b8dbff 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarEquipChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarEquipChangeNotify.java @@ -1,39 +1,41 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.inventory.EquipType; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarEquipChangeNotifyOuterClass.AvatarEquipChangeNotify; - -public class PacketAvatarEquipChangeNotify extends BasePacket { - - public PacketAvatarEquipChangeNotify(Avatar avatar, GameItem item) { - super(PacketOpcodes.AvatarEquipChangeNotify); - - AvatarEquipChangeNotify.Builder proto = AvatarEquipChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEquipType(item.getEquipSlot()) - .setItemId(item.getItemId()) - .setEquipGuid(item.getGuid()); - - if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) { - proto.setWeapon(item.createSceneWeaponInfo()); - } else { - proto.setReliquary(item.createSceneReliquaryInfo()); - } - - this.setData(proto); - } - - public PacketAvatarEquipChangeNotify(Avatar avatar, EquipType slot) { - super(PacketOpcodes.AvatarEquipChangeNotify); - - AvatarEquipChangeNotify.Builder proto = AvatarEquipChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEquipType(slot.getValue()); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.inventory.EquipType; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarEquipChangeNotifyOuterClass.AvatarEquipChangeNotify; + +public class PacketAvatarEquipChangeNotify extends BasePacket { + + public PacketAvatarEquipChangeNotify(Avatar avatar, GameItem item) { + super(PacketOpcodes.AvatarEquipChangeNotify); + + AvatarEquipChangeNotify.Builder proto = + AvatarEquipChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEquipType(item.getEquipSlot()) + .setItemId(item.getItemId()) + .setEquipGuid(item.getGuid()); + + if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) { + proto.setWeapon(item.createSceneWeaponInfo()); + } else { + proto.setReliquary(item.createSceneReliquaryInfo()); + } + + this.setData(proto); + } + + public PacketAvatarEquipChangeNotify(Avatar avatar, EquipType slot) { + super(PacketOpcodes.AvatarEquipChangeNotify); + + AvatarEquipChangeNotify.Builder proto = + AvatarEquipChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEquipType(slot.getValue()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionAllDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionAllDataRsp.java index 5e78da953..3f6af6161 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionAllDataRsp.java @@ -1,28 +1,30 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionAllDataRspOuterClass.AvatarExpeditionAllDataRsp; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class PacketAvatarExpeditionAllDataRsp extends BasePacket { - public PacketAvatarExpeditionAllDataRsp(Map expeditionInfo, int expeditionCountLimit) { - super(PacketOpcodes.AvatarExpeditionAllDataRsp); - - var openExpeditionList = List.of(306, 305, 304, 303, 302, 301, 206, 105, 204, 104, 203, 103, 202, 101, 102, 201, 106, 205, 401, 402, 403, 404, 405, 406); - - this.setData(AvatarExpeditionAllDataRsp.newBuilder() - .addAllOpenExpeditionList(openExpeditionList) - .setExpeditionCountLimit(expeditionCountLimit) - .putAllExpeditionInfoMap( - expeditionInfo.entrySet().stream() - .collect(Collectors.toMap( - e -> e.getKey(), - e -> e.getValue().toProto()))) - .build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionAllDataRspOuterClass.AvatarExpeditionAllDataRsp; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PacketAvatarExpeditionAllDataRsp extends BasePacket { + public PacketAvatarExpeditionAllDataRsp( + Map expeditionInfo, int expeditionCountLimit) { + super(PacketOpcodes.AvatarExpeditionAllDataRsp); + + var openExpeditionList = + List.of( + 306, 305, 304, 303, 302, 301, 206, 105, 204, 104, 203, 103, 202, 101, 102, 201, 106, + 205, 401, 402, 403, 404, 405, 406); + + this.setData( + AvatarExpeditionAllDataRsp.newBuilder() + .addAllOpenExpeditionList(openExpeditionList) + .setExpeditionCountLimit(expeditionCountLimit) + .putAllExpeditionInfoMap( + expeditionInfo.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toProto()))) + .build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionCallBackRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionCallBackRsp.java index 3057323bd..6df6b34b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionCallBackRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionCallBackRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionCallBackRspOuterClass.AvatarExpeditionCallBackRsp; - -import java.util.Map; - -public class PacketAvatarExpeditionCallBackRsp extends BasePacket { - public PacketAvatarExpeditionCallBackRsp(Map expeditionInfo) { - super(PacketOpcodes.AvatarExpeditionCallBackRsp); - - AvatarExpeditionCallBackRsp.Builder proto = AvatarExpeditionCallBackRsp.newBuilder(); - expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionCallBackRspOuterClass.AvatarExpeditionCallBackRsp; +import java.util.Map; + +public class PacketAvatarExpeditionCallBackRsp extends BasePacket { + public PacketAvatarExpeditionCallBackRsp(Map expeditionInfo) { + super(PacketOpcodes.AvatarExpeditionCallBackRsp); + + AvatarExpeditionCallBackRsp.Builder proto = AvatarExpeditionCallBackRsp.newBuilder(); + expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionDataNotify.java index 35f45cf78..f437b6114 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionDataNotify.java @@ -1,24 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionDataNotifyOuterClass.AvatarExpeditionDataNotify; - -import java.util.Map; -import java.util.stream.Collectors; - -public class PacketAvatarExpeditionDataNotify extends BasePacket { - public PacketAvatarExpeditionDataNotify(Map expeditionInfo) { - super(PacketOpcodes.AvatarExpeditionDataNotify); - - this.setData(AvatarExpeditionDataNotify.newBuilder() - .putAllExpeditionInfoMap( - expeditionInfo.entrySet().stream() - .collect(Collectors.toMap( - e -> e.getKey(), - e -> e.getValue().toProto()))) - .build() - ); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionDataNotifyOuterClass.AvatarExpeditionDataNotify; +import java.util.Map; +import java.util.stream.Collectors; + +public class PacketAvatarExpeditionDataNotify extends BasePacket { + public PacketAvatarExpeditionDataNotify(Map expeditionInfo) { + super(PacketOpcodes.AvatarExpeditionDataNotify); + + this.setData( + AvatarExpeditionDataNotify.newBuilder() + .putAllExpeditionInfoMap( + expeditionInfo.entrySet().stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toProto()))) + .build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionGetRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionGetRewardRsp.java index 5ef5cbde4..d77f2abd5 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionGetRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionGetRewardRsp.java @@ -1,22 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionGetRewardRspOuterClass.AvatarExpeditionGetRewardRsp; - -import java.util.Collection; -import java.util.Map; - -public class PacketAvatarExpeditionGetRewardRsp extends BasePacket { - public PacketAvatarExpeditionGetRewardRsp(Map expeditionInfo, Collection items) { - super(PacketOpcodes.AvatarExpeditionGetRewardRsp); - - AvatarExpeditionGetRewardRsp.Builder proto = AvatarExpeditionGetRewardRsp.newBuilder(); - expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); - items.forEach(item -> proto.addItemList(item.toItemParam())); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionGetRewardRspOuterClass.AvatarExpeditionGetRewardRsp; +import java.util.Collection; +import java.util.Map; + +public class PacketAvatarExpeditionGetRewardRsp extends BasePacket { + public PacketAvatarExpeditionGetRewardRsp( + Map expeditionInfo, Collection items) { + super(PacketOpcodes.AvatarExpeditionGetRewardRsp); + + AvatarExpeditionGetRewardRsp.Builder proto = AvatarExpeditionGetRewardRsp.newBuilder(); + expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); + items.forEach(item -> proto.addItemList(item.toItemParam())); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionStartRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionStartRsp.java index cfe127097..438ceb5c6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionStartRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarExpeditionStartRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.expedition.ExpeditionInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarExpeditionStartRspOuterClass.AvatarExpeditionStartRsp; - -import java.util.Map; - -public class PacketAvatarExpeditionStartRsp extends BasePacket { - public PacketAvatarExpeditionStartRsp(Map expeditionInfo) { - super(PacketOpcodes.AvatarExpeditionStartRsp); - - AvatarExpeditionStartRsp.Builder proto = AvatarExpeditionStartRsp.newBuilder(); - expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.expedition.ExpeditionInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarExpeditionStartRspOuterClass.AvatarExpeditionStartRsp; +import java.util.Map; + +public class PacketAvatarExpeditionStartRsp extends BasePacket { + public PacketAvatarExpeditionStartRsp(Map expeditionInfo) { + super(PacketOpcodes.AvatarExpeditionStartRsp); + + AvatarExpeditionStartRsp.Builder proto = AvatarExpeditionStartRsp.newBuilder(); + expeditionInfo.forEach((key, e) -> proto.putExpeditionInfoMap(key, e.toProto())); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterDataNotify.java index f94d6ae93..f03a99550 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterDataNotify.java @@ -1,49 +1,49 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.FetterState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify; -import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; -import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData; - -public class PacketAvatarFetterDataNotify extends BasePacket { - - public PacketAvatarFetterDataNotify(Avatar avatar) { - super(PacketOpcodes.AvatarFetterDataNotify); - - int fetterLevel = avatar.getFetterLevel(); - - AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder() - .setExpLevel(avatar.getFetterLevel()); - - if (fetterLevel != 10) { - avatarFetter.setExpNumber(avatar.getFetterExp()); - } - - if (avatar.getFetterList() != null) { - for (int i = 0; i < avatar.getFetterList().size(); i++) { - avatarFetter.addFetterList( - FetterData.newBuilder() - .setFetterId(avatar.getFetterList().get(i)) - .setFetterState(FetterState.FINISH.getValue()) - ); - } - } - - int cardId = avatar.getNameCardId(); - - if (avatar.getPlayer().getNameCardList().contains(cardId)) { - avatarFetter.addRewardedFetterLevelList(10); - } - - AvatarFetterInfo avatarFetterInfo = avatarFetter.build(); - - AvatarFetterDataNotify proto = AvatarFetterDataNotify.newBuilder() - .putFetterInfoMap(avatar.getGuid(), avatarFetterInfo) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.FetterState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify; +import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; +import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData; + +public class PacketAvatarFetterDataNotify extends BasePacket { + + public PacketAvatarFetterDataNotify(Avatar avatar) { + super(PacketOpcodes.AvatarFetterDataNotify); + + int fetterLevel = avatar.getFetterLevel(); + + AvatarFetterInfo.Builder avatarFetter = + AvatarFetterInfo.newBuilder().setExpLevel(avatar.getFetterLevel()); + + if (fetterLevel != 10) { + avatarFetter.setExpNumber(avatar.getFetterExp()); + } + + if (avatar.getFetterList() != null) { + for (int i = 0; i < avatar.getFetterList().size(); i++) { + avatarFetter.addFetterList( + FetterData.newBuilder() + .setFetterId(avatar.getFetterList().get(i)) + .setFetterState(FetterState.FINISH.getValue())); + } + } + + int cardId = avatar.getNameCardId(); + + if (avatar.getPlayer().getNameCardList().contains(cardId)) { + avatarFetter.addRewardedFetterLevelList(10); + } + + AvatarFetterInfo avatarFetterInfo = avatarFetter.build(); + + AvatarFetterDataNotify proto = + AvatarFetterDataNotify.newBuilder() + .putFetterInfoMap(avatar.getGuid(), avatarFetterInfo) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterLevelRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterLevelRewardRsp.java index 1dbbbbe97..91afb0efb 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterLevelRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFetterLevelRewardRsp.java @@ -1,35 +1,36 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp; - -public class PacketAvatarFetterLevelRewardRsp extends BasePacket { - - public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel, int rewardId) { - super(PacketOpcodes.AvatarFetterLevelRewardRsp); - - AvatarFetterLevelRewardRsp proto = AvatarFetterLevelRewardRsp.newBuilder() - .setAvatarGuid(guid) - .setFetterLevel(fetterLevel) - .setRetcode(0) - .setRewardId(rewardId) - .build(); - - this.setData(proto); - } - - public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel) { - super(PacketOpcodes.AvatarFetterLevelRewardRsp); - - AvatarFetterLevelRewardRsp proto = AvatarFetterLevelRewardRsp.newBuilder() - .setAvatarGuid(guid) - .setFetterLevel(fetterLevel) - .setRetcode(1) - .setRewardId(0) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp; + +public class PacketAvatarFetterLevelRewardRsp extends BasePacket { + + public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel, int rewardId) { + super(PacketOpcodes.AvatarFetterLevelRewardRsp); + + AvatarFetterLevelRewardRsp proto = + AvatarFetterLevelRewardRsp.newBuilder() + .setAvatarGuid(guid) + .setFetterLevel(fetterLevel) + .setRetcode(0) + .setRewardId(rewardId) + .build(); + + this.setData(proto); + } + + public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel) { + super(PacketOpcodes.AvatarFetterLevelRewardRsp); + + AvatarFetterLevelRewardRsp proto = + AvatarFetterLevelRewardRsp.newBuilder() + .setAvatarGuid(guid) + .setFetterLevel(fetterLevel) + .setRetcode(1) + .setRewardId(0) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropNotify.java index bc7582fca..87b265877 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFightPropNotifyOuterClass.AvatarFightPropNotify; - -public class PacketAvatarFightPropNotify extends BasePacket { - - public PacketAvatarFightPropNotify(Avatar avatar) { - super(PacketOpcodes.AvatarFightPropNotify); - - AvatarFightPropNotify proto = AvatarFightPropNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .putAllFightPropMap(avatar.getFightProperties()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFightPropNotifyOuterClass.AvatarFightPropNotify; + +public class PacketAvatarFightPropNotify extends BasePacket { + + public PacketAvatarFightPropNotify(Avatar avatar) { + super(PacketOpcodes.AvatarFightPropNotify); + + AvatarFightPropNotify proto = + AvatarFightPropNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .putAllFightPropMap(avatar.getFightProperties()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropUpdateNotify.java index 5a13cba8a..f33158502 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFightPropUpdateNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFightPropUpdateNotifyOuterClass.AvatarFightPropUpdateNotify; - -public class PacketAvatarFightPropUpdateNotify extends BasePacket { - - public PacketAvatarFightPropUpdateNotify(Avatar avatar, FightProperty prop) { - super(PacketOpcodes.AvatarFightPropUpdateNotify); - - AvatarFightPropUpdateNotify proto = AvatarFightPropUpdateNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .putFightPropMap(prop.getId(), avatar.getFightProperty(prop)) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFightPropUpdateNotifyOuterClass.AvatarFightPropUpdateNotify; + +public class PacketAvatarFightPropUpdateNotify extends BasePacket { + + public PacketAvatarFightPropUpdateNotify(Avatar avatar, FightProperty prop) { + super(PacketOpcodes.AvatarFightPropUpdateNotify); + + AvatarFightPropUpdateNotify proto = + AvatarFightPropUpdateNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .putFightPropMap(prop.getId(), avatar.getFightProperty(prop)) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFlycloakChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFlycloakChangeNotify.java index dba50ece2..18d18d4ba 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFlycloakChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarFlycloakChangeNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarFlycloakChangeNotifyOuterClass.AvatarFlycloakChangeNotify; - -public class PacketAvatarFlycloakChangeNotify extends BasePacket { - - public PacketAvatarFlycloakChangeNotify(Avatar avatar) { - super(PacketOpcodes.AvatarFlycloakChangeNotify); - - AvatarFlycloakChangeNotify proto = AvatarFlycloakChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setFlycloakId(avatar.getFlyCloak()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarFlycloakChangeNotifyOuterClass.AvatarFlycloakChangeNotify; + +public class PacketAvatarFlycloakChangeNotify extends BasePacket { + + public PacketAvatarFlycloakChangeNotify(Avatar avatar) { + super(PacketOpcodes.AvatarFlycloakChangeNotify); + + AvatarFlycloakChangeNotify proto = + AvatarFlycloakChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setFlycloakId(avatar.getFlyCloak()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainCostumeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainCostumeNotify.java index c7da2f9ca..f28718eb3 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainCostumeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainCostumeNotify.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarGainCostumeNotifyOuterClass.AvatarGainCostumeNotify; - -public class PacketAvatarGainCostumeNotify extends BasePacket { - - public PacketAvatarGainCostumeNotify(int costumeId) { - super(PacketOpcodes.AvatarGainCostumeNotify); - - AvatarGainCostumeNotify proto = AvatarGainCostumeNotify.newBuilder() - .setCostumeId(costumeId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarGainCostumeNotifyOuterClass.AvatarGainCostumeNotify; + +public class PacketAvatarGainCostumeNotify extends BasePacket { + + public PacketAvatarGainCostumeNotify(int costumeId) { + super(PacketOpcodes.AvatarGainCostumeNotify); + + AvatarGainCostumeNotify proto = + AvatarGainCostumeNotify.newBuilder().setCostumeId(costumeId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainFlycloakNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainFlycloakNotify.java index 82806f360..2acbde0bc 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainFlycloakNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarGainFlycloakNotify.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarGainFlycloakNotifyOuterClass.AvatarGainFlycloakNotify; - -public class PacketAvatarGainFlycloakNotify extends BasePacket { - - public PacketAvatarGainFlycloakNotify(int flycloak) { - super(PacketOpcodes.AvatarGainFlycloakNotify); - - AvatarGainFlycloakNotify proto = AvatarGainFlycloakNotify.newBuilder() - .setFlycloakId(flycloak) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarGainFlycloakNotifyOuterClass.AvatarGainFlycloakNotify; + +public class PacketAvatarGainFlycloakNotify extends BasePacket { + + public PacketAvatarGainFlycloakNotify(int flycloak) { + super(PacketOpcodes.AvatarGainFlycloakNotify); + + AvatarGainFlycloakNotify proto = + AvatarGainFlycloakNotify.newBuilder().setFlycloakId(flycloak).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java index 0f1458f2b..8d6e00cc9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java @@ -1,58 +1,67 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.LifeState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarLifeStateChangeNotifyOuterClass.AvatarLifeStateChangeNotify; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; - -public class PacketAvatarLifeStateChangeNotify extends BasePacket { - - public PacketAvatarLifeStateChangeNotify(Avatar avatar) { - super(PacketOpcodes.AvatarLifeStateChangeNotify); - - AvatarLifeStateChangeNotify proto = AvatarLifeStateChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setLifeState(avatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0 ? LifeState.LIFE_ALIVE.getValue() : LifeState.LIFE_DEAD.getValue()) - .build(); - - this.setData(proto); - } - - public PacketAvatarLifeStateChangeNotify(Avatar avatar, int attackerId, LifeState lifeState) { - super(PacketOpcodes.AvatarLifeStateChangeNotify); - - AvatarLifeStateChangeNotify proto = AvatarLifeStateChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setLifeState(lifeState.getValue()) - .setMoveReliableSeq(attackerId) - .build(); - - this.setData(proto); - } - - public PacketAvatarLifeStateChangeNotify(Avatar avatar, LifeState lifeState, PlayerDieType dieType) { - this(avatar, lifeState, null, "", dieType); - } - - public PacketAvatarLifeStateChangeNotify(Avatar avatar, LifeState lifeState, GameEntity sourceEntity, - String attackTag, PlayerDieType dieType) { - super(PacketOpcodes.AvatarLifeStateChangeNotify); - - AvatarLifeStateChangeNotify.Builder proto = AvatarLifeStateChangeNotify.newBuilder(); - - proto.setAvatarGuid(avatar.getGuid()); - proto.setLifeState(lifeState.getValue()); - if (sourceEntity != null) { - proto.setSourceEntityId(sourceEntity.getId()); - } - proto.setDieType(dieType); - proto.setAttackTag((attackTag)); - - this.setData(proto.build()); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarLifeStateChangeNotifyOuterClass.AvatarLifeStateChangeNotify; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; + +public class PacketAvatarLifeStateChangeNotify extends BasePacket { + + public PacketAvatarLifeStateChangeNotify(Avatar avatar) { + super(PacketOpcodes.AvatarLifeStateChangeNotify); + + AvatarLifeStateChangeNotify proto = + AvatarLifeStateChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setLifeState( + avatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0 + ? LifeState.LIFE_ALIVE.getValue() + : LifeState.LIFE_DEAD.getValue()) + .build(); + + this.setData(proto); + } + + public PacketAvatarLifeStateChangeNotify(Avatar avatar, int attackerId, LifeState lifeState) { + super(PacketOpcodes.AvatarLifeStateChangeNotify); + + AvatarLifeStateChangeNotify proto = + AvatarLifeStateChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setLifeState(lifeState.getValue()) + .setMoveReliableSeq(attackerId) + .build(); + + this.setData(proto); + } + + public PacketAvatarLifeStateChangeNotify( + Avatar avatar, LifeState lifeState, PlayerDieType dieType) { + this(avatar, lifeState, null, "", dieType); + } + + public PacketAvatarLifeStateChangeNotify( + Avatar avatar, + LifeState lifeState, + GameEntity sourceEntity, + String attackTag, + PlayerDieType dieType) { + super(PacketOpcodes.AvatarLifeStateChangeNotify); + + AvatarLifeStateChangeNotify.Builder proto = AvatarLifeStateChangeNotify.newBuilder(); + + proto.setAvatarGuid(avatar.getGuid()); + proto.setLifeState(lifeState.getValue()); + if (sourceEntity != null) { + proto.setSourceEntityId(sourceEntity.getId()); + } + proto.setDieType(dieType); + proto.setAttackTag((attackTag)); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPromoteRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPromoteRsp.java index d220c7b2a..f962e99d3 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPromoteRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPromoteRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarPromoteRspOuterClass.AvatarPromoteRsp; - -public class PacketAvatarPromoteRsp extends BasePacket { - - public PacketAvatarPromoteRsp(Avatar avatar) { - super(PacketOpcodes.AvatarPromoteRsp); - - AvatarPromoteRsp proto = AvatarPromoteRsp.newBuilder() - .setGuid(avatar.getGuid()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarPromoteRspOuterClass.AvatarPromoteRsp; + +public class PacketAvatarPromoteRsp extends BasePacket { + + public PacketAvatarPromoteRsp(Avatar avatar) { + super(PacketOpcodes.AvatarPromoteRsp); + + AvatarPromoteRsp proto = AvatarPromoteRsp.newBuilder().setGuid(avatar.getGuid()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPropNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPropNotify.java index 6fef6e53c..8ef965c65 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPropNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarPropNotify.java @@ -1,48 +1,51 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarPropNotifyOuterClass.AvatarPropNotify; - -import java.util.Map; - -public class PacketAvatarPropNotify extends BasePacket { - public PacketAvatarPropNotify(Avatar avatar) { - super(PacketOpcodes.AvatarPropNotify); - - AvatarPropNotify proto = AvatarPropNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .putPropMap(PlayerProperty.PROP_LEVEL.getId(), avatar.getLevel()) - .putPropMap(PlayerProperty.PROP_EXP.getId(), avatar.getExp()) - .putPropMap(PlayerProperty.PROP_BREAK_LEVEL.getId(), avatar.getPromoteLevel()) - .putPropMap(PlayerProperty.PROP_SATIATION_VAL.getId(), avatar.getSatiation()) - .putPropMap(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), avatar.getSatiationPenalty()) - .build(); - - this.setData(proto); - } - - public PacketAvatarPropNotify(Avatar avatar, PlayerProperty prop, int value) { - super(PacketOpcodes.AvatarPropNotify); - - AvatarPropNotify proto = AvatarPropNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .putPropMap(prop.getId(), value) - .build(); - - this.setData(proto); - } - - public PacketAvatarPropNotify(Avatar avatar, Map propMap) { - super(PacketOpcodes.AvatarPropNotify); - - AvatarPropNotify proto = AvatarPropNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .putAllPropMap(propMap) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarPropNotifyOuterClass.AvatarPropNotify; +import java.util.Map; + +public class PacketAvatarPropNotify extends BasePacket { + public PacketAvatarPropNotify(Avatar avatar) { + super(PacketOpcodes.AvatarPropNotify); + + AvatarPropNotify proto = + AvatarPropNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .putPropMap(PlayerProperty.PROP_LEVEL.getId(), avatar.getLevel()) + .putPropMap(PlayerProperty.PROP_EXP.getId(), avatar.getExp()) + .putPropMap(PlayerProperty.PROP_BREAK_LEVEL.getId(), avatar.getPromoteLevel()) + .putPropMap(PlayerProperty.PROP_SATIATION_VAL.getId(), avatar.getSatiation()) + .putPropMap( + PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), avatar.getSatiationPenalty()) + .build(); + + this.setData(proto); + } + + public PacketAvatarPropNotify(Avatar avatar, PlayerProperty prop, int value) { + super(PacketOpcodes.AvatarPropNotify); + + AvatarPropNotify proto = + AvatarPropNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .putPropMap(prop.getId(), value) + .build(); + + this.setData(proto); + } + + public PacketAvatarPropNotify(Avatar avatar, Map propMap) { + super(PacketOpcodes.AvatarPropNotify); + + AvatarPropNotify proto = + AvatarPropNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .putAllPropMap(propMap) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSatiationDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSatiationDataNotify.java index 7f5da2ab3..8e094ab59 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSatiationDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSatiationDataNotify.java @@ -1,48 +1,46 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSatiationDataNotifyOuterClass.AvatarSatiationDataNotify; -import emu.grasscutter.net.proto.AvatarSatiationDataOuterClass.AvatarSatiationData; - -public class PacketAvatarSatiationDataNotify extends BasePacket { - - public PacketAvatarSatiationDataNotify(Avatar avatar, float finishTime, long penaltyTime) { - super(PacketOpcodes.AvatarSatiationDataNotify); - - AvatarSatiationData.Builder avatarSatiation = AvatarSatiationData.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setFinishTime(finishTime); - - // Penalty for overeating - if (penaltyTime > 0) { - avatarSatiation.setPenaltyFinishTime(penaltyTime); - } - - avatarSatiation.build(); - - AvatarSatiationDataNotify notify = AvatarSatiationDataNotify.newBuilder() - .addSatiationDataList(0, avatarSatiation) - .build(); - - this.setData(notify); - } - - public PacketAvatarSatiationDataNotify(float time, Avatar avatar) { - super(PacketOpcodes.AvatarSatiationDataNotify); - - var avatarSatiation = AvatarSatiationData.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setFinishTime(time + (avatar.getSatiation() / 30f)) - // Penalty time always ends before finish time - .setPenaltyFinishTime(time + (avatar.getSatiationPenalty() / 100f)) - .build(); - - AvatarSatiationDataNotify notify = AvatarSatiationDataNotify.newBuilder() - .addSatiationDataList(0, avatarSatiation) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSatiationDataNotifyOuterClass.AvatarSatiationDataNotify; +import emu.grasscutter.net.proto.AvatarSatiationDataOuterClass.AvatarSatiationData; + +public class PacketAvatarSatiationDataNotify extends BasePacket { + + public PacketAvatarSatiationDataNotify(Avatar avatar, float finishTime, long penaltyTime) { + super(PacketOpcodes.AvatarSatiationDataNotify); + + AvatarSatiationData.Builder avatarSatiation = + AvatarSatiationData.newBuilder().setAvatarGuid(avatar.getGuid()).setFinishTime(finishTime); + + // Penalty for overeating + if (penaltyTime > 0) { + avatarSatiation.setPenaltyFinishTime(penaltyTime); + } + + avatarSatiation.build(); + + AvatarSatiationDataNotify notify = + AvatarSatiationDataNotify.newBuilder().addSatiationDataList(0, avatarSatiation).build(); + + this.setData(notify); + } + + public PacketAvatarSatiationDataNotify(float time, Avatar avatar) { + super(PacketOpcodes.AvatarSatiationDataNotify); + + var avatarSatiation = + AvatarSatiationData.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setFinishTime(time + (avatar.getSatiation() / 30f)) + // Penalty time always ends before finish time + .setPenaltyFinishTime(time + (avatar.getSatiationPenalty() / 100f)) + .build(); + + AvatarSatiationDataNotify notify = + AvatarSatiationDataNotify.newBuilder().addSatiationDataList(0, avatarSatiation).build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillChangeNotify.java index 9116f13e3..3eb123dd8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillChangeNotify.java @@ -1,24 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillChangeNotifyOuterClass.AvatarSkillChangeNotify; - -public class PacketAvatarSkillChangeNotify extends BasePacket { - - public PacketAvatarSkillChangeNotify(Avatar avatar, int skillId, int oldLevel, int curLevel) { - super(PacketOpcodes.AvatarSkillChangeNotify); - - AvatarSkillChangeNotify proto = AvatarSkillChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEntityId(avatar.getEntityId()) - .setSkillDepotId(avatar.getSkillDepotId()) - .setAvatarSkillId(skillId) - .setOldLevel(oldLevel) - .setCurLevel(curLevel) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillChangeNotifyOuterClass.AvatarSkillChangeNotify; + +public class PacketAvatarSkillChangeNotify extends BasePacket { + + public PacketAvatarSkillChangeNotify(Avatar avatar, int skillId, int oldLevel, int curLevel) { + super(PacketOpcodes.AvatarSkillChangeNotify); + + AvatarSkillChangeNotify proto = + AvatarSkillChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEntityId(avatar.getEntityId()) + .setSkillDepotId(avatar.getSkillDepotId()) + .setAvatarSkillId(skillId) + .setOldLevel(oldLevel) + .setCurLevel(curLevel) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java index 2b787b247..3187356d7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillDepotChangeNotifyOuterClass.AvatarSkillDepotChangeNotify; - -public class PacketAvatarSkillDepotChangeNotify extends BasePacket { - - public PacketAvatarSkillDepotChangeNotify(Avatar avatar) { - super(PacketOpcodes.AvatarSkillDepotChangeNotify); - - AvatarSkillDepotChangeNotify proto = AvatarSkillDepotChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEntityId(avatar.getEntityId()) - .setSkillDepotId(avatar.getSkillDepotId()) - .setCoreProudSkillLevel(avatar.getCoreProudSkillLevel()) - .addAllTalentIdList(avatar.getTalentIdList()) - .addAllProudSkillList(avatar.getProudSkillList()) - .putAllSkillLevelMap(avatar.getSkillLevelMap()) - .putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillDepotChangeNotifyOuterClass.AvatarSkillDepotChangeNotify; + +public class PacketAvatarSkillDepotChangeNotify extends BasePacket { + + public PacketAvatarSkillDepotChangeNotify(Avatar avatar) { + super(PacketOpcodes.AvatarSkillDepotChangeNotify); + + AvatarSkillDepotChangeNotify proto = + AvatarSkillDepotChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEntityId(avatar.getEntityId()) + .setSkillDepotId(avatar.getSkillDepotId()) + .setCoreProudSkillLevel(avatar.getCoreProudSkillLevel()) + .addAllTalentIdList(avatar.getTalentIdList()) + .addAllProudSkillList(avatar.getProudSkillList()) + .putAllSkillLevelMap(avatar.getSkillLevelMap()) + .putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillInfoNotify.java index f7fdba686..145640354 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillInfoNotify.java @@ -1,20 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillInfoNotifyOuterClass.AvatarSkillInfoNotify; -import emu.grasscutter.net.proto.AvatarSkillInfoOuterClass.AvatarSkillInfo; -import it.unimi.dsi.fastutil.ints.Int2IntMap; - -public class PacketAvatarSkillInfoNotify extends BasePacket { - public PacketAvatarSkillInfoNotify(long avatarGuid, Int2IntMap skillExtraChargeMap) { - super(PacketOpcodes.AvatarSkillInfoNotify); - - var proto = AvatarSkillInfoNotify.newBuilder().setGuid(avatarGuid); - - skillExtraChargeMap.forEach((skillId, count) -> - proto.putSkillMap(skillId, AvatarSkillInfo.newBuilder().setMaxChargeCount(count).build())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillInfoNotifyOuterClass.AvatarSkillInfoNotify; +import emu.grasscutter.net.proto.AvatarSkillInfoOuterClass.AvatarSkillInfo; +import it.unimi.dsi.fastutil.ints.Int2IntMap; + +public class PacketAvatarSkillInfoNotify extends BasePacket { + public PacketAvatarSkillInfoNotify(long avatarGuid, Int2IntMap skillExtraChargeMap) { + super(PacketOpcodes.AvatarSkillInfoNotify); + + var proto = AvatarSkillInfoNotify.newBuilder().setGuid(avatarGuid); + + skillExtraChargeMap.forEach( + (skillId, count) -> + proto.putSkillMap( + skillId, AvatarSkillInfo.newBuilder().setMaxChargeCount(count).build())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillMaxChargeCountNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillMaxChargeCountNotify.java index e9091f7d2..0a8bbf327 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillMaxChargeCountNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillMaxChargeCountNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillMaxChargeCountNotifyOuterClass.AvatarSkillMaxChargeCountNotify; - -public class PacketAvatarSkillMaxChargeCountNotify extends BasePacket { - - public PacketAvatarSkillMaxChargeCountNotify(Avatar avatar, int skillId, int maxCharges) { - super(PacketOpcodes.AvatarSkillMaxChargeCountNotify); - - AvatarSkillMaxChargeCountNotify proto = AvatarSkillMaxChargeCountNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setSkillId(skillId) - .setMaxChargeCount(maxCharges) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillMaxChargeCountNotifyOuterClass.AvatarSkillMaxChargeCountNotify; + +public class PacketAvatarSkillMaxChargeCountNotify extends BasePacket { + + public PacketAvatarSkillMaxChargeCountNotify(Avatar avatar, int skillId, int maxCharges) { + super(PacketOpcodes.AvatarSkillMaxChargeCountNotify); + + AvatarSkillMaxChargeCountNotify proto = + AvatarSkillMaxChargeCountNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setSkillId(skillId) + .setMaxChargeCount(maxCharges) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillUpgradeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillUpgradeRsp.java index 874cc4ce7..6be8c2161 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillUpgradeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillUpgradeRsp.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarSkillUpgradeRspOuterClass.AvatarSkillUpgradeRsp; - -public class PacketAvatarSkillUpgradeRsp extends BasePacket { - - public PacketAvatarSkillUpgradeRsp(Avatar avatar, int skillId, int oldLevel, int newLevel) { - super(PacketOpcodes.AvatarSkillUpgradeRsp); - - AvatarSkillUpgradeRsp proto = AvatarSkillUpgradeRsp.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setAvatarSkillId(skillId) - .setOldLevel(oldLevel) - .setCurLevel(newLevel) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillUpgradeRspOuterClass.AvatarSkillUpgradeRsp; + +public class PacketAvatarSkillUpgradeRsp extends BasePacket { + + public PacketAvatarSkillUpgradeRsp(Avatar avatar, int skillId, int oldLevel, int newLevel) { + super(PacketOpcodes.AvatarSkillUpgradeRsp); + + AvatarSkillUpgradeRsp proto = + AvatarSkillUpgradeRsp.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setAvatarSkillId(skillId) + .setOldLevel(oldLevel) + .setCurLevel(newLevel) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamAllDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamAllDataNotify.java index b09f0a763..8f712c138 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamAllDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamAllDataNotify.java @@ -1,26 +1,29 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarTeamAllDataNotifyOuterClass.AvatarTeamAllDataNotify; - -public class PacketAvatarTeamAllDataNotify extends BasePacket { - public PacketAvatarTeamAllDataNotify(Player player) { - super(PacketOpcodes.AvatarTeamAllDataNotify); - - AvatarTeamAllDataNotify.Builder proto = AvatarTeamAllDataNotify.newBuilder(); - - // Add the id list for custom teams. - for (int id : player.getTeamManager().getTeams().keySet()) { - if (id > 4) { - proto.addBackupAvatarTeamOrderList(id); - } - } - - // Add the avatar lists for all the teams the player has. - player.getTeamManager().getTeams().forEach((id, teamInfo) -> proto.putAvatarTeamMap(id, teamInfo.toProto(player))); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarTeamAllDataNotifyOuterClass.AvatarTeamAllDataNotify; + +public class PacketAvatarTeamAllDataNotify extends BasePacket { + public PacketAvatarTeamAllDataNotify(Player player) { + super(PacketOpcodes.AvatarTeamAllDataNotify); + + AvatarTeamAllDataNotify.Builder proto = AvatarTeamAllDataNotify.newBuilder(); + + // Add the id list for custom teams. + for (int id : player.getTeamManager().getTeams().keySet()) { + if (id > 4) { + proto.addBackupAvatarTeamOrderList(id); + } + } + + // Add the avatar lists for all the teams the player has. + player + .getTeamManager() + .getTeams() + .forEach((id, teamInfo) -> proto.putAvatarTeamMap(id, teamInfo.toProto(player))); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamUpdateNotify.java index 63f43dd0d..d86904686 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarTeamUpdateNotify.java @@ -1,19 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarTeamUpdateNotifyOuterClass.AvatarTeamUpdateNotify; - -public class PacketAvatarTeamUpdateNotify extends BasePacket { - - public PacketAvatarTeamUpdateNotify(Player player) { - super(PacketOpcodes.AvatarTeamUpdateNotify); - - AvatarTeamUpdateNotify.Builder proto = AvatarTeamUpdateNotify.newBuilder(); - - player.getTeamManager().getTeams().forEach((id, teamInfo) -> proto.putAvatarTeamMap(id, teamInfo.toProto(player))); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarTeamUpdateNotifyOuterClass.AvatarTeamUpdateNotify; + +public class PacketAvatarTeamUpdateNotify extends BasePacket { + + public PacketAvatarTeamUpdateNotify(Player player) { + super(PacketOpcodes.AvatarTeamUpdateNotify); + + AvatarTeamUpdateNotify.Builder proto = AvatarTeamUpdateNotify.newBuilder(); + + player + .getTeamManager() + .getTeams() + .forEach((id, teamInfo) -> proto.putAvatarTeamMap(id, teamInfo.toProto(player))); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUnlockTalentNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUnlockTalentNotify.java index 8a924fea5..e0ace945f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUnlockTalentNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUnlockTalentNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarUnlockTalentNotifyOuterClass.AvatarUnlockTalentNotify; - -public class PacketAvatarUnlockTalentNotify extends BasePacket { - - public PacketAvatarUnlockTalentNotify(Avatar avatar, int talentId) { - super(PacketOpcodes.AvatarUnlockTalentNotify); - - AvatarUnlockTalentNotify proto = AvatarUnlockTalentNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEntityId(avatar.getEntityId()) - .setTalentId(talentId) - .setSkillDepotId(avatar.getSkillDepotId()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarUnlockTalentNotifyOuterClass.AvatarUnlockTalentNotify; + +public class PacketAvatarUnlockTalentNotify extends BasePacket { + + public PacketAvatarUnlockTalentNotify(Avatar avatar, int talentId) { + super(PacketOpcodes.AvatarUnlockTalentNotify); + + AvatarUnlockTalentNotify proto = + AvatarUnlockTalentNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEntityId(avatar.getEntityId()) + .setTalentId(talentId) + .setSkillDepotId(avatar.getSkillDepotId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUpgradeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUpgradeRsp.java index 0522cc06b..beab5abf7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUpgradeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarUpgradeRsp.java @@ -1,27 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarUpgradeRspOuterClass.AvatarUpgradeRsp; - -import java.util.Map; - -public class PacketAvatarUpgradeRsp extends BasePacket { - - public PacketAvatarUpgradeRsp(Avatar avatar, int oldLevel, Map oldFightPropMap) { - super(PacketOpcodes.AvatarUpgradeRsp); - - this.buildHeader(0); - - AvatarUpgradeRsp proto = AvatarUpgradeRsp.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setOldLevel(oldLevel) - .setCurLevel(avatar.getLevel()) - .putAllOldFightPropMap(oldFightPropMap) - .putAllCurFightPropMap(avatar.getFightProperties()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarUpgradeRspOuterClass.AvatarUpgradeRsp; +import java.util.Map; + +public class PacketAvatarUpgradeRsp extends BasePacket { + + public PacketAvatarUpgradeRsp(Avatar avatar, int oldLevel, Map oldFightPropMap) { + super(PacketOpcodes.AvatarUpgradeRsp); + + this.buildHeader(0); + + AvatarUpgradeRsp proto = + AvatarUpgradeRsp.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setOldLevel(oldLevel) + .setCurLevel(avatar.getLevel()) + .putAllOldFightPropMap(oldFightPropMap) + .putAllCurFightPropMap(avatar.getFightProperties()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarWearFlycloakRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarWearFlycloakRsp.java index 826c02529..74fec9b76 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarWearFlycloakRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarWearFlycloakRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AvatarWearFlycloakRspOuterClass.AvatarWearFlycloakRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketAvatarWearFlycloakRsp extends BasePacket { - public PacketAvatarWearFlycloakRsp(long avatarGuid, int costumeId) { - super(PacketOpcodes.AvatarWearFlycloakRsp); - - AvatarWearFlycloakRsp proto = AvatarWearFlycloakRsp.newBuilder() - .setAvatarGuid(avatarGuid) - .setFlycloakId(costumeId) - .build(); - - this.setData(proto); - } - - public PacketAvatarWearFlycloakRsp() { - super(PacketOpcodes.AvatarWearFlycloakRsp); - - AvatarWearFlycloakRsp proto = AvatarWearFlycloakRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarWearFlycloakRspOuterClass.AvatarWearFlycloakRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketAvatarWearFlycloakRsp extends BasePacket { + public PacketAvatarWearFlycloakRsp(long avatarGuid, int costumeId) { + super(PacketOpcodes.AvatarWearFlycloakRsp); + + AvatarWearFlycloakRsp proto = + AvatarWearFlycloakRsp.newBuilder() + .setAvatarGuid(avatarGuid) + .setFlycloakId(costumeId) + .build(); + + this.setData(proto); + } + + public PacketAvatarWearFlycloakRsp() { + super(PacketOpcodes.AvatarWearFlycloakRsp); + + AvatarWearFlycloakRsp proto = + AvatarWearFlycloakRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBackMyWorldRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBackMyWorldRsp.java index 90e02ca73..887f47bba 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBackMyWorldRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBackMyWorldRsp.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BackMyWorldRspOuterClass; - -public class PacketBackMyWorldRsp extends BasePacket { - - public PacketBackMyWorldRsp() { - super(PacketOpcodes.BackMyWorldRsp); - - var proto = BackMyWorldRspOuterClass.BackMyWorldRsp.newBuilder(); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BackMyWorldRspOuterClass; + +public class PacketBackMyWorldRsp extends BasePacket { + + public PacketBackMyWorldRsp() { + super(PacketOpcodes.BackMyWorldRsp); + + var proto = BackMyWorldRspOuterClass.BackMyWorldRsp.newBuilder(); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassAllDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassAllDataNotify.java index b33f75be5..a5b7ed871 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassAllDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassAllDataNotify.java @@ -1,35 +1,35 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BattlePassAllDataNotifyOuterClass.BattlePassAllDataNotify; - -public class PacketBattlePassAllDataNotify extends BasePacket { - public PacketBattlePassAllDataNotify(Player player) { - super(PacketOpcodes.BattlePassAllDataNotify); - - var proto = BattlePassAllDataNotify.newBuilder(); - - proto - .setHaveCurSchedule(true) - .setCurSchedule(player.getBattlePassManager().getScheduleProto()); - - for (var missionData : GameData.getBattlePassMissionDataMap().values()) { - // Dont send invalid refresh types - if (!missionData.isValidRefreshType()) { - continue; - } - - // Check if player has mission in bp manager. If not, then add an empty proto from the mission data - if (player.getBattlePassManager().hasMission(missionData.getId())) { - proto.addMissionList(player.getBattlePassManager().loadMissionById(missionData.getId()).toProto()); - } else { - proto.addMissionList(missionData.toProto()); - } - } - - setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BattlePassAllDataNotifyOuterClass.BattlePassAllDataNotify; + +public class PacketBattlePassAllDataNotify extends BasePacket { + public PacketBattlePassAllDataNotify(Player player) { + super(PacketOpcodes.BattlePassAllDataNotify); + + var proto = BattlePassAllDataNotify.newBuilder(); + + proto.setHaveCurSchedule(true).setCurSchedule(player.getBattlePassManager().getScheduleProto()); + + for (var missionData : GameData.getBattlePassMissionDataMap().values()) { + // Dont send invalid refresh types + if (!missionData.isValidRefreshType()) { + continue; + } + + // Check if player has mission in bp manager. If not, then add an empty proto from the mission + // data + if (player.getBattlePassManager().hasMission(missionData.getId())) { + proto.addMissionList( + player.getBattlePassManager().loadMissionById(missionData.getId()).toProto()); + } else { + proto.addMissionList(missionData.toProto()); + } + } + + setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassCurScheduleUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassCurScheduleUpdateNotify.java index f4437945b..9350e4f50 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassCurScheduleUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassCurScheduleUpdateNotify.java @@ -1,23 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BattlePassCurScheduleUpdateNotifyOuterClass.BattlePassCurScheduleUpdateNotify; - -public class PacketBattlePassCurScheduleUpdateNotify extends BasePacket { - - public PacketBattlePassCurScheduleUpdateNotify(Player player) { - super(PacketOpcodes.BattlePassCurScheduleUpdateNotify); - - var proto = BattlePassCurScheduleUpdateNotify.newBuilder(); - - proto - .setHaveCurSchedule(true) - .setCurSchedule(player.getBattlePassManager().getScheduleProto()) - .build(); - - setData(proto.build()); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BattlePassCurScheduleUpdateNotifyOuterClass.BattlePassCurScheduleUpdateNotify; + +public class PacketBattlePassCurScheduleUpdateNotify extends BasePacket { + + public PacketBattlePassCurScheduleUpdateNotify(Player player) { + super(PacketOpcodes.BattlePassCurScheduleUpdateNotify); + + var proto = BattlePassCurScheduleUpdateNotify.newBuilder(); + + proto + .setHaveCurSchedule(true) + .setCurSchedule(player.getBattlePassManager().getScheduleProto()) + .build(); + + setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassMissionUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassMissionUpdateNotify.java index f450108fc..5c94fd9a7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassMissionUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBattlePassMissionUpdateNotify.java @@ -1,34 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.battlepass.BattlePassMission; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BattlePassMissionUpdateNotifyOuterClass.BattlePassMissionUpdateNotify; - -import java.util.Collection; - -public class PacketBattlePassMissionUpdateNotify extends BasePacket { - - public PacketBattlePassMissionUpdateNotify(BattlePassMission mission) { - super(PacketOpcodes.BattlePassMissionUpdateNotify); - - var proto = BattlePassMissionUpdateNotify.newBuilder() - .addMissionList(mission.toProto()) - .build(); - - this.setData(proto); - } - - public PacketBattlePassMissionUpdateNotify(Collection missions) { - super(PacketOpcodes.BattlePassMissionUpdateNotify); - - var proto = BattlePassMissionUpdateNotify.newBuilder(); - - missions.forEach(mission -> { - proto.addMissionList(mission.toProto()); - }); - - this.setData(proto.build()); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.battlepass.BattlePassMission; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BattlePassMissionUpdateNotifyOuterClass.BattlePassMissionUpdateNotify; +import java.util.Collection; + +public class PacketBattlePassMissionUpdateNotify extends BasePacket { + + public PacketBattlePassMissionUpdateNotify(BattlePassMission mission) { + super(PacketOpcodes.BattlePassMissionUpdateNotify); + + var proto = + BattlePassMissionUpdateNotify.newBuilder().addMissionList(mission.toProto()).build(); + + this.setData(proto); + } + + public PacketBattlePassMissionUpdateNotify(Collection missions) { + super(PacketOpcodes.BattlePassMissionUpdateNotify); + + var proto = BattlePassMissionUpdateNotify.newBuilder(); + + missions.forEach( + mission -> { + proto.addMissionList(mission.toProto()); + }); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBlossomBriefInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBlossomBriefInfoNotify.java index 00cd96362..204c02836 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBlossomBriefInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBlossomBriefInfoNotify.java @@ -1,13 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BlossomBriefInfoNotifyOuterClass; -import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass; - -public class PacketBlossomBriefInfoNotify extends BasePacket { - public PacketBlossomBriefInfoNotify(Iterable blossoms) { - super(PacketOpcodes.BlossomBriefInfoNotify); - this.setData(BlossomBriefInfoNotifyOuterClass.BlossomBriefInfoNotify.newBuilder().addAllBriefInfoList(blossoms)); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BlossomBriefInfoNotifyOuterClass; +import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass; + +public class PacketBlossomBriefInfoNotify extends BasePacket { + public PacketBlossomBriefInfoNotify( + Iterable blossoms) { + super(PacketOpcodes.BlossomBriefInfoNotify); + this.setData( + BlossomBriefInfoNotifyOuterClass.BlossomBriefInfoNotify.newBuilder() + .addAllBriefInfoList(blossoms)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyBattlePassLevelRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyBattlePassLevelRsp.java index e5026bfbc..17da597ed 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyBattlePassLevelRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyBattlePassLevelRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BuyBattlePassLevelRspOuterClass.BuyBattlePassLevelRsp; - -public class PacketBuyBattlePassLevelRsp extends BasePacket { - - public PacketBuyBattlePassLevelRsp(int buyLevel) { - super(PacketOpcodes.BuyBattlePassLevelRsp); - - BuyBattlePassLevelRsp proto = BuyBattlePassLevelRsp.newBuilder() - .setBuyLevel(buyLevel) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyBattlePassLevelRspOuterClass.BuyBattlePassLevelRsp; + +public class PacketBuyBattlePassLevelRsp extends BasePacket { + + public PacketBuyBattlePassLevelRsp(int buyLevel) { + super(PacketOpcodes.BuyBattlePassLevelRsp); + + BuyBattlePassLevelRsp proto = BuyBattlePassLevelRsp.newBuilder().setBuyLevel(buyLevel).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java index fc49136af..310c8c0d2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java @@ -1,22 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BuyGoodsRspOuterClass; -import emu.grasscutter.net.proto.ShopGoodsOuterClass; - -public class PacketBuyGoodsRsp extends BasePacket { - public PacketBuyGoodsRsp(int shopType, int boughtNum, ShopGoodsOuterClass.ShopGoods sg) { - super(PacketOpcodes.BuyGoodsRsp); - - BuyGoodsRspOuterClass.BuyGoodsRsp buyGoodsRsp = BuyGoodsRspOuterClass.BuyGoodsRsp.newBuilder() - .setShopType(shopType) - .setBuyCount(boughtNum) - .addGoodsList(ShopGoodsOuterClass.ShopGoods.newBuilder() - .mergeFrom(sg) - .setBoughtNum(boughtNum) - ).build(); - - this.setData(buyGoodsRsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BuyGoodsRspOuterClass; +import emu.grasscutter.net.proto.ShopGoodsOuterClass; + +public class PacketBuyGoodsRsp extends BasePacket { + public PacketBuyGoodsRsp(int shopType, int boughtNum, ShopGoodsOuterClass.ShopGoods sg) { + super(PacketOpcodes.BuyGoodsRsp); + + BuyGoodsRspOuterClass.BuyGoodsRsp buyGoodsRsp = + BuyGoodsRspOuterClass.BuyGoodsRsp.newBuilder() + .setShopType(shopType) + .setBuyCount(boughtNum) + .addGoodsList( + ShopGoodsOuterClass.ShopGoods.newBuilder().mergeFrom(sg).setBoughtNum(boughtNum)) + .build(); + + this.setData(buyGoodsRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCalcWeaponUpgradeReturnItemsRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCalcWeaponUpgradeReturnItemsRsp.java index d0ca398ab..303802125 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCalcWeaponUpgradeReturnItemsRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCalcWeaponUpgradeReturnItemsRsp.java @@ -1,33 +1,34 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsRspOuterClass.CalcWeaponUpgradeReturnItemsRsp; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -import java.util.List; - -public class PacketCalcWeaponUpgradeReturnItemsRsp extends BasePacket { - - public PacketCalcWeaponUpgradeReturnItemsRsp(long itemGuid, List returnItems) { - super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp); - - CalcWeaponUpgradeReturnItemsRsp proto = CalcWeaponUpgradeReturnItemsRsp.newBuilder() - .setTargetWeaponGuid(itemGuid) - .addAllItemParamList(returnItems) - .build(); - - this.setData(proto); - } - - public PacketCalcWeaponUpgradeReturnItemsRsp() { - super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp); - - CalcWeaponUpgradeReturnItemsRsp proto = CalcWeaponUpgradeReturnItemsRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsRspOuterClass.CalcWeaponUpgradeReturnItemsRsp; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import java.util.List; + +public class PacketCalcWeaponUpgradeReturnItemsRsp extends BasePacket { + + public PacketCalcWeaponUpgradeReturnItemsRsp(long itemGuid, List returnItems) { + super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp); + + CalcWeaponUpgradeReturnItemsRsp proto = + CalcWeaponUpgradeReturnItemsRsp.newBuilder() + .setTargetWeaponGuid(itemGuid) + .addAllItemParamList(returnItems) + .build(); + + this.setData(proto); + } + + public PacketCalcWeaponUpgradeReturnItemsRsp() { + super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp); + + CalcWeaponUpgradeReturnItemsRsp proto = + CalcWeaponUpgradeReturnItemsRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java index 5e4d26edd..80f8eda0d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java @@ -1,19 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CanUseSkillNotifyOuterClass; - -public class PacketCanUseSkillNotify extends BasePacket { - - public PacketCanUseSkillNotify(boolean canUseSkill) { - super(PacketOpcodes.CanUseSkillNotify); - - CanUseSkillNotifyOuterClass.CanUseSkillNotify proto = CanUseSkillNotifyOuterClass.CanUseSkillNotify.newBuilder() - .setIsCanUseSkill(canUseSkill) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CanUseSkillNotifyOuterClass; + +public class PacketCanUseSkillNotify extends BasePacket { + + public PacketCanUseSkillNotify(boolean canUseSkill) { + super(PacketOpcodes.CanUseSkillNotify); + + CanUseSkillNotifyOuterClass.CanUseSkillNotify proto = + CanUseSkillNotifyOuterClass.CanUseSkillNotify.newBuilder() + .setIsCanUseSkill(canUseSkill) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCardProductRewardNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCardProductRewardNotify.java index f4fb678b5..269de5d5c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCardProductRewardNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCardProductRewardNotify.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.send; - - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CardProductRewardNotifyOuterClass.CardProductRewardNotify; - -public class PacketCardProductRewardNotify extends BasePacket { - - public PacketCardProductRewardNotify(int remainsDay) { - super(PacketOpcodes.CardProductRewardNotify); - - CardProductRewardNotify proto = CardProductRewardNotify.newBuilder() - .setProductId("ys_chn_blessofmoon_tier5") - .setHcoin(90) - .setRemainDays(remainsDay) - .build(); - - // Hard code Product id keep cool 😎 - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CardProductRewardNotifyOuterClass.CardProductRewardNotify; + +public class PacketCardProductRewardNotify extends BasePacket { + + public PacketCardProductRewardNotify(int remainsDay) { + super(PacketOpcodes.CardProductRewardNotify); + + CardProductRewardNotify proto = + CardProductRewardNotify.newBuilder() + .setProductId("ys_chn_blessofmoon_tier5") + .setHcoin(90) + .setRemainDays(remainsDay) + .build(); + + // Hard code Product id keep cool 😎 + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChallengeDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChallengeDataNotify.java index e1011366a..ac48896e7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChallengeDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChallengeDataNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChallengeDataNotifyOuterClass.ChallengeDataNotify; - -public class PacketChallengeDataNotify extends BasePacket { - - public PacketChallengeDataNotify(WorldChallenge challenge, int index, int value) { - super(PacketOpcodes.ChallengeDataNotify); - - ChallengeDataNotify proto = ChallengeDataNotify.newBuilder() - .setChallengeIndex(challenge.getChallengeIndex()) - .setParamIndex(index) - .setValue(value) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChallengeDataNotifyOuterClass.ChallengeDataNotify; + +public class PacketChallengeDataNotify extends BasePacket { + + public PacketChallengeDataNotify(WorldChallenge challenge, int index, int value) { + super(PacketOpcodes.ChallengeDataNotify); + + ChallengeDataNotify proto = + ChallengeDataNotify.newBuilder() + .setChallengeIndex(challenge.getChallengeIndex()) + .setParamIndex(index) + .setValue(value) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeAvatarRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeAvatarRsp.java index b46b70471..0c74fea6e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeAvatarRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeAvatarRsp.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeAvatarRspOuterClass.ChangeAvatarRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketChangeAvatarRsp extends BasePacket { - - public PacketChangeAvatarRsp(long guid) { - super(PacketOpcodes.ChangeAvatarRsp); - - ChangeAvatarRsp p = ChangeAvatarRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) - .setCurGuid(guid) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeAvatarRspOuterClass.ChangeAvatarRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketChangeAvatarRsp extends BasePacket { + + public PacketChangeAvatarRsp(long guid) { + super(PacketOpcodes.ChangeAvatarRsp); + + ChangeAvatarRsp p = + ChangeAvatarRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) + .setCurGuid(guid) + .build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeGameTimeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeGameTimeRsp.java index eb9527220..fe69b62f4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeGameTimeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeGameTimeRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeGameTimeRspOuterClass.ChangeGameTimeRsp; - -public class PacketChangeGameTimeRsp extends BasePacket { - - public PacketChangeGameTimeRsp(Player player) { - super(PacketOpcodes.ChangeGameTimeRsp); - - ChangeGameTimeRsp proto = ChangeGameTimeRsp.newBuilder() - .setCurGameTime(player.getScene().getTime()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeGameTimeRspOuterClass.ChangeGameTimeRsp; + +public class PacketChangeGameTimeRsp extends BasePacket { + + public PacketChangeGameTimeRsp(Player player) { + super(PacketOpcodes.ChangeGameTimeRsp); + + ChangeGameTimeRsp proto = + ChangeGameTimeRsp.newBuilder().setCurGameTime(player.getScene().getTime()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeMpTeamAvatarRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeMpTeamAvatarRsp.java index 91b792a12..33d90a37f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeMpTeamAvatarRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeMpTeamAvatarRsp.java @@ -1,23 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.TeamInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeMpTeamAvatarRspOuterClass.ChangeMpTeamAvatarRsp; - -public class PacketChangeMpTeamAvatarRsp extends BasePacket { - - public PacketChangeMpTeamAvatarRsp(Player player, TeamInfo teamInfo) { - super(PacketOpcodes.ChangeMpTeamAvatarRsp); - - ChangeMpTeamAvatarRsp.Builder proto = ChangeMpTeamAvatarRsp.newBuilder() - .setCurAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()); - - for (int avatarId : teamInfo.getAvatars()) { - proto.addAvatarGuidList(player.getAvatars().getAvatarById(avatarId).getGuid()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.TeamInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeMpTeamAvatarRspOuterClass.ChangeMpTeamAvatarRsp; + +public class PacketChangeMpTeamAvatarRsp extends BasePacket { + + public PacketChangeMpTeamAvatarRsp(Player player, TeamInfo teamInfo) { + super(PacketOpcodes.ChangeMpTeamAvatarRsp); + + ChangeMpTeamAvatarRsp.Builder proto = + ChangeMpTeamAvatarRsp.newBuilder() + .setCurAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()); + + for (int avatarId : teamInfo.getAvatars()) { + proto.addAvatarGuidList(player.getAvatars().getAvatarById(avatarId).getGuid()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeTeamNameRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeTeamNameRsp.java index 9d2585137..8e1abb7b1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChangeTeamNameRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChangeTeamNameRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeTeamNameRspOuterClass.ChangeTeamNameRsp; - -public class PacketChangeTeamNameRsp extends BasePacket { - - public PacketChangeTeamNameRsp(int teamId, String teamName) { - super(PacketOpcodes.ChangeTeamNameRsp); - - ChangeTeamNameRsp proto = ChangeTeamNameRsp.newBuilder() - .setTeamId(teamId) - .setTeamName(teamName) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeTeamNameRspOuterClass.ChangeTeamNameRsp; + +public class PacketChangeTeamNameRsp extends BasePacket { + + public PacketChangeTeamNameRsp(int teamId, String teamName) { + super(PacketOpcodes.ChangeTeamNameRsp); + + ChangeTeamNameRsp proto = + ChangeTeamNameRsp.newBuilder().setTeamId(teamId).setTeamName(teamName).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChapterStateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChapterStateNotify.java index 38d8f53d5..488fab184 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChapterStateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChapterStateNotify.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChapterStateNotifyOuterClass; -import emu.grasscutter.net.proto.ChapterStateOuterClass; - -public class PacketChapterStateNotify extends BasePacket { - - public PacketChapterStateNotify(int id, ChapterStateOuterClass.ChapterState state) { - super(PacketOpcodes.ChapterStateNotify); - - var proto = ChapterStateNotifyOuterClass.ChapterStateNotify.newBuilder(); - - proto.setChapterId(id) - .setChapterState(state); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChapterStateNotifyOuterClass; +import emu.grasscutter.net.proto.ChapterStateOuterClass; + +public class PacketChapterStateNotify extends BasePacket { + + public PacketChapterStateNotify(int id, ChapterStateOuterClass.ChapterState state) { + super(PacketOpcodes.ChapterStateNotify); + + var proto = ChapterStateNotifyOuterClass.ChapterStateNotify.newBuilder(); + + proto.setChapterId(id).setChapterState(state); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketChooseCurAvatarTeamRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketChooseCurAvatarTeamRsp.java index 27319ca9c..4acb3349d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketChooseCurAvatarTeamRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketChooseCurAvatarTeamRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChooseCurAvatarTeamRspOuterClass.ChooseCurAvatarTeamRsp; - -public class PacketChooseCurAvatarTeamRsp extends BasePacket { - - public PacketChooseCurAvatarTeamRsp(int teamId) { - super(PacketOpcodes.ChooseCurAvatarTeamRsp); - - ChooseCurAvatarTeamRsp proto = ChooseCurAvatarTeamRsp.newBuilder() - .setCurTeamId(teamId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChooseCurAvatarTeamRspOuterClass.ChooseCurAvatarTeamRsp; + +public class PacketChooseCurAvatarTeamRsp extends BasePacket { + + public PacketChooseCurAvatarTeamRsp(int teamId) { + super(PacketOpcodes.ChooseCurAvatarTeamRsp); + + ChooseCurAvatarTeamRsp proto = ChooseCurAvatarTeamRsp.newBuilder().setCurTeamId(teamId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketClientAbilityInitFinishNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketClientAbilityInitFinishNotify.java index 33cdb6cf8..8bfdc3ce4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketClientAbilityInitFinishNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketClientAbilityInitFinishNotify.java @@ -1,29 +1,29 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; -import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; - -import java.util.List; - -public class PacketClientAbilityInitFinishNotify extends BasePacket { - - public PacketClientAbilityInitFinishNotify(List entries) { - super(PacketOpcodes.ClientAbilityInitFinishNotify, true); - - int entityId = 0; - - if (entries.size() > 0) { - AbilityInvokeEntry entry = entries.get(0); - entityId = entry.getEntityId(); - } - - ClientAbilityInitFinishNotify proto = ClientAbilityInitFinishNotify.newBuilder() - .setEntityId(entityId) - .addAllInvokes(entries) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; +import java.util.List; + +public class PacketClientAbilityInitFinishNotify extends BasePacket { + + public PacketClientAbilityInitFinishNotify(List entries) { + super(PacketOpcodes.ClientAbilityInitFinishNotify, true); + + int entityId = 0; + + if (entries.size() > 0) { + AbilityInvokeEntry entry = entries.get(0); + entityId = entry.getEntityId(); + } + + ClientAbilityInitFinishNotify proto = + ClientAbilityInitFinishNotify.newBuilder() + .setEntityId(entityId) + .addAllInvokes(entries) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java index 071b3519e..3430c36b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java @@ -1,94 +1,116 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CodexDataFullNotifyOuterClass.CodexDataFullNotify; -import emu.grasscutter.net.proto.CodexTypeDataOuterClass.CodexTypeData; - -import java.util.Collections; - -public class PacketCodexDataFullNotify extends BasePacket { - public PacketCodexDataFullNotify(Player player) { - super(PacketOpcodes.CodexDataFullNotify, true); - - //Quests - CodexTypeData.Builder questTypeData = CodexTypeData.newBuilder() - .setTypeValue(1); - - //Weapons - CodexTypeData.Builder weaponTypeData = CodexTypeData.newBuilder() - .setTypeValue(2); - - //Animals - CodexTypeData.Builder animalTypeData = CodexTypeData.newBuilder() - .setTypeValue(3); - - //Materials - CodexTypeData.Builder materialTypeData = CodexTypeData.newBuilder() - .setTypeValue(4); - - //Books - CodexTypeData.Builder bookTypeData = CodexTypeData.newBuilder() - .setTypeValue(5); - - //Tips - CodexTypeData.Builder pushTipsTypeData = CodexTypeData.newBuilder() - .setTypeValue(6); - - //Views - CodexTypeData.Builder viewTypeData = CodexTypeData.newBuilder() - .setTypeValue(7); - - //Reliquary - CodexTypeData.Builder reliquaryData = CodexTypeData.newBuilder() - .setTypeValue(8); - - player.getQuestManager().forEachMainQuest(mainQuest -> { - if (mainQuest.isFinished()) { - var codexQuest = GameData.getCodexQuestDataIdMap().get(mainQuest.getParentQuestId()); - if (codexQuest != null) { - questTypeData.addCodexIdList(codexQuest.getId()).addAllHaveViewedList(Collections.singleton(true)); - } - } - }); - - player.getCodex().getUnlockedWeapon().forEach(weapon -> { - var codexWeapon = GameData.getCodexWeaponDataIdMap().get(weapon); - if (codexWeapon != null) { - weaponTypeData.addCodexIdList(codexWeapon.getId()).addAllHaveViewedList(Collections.singleton(true)); - } - }); - - player.getCodex().getUnlockedAnimal().forEach((animal, amount) -> { - var codexAnimal = GameData.getCodexAnimalDataMap().get(animal); - if (codexAnimal != null) { - animalTypeData.addCodexIdList(codexAnimal.getId()).addAllHaveViewedList(Collections.singleton(true)); - } - }); - - player.getCodex().getUnlockedMaterial().forEach(material -> { - var codexMaterial = GameData.getCodexMaterialDataIdMap().get(material); - if (codexMaterial != null) { - materialTypeData.addCodexIdList(codexMaterial.getId()).addAllHaveViewedList(Collections.singleton(true)); - } - }); - - player.getCodex().getUnlockedReliquarySuitCodex().forEach(reliquarySuit -> { - reliquaryData.addCodexIdList(reliquarySuit).addAllHaveViewedList(Collections.singleton(true)); - }); - - CodexDataFullNotify.Builder proto = CodexDataFullNotify.newBuilder() - .addTypeDataList(questTypeData.build()) - .addTypeDataList(weaponTypeData) - .addTypeDataList(animalTypeData) - .addTypeDataList(materialTypeData) - .addTypeDataList(bookTypeData) - .addTypeDataList(pushTipsTypeData.build()) - .addTypeDataList(viewTypeData.build()) - .addTypeDataList(reliquaryData); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CodexDataFullNotifyOuterClass.CodexDataFullNotify; +import emu.grasscutter.net.proto.CodexTypeDataOuterClass.CodexTypeData; +import java.util.Collections; + +public class PacketCodexDataFullNotify extends BasePacket { + public PacketCodexDataFullNotify(Player player) { + super(PacketOpcodes.CodexDataFullNotify, true); + + // Quests + CodexTypeData.Builder questTypeData = CodexTypeData.newBuilder().setTypeValue(1); + + // Weapons + CodexTypeData.Builder weaponTypeData = CodexTypeData.newBuilder().setTypeValue(2); + + // Animals + CodexTypeData.Builder animalTypeData = CodexTypeData.newBuilder().setTypeValue(3); + + // Materials + CodexTypeData.Builder materialTypeData = CodexTypeData.newBuilder().setTypeValue(4); + + // Books + CodexTypeData.Builder bookTypeData = CodexTypeData.newBuilder().setTypeValue(5); + + // Tips + CodexTypeData.Builder pushTipsTypeData = CodexTypeData.newBuilder().setTypeValue(6); + + // Views + CodexTypeData.Builder viewTypeData = CodexTypeData.newBuilder().setTypeValue(7); + + // Reliquary + CodexTypeData.Builder reliquaryData = CodexTypeData.newBuilder().setTypeValue(8); + + player + .getQuestManager() + .forEachMainQuest( + mainQuest -> { + if (mainQuest.isFinished()) { + var codexQuest = + GameData.getCodexQuestDataIdMap().get(mainQuest.getParentQuestId()); + if (codexQuest != null) { + questTypeData + .addCodexIdList(codexQuest.getId()) + .addAllHaveViewedList(Collections.singleton(true)); + } + } + }); + + player + .getCodex() + .getUnlockedWeapon() + .forEach( + weapon -> { + var codexWeapon = GameData.getCodexWeaponDataIdMap().get(weapon); + if (codexWeapon != null) { + weaponTypeData + .addCodexIdList(codexWeapon.getId()) + .addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player + .getCodex() + .getUnlockedAnimal() + .forEach( + (animal, amount) -> { + var codexAnimal = GameData.getCodexAnimalDataMap().get(animal); + if (codexAnimal != null) { + animalTypeData + .addCodexIdList(codexAnimal.getId()) + .addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player + .getCodex() + .getUnlockedMaterial() + .forEach( + material -> { + var codexMaterial = GameData.getCodexMaterialDataIdMap().get(material); + if (codexMaterial != null) { + materialTypeData + .addCodexIdList(codexMaterial.getId()) + .addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player + .getCodex() + .getUnlockedReliquarySuitCodex() + .forEach( + reliquarySuit -> { + reliquaryData + .addCodexIdList(reliquarySuit) + .addAllHaveViewedList(Collections.singleton(true)); + }); + + CodexDataFullNotify.Builder proto = + CodexDataFullNotify.newBuilder() + .addTypeDataList(questTypeData.build()) + .addTypeDataList(weaponTypeData) + .addTypeDataList(animalTypeData) + .addTypeDataList(materialTypeData) + .addTypeDataList(bookTypeData) + .addTypeDataList(pushTipsTypeData.build()) + .addTypeDataList(viewTypeData.build()) + .addTypeDataList(reliquaryData); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java index e287307d1..760e0a40c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java @@ -1,30 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CodexDataUpdateNotifyOuterClass.CodexDataUpdateNotify; - -public class PacketCodexDataUpdateNotify extends BasePacket { - public PacketCodexDataUpdateNotify(GameMainQuest quest) { - super(PacketOpcodes.CodexDataUpdateNotify, true); - var codexQuest = GameData.getCodexQuestDataIdMap().get(quest.getParentQuestId()); - if (codexQuest != null) { - CodexDataUpdateNotify proto = CodexDataUpdateNotify.newBuilder() - .setTypeValue(1) - .setId(codexQuest.getId()) - .build(); - this.setData(proto); - } - } - - public PacketCodexDataUpdateNotify(int typeValue, int codexId) { - super(PacketOpcodes.CodexDataUpdateNotify, true); - CodexDataUpdateNotify proto = CodexDataUpdateNotify.newBuilder() - .setTypeValue(typeValue) - .setId(codexId) - .build(); - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CodexDataUpdateNotifyOuterClass.CodexDataUpdateNotify; + +public class PacketCodexDataUpdateNotify extends BasePacket { + public PacketCodexDataUpdateNotify(GameMainQuest quest) { + super(PacketOpcodes.CodexDataUpdateNotify, true); + var codexQuest = GameData.getCodexQuestDataIdMap().get(quest.getParentQuestId()); + if (codexQuest != null) { + CodexDataUpdateNotify proto = + CodexDataUpdateNotify.newBuilder().setTypeValue(1).setId(codexQuest.getId()).build(); + this.setData(proto); + } + } + + public PacketCodexDataUpdateNotify(int typeValue, int codexId) { + super(PacketOpcodes.CodexDataUpdateNotify, true); + CodexDataUpdateNotify proto = + CodexDataUpdateNotify.newBuilder().setTypeValue(typeValue).setId(codexId).build(); + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCombatInvocationsNotify.java index 5ab6776f6..ef6feb003 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCombatInvocationsNotify.java @@ -1,32 +1,28 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; -import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; - -import java.util.List; - -public class PacketCombatInvocationsNotify extends BasePacket { - - public PacketCombatInvocationsNotify(CombatInvokeEntry entry) { - super(PacketOpcodes.CombatInvocationsNotify, true); - - CombatInvocationsNotify proto = CombatInvocationsNotify.newBuilder() - .addInvokeList(entry) - .build(); - - this.setData(proto); - } - - public PacketCombatInvocationsNotify(List entries) { - super(PacketOpcodes.CombatInvocationsNotify, true); - - CombatInvocationsNotify proto = CombatInvocationsNotify.newBuilder() - .addAllInvokeList(entries) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; +import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; +import java.util.List; + +public class PacketCombatInvocationsNotify extends BasePacket { + + public PacketCombatInvocationsNotify(CombatInvokeEntry entry) { + super(PacketOpcodes.CombatInvocationsNotify, true); + + CombatInvocationsNotify proto = + CombatInvocationsNotify.newBuilder().addInvokeList(entry).build(); + + this.setData(proto); + } + + public PacketCombatInvocationsNotify(List entries) { + super(PacketOpcodes.CombatInvocationsNotify, true); + + CombatInvocationsNotify proto = + CombatInvocationsNotify.newBuilder().addAllInvokeList(entries).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineDataNotify.java index b988c3a61..68c1f6602 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineDataNotify.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CombineDataNotifyOuterClass.CombineDataNotify; - -public class PacketCombineDataNotify extends BasePacket { - - public PacketCombineDataNotify(Iterable unlockedCombines) { - super(PacketOpcodes.CombineDataNotify); - - CombineDataNotify proto = CombineDataNotify.newBuilder() - .addAllCombineIdList(unlockedCombines) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CombineDataNotifyOuterClass.CombineDataNotify; + +public class PacketCombineDataNotify extends BasePacket { + + public PacketCombineDataNotify(Iterable unlockedCombines) { + super(PacketOpcodes.CombineDataNotify); + + CombineDataNotify proto = + CombineDataNotify.newBuilder().addAllCombineIdList(unlockedCombines).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineFormulaDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineFormulaDataNotify.java index 558f54fac..397c3116c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineFormulaDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineFormulaDataNotify.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CombineFormulaDataNotifyOuterClass.CombineFormulaDataNotify; - -public class PacketCombineFormulaDataNotify extends BasePacket { - - public PacketCombineFormulaDataNotify(int combineId) { - super(PacketOpcodes.CombineFormulaDataNotify); - - CombineFormulaDataNotify proto = CombineFormulaDataNotify.newBuilder() - .setCombineId(combineId) - .setIsLocked(false) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CombineFormulaDataNotifyOuterClass.CombineFormulaDataNotify; + +public class PacketCombineFormulaDataNotify extends BasePacket { + + public PacketCombineFormulaDataNotify(int combineId) { + super(PacketOpcodes.CombineFormulaDataNotify); + + CombineFormulaDataNotify proto = + CombineFormulaDataNotify.newBuilder().setCombineId(combineId).setIsLocked(false).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineRsp.java index c5fd2b87f..31989aaa2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCombineRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCombineRsp.java @@ -1,57 +1,57 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CombineReqOuterClass; -import emu.grasscutter.net.proto.CombineRspOuterClass; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketCombineRsp extends BasePacket { - - public PacketCombineRsp() { - super(PacketOpcodes.CombineRsp); - - CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build(); - - - this.setData(proto); - } - - public PacketCombineRsp(int retcode) { - super(PacketOpcodes.CombineRsp); - - CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder() - .setRetcode(retcode).build(); - - - this.setData(proto); - } - - public PacketCombineRsp(CombineReqOuterClass.CombineReq combineReq, - Iterable costItemList, - Iterable resultItemList, - Iterable totalRandomItemList, - Iterable totalReturnItemList, - Iterable totalExtraItemList) { - - super(PacketOpcodes.CombineRsp); - - CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) - .setCombineId(combineReq.getCombineId()) - .setCombineCount(combineReq.getCombineCount()) - .setAvatarGuid(combineReq.getAvatarGuid()) - .addAllCostItemList(costItemList) - .addAllResultItemList(resultItemList) - .addAllTotalRandomItemList(totalRandomItemList) - .addAllTotalReturnItemList(totalReturnItemList) - .addAllTotalExtraItemList(totalExtraItemList) - .build(); - - this.setData(proto); - } - - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CombineReqOuterClass; +import emu.grasscutter.net.proto.CombineRspOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketCombineRsp extends BasePacket { + + public PacketCombineRsp() { + super(PacketOpcodes.CombineRsp); + + CombineRspOuterClass.CombineRsp proto = + CombineRspOuterClass.CombineRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } + + public PacketCombineRsp(int retcode) { + super(PacketOpcodes.CombineRsp); + + CombineRspOuterClass.CombineRsp proto = + CombineRspOuterClass.CombineRsp.newBuilder().setRetcode(retcode).build(); + + this.setData(proto); + } + + public PacketCombineRsp( + CombineReqOuterClass.CombineReq combineReq, + Iterable costItemList, + Iterable resultItemList, + Iterable totalRandomItemList, + Iterable totalReturnItemList, + Iterable totalExtraItemList) { + + super(PacketOpcodes.CombineRsp); + + CombineRspOuterClass.CombineRsp proto = + CombineRspOuterClass.CombineRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) + .setCombineId(combineReq.getCombineId()) + .setCombineCount(combineReq.getCombineCount()) + .setAvatarGuid(combineReq.getAvatarGuid()) + .addAllCostItemList(costItemList) + .addAllResultItemList(resultItemList) + .addAllTotalRandomItemList(totalRandomItemList) + .addAllTotalReturnItemList(totalReturnItemList) + .addAllTotalExtraItemList(totalExtraItemList) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCompoundDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCompoundDataNotify.java index f60d6105f..b54ad7598 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCompoundDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCompoundDataNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CompoundDataNotifyOuterClass.CompoundDataNotify; -import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; - -import java.util.List; -import java.util.Set; - -public class PacketCompoundDataNotify extends BasePacket { - - public PacketCompoundDataNotify(Set unlockedCompounds, List compoundQueueData) { - super(PacketOpcodes.CompoundDataNotify); - var proto = CompoundDataNotify.newBuilder() - .addAllUnlockCompoundList(unlockedCompounds) - .addAllCompoundQueueDataList(compoundQueueData) - .build(); - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CompoundDataNotifyOuterClass.CompoundDataNotify; +import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; +import java.util.List; +import java.util.Set; + +public class PacketCompoundDataNotify extends BasePacket { + + public PacketCompoundDataNotify( + Set unlockedCompounds, List compoundQueueData) { + super(PacketOpcodes.CompoundDataNotify); + var proto = + CompoundDataNotify.newBuilder() + .addAllUnlockCompoundList(unlockedCompounds) + .addAllCompoundQueueDataList(compoundQueueData) + .build(); + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCookDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCookDataNotify.java index af85a35b2..b35475681 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCookDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCookDataNotify.java @@ -1,21 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CookDataNotifyOuterClass.CookDataNotify; -import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; - -import java.util.List; - -public class PacketCookDataNotify extends BasePacket { - - public PacketCookDataNotify(List recipes) { - super(PacketOpcodes.CookDataNotify); - - CookDataNotify proto = CookDataNotify.newBuilder() - .addAllRecipeDataList(recipes) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CookDataNotifyOuterClass.CookDataNotify; +import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; +import java.util.List; + +public class PacketCookDataNotify extends BasePacket { + + public PacketCookDataNotify(List recipes) { + super(PacketOpcodes.CookDataNotify); + + CookDataNotify proto = CookDataNotify.newBuilder().addAllRecipeDataList(recipes).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCookRecipeDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCookRecipeDataNotify.java index 587f4c3f5..2fca3b7e4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCookRecipeDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCookRecipeDataNotify.java @@ -1,28 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CookRecipeDataNotifyOuterClass.CookRecipeDataNotify; -import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; - -public class PacketCookRecipeDataNotify extends BasePacket { - public PacketCookRecipeDataNotify(CookRecipeData recipe) { - super(PacketOpcodes.CookRecipeDataNotify); - - CookRecipeDataNotify proto = CookRecipeDataNotify.newBuilder() - .setRecipeData(recipe) - .build(); - - this.setData(proto); - } - - public PacketCookRecipeDataNotify(int recipeId) { - super(PacketOpcodes.CookRecipeDataNotify); - - CookRecipeDataNotify proto = CookRecipeDataNotify.newBuilder() - .setRecipeData(CookRecipeData.newBuilder().setRecipeId(recipeId)) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CookRecipeDataNotifyOuterClass.CookRecipeDataNotify; +import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; + +public class PacketCookRecipeDataNotify extends BasePacket { + public PacketCookRecipeDataNotify(CookRecipeData recipe) { + super(PacketOpcodes.CookRecipeDataNotify); + + CookRecipeDataNotify proto = CookRecipeDataNotify.newBuilder().setRecipeData(recipe).build(); + + this.setData(proto); + } + + public PacketCookRecipeDataNotify(int recipeId) { + super(PacketOpcodes.CookRecipeDataNotify); + + CookRecipeDataNotify proto = + CookRecipeDataNotify.newBuilder() + .setRecipeData(CookRecipeData.newBuilder().setRecipeId(recipeId)) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java index b8dd6a991..fde7add22 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java @@ -1,46 +1,62 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityVehicle; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CreateVehicleRspOuterClass.CreateVehicleRsp; -import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass; -import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; -import emu.grasscutter.utils.Position; - -import java.util.List; - -public class PacketCreateVehicleRsp extends BasePacket { - - public PacketCreateVehicleRsp(Player player, int vehicleId, int pointId, Position pos, Position rot) { - super(PacketOpcodes.CreateVehicleRsp); - CreateVehicleRsp.Builder proto = CreateVehicleRsp.newBuilder(); - - // Eject vehicle members and Kill previous vehicles if there are any - List previousVehicles = player.getScene().getEntities().values().stream() - .filter(entity -> entity instanceof EntityVehicle - && ((EntityVehicle) entity).getGadgetId() == vehicleId - && ((EntityVehicle) entity).getOwner().equals(player)) - .toList(); - - previousVehicles.stream().forEach(entity -> { - List vehicleMembers = ((EntityVehicle) entity).getVehicleMembers().stream().toList(); - - vehicleMembers.stream().forEach(vehicleMember -> { - player.getScene().broadcastPacket(new PacketVehicleInteractRsp(((EntityVehicle) entity), vehicleMember, VehicleInteractTypeOuterClass.VehicleInteractType.VEHICLE_INTERACT_TYPE_OUT)); - }); - - player.getScene().killEntity(entity, 0); - }); - - EntityVehicle vehicle = new EntityVehicle(player.getScene(), player, vehicleId, pointId, pos, rot); - player.getScene().addEntity(vehicle); - - proto.setVehicleId(vehicleId); - proto.setEntityId(vehicle.getId()); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CreateVehicleRspOuterClass.CreateVehicleRsp; +import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass; +import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; +import emu.grasscutter.utils.Position; +import java.util.List; + +public class PacketCreateVehicleRsp extends BasePacket { + + public PacketCreateVehicleRsp( + Player player, int vehicleId, int pointId, Position pos, Position rot) { + super(PacketOpcodes.CreateVehicleRsp); + CreateVehicleRsp.Builder proto = CreateVehicleRsp.newBuilder(); + + // Eject vehicle members and Kill previous vehicles if there are any + List previousVehicles = + player.getScene().getEntities().values().stream() + .filter( + entity -> + entity instanceof EntityVehicle + && ((EntityVehicle) entity).getGadgetId() == vehicleId + && ((EntityVehicle) entity).getOwner().equals(player)) + .toList(); + + previousVehicles.stream() + .forEach( + entity -> { + List vehicleMembers = + ((EntityVehicle) entity).getVehicleMembers().stream().toList(); + + vehicleMembers.stream() + .forEach( + vehicleMember -> { + player + .getScene() + .broadcastPacket( + new PacketVehicleInteractRsp( + ((EntityVehicle) entity), + vehicleMember, + VehicleInteractTypeOuterClass.VehicleInteractType + .VEHICLE_INTERACT_TYPE_OUT)); + }); + + player.getScene().killEntity(entity, 0); + }); + + EntityVehicle vehicle = + new EntityVehicle(player.getScene(), player, vehicleId, pointId, pos, rot); + player.getScene().addEntity(vehicle); + + proto.setVehicleId(vehicleId); + proto.setEntityId(vehicle.getId()); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDealAddFriendRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDealAddFriendRsp.java index 9c8ceba15..9072c97f7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDealAddFriendRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDealAddFriendRsp.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType; -import emu.grasscutter.net.proto.DealAddFriendRspOuterClass.DealAddFriendRsp; - -public class PacketDealAddFriendRsp extends BasePacket { - - public PacketDealAddFriendRsp(int targetUid, DealAddFriendResultType result) { - super(PacketOpcodes.DealAddFriendRsp); - - DealAddFriendRsp proto = DealAddFriendRsp.newBuilder() - .setTargetUid(targetUid) - .setDealAddFriendResult(result) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType; +import emu.grasscutter.net.proto.DealAddFriendRspOuterClass.DealAddFriendRsp; + +public class PacketDealAddFriendRsp extends BasePacket { + + public PacketDealAddFriendRsp(int targetUid, DealAddFriendResultType result) { + super(PacketOpcodes.DealAddFriendRsp); + + DealAddFriendRsp proto = + DealAddFriendRsp.newBuilder() + .setTargetUid(targetUid) + .setDealAddFriendResult(result) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDelBackupAvatarTeamRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDelBackupAvatarTeamRsp.java index 3d4b899d4..4cbe26748 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDelBackupAvatarTeamRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDelBackupAvatarTeamRsp.java @@ -1,23 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DelBackupAvatarTeamRspOuterClass.DelBackupAvatarTeamRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -public class PacketDelBackupAvatarTeamRsp extends BasePacket { - public PacketDelBackupAvatarTeamRsp(Retcode retcode, int id) { - super(PacketOpcodes.DelBackupAvatarTeamRsp); - - DelBackupAvatarTeamRsp proto = DelBackupAvatarTeamRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .setBackupAvatarTeamId(id) - .build(); - - this.setData(proto); - } - - public PacketDelBackupAvatarTeamRsp(int id) { - this(Retcode.RET_SUCC, id); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelBackupAvatarTeamRspOuterClass.DelBackupAvatarTeamRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; + +public class PacketDelBackupAvatarTeamRsp extends BasePacket { + public PacketDelBackupAvatarTeamRsp(Retcode retcode, int id) { + super(PacketOpcodes.DelBackupAvatarTeamRsp); + + DelBackupAvatarTeamRsp proto = + DelBackupAvatarTeamRsp.newBuilder() + .setRetcode(retcode.getNumber()) + .setBackupAvatarTeamId(id) + .build(); + + this.setData(proto); + } + + public PacketDelBackupAvatarTeamRsp(int id) { + this(Retcode.RET_SUCC, id); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java index 447f611de..92c6d63a4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java @@ -1,21 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DelMailRspOuterClass.DelMailRsp; - -import java.util.List; - -public class PacketDelMailRsp extends BasePacket { - - public PacketDelMailRsp(Player player, List toDeleteIds) { - super(PacketOpcodes.DelMailRsp); - - DelMailRsp proto = DelMailRsp.newBuilder() - .addAllMailIdList(toDeleteIds) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelMailRspOuterClass.DelMailRsp; +import java.util.List; + +public class PacketDelMailRsp extends BasePacket { + + public PacketDelMailRsp(Player player, List toDeleteIds) { + super(PacketOpcodes.DelMailRsp); + + DelMailRsp proto = DelMailRsp.newBuilder().addAllMailIdList(toDeleteIds).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDelTeamEntityNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDelTeamEntityNotify.java index 20757d705..904b9baa8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDelTeamEntityNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDelTeamEntityNotify.java @@ -1,32 +1,30 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DelTeamEntityNotifyOuterClass.DelTeamEntityNotify; - -import java.util.List; - -public class PacketDelTeamEntityNotify extends BasePacket { - - public PacketDelTeamEntityNotify(int sceneId, int teamEntityId) { - super(PacketOpcodes.DelTeamEntityNotify); - - DelTeamEntityNotify proto = DelTeamEntityNotify.newBuilder() - .setSceneId(sceneId) - .addDelEntityIdList(teamEntityId) - .build(); - - this.setData(proto); - } - - public PacketDelTeamEntityNotify(int sceneId, List list) { - super(PacketOpcodes.DelTeamEntityNotify); - - DelTeamEntityNotify proto = DelTeamEntityNotify.newBuilder() - .setSceneId(sceneId) - .addAllDelEntityIdList(list) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelTeamEntityNotifyOuterClass.DelTeamEntityNotify; +import java.util.List; + +public class PacketDelTeamEntityNotify extends BasePacket { + + public PacketDelTeamEntityNotify(int sceneId, int teamEntityId) { + super(PacketOpcodes.DelTeamEntityNotify); + + DelTeamEntityNotify proto = + DelTeamEntityNotify.newBuilder() + .setSceneId(sceneId) + .addDelEntityIdList(teamEntityId) + .build(); + + this.setData(proto); + } + + public PacketDelTeamEntityNotify(int sceneId, List list) { + super(PacketOpcodes.DelTeamEntityNotify); + + DelTeamEntityNotify proto = + DelTeamEntityNotify.newBuilder().setSceneId(sceneId).addAllDelEntityIdList(list).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendNotify.java index 34af03339..72105374e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendNotify.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DeleteFriendNotifyOuterClass.DeleteFriendNotify; - -public class PacketDeleteFriendNotify extends BasePacket { - - public PacketDeleteFriendNotify(int targetUid) { - super(PacketOpcodes.DeleteFriendNotify); - - DeleteFriendNotify proto = DeleteFriendNotify.newBuilder() - .setTargetUid(targetUid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DeleteFriendNotifyOuterClass.DeleteFriendNotify; + +public class PacketDeleteFriendNotify extends BasePacket { + + public PacketDeleteFriendNotify(int targetUid) { + super(PacketOpcodes.DeleteFriendNotify); + + DeleteFriendNotify proto = DeleteFriendNotify.newBuilder().setTargetUid(targetUid).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendRsp.java index 4e35d95aa..2bb475702 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDeleteFriendRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DeleteFriendRspOuterClass.DeleteFriendRsp; - -public class PacketDeleteFriendRsp extends BasePacket { - - public PacketDeleteFriendRsp(int targetUid) { - super(PacketOpcodes.DeleteFriendRsp); - - DeleteFriendRsp proto = DeleteFriendRsp.newBuilder() - .setTargetUid(targetUid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DeleteFriendRspOuterClass.DeleteFriendRsp; + +public class PacketDeleteFriendRsp extends BasePacket { + + public PacketDeleteFriendRsp(int targetUid) { + super(PacketOpcodes.DeleteFriendRsp); + + DeleteFriendRsp proto = DeleteFriendRsp.newBuilder().setTargetUid(targetUid).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDestroyMaterialRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDestroyMaterialRsp.java index 373ab0539..e137d2174 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDestroyMaterialRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDestroyMaterialRsp.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DestroyMaterialRspOuterClass.DestroyMaterialRsp; -import it.unimi.dsi.fastutil.ints.Int2IntMap; - -public class PacketDestroyMaterialRsp extends BasePacket { - - public PacketDestroyMaterialRsp(Int2IntMap returnMaterialMap) { - super(PacketOpcodes.DestroyMaterialRsp); - - var proto = DestroyMaterialRsp.newBuilder(); - - returnMaterialMap.forEach((id, count) -> { - proto.addItemIdList(id); - proto.addItemCountList(count); - }); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DestroyMaterialRspOuterClass.DestroyMaterialRsp; +import it.unimi.dsi.fastutil.ints.Int2IntMap; + +public class PacketDestroyMaterialRsp extends BasePacket { + + public PacketDestroyMaterialRsp(Int2IntMap returnMaterialMap) { + super(PacketOpcodes.DestroyMaterialRsp); + + var proto = DestroyMaterialRsp.newBuilder(); + + returnMaterialMap.forEach( + (id, count) -> { + proto.addItemIdList(id); + proto.addItemCountList(count); + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java index d06306048..7d22d01ba 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java @@ -1,68 +1,67 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.game.gacha.GachaBanner; -import emu.grasscutter.game.gacha.PlayerGachaBannerInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DoGachaRspOuterClass.DoGachaRsp; -import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; - -public class PacketDoGachaRsp extends BasePacket { - - public PacketDoGachaRsp(GachaBanner banner, List list, PlayerGachaBannerInfo gachaInfo) { - super(PacketOpcodes.DoGachaRsp); - - ItemParamData costItem = banner.getCost(1); - ItemParamData costItem10 = banner.getCost(10); - int gachaTimesLimit = banner.getGachaTimesLimit(); - int leftGachaTimes = switch (gachaTimesLimit) { - case Integer.MAX_VALUE -> Integer.MAX_VALUE; - default -> Math.max(gachaTimesLimit - gachaInfo.getTotalPulls(), 0); - }; - DoGachaRsp.Builder rsp = DoGachaRsp.newBuilder() - .setGachaType(banner.getGachaType()) - .setGachaScheduleId(banner.getScheduleId()) - .setGachaTimes(list.size()) - .setNewGachaRandom(12345) - .setLeftGachaTimes(leftGachaTimes) - .setGachaTimesLimit(gachaTimesLimit) - .setCostItemId(costItem.getId()) - .setCostItemNum(costItem.getCount()) - .setTenCostItemId(costItem10.getId()) - .setTenCostItemNum(costItem10.getCount()) - .addAllGachaItemList(list); - - if (banner.hasEpitomized()) { - rsp.setWishItemId(gachaInfo.getWishItemId()) - .setWishProgress(gachaInfo.getFailedChosenItemPulls()) - .setWishMaxProgress(banner.getWishMaxProgress()); - } - - this.setData(rsp.build()); - } - - public PacketDoGachaRsp() { - super(PacketOpcodes.DoGachaRsp); - - DoGachaRsp p = DoGachaRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(p); - } - - public PacketDoGachaRsp(Retcode retcode) { - super(PacketOpcodes.DoGachaRsp); - - DoGachaRsp p = DoGachaRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.gacha.GachaBanner; +import emu.grasscutter.game.gacha.PlayerGachaBannerInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DoGachaRspOuterClass.DoGachaRsp; +import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; + +public class PacketDoGachaRsp extends BasePacket { + + public PacketDoGachaRsp( + GachaBanner banner, List list, PlayerGachaBannerInfo gachaInfo) { + super(PacketOpcodes.DoGachaRsp); + + ItemParamData costItem = banner.getCost(1); + ItemParamData costItem10 = banner.getCost(10); + int gachaTimesLimit = banner.getGachaTimesLimit(); + int leftGachaTimes = + switch (gachaTimesLimit) { + case Integer.MAX_VALUE -> Integer.MAX_VALUE; + default -> Math.max(gachaTimesLimit - gachaInfo.getTotalPulls(), 0); + }; + DoGachaRsp.Builder rsp = + DoGachaRsp.newBuilder() + .setGachaType(banner.getGachaType()) + .setGachaScheduleId(banner.getScheduleId()) + .setGachaTimes(list.size()) + .setNewGachaRandom(12345) + .setLeftGachaTimes(leftGachaTimes) + .setGachaTimesLimit(gachaTimesLimit) + .setCostItemId(costItem.getId()) + .setCostItemNum(costItem.getCount()) + .setTenCostItemId(costItem10.getId()) + .setTenCostItemNum(costItem10.getCount()) + .addAllGachaItemList(list); + + if (banner.hasEpitomized()) { + rsp.setWishItemId(gachaInfo.getWishItemId()) + .setWishProgress(gachaInfo.getFailedChosenItemPulls()) + .setWishMaxProgress(banner.getWishMaxProgress()); + } + + this.setData(rsp.build()); + } + + public PacketDoGachaRsp() { + super(PacketOpcodes.DoGachaRsp); + + DoGachaRsp p = + DoGachaRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build(); + + this.setData(p); + } + + public PacketDoGachaRsp(Retcode retcode) { + super(PacketOpcodes.DoGachaRsp); + + DoGachaRsp p = DoGachaRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeBeginNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeBeginNotify.java index a50c26bb8..6eca4bf33 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeBeginNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeBeginNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonChallengeBeginNotifyOuterClass.DungeonChallengeBeginNotify; - -public class PacketDungeonChallengeBeginNotify extends BasePacket { - - public PacketDungeonChallengeBeginNotify(WorldChallenge challenge) { - super(PacketOpcodes.DungeonChallengeBeginNotify, true); - - DungeonChallengeBeginNotify proto = DungeonChallengeBeginNotify.newBuilder() - .setChallengeId(challenge.getChallengeId()) - .setChallengeIndex(challenge.getChallengeIndex()) - .setGroupId(challenge.getGroup().id) - .addAllParamList(challenge.getParamList()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonChallengeBeginNotifyOuterClass.DungeonChallengeBeginNotify; + +public class PacketDungeonChallengeBeginNotify extends BasePacket { + + public PacketDungeonChallengeBeginNotify(WorldChallenge challenge) { + super(PacketOpcodes.DungeonChallengeBeginNotify, true); + + DungeonChallengeBeginNotify proto = + DungeonChallengeBeginNotify.newBuilder() + .setChallengeId(challenge.getChallengeId()) + .setChallengeIndex(challenge.getChallengeIndex()) + .setGroupId(challenge.getGroup().id) + .addAllParamList(challenge.getParamList()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java index 761a4c711..01922f6c4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonChallengeFinishNotifyOuterClass.DungeonChallengeFinishNotify; - -public class PacketDungeonChallengeFinishNotify extends BasePacket { - - public PacketDungeonChallengeFinishNotify(WorldChallenge challenge) { - super(PacketOpcodes.DungeonChallengeFinishNotify, true); - - DungeonChallengeFinishNotify proto = DungeonChallengeFinishNotify.newBuilder() - .setChallengeIndex(challenge.getChallengeIndex()) - .setIsSuccess(challenge.isSuccess()) - .setChallengeRecordType(2) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonChallengeFinishNotifyOuterClass.DungeonChallengeFinishNotify; + +public class PacketDungeonChallengeFinishNotify extends BasePacket { + + public PacketDungeonChallengeFinishNotify(WorldChallenge challenge) { + super(PacketOpcodes.DungeonChallengeFinishNotify, true); + + DungeonChallengeFinishNotify proto = + DungeonChallengeFinishNotify.newBuilder() + .setChallengeIndex(challenge.getChallengeIndex()) + .setIsSuccess(challenge.isSuccess()) + .setChallengeRecordType(2) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonEntryInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonEntryInfoRsp.java index 2f5106c56..815b85b56 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonEntryInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonEntryInfoRsp.java @@ -1,37 +1,35 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.common.PointData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo; -import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp; - -public class PacketDungeonEntryInfoRsp extends BasePacket { - - public PacketDungeonEntryInfoRsp(Player player, PointData pointData) { - super(PacketOpcodes.DungeonEntryInfoRsp); - - DungeonEntryInfoRsp.Builder proto = DungeonEntryInfoRsp.newBuilder() - .setPointId(pointData.getId()); - - if (pointData.getDungeonIds() != null) { - for (int dungeonId : pointData.getDungeonIds()) { - DungeonEntryInfo info = DungeonEntryInfo.newBuilder().setDungeonId(dungeonId).build(); - proto.addDungeonEntryList(info); - } - } - - this.setData(proto); - } - - public PacketDungeonEntryInfoRsp() { - super(PacketOpcodes.DungeonEntryInfoRsp); - - DungeonEntryInfoRsp proto = DungeonEntryInfoRsp.newBuilder() - .setRetcode(1) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.common.PointData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo; +import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp; + +public class PacketDungeonEntryInfoRsp extends BasePacket { + + public PacketDungeonEntryInfoRsp(Player player, PointData pointData) { + super(PacketOpcodes.DungeonEntryInfoRsp); + + DungeonEntryInfoRsp.Builder proto = + DungeonEntryInfoRsp.newBuilder().setPointId(pointData.getId()); + + if (pointData.getDungeonIds() != null) { + for (int dungeonId : pointData.getDungeonIds()) { + DungeonEntryInfo info = DungeonEntryInfo.newBuilder().setDungeonId(dungeonId).build(); + proto.addDungeonEntryList(info); + } + } + + this.setData(proto); + } + + public PacketDungeonEntryInfoRsp() { + super(PacketOpcodes.DungeonEntryInfoRsp); + + DungeonEntryInfoRsp proto = DungeonEntryInfoRsp.newBuilder().setRetcode(1).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java index 61b51614f..31dd3c9f2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java @@ -1,62 +1,64 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.dungeons.challenge.WorldChallenge; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass.DungeonSettleNotify; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.TowerLevelEndNotifyOuterClass.TowerLevelEndNotify; - -public class PacketDungeonSettleNotify extends BasePacket { - - public PacketDungeonSettleNotify(WorldChallenge challenge) { - super(PacketOpcodes.DungeonSettleNotify); - - DungeonSettleNotify proto = DungeonSettleNotify.newBuilder() - .setDungeonId(challenge.getScene().getDungeonData().getId()) - .setIsSuccess(challenge.isSuccess()) - .setCloseTime(challenge.getScene().getAutoCloseTime()) - .setResult(challenge.isSuccess() ? 1 : 0) - .build(); - - this.setData(proto); - } - - public PacketDungeonSettleNotify(WorldChallenge challenge, - boolean canJump, - boolean hasNextLevel, - int nextFloorId - ) { - super(PacketOpcodes.DungeonSettleNotify); - - var continueStatus = TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_NOT_CONTINUE_VALUE; - if (challenge.isSuccess() && canJump) { - continueStatus = hasNextLevel ? TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_LEVEL_VALUE - : TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_FLOOR_VALUE; - } - - var towerLevelEndNotify = TowerLevelEndNotify.newBuilder() - .setIsSuccess(challenge.isSuccess()) - .setContinueState(continueStatus) - .addFinishedStarCondList(1) - .addFinishedStarCondList(2) - .addFinishedStarCondList(3) - .addRewardItemList(ItemParamOuterClass.ItemParam.newBuilder() - .setItemId(201) - .setCount(1000) - .build()); - if (nextFloorId > 0 && canJump) { - towerLevelEndNotify.setNextFloorId(nextFloorId); - } - - DungeonSettleNotify proto = DungeonSettleNotify.newBuilder() - .setDungeonId(challenge.getScene().getDungeonData().getId()) - .setIsSuccess(challenge.isSuccess()) - .setCloseTime(challenge.getScene().getAutoCloseTime()) - .setResult(challenge.isSuccess() ? 1 : 0) - .setTowerLevelEndNotify(towerLevelEndNotify.build()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.dungeons.challenge.WorldChallenge; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass.DungeonSettleNotify; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.TowerLevelEndNotifyOuterClass.TowerLevelEndNotify; + +public class PacketDungeonSettleNotify extends BasePacket { + + public PacketDungeonSettleNotify(WorldChallenge challenge) { + super(PacketOpcodes.DungeonSettleNotify); + + DungeonSettleNotify proto = + DungeonSettleNotify.newBuilder() + .setDungeonId(challenge.getScene().getDungeonData().getId()) + .setIsSuccess(challenge.isSuccess()) + .setCloseTime(challenge.getScene().getAutoCloseTime()) + .setResult(challenge.isSuccess() ? 1 : 0) + .build(); + + this.setData(proto); + } + + public PacketDungeonSettleNotify( + WorldChallenge challenge, boolean canJump, boolean hasNextLevel, int nextFloorId) { + super(PacketOpcodes.DungeonSettleNotify); + + var continueStatus = + TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_NOT_CONTINUE_VALUE; + if (challenge.isSuccess() && canJump) { + continueStatus = + hasNextLevel + ? TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_LEVEL_VALUE + : TowerLevelEndNotify.ContinueStateType + .CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_FLOOR_VALUE; + } + + var towerLevelEndNotify = + TowerLevelEndNotify.newBuilder() + .setIsSuccess(challenge.isSuccess()) + .setContinueState(continueStatus) + .addFinishedStarCondList(1) + .addFinishedStarCondList(2) + .addFinishedStarCondList(3) + .addRewardItemList( + ItemParamOuterClass.ItemParam.newBuilder().setItemId(201).setCount(1000).build()); + if (nextFloorId > 0 && canJump) { + towerLevelEndNotify.setNextFloorId(nextFloorId); + } + + DungeonSettleNotify proto = + DungeonSettleNotify.newBuilder() + .setDungeonId(challenge.getScene().getDungeonData().getId()) + .setIsSuccess(challenge.isSuccess()) + .setCloseTime(challenge.getScene().getAutoCloseTime()) + .setResult(challenge.isSuccess() ? 1 : 0) + .setTowerLevelEndNotify(towerLevelEndNotify.build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonShowReminderNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonShowReminderNotify.java index c0c612ff8..48b05d3cc 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonShowReminderNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonShowReminderNotify.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DungeonShowReminderNotifyOuterClass; - -public class PacketDungeonShowReminderNotify extends BasePacket { - - public PacketDungeonShowReminderNotify(int reminderId) { - super(PacketOpcodes.DungeonShowReminderNotify); - - var proto = DungeonShowReminderNotifyOuterClass.DungeonShowReminderNotify.newBuilder(); - - proto.setReminderId(reminderId); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DungeonShowReminderNotifyOuterClass; + +public class PacketDungeonShowReminderNotify extends BasePacket { + + public PacketDungeonShowReminderNotify(int reminderId) { + super(PacketOpcodes.DungeonShowReminderNotify); + + var proto = DungeonShowReminderNotifyOuterClass.DungeonShowReminderNotify.newBuilder(); + + proto.setReminderId(reminderId); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneDoneRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneDoneRsp.java index caf39c462..fe774e82f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneDoneRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneDoneRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterSceneDoneRspOuterClass.EnterSceneDoneRsp; - -public class PacketEnterSceneDoneRsp extends BasePacket { - - public PacketEnterSceneDoneRsp(Player player) { - super(PacketOpcodes.EnterSceneDoneRsp); - - EnterSceneDoneRsp p = EnterSceneDoneRsp.newBuilder() - .setEnterSceneToken(player.getEnterSceneToken()) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterSceneDoneRspOuterClass.EnterSceneDoneRsp; + +public class PacketEnterSceneDoneRsp extends BasePacket { + + public PacketEnterSceneDoneRsp(Player player) { + super(PacketOpcodes.EnterSceneDoneRsp); + + EnterSceneDoneRsp p = + EnterSceneDoneRsp.newBuilder().setEnterSceneToken(player.getEnterSceneToken()).build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterScenePeerNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterScenePeerNotify.java index 2ed018b51..ca4974e4d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterScenePeerNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterScenePeerNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterScenePeerNotifyOuterClass.EnterScenePeerNotify; - -public class PacketEnterScenePeerNotify extends BasePacket { - - public PacketEnterScenePeerNotify(Player player) { - super(PacketOpcodes.EnterScenePeerNotify); - - EnterScenePeerNotify proto = EnterScenePeerNotify.newBuilder() - .setDestSceneId(player.getSceneId()) - .setPeerId(player.getPeerId()) - .setHostPeerId(player.getWorld().getHost().getPeerId()) - .setEnterSceneToken(player.getEnterSceneToken()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterScenePeerNotifyOuterClass.EnterScenePeerNotify; + +public class PacketEnterScenePeerNotify extends BasePacket { + + public PacketEnterScenePeerNotify(Player player) { + super(PacketOpcodes.EnterScenePeerNotify); + + EnterScenePeerNotify proto = + EnterScenePeerNotify.newBuilder() + .setDestSceneId(player.getSceneId()) + .setPeerId(player.getPeerId()) + .setHostPeerId(player.getWorld().getHost().getPeerId()) + .setEnterSceneToken(player.getEnterSceneToken()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneReadyRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneReadyRsp.java index a081d92db..9dd481c0c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneReadyRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterSceneReadyRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterSceneReadyRspOuterClass.EnterSceneReadyRsp; - -public class PacketEnterSceneReadyRsp extends BasePacket { - - public PacketEnterSceneReadyRsp(Player player) { - super(PacketOpcodes.EnterSceneReadyRsp, 11); - - EnterSceneReadyRsp p = EnterSceneReadyRsp.newBuilder() - .setEnterSceneToken(player.getEnterSceneToken()) - .build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterSceneReadyRspOuterClass.EnterSceneReadyRsp; + +public class PacketEnterSceneReadyRsp extends BasePacket { + + public PacketEnterSceneReadyRsp(Player player) { + super(PacketOpcodes.EnterSceneReadyRsp, 11); + + EnterSceneReadyRsp p = + EnterSceneReadyRsp.newBuilder().setEnterSceneToken(player.getEnterSceneToken()).build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterWorldAreaRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterWorldAreaRsp.java index cbba22a00..e978c0d6c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEnterWorldAreaRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEnterWorldAreaRsp.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterWorldAreaReqOuterClass.EnterWorldAreaReq; -import emu.grasscutter.net.proto.EnterWorldAreaRspOuterClass.EnterWorldAreaRsp; - -public class PacketEnterWorldAreaRsp extends BasePacket { - - public PacketEnterWorldAreaRsp(int clientSequence, EnterWorldAreaReq enterWorld) { - super(PacketOpcodes.EnterWorldAreaRsp, clientSequence); - - EnterWorldAreaRsp p = EnterWorldAreaRsp.newBuilder() - .setAreaType(enterWorld.getAreaType()) - .setAreaId(enterWorld.getAreaId()) - .build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterWorldAreaReqOuterClass.EnterWorldAreaReq; +import emu.grasscutter.net.proto.EnterWorldAreaRspOuterClass.EnterWorldAreaRsp; + +public class PacketEnterWorldAreaRsp extends BasePacket { + + public PacketEnterWorldAreaRsp(int clientSequence, EnterWorldAreaReq enterWorld) { + super(PacketOpcodes.EnterWorldAreaRsp, clientSequence); + + EnterWorldAreaRsp p = + EnterWorldAreaRsp.newBuilder() + .setAreaType(enterWorld.getAreaType()) + .setAreaId(enterWorld.getAreaId()) + .build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java index a3f093982..ad8b9640d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AiSyncInfoOuterClass.AiSyncInfo; -import emu.grasscutter.net.proto.EntityAiSyncNotifyOuterClass.EntityAiSyncNotify; - -public class PacketEntityAiSyncNotify extends BasePacket { - - public PacketEntityAiSyncNotify(EntityAiSyncNotify notify) { - super(PacketOpcodes.EntityAiSyncNotify, true); - - EntityAiSyncNotify.Builder proto = EntityAiSyncNotify.newBuilder(); - - for (int monsterId : notify.getLocalAvatarAlertedMonsterListList()) { - proto.addInfoList(AiSyncInfo.newBuilder().setEntityId(monsterId).setHasPathToTarget(true)); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AiSyncInfoOuterClass.AiSyncInfo; +import emu.grasscutter.net.proto.EntityAiSyncNotifyOuterClass.EntityAiSyncNotify; + +public class PacketEntityAiSyncNotify extends BasePacket { + + public PacketEntityAiSyncNotify(EntityAiSyncNotify notify) { + super(PacketOpcodes.EntityAiSyncNotify, true); + + EntityAiSyncNotify.Builder proto = EntityAiSyncNotify.newBuilder(); + + for (int monsterId : notify.getLocalAvatarAlertedMonsterListList()) { + proto.addInfoList(AiSyncInfo.newBuilder().setEntityId(monsterId).setHasPathToTarget(true)); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java index aab41764c..b0300fca0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java @@ -1,72 +1,88 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; -import emu.grasscutter.net.proto.EntityFightPropChangeReasonNotifyOuterClass.EntityFightPropChangeReasonNotify; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; - -import java.util.List; - -public class PacketEntityFightPropChangeReasonNotify extends BasePacket { - - public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, List param, PropChangeReason reason, ChangeHpReason changeHpReason) { - super(PacketOpcodes.EntityFightPropChangeReasonNotify); - - EntityFightPropChangeReasonNotify.Builder proto = EntityFightPropChangeReasonNotify.newBuilder() - .setEntityId(entity.getId()) - .setPropType(prop.getId()) - .setPropDelta(value) - .setReason(reason) - .setChangeHpReason(changeHpReason); - - for (int p : param) { - proto.addParamList(p); - } - - this.setData(proto); - } - - public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, PropChangeReason reason, ChangeHpReason changeHpReason) { - super(PacketOpcodes.EntityFightPropChangeReasonNotify); - - EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() - .setEntityId(entity.getId()) - .setPropType(prop.getId()) - .setPropDelta(value) - .setReason(reason) - .setChangeHpReason(changeHpReason) - .build(); - - this.setData(proto); - } - - public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, PropChangeReason reason) { - super(PacketOpcodes.EntityFightPropChangeReasonNotify); - - EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() - .setEntityId(entity.getId()) - .setPropType(prop.getId()) - .setPropDelta(value) - .setReason(reason) - .build(); - - this.setData(proto); - } - - public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, ChangeEnergyReason reason) { - super(PacketOpcodes.EntityFightPropChangeReasonNotify); - - EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() - .setEntityId(entity.getId()) - .setPropType(prop.getId()) - .setPropDelta(value) - .setChangeEnergyReason(reason) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.EntityFightPropChangeReasonNotifyOuterClass.EntityFightPropChangeReasonNotify; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import java.util.List; + +public class PacketEntityFightPropChangeReasonNotify extends BasePacket { + + public PacketEntityFightPropChangeReasonNotify( + GameEntity entity, + FightProperty prop, + Float value, + List param, + PropChangeReason reason, + ChangeHpReason changeHpReason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + + EntityFightPropChangeReasonNotify.Builder proto = + EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .setChangeHpReason(changeHpReason); + + for (int p : param) { + proto.addParamList(p); + } + + this.setData(proto); + } + + public PacketEntityFightPropChangeReasonNotify( + GameEntity entity, + FightProperty prop, + Float value, + PropChangeReason reason, + ChangeHpReason changeHpReason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + + EntityFightPropChangeReasonNotify proto = + EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .setChangeHpReason(changeHpReason) + .build(); + + this.setData(proto); + } + + public PacketEntityFightPropChangeReasonNotify( + GameEntity entity, FightProperty prop, Float value, PropChangeReason reason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + + EntityFightPropChangeReasonNotify proto = + EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .build(); + + this.setData(proto); + } + + public PacketEntityFightPropChangeReasonNotify( + GameEntity entity, FightProperty prop, Float value, ChangeEnergyReason reason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + + EntityFightPropChangeReasonNotify proto = + EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setChangeEnergyReason(reason) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropUpdateNotify.java index 335e944fa..bcb4e4b76 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropUpdateNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EntityFightPropUpdateNotifyOuterClass.EntityFightPropUpdateNotify; - -public class PacketEntityFightPropUpdateNotify extends BasePacket { - - public PacketEntityFightPropUpdateNotify(GameEntity entity, FightProperty prop) { - super(PacketOpcodes.EntityFightPropUpdateNotify); - - EntityFightPropUpdateNotify proto = EntityFightPropUpdateNotify.newBuilder() - .setEntityId(entity.getId()) - .putFightPropMap(prop.getId(), entity.getFightProperty(prop)) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EntityFightPropUpdateNotifyOuterClass.EntityFightPropUpdateNotify; + +public class PacketEntityFightPropUpdateNotify extends BasePacket { + + public PacketEntityFightPropUpdateNotify(GameEntity entity, FightProperty prop) { + super(PacketOpcodes.EntityFightPropUpdateNotify); + + EntityFightPropUpdateNotify proto = + EntityFightPropUpdateNotify.newBuilder() + .setEntityId(entity.getId()) + .putFightPropMap(prop.getId(), entity.getFightProperty(prop)) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarLockChairRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarLockChairRsp.java index 0ecf2fca1..140c6a9b3 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarLockChairRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarLockChairRsp.java @@ -1,23 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarLockChairReqOuterClass.EvtAvatarLockChairReq; -import emu.grasscutter.net.proto.EvtAvatarLockChairRspOuterClass.EvtAvatarLockChairRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketEvtAvatarLockChairRsp extends BasePacket { - public PacketEvtAvatarLockChairRsp(int clientSequence, EntityAvatar entityAvatar, EvtAvatarLockChairReq lockChairReq) { - super(PacketOpcodes.EvtAvatarLockChairRsp); - - EvtAvatarLockChairRsp p = EvtAvatarLockChairRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) - .setEntityId(entityAvatar.getId()) - .setPosition(lockChairReq.getPosition()) - .setChairId(lockChairReq.getChairId()) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarLockChairReqOuterClass.EvtAvatarLockChairReq; +import emu.grasscutter.net.proto.EvtAvatarLockChairRspOuterClass.EvtAvatarLockChairRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketEvtAvatarLockChairRsp extends BasePacket { + public PacketEvtAvatarLockChairRsp( + int clientSequence, EntityAvatar entityAvatar, EvtAvatarLockChairReq lockChairReq) { + super(PacketOpcodes.EvtAvatarLockChairRsp); + + EvtAvatarLockChairRsp p = + EvtAvatarLockChairRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE) + .setEntityId(entityAvatar.getId()) + .setPosition(lockChairReq.getPosition()) + .setChairId(lockChairReq.getChairId()) + .build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarSitDownNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarSitDownNotify.java index ebb0503df..70c4ef387 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarSitDownNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarSitDownNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarSitDownNotifyOuterClass.EvtAvatarSitDownNotify; - -public class PacketEvtAvatarSitDownNotify extends BasePacket { - - public PacketEvtAvatarSitDownNotify(EvtAvatarSitDownNotify notify) { - super(PacketOpcodes.EvtAvatarSitDownNotify); - - EvtAvatarSitDownNotify proto = EvtAvatarSitDownNotify.newBuilder() - .setEntityId(notify.getEntityId()) - .setPosition(notify.getPosition()) - .setChairId(notify.getChairId()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarSitDownNotifyOuterClass.EvtAvatarSitDownNotify; + +public class PacketEvtAvatarSitDownNotify extends BasePacket { + + public PacketEvtAvatarSitDownNotify(EvtAvatarSitDownNotify notify) { + super(PacketOpcodes.EvtAvatarSitDownNotify); + + EvtAvatarSitDownNotify proto = + EvtAvatarSitDownNotify.newBuilder() + .setEntityId(notify.getEntityId()) + .setPosition(notify.getPosition()) + .setChairId(notify.getChairId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java index 23d332335..d20a68d32 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtAvatarStandUpNotifyOuterClass.EvtAvatarStandUpNotify; - -public class PacketEvtAvatarStandUpNotify extends BasePacket { - - public PacketEvtAvatarStandUpNotify(EvtAvatarStandUpNotify notify) { - super(PacketOpcodes.EvtAvatarStandUpNotify); - - EvtAvatarStandUpNotify proto = EvtAvatarStandUpNotify.newBuilder() - .setEntityId(notify.getEntityId()) - .setDirection(notify.getDirection()) - .setPerformId(notify.getPerformId()) - .setChairId(notify.getChairId()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtAvatarStandUpNotifyOuterClass.EvtAvatarStandUpNotify; + +public class PacketEvtAvatarStandUpNotify extends BasePacket { + + public PacketEvtAvatarStandUpNotify(EvtAvatarStandUpNotify notify) { + super(PacketOpcodes.EvtAvatarStandUpNotify); + + EvtAvatarStandUpNotify proto = + EvtAvatarStandUpNotify.newBuilder() + .setEntityId(notify.getEntityId()) + .setDirection(notify.getDirection()) + .setPerformId(notify.getPerformId()) + .setChairId(notify.getChairId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtEntityRenderersChangedNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtEntityRenderersChangedNotify.java index b7f821227..b1075f8da 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtEntityRenderersChangedNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtEntityRenderersChangedNotify.java @@ -1,14 +1,15 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EvtEntityRenderersChangedNotifyOuterClass; - -public class PacketEvtEntityRenderersChangedNotify extends BasePacket { - - public PacketEvtEntityRenderersChangedNotify(EvtEntityRenderersChangedNotifyOuterClass.EvtEntityRenderersChangedNotify req) { - super(PacketOpcodes.EvtEntityRenderersChangedNotify, true); - - this.setData(req); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EvtEntityRenderersChangedNotifyOuterClass; + +public class PacketEvtEntityRenderersChangedNotify extends BasePacket { + + public PacketEvtEntityRenderersChangedNotify( + EvtEntityRenderersChangedNotifyOuterClass.EvtEntityRenderersChangedNotify req) { + super(PacketOpcodes.EvtEntityRenderersChangedNotify, true); + + this.setData(req); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java index d4133d2f2..30a8ede32 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java @@ -1,26 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.enums.ParentQuestState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify; - -public class PacketFinishedParentQuestNotify extends BasePacket { - - public PacketFinishedParentQuestNotify(Player player) { - super(PacketOpcodes.FinishedParentQuestNotify, true); - - FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder(); - - for (GameMainQuest mainQuest : player.getQuestManager().getMainQuests().values()) { - //Canceled Quests do not appear in this packet - if (mainQuest.getState() != ParentQuestState.PARENT_QUEST_STATE_CANCELED) { - proto.addParentQuestList(mainQuest.toProto()); - } - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.enums.ParentQuestState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify; + +public class PacketFinishedParentQuestNotify extends BasePacket { + + public PacketFinishedParentQuestNotify(Player player) { + super(PacketOpcodes.FinishedParentQuestNotify, true); + + FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder(); + + for (GameMainQuest mainQuest : player.getQuestManager().getMainQuests().values()) { + // Canceled Quests do not appear in this packet + if (mainQuest.getState() != ParentQuestState.PARENT_QUEST_STATE_CANCELED) { + proto.addParentQuestList(mainQuest.toProto()); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java index 0fb8d0feb..db571e003 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java @@ -1,33 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; - -import java.util.List; - -public class PacketFinishedParentQuestUpdateNotify extends BasePacket { - - public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { - super(PacketOpcodes.FinishedParentQuestUpdateNotify); - - FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder() - .addParentQuestList(quest.toProto()) - .build(); - - this.setData(proto); - } - - public PacketFinishedParentQuestUpdateNotify(List quests) { - super(PacketOpcodes.FinishedParentQuestUpdateNotify); - - var proto = FinishedParentQuestUpdateNotify.newBuilder(); - - for (GameMainQuest mainQuest : quests) { - proto.addParentQuestList(mainQuest.toProto()); - } - proto.build(); - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; +import java.util.List; + +public class PacketFinishedParentQuestUpdateNotify extends BasePacket { + + public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { + super(PacketOpcodes.FinishedParentQuestUpdateNotify); + + FinishedParentQuestUpdateNotify proto = + FinishedParentQuestUpdateNotify.newBuilder().addParentQuestList(quest.toProto()).build(); + + this.setData(proto); + } + + public PacketFinishedParentQuestUpdateNotify(List quests) { + super(PacketOpcodes.FinishedParentQuestUpdateNotify); + + var proto = FinishedParentQuestUpdateNotify.newBuilder(); + + for (GameMainQuest mainQuest : quests) { + proto.addParentQuestList(mainQuest.toProto()); + } + proto.build(); + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java index 8b0580397..23ca2c130 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java @@ -1,26 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeDataNotifyOuterClass.ForgeDataNotify; -import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; - -import java.util.Map; - -public class PacketForgeDataNotify extends BasePacket { - - public PacketForgeDataNotify(Iterable unlockedItem, int numQueues, Map queueData) { - super(PacketOpcodes.ForgeDataNotify); - - ForgeDataNotify.Builder builder = ForgeDataNotify.newBuilder() - .addAllForgeIdList(unlockedItem) - .setMaxQueueNum(numQueues); - - for (int queueId : queueData.keySet()) { - var data = queueData.get(queueId); - builder.putForgeQueueMap(queueId, data); - } - - this.setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeDataNotifyOuterClass.ForgeDataNotify; +import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; +import java.util.Map; + +public class PacketForgeDataNotify extends BasePacket { + + public PacketForgeDataNotify( + Iterable unlockedItem, int numQueues, Map queueData) { + super(PacketOpcodes.ForgeDataNotify); + + ForgeDataNotify.Builder builder = + ForgeDataNotify.newBuilder().addAllForgeIdList(unlockedItem).setMaxQueueNum(numQueues); + + for (int queueId : queueData.keySet()) { + var data = queueData.get(queueId); + builder.putForgeQueueMap(queueId, data); + } + + this.setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java index bb7390fd6..cad180b70 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeFormulaDataNotifyOuterClass.ForgeFormulaDataNotify; - -public class PacketForgeFormulaDataNotify extends BasePacket { - - public PacketForgeFormulaDataNotify(int itemId) { - super(PacketOpcodes.ForgeFormulaDataNotify); - - ForgeFormulaDataNotify proto = ForgeFormulaDataNotify.newBuilder() - .setForgeId(itemId) - .setIsLocked(false) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeFormulaDataNotifyOuterClass.ForgeFormulaDataNotify; + +public class PacketForgeFormulaDataNotify extends BasePacket { + + public PacketForgeFormulaDataNotify(int itemId) { + super(PacketOpcodes.ForgeFormulaDataNotify); + + ForgeFormulaDataNotify proto = + ForgeFormulaDataNotify.newBuilder().setForgeId(itemId).setIsLocked(false).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeGetQueueDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeGetQueueDataRsp.java index dc35f0e68..f03f15987 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeGetQueueDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeGetQueueDataRsp.java @@ -1,27 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeGetQueueDataRspOuterClass.ForgeGetQueueDataRsp; -import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.Map; - -public class PacketForgeGetQueueDataRsp extends BasePacket { - - public PacketForgeGetQueueDataRsp(Retcode retcode, int numQueues, Map queueData) { - super(PacketOpcodes.ForgeGetQueueDataRsp); - - ForgeGetQueueDataRsp.Builder builder = ForgeGetQueueDataRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .setMaxQueueNum(numQueues); - - for (int queueId : queueData.keySet()) { - var data = queueData.get(queueId); - builder.putForgeQueueMap(queueId, data); - } - - this.setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeGetQueueDataRspOuterClass.ForgeGetQueueDataRsp; +import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.Map; + +public class PacketForgeGetQueueDataRsp extends BasePacket { + + public PacketForgeGetQueueDataRsp( + Retcode retcode, int numQueues, Map queueData) { + super(PacketOpcodes.ForgeGetQueueDataRsp); + + ForgeGetQueueDataRsp.Builder builder = + ForgeGetQueueDataRsp.newBuilder().setRetcode(retcode.getNumber()).setMaxQueueNum(numQueues); + + for (int queueId : queueData.keySet()) { + var data = queueData.get(queueId); + builder.putForgeQueueMap(queueId, data); + } + + this.setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueDataNotify.java index 906855c42..6f5fb8ba6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueDataNotify.java @@ -1,26 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeQueueDataNotifyOuterClass.ForgeQueueDataNotify; -import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; - -import java.util.List; -import java.util.Map; - -public class PacketForgeQueueDataNotify extends BasePacket { - - public PacketForgeQueueDataNotify(Map queueData, List removedQueues) { - super(PacketOpcodes.ForgeQueueDataNotify); - - ForgeQueueDataNotify.Builder builder = ForgeQueueDataNotify.newBuilder() - .addAllRemovedForgeQueueList(removedQueues); - - for (int queueId : queueData.keySet()) { - var data = queueData.get(queueId); - builder.putForgeQueueMap(queueId, data); - } - - this.setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeQueueDataNotifyOuterClass.ForgeQueueDataNotify; +import emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData; +import java.util.List; +import java.util.Map; + +public class PacketForgeQueueDataNotify extends BasePacket { + + public PacketForgeQueueDataNotify( + Map queueData, List removedQueues) { + super(PacketOpcodes.ForgeQueueDataNotify); + + ForgeQueueDataNotify.Builder builder = + ForgeQueueDataNotify.newBuilder().addAllRemovedForgeQueueList(removedQueues); + + for (int queueId : queueData.keySet()) { + var data = queueData.get(queueId); + builder.putForgeQueueMap(queueId, data); + } + + this.setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueManipulateRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueManipulateRsp.java index d5bbb938e..20e00143d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueManipulateRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeQueueManipulateRsp.java @@ -1,44 +1,45 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeQueueManipulateRspOuterClass.ForgeQueueManipulateRsp; -import emu.grasscutter.net.proto.ForgeQueueManipulateTypeOuterClass.ForgeQueueManipulateType; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; - -public class PacketForgeQueueManipulateRsp extends BasePacket { - - public PacketForgeQueueManipulateRsp(Retcode retcode, ForgeQueueManipulateType type, List output, List refund, List extra) { - super(PacketOpcodes.ForgeQueueManipulateRsp); - - ForgeQueueManipulateRsp.Builder builder = ForgeQueueManipulateRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .setManipulateType(type); - - for (GameItem item : output) { - ItemParam toAdd = ItemParam.newBuilder() - .setItemId(item.getItemId()) - .setCount(item.getCount()) - .build(); - - builder.addExtraOutputItemList(toAdd); - } - - for (GameItem item : refund) { - ItemParam toAdd = ItemParam.newBuilder() - .setItemId(item.getItemId()) - .setCount(item.getCount()) - .build(); - - builder.addReturnItemList(toAdd); - } - - // ToDo: Add extra items when once we have handling for it. - - this.setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeQueueManipulateRspOuterClass.ForgeQueueManipulateRsp; +import emu.grasscutter.net.proto.ForgeQueueManipulateTypeOuterClass.ForgeQueueManipulateType; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; + +public class PacketForgeQueueManipulateRsp extends BasePacket { + + public PacketForgeQueueManipulateRsp( + Retcode retcode, + ForgeQueueManipulateType type, + List output, + List refund, + List extra) { + super(PacketOpcodes.ForgeQueueManipulateRsp); + + ForgeQueueManipulateRsp.Builder builder = + ForgeQueueManipulateRsp.newBuilder() + .setRetcode(retcode.getNumber()) + .setManipulateType(type); + + for (GameItem item : output) { + ItemParam toAdd = + ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount()).build(); + + builder.addExtraOutputItemList(toAdd); + } + + for (GameItem item : refund) { + ItemParam toAdd = + ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount()).build(); + + builder.addReturnItemList(toAdd); + } + + // ToDo: Add extra items when once we have handling for it. + + this.setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeStartRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeStartRsp.java index 7ff520631..628c1983e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeStartRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeStartRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ForgeStartRspOuterClass.ForgeStartRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -public class PacketForgeStartRsp extends BasePacket { - - public PacketForgeStartRsp(Retcode retcode) { - super(PacketOpcodes.ForgeStartRsp); - - ForgeStartRsp proto = ForgeStartRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeStartRspOuterClass.ForgeStartRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; + +public class PacketForgeStartRsp extends BasePacket { + + public PacketForgeStartRsp(Retcode retcode) { + super(PacketOpcodes.ForgeStartRsp); + + ForgeStartRsp proto = ForgeStartRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureCurModuleArrangeCountNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureCurModuleArrangeCountNotify.java index 847618a74..dbc118979 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureCurModuleArrangeCountNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureCurModuleArrangeCountNotify.java @@ -1,18 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FurnitureCurModuleArrangeCountNotifyOuterClass; - -public class PacketFurnitureCurModuleArrangeCountNotify extends BasePacket { - - public PacketFurnitureCurModuleArrangeCountNotify() { - super(PacketOpcodes.FurnitureCurModuleArrangeCountNotify); - - var proto = FurnitureCurModuleArrangeCountNotifyOuterClass.FurnitureCurModuleArrangeCountNotify.newBuilder(); - - // TODO - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureCurModuleArrangeCountNotifyOuterClass; + +public class PacketFurnitureCurModuleArrangeCountNotify extends BasePacket { + + public PacketFurnitureCurModuleArrangeCountNotify() { + super(PacketOpcodes.FurnitureCurModuleArrangeCountNotify); + + var proto = + FurnitureCurModuleArrangeCountNotifyOuterClass.FurnitureCurModuleArrangeCountNotify + .newBuilder(); + + // TODO + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java index 0350f5ed5..e897084f6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeRsp.java @@ -1,25 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.home.FurnitureMakeSlotItem; -import emu.grasscutter.game.home.GameHome; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FurnitureMakeRspOuterClass; -import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; - -public class PacketFurnitureMakeRsp extends BasePacket { - - public PacketFurnitureMakeRsp(GameHome home) { - super(PacketOpcodes.FurnitureMakeRsp); - - var proto = FurnitureMakeRspOuterClass.FurnitureMakeRsp.newBuilder(); - - proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() - .addAllFurnitureMakeDataList(home.getFurnitureMakeSlotItemList().stream() - .map(FurnitureMakeSlotItem::toProto) - .toList()) - .build()); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.home.FurnitureMakeSlotItem; +import emu.grasscutter.game.home.GameHome; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeRspOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; + +public class PacketFurnitureMakeRsp extends BasePacket { + + public PacketFurnitureMakeRsp(GameHome home) { + super(PacketOpcodes.FurnitureMakeRsp); + + var proto = FurnitureMakeRspOuterClass.FurnitureMakeRsp.newBuilder(); + + proto.setFurnitureMakeSlot( + FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList( + home.getFurnitureMakeSlotItemList().stream() + .map(FurnitureMakeSlotItem::toProto) + .toList()) + .build()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java index 6e3a33b0e..94745435a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFurnitureMakeStartRsp.java @@ -1,28 +1,29 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; -import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; -import emu.grasscutter.net.proto.FurnitureMakeStartRspOuterClass; - -import java.util.List; - -public class PacketFurnitureMakeStartRsp extends BasePacket { - - public PacketFurnitureMakeStartRsp(int ret, List furnitureMakeData) { - super(PacketOpcodes.FurnitureMakeStartRsp); - - var proto = FurnitureMakeStartRspOuterClass.FurnitureMakeStartRsp.newBuilder(); - - proto.setRetcode(ret); - - if (furnitureMakeData != null) { - proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() - .addAllFurnitureMakeDataList(furnitureMakeData) - .build()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeStartRspOuterClass; +import java.util.List; + +public class PacketFurnitureMakeStartRsp extends BasePacket { + + public PacketFurnitureMakeStartRsp( + int ret, List furnitureMakeData) { + super(PacketOpcodes.FurnitureMakeStartRsp); + + var proto = FurnitureMakeStartRspOuterClass.FurnitureMakeStartRsp.newBuilder(); + + proto.setRetcode(ret); + + if (furnitureMakeData != null) { + proto.setFurnitureMakeSlot( + FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList(furnitureMakeData) + .build()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGachaWishRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGachaWishRsp.java index 8e35f566d..f87ce5bbb 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGachaWishRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGachaWishRsp.java @@ -1,23 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GachaWishRspOuterClass.GachaWishRsp; - -public class PacketGachaWishRsp extends BasePacket { - - public PacketGachaWishRsp(int gachaType, int scheduleId, int itemId, int progress, int maxProgress) { - super(PacketOpcodes.GachaWishRsp); - - GachaWishRsp proto = GachaWishRsp.newBuilder() - .setGachaType(gachaType) - .setGachaScheduleId(scheduleId) - .setWishItemId(itemId) - .setWishProgress(progress) - .setWishMaxProgress(maxProgress) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GachaWishRspOuterClass.GachaWishRsp; + +public class PacketGachaWishRsp extends BasePacket { + + public PacketGachaWishRsp( + int gachaType, int scheduleId, int itemId, int progress, int maxProgress) { + super(PacketOpcodes.GachaWishRsp); + + GachaWishRsp proto = + GachaWishRsp.newBuilder() + .setGachaType(gachaType) + .setGachaScheduleId(scheduleId) + .setWishItemId(itemId) + .setWishProgress(progress) + .setWishMaxProgress(maxProgress) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetAutoPickDropInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetAutoPickDropInfoNotify.java index b5fa3f32e..94765a553 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetAutoPickDropInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetAutoPickDropInfoNotify.java @@ -1,21 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GadgetAutoPickDropInfoNotifyOuterClass.GadgetAutoPickDropInfoNotify; - -import java.util.Collection; - -public class PacketGadgetAutoPickDropInfoNotify extends BasePacket { - - public PacketGadgetAutoPickDropInfoNotify(Collection items) { - super(PacketOpcodes.GadgetAutoPickDropInfoNotify); - - GadgetAutoPickDropInfoNotify.Builder proto = GadgetAutoPickDropInfoNotify.newBuilder(); - - items.forEach(item -> proto.addItemList(item.toProto())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GadgetAutoPickDropInfoNotifyOuterClass.GadgetAutoPickDropInfoNotify; +import java.util.Collection; + +public class PacketGadgetAutoPickDropInfoNotify extends BasePacket { + + public PacketGadgetAutoPickDropInfoNotify(Collection items) { + super(PacketOpcodes.GadgetAutoPickDropInfoNotify); + + GadgetAutoPickDropInfoNotify.Builder proto = GadgetAutoPickDropInfoNotify.newBuilder(); + + items.forEach(item -> proto.addItemList(item.toProto())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java index d5b1f5424..71a80ad3e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetInteractRsp.java @@ -1,40 +1,43 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityBaseGadget; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp; -import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType; -import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketGadgetInteractRsp extends BasePacket { - public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) { - this(gadget, interact, null); - } - - public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpType opType) { - super(PacketOpcodes.GadgetInteractRsp); - - var proto = GadgetInteractRsp.newBuilder() - .setGadgetEntityId(gadget.getId()) - .setInteractType(interact) - .setGadgetId(gadget.getGadgetId()); - - if (opType != null) { - proto.setOpType(opType); - } - - this.setData(proto.build()); - } - - public PacketGadgetInteractRsp() { - super(PacketOpcodes.GadgetInteractRsp); - - GadgetInteractRsp proto = GadgetInteractRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityBaseGadget; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp; +import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType; +import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketGadgetInteractRsp extends BasePacket { + public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) { + this(gadget, interact, null); + } + + public PacketGadgetInteractRsp( + EntityBaseGadget gadget, InteractType interact, InterOpType opType) { + super(PacketOpcodes.GadgetInteractRsp); + + var proto = + GadgetInteractRsp.newBuilder() + .setGadgetEntityId(gadget.getId()) + .setInteractType(interact) + .setGadgetId(gadget.getGadgetId()); + + if (opType != null) { + proto.setOpType(opType); + } + + this.setData(proto.build()); + } + + public PacketGadgetInteractRsp() { + super(PacketOpcodes.GadgetInteractRsp); + + GadgetInteractRsp proto = + GadgetInteractRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetStateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetStateNotify.java index e09fea656..9847027dd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetStateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGadgetStateNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GadgetStateNotifyOuterClass.GadgetStateNotify; - -public class PacketGadgetStateNotify extends BasePacket { - - public PacketGadgetStateNotify(EntityGadget gadget, int newState) { - super(PacketOpcodes.GadgetStateNotify); - - GadgetStateNotify proto = GadgetStateNotify.newBuilder() - .setGadgetEntityId(gadget.getId()) - .setGadgetState(newState) - .setIsEnableInteract(true) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GadgetStateNotifyOuterClass.GadgetStateNotify; + +public class PacketGadgetStateNotify extends BasePacket { + + public PacketGadgetStateNotify(EntityGadget gadget, int newState) { + super(PacketOpcodes.GadgetStateNotify); + + GadgetStateNotify proto = + GadgetStateNotify.newBuilder() + .setGadgetEntityId(gadget.getId()) + .setGadgetState(newState) + .setIsEnableInteract(true) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityInfoRsp.java index 13896ebf9..736bd9bfe 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityInfoRsp.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.activity.ActivityManager; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetActivityInfoRspOuterClass.GetActivityInfoRsp; - -import java.util.Set; - -public class PacketGetActivityInfoRsp extends BasePacket { - public PacketGetActivityInfoRsp(Set activityIdList, ActivityManager activityManager) { - super(PacketOpcodes.GetActivityInfoRsp); - - var proto = GetActivityInfoRsp.newBuilder(); - - activityIdList.stream() - .map(activityManager::getInfoProtoByActivityId) - .forEach(proto::addActivityInfoList); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.activity.ActivityManager; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetActivityInfoRspOuterClass.GetActivityInfoRsp; +import java.util.Set; + +public class PacketGetActivityInfoRsp extends BasePacket { + public PacketGetActivityInfoRsp(Set activityIdList, ActivityManager activityManager) { + super(PacketOpcodes.GetActivityInfoRsp); + + var proto = GetActivityInfoRsp.newBuilder(); + + activityIdList.stream() + .map(activityManager::getInfoProtoByActivityId) + .forEach(proto::addActivityInfoList); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityShopSheetInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityShopSheetInfoRsp.java index e4c67a07b..fc726079c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityShopSheetInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetActivityShopSheetInfoRsp.java @@ -1,50 +1,52 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.activity.ActivityConfigItem; -import emu.grasscutter.game.activity.ActivityManager; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ActivityShopSheetInfoOuterClass.ActivityShopSheetInfo; -import emu.grasscutter.net.proto.GetActivityShopSheetInfoRspOuterClass.GetActivityShopSheetInfoRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -import java.util.ArrayList; -import java.util.List; - -public class PacketGetActivityShopSheetInfoRsp extends BasePacket { - - - public PacketGetActivityShopSheetInfoRsp(int shopType) { - super(PacketOpcodes.GetActivityShopSheetInfoRsp); - - var sheetInfo = GameData.getActivityShopDataMap().get(shopType); - ActivityConfigItem activityConfigItem = null; - - if (sheetInfo != null) { - activityConfigItem = ActivityManager.getScheduleActivityConfigMap().get(sheetInfo.getScheduleId()); - } - - if (sheetInfo == null || activityConfigItem == null) { - setData(GetActivityShopSheetInfoRsp.newBuilder() - .setShopType(shopType) - .setRetcode(RetcodeOuterClass.Retcode.RET_SHOP_NOT_OPEN_VALUE) - .build()); - return; - } - - List sheetInfos = new ArrayList<>(sheetInfo.getSheetList().size()); - for (int id : sheetInfo.getSheetList()) { - sheetInfos.add(ActivityShopSheetInfo.newBuilder() - .setSheetId(id) - .setBeginTime((int) activityConfigItem.getBeginTime().getTime()) - .setEndTime((int) activityConfigItem.getEndTime().getTime()) - .build()); - } - - setData(GetActivityShopSheetInfoRsp.newBuilder() - .setShopType(shopType) - .addAllSheetInfoList(sheetInfos) - .build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.activity.ActivityConfigItem; +import emu.grasscutter.game.activity.ActivityManager; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ActivityShopSheetInfoOuterClass.ActivityShopSheetInfo; +import emu.grasscutter.net.proto.GetActivityShopSheetInfoRspOuterClass.GetActivityShopSheetInfoRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import java.util.ArrayList; +import java.util.List; + +public class PacketGetActivityShopSheetInfoRsp extends BasePacket { + + public PacketGetActivityShopSheetInfoRsp(int shopType) { + super(PacketOpcodes.GetActivityShopSheetInfoRsp); + + var sheetInfo = GameData.getActivityShopDataMap().get(shopType); + ActivityConfigItem activityConfigItem = null; + + if (sheetInfo != null) { + activityConfigItem = + ActivityManager.getScheduleActivityConfigMap().get(sheetInfo.getScheduleId()); + } + + if (sheetInfo == null || activityConfigItem == null) { + setData( + GetActivityShopSheetInfoRsp.newBuilder() + .setShopType(shopType) + .setRetcode(RetcodeOuterClass.Retcode.RET_SHOP_NOT_OPEN_VALUE) + .build()); + return; + } + + List sheetInfos = new ArrayList<>(sheetInfo.getSheetList().size()); + for (int id : sheetInfo.getSheetList()) { + sheetInfos.add( + ActivityShopSheetInfo.newBuilder() + .setSheetId(id) + .setBeginTime((int) activityConfigItem.getBeginTime().getTime()) + .setEndTime((int) activityConfigItem.getEndTime().getTime()) + .build()); + } + + setData( + GetActivityShopSheetInfoRsp.newBuilder() + .setShopType(shopType) + .addAllSheetInfoList(sheetInfos) + .build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java index 6658d3c09..069980a4e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java @@ -1,76 +1,89 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EquipParamOuterClass; -import emu.grasscutter.net.proto.GetAllMailRspOuterClass.GetAllMailRsp; -import emu.grasscutter.net.proto.MailDataOuterClass; -import emu.grasscutter.net.proto.MailDataOuterClass.MailData; -import emu.grasscutter.net.proto.MailItemOuterClass; -import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; - -public class PacketGetAllMailRsp extends BasePacket { - - public PacketGetAllMailRsp(Player player, boolean isGiftMail) { - super(PacketOpcodes.GetAllMailRsp); - GetAllMailRsp.Builder proto = GetAllMailRsp.newBuilder(); - - if (isGiftMail) { - proto.setIsCollected(true); - } else { - proto.setIsCollected(false); - - if (player.getAllMail().size() != 0) { // Make sure the player has mail - List mailDataList = new ArrayList(); - - for (Mail message : player.getAllMail()) { - if (message.stateValue == 1) { // Make sure it isn't a gift - if (message.expireTime > (int) Instant.now().getEpochSecond()) { // Make sure the message isn't expired (The game won't show expired mail, but I don't want to send unnecessary information). - if (mailDataList.size() <= 1000) { // Make sure that there isn't over 1000 messages in the mailbox. (idk what will happen if there is but the game probably won't like it.) - MailTextContent.Builder mailTextContent = MailTextContent.newBuilder(); - mailTextContent.setTitle(message.mailContent.title); - mailTextContent.setContent(message.mailContent.content); - mailTextContent.setSender(message.mailContent.sender); - - List mailItems = new ArrayList<>(); - - for (Mail.MailItem item : message.itemList) { - MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); - EquipParamOuterClass.EquipParam.Builder itemParam = EquipParamOuterClass.EquipParam.newBuilder(); - itemParam.setItemId(item.itemId); - itemParam.setItemNum(item.itemCount); - mailItem.setEquipParam(itemParam.build()); - - mailItems.add(mailItem.build()); - } - - MailDataOuterClass.MailData.Builder mailData = MailDataOuterClass.MailData.newBuilder(); - mailData.setMailId(player.getMailId(message)); - mailData.setMailTextContent(mailTextContent.build()); - mailData.addAllItemList(mailItems); - mailData.setSendTime((int) message.sendTime); - mailData.setExpireTime((int) message.expireTime); - mailData.setImportance(message.importance); - mailData.setIsRead(message.isRead); - mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setCollectStateValue(1); - - mailDataList.add(mailData.build()); - } - } - } - } - - proto.addAllMailList(mailDataList); - proto.setIsTruncated(mailDataList.size() > 1000); // When enabled this will send a notification to the user telling them their inbox is full and they should delete old messages when opening the mailbox. - } - } - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EquipParamOuterClass; +import emu.grasscutter.net.proto.GetAllMailRspOuterClass.GetAllMailRsp; +import emu.grasscutter.net.proto.MailDataOuterClass; +import emu.grasscutter.net.proto.MailDataOuterClass.MailData; +import emu.grasscutter.net.proto.MailItemOuterClass; +import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +public class PacketGetAllMailRsp extends BasePacket { + + public PacketGetAllMailRsp(Player player, boolean isGiftMail) { + super(PacketOpcodes.GetAllMailRsp); + GetAllMailRsp.Builder proto = GetAllMailRsp.newBuilder(); + + if (isGiftMail) { + proto.setIsCollected(true); + } else { + proto.setIsCollected(false); + + if (player.getAllMail().size() != 0) { // Make sure the player has mail + List mailDataList = new ArrayList(); + + for (Mail message : player.getAllMail()) { + if (message.stateValue == 1) { // Make sure it isn't a gift + if (message.expireTime + > (int) + Instant.now() + .getEpochSecond()) { // Make sure the message isn't expired (The game won't + // show expired mail, but I don't want to send + // unnecessary information). + if (mailDataList.size() + <= 1000) { // Make sure that there isn't over 1000 messages in the mailbox. (idk + // what will happen if there is but the game probably won't like it.) + MailTextContent.Builder mailTextContent = MailTextContent.newBuilder(); + mailTextContent.setTitle(message.mailContent.title); + mailTextContent.setContent(message.mailContent.content); + mailTextContent.setSender(message.mailContent.sender); + + List mailItems = new ArrayList<>(); + + for (Mail.MailItem item : message.itemList) { + MailItemOuterClass.MailItem.Builder mailItem = + MailItemOuterClass.MailItem.newBuilder(); + EquipParamOuterClass.EquipParam.Builder itemParam = + EquipParamOuterClass.EquipParam.newBuilder(); + itemParam.setItemId(item.itemId); + itemParam.setItemNum(item.itemCount); + mailItem.setEquipParam(itemParam.build()); + + mailItems.add(mailItem.build()); + } + + MailDataOuterClass.MailData.Builder mailData = + MailDataOuterClass.MailData.newBuilder(); + mailData.setMailId(player.getMailId(message)); + mailData.setMailTextContent(mailTextContent.build()); + mailData.addAllItemList(mailItems); + mailData.setSendTime((int) message.sendTime); + mailData.setExpireTime((int) message.expireTime); + mailData.setImportance(message.importance); + mailData.setIsRead(message.isRead); + mailData.setIsAttachmentGot(message.isAttachmentGot); + mailData.setCollectStateValue(1); + + mailDataList.add(mailData.build()); + } + } + } + } + + proto.addAllMailList(mailDataList); + proto.setIsTruncated( + mailDataList.size() + > 1000); // When enabled this will send a notification to the user telling them + // their inbox is full and they should delete old messages when opening the + // mailbox. + } + } + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllUnlockNameCardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllUnlockNameCardRsp.java index 22c093d88..9cc78c98b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllUnlockNameCardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllUnlockNameCardRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetAllUnlockNameCardRspOuterClass.GetAllUnlockNameCardRsp; - -public class PacketGetAllUnlockNameCardRsp extends BasePacket { - - public PacketGetAllUnlockNameCardRsp(Player player) { - super(PacketOpcodes.GetAllUnlockNameCardRsp); - - GetAllUnlockNameCardRsp proto = GetAllUnlockNameCardRsp.newBuilder() - .addAllNameCardList(player.getNameCardList()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetAllUnlockNameCardRspOuterClass.GetAllUnlockNameCardRsp; + +public class PacketGetAllUnlockNameCardRsp extends BasePacket { + + public PacketGetAllUnlockNameCardRsp(Player player) { + super(PacketOpcodes.GetAllUnlockNameCardRsp); + + GetAllUnlockNameCardRsp proto = + GetAllUnlockNameCardRsp.newBuilder().addAllNameCardList(player.getNameCardList()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAuthkeyRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAuthkeyRsp.java index a8b603332..aca745fb0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAuthkeyRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAuthkeyRsp.java @@ -1,17 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetAuthkeyRspOuterClass.GetAuthkeyRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; - -public class PacketGetAuthkeyRsp extends BasePacket { - - public PacketGetAuthkeyRsp() { - super(PacketOpcodes.GetAuthkeyRsp); - - GetAuthkeyRsp proto = GetAuthkeyRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetAuthkeyRspOuterClass.GetAuthkeyRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; + +public class PacketGetAuthkeyRsp extends BasePacket { + + public PacketGetAuthkeyRsp() { + super(PacketOpcodes.GetAuthkeyRsp); + + GetAuthkeyRsp proto = + GetAuthkeyRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetChatEmojiCollectionRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetChatEmojiCollectionRsp.java index 5ed1a0578..195c5f88e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetChatEmojiCollectionRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetChatEmojiCollectionRsp.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatEmojiCollectionDataOuterClass; -import emu.grasscutter.net.proto.GetChatEmojiCollectionRspOuterClass; - -import java.util.List; - -public class PacketGetChatEmojiCollectionRsp extends BasePacket { - public PacketGetChatEmojiCollectionRsp(List emojiIds) { - super(PacketOpcodes.GetChatEmojiCollectionRsp); - - var rsp = GetChatEmojiCollectionRspOuterClass.GetChatEmojiCollectionRsp.newBuilder() - .setChatEmojiCollectionData(ChatEmojiCollectionDataOuterClass.ChatEmojiCollectionData.newBuilder() - .addAllEmojiIdList(emojiIds) - .build()); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatEmojiCollectionDataOuterClass; +import emu.grasscutter.net.proto.GetChatEmojiCollectionRspOuterClass; +import java.util.List; + +public class PacketGetChatEmojiCollectionRsp extends BasePacket { + public PacketGetChatEmojiCollectionRsp(List emojiIds) { + super(PacketOpcodes.GetChatEmojiCollectionRsp); + + var rsp = + GetChatEmojiCollectionRspOuterClass.GetChatEmojiCollectionRsp.newBuilder() + .setChatEmojiCollectionData( + ChatEmojiCollectionDataOuterClass.ChatEmojiCollectionData.newBuilder() + .addAllEmojiIdList(emojiIds) + .build()); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetCompoundDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetCompoundDataRsp.java index 27e19dc26..cfdc15afd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetCompoundDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetCompoundDataRsp.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; -import emu.grasscutter.net.proto.GetCompoundDataRspOuterClass.GetCompoundDataRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; -import java.util.Set; - -public class PacketGetCompoundDataRsp extends BasePacket { - public PacketGetCompoundDataRsp(Set unlockedCompounds, List compoundQueueData) { - super(PacketOpcodes.GetCompoundDataRsp); - var proto = GetCompoundDataRsp.newBuilder() - .addAllUnlockCompoundList(unlockedCompounds) - .addAllCompoundQueueDataList(compoundQueueData) - .setRetcode(Retcode.RET_SUCC_VALUE) - .build(); - setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; +import emu.grasscutter.net.proto.GetCompoundDataRspOuterClass.GetCompoundDataRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; +import java.util.Set; + +public class PacketGetCompoundDataRsp extends BasePacket { + public PacketGetCompoundDataRsp( + Set unlockedCompounds, List compoundQueueData) { + super(PacketOpcodes.GetCompoundDataRsp); + var proto = + GetCompoundDataRsp.newBuilder() + .addAllUnlockCompoundList(unlockedCompounds) + .addAllCompoundQueueDataList(compoundQueueData) + .setRetcode(Retcode.RET_SUCC_VALUE) + .build(); + setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetDailyDungeonEntryInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetDailyDungeonEntryInfoRsp.java index 38b001d31..fcfd4bb5b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetDailyDungeonEntryInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetDailyDungeonEntryInfoRsp.java @@ -1,40 +1,43 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.DungeonEntryData; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.DailyDungeonEntryInfoOuterClass; -import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass; -import emu.grasscutter.net.proto.GetDailyDungeonEntryInfoRspOuterClass; - -public class PacketGetDailyDungeonEntryInfoRsp extends BasePacket { - - public PacketGetDailyDungeonEntryInfoRsp(Integer sceneID) { - super(PacketOpcodes.GetDailyDungeonEntryInfoRsp); - - var resp = GetDailyDungeonEntryInfoRspOuterClass.GetDailyDungeonEntryInfoRsp.newBuilder(); - - for (var info : GameData.getDungeonEntryDataMap().values().parallelStream().filter(d -> d.getSceneId() == sceneID).map(this::getDungonEntryInfo).toList()) - resp.addDailyDungeonInfoList(info); - - this.setData(resp.build()); - } - - private DailyDungeonEntryInfoOuterClass.DailyDungeonEntryInfo getDungonEntryInfo(DungeonEntryData data) { - var dungeonEntryId = data.getDungeonEntryId(); - var id = data.getId(); - - // TODO - DungeonEntryInfoOuterClass.DungeonEntryInfo dungeonEntryInfo - = DungeonEntryInfoOuterClass.DungeonEntryInfo.newBuilder().setDungeonId(130).build(); - - var builder = DailyDungeonEntryInfoOuterClass.DailyDungeonEntryInfo.newBuilder(); - - builder.setDungeonEntryId(dungeonEntryId); - builder.setDungeonEntryConfigId(id); - builder.setRecommendDungeonEntryInfo(dungeonEntryInfo); - return builder.build(); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.DungeonEntryData; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DailyDungeonEntryInfoOuterClass; +import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass; +import emu.grasscutter.net.proto.GetDailyDungeonEntryInfoRspOuterClass; + +public class PacketGetDailyDungeonEntryInfoRsp extends BasePacket { + + public PacketGetDailyDungeonEntryInfoRsp(Integer sceneID) { + super(PacketOpcodes.GetDailyDungeonEntryInfoRsp); + + var resp = GetDailyDungeonEntryInfoRspOuterClass.GetDailyDungeonEntryInfoRsp.newBuilder(); + + for (var info : + GameData.getDungeonEntryDataMap().values().parallelStream() + .filter(d -> d.getSceneId() == sceneID) + .map(this::getDungonEntryInfo) + .toList()) resp.addDailyDungeonInfoList(info); + + this.setData(resp.build()); + } + + private DailyDungeonEntryInfoOuterClass.DailyDungeonEntryInfo getDungonEntryInfo( + DungeonEntryData data) { + var dungeonEntryId = data.getDungeonEntryId(); + var id = data.getId(); + + // TODO + DungeonEntryInfoOuterClass.DungeonEntryInfo dungeonEntryInfo = + DungeonEntryInfoOuterClass.DungeonEntryInfo.newBuilder().setDungeonId(130).build(); + + var builder = DailyDungeonEntryInfoOuterClass.DailyDungeonEntryInfo.newBuilder(); + + builder.setDungeonEntryId(dungeonEntryId); + builder.setDungeonEntryConfigId(id); + builder.setRecommendDungeonEntryInfo(dungeonEntryInfo); + return builder.build(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowAvatarInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowAvatarInfoRsp.java index 5edd8ec5d..8c13a87ca 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowAvatarInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowAvatarInfoRsp.java @@ -1,24 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetFriendShowAvatarInfoRspOuterClass.GetFriendShowAvatarInfoRsp; -import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo; - -import java.util.List; - -@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoRsp) -public class PacketGetFriendShowAvatarInfoRsp extends BasePacket { - - public PacketGetFriendShowAvatarInfoRsp(int uid, List showAvatarInfoList) { - super(PacketOpcodes.GetFriendShowAvatarInfoRsp); - - GetFriendShowAvatarInfoRsp.Builder p = GetFriendShowAvatarInfoRsp.newBuilder() - .setUid(uid) - .addAllShowAvatarInfoList(showAvatarInfoList); - - this.setData(p.build()); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetFriendShowAvatarInfoRspOuterClass.GetFriendShowAvatarInfoRsp; +import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo; +import java.util.List; + +@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoRsp) +public class PacketGetFriendShowAvatarInfoRsp extends BasePacket { + + public PacketGetFriendShowAvatarInfoRsp(int uid, List showAvatarInfoList) { + super(PacketOpcodes.GetFriendShowAvatarInfoRsp); + + GetFriendShowAvatarInfoRsp.Builder p = + GetFriendShowAvatarInfoRsp.newBuilder() + .setUid(uid) + .addAllShowAvatarInfoList(showAvatarInfoList); + + this.setData(p.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowNameCardInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowNameCardInfoRsp.java index 7a7d8e8ef..7eba3da37 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowNameCardInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetFriendShowNameCardInfoRsp.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetFriendShowNameCardInfoRspOuterClass; - -import java.util.List; - -public class PacketGetFriendShowNameCardInfoRsp extends BasePacket { - public PacketGetFriendShowNameCardInfoRsp(int uid, List cardIds) { - super(PacketOpcodes.GetFriendShowNameCardInfoRsp); - - var rsp = GetFriendShowNameCardInfoRspOuterClass.GetFriendShowNameCardInfoRsp.newBuilder() - .setUid(uid) - .addAllShowNameCardIdList(cardIds) - .setRetcode(0) - .build(); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetFriendShowNameCardInfoRspOuterClass; +import java.util.List; + +public class PacketGetFriendShowNameCardInfoRsp extends BasePacket { + public PacketGetFriendShowNameCardInfoRsp(int uid, List cardIds) { + super(PacketOpcodes.GetFriendShowNameCardInfoRsp); + + var rsp = + GetFriendShowNameCardInfoRspOuterClass.GetFriendShowNameCardInfoRsp.newBuilder() + .setUid(uid) + .addAllShowNameCardIdList(cardIds) + .setRetcode(0) + .build(); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetGachaInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetGachaInfoRsp.java index 7e6eb3edd..e3d1ac27c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetGachaInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetGachaInfoRsp.java @@ -1,16 +1,15 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.gacha.GachaSystem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketGetGachaInfoRsp extends BasePacket { - - public PacketGetGachaInfoRsp(GachaSystem manager, Player player) { - super(PacketOpcodes.GetGachaInfoRsp); - - this.setData(manager.toProto(player)); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.gacha.GachaSystem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketGetGachaInfoRsp extends BasePacket { + + public PacketGetGachaInfoRsp(GachaSystem manager, Player player) { + super(PacketOpcodes.GetGachaInfoRsp); + + this.setData(manager.toProto(player)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetHomeLevelUpRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetHomeLevelUpRewardRsp.java index 10e110603..53492a2d4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetHomeLevelUpRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetHomeLevelUpRewardRsp.java @@ -1,25 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetHomeLevelUpRewardRspOuterClass.GetHomeLevelUpRewardRsp; - -public class PacketGetHomeLevelUpRewardRsp extends BasePacket { - - public PacketGetHomeLevelUpRewardRsp(int level, int rewardId) { - super(PacketOpcodes.GetHomeLevelUpRewardRsp); - - int retcode = 0; - - if (rewardId == 0) { - retcode = 1; - } - - GetHomeLevelUpRewardRsp proto = GetHomeLevelUpRewardRsp.newBuilder() - .setLevel(level) - .setRetcode(retcode) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetHomeLevelUpRewardRspOuterClass.GetHomeLevelUpRewardRsp; + +public class PacketGetHomeLevelUpRewardRsp extends BasePacket { + + public PacketGetHomeLevelUpRewardRsp(int level, int rewardId) { + super(PacketOpcodes.GetHomeLevelUpRewardRsp); + + int retcode = 0; + + if (rewardId == 0) { + retcode = 1; + } + + GetHomeLevelUpRewardRsp proto = + GetHomeLevelUpRewardRsp.newBuilder().setLevel(level).setRetcode(retcode).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java index 2517d66e5..8dcf6d585 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetInvestigationMonsterRsp.java @@ -1,24 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.WorldDataSystem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetInvestigationMonsterRspOuterClass; - -import java.util.List; - -public class PacketGetInvestigationMonsterRsp extends BasePacket { - - public PacketGetInvestigationMonsterRsp(Player player, WorldDataSystem worldDataManager, List cityIdListList) { - - super(PacketOpcodes.GetInvestigationMonsterRsp); - - var resp = GetInvestigationMonsterRspOuterClass.GetInvestigationMonsterRsp.newBuilder(); - - cityIdListList.forEach(id -> resp.addAllMonsterList(worldDataManager.getInvestigationMonstersByCityId(player, id))); - - - this.setData(resp.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.WorldDataSystem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetInvestigationMonsterRspOuterClass; +import java.util.List; + +public class PacketGetInvestigationMonsterRsp extends BasePacket { + + public PacketGetInvestigationMonsterRsp( + Player player, WorldDataSystem worldDataManager, List cityIdListList) { + + super(PacketOpcodes.GetInvestigationMonsterRsp); + + var resp = GetInvestigationMonsterRspOuterClass.GetInvestigationMonsterRsp.newBuilder(); + + cityIdListList.forEach( + id -> + resp.addAllMonsterList(worldDataManager.getInvestigationMonstersByCityId(player, id))); + + this.setData(resp.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java index 2e94a1f20..2c2788af6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java @@ -1,66 +1,73 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EquipParamOuterClass; -import emu.grasscutter.net.proto.GetMailItemRspOuterClass.GetMailItemRsp; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -public class PacketGetMailItemRsp extends BasePacket { - - public PacketGetMailItemRsp(Player player, List mailList) { - super(PacketOpcodes.GetMailItemRsp); - List claimedMessages = new ArrayList<>(); - List claimedItems = new ArrayList<>(); - - GetMailItemRsp.Builder proto = GetMailItemRsp.newBuilder(); - - synchronized (player) { - boolean modified = false; - for (int mailId : mailList) { - Mail message = player.getMail(mailId); - if (!message.isAttachmentGot) {//No duplicated item - for (Mail.MailItem mailItem : message.itemList) { - EquipParamOuterClass.EquipParam.Builder item = EquipParamOuterClass.EquipParam.newBuilder(); - int promoteLevel = GameItem.getMinPromoteLevel(mailItem.itemLevel); - - item.setItemId(mailItem.itemId); - item.setItemNum(mailItem.itemCount); - item.setItemLevel(mailItem.itemLevel); - item.setPromoteLevel(promoteLevel); - claimedItems.add(item.build()); - - GameItem gameItem = new GameItem(GameData.getItemDataMap().get(mailItem.itemId)); - gameItem.setCount(mailItem.itemCount); - gameItem.setLevel(mailItem.itemLevel); - gameItem.setPromoteLevel(promoteLevel); - player.getInventory().addItem(gameItem, ActionReason.MailAttachment); - } - - message.isAttachmentGot = true; - claimedMessages.add(message); - - player.replaceMailByIndex(mailId, message); - modified = true; - } - } - if (modified) { - player.save(); - } - } - - proto.addAllMailIdList(claimedMessages.stream().map(player::getMailId).collect(Collectors.toList())); - proto.addAllItemList(claimedItems); - - this.setData(proto.build()); - player.getSession().send(new PacketMailChangeNotify(player, claimedMessages)); // For some reason you have to also send the MailChangeNotify packet - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EquipParamOuterClass; +import emu.grasscutter.net.proto.GetMailItemRspOuterClass.GetMailItemRsp; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class PacketGetMailItemRsp extends BasePacket { + + public PacketGetMailItemRsp(Player player, List mailList) { + super(PacketOpcodes.GetMailItemRsp); + List claimedMessages = new ArrayList<>(); + List claimedItems = new ArrayList<>(); + + GetMailItemRsp.Builder proto = GetMailItemRsp.newBuilder(); + + synchronized (player) { + boolean modified = false; + for (int mailId : mailList) { + Mail message = player.getMail(mailId); + if (!message.isAttachmentGot) { // No duplicated item + for (Mail.MailItem mailItem : message.itemList) { + EquipParamOuterClass.EquipParam.Builder item = + EquipParamOuterClass.EquipParam.newBuilder(); + int promoteLevel = GameItem.getMinPromoteLevel(mailItem.itemLevel); + + item.setItemId(mailItem.itemId); + item.setItemNum(mailItem.itemCount); + item.setItemLevel(mailItem.itemLevel); + item.setPromoteLevel(promoteLevel); + claimedItems.add(item.build()); + + GameItem gameItem = new GameItem(GameData.getItemDataMap().get(mailItem.itemId)); + gameItem.setCount(mailItem.itemCount); + gameItem.setLevel(mailItem.itemLevel); + gameItem.setPromoteLevel(promoteLevel); + player.getInventory().addItem(gameItem, ActionReason.MailAttachment); + } + + message.isAttachmentGot = true; + claimedMessages.add(message); + + player.replaceMailByIndex(mailId, message); + modified = true; + } + } + if (modified) { + player.save(); + } + } + + proto.addAllMailIdList( + claimedMessages.stream().map(player::getMailId).collect(Collectors.toList())); + proto.addAllItemList(claimedItems); + + this.setData(proto.build()); + player + .getSession() + .send( + new PacketMailChangeNotify( + player, + claimedMessages)); // For some reason you have to also send the MailChangeNotify + // packet + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetOnlinePlayerListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetOnlinePlayerListRsp.java index 9f498659d..931ae364c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetOnlinePlayerListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetOnlinePlayerListRsp.java @@ -1,29 +1,29 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetOnlinePlayerListRspOuterClass.GetOnlinePlayerListRsp; - -import java.util.List; - -public class PacketGetOnlinePlayerListRsp extends BasePacket { - public PacketGetOnlinePlayerListRsp(Player session) { - super(PacketOpcodes.GetOnlinePlayerListRsp); - - List players = Grasscutter.getGameServer().getPlayers().values().stream().limit(50).toList(); - - GetOnlinePlayerListRsp.Builder proto = GetOnlinePlayerListRsp.newBuilder(); - - if (players.size() != 0) { - for (Player player : players) { - if (player.getUid() == session.getUid()) continue; - - proto.addPlayerInfoList(player.getOnlinePlayerInfo()); - } - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetOnlinePlayerListRspOuterClass.GetOnlinePlayerListRsp; +import java.util.List; + +public class PacketGetOnlinePlayerListRsp extends BasePacket { + public PacketGetOnlinePlayerListRsp(Player session) { + super(PacketOpcodes.GetOnlinePlayerListRsp); + + List players = + Grasscutter.getGameServer().getPlayers().values().stream().limit(50).toList(); + + GetOnlinePlayerListRsp.Builder proto = GetOnlinePlayerListRsp.newBuilder(); + + if (players.size() != 0) { + for (Player player : players) { + if (player.getUid() == session.getUid()) continue; + + proto.addPlayerInfoList(player.getOnlinePlayerInfo()); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerAskFriendListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerAskFriendListRsp.java index 9f8573008..a45195f6e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerAskFriendListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerAskFriendListRsp.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.friends.Friendship; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetPlayerAskFriendListRspOuterClass.GetPlayerAskFriendListRsp; - -public class PacketGetPlayerAskFriendListRsp extends BasePacket { - - public PacketGetPlayerAskFriendListRsp(Player player) { - super(PacketOpcodes.GetPlayerAskFriendListRsp); - - GetPlayerAskFriendListRsp.Builder proto = GetPlayerAskFriendListRsp.newBuilder(); - - for (Friendship friendship : player.getFriendsList().getPendingFriends().values()) { - if (friendship.getAskerId() == player.getUid()) { - continue; - } - proto.addAskFriendList(friendship.toProto()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.friends.Friendship; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetPlayerAskFriendListRspOuterClass.GetPlayerAskFriendListRsp; + +public class PacketGetPlayerAskFriendListRsp extends BasePacket { + + public PacketGetPlayerAskFriendListRsp(Player player) { + super(PacketOpcodes.GetPlayerAskFriendListRsp); + + GetPlayerAskFriendListRsp.Builder proto = GetPlayerAskFriendListRsp.newBuilder(); + + for (Friendship friendship : player.getFriendsList().getPendingFriends().values()) { + if (friendship.getAskerId() == player.getUid()) { + continue; + } + proto.addAskFriendList(friendship.toProto()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java index 1082d37de..6382378f2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java @@ -1,45 +1,47 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.game.friends.Friendship; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief; -import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState; -import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFriendListRsp; -import emu.grasscutter.net.proto.PlatformTypeOuterClass; -import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; - -import static emu.grasscutter.config.Configuration.GAME_INFO; - -public class PacketGetPlayerFriendListRsp extends BasePacket { - - public PacketGetPlayerFriendListRsp(Player player) { - super(PacketOpcodes.GetPlayerFriendListRsp); - - var serverAccount = GAME_INFO.serverAccount; - FriendBrief serverFriend = FriendBrief.newBuilder() - .setUid(GameConstants.SERVER_CONSOLE_UID) - .setNickname(serverAccount.nickName) - .setLevel(serverAccount.adventureRank) - .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(serverAccount.avatarId)) - .setWorldLevel(serverAccount.worldLevel) - .setSignature(serverAccount.signature) - .setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) - .setNameCardId(serverAccount.nameCardId) - .setOnlineState(FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE) - .setParam(1) - .setIsGameSource(true) - .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) - .build(); - - GetPlayerFriendListRsp.Builder proto = GetPlayerFriendListRsp.newBuilder().addFriendList(serverFriend); - - for (Friendship friendship : player.getFriendsList().getFriends().values()) { - proto.addFriendList(friendship.toProto()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import static emu.grasscutter.config.Configuration.GAME_INFO; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.game.friends.Friendship; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief; +import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState; +import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFriendListRsp; +import emu.grasscutter.net.proto.PlatformTypeOuterClass; +import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; + +public class PacketGetPlayerFriendListRsp extends BasePacket { + + public PacketGetPlayerFriendListRsp(Player player) { + super(PacketOpcodes.GetPlayerFriendListRsp); + + var serverAccount = GAME_INFO.serverAccount; + FriendBrief serverFriend = + FriendBrief.newBuilder() + .setUid(GameConstants.SERVER_CONSOLE_UID) + .setNickname(serverAccount.nickName) + .setLevel(serverAccount.adventureRank) + .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(serverAccount.avatarId)) + .setWorldLevel(serverAccount.worldLevel) + .setSignature(serverAccount.signature) + .setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) + .setNameCardId(serverAccount.nameCardId) + .setOnlineState(FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE) + .setParam(1) + .setIsGameSource(true) + .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) + .build(); + + GetPlayerFriendListRsp.Builder proto = + GetPlayerFriendListRsp.newBuilder().addFriendList(serverFriend); + + for (Friendship friendship : player.getFriendsList().getFriends().values()) { + proto.addFriendList(friendship.toProto()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerSocialDetailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerSocialDetailRsp.java index d5b80045b..4c997960b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerSocialDetailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerSocialDetailRsp.java @@ -1,24 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetPlayerSocialDetailRspOuterClass.GetPlayerSocialDetailRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; - -public class PacketGetPlayerSocialDetailRsp extends BasePacket { - - public PacketGetPlayerSocialDetailRsp(SocialDetail.Builder detail) { - super(PacketOpcodes.GetPlayerSocialDetailRsp); - - GetPlayerSocialDetailRsp.Builder proto = GetPlayerSocialDetailRsp.newBuilder(); - - if (detail != null) { - proto.setDetailData(detail); - } else { - proto.setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetPlayerSocialDetailRspOuterClass.GetPlayerSocialDetailRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; + +public class PacketGetPlayerSocialDetailRsp extends BasePacket { + + public PacketGetPlayerSocialDetailRsp(SocialDetail.Builder detail) { + super(PacketOpcodes.GetPlayerSocialDetailRsp); + + GetPlayerSocialDetailRsp.Builder proto = GetPlayerSocialDetailRsp.newBuilder(); + + if (detail != null) { + proto.setDetailData(detail); + } else { + proto.setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java index ae189930e..413edde81 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java @@ -1,78 +1,84 @@ -package emu.grasscutter.server.packet.send; - -import com.google.protobuf.ByteString; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.utils.Crypto; - -public class PacketGetPlayerTokenRsp extends BasePacket { - - public PacketGetPlayerTokenRsp(GameSession session) { - super(PacketOpcodes.GetPlayerTokenRsp, true); - - this.setUseDispatchKey(true); - - GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() - .setUid(session.getPlayer().getUid()) - .setToken(session.getAccount().getToken()) - .setAccountType(1) - .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(Crypto.ENCRYPT_SEED) - .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) - .setPlatformType(3) - .setChannelId(1) - .setCountryCode("US") - .setClientVersionRandomKey("c25-314dd05b0b5f") - .setRegPlatform(3) - .setClientIpStr(session.getAddress().getAddress().getHostAddress()) - .build(); - - this.setData(p.toByteArray()); - } - - public PacketGetPlayerTokenRsp(GameSession session, int retcode, String msg, int blackEndTime) { - super(PacketOpcodes.GetPlayerTokenRsp, true); - - this.setUseDispatchKey(true); - - GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() - .setUid(session.getPlayer().getUid()) - .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) - .setRetcode(retcode) - .setMsg(msg) - .setBlackUidEndTime(blackEndTime) - .setRegPlatform(3) - .setCountryCode("US") - .setClientIpStr(session.getAddress().getAddress().getHostAddress()) - .build(); - - this.setData(p.toByteArray()); - } - - public PacketGetPlayerTokenRsp(GameSession session, String encryptedSeed, String encryptedSeedSign) { - super(PacketOpcodes.GetPlayerTokenRsp, true); - - this.setUseDispatchKey(true); - - GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() - .setUid(session.getPlayer().getUid()) - .setToken(session.getAccount().getToken()) - .setAccountType(1) - .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes - .setSecretKeySeed(Crypto.ENCRYPT_SEED) - .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) - .setPlatformType(3) - .setChannelId(1) - .setCountryCode("US") - .setClientVersionRandomKey("c25-314dd05b0b5f") - .setRegPlatform(3) - .setClientIpStr(session.getAddress().getAddress().getHostAddress()) - .setServerRandKey(encryptedSeed) - .setSign(encryptedSeedSign) - .build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import com.google.protobuf.ByteString; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Crypto; + +public class PacketGetPlayerTokenRsp extends BasePacket { + + public PacketGetPlayerTokenRsp(GameSession session) { + super(PacketOpcodes.GetPlayerTokenRsp, true); + + this.setUseDispatchKey(true); + + GetPlayerTokenRsp p = + GetPlayerTokenRsp.newBuilder() + .setUid(session.getPlayer().getUid()) + .setToken(session.getAccount().getToken()) + .setAccountType(1) + .setIsProficientPlayer( + session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes + .setSecretKeySeed(Crypto.ENCRYPT_SEED) + .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) + .setPlatformType(3) + .setChannelId(1) + .setCountryCode("US") + .setClientVersionRandomKey("c25-314dd05b0b5f") + .setRegPlatform(3) + .setClientIpStr(session.getAddress().getAddress().getHostAddress()) + .build(); + + this.setData(p.toByteArray()); + } + + public PacketGetPlayerTokenRsp(GameSession session, int retcode, String msg, int blackEndTime) { + super(PacketOpcodes.GetPlayerTokenRsp, true); + + this.setUseDispatchKey(true); + + GetPlayerTokenRsp p = + GetPlayerTokenRsp.newBuilder() + .setUid(session.getPlayer().getUid()) + .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) + .setRetcode(retcode) + .setMsg(msg) + .setBlackUidEndTime(blackEndTime) + .setRegPlatform(3) + .setCountryCode("US") + .setClientIpStr(session.getAddress().getAddress().getHostAddress()) + .build(); + + this.setData(p.toByteArray()); + } + + public PacketGetPlayerTokenRsp( + GameSession session, String encryptedSeed, String encryptedSeedSign) { + super(PacketOpcodes.GetPlayerTokenRsp, true); + + this.setUseDispatchKey(true); + + GetPlayerTokenRsp p = + GetPlayerTokenRsp.newBuilder() + .setUid(session.getPlayer().getUid()) + .setToken(session.getAccount().getToken()) + .setAccountType(1) + .setIsProficientPlayer( + session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes + .setSecretKeySeed(Crypto.ENCRYPT_SEED) + .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) + .setPlatformType(3) + .setChannelId(1) + .setCountryCode("US") + .setClientVersionRandomKey("c25-314dd05b0b5f") + .setRegPlatform(3) + .setClientIpStr(session.getAddress().getAddress().getHostAddress()) + .setServerRandKey(encryptedSeed) + .setSign(encryptedSeedSign) + .build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetSceneAreaRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetSceneAreaRsp.java index 4c7e52d2f..925769be4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetSceneAreaRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetSceneAreaRsp.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CityInfoOuterClass.CityInfo; -import emu.grasscutter.net.proto.GetSceneAreaRspOuterClass.GetSceneAreaRsp; - -public class PacketGetSceneAreaRsp extends BasePacket { - - public PacketGetSceneAreaRsp(Player player, int sceneId) { - super(PacketOpcodes.GetSceneAreaRsp); - - this.buildHeader(0); - - GetSceneAreaRsp p = GetSceneAreaRsp.newBuilder() - .setSceneId(sceneId) - .addAllAreaIdList(player.getUnlockedSceneAreas(sceneId)) - .addCityInfoList(CityInfo.newBuilder().setCityId(1).setLevel(1).build()) - .addCityInfoList(CityInfo.newBuilder().setCityId(2).setLevel(1).build()) - .addCityInfoList(CityInfo.newBuilder().setCityId(3).setLevel(1).build()) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CityInfoOuterClass.CityInfo; +import emu.grasscutter.net.proto.GetSceneAreaRspOuterClass.GetSceneAreaRsp; + +public class PacketGetSceneAreaRsp extends BasePacket { + + public PacketGetSceneAreaRsp(Player player, int sceneId) { + super(PacketOpcodes.GetSceneAreaRsp); + + this.buildHeader(0); + + GetSceneAreaRsp p = + GetSceneAreaRsp.newBuilder() + .setSceneId(sceneId) + .addAllAreaIdList(player.getUnlockedSceneAreas(sceneId)) + .addCityInfoList(CityInfo.newBuilder().setCityId(1).setLevel(1).build()) + .addCityInfoList(CityInfo.newBuilder().setCityId(2).setLevel(1).build()) + .addCityInfoList(CityInfo.newBuilder().setCityId(3).setLevel(1).build()) + .build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetScenePointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetScenePointRsp.java index 9df0581f1..b585398ed 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetScenePointRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetScenePointRsp.java @@ -1,33 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetScenePointRspOuterClass.GetScenePointRsp; - -public class PacketGetScenePointRsp extends BasePacket { - - public PacketGetScenePointRsp(Player player, int sceneId) { - super(PacketOpcodes.GetScenePointRsp); - - GetScenePointRsp.Builder p = GetScenePointRsp.newBuilder() - .setSceneId(sceneId); - - if (GameData.getScenePointIdList().size() == 0) { - for (int i = 1; i < 1000; i++) { - p.addUnlockedPointList(i); - p.addUnhidePointList(i); - } - } else { - p.addAllUnlockedPointList(player.getUnlockedScenePoints(sceneId)); - p.addAllUnhidePointList(player.getUnlockedScenePoints(sceneId)); - } - - for (int i = 1; i < 9; i++) { - p.addUnlockAreaList(i); - } - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetScenePointRspOuterClass.GetScenePointRsp; + +public class PacketGetScenePointRsp extends BasePacket { + + public PacketGetScenePointRsp(Player player, int sceneId) { + super(PacketOpcodes.GetScenePointRsp); + + GetScenePointRsp.Builder p = GetScenePointRsp.newBuilder().setSceneId(sceneId); + + if (GameData.getScenePointIdList().size() == 0) { + for (int i = 1; i < 1000; i++) { + p.addUnlockedPointList(i); + p.addUnhidePointList(i); + } + } else { + p.addAllUnlockedPointList(player.getUnlockedScenePoints(sceneId)); + p.addAllUnhidePointList(player.getUnlockedScenePoints(sceneId)); + } + + for (int i = 1; i < 9; i++) { + p.addUnlockAreaList(i); + } + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java index 92fa43db2..c625e62b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java @@ -1,78 +1,91 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.shop.ShopInfo; -import emu.grasscutter.game.shop.ShopLimit; -import emu.grasscutter.game.shop.ShopSystem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetShopRspOuterClass; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.ShopGoodsOuterClass.ShopGoods; -import emu.grasscutter.net.proto.ShopOuterClass.Shop; -import emu.grasscutter.utils.Utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -public class PacketGetShopRsp extends BasePacket { - public PacketGetShopRsp(Player inv, int shopType) { - super(PacketOpcodes.GetShopRsp); - - // TODO: CityReputationLevel - Shop.Builder shop = Shop.newBuilder() - .setShopType(shopType) - .setCityId(1) //mock - .setCityReputationLevel(10); //mock - - ShopSystem manager = Grasscutter.getGameServer().getShopSystem(); - if (manager.getShopData().get(shopType) != null) { - List list = manager.getShopData().get(shopType); - List goodsList = new ArrayList<>(); - for (ShopInfo info : list) { - ShopGoods.Builder goods = ShopGoods.newBuilder() - .setGoodsId(info.getGoodsId()) - .setGoodsItem(ItemParamOuterClass.ItemParam.newBuilder().setItemId(info.getGoodsItem().getId()).setCount(info.getGoodsItem().getCount()).build()) - .setScoin(info.getScoin()) - .setHcoin(info.getHcoin()) - .setBuyLimit(info.getBuyLimit()) - .setBeginTime(info.getBeginTime()) - .setEndTime(info.getEndTime()) - .setMinLevel(info.getMinLevel()) - .setMaxLevel(info.getMaxLevel()) - .setMcoin(info.getMcoin()) - .setDisableType(info.getDisableType()) - .setSecondarySheetId(info.getSecondarySheetId()); - if (info.getCostItemList() != null) { - goods.addAllCostItemList(info.getCostItemList().stream().map(x -> ItemParamOuterClass.ItemParam.newBuilder().setItemId(x.getId()).setCount(x.getCount()).build()).collect(Collectors.toList())); - } - if (info.getPreGoodsIdList() != null) { - goods.addAllPreGoodsIdList(info.getPreGoodsIdList()); - } - - int currentTs = Utils.getCurrentSeconds(); - ShopLimit currentShopLimit = inv.getGoodsLimit(info.getGoodsId()); - int nextRefreshTime = ShopSystem.getShopNextRefreshTime(info); - if (currentShopLimit != null) { - if (currentShopLimit.getNextRefreshTime() < currentTs) { // second game day - currentShopLimit.setHasBoughtInPeriod(0); - currentShopLimit.setNextRefreshTime(nextRefreshTime); - } - goods.setBoughtNum(currentShopLimit.getHasBoughtInPeriod()); - goods.setNextRefreshTime(currentShopLimit.getNextRefreshTime()); - } else { - inv.addShopLimit(goods.getGoodsId(), 0, nextRefreshTime); // save generated refresh time - goods.setNextRefreshTime(nextRefreshTime); - } - - goodsList.add(goods.build()); - } - shop.addAllGoodsList(goodsList); - } - - inv.save(); - this.setData(GetShopRspOuterClass.GetShopRsp.newBuilder().setShop(shop).build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.shop.ShopInfo; +import emu.grasscutter.game.shop.ShopLimit; +import emu.grasscutter.game.shop.ShopSystem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetShopRspOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.ShopGoodsOuterClass.ShopGoods; +import emu.grasscutter.net.proto.ShopOuterClass.Shop; +import emu.grasscutter.utils.Utils; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class PacketGetShopRsp extends BasePacket { + public PacketGetShopRsp(Player inv, int shopType) { + super(PacketOpcodes.GetShopRsp); + + // TODO: CityReputationLevel + Shop.Builder shop = + Shop.newBuilder() + .setShopType(shopType) + .setCityId(1) // mock + .setCityReputationLevel(10); // mock + + ShopSystem manager = Grasscutter.getGameServer().getShopSystem(); + if (manager.getShopData().get(shopType) != null) { + List list = manager.getShopData().get(shopType); + List goodsList = new ArrayList<>(); + for (ShopInfo info : list) { + ShopGoods.Builder goods = + ShopGoods.newBuilder() + .setGoodsId(info.getGoodsId()) + .setGoodsItem( + ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(info.getGoodsItem().getId()) + .setCount(info.getGoodsItem().getCount()) + .build()) + .setScoin(info.getScoin()) + .setHcoin(info.getHcoin()) + .setBuyLimit(info.getBuyLimit()) + .setBeginTime(info.getBeginTime()) + .setEndTime(info.getEndTime()) + .setMinLevel(info.getMinLevel()) + .setMaxLevel(info.getMaxLevel()) + .setMcoin(info.getMcoin()) + .setDisableType(info.getDisableType()) + .setSecondarySheetId(info.getSecondarySheetId()); + if (info.getCostItemList() != null) { + goods.addAllCostItemList( + info.getCostItemList().stream() + .map( + x -> + ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(x.getId()) + .setCount(x.getCount()) + .build()) + .collect(Collectors.toList())); + } + if (info.getPreGoodsIdList() != null) { + goods.addAllPreGoodsIdList(info.getPreGoodsIdList()); + } + + int currentTs = Utils.getCurrentSeconds(); + ShopLimit currentShopLimit = inv.getGoodsLimit(info.getGoodsId()); + int nextRefreshTime = ShopSystem.getShopNextRefreshTime(info); + if (currentShopLimit != null) { + if (currentShopLimit.getNextRefreshTime() < currentTs) { // second game day + currentShopLimit.setHasBoughtInPeriod(0); + currentShopLimit.setNextRefreshTime(nextRefreshTime); + } + goods.setBoughtNum(currentShopLimit.getHasBoughtInPeriod()); + goods.setNextRefreshTime(currentShopLimit.getNextRefreshTime()); + } else { + inv.addShopLimit(goods.getGoodsId(), 0, nextRefreshTime); // save generated refresh time + goods.setNextRefreshTime(nextRefreshTime); + } + + goodsList.add(goods.build()); + } + shop.addAllGoodsList(goodsList); + } + + inv.save(); + this.setData(GetShopRspOuterClass.GetShopRsp.newBuilder().setShop(shop).build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopmallDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopmallDataRsp.java index 7b42af316..2e6cda4cf 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopmallDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetShopmallDataRsp.java @@ -1,22 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetShopmallDataRspOuterClass.GetShopmallDataRsp; - -import java.util.List; - -public class PacketGetShopmallDataRsp extends BasePacket { - - public PacketGetShopmallDataRsp() { - super(PacketOpcodes.GetShopmallDataRsp); - - List shop_malls = List.of(900, 1052, 902, 1001, 903); - - GetShopmallDataRsp proto = GetShopmallDataRsp.newBuilder() - .addAllShopTypeList(shop_malls) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetShopmallDataRspOuterClass.GetShopmallDataRsp; +import java.util.List; + +public class PacketGetShopmallDataRsp extends BasePacket { + + public PacketGetShopmallDataRsp() { + super(PacketOpcodes.GetShopmallDataRsp); + + List shop_malls = List.of(900, 1052, 902, 1001, 903); + + GetShopmallDataRsp proto = + GetShopmallDataRsp.newBuilder().addAllShopTypeList(shop_malls).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java index a6e430aa9..9d700c4ca 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java @@ -1,41 +1,40 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetWidgetSlotRspOuterClass; -import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; -import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; - -import java.util.List; - -public class PacketGetWidgetSlotRsp extends BasePacket { - - public PacketGetWidgetSlotRsp(Player player) { - super(PacketOpcodes.GetWidgetSlotRsp); - - GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.Builder proto = - GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.newBuilder(); - - if (player.getWidgetId() == 0) { // TODO: check this logic later, it was null-checking an int before which made it dead code - proto.addAllSlotList(List.of()); - } else { - proto.addSlotList( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setIsActive(true) - .setMaterialId(player.getWidgetId()) - .build() - ); - - proto.addSlotList( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) - .build() - ); - } - - GetWidgetSlotRspOuterClass.GetWidgetSlotRsp protoData = proto.build(); - - this.setData(protoData); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetWidgetSlotRspOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; +import java.util.List; + +public class PacketGetWidgetSlotRsp extends BasePacket { + + public PacketGetWidgetSlotRsp(Player player) { + super(PacketOpcodes.GetWidgetSlotRsp); + + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.Builder proto = + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.newBuilder(); + + if (player.getWidgetId() + == 0) { // TODO: check this logic later, it was null-checking an int before which made it + // dead code + proto.addAllSlotList(List.of()); + } else { + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(player.getWidgetId()) + .build()); + + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) + .build()); + } + + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp protoData = proto.build(); + + this.setData(protoData); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetWorldMpInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWorldMpInfoRsp.java index 97256d1d8..2884e5b6e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetWorldMpInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWorldMpInfoRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GetWorldMpInfoRspOuterClass.GetWorldMpInfoRsp; - -public class PacketGetWorldMpInfoRsp extends BasePacket { - - public PacketGetWorldMpInfoRsp(World world) { - super(PacketOpcodes.GetWorldMpInfoRsp); - - GetWorldMpInfoRsp proto = GetWorldMpInfoRsp.newBuilder() - .setIsInMpMode(world.isMultiplayer()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetWorldMpInfoRspOuterClass.GetWorldMpInfoRsp; + +public class PacketGetWorldMpInfoRsp extends BasePacket { + + public PacketGetWorldMpInfoRsp(World world) { + super(PacketOpcodes.GetWorldMpInfoRsp); + + GetWorldMpInfoRsp proto = + GetWorldMpInfoRsp.newBuilder().setIsInMpMode(world.isMultiplayer()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGroupSuiteNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGroupSuiteNotify.java index 6d1152423..dcaf2bc14 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGroupSuiteNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGroupSuiteNotify.java @@ -1,52 +1,45 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.binout.SceneNpcBornEntry; -import emu.grasscutter.game.quest.QuestGroupSuite; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GroupSuiteNotifyOuterClass; - -import java.util.Collection; -import java.util.List; - -public class PacketGroupSuiteNotify extends BasePacket { - - /** - * Real control which npc suite is loaded - * EntityNPC is useless - */ - public PacketGroupSuiteNotify(List npcBornEntries) { - super(PacketOpcodes.GroupSuiteNotify); - - var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); - - npcBornEntries.stream() - .filter(x -> x.getGroupId() > 0 && x.getSuiteIdList() != null) - .forEach(x -> x.getSuiteIdList().forEach(y -> - proto.putGroupMap(x.getGroupId(), y) - )); - - this.setData(proto); - - } - - public PacketGroupSuiteNotify(int groupId, int suiteId) { - super(PacketOpcodes.GroupSuiteNotify); - - var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); - - proto.putGroupMap(groupId, suiteId); - - this.setData(proto); - } - - public PacketGroupSuiteNotify(Collection questGroupSuites) { - super(PacketOpcodes.GroupSuiteNotify); - - var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); - - questGroupSuites.forEach(i -> proto.putGroupMap(i.getGroup(), i.getSuite())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.binout.SceneNpcBornEntry; +import emu.grasscutter.game.quest.QuestGroupSuite; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GroupSuiteNotifyOuterClass; +import java.util.Collection; +import java.util.List; + +public class PacketGroupSuiteNotify extends BasePacket { + + /** Real control which npc suite is loaded EntityNPC is useless */ + public PacketGroupSuiteNotify(List npcBornEntries) { + super(PacketOpcodes.GroupSuiteNotify); + + var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); + + npcBornEntries.stream() + .filter(x -> x.getGroupId() > 0 && x.getSuiteIdList() != null) + .forEach(x -> x.getSuiteIdList().forEach(y -> proto.putGroupMap(x.getGroupId(), y))); + + this.setData(proto); + } + + public PacketGroupSuiteNotify(int groupId, int suiteId) { + super(PacketOpcodes.GroupSuiteNotify); + + var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); + + proto.putGroupMap(groupId, suiteId); + + this.setData(proto); + } + + public PacketGroupSuiteNotify(Collection questGroupSuites) { + super(PacketOpcodes.GroupSuiteNotify); + + var proto = GroupSuiteNotifyOuterClass.GroupSuiteNotify.newBuilder(); + + questGroupSuites.forEach(i -> proto.putGroupMap(i.getGroup(), i.getSuite())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGroupUnloadNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGroupUnloadNotify.java index 6923ccdbb..ad7578c18 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGroupUnloadNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGroupUnloadNotify.java @@ -1,20 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.GroupUnloadNotifyOuterClass; - -import java.util.List; - -public class PacketGroupUnloadNotify extends BasePacket { - - public PacketGroupUnloadNotify(List groupList) { - super(PacketOpcodes.GroupUnloadNotify); - - var proto = GroupUnloadNotifyOuterClass.GroupUnloadNotify.newBuilder(); - - proto.addAllGroupList(groupList); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GroupUnloadNotifyOuterClass; +import java.util.List; + +public class PacketGroupUnloadNotify extends BasePacket { + + public PacketGroupUnloadNotify(List groupList) { + super(PacketOpcodes.GroupUnloadNotify); + + var proto = GroupUnloadNotifyOuterClass.GroupUnloadNotify.newBuilder(); + + proto.addAllGroupList(groupList); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketH5ActivityIdsNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketH5ActivityIdsNotify.java index 37546849a..03754da10 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketH5ActivityIdsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketH5ActivityIdsNotify.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.H5ActivityIdsNotifyOuterClass.H5ActivityIdsNotify; - -public class PacketH5ActivityIdsNotify extends BasePacket { - - public PacketH5ActivityIdsNotify() { - super(PacketOpcodes.H5ActivityIdsNotify); - - H5ActivityIdsNotify proto = H5ActivityIdsNotify.newBuilder() - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.H5ActivityIdsNotifyOuterClass.H5ActivityIdsNotify; + +public class PacketH5ActivityIdsNotify extends BasePacket { + + public PacketH5ActivityIdsNotify() { + super(PacketOpcodes.H5ActivityIdsNotify); + + H5ActivityIdsNotify proto = H5ActivityIdsNotify.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeAllUnlockedBgmIdListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeAllUnlockedBgmIdListNotify.java index 23f4c1fab..a65162390 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeAllUnlockedBgmIdListNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeAllUnlockedBgmIdListNotify.java @@ -1,24 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeAllUnlockedBgmIdListNotifyOuterClass; - -public class PacketHomeAllUnlockedBgmIdListNotify extends BasePacket { - public PacketHomeAllUnlockedBgmIdListNotify(Player player) { - super(PacketOpcodes.HomeAllUnlockedBgmIdListNotify); - - if (player.getRealmList() == null) { - return; - } - - var unlocked = player.getHome().getUnlockedHomeBgmList(); - - var notify = HomeAllUnlockedBgmIdListNotifyOuterClass.HomeAllUnlockedBgmIdListNotify.newBuilder() - .addAllAllUnlockedBgmIdList(unlocked) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeAllUnlockedBgmIdListNotifyOuterClass; + +public class PacketHomeAllUnlockedBgmIdListNotify extends BasePacket { + public PacketHomeAllUnlockedBgmIdListNotify(Player player) { + super(PacketOpcodes.HomeAllUnlockedBgmIdListNotify); + + if (player.getRealmList() == null) { + return; + } + + var unlocked = player.getHome().getUnlockedHomeBgmList(); + + var notify = + HomeAllUnlockedBgmIdListNotifyOuterClass.HomeAllUnlockedBgmIdListNotify.newBuilder() + .addAllAllUnlockedBgmIdList(unlocked) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java index fe3ef2709..6cccfe5aa 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java @@ -1,36 +1,37 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeBasicInfoNotifyOuterClass; -import emu.grasscutter.net.proto.HomeBasicInfoOuterClass; - -public class PacketHomeBasicInfoNotify extends BasePacket { - - public PacketHomeBasicInfoNotify(Player player, boolean editMode) { - super(PacketOpcodes.HomeBasicInfoNotify); - - if (player.getCurrentRealmId() <= 0) { - return; - } - - var proto = HomeBasicInfoNotifyOuterClass.HomeBasicInfoNotify.newBuilder(); - - var sceneId = player.getCurrentRealmId() + 2000; - var homeScene = player.getHome().getHomeSceneItem(sceneId); - - proto.setBasicInfo(HomeBasicInfoOuterClass.HomeBasicInfo.newBuilder() - .setCurModuleId(player.getCurrentRealmId()) - .setCurRoomSceneId(homeScene.getRoomSceneId()) - .setIsInEditMode(editMode) - .setHomeOwnerUid(player.getUid()) - .setExp(player.getHome().getExp()) - .setLevel(player.getHome().getLevel()) - .setOwnerNickName(player.getNickname()) - // TODO limit shop - .build()); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeBasicInfoNotifyOuterClass; +import emu.grasscutter.net.proto.HomeBasicInfoOuterClass; + +public class PacketHomeBasicInfoNotify extends BasePacket { + + public PacketHomeBasicInfoNotify(Player player, boolean editMode) { + super(PacketOpcodes.HomeBasicInfoNotify); + + if (player.getCurrentRealmId() <= 0) { + return; + } + + var proto = HomeBasicInfoNotifyOuterClass.HomeBasicInfoNotify.newBuilder(); + + var sceneId = player.getCurrentRealmId() + 2000; + var homeScene = player.getHome().getHomeSceneItem(sceneId); + + proto.setBasicInfo( + HomeBasicInfoOuterClass.HomeBasicInfo.newBuilder() + .setCurModuleId(player.getCurrentRealmId()) + .setCurRoomSceneId(homeScene.getRoomSceneId()) + .setIsInEditMode(editMode) + .setHomeOwnerUid(player.getUid()) + .setExp(player.getHome().getExp()) + .setLevel(player.getHome().getLevel()) + .setOwnerNickName(player.getNickname()) + // TODO limit shop + .build()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmNotify.java index 6b803b302..73a7911ad 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmNotify.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeBgmNotifyOuterClass; - -public class PacketHomeChangeBgmNotify extends BasePacket { - public PacketHomeChangeBgmNotify(int homeBgmId) { - super(PacketOpcodes.HomeChangeBgmNotify); - - var notify = HomeChangeBgmNotifyOuterClass.HomeChangeBgmNotify.newBuilder() - .setBgmId(homeBgmId) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeBgmNotifyOuterClass; + +public class PacketHomeChangeBgmNotify extends BasePacket { + public PacketHomeChangeBgmNotify(int homeBgmId) { + super(PacketOpcodes.HomeChangeBgmNotify); + + var notify = + HomeChangeBgmNotifyOuterClass.HomeChangeBgmNotify.newBuilder().setBgmId(homeBgmId).build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmRsp.java index 9435f7fbf..7a3c2ab71 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeBgmRsp.java @@ -1,17 +1,15 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeBgmRspOuterClass; - -public class PacketHomeChangeBgmRsp extends BasePacket { - public PacketHomeChangeBgmRsp() { - super(PacketOpcodes.HomeChangeBgmRsp); - - var rsp = HomeChangeBgmRspOuterClass.HomeChangeBgmRsp.newBuilder() - .setRetcode(0) - .build(); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeBgmRspOuterClass; + +public class PacketHomeChangeBgmRsp extends BasePacket { + public PacketHomeChangeBgmRsp() { + super(PacketOpcodes.HomeChangeBgmRsp); + + var rsp = HomeChangeBgmRspOuterClass.HomeChangeBgmRsp.newBuilder().setRetcode(0).build(); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeEditModeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeEditModeRsp.java index 9a2f91cc4..9ebcb6c8b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeEditModeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeEditModeRsp.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeEditModeRspOuterClass; - -public class PacketHomeChangeEditModeRsp extends BasePacket { - - public PacketHomeChangeEditModeRsp(boolean enterEditMode) { - super(PacketOpcodes.HomeChangeEditModeRsp); - - var proto = HomeChangeEditModeRspOuterClass.HomeChangeEditModeRsp.newBuilder(); - - proto.setIsEnterEditMode(enterEditMode); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeEditModeRspOuterClass; + +public class PacketHomeChangeEditModeRsp extends BasePacket { + + public PacketHomeChangeEditModeRsp(boolean enterEditMode) { + super(PacketOpcodes.HomeChangeEditModeRsp); + + var proto = HomeChangeEditModeRspOuterClass.HomeChangeEditModeRsp.newBuilder(); + + proto.setIsEnterEditMode(enterEditMode); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java index c86eaf503..d54a938d7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChangeModuleRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChangeModuleRspOuterClass; - -public class PacketHomeChangeModuleRsp extends BasePacket { - - public PacketHomeChangeModuleRsp(int targetModuleId) { - super(PacketOpcodes.HomeChangeModuleRsp); - - HomeChangeModuleRspOuterClass.HomeChangeModuleRsp proto = HomeChangeModuleRspOuterClass.HomeChangeModuleRsp.newBuilder() - .setRetcode(0) - .setTargetModuleId(targetModuleId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChangeModuleRspOuterClass; + +public class PacketHomeChangeModuleRsp extends BasePacket { + + public PacketHomeChangeModuleRsp(int targetModuleId) { + super(PacketOpcodes.HomeChangeModuleRsp); + + HomeChangeModuleRspOuterClass.HomeChangeModuleRsp proto = + HomeChangeModuleRspOuterClass.HomeChangeModuleRsp.newBuilder() + .setRetcode(0) + .setTargetModuleId(targetModuleId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java index 90c5e969a..836931068 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeChooseModuleRspOuterClass; - -public class PacketHomeChooseModuleRsp extends BasePacket { - - public PacketHomeChooseModuleRsp(int moduleId) { - super(PacketOpcodes.HomeChooseModuleRsp); - - HomeChooseModuleRspOuterClass.HomeChooseModuleRsp proto = HomeChooseModuleRspOuterClass.HomeChooseModuleRsp.newBuilder() - .setRetcode(0) - .setModuleId(moduleId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChooseModuleRspOuterClass; + +public class PacketHomeChooseModuleRsp extends BasePacket { + + public PacketHomeChooseModuleRsp(int moduleId) { + super(PacketOpcodes.HomeChooseModuleRsp); + + HomeChooseModuleRspOuterClass.HomeChooseModuleRsp proto = + HomeChooseModuleRspOuterClass.HomeChooseModuleRsp.newBuilder() + .setRetcode(0) + .setModuleId(moduleId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java index 9b14022ba..c58304358 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java @@ -1,49 +1,45 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.home.HomeBlockItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeComfortInfoNotifyOuterClass; -import emu.grasscutter.net.proto.HomeModuleComfortInfoOuterClass; - -import java.util.ArrayList; -import java.util.List; - -public class PacketHomeComfortInfoNotify extends BasePacket { - - public PacketHomeComfortInfoNotify(Player player) { - super(PacketOpcodes.HomeComfortInfoNotify); - - if (player.getRealmList() == null) { - // Do not send - return; - } - - List comfortInfoList = new ArrayList<>(); - - for (int moduleId : player.getRealmList()) { - var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); - var blockComfortList = homeScene.getBlockItems().values().stream() - .map(HomeBlockItem::calComfort) - .toList(); - var homeRoomScene = player.getHome().getHomeSceneItem(homeScene.getRoomSceneId()); - - comfortInfoList.add( - HomeModuleComfortInfoOuterClass.HomeModuleComfortInfo.newBuilder() - .setModuleId(moduleId) - .setRoomSceneComfortValue(homeRoomScene.calComfort()) - .addAllWorldSceneBlockComfortValueList(blockComfortList) - .build() - ); - } - - HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify proto = HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify - .newBuilder() - .addAllModuleInfoList(comfortInfoList) - .build(); - - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.home.HomeBlockItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeComfortInfoNotifyOuterClass; +import emu.grasscutter.net.proto.HomeModuleComfortInfoOuterClass; +import java.util.ArrayList; +import java.util.List; + +public class PacketHomeComfortInfoNotify extends BasePacket { + + public PacketHomeComfortInfoNotify(Player player) { + super(PacketOpcodes.HomeComfortInfoNotify); + + if (player.getRealmList() == null) { + // Do not send + return; + } + + List comfortInfoList = new ArrayList<>(); + + for (int moduleId : player.getRealmList()) { + var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); + var blockComfortList = + homeScene.getBlockItems().values().stream().map(HomeBlockItem::calComfort).toList(); + var homeRoomScene = player.getHome().getHomeSceneItem(homeScene.getRoomSceneId()); + + comfortInfoList.add( + HomeModuleComfortInfoOuterClass.HomeModuleComfortInfo.newBuilder() + .setModuleId(moduleId) + .setRoomSceneComfortValue(homeRoomScene.calComfort()) + .addAllWorldSceneBlockComfortValueList(blockComfortList) + .build()); + } + + HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify proto = + HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify.newBuilder() + .addAllModuleInfoList(comfortInfoList) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeEnterEditModeFinishRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeEnterEditModeFinishRsp.java index f2e754e37..9e9f1b0fd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeEnterEditModeFinishRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeEnterEditModeFinishRsp.java @@ -1,12 +1,11 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketHomeEnterEditModeFinishRsp extends BasePacket { - - public PacketHomeEnterEditModeFinishRsp() { - super(PacketOpcodes.HomeEnterEditModeFinishRsp); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketHomeEnterEditModeFinishRsp extends BasePacket { + + public PacketHomeEnterEditModeFinishRsp() { + super(PacketOpcodes.HomeEnterEditModeFinishRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeGetArrangementInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeGetArrangementInfoRsp.java index f397b353e..30033bc07 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeGetArrangementInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeGetArrangementInfoRsp.java @@ -1,31 +1,28 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.home.HomeSceneItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeGetArrangementInfoRspOuterClass; - -import java.util.List; - -public class PacketHomeGetArrangementInfoRsp extends BasePacket { - - public PacketHomeGetArrangementInfoRsp(Player player, List sceneIdList) { - super(PacketOpcodes.HomeGetArrangementInfoRsp); - - var home = player.getHome(); - - var homeScenes = sceneIdList.stream() - .map(home::getHomeSceneItem) - .map(HomeSceneItem::toProto) - .toList(); - - home.save(); - - var proto = HomeGetArrangementInfoRspOuterClass.HomeGetArrangementInfoRsp.newBuilder(); - - proto.addAllSceneArrangementInfoList(homeScenes); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.home.HomeSceneItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeGetArrangementInfoRspOuterClass; +import java.util.List; + +public class PacketHomeGetArrangementInfoRsp extends BasePacket { + + public PacketHomeGetArrangementInfoRsp(Player player, List sceneIdList) { + super(PacketOpcodes.HomeGetArrangementInfoRsp); + + var home = player.getHome(); + + var homeScenes = + sceneIdList.stream().map(home::getHomeSceneItem).map(HomeSceneItem::toProto).toList(); + + home.save(); + + var proto = HomeGetArrangementInfoRspOuterClass.HomeGetArrangementInfoRsp.newBuilder(); + + proto.addAllSceneArrangementInfoList(homeScenes); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java index c736a9d42..8c65e5926 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeMarkPointNotify.java @@ -1,45 +1,46 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.home.HomeBlockItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeMarkPointNotifyOuterClass; -import emu.grasscutter.net.proto.HomeMarkPointSceneDataOuterClass; - -import java.util.Collection; - -public class PacketHomeMarkPointNotify extends BasePacket { - - public PacketHomeMarkPointNotify(Player player) { - super(PacketOpcodes.HomeMarkPointNotify); - - var proto = HomeMarkPointNotifyOuterClass.HomeMarkPointNotify.newBuilder(); - - if (player.getRealmList() == null) { - return; - } - for (var moduleId : player.getRealmList()) { - var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); - - var markPointData = HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData.newBuilder() - .setModuleId(moduleId) - .setSceneId(moduleId + 2000) - .setTeapotSpiritPos(homeScene.getDjinnPos().toProto()); - - // Now it only supports the teleport point - // TODO add more types - var marks = homeScene.getBlockItems().values().stream() - .map(HomeBlockItem::getDeployFurnitureList) - .flatMap(Collection::stream) - .filter(i -> i.getFurnitureId() == 373501) - .map(x -> x.toMarkPointProto(3)) - .toList(); - - markPointData.addAllFurnitureList(marks); - proto.addMarkPointDataList(markPointData); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.home.HomeBlockItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeMarkPointNotifyOuterClass; +import emu.grasscutter.net.proto.HomeMarkPointSceneDataOuterClass; +import java.util.Collection; + +public class PacketHomeMarkPointNotify extends BasePacket { + + public PacketHomeMarkPointNotify(Player player) { + super(PacketOpcodes.HomeMarkPointNotify); + + var proto = HomeMarkPointNotifyOuterClass.HomeMarkPointNotify.newBuilder(); + + if (player.getRealmList() == null) { + return; + } + for (var moduleId : player.getRealmList()) { + var homeScene = player.getHome().getHomeSceneItem(moduleId + 2000); + + var markPointData = + HomeMarkPointSceneDataOuterClass.HomeMarkPointSceneData.newBuilder() + .setModuleId(moduleId) + .setSceneId(moduleId + 2000) + .setTeapotSpiritPos(homeScene.getDjinnPos().toProto()); + + // Now it only supports the teleport point + // TODO add more types + var marks = + homeScene.getBlockItems().values().stream() + .map(HomeBlockItem::getDeployFurnitureList) + .flatMap(Collection::stream) + .filter(i -> i.getFurnitureId() == 373501) + .map(x -> x.toMarkPointProto(3)) + .toList(); + + markPointData.addAllFurnitureList(marks); + proto.addMarkPointDataList(markPointData); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleSeenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleSeenRsp.java index 0c6b756e3..1ca0a570d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleSeenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleSeenRsp.java @@ -1,20 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeModuleSeenRspOuterClass.HomeModuleSeenRsp; - -import java.util.List; - -public class PacketHomeModuleSeenRsp extends BasePacket { - - public PacketHomeModuleSeenRsp(List seen) { - super(PacketOpcodes.HomeModuleSeenRsp); - - HomeModuleSeenRsp proto = HomeModuleSeenRsp.newBuilder() - .addAllSeenModuleIdList(seen) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeModuleSeenRspOuterClass.HomeModuleSeenRsp; +import java.util.List; + +public class PacketHomeModuleSeenRsp extends BasePacket { + + public PacketHomeModuleSeenRsp(List seen) { + super(PacketOpcodes.HomeModuleSeenRsp); + + HomeModuleSeenRsp proto = HomeModuleSeenRsp.newBuilder().addAllSeenModuleIdList(seen).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleUnlockNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleUnlockNotify.java index e8147270e..3893c96ba 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleUnlockNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeModuleUnlockNotify.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeModuleUnlockNotifyOuterClass.HomeModuleUnlockNotify; - -public class PacketHomeModuleUnlockNotify extends BasePacket { - - public PacketHomeModuleUnlockNotify(int targetModuleId) { - super(PacketOpcodes.HomeModuleUnlockNotify); - - HomeModuleUnlockNotify proto = HomeModuleUnlockNotify.newBuilder() - .setModuleId(targetModuleId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeModuleUnlockNotifyOuterClass.HomeModuleUnlockNotify; + +public class PacketHomeModuleUnlockNotify extends BasePacket { + + public PacketHomeModuleUnlockNotify(int targetModuleId) { + super(PacketOpcodes.HomeModuleUnlockNotify); + + HomeModuleUnlockNotify proto = + HomeModuleUnlockNotify.newBuilder().setModuleId(targetModuleId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeNewUnlockedBgmIdListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeNewUnlockedBgmIdListNotify.java index e990baf7e..c57b32157 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeNewUnlockedBgmIdListNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeNewUnlockedBgmIdListNotify.java @@ -1,17 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeNewUnlockedBgmIdListNotifyOuterClass; - -public class PacketHomeNewUnlockedBgmIdListNotify extends BasePacket { - public PacketHomeNewUnlockedBgmIdListNotify(int homeBgmId) { - super(PacketOpcodes.HomeNewUnlockedBgmIdListNotify); - - var notify = HomeNewUnlockedBgmIdListNotifyOuterClass.HomeNewUnlockedBgmIdListNotify.newBuilder() - .addNewUnlockedBgmIdList(homeBgmId) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeNewUnlockedBgmIdListNotifyOuterClass; + +public class PacketHomeNewUnlockedBgmIdListNotify extends BasePacket { + public PacketHomeNewUnlockedBgmIdListNotify(int homeBgmId) { + super(PacketOpcodes.HomeNewUnlockedBgmIdListNotify); + + var notify = + HomeNewUnlockedBgmIdListNotifyOuterClass.HomeNewUnlockedBgmIdListNotify.newBuilder() + .addNewUnlockedBgmIdList(homeBgmId) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceNotify.java index b383cb799..aaeae4bc0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceNotify.java @@ -1,35 +1,38 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeResourceNotifyOuterClass; -import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; - -public class PacketHomeResourceNotify extends BasePacket { - public PacketHomeResourceNotify(Player player) { - super(PacketOpcodes.HomeResourceNotify); - - var home = player.getHome(); - var level = home.getLevel(); - - HomeResource coin = HomeResource.newBuilder() - .setNextRefreshTime(home.getNextUpdateTime()) - .setStoreLimit(home.getMaxCoin(level)) - .setStoreValue(home.getStoredCoin()) - .build(); - - HomeResource fetter = HomeResource.newBuilder() - .setNextRefreshTime(home.getNextUpdateTime()) - .setStoreLimit(home.getMaxFetter(level)) - .setStoreValue(home.getStoredFetterExp()) - .build(); - - var notify = HomeResourceNotifyOuterClass.HomeResourceNotify.newBuilder() - .setFetterExp(fetter) - .setHomeCoin(coin) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeResourceNotifyOuterClass; +import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; + +public class PacketHomeResourceNotify extends BasePacket { + public PacketHomeResourceNotify(Player player) { + super(PacketOpcodes.HomeResourceNotify); + + var home = player.getHome(); + var level = home.getLevel(); + + HomeResource coin = + HomeResource.newBuilder() + .setNextRefreshTime(home.getNextUpdateTime()) + .setStoreLimit(home.getMaxCoin(level)) + .setStoreValue(home.getStoredCoin()) + .build(); + + HomeResource fetter = + HomeResource.newBuilder() + .setNextRefreshTime(home.getNextUpdateTime()) + .setStoreLimit(home.getMaxFetter(level)) + .setStoreValue(home.getStoredFetterExp()) + .build(); + + var notify = + HomeResourceNotifyOuterClass.HomeResourceNotify.newBuilder() + .setFetterExp(fetter) + .setHomeCoin(coin) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeFetterExpRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeFetterExpRsp.java index d45d27ca9..fb98e659c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeFetterExpRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeFetterExpRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; -import emu.grasscutter.net.proto.HomeResourceTakeFetterExpRspOuterClass; - -public class PacketHomeResourceTakeFetterExpRsp extends BasePacket { - public PacketHomeResourceTakeFetterExpRsp(Player player) { - super(PacketOpcodes.HomeResourceTakeFetterExpRsp); - - var home = player.getHome(); - - home.takeHomeFetter(player); - - var fetterExp = HomeResource.newBuilder() - .setNextRefreshTime(home.getNextUpdateTime()) - .setStoreLimit(home.getMaxFetter(home.getLevel())) - .setStoreValue(0) - .build(); - - var proto = HomeResourceTakeFetterExpRspOuterClass.HomeResourceTakeFetterExpRsp.newBuilder() - .setFetterExp(fetterExp) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; +import emu.grasscutter.net.proto.HomeResourceTakeFetterExpRspOuterClass; + +public class PacketHomeResourceTakeFetterExpRsp extends BasePacket { + public PacketHomeResourceTakeFetterExpRsp(Player player) { + super(PacketOpcodes.HomeResourceTakeFetterExpRsp); + + var home = player.getHome(); + + home.takeHomeFetter(player); + + var fetterExp = + HomeResource.newBuilder() + .setNextRefreshTime(home.getNextUpdateTime()) + .setStoreLimit(home.getMaxFetter(home.getLevel())) + .setStoreValue(0) + .build(); + + var proto = + HomeResourceTakeFetterExpRspOuterClass.HomeResourceTakeFetterExpRsp.newBuilder() + .setFetterExp(fetterExp) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeHomeCoinRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeHomeCoinRsp.java index 0112d1b29..c273d80a4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeHomeCoinRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeResourceTakeHomeCoinRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; -import emu.grasscutter.net.proto.HomeResourceTakeHomeCoinRspOuterClass; - -public class PacketHomeResourceTakeHomeCoinRsp extends BasePacket { - public PacketHomeResourceTakeHomeCoinRsp(Player player) { - super(PacketOpcodes.HomeResourceTakeHomeCoinRsp); - - var home = player.getHome(); - - home.takeHomeCoin(player); - - var coin = HomeResource.newBuilder() - .setNextRefreshTime(home.getNextUpdateTime()) - .setStoreLimit(home.getMaxCoin(home.getLevel())) - .setStoreValue(0) - .build(); - - var proto = HomeResourceTakeHomeCoinRspOuterClass.HomeResourceTakeHomeCoinRsp.newBuilder() - .setHomeCoin(coin) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeResourceOuterClass.HomeResource; +import emu.grasscutter.net.proto.HomeResourceTakeHomeCoinRspOuterClass; + +public class PacketHomeResourceTakeHomeCoinRsp extends BasePacket { + public PacketHomeResourceTakeHomeCoinRsp(Player player) { + super(PacketOpcodes.HomeResourceTakeHomeCoinRsp); + + var home = player.getHome(); + + home.takeHomeCoin(player); + + var coin = + HomeResource.newBuilder() + .setNextRefreshTime(home.getNextUpdateTime()) + .setStoreLimit(home.getMaxCoin(home.getLevel())) + .setStoreValue(0) + .build(); + + var proto = + HomeResourceTakeHomeCoinRspOuterClass.HomeResourceTakeHomeCoinRsp.newBuilder() + .setHomeCoin(coin) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneInitFinishRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneInitFinishRsp.java index 8fd8f1883..6f1005b5d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneInitFinishRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneInitFinishRsp.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeSceneInitFinishReqOuterClass; - -public class PacketHomeSceneInitFinishRsp extends BasePacket { - - public PacketHomeSceneInitFinishRsp() { - super(PacketOpcodes.HomeSceneInitFinishRsp); - - var proto = HomeSceneInitFinishReqOuterClass.HomeSceneInitFinishReq.newBuilder(); - - this.setData(proto); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeSceneInitFinishReqOuterClass; + +public class PacketHomeSceneInitFinishRsp extends BasePacket { + + public PacketHomeSceneInitFinishRsp() { + super(PacketOpcodes.HomeSceneInitFinishRsp); + + var proto = HomeSceneInitFinishReqOuterClass.HomeSceneInitFinishReq.newBuilder(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneJumpRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneJumpRsp.java index 0da6158d6..3ce855a0c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneJumpRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeSceneJumpRsp.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HomeSceneJumpRspOuterClass; - -public class PacketHomeSceneJumpRsp extends BasePacket { - - public PacketHomeSceneJumpRsp(boolean enterRoomScene) { - super(PacketOpcodes.HomeSceneJumpRsp); - - var proto = HomeSceneJumpRspOuterClass.HomeSceneJumpRsp.newBuilder(); - - proto.setIsEnterRoomScene(enterRoomScene); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeSceneJumpRspOuterClass; + +public class PacketHomeSceneJumpRsp extends BasePacket { + + public PacketHomeSceneJumpRsp(boolean enterRoomScene) { + super(PacketOpcodes.HomeSceneJumpRsp); + + var proto = HomeSceneJumpRspOuterClass.HomeSceneJumpRsp.newBuilder(); + + proto.setIsEnterRoomScene(enterRoomScene); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeUpdateArrangementInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeUpdateArrangementInfoRsp.java index 1c508bdd0..bd71654d0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeUpdateArrangementInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeUpdateArrangementInfoRsp.java @@ -1,12 +1,11 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketHomeUpdateArrangementInfoRsp extends BasePacket { - - public PacketHomeUpdateArrangementInfoRsp() { - super(PacketOpcodes.HomeUpdateArrangementInfoRsp); - - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketHomeUpdateArrangementInfoRsp extends BasePacket { + + public PacketHomeUpdateArrangementInfoRsp() { + super(PacketOpcodes.HomeUpdateArrangementInfoRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHostPlayerNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHostPlayerNotify.java index d0b65f545..a089ac1e7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketHostPlayerNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHostPlayerNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.HostPlayerNotifyOuterClass.HostPlayerNotify; - -public class PacketHostPlayerNotify extends BasePacket { - - public PacketHostPlayerNotify(World world) { - super(PacketOpcodes.HostPlayerNotify); - - HostPlayerNotify proto = HostPlayerNotify.newBuilder() - .setHostUid(world.getHost().getUid()) - .setHostPeerId(world.getHost().getPeerId()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HostPlayerNotifyOuterClass.HostPlayerNotify; + +public class PacketHostPlayerNotify extends BasePacket { + + public PacketHostPlayerNotify(World world) { + super(PacketOpcodes.HostPlayerNotify); + + HostPlayerNotify proto = + HostPlayerNotify.newBuilder() + .setHostUid(world.getHost().getUid()) + .setHostPeerId(world.getHost().getPeerId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketItemAddHintNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketItemAddHintNotify.java index 4ee6ee534..409dd9b06 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketItemAddHintNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketItemAddHintNotify.java @@ -1,36 +1,35 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.props.ActionReason; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemAddHintNotifyOuterClass.ItemAddHintNotify; - -import java.util.Collection; - -public class PacketItemAddHintNotify extends BasePacket { - - public PacketItemAddHintNotify(GameItem item, ActionReason reason) { - super(PacketOpcodes.ItemAddHintNotify); - - ItemAddHintNotify proto = ItemAddHintNotify.newBuilder() - .addItemList(item.toItemHintProto()) - .setReason(reason.getValue()) - .build(); - - this.setData(proto); - } - - public PacketItemAddHintNotify(Collection items, ActionReason reason) { - super(PacketOpcodes.ItemAddHintNotify); - - ItemAddHintNotify.Builder proto = ItemAddHintNotify.newBuilder() - .setReason(reason.getValue()); - - for (GameItem item : items) { - proto.addItemList(item.toItemHintProto()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemAddHintNotifyOuterClass.ItemAddHintNotify; +import java.util.Collection; + +public class PacketItemAddHintNotify extends BasePacket { + + public PacketItemAddHintNotify(GameItem item, ActionReason reason) { + super(PacketOpcodes.ItemAddHintNotify); + + ItemAddHintNotify proto = + ItemAddHintNotify.newBuilder() + .addItemList(item.toItemHintProto()) + .setReason(reason.getValue()) + .build(); + + this.setData(proto); + } + + public PacketItemAddHintNotify(Collection items, ActionReason reason) { + super(PacketOpcodes.ItemAddHintNotify); + + ItemAddHintNotify.Builder proto = ItemAddHintNotify.newBuilder().setReason(reason.getValue()); + + for (GameItem item : items) { + proto.addItemList(item.toItemHintProto()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketLaunchFireworksRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketLaunchFireworksRsp.java index 3e0d29c6b..271dfc2db 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketLaunchFireworksRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketLaunchFireworksRsp.java @@ -1,13 +1,11 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketLaunchFireworksRsp extends BasePacket { - - public PacketLaunchFireworksRsp() { - super(PacketOpcodes.LaunchFireworksRsp); - - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketLaunchFireworksRsp extends BasePacket { + + public PacketLaunchFireworksRsp() { + super(PacketOpcodes.LaunchFireworksRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketLifeStateChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketLifeStateChangeNotify.java index f427768dc..141e1ffc4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketLifeStateChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketLifeStateChangeNotify.java @@ -1,67 +1,74 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.LifeState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.LifeStateChangeNotifyOuterClass.LifeStateChangeNotify; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; - -public class PacketLifeStateChangeNotify extends BasePacket { - public PacketLifeStateChangeNotify(GameEntity target, LifeState lifeState) { - super(PacketOpcodes.LifeStateChangeNotify); - - LifeStateChangeNotify proto = LifeStateChangeNotify.newBuilder() - .setEntityId(target.getId()) - .setLifeState(lifeState.getValue()) - .build(); - - this.setData(proto); - } - - public PacketLifeStateChangeNotify(GameEntity attacker, GameEntity target, LifeState lifeState) { - super(PacketOpcodes.LifeStateChangeNotify); - - LifeStateChangeNotify proto = LifeStateChangeNotify.newBuilder() - .setEntityId(target.getId()) - .setLifeState(lifeState.getValue()) - .setSourceEntityId(attacker.getId()) - .build(); - - this.setData(proto); - } - - public PacketLifeStateChangeNotify(int attackerId, GameEntity target, LifeState lifeState) { - super(PacketOpcodes.LifeStateChangeNotify); - - LifeStateChangeNotify proto = LifeStateChangeNotify.newBuilder() - .setEntityId(target.getId()) - .setLifeState(lifeState.getValue()) - .setSourceEntityId(attackerId) - .build(); - - this.setData(proto); - } - - public PacketLifeStateChangeNotify(GameEntity entity, LifeState lifeState, PlayerDieType dieType) { - this(entity, lifeState, null, "", dieType); - } - - public PacketLifeStateChangeNotify(GameEntity entity, LifeState lifeState, GameEntity sourceEntity, - String attackTag, PlayerDieType dieType) { - super(PacketOpcodes.LifeStateChangeNotify); - - LifeStateChangeNotify.Builder proto = LifeStateChangeNotify.newBuilder(); - - - proto.setEntityId(entity.getId()); - proto.setLifeState(lifeState.getValue()); - if (sourceEntity != null) { - proto.setSourceEntityId(sourceEntity.getId()); - } - proto.setAttackTag(attackTag); - proto.setDieType(dieType); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.LifeStateChangeNotifyOuterClass.LifeStateChangeNotify; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; + +public class PacketLifeStateChangeNotify extends BasePacket { + public PacketLifeStateChangeNotify(GameEntity target, LifeState lifeState) { + super(PacketOpcodes.LifeStateChangeNotify); + + LifeStateChangeNotify proto = + LifeStateChangeNotify.newBuilder() + .setEntityId(target.getId()) + .setLifeState(lifeState.getValue()) + .build(); + + this.setData(proto); + } + + public PacketLifeStateChangeNotify(GameEntity attacker, GameEntity target, LifeState lifeState) { + super(PacketOpcodes.LifeStateChangeNotify); + + LifeStateChangeNotify proto = + LifeStateChangeNotify.newBuilder() + .setEntityId(target.getId()) + .setLifeState(lifeState.getValue()) + .setSourceEntityId(attacker.getId()) + .build(); + + this.setData(proto); + } + + public PacketLifeStateChangeNotify(int attackerId, GameEntity target, LifeState lifeState) { + super(PacketOpcodes.LifeStateChangeNotify); + + LifeStateChangeNotify proto = + LifeStateChangeNotify.newBuilder() + .setEntityId(target.getId()) + .setLifeState(lifeState.getValue()) + .setSourceEntityId(attackerId) + .build(); + + this.setData(proto); + } + + public PacketLifeStateChangeNotify( + GameEntity entity, LifeState lifeState, PlayerDieType dieType) { + this(entity, lifeState, null, "", dieType); + } + + public PacketLifeStateChangeNotify( + GameEntity entity, + LifeState lifeState, + GameEntity sourceEntity, + String attackTag, + PlayerDieType dieType) { + super(PacketOpcodes.LifeStateChangeNotify); + + LifeStateChangeNotify.Builder proto = LifeStateChangeNotify.newBuilder(); + + proto.setEntityId(entity.getId()); + proto.setLifeState(lifeState.getValue()); + if (sourceEntity != null) { + proto.setSourceEntityId(sourceEntity.getId()); + } + proto.setAttackTag(attackTag); + proto.setDieType(dieType); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java index b73c9dcec..8c5566ec6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java @@ -1,74 +1,76 @@ -package emu.grasscutter.server.packet.send; - - -import emu.grasscutter.game.mail.Mail; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EquipParamOuterClass.EquipParam; -import emu.grasscutter.net.proto.MailChangeNotifyOuterClass.MailChangeNotify; -import emu.grasscutter.net.proto.MailDataOuterClass.MailData; -import emu.grasscutter.net.proto.MailItemOuterClass.MailItem; -import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; - -import java.util.ArrayList; -import java.util.List; - -public class PacketMailChangeNotify extends BasePacket { - - public PacketMailChangeNotify(Player player, Mail message) { - this(player, new ArrayList() {{ - add(message); - }}); - } - - public PacketMailChangeNotify(Player player, List mailList) { - this(player, mailList, null); - } - - public PacketMailChangeNotify(Player player, List mailList, List delMailIdList) { - super(PacketOpcodes.MailChangeNotify); - - var proto = MailChangeNotify.newBuilder(); - - if (mailList != null) { - for (Mail message : mailList) { - var mailTextContent = MailTextContent.newBuilder(); - mailTextContent.setTitle(message.mailContent.title); - mailTextContent.setContent(message.mailContent.content); - mailTextContent.setSender(message.mailContent.sender); - - List mailItems = new ArrayList<>(); - - for (Mail.MailItem item : message.itemList) { - var mailItem = MailItem.newBuilder(); - var itemParam = EquipParam.newBuilder(); - itemParam.setItemId(item.itemId); - itemParam.setItemNum(item.itemCount); - mailItem.setEquipParam(itemParam.build()); - - mailItems.add(mailItem.build()); - } - - var mailData = MailData.newBuilder(); - mailData.setMailId(player.getMailId(message)); - mailData.setMailTextContent(mailTextContent.build()); - mailData.addAllItemList(mailItems); - mailData.setSendTime((int) message.sendTime); - mailData.setExpireTime((int) message.expireTime); - mailData.setImportance(message.importance); - mailData.setIsRead(message.isRead); - mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setCollectStateValue(message.stateValue); - - proto.addMailList(mailData.build()); - } - } - - if (delMailIdList != null) { - proto.addAllDelMailIdList(delMailIdList); - } - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.mail.Mail; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EquipParamOuterClass.EquipParam; +import emu.grasscutter.net.proto.MailChangeNotifyOuterClass.MailChangeNotify; +import emu.grasscutter.net.proto.MailDataOuterClass.MailData; +import emu.grasscutter.net.proto.MailItemOuterClass.MailItem; +import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; +import java.util.ArrayList; +import java.util.List; + +public class PacketMailChangeNotify extends BasePacket { + + public PacketMailChangeNotify(Player player, Mail message) { + this( + player, + new ArrayList() { + { + add(message); + } + }); + } + + public PacketMailChangeNotify(Player player, List mailList) { + this(player, mailList, null); + } + + public PacketMailChangeNotify(Player player, List mailList, List delMailIdList) { + super(PacketOpcodes.MailChangeNotify); + + var proto = MailChangeNotify.newBuilder(); + + if (mailList != null) { + for (Mail message : mailList) { + var mailTextContent = MailTextContent.newBuilder(); + mailTextContent.setTitle(message.mailContent.title); + mailTextContent.setContent(message.mailContent.content); + mailTextContent.setSender(message.mailContent.sender); + + List mailItems = new ArrayList<>(); + + for (Mail.MailItem item : message.itemList) { + var mailItem = MailItem.newBuilder(); + var itemParam = EquipParam.newBuilder(); + itemParam.setItemId(item.itemId); + itemParam.setItemNum(item.itemCount); + mailItem.setEquipParam(itemParam.build()); + + mailItems.add(mailItem.build()); + } + + var mailData = MailData.newBuilder(); + mailData.setMailId(player.getMailId(message)); + mailData.setMailTextContent(mailTextContent.build()); + mailData.addAllItemList(mailItems); + mailData.setSendTime((int) message.sendTime); + mailData.setExpireTime((int) message.expireTime); + mailData.setImportance(message.importance); + mailData.setIsRead(message.isRead); + mailData.setIsAttachmentGot(message.isAttachmentGot); + mailData.setCollectStateValue(message.stateValue); + + proto.addMailList(mailData.build()); + } + } + + if (delMailIdList != null) { + proto.addAllDelMailIdList(delMailIdList); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java index 9a21f3e7e..90b39244f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java @@ -1,35 +1,34 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.managers.mapmark.MapMark; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MapMarkPointOuterClass.MapMarkPoint; -import emu.grasscutter.net.proto.MarkMapRspOuterClass.MarkMapRsp; - -import java.util.Map; - -public class PacketMarkMapRsp extends BasePacket { - - public PacketMarkMapRsp(Map mapMarks) { - super(PacketOpcodes.MarkMapRsp); - - var proto = MarkMapRsp.newBuilder(); - proto.setRetcode(0); - - if (mapMarks != null) { - for (MapMark mapMark : mapMarks.values()) { - var markPoint = MapMarkPoint.newBuilder(); - markPoint.setSceneId(mapMark.getSceneId()); - markPoint.setName(mapMark.getName()); - markPoint.setPos(mapMark.getPosition().toProto()); - markPoint.setPointType(mapMark.getMapMarkPointType()); - markPoint.setFromType(mapMark.getMapMarkFromType()); - markPoint.setMonsterId(mapMark.getMonsterId()); - markPoint.setQuestId(mapMark.getQuestId()); - - proto.addMarkList(markPoint.build()); - } - } - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.managers.mapmark.MapMark; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MapMarkPointOuterClass.MapMarkPoint; +import emu.grasscutter.net.proto.MarkMapRspOuterClass.MarkMapRsp; +import java.util.Map; + +public class PacketMarkMapRsp extends BasePacket { + + public PacketMarkMapRsp(Map mapMarks) { + super(PacketOpcodes.MarkMapRsp); + + var proto = MarkMapRsp.newBuilder(); + proto.setRetcode(0); + + if (mapMarks != null) { + for (MapMark mapMark : mapMarks.values()) { + var markPoint = MapMarkPoint.newBuilder(); + markPoint.setSceneId(mapMark.getSceneId()); + markPoint.setName(mapMark.getName()); + markPoint.setPos(mapMark.getPosition().toProto()); + markPoint.setPointType(mapMark.getMapMarkPointType()); + markPoint.setFromType(mapMark.getMapMarkFromType()); + markPoint.setMonsterId(mapMark.getMonsterId()); + markPoint.setQuestId(mapMark.getQuestId()); + + proto.addMarkList(markPoint.build()); + } + } + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkNewNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkNewNotify.java index c38826b26..4c847c1f2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkNewNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkNewNotify.java @@ -1,21 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MarkNewNotifyOuterClass.MarkNewNotify; - -import java.util.ArrayList; - -public class PacketMarkNewNotify extends BasePacket { - - public PacketMarkNewNotify(Player player, int markNewType, ArrayList idList) { - super(PacketOpcodes.MarkNewNotify); - - var proto = MarkNewNotify.newBuilder(); - proto.setMarkNewType(markNewType); - proto.addAllIdList(idList); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MarkNewNotifyOuterClass.MarkNewNotify; +import java.util.ArrayList; + +public class PacketMarkNewNotify extends BasePacket { + + public PacketMarkNewNotify(Player player, int markNewType, ArrayList idList) { + super(PacketOpcodes.MarkNewNotify); + + var proto = MarkNewNotify.newBuilder(); + proto.setMarkNewType(markNewType); + proto.addAllIdList(idList); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMcoinExchangeHcoinRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMcoinExchangeHcoinRsp.java index c53ed8dc2..7d7ebe937 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMcoinExchangeHcoinRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMcoinExchangeHcoinRsp.java @@ -1,18 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.McoinExchangeHcoinRspOuterClass; - -public class PacketMcoinExchangeHcoinRsp extends BasePacket { - - public PacketMcoinExchangeHcoinRsp(int retCode) { - super(PacketOpcodes.McoinExchangeHcoinRsp); - - McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp proto = McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp.newBuilder() - .setRetcode(retCode) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.McoinExchangeHcoinRspOuterClass; + +public class PacketMcoinExchangeHcoinRsp extends BasePacket { + + public PacketMcoinExchangeHcoinRsp(int retCode) { + super(PacketOpcodes.McoinExchangeHcoinRsp); + + McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp proto = + McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp.newBuilder() + .setRetcode(retCode) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameCreateBeatmapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameCreateBeatmapRsp.java index 638c8463e..c106f6caf 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameCreateBeatmapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameCreateBeatmapRsp.java @@ -1,20 +1,21 @@ -//package emu.grasscutter.server.packet.send; -// -//import emu.grasscutter.net.packet.BasePacket; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameCreateBeatmapRspOuterClass; -//import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; -// -//public class PacketMusicGameCreateBeatmapRsp extends BasePacket { -// -// public PacketMusicGameCreateBeatmapRsp(long musicShareId, MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { -// super(PacketOpcodes.MusicGameCreateBeatmapRsp); -// -// var proto = MusicGameCreateBeatmapRspOuterClass.MusicGameCreateBeatmapRsp.newBuilder(); -// -// proto.setMusicShareId(musicShareId) -// .setUnknownEnum1(unknownEnum1); -// -// this.setData(proto); -// } -//} +// package emu.grasscutter.server.packet.send; +// +// import emu.grasscutter.net.packet.BasePacket; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameCreateBeatmapRspOuterClass; +// import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; +// +// public class PacketMusicGameCreateBeatmapRsp extends BasePacket { +// +// public PacketMusicGameCreateBeatmapRsp(long musicShareId, +// MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { +// super(PacketOpcodes.MusicGameCreateBeatmapRsp); +// +// var proto = MusicGameCreateBeatmapRspOuterClass.MusicGameCreateBeatmapRsp.newBuilder(); +// +// proto.setMusicShareId(musicShareId) +// .setUnknownEnum1(unknownEnum1); +// +// this.setData(proto); +// } +// } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameGetBeatmapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameGetBeatmapRsp.java index 43c49ef21..bbafd4f2e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameGetBeatmapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameGetBeatmapRsp.java @@ -1,27 +1,29 @@ -//package emu.grasscutter.server.packet.send; -// -//import emu.grasscutter.net.packet.BasePacket; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicBeatmapOuterClass; -//import emu.grasscutter.net.proto.MusicBriefInfoOuterClass; -//import emu.grasscutter.net.proto.MusicGameGetBeatmapReqOuterClass; -//import emu.grasscutter.net.proto.MusicGameGetBeatmapRspOuterClass; -// -//public class PacketMusicGameGetBeatmapRsp extends BasePacket { -// -// public PacketMusicGameGetBeatmapRsp(MusicBriefInfoOuterClass.MusicBriefInfo briefInfo, MusicBeatmapOuterClass.MusicBeatmap musicRecord, MusicGameGetBeatmapReqOuterClass.MusicGameGetBeatmapReq req) { -// super(PacketOpcodes.MusicGameGetBeatmapRsp); -// -// var proto = MusicGameGetBeatmapRspOuterClass.MusicGameGetBeatmapRsp.newBuilder(); -// -// proto.setMusicBriefInfo(briefInfo) -// .setMusicShareId(briefInfo.getMusicShareId()) -// .setMusicRecord(musicRecord) -// .setUnknownEnum1(req.getUnknownEnum1()) -// .setReqType(req.getReqType()) -// ; -// -// -// this.setData(proto); -// } -//} +// package emu.grasscutter.server.packet.send; +// +// import emu.grasscutter.net.packet.BasePacket; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicBeatmapOuterClass; +// import emu.grasscutter.net.proto.MusicBriefInfoOuterClass; +// import emu.grasscutter.net.proto.MusicGameGetBeatmapReqOuterClass; +// import emu.grasscutter.net.proto.MusicGameGetBeatmapRspOuterClass; +// +// public class PacketMusicGameGetBeatmapRsp extends BasePacket { +// +// public PacketMusicGameGetBeatmapRsp(MusicBriefInfoOuterClass.MusicBriefInfo briefInfo, +// MusicBeatmapOuterClass.MusicBeatmap musicRecord, +// MusicGameGetBeatmapReqOuterClass.MusicGameGetBeatmapReq req) { +// super(PacketOpcodes.MusicGameGetBeatmapRsp); +// +// var proto = MusicGameGetBeatmapRspOuterClass.MusicGameGetBeatmapRsp.newBuilder(); +// +// proto.setMusicBriefInfo(briefInfo) +// .setMusicShareId(briefInfo.getMusicShareId()) +// .setMusicRecord(musicRecord) +// .setUnknownEnum1(req.getUnknownEnum1()) +// .setReqType(req.getReqType()) +// ; +// +// +// this.setData(proto); +// } +// } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSearchBeatmapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSearchBeatmapRsp.java index b29b750ba..9bfd9ce18 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSearchBeatmapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSearchBeatmapRsp.java @@ -1,34 +1,36 @@ -//package emu.grasscutter.server.packet.send; -// -//import emu.grasscutter.net.packet.BasePacket; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicBriefInfoOuterClass; -//import emu.grasscutter.net.proto.MusicGameSearchBeatmapRspOuterClass; -//import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; -// -//public class PacketMusicGameSearchBeatmapRsp extends BasePacket { -// -// public PacketMusicGameSearchBeatmapRsp(int ret, MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { -// super(PacketOpcodes.MusicGameSearchBeatmapRsp); -// -// var proto = MusicGameSearchBeatmapRspOuterClass.MusicGameSearchBeatmapRsp.newBuilder(); -// -// proto.setRetcode(ret) -// .setUnknownEnum1(unknownEnum1); -// -// this.setData(proto); -// } -// -// public PacketMusicGameSearchBeatmapRsp(MusicBriefInfoOuterClass.MusicBriefInfo briefInfo, MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { -// super(PacketOpcodes.MusicGameSearchBeatmapRsp); -// -// var proto = MusicGameSearchBeatmapRspOuterClass.MusicGameSearchBeatmapRsp.newBuilder(); -// -// proto.setMusicBriefInfo(briefInfo) -// .setUnknownEnum1(unknownEnum1); -// -// this.setData(proto); -// } -// -// -//} +// package emu.grasscutter.server.packet.send; +// +// import emu.grasscutter.net.packet.BasePacket; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicBriefInfoOuterClass; +// import emu.grasscutter.net.proto.MusicGameSearchBeatmapRspOuterClass; +// import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; +// +// public class PacketMusicGameSearchBeatmapRsp extends BasePacket { +// +// public PacketMusicGameSearchBeatmapRsp(int ret, +// MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { +// super(PacketOpcodes.MusicGameSearchBeatmapRsp); +// +// var proto = MusicGameSearchBeatmapRspOuterClass.MusicGameSearchBeatmapRsp.newBuilder(); +// +// proto.setRetcode(ret) +// .setUnknownEnum1(unknownEnum1); +// +// this.setData(proto); +// } +// +// public PacketMusicGameSearchBeatmapRsp(MusicBriefInfoOuterClass.MusicBriefInfo briefInfo, +// MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { +// super(PacketOpcodes.MusicGameSearchBeatmapRsp); +// +// var proto = MusicGameSearchBeatmapRspOuterClass.MusicGameSearchBeatmapRsp.newBuilder(); +// +// proto.setMusicBriefInfo(briefInfo) +// .setUnknownEnum1(unknownEnum1); +// +// this.setData(proto); +// } +// +// +// } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSettleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSettleRsp.java index 7d74f3737..403be8b98 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSettleRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameSettleRsp.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MusicGameSettleRspOuterClass; - -public class PacketMusicGameSettleRsp extends BasePacket { - - public PacketMusicGameSettleRsp(int musicBasicId, long musicShareId, boolean isNewRecord) { - super(PacketOpcodes.MusicGameSettleRsp); - - var proto = MusicGameSettleRspOuterClass.MusicGameSettleRsp.newBuilder(); - - proto.setMusicBasicId(musicBasicId) - .setUgcGuid(musicShareId) - .setIsNewRecord(isNewRecord); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MusicGameSettleRspOuterClass; + +public class PacketMusicGameSettleRsp extends BasePacket { + + public PacketMusicGameSettleRsp(int musicBasicId, long musicShareId, boolean isNewRecord) { + super(PacketOpcodes.MusicGameSettleRsp); + + var proto = MusicGameSettleRspOuterClass.MusicGameSettleRsp.newBuilder(); + + proto.setMusicBasicId(musicBasicId).setUgcGuid(musicShareId).setIsNewRecord(isNewRecord); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartRsp.java index fedd29dd6..05052dc1a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.MusicGameStartRspOuterClass; - -public class PacketMusicGameStartRsp extends BasePacket { - - public PacketMusicGameStartRsp(int musicBasicId, long musicShareId) { - super(PacketOpcodes.MusicGameStartRsp); - - var proto = MusicGameStartRspOuterClass.MusicGameStartRsp.newBuilder(); - - proto.setMusicBasicId(musicBasicId) - .setUgcGuid(musicShareId); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.MusicGameStartRspOuterClass; + +public class PacketMusicGameStartRsp extends BasePacket { + + public PacketMusicGameStartRsp(int musicBasicId, long musicShareId) { + super(PacketOpcodes.MusicGameStartRsp); + + var proto = MusicGameStartRspOuterClass.MusicGameStartRsp.newBuilder(); + + proto.setMusicBasicId(musicBasicId).setUgcGuid(musicShareId); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartToPlayOthersBeatmapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartToPlayOthersBeatmapRsp.java index 0d2f36957..a0a90a69f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartToPlayOthersBeatmapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMusicGameStartToPlayOthersBeatmapRsp.java @@ -1,19 +1,22 @@ -//package emu.grasscutter.server.packet.send; -// -//import emu.grasscutter.net.packet.BasePacket; -//import emu.grasscutter.net.packet.PacketOpcodes; -//import emu.grasscutter.net.proto.MusicGameStartToPlayOthersBeatmapRspOuterClass; -//import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; -// -//public class PacketMusicGameStartToPlayOthersBeatmapRsp extends BasePacket { -// -// public PacketMusicGameStartToPlayOthersBeatmapRsp(MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum unknownEnum1) { -// super(PacketOpcodes.MusicGameStartToPlayOthersBeatmapRsp); -// -// var proto = MusicGameStartToPlayOthersBeatmapRspOuterClass.MusicGameStartToPlayOthersBeatmapRsp.newBuilder(); -// -// proto.setUnknownEnum1(unknownEnum1); -// -// this.setData(proto); -// } -//} +// package emu.grasscutter.server.packet.send; +// +// import emu.grasscutter.net.packet.BasePacket; +// import emu.grasscutter.net.packet.PacketOpcodes; +// import emu.grasscutter.net.proto.MusicGameStartToPlayOthersBeatmapRspOuterClass; +// import emu.grasscutter.net.proto.MusicGameUnknown1EnumOuterClass; +// +// public class PacketMusicGameStartToPlayOthersBeatmapRsp extends BasePacket { +// +// public +// PacketMusicGameStartToPlayOthersBeatmapRsp(MusicGameUnknown1EnumOuterClass.MusicGameUnknown1Enum +// unknownEnum1) { +// super(PacketOpcodes.MusicGameStartToPlayOthersBeatmapRsp); +// +// var proto = +// MusicGameStartToPlayOthersBeatmapRspOuterClass.MusicGameStartToPlayOthersBeatmapRsp.newBuilder(); +// +// proto.setUnknownEnum1(unknownEnum1); +// +// this.setData(proto); +// } +// } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketNpcTalkRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketNpcTalkRsp.java index c960c485b..c32416758 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketNpcTalkRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketNpcTalkRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.NpcTalkRspOuterClass.NpcTalkRsp; - -public class PacketNpcTalkRsp extends BasePacket { - public PacketNpcTalkRsp(int npcEntityId, int curTalkId, int entityId) { - super(PacketOpcodes.NpcTalkRsp); - - NpcTalkRsp p = NpcTalkRsp.newBuilder() - .setNpcEntityId(npcEntityId) - .setCurTalkId(curTalkId) - .setEntityId(entityId) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.NpcTalkRspOuterClass.NpcTalkRsp; + +public class PacketNpcTalkRsp extends BasePacket { + public PacketNpcTalkRsp(int npcEntityId, int curTalkId, int entityId) { + super(PacketOpcodes.NpcTalkRsp); + + NpcTalkRsp p = + NpcTalkRsp.newBuilder() + .setNpcEntityId(npcEntityId) + .setCurTalkId(curTalkId) + .setEntityId(entityId) + .build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketOpenStateChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketOpenStateChangeNotify.java index 33e970f85..c1ecf5d25 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketOpenStateChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketOpenStateChangeNotify.java @@ -1,32 +1,28 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.OpenStateChangeNotifyOuterClass.OpenStateChangeNotify; - -import java.util.Map; - -//Sets openState to value -public class PacketOpenStateChangeNotify extends BasePacket { - - public PacketOpenStateChangeNotify(int openState, int value) { - super(PacketOpcodes.OpenStateChangeNotify); - - OpenStateChangeNotify proto = OpenStateChangeNotify.newBuilder() - .putOpenStateMap(openState, value) - .build(); - - this.setData(proto); - } - - public PacketOpenStateChangeNotify(Map map) { - super(PacketOpcodes.OpenStateChangeNotify); - - OpenStateChangeNotify proto = OpenStateChangeNotify.newBuilder() - .putAllOpenStateMap(map) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.OpenStateChangeNotifyOuterClass.OpenStateChangeNotify; +import java.util.Map; + +// Sets openState to value +public class PacketOpenStateChangeNotify extends BasePacket { + + public PacketOpenStateChangeNotify(int openState, int value) { + super(PacketOpcodes.OpenStateChangeNotify); + + OpenStateChangeNotify proto = + OpenStateChangeNotify.newBuilder().putOpenStateMap(openState, value).build(); + + this.setData(proto); + } + + public PacketOpenStateChangeNotify(Map map) { + super(PacketOpcodes.OpenStateChangeNotify); + + OpenStateChangeNotify proto = + OpenStateChangeNotify.newBuilder().putAllOpenStateMap(map).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPathfindingEnterSceneRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPathfindingEnterSceneRsp.java index eb9458f21..75daebb19 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPathfindingEnterSceneRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPathfindingEnterSceneRsp.java @@ -1,11 +1,11 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketPathfindingEnterSceneRsp extends BasePacket { - - public PacketPathfindingEnterSceneRsp(int clientSequence) { - super(PacketOpcodes.PathfindingEnterSceneRsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketPathfindingEnterSceneRsp extends BasePacket { + + public PacketPathfindingEnterSceneRsp(int clientSequence) { + super(PacketOpcodes.PathfindingEnterSceneRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalLineAllDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalLineAllDataRsp.java index 6157e11e9..dfd588c44 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalLineAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalLineAllDataRsp.java @@ -1,34 +1,34 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.data.GameData; -import emu.grasscutter.game.quest.GameMainQuest; -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PersonalLineAllDataRspOuterClass; - -import java.util.Collection; -import java.util.Map; -import java.util.stream.Collectors; - -public class PacketPersonalLineAllDataRsp extends BasePacket { - - public PacketPersonalLineAllDataRsp(Collection gameMainQuestList) { - super(PacketOpcodes.PersonalLineAllDataRsp); - - var proto = PersonalLineAllDataRspOuterClass.PersonalLineAllDataRsp.newBuilder(); - - var questList = gameMainQuestList.stream() - .map(GameMainQuest::getChildQuests) - .map(Map::values) - .flatMap(Collection::stream) - .map(GameQuest::getSubQuestId) - .collect(Collectors.toSet()); - - GameData.getPersonalLineDataMap().values().stream() - .filter(i -> !questList.contains(i.getStartQuestId())) - .forEach(i -> proto.addCanBeUnlockedPersonalLineList(i.getId())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PersonalLineAllDataRspOuterClass; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +public class PacketPersonalLineAllDataRsp extends BasePacket { + + public PacketPersonalLineAllDataRsp(Collection gameMainQuestList) { + super(PacketOpcodes.PersonalLineAllDataRsp); + + var proto = PersonalLineAllDataRspOuterClass.PersonalLineAllDataRsp.newBuilder(); + + var questList = + gameMainQuestList.stream() + .map(GameMainQuest::getChildQuests) + .map(Map::values) + .flatMap(Collection::stream) + .map(GameQuest::getSubQuestId) + .collect(Collectors.toSet()); + + GameData.getPersonalLineDataMap().values().stream() + .filter(i -> !questList.contains(i.getStartQuestId())) + .forEach(i -> proto.addCanBeUnlockedPersonalLineList(i.getId())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java index e61d1c7da..c633980c9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PersonalSceneJumpRspOuterClass.PersonalSceneJumpRsp; -import emu.grasscutter.utils.Position; - -public class PacketPersonalSceneJumpRsp extends BasePacket { - - public PacketPersonalSceneJumpRsp(int sceneId, Position pos) { - super(PacketOpcodes.PersonalSceneJumpRsp); - - PersonalSceneJumpRsp proto = PersonalSceneJumpRsp.newBuilder() - .setDestSceneId(sceneId) - .setDestPos(pos.toProto()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PersonalSceneJumpRspOuterClass.PersonalSceneJumpRsp; +import emu.grasscutter.utils.Position; + +public class PacketPersonalSceneJumpRsp extends BasePacket { + + public PacketPersonalSceneJumpRsp(int sceneId, Position pos) { + super(PacketOpcodes.PersonalSceneJumpRsp); + + PersonalSceneJumpRsp proto = + PersonalSceneJumpRsp.newBuilder().setDestSceneId(sceneId).setDestPos(pos.toProto()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPingRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPingRsp.java index c34dc84b3..539739b6b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPingRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPingRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PingRspOuterClass.PingRsp; - -public class PacketPingRsp extends BasePacket { - - public PacketPingRsp(int clientSeq, int time) { - super(PacketOpcodes.PingRsp, clientSeq); - - PingRsp p = PingRsp.newBuilder() - .setClientTime(time) - .build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PingRspOuterClass.PingRsp; + +public class PacketPingRsp extends BasePacket { + + public PacketPingRsp(int clientSeq, int time) { + super(PacketOpcodes.PingRsp, clientSeq); + + PingRsp p = PingRsp.newBuilder().setClientTime(time).build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStartRouteNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStartRouteNotify.java index 802de977a..c9ad31dc6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStartRouteNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStartRouteNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.platform.EntityPlatform; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlatformStartRouteNotifyOuterClass; - -public class PacketPlatformStartRouteNotify extends BasePacket { - public PacketPlatformStartRouteNotify(EntityPlatform entity, Scene scene) { - super(PacketOpcodes.PlatformStartRouteNotify); - - var notify = PlatformStartRouteNotifyOuterClass.PlatformStartRouteNotify.newBuilder() - .setEntityId(entity.getId()) - .setSceneTime(scene.getSceneTime()) - .setPlatform(entity.onStartRoute()) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.platform.EntityPlatform; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlatformStartRouteNotifyOuterClass; + +public class PacketPlatformStartRouteNotify extends BasePacket { + public PacketPlatformStartRouteNotify(EntityPlatform entity, Scene scene) { + super(PacketOpcodes.PlatformStartRouteNotify); + + var notify = + PlatformStartRouteNotifyOuterClass.PlatformStartRouteNotify.newBuilder() + .setEntityId(entity.getId()) + .setSceneTime(scene.getSceneTime()) + .setPlatform(entity.onStartRoute()) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStopRouteNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStopRouteNotify.java index 7b74a2379..6dec5b466 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStopRouteNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlatformStopRouteNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.platform.EntityPlatform; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlatformStopRouteNotifyOuterClass; - -public class PacketPlatformStopRouteNotify extends BasePacket { - public PacketPlatformStopRouteNotify(EntityPlatform entity, Scene scene) { - super(PacketOpcodes.PlatformStopRouteNotify); - - var notify = PlatformStopRouteNotifyOuterClass.PlatformStopRouteNotify.newBuilder() - .setPlatform(entity.onStopRoute()) - .setSceneTime(scene.getSceneTime()) - .setEntityId(entity.getId()) - .build(); - - this.setData(notify); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.platform.EntityPlatform; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlatformStopRouteNotifyOuterClass; + +public class PacketPlatformStopRouteNotify extends BasePacket { + public PacketPlatformStopRouteNotify(EntityPlatform entity, Scene scene) { + super(PacketOpcodes.PlatformStopRouteNotify); + + var notify = + PlatformStopRouteNotifyOuterClass.PlatformStopRouteNotify.newBuilder() + .setPlatform(entity.onStopRoute()) + .setSceneTime(scene.getSceneTime()) + .setEntityId(entity.getId()) + .build(); + + this.setData(notify); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpNotify.java index 228f48141..6f7c9e80c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpNotify.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpNotifyOuterClass.PlayerApplyEnterMpNotify; - -public class PacketPlayerApplyEnterMpNotify extends BasePacket { - - public PacketPlayerApplyEnterMpNotify(Player srcPlayer) { - super(PacketOpcodes.PlayerApplyEnterMpNotify); - - PlayerApplyEnterMpNotify proto = PlayerApplyEnterMpNotify.newBuilder() - .setSrcPlayerInfo(srcPlayer.getOnlinePlayerInfo()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpNotifyOuterClass.PlayerApplyEnterMpNotify; + +public class PacketPlayerApplyEnterMpNotify extends BasePacket { + + public PacketPlayerApplyEnterMpNotify(Player srcPlayer) { + super(PacketOpcodes.PlayerApplyEnterMpNotify); + + PlayerApplyEnterMpNotify proto = + PlayerApplyEnterMpNotify.newBuilder() + .setSrcPlayerInfo(srcPlayer.getOnlinePlayerInfo()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultNotify.java index e962d5d9c..2b0e9a8c8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultNotify.java @@ -1,36 +1,45 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass; -import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify; - -public class PacketPlayerApplyEnterMpResultNotify extends BasePacket { - - public PacketPlayerApplyEnterMpResultNotify(Player target, boolean isAgreed, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason reason) { - super(PacketOpcodes.PlayerApplyEnterMpResultNotify); - - PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder() - .setTargetUid(target.getUid()) - .setTargetNickname(target.getNickname()) - .setIsAgreed(isAgreed) - .setReason(reason) - .build(); - - this.setData(proto); - } - - public PacketPlayerApplyEnterMpResultNotify(int targetId, String targetName, boolean isAgreed, PlayerApplyEnterMpResultNotify.Reason reason) { - super(PacketOpcodes.PlayerApplyEnterMpResultNotify); - - PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder() - .setTargetUid(targetId) - .setTargetNickname(targetName) - .setIsAgreed(isAgreed) - .setReason(reason) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass; +import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify; + +public class PacketPlayerApplyEnterMpResultNotify extends BasePacket { + + public PacketPlayerApplyEnterMpResultNotify( + Player target, + boolean isAgreed, + PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason reason) { + super(PacketOpcodes.PlayerApplyEnterMpResultNotify); + + PlayerApplyEnterMpResultNotify proto = + PlayerApplyEnterMpResultNotify.newBuilder() + .setTargetUid(target.getUid()) + .setTargetNickname(target.getNickname()) + .setIsAgreed(isAgreed) + .setReason(reason) + .build(); + + this.setData(proto); + } + + public PacketPlayerApplyEnterMpResultNotify( + int targetId, + String targetName, + boolean isAgreed, + PlayerApplyEnterMpResultNotify.Reason reason) { + super(PacketOpcodes.PlayerApplyEnterMpResultNotify); + + PlayerApplyEnterMpResultNotify proto = + PlayerApplyEnterMpResultNotify.newBuilder() + .setTargetUid(targetId) + .setTargetNickname(targetName) + .setIsAgreed(isAgreed) + .setReason(reason) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultRsp.java index 3272540e3..f6a799a20 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpResultRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpResultRspOuterClass.PlayerApplyEnterMpResultRsp; - -public class PacketPlayerApplyEnterMpResultRsp extends BasePacket { - - public PacketPlayerApplyEnterMpResultRsp(int applyUid, boolean isAgreed) { - super(PacketOpcodes.PlayerApplyEnterMpResultRsp); - - PlayerApplyEnterMpResultRsp proto = PlayerApplyEnterMpResultRsp.newBuilder() - .setApplyUid(applyUid) - .setIsAgreed(isAgreed) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpResultRspOuterClass.PlayerApplyEnterMpResultRsp; + +public class PacketPlayerApplyEnterMpResultRsp extends BasePacket { + + public PacketPlayerApplyEnterMpResultRsp(int applyUid, boolean isAgreed) { + super(PacketOpcodes.PlayerApplyEnterMpResultRsp); + + PlayerApplyEnterMpResultRsp proto = + PlayerApplyEnterMpResultRsp.newBuilder() + .setApplyUid(applyUid) + .setIsAgreed(isAgreed) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpRsp.java index 911f72921..6c423425f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerApplyEnterMpRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerApplyEnterMpRspOuterClass.PlayerApplyEnterMpRsp; - -public class PacketPlayerApplyEnterMpRsp extends BasePacket { - - public PacketPlayerApplyEnterMpRsp(int targetUid) { - super(PacketOpcodes.PlayerApplyEnterMpRsp); - - PlayerApplyEnterMpRsp proto = PlayerApplyEnterMpRsp.newBuilder() - .setTargetUid(targetUid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerApplyEnterMpRspOuterClass.PlayerApplyEnterMpRsp; + +public class PacketPlayerApplyEnterMpRsp extends BasePacket { + + public PacketPlayerApplyEnterMpRsp(int targetUid) { + super(PacketOpcodes.PlayerApplyEnterMpRsp); + + PlayerApplyEnterMpRsp proto = + PlayerApplyEnterMpRsp.newBuilder().setTargetUid(targetUid).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatNotify.java index e0705a01c..f257362e1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatNotify.java @@ -1,61 +1,58 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.net.proto.PlayerChatNotifyOuterClass.PlayerChatNotify; - -public class PacketPlayerChatNotify extends BasePacket { - - public PacketPlayerChatNotify(Player sender, int channelId, String message) { - super(PacketOpcodes.PlayerChatNotify); - - ChatInfo info = ChatInfo.newBuilder() - .setTime((int) (System.currentTimeMillis() / 1000)) - .setUid(sender.getUid()) - .setText(message) - .build(); - - PlayerChatNotify proto = PlayerChatNotify.newBuilder() - .setChannelId(channelId) - .setChatInfo(info) - .build(); - - this.setData(proto); - } - - public PacketPlayerChatNotify(Player sender, int channelId, int emote) { - super(PacketOpcodes.PlayerChatNotify); - - ChatInfo info = ChatInfo.newBuilder() - .setTime((int) (System.currentTimeMillis() / 1000)) - .setUid(sender.getUid()) - .setIcon(emote) - .build(); - - PlayerChatNotify proto = PlayerChatNotify.newBuilder() - .setChannelId(channelId) - .setChatInfo(info) - .build(); - - this.setData(proto); - } - - public PacketPlayerChatNotify(Player sender, int channelId, ChatInfo.SystemHint systemHint) { - super(PacketOpcodes.PlayerChatNotify); - - ChatInfo info = ChatInfo.newBuilder() - .setTime((int) (System.currentTimeMillis() / 1000)) - .setUid(sender.getUid()) - .setSystemHint(systemHint) - .build(); - - PlayerChatNotify proto = PlayerChatNotify.newBuilder() - .setChannelId(channelId) - .setChatInfo(info) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.net.proto.PlayerChatNotifyOuterClass.PlayerChatNotify; + +public class PacketPlayerChatNotify extends BasePacket { + + public PacketPlayerChatNotify(Player sender, int channelId, String message) { + super(PacketOpcodes.PlayerChatNotify); + + ChatInfo info = + ChatInfo.newBuilder() + .setTime((int) (System.currentTimeMillis() / 1000)) + .setUid(sender.getUid()) + .setText(message) + .build(); + + PlayerChatNotify proto = + PlayerChatNotify.newBuilder().setChannelId(channelId).setChatInfo(info).build(); + + this.setData(proto); + } + + public PacketPlayerChatNotify(Player sender, int channelId, int emote) { + super(PacketOpcodes.PlayerChatNotify); + + ChatInfo info = + ChatInfo.newBuilder() + .setTime((int) (System.currentTimeMillis() / 1000)) + .setUid(sender.getUid()) + .setIcon(emote) + .build(); + + PlayerChatNotify proto = + PlayerChatNotify.newBuilder().setChannelId(channelId).setChatInfo(info).build(); + + this.setData(proto); + } + + public PacketPlayerChatNotify(Player sender, int channelId, ChatInfo.SystemHint systemHint) { + super(PacketOpcodes.PlayerChatNotify); + + ChatInfo info = + ChatInfo.newBuilder() + .setTime((int) (System.currentTimeMillis() / 1000)) + .setUid(sender.getUid()) + .setSystemHint(systemHint) + .build(); + + PlayerChatNotify proto = + PlayerChatNotify.newBuilder().setChannelId(channelId).setChatInfo(info).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatRsp.java index abf86cac0..f89427fb9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerChatRsp.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerChatRspOuterClass.PlayerChatRsp; - -public class PacketPlayerChatRsp extends BasePacket { - - public PacketPlayerChatRsp() { - super(PacketOpcodes.PlayerChatRsp); - - PlayerChatRsp proto = PlayerChatRsp.newBuilder().build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerChatRspOuterClass.PlayerChatRsp; + +public class PacketPlayerChatRsp extends BasePacket { + + public PacketPlayerChatRsp() { + super(PacketOpcodes.PlayerChatRsp); + + PlayerChatRsp proto = PlayerChatRsp.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCompoundMaterialRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCompoundMaterialRsp.java index 714b5daa4..7c46bc5ef 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCompoundMaterialRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCompoundMaterialRsp.java @@ -1,37 +1,36 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; -import emu.grasscutter.net.proto.PlayerCompoundMaterialRspOuterClass.PlayerCompoundMaterialRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -public class PacketPlayerCompoundMaterialRsp extends BasePacket { - /** - * Builder for successful message. - * - * @param compoundQueueData new compound queue - */ - public PacketPlayerCompoundMaterialRsp(CompoundQueueData compoundQueueData) { - super(PacketOpcodes.PlayerCompoundMaterialRsp); - PlayerCompoundMaterialRsp proto = PlayerCompoundMaterialRsp.newBuilder() - .setCompoundQueueData(compoundQueueData) - .setRetcode(Retcode.RET_SUCC_VALUE) - .build(); - setData(proto); - } - - /** - * Builder for failed message. - * - * @param retcode error code - */ - public PacketPlayerCompoundMaterialRsp(int retcode) { - super(PacketOpcodes.PlayerCompoundMaterialRsp); - PlayerCompoundMaterialRsp proto = PlayerCompoundMaterialRsp.newBuilder() - .setRetcode(retcode) - .build(); - setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CompoundQueueDataOuterClass.CompoundQueueData; +import emu.grasscutter.net.proto.PlayerCompoundMaterialRspOuterClass.PlayerCompoundMaterialRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; + +public class PacketPlayerCompoundMaterialRsp extends BasePacket { + /** + * Builder for successful message. + * + * @param compoundQueueData new compound queue + */ + public PacketPlayerCompoundMaterialRsp(CompoundQueueData compoundQueueData) { + super(PacketOpcodes.PlayerCompoundMaterialRsp); + PlayerCompoundMaterialRsp proto = + PlayerCompoundMaterialRsp.newBuilder() + .setCompoundQueueData(compoundQueueData) + .setRetcode(Retcode.RET_SUCC_VALUE) + .build(); + setData(proto); + } + + /** + * Builder for failed message. + * + * @param retcode error code + */ + public PacketPlayerCompoundMaterialRsp(int retcode) { + super(PacketOpcodes.PlayerCompoundMaterialRsp); + PlayerCompoundMaterialRsp proto = + PlayerCompoundMaterialRsp.newBuilder().setRetcode(retcode).build(); + setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookArgsRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookArgsRsp.java index 684006268..0fdcb5172 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookArgsRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookArgsRsp.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerCookArgsRspOuterClass.PlayerCookArgsRsp; - -public class PacketPlayerCookArgsRsp extends BasePacket { - - public PacketPlayerCookArgsRsp() { - super(PacketOpcodes.PlayerCookArgsRsp); - - PlayerCookArgsRsp proto = PlayerCookArgsRsp.newBuilder() - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerCookArgsRspOuterClass.PlayerCookArgsRsp; + +public class PacketPlayerCookArgsRsp extends BasePacket { + + public PacketPlayerCookArgsRsp() { + super(PacketOpcodes.PlayerCookArgsRsp); + + PlayerCookArgsRsp proto = PlayerCookArgsRsp.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookRsp.java index 64396bf73..32cc5a518 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerCookRsp.java @@ -1,46 +1,39 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.PlayerCookRspOuterClass.PlayerCookRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; - -public class PacketPlayerCookRsp extends BasePacket { - public PacketPlayerCookRsp(Retcode retcode) { - super(PacketOpcodes.PlayerCookRsp); - - PlayerCookRsp proto = PlayerCookRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(proto); - } - - public PacketPlayerCookRsp(List output, int quality, int count, int recipeId, int proficiency) { - super(PacketOpcodes.PlayerCookRsp); - - PlayerCookRsp.Builder proto = PlayerCookRsp.newBuilder() - .setRecipeData( - CookRecipeData.newBuilder() - .setRecipeId(recipeId) - .setProficiency(proficiency) - ) - .setQteQuality(quality) - .setCookCount(count); - - for (var item : output) { - proto.addItemList( - ItemParam.newBuilder() - .setItemId(item.getItemId()) - .setCount(item.getCount()) - ); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CookRecipeDataOuterClass.CookRecipeData; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.PlayerCookRspOuterClass.PlayerCookRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; + +public class PacketPlayerCookRsp extends BasePacket { + public PacketPlayerCookRsp(Retcode retcode) { + super(PacketOpcodes.PlayerCookRsp); + + PlayerCookRsp proto = PlayerCookRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } + + public PacketPlayerCookRsp( + List output, int quality, int count, int recipeId, int proficiency) { + super(PacketOpcodes.PlayerCookRsp); + + PlayerCookRsp.Builder proto = + PlayerCookRsp.newBuilder() + .setRecipeData( + CookRecipeData.newBuilder().setRecipeId(recipeId).setProficiency(proficiency)) + .setQteQuality(quality) + .setCookCount(count); + + for (var item : output) { + proto.addItemList( + ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount())); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerDataNotify.java index d31714cc9..c9275033b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerDataNotify.java @@ -1,26 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerDataNotifyOuterClass.PlayerDataNotify; -import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; - -public class PacketPlayerDataNotify extends BasePacket { - - public PacketPlayerDataNotify(Player player) { - super(PacketOpcodes.PlayerDataNotify, 2); - - PlayerDataNotify.Builder p = PlayerDataNotify.newBuilder() - .setNickName(player.getNickname()) - .setServerTime(System.currentTimeMillis()) - .setIsFirstLoginToday(true) - .setRegionId(player.getRegionId()); - - player.getProperties().forEach((key, value) -> { - p.putPropMap(key, PropValue.newBuilder().setType(key).setIval(value).setVal(value).build()); - }); - - this.setData(p.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerDataNotifyOuterClass.PlayerDataNotify; +import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; + +public class PacketPlayerDataNotify extends BasePacket { + + public PacketPlayerDataNotify(Player player) { + super(PacketOpcodes.PlayerDataNotify, 2); + + PlayerDataNotify.Builder p = + PlayerDataNotify.newBuilder() + .setNickName(player.getNickname()) + .setServerTime(System.currentTimeMillis()) + .setIsFirstLoginToday(true) + .setRegionId(player.getRegionId()); + + player + .getProperties() + .forEach( + (key, value) -> { + p.putPropMap( + key, PropValue.newBuilder().setType(key).setIval(value).setVal(value).build()); + }); + + this.setData(p.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterDungeonRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterDungeonRsp.java index cbf7b4838..4475b550c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterDungeonRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterDungeonRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerEnterDungeonRspOuterClass.PlayerEnterDungeonRsp; - -public class PacketPlayerEnterDungeonRsp extends BasePacket { - - public PacketPlayerEnterDungeonRsp(int pointId, int dungeonId) { - super(PacketOpcodes.PlayerEnterDungeonRsp); - - PlayerEnterDungeonRsp proto = PlayerEnterDungeonRsp.newBuilder() - .setPointId(pointId) - .setDungeonId(dungeonId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerEnterDungeonRspOuterClass.PlayerEnterDungeonRsp; + +public class PacketPlayerEnterDungeonRsp extends BasePacket { + + public PacketPlayerEnterDungeonRsp(int pointId, int dungeonId) { + super(PacketOpcodes.PlayerEnterDungeonRsp); + + PlayerEnterDungeonRsp proto = + PlayerEnterDungeonRsp.newBuilder().setPointId(pointId).setDungeonId(dungeonId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneInfoNotify.java index deb6115b1..9b8db75f6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneInfoNotify.java @@ -1,57 +1,58 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilityControlBlockOuterClass; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.AvatarEnterSceneInfoOuterClass.AvatarEnterSceneInfo; -import emu.grasscutter.net.proto.MPLevelEntityInfoOuterClass.MPLevelEntityInfo; -import emu.grasscutter.net.proto.PlayerEnterSceneInfoNotifyOuterClass.PlayerEnterSceneInfoNotify; -import emu.grasscutter.net.proto.TeamEnterSceneInfoOuterClass.TeamEnterSceneInfo; - -public class PacketPlayerEnterSceneInfoNotify extends BasePacket { - - public PacketPlayerEnterSceneInfoNotify(Player player) { - super(PacketOpcodes.PlayerEnterSceneInfoNotify); - - AbilitySyncStateInfo empty = AbilitySyncStateInfo.newBuilder().build(); - - PlayerEnterSceneInfoNotify.Builder proto = PlayerEnterSceneInfoNotify.newBuilder() - .setCurAvatarEntityId(player.getTeamManager().getCurrentAvatarEntity().getId()) - .setEnterSceneToken(player.getEnterSceneToken()); - - proto.setTeamEnterInfo( - TeamEnterSceneInfo.newBuilder() - .setTeamEntityId(player.getTeamManager().getEntityId()) // 150995833 - .setTeamAbilityInfo(empty) - .setAbilityControlBlock(AbilityControlBlockOuterClass.AbilityControlBlock.newBuilder().build()) - ); - proto.setMpLevelEntityInfo( - MPLevelEntityInfo.newBuilder() - .setEntityId(player.getWorld().getLevelEntityId()) // 184550274 - .setAuthorityPeerId(player.getWorld().getHostPeerId()) - .setAbilityInfo(empty) - ); - - for (EntityAvatar avatarEntity : player.getTeamManager().getActiveTeam()) { - GameItem weapon = avatarEntity.getAvatar().getWeapon(); - long weaponGuid = weapon != null ? weapon.getGuid() : 0; - - AvatarEnterSceneInfo avatarInfo = AvatarEnterSceneInfo.newBuilder() - .setAvatarGuid(avatarEntity.getAvatar().getGuid()) - .setAvatarEntityId(avatarEntity.getId()) - .setWeaponGuid(weaponGuid) - .setWeaponEntityId(avatarEntity.getWeaponEntityId()) - .setAvatarAbilityInfo(empty) - .setWeaponAbilityInfo(empty) - .build(); - - proto.addAvatarEnterInfo(avatarInfo); - } - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilityControlBlockOuterClass; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.AvatarEnterSceneInfoOuterClass.AvatarEnterSceneInfo; +import emu.grasscutter.net.proto.MPLevelEntityInfoOuterClass.MPLevelEntityInfo; +import emu.grasscutter.net.proto.PlayerEnterSceneInfoNotifyOuterClass.PlayerEnterSceneInfoNotify; +import emu.grasscutter.net.proto.TeamEnterSceneInfoOuterClass.TeamEnterSceneInfo; + +public class PacketPlayerEnterSceneInfoNotify extends BasePacket { + + public PacketPlayerEnterSceneInfoNotify(Player player) { + super(PacketOpcodes.PlayerEnterSceneInfoNotify); + + AbilitySyncStateInfo empty = AbilitySyncStateInfo.newBuilder().build(); + + PlayerEnterSceneInfoNotify.Builder proto = + PlayerEnterSceneInfoNotify.newBuilder() + .setCurAvatarEntityId(player.getTeamManager().getCurrentAvatarEntity().getId()) + .setEnterSceneToken(player.getEnterSceneToken()); + + proto.setTeamEnterInfo( + TeamEnterSceneInfo.newBuilder() + .setTeamEntityId(player.getTeamManager().getEntityId()) // 150995833 + .setTeamAbilityInfo(empty) + .setAbilityControlBlock( + AbilityControlBlockOuterClass.AbilityControlBlock.newBuilder().build())); + proto.setMpLevelEntityInfo( + MPLevelEntityInfo.newBuilder() + .setEntityId(player.getWorld().getLevelEntityId()) // 184550274 + .setAuthorityPeerId(player.getWorld().getHostPeerId()) + .setAbilityInfo(empty)); + + for (EntityAvatar avatarEntity : player.getTeamManager().getActiveTeam()) { + GameItem weapon = avatarEntity.getAvatar().getWeapon(); + long weaponGuid = weapon != null ? weapon.getGuid() : 0; + + AvatarEnterSceneInfo avatarInfo = + AvatarEnterSceneInfo.newBuilder() + .setAvatarGuid(avatarEntity.getAvatar().getGuid()) + .setAvatarEntityId(avatarEntity.getId()) + .setWeaponGuid(weaponGuid) + .setWeaponEntityId(avatarEntity.getWeaponEntityId()) + .setAvatarAbilityInfo(empty) + .setWeaponAbilityInfo(empty) + .build(); + + proto.addAvatarEnterInfo(avatarInfo); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java index ba387c186..612386a90 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java @@ -1,73 +1,95 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.game.props.EnterReason; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; -import emu.grasscutter.net.proto.PlayerEnterSceneNotifyOuterClass.PlayerEnterSceneNotify; -import emu.grasscutter.utils.Position; -import emu.grasscutter.utils.Utils; - -public class PacketPlayerEnterSceneNotify extends BasePacket { - - // Login - public PacketPlayerEnterSceneNotify(Player player) { - super(PacketOpcodes.PlayerEnterSceneNotify); - - player.setSceneLoadState(SceneLoadState.LOADING); - player.setEnterSceneToken(Utils.randomRange(1000, 99999)); - - PlayerEnterSceneNotify.Builder proto = PlayerEnterSceneNotify.newBuilder() - .setSceneId(player.getSceneId()) - .setPos(player.getPosition().toProto()) - .setSceneBeginTime(System.currentTimeMillis()) - .setType(EnterType.ENTER_TYPE_SELF) - .setTargetUid(player.getUid()) - .setEnterSceneToken(player.getEnterSceneToken()) - .setWorldLevel(player.getWorldLevel()) - .setEnterReason(EnterReason.Login.getValue()) - .setIsFirstLoginEnterScene(player.isFirstLoginEnterScene()) - .setWorldType(1) - .setSceneTransaction("3-" + player.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402); - - this.setData(proto); - } - - public PacketPlayerEnterSceneNotify(Player player, EnterType type, EnterReason reason, int newScene, Position newPos) { - this(player, player, type, reason, newScene, newPos); - } - - // Teleport or go somewhere - public PacketPlayerEnterSceneNotify(Player player, Player target, EnterType type, EnterReason reason, int newScene, Position newPos) { - super(PacketOpcodes.PlayerEnterSceneNotify); - - // Set previous position - if (!(newScene == 3)) { // Hardcoded for now else weird positions will occur - // Don't update position within same scene or teapot - } else { - // Only used for exiting teapot currently - player.setPrevPos(player.getPosition()); - } - - player.setSceneLoadState(SceneLoadState.LOADING); - player.setEnterSceneToken(Utils.randomRange(1000, 99999)); - - PlayerEnterSceneNotify.Builder proto = PlayerEnterSceneNotify.newBuilder() - .setPrevSceneId(player.getSceneId()) - .setPrevPos(player.getPosition().toProto()) - .setSceneId(newScene) - .setPos(newPos.toProto()) - .setSceneBeginTime(System.currentTimeMillis()) - .setType(type) - .setTargetUid(target.getUid()) - .setEnterSceneToken(player.getEnterSceneToken()) - .setWorldLevel(target.getWorld().getWorldLevel()) - .setEnterReason(reason.getValue()) - .setWorldType(1) - .setSceneTransaction(newScene + "-" + target.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.Player.SceneLoadState; +import emu.grasscutter.game.props.EnterReason; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; +import emu.grasscutter.net.proto.PlayerEnterSceneNotifyOuterClass.PlayerEnterSceneNotify; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; + +public class PacketPlayerEnterSceneNotify extends BasePacket { + + // Login + public PacketPlayerEnterSceneNotify(Player player) { + super(PacketOpcodes.PlayerEnterSceneNotify); + + player.setSceneLoadState(SceneLoadState.LOADING); + player.setEnterSceneToken(Utils.randomRange(1000, 99999)); + + PlayerEnterSceneNotify.Builder proto = + PlayerEnterSceneNotify.newBuilder() + .setSceneId(player.getSceneId()) + .setPos(player.getPosition().toProto()) + .setSceneBeginTime(System.currentTimeMillis()) + .setType(EnterType.ENTER_TYPE_SELF) + .setTargetUid(player.getUid()) + .setEnterSceneToken(player.getEnterSceneToken()) + .setWorldLevel(player.getWorldLevel()) + .setEnterReason(EnterReason.Login.getValue()) + .setIsFirstLoginEnterScene(player.isFirstLoginEnterScene()) + .setWorldType(1) + .setSceneTransaction( + "3-" + + player.getUid() + + "-" + + (int) (System.currentTimeMillis() / 1000) + + "-" + + 18402); + + this.setData(proto); + } + + public PacketPlayerEnterSceneNotify( + Player player, EnterType type, EnterReason reason, int newScene, Position newPos) { + this(player, player, type, reason, newScene, newPos); + } + + // Teleport or go somewhere + public PacketPlayerEnterSceneNotify( + Player player, + Player target, + EnterType type, + EnterReason reason, + int newScene, + Position newPos) { + super(PacketOpcodes.PlayerEnterSceneNotify); + + // Set previous position + if (!(newScene == 3)) { // Hardcoded for now else weird positions will occur + // Don't update position within same scene or teapot + } else { + // Only used for exiting teapot currently + player.setPrevPos(player.getPosition()); + } + + player.setSceneLoadState(SceneLoadState.LOADING); + player.setEnterSceneToken(Utils.randomRange(1000, 99999)); + + PlayerEnterSceneNotify.Builder proto = + PlayerEnterSceneNotify.newBuilder() + .setPrevSceneId(player.getSceneId()) + .setPrevPos(player.getPosition().toProto()) + .setSceneId(newScene) + .setPos(newPos.toProto()) + .setSceneBeginTime(System.currentTimeMillis()) + .setType(type) + .setTargetUid(target.getUid()) + .setEnterSceneToken(player.getEnterSceneToken()) + .setWorldLevel(target.getWorld().getWorldLevel()) + .setEnterReason(reason.getValue()) + .setWorldType(1) + .setSceneTransaction( + newScene + + "-" + + target.getUid() + + "-" + + (int) (System.currentTimeMillis() / 1000) + + "-" + + 18402); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGameTimeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGameTimeNotify.java index 62f8b4576..8dd589ef8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGameTimeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGameTimeNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerGameTimeNotifyOuterClass.PlayerGameTimeNotify; - -public class PacketPlayerGameTimeNotify extends BasePacket { - - public PacketPlayerGameTimeNotify(Player player) { - super(PacketOpcodes.PlayerGameTimeNotify); - - PlayerGameTimeNotify proto = PlayerGameTimeNotify.newBuilder() - .setGameTime(player.getScene().getTime()) - .setUid(player.getUid()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerGameTimeNotifyOuterClass.PlayerGameTimeNotify; + +public class PacketPlayerGameTimeNotify extends BasePacket { + + public PacketPlayerGameTimeNotify(Player player) { + super(PacketOpcodes.PlayerGameTimeNotify); + + PlayerGameTimeNotify proto = + PlayerGameTimeNotify.newBuilder() + .setGameTime(player.getScene().getTime()) + .setUid(player.getUid()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGetForceQuitBanInfoRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGetForceQuitBanInfoRsp.java index c079517a5..49cf83d40 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGetForceQuitBanInfoRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerGetForceQuitBanInfoRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerGetForceQuitBanInfoRspOuterClass.PlayerGetForceQuitBanInfoRsp; - -public class PacketPlayerGetForceQuitBanInfoRsp extends BasePacket { - - public PacketPlayerGetForceQuitBanInfoRsp(int retcode) { - super(PacketOpcodes.PlayerGetForceQuitBanInfoRsp); - - PlayerGetForceQuitBanInfoRsp proto = PlayerGetForceQuitBanInfoRsp.newBuilder() - .setRetcode(retcode) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerGetForceQuitBanInfoRspOuterClass.PlayerGetForceQuitBanInfoRsp; + +public class PacketPlayerGetForceQuitBanInfoRsp extends BasePacket { + + public PacketPlayerGetForceQuitBanInfoRsp(int retcode) { + super(PacketOpcodes.PlayerGetForceQuitBanInfoRsp); + + PlayerGetForceQuitBanInfoRsp proto = + PlayerGetForceQuitBanInfoRsp.newBuilder().setRetcode(retcode).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java index e6e4e96bc..5cacdf836 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java @@ -1,32 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerHomeCompInfoNotifyOuterClass; -import emu.grasscutter.net.proto.PlayerHomeCompInfoOuterClass; - -public class PacketPlayerHomeCompInfoNotify extends BasePacket { - - public PacketPlayerHomeCompInfoNotify(Player player) { - super(PacketOpcodes.PlayerHomeCompInfoNotify); - - if (player.getRealmList() == null) { - // Do not send - return; - } - - PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify proto = PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify.newBuilder() - .setCompInfo( - PlayerHomeCompInfoOuterClass.PlayerHomeCompInfo.newBuilder() - .addAllUnlockedModuleIdList(player.getRealmList()) - .addAllSeenModuleIdList(player.getSeenRealmList()) - .addAllLevelupRewardGotLevelList(player.getHomeRewardedLevels()) - .setFriendEnterHomeOptionValue(player.getHome().getEnterHomeOption()) - .build() - ) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerHomeCompInfoNotifyOuterClass; +import emu.grasscutter.net.proto.PlayerHomeCompInfoOuterClass; + +public class PacketPlayerHomeCompInfoNotify extends BasePacket { + + public PacketPlayerHomeCompInfoNotify(Player player) { + super(PacketOpcodes.PlayerHomeCompInfoNotify); + + if (player.getRealmList() == null) { + // Do not send + return; + } + + PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify proto = + PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify.newBuilder() + .setCompInfo( + PlayerHomeCompInfoOuterClass.PlayerHomeCompInfo.newBuilder() + .addAllUnlockedModuleIdList(player.getRealmList()) + .addAllSeenModuleIdList(player.getSeenRealmList()) + .addAllLevelupRewardGotLevelList(player.getHomeRewardedLevels()) + .setFriendEnterHomeOptionValue(player.getHome().getEnterHomeOption()) + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLevelRewardUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLevelRewardUpdateNotify.java index c245168ba..a05c6c923 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLevelRewardUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLevelRewardUpdateNotify.java @@ -1,22 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerLevelRewardUpdateNotifyOuterClass.PlayerLevelRewardUpdateNotify; - -import java.util.Set; - -public class PacketPlayerLevelRewardUpdateNotify extends BasePacket { - - public PacketPlayerLevelRewardUpdateNotify(Set rewardedLevels) { - super(PacketOpcodes.PlayerLevelRewardUpdateNotify); - - PlayerLevelRewardUpdateNotify.Builder proto = PlayerLevelRewardUpdateNotify.newBuilder(); - - for (Integer level : rewardedLevels) { - proto.addLevelList(level); - } - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerLevelRewardUpdateNotifyOuterClass.PlayerLevelRewardUpdateNotify; +import java.util.Set; + +public class PacketPlayerLevelRewardUpdateNotify extends BasePacket { + + public PacketPlayerLevelRewardUpdateNotify(Set rewardedLevels) { + super(PacketOpcodes.PlayerLevelRewardUpdateNotify); + + PlayerLevelRewardUpdateNotify.Builder proto = PlayerLevelRewardUpdateNotify.newBuilder(); + + for (Integer level : rewardedLevels) { + proto.addLevelList(level); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java index 112d5d996..71a1b363e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java @@ -1,70 +1,74 @@ -package emu.grasscutter.server.packet.send; - -import com.google.protobuf.ByteString; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerLoginRspOuterClass.PlayerLoginRsp; -import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass; -import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.http.dispatch.RegionHandler; -import emu.grasscutter.utils.Crypto; - -import java.util.Objects; - -import static emu.grasscutter.config.Configuration.*; - -public class PacketPlayerLoginRsp extends BasePacket { - - private static QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionCache; - - public PacketPlayerLoginRsp(GameSession session) { - super(PacketOpcodes.PlayerLoginRsp, 1); - - this.setUseDispatchKey(true); - - RegionInfo info; - - if (SERVER.runMode == ServerRunMode.GAME_ONLY) { - if (regionCache == null) { - try { - // todo: we might want to push custom config to client - RegionInfo serverRegion = RegionInfo.newBuilder() - .setGateserverIp(lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress)) - .setGateserverPort(lr(GAME_INFO.accessPort, GAME_INFO.bindPort)) - .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) - .build(); - - regionCache = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.newBuilder().setRegionInfo(serverRegion).build(); - } catch (Exception e) { - Grasscutter.getLogger().error("Error while initializing region cache!", e); - } - } - - info = regionCache.getRegionInfo(); - } else { - info = Objects.requireNonNull(RegionHandler.getCurrentRegion()).getRegionInfo(); - } - - PlayerLoginRsp p = PlayerLoginRsp.newBuilder() - .setIsUseAbilityHash(true) // true - .setAbilityHashCode(1844674) // 1844674 - .setGameBiz("hk4e_global") - .setClientDataVersion(info.getClientDataVersion()) - .setClientSilenceDataVersion(info.getClientSilenceDataVersion()) - .setClientMd5(info.getClientDataMd5()) - .setClientSilenceMd5(info.getClientSilenceDataMd5()) - .setResVersionConfig(info.getResVersionConfig()) - .setClientVersionSuffix(info.getClientVersionSuffix()) - .setClientSilenceVersionSuffix(info.getClientSilenceVersionSuffix()) - .setIsScOpen(false) - //.setScInfo(ByteString.copyFrom(new byte[] {})) - .setRegisterCps("mihoyo") - .setCountryCode("US") - .build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import static emu.grasscutter.config.Configuration.*; + +import com.google.protobuf.ByteString; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerLoginRspOuterClass.PlayerLoginRsp; +import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass; +import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.http.dispatch.RegionHandler; +import emu.grasscutter.utils.Crypto; +import java.util.Objects; + +public class PacketPlayerLoginRsp extends BasePacket { + + private static QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionCache; + + public PacketPlayerLoginRsp(GameSession session) { + super(PacketOpcodes.PlayerLoginRsp, 1); + + this.setUseDispatchKey(true); + + RegionInfo info; + + if (SERVER.runMode == ServerRunMode.GAME_ONLY) { + if (regionCache == null) { + try { + // todo: we might want to push custom config to client + RegionInfo serverRegion = + RegionInfo.newBuilder() + .setGateserverIp(lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress)) + .setGateserverPort(lr(GAME_INFO.accessPort, GAME_INFO.bindPort)) + .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .build(); + + regionCache = + QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.newBuilder() + .setRegionInfo(serverRegion) + .build(); + } catch (Exception e) { + Grasscutter.getLogger().error("Error while initializing region cache!", e); + } + } + + info = regionCache.getRegionInfo(); + } else { + info = Objects.requireNonNull(RegionHandler.getCurrentRegion()).getRegionInfo(); + } + + PlayerLoginRsp p = + PlayerLoginRsp.newBuilder() + .setIsUseAbilityHash(true) // true + .setAbilityHashCode(1844674) // 1844674 + .setGameBiz("hk4e_global") + .setClientDataVersion(info.getClientDataVersion()) + .setClientSilenceDataVersion(info.getClientSilenceDataVersion()) + .setClientMd5(info.getClientDataMd5()) + .setClientSilenceMd5(info.getClientSilenceDataMd5()) + .setResVersionConfig(info.getResVersionConfig()) + .setClientVersionSuffix(info.getClientVersionSuffix()) + .setClientSilenceVersionSuffix(info.getClientSilenceVersionSuffix()) + .setIsScOpen(false) + // .setScInfo(ByteString.copyFrom(new byte[] {})) + .setRegisterCps("mihoyo") + .setCountryCode("US") + .build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeNotify.java index 34043e3d4..f83d79c18 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeNotify.java @@ -1,23 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerPropChangeNotifyOuterClass.PlayerPropChangeNotify; - -public class PacketPlayerPropChangeNotify extends BasePacket { - - public PacketPlayerPropChangeNotify(Player player, PlayerProperty prop, int delta) { - super(PacketOpcodes.PlayerPropChangeNotify); - - this.buildHeader(0); - - PlayerPropChangeNotify proto = PlayerPropChangeNotify.newBuilder() - .setPropType(prop.getId()) - .setPropDelta(delta) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerPropChangeNotifyOuterClass.PlayerPropChangeNotify; + +public class PacketPlayerPropChangeNotify extends BasePacket { + + public PacketPlayerPropChangeNotify(Player player, PlayerProperty prop, int delta) { + super(PacketOpcodes.PlayerPropChangeNotify); + + this.buildHeader(0); + + PlayerPropChangeNotify proto = + PlayerPropChangeNotify.newBuilder().setPropType(prop.getId()).setPropDelta(delta).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeReasonNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeReasonNotify.java index 9d078b38f..705471797 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeReasonNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropChangeReasonNotify.java @@ -1,26 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerPropChangeReasonNotifyOuterClass.PlayerPropChangeReasonNotify; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; - -public class PacketPlayerPropChangeReasonNotify extends BasePacket { - - public PacketPlayerPropChangeReasonNotify(Player player, PlayerProperty prop, int oldValue, int newValue, PropChangeReason changeReason) { - super(PacketOpcodes.PlayerPropChangeReasonNotify); - - this.buildHeader(0); - - PlayerPropChangeReasonNotify proto = PlayerPropChangeReasonNotify.newBuilder() - .setPropType(prop.getId()) - .setReason(changeReason) - .setOldValue(oldValue) - .setCurValue(newValue) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerPropChangeReasonNotifyOuterClass.PlayerPropChangeReasonNotify; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; + +public class PacketPlayerPropChangeReasonNotify extends BasePacket { + + public PacketPlayerPropChangeReasonNotify( + Player player, + PlayerProperty prop, + int oldValue, + int newValue, + PropChangeReason changeReason) { + super(PacketOpcodes.PlayerPropChangeReasonNotify); + + this.buildHeader(0); + + PlayerPropChangeReasonNotify proto = + PlayerPropChangeReasonNotify.newBuilder() + .setPropType(prop.getId()) + .setReason(changeReason) + .setOldValue(oldValue) + .setCurValue(newValue) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropNotify.java index aff67639f..01d4b6da6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerPropNotify.java @@ -1,23 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerPropNotifyOuterClass.PlayerPropNotify; -import emu.grasscutter.utils.ProtoHelper; - -public class PacketPlayerPropNotify extends BasePacket { - - public PacketPlayerPropNotify(Player player, PlayerProperty prop) { - super(PacketOpcodes.PlayerPropNotify); - - this.buildHeader(0); - - PlayerPropNotify proto = PlayerPropNotify.newBuilder() - .putPropMap(prop.getId(), ProtoHelper.newPropValue(prop, player.getProperty(prop))) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerPropNotifyOuterClass.PlayerPropNotify; +import emu.grasscutter.utils.ProtoHelper; + +public class PacketPlayerPropNotify extends BasePacket { + + public PacketPlayerPropNotify(Player player, PlayerProperty prop) { + super(PacketOpcodes.PlayerPropNotify); + + this.buildHeader(0); + + PlayerPropNotify proto = + PlayerPropNotify.newBuilder() + .putPropMap(prop.getId(), ProtoHelper.newPropValue(prop, player.getProperty(prop))) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerSetPauseRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerSetPauseRsp.java index 844c1496e..fdf37f696 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerSetPauseRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerSetPauseRsp.java @@ -1,13 +1,13 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketPlayerSetPauseRsp extends BasePacket { - - public PacketPlayerSetPauseRsp(int clientSequence) { - super(PacketOpcodes.PlayerSetPauseRsp); - - this.buildHeader(clientSequence); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketPlayerSetPauseRsp extends BasePacket { + + public PacketPlayerSetPauseRsp(int clientSequence) { + super(PacketOpcodes.PlayerSetPauseRsp); + + this.buildHeader(clientSequence); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java index ba02b8a13..1b357aa0a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java @@ -1,31 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemOuterClass.Item; -import emu.grasscutter.net.proto.PlayerStoreNotifyOuterClass.PlayerStoreNotify; -import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -public class PacketPlayerStoreNotify extends BasePacket { - - public PacketPlayerStoreNotify(Player player) { - super(PacketOpcodes.PlayerStoreNotify); - - this.buildHeader(2); - - PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK) - .setWeightLimit(GAME_OPTIONS.inventoryLimits.all); - - for (GameItem item : player.getInventory()) { - Item itemProto = item.toProto(); - p.addItemList(itemProto); - } - - this.setData(p.build()); - } -} +package emu.grasscutter.server.packet.send; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemOuterClass.Item; +import emu.grasscutter.net.proto.PlayerStoreNotifyOuterClass.PlayerStoreNotify; +import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; + +public class PacketPlayerStoreNotify extends BasePacket { + + public PacketPlayerStoreNotify(Player player) { + super(PacketOpcodes.PlayerStoreNotify); + + this.buildHeader(2); + + PlayerStoreNotify.Builder p = + PlayerStoreNotify.newBuilder() + .setStoreType(StoreType.STORE_TYPE_PACK) + .setWeightLimit(GAME_OPTIONS.inventoryLimits.all); + + for (GameItem item : player.getInventory()) { + Item itemProto = item.toProto(); + p.addItemList(itemProto); + } + + this.setData(p.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerTimeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerTimeNotify.java index 650fe017c..370a48838 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerTimeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerTimeNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerTimeNotifyOuterClass.PlayerTimeNotify; - -public class PacketPlayerTimeNotify extends BasePacket { - - public PacketPlayerTimeNotify(Player player) { - super(PacketOpcodes.PlayerTimeNotify); - - PlayerTimeNotify proto = PlayerTimeNotify.newBuilder() - .setIsPaused(player.isPaused()) - .setPlayerTime(player.getClientTime()) - .setServerTime(System.currentTimeMillis()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerTimeNotifyOuterClass.PlayerTimeNotify; + +public class PacketPlayerTimeNotify extends BasePacket { + + public PacketPlayerTimeNotify(Player player) { + super(PacketOpcodes.PlayerTimeNotify); + + PlayerTimeNotify proto = + PlayerTimeNotify.newBuilder() + .setIsPaused(player.isPaused()) + .setPlayerTime(player.getClientTime()) + .setServerTime(System.currentTimeMillis()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java index ce5aed216..0e32a0a01 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java @@ -1,85 +1,62 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; -import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.PlayerWorldSceneInfo; - -import java.util.stream.IntStream; - -public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { - - public PacketPlayerWorldSceneInfoListNotify() { - super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later - - PlayerWorldSceneInfoListNotify.Builder proto = PlayerWorldSceneInfoListNotify.newBuilder() - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(1) - .setIsLocked(false) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(3) - .setIsLocked(false) - .addSceneTagIdList(102) // Jade chamber - .addSceneTagIdList(113) - .addSceneTagIdList(117) - - // Vanarana (Sumeru tree) - .addSceneTagIdList(1093) // Vana_real - // .addSceneTagIdList(1094) // Vana_dream - // .addSceneTagIdList(1095) // Vana_first - // .addSceneTagIdList(1096) // Vana_festival - - // 3.1 event - .addSceneTagIdList(152) - .addSceneTagIdList(153) - - // Pyramid - .addSceneTagIdList(1164) // Arena (XMSM_CWLTop) - .addSceneTagIdList(1166) // Pyramid (CWL_Trans_02) - - // Brute force - //.addAllSceneTagIdList(IntStream.range(1150, 1250).boxed().toList()) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(4) - .setIsLocked(false) - .addSceneTagIdList(106) - .addSceneTagIdList(109) - .addSceneTagIdList(117) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(5) - .setIsLocked(false) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(6) - .setIsLocked(false) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(7) - .setIsLocked(false) - .build() - ) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(9) - .setIsLocked(false) - .addAllSceneTagIdList(IntStream.range(0, 3000).boxed().toList()) - .build() - ); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; +import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.PlayerWorldSceneInfo; +import java.util.stream.IntStream; + +public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { + + public PacketPlayerWorldSceneInfoListNotify() { + super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later + + PlayerWorldSceneInfoListNotify.Builder proto = + PlayerWorldSceneInfoListNotify.newBuilder() + .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(1).setIsLocked(false).build()) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(3) + .setIsLocked(false) + .addSceneTagIdList(102) // Jade chamber + .addSceneTagIdList(113) + .addSceneTagIdList(117) + + // Vanarana (Sumeru tree) + .addSceneTagIdList(1093) // Vana_real + // .addSceneTagIdList(1094) // Vana_dream + // .addSceneTagIdList(1095) // Vana_first + // .addSceneTagIdList(1096) // Vana_festival + + // 3.1 event + .addSceneTagIdList(152) + .addSceneTagIdList(153) + + // Pyramid + .addSceneTagIdList(1164) // Arena (XMSM_CWLTop) + .addSceneTagIdList(1166) // Pyramid (CWL_Trans_02) + + // Brute force + // .addAllSceneTagIdList(IntStream.range(1150, 1250).boxed().toList()) + .build()) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(4) + .setIsLocked(false) + .addSceneTagIdList(106) + .addSceneTagIdList(109) + .addSceneTagIdList(117) + .build()) + .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(5).setIsLocked(false).build()) + .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(6).setIsLocked(false).build()) + .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(7).setIsLocked(false).build()) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(9) + .setIsLocked(false) + .addAllSceneTagIdList(IntStream.range(0, 3000).boxed().toList()) + .build()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPostEnterSceneRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPostEnterSceneRsp.java index d220c6480..c1485653d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPostEnterSceneRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPostEnterSceneRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PostEnterSceneRspOuterClass.PostEnterSceneRsp; - -public class PacketPostEnterSceneRsp extends BasePacket { - - public PacketPostEnterSceneRsp(Player player) { - super(PacketOpcodes.PostEnterSceneRsp); - - PostEnterSceneRsp p = PostEnterSceneRsp.newBuilder() - .setEnterSceneToken(player.getEnterSceneToken()) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PostEnterSceneRspOuterClass.PostEnterSceneRsp; + +public class PacketPostEnterSceneRsp extends BasePacket { + + public PacketPostEnterSceneRsp(Player player) { + super(PacketOpcodes.PostEnterSceneRsp); + + PostEnterSceneRsp p = + PostEnterSceneRsp.newBuilder().setEnterSceneToken(player.getEnterSceneToken()).build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPrivateChatNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPrivateChatNotify.java index 1f50d48f9..384c22583 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPrivateChatNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPrivateChatNotify.java @@ -1,50 +1,48 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.net.proto.PrivateChatNotifyOuterClass.PrivateChatNotify; - -public class PacketPrivateChatNotify extends BasePacket { - private final ChatInfo info; - - public PacketPrivateChatNotify(int senderId, int recvId, String message) { - super(PacketOpcodes.PrivateChatNotify); - - ChatInfo info = ChatInfo.newBuilder() - .setTime((int) (System.currentTimeMillis() / 1000)) - .setUid(senderId) - .setToUid(recvId) - .setText(message) - .build(); - this.info = info; - - PrivateChatNotify proto = PrivateChatNotify.newBuilder() - .setChatInfo(info) - .build(); - - this.setData(proto); - } - - public PacketPrivateChatNotify(int senderId, int recvId, int emote) { - super(PacketOpcodes.PrivateChatNotify); - - ChatInfo info = ChatInfo.newBuilder() - .setTime((int) (System.currentTimeMillis() / 1000)) - .setUid(senderId) - .setToUid(recvId) - .setIcon(emote) - .build(); - this.info = info; - - PrivateChatNotify proto = PrivateChatNotify.newBuilder() - .setChatInfo(info) - .build(); - - this.setData(proto); - } - - public ChatInfo getChatInfo() { - return this.info; - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.net.proto.PrivateChatNotifyOuterClass.PrivateChatNotify; + +public class PacketPrivateChatNotify extends BasePacket { + private final ChatInfo info; + + public PacketPrivateChatNotify(int senderId, int recvId, String message) { + super(PacketOpcodes.PrivateChatNotify); + + ChatInfo info = + ChatInfo.newBuilder() + .setTime((int) (System.currentTimeMillis() / 1000)) + .setUid(senderId) + .setToUid(recvId) + .setText(message) + .build(); + this.info = info; + + PrivateChatNotify proto = PrivateChatNotify.newBuilder().setChatInfo(info).build(); + + this.setData(proto); + } + + public PacketPrivateChatNotify(int senderId, int recvId, int emote) { + super(PacketOpcodes.PrivateChatNotify); + + ChatInfo info = + ChatInfo.newBuilder() + .setTime((int) (System.currentTimeMillis() / 1000)) + .setUid(senderId) + .setToUid(recvId) + .setIcon(emote) + .build(); + this.info = info; + + PrivateChatNotify proto = PrivateChatNotify.newBuilder().setChatInfo(info).build(); + + this.setData(proto); + } + + public ChatInfo getChatInfo() { + return this.info; + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillChangeNotify.java index 7b5cc8dfc..17b0a67a9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillChangeNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ProudSkillChangeNotifyOuterClass.ProudSkillChangeNotify; - -public class PacketProudSkillChangeNotify extends BasePacket { - - public PacketProudSkillChangeNotify(Avatar avatar) { - super(PacketOpcodes.ProudSkillChangeNotify); - - ProudSkillChangeNotify proto = ProudSkillChangeNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setEntityId(avatar.getEntityId()) - .setSkillDepotId(avatar.getSkillDepotId()) - .addAllProudSkillList(avatar.getProudSkillList()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ProudSkillChangeNotifyOuterClass.ProudSkillChangeNotify; + +public class PacketProudSkillChangeNotify extends BasePacket { + + public PacketProudSkillChangeNotify(Avatar avatar) { + super(PacketOpcodes.ProudSkillChangeNotify); + + ProudSkillChangeNotify proto = + ProudSkillChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEntityId(avatar.getEntityId()) + .setSkillDepotId(avatar.getSkillDepotId()) + .addAllProudSkillList(avatar.getProudSkillList()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillExtraLevelNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillExtraLevelNotify.java index 3dd739f1a..ebe553565 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillExtraLevelNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketProudSkillExtraLevelNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ProudSkillExtraLevelNotifyOuterClass.ProudSkillExtraLevelNotify; - -public class PacketProudSkillExtraLevelNotify extends BasePacket { - - public PacketProudSkillExtraLevelNotify(Avatar avatar, int talentIndex) { - super(PacketOpcodes.ProudSkillExtraLevelNotify); - - ProudSkillExtraLevelNotify proto = ProudSkillExtraLevelNotify.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setTalentType(3) // Talent type = 3 - .setTalentIndex(talentIndex) - .setExtraLevel(3) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ProudSkillExtraLevelNotifyOuterClass.ProudSkillExtraLevelNotify; + +public class PacketProudSkillExtraLevelNotify extends BasePacket { + + public PacketProudSkillExtraLevelNotify(Avatar avatar, int talentIndex) { + super(PacketOpcodes.ProudSkillExtraLevelNotify); + + ProudSkillExtraLevelNotify proto = + ProudSkillExtraLevelNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setTalentType(3) // Talent type = 3 + .setTalentIndex(talentIndex) + .setExtraLevel(3) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPullPrivateChatRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPullPrivateChatRsp.java index f93899c10..a716c98eb 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPullPrivateChatRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPullPrivateChatRsp.java @@ -1,28 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.net.proto.PullPrivateChatRspOuterClass.PullPrivateChatRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; - -public class PacketPullPrivateChatRsp extends BasePacket { - - public PacketPullPrivateChatRsp(List history) { - super(PacketOpcodes.PullPrivateChatRsp); - - PullPrivateChatRsp.Builder builder = PullPrivateChatRsp.newBuilder(); - - if (history == null) { - builder.setRetcode(Retcode.RET_FAIL_VALUE); - } else { - for (var info : history) { - builder.addChatInfo(info); - } - } - - this.setData(builder.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.net.proto.PullPrivateChatRspOuterClass.PullPrivateChatRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; + +public class PacketPullPrivateChatRsp extends BasePacket { + + public PacketPullPrivateChatRsp(List history) { + super(PacketOpcodes.PullPrivateChatRsp); + + PullPrivateChatRsp.Builder builder = PullPrivateChatRsp.newBuilder(); + + if (history == null) { + builder.setRetcode(Retcode.RET_FAIL_VALUE); + } else { + for (var info : history) { + builder.addChatInfo(info); + } + } + + this.setData(builder.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java index a56bb2371..af3d091df 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; -import emu.grasscutter.net.proto.PullRecentChatRspOuterClass.PullRecentChatRsp; - -import java.util.List; - -public class PacketPullRecentChatRsp extends BasePacket { - public PacketPullRecentChatRsp(List messages) { - super(PacketOpcodes.PullRecentChatRsp); - - PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder() - .addAllChatInfo(messages); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; +import emu.grasscutter.net.proto.PullRecentChatRspOuterClass.PullRecentChatRsp; +import java.util.List; + +public class PacketPullRecentChatRsp extends BasePacket { + public PacketPullRecentChatRsp(List messages) { + super(PacketOpcodes.PullRecentChatRsp); + + PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder().addAllChatInfo(messages); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java index eb6787afe..4afa53890 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumRspOuterClass.QueryCodexMonsterBeKilledNumRsp; - -import java.util.List; - -public class PacketQueryCodexMonsterBeKilledNumRsp extends BasePacket { - - public PacketQueryCodexMonsterBeKilledNumRsp(Player player, List codexList) { - super(PacketOpcodes.QueryCodexMonsterBeKilledNumRsp); - QueryCodexMonsterBeKilledNumRsp.Builder proto = QueryCodexMonsterBeKilledNumRsp.newBuilder(); - - codexList.forEach(animal -> { - if (player.getCodex().getUnlockedAnimal().containsKey(animal)) { - proto.addCodexIdList(animal) - .addBeKilledNumList(player.getCodex().getUnlockedAnimal().get(animal)) - .addBeCapturedNumList(0); - } - }); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumRspOuterClass.QueryCodexMonsterBeKilledNumRsp; +import java.util.List; + +public class PacketQueryCodexMonsterBeKilledNumRsp extends BasePacket { + + public PacketQueryCodexMonsterBeKilledNumRsp(Player player, List codexList) { + super(PacketOpcodes.QueryCodexMonsterBeKilledNumRsp); + QueryCodexMonsterBeKilledNumRsp.Builder proto = QueryCodexMonsterBeKilledNumRsp.newBuilder(); + + codexList.forEach( + animal -> { + if (player.getCodex().getUnlockedAnimal().containsKey(animal)) { + proto + .addCodexIdList(animal) + .addBeKilledNumList(player.getCodex().getUnlockedAnimal().get(animal)) + .addBeCapturedNumList(0); + } + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQueryPathRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryPathRsp.java index 688df460f..6545eb5a5 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQueryPathRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryPathRsp.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PathStatusTypeOuterClass; -import emu.grasscutter.net.proto.QueryPathReqOuterClass; -import emu.grasscutter.net.proto.QueryPathRspOuterClass; - - -public class PacketQueryPathRsp extends BasePacket { - - public PacketQueryPathRsp(QueryPathReqOuterClass.QueryPathReq req) { - super(PacketOpcodes.QueryPathRsp); - - var proto = QueryPathRspOuterClass.QueryPathRsp.newBuilder(); - - proto.addCorners(req.getSourcePos()) - .addCorners(req.getDestinationPos(0)) - .setQueryId(req.getQueryId()) - .setQueryStatus(PathStatusTypeOuterClass.PathStatusType.PATH_STATUS_TYPE_SUCC); - //.setQueryStatus(QueryPathRspOuterClass.QueryPathRsp.PathStatusType.PATH_STATUS_TYPE_SUCC); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PathStatusTypeOuterClass; +import emu.grasscutter.net.proto.QueryPathReqOuterClass; +import emu.grasscutter.net.proto.QueryPathRspOuterClass; + +public class PacketQueryPathRsp extends BasePacket { + + public PacketQueryPathRsp(QueryPathReqOuterClass.QueryPathReq req) { + super(PacketOpcodes.QueryPathRsp); + + var proto = QueryPathRspOuterClass.QueryPathRsp.newBuilder(); + + proto + .addCorners(req.getSourcePos()) + .addCorners(req.getDestinationPos(0)) + .setQueryId(req.getQueryId()) + .setQueryStatus(PathStatusTypeOuterClass.PathStatusType.PATH_STATUS_TYPE_SUCC); + // .setQueryStatus(QueryPathRspOuterClass.QueryPathRsp.PathStatusType.PATH_STATUS_TYPE_SUCC); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java index 380a3a789..75332ec6d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java @@ -1,24 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.quest.enums.QuestState; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuestListNotifyOuterClass.QuestListNotify; - -public class PacketQuestListNotify extends BasePacket { - - public PacketQuestListNotify(Player player) { - super(PacketOpcodes.QuestListNotify, true); - - QuestListNotify.Builder proto = QuestListNotify.newBuilder(); - - player.getQuestManager().forEachQuest(quest -> { - if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) { - proto.addQuestList(quest.toProto()); - } - }); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListNotifyOuterClass.QuestListNotify; + +public class PacketQuestListNotify extends BasePacket { + + public PacketQuestListNotify(Player player) { + super(PacketOpcodes.QuestListNotify, true); + + QuestListNotify.Builder proto = QuestListNotify.newBuilder(); + + player + .getQuestManager() + .forEachQuest( + quest -> { + if (quest.getState() != QuestState.QUEST_STATE_UNSTARTED) { + proto.addQuestList(quest.toProto()); + } + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java index 7e820c574..f08ebe6f6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java @@ -1,32 +1,30 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify; - -import java.util.List; - -public class PacketQuestListUpdateNotify extends BasePacket { - - public PacketQuestListUpdateNotify(GameQuest quest) { - super(PacketOpcodes.QuestListUpdateNotify); - - QuestListUpdateNotify proto = QuestListUpdateNotify.newBuilder() - .addQuestList(quest.toProto()) - .build(); - - this.setData(proto); - } - - public PacketQuestListUpdateNotify(List quests) { - super(PacketOpcodes.QuestListUpdateNotify); - var proto = QuestListUpdateNotify.newBuilder(); - for (GameQuest quest : quests) { - proto.addQuestList(quest.toProto()); - } - proto.build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify; +import java.util.List; + +public class PacketQuestListUpdateNotify extends BasePacket { + + public PacketQuestListUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestListUpdateNotify); + + QuestListUpdateNotify proto = + QuestListUpdateNotify.newBuilder().addQuestList(quest.toProto()).build(); + + this.setData(proto); + } + + public PacketQuestListUpdateNotify(List quests) { + super(PacketOpcodes.QuestListUpdateNotify); + var proto = QuestListUpdateNotify.newBuilder(); + for (GameQuest quest : quests) { + proto.addQuestList(quest.toProto()); + } + proto.build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java index 85856e8d7..89e5c54c1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java @@ -1,29 +1,30 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.quest.GameQuest; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuestProgressUpdateNotifyOuterClass.QuestProgressUpdateNotify; - -public class PacketQuestProgressUpdateNotify extends BasePacket { - - public PacketQuestProgressUpdateNotify(GameQuest quest) { - super(PacketOpcodes.QuestProgressUpdateNotify); - - QuestProgressUpdateNotify.Builder proto = QuestProgressUpdateNotify.newBuilder().setQuestId(quest.getSubQuestId()); - - if (quest.getFinishProgressList() != null) { - for (int i : quest.getFinishProgressList()) { - proto.addFinishProgressList(i); - } - } - - if (quest.getFailProgressList() != null) { - for (int i : quest.getFailProgressList()) { - proto.addFailProgressList(i); - } - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestProgressUpdateNotifyOuterClass.QuestProgressUpdateNotify; + +public class PacketQuestProgressUpdateNotify extends BasePacket { + + public PacketQuestProgressUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestProgressUpdateNotify); + + QuestProgressUpdateNotify.Builder proto = + QuestProgressUpdateNotify.newBuilder().setQuestId(quest.getSubQuestId()); + + if (quest.getFinishProgressList() != null) { + for (int i : quest.getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (quest.getFailProgressList() != null) { + for (int i : quest.getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestUpdateQuestVarRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestUpdateQuestVarRsp.java index fc788ebed..3324f5149 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestUpdateQuestVarRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestUpdateQuestVarRsp.java @@ -1,18 +1,19 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.QuestUpdateQuestVarRspOuterClass; - -@Opcodes(PacketOpcodes.QuestUpdateQuestVarReq) -public class PacketQuestUpdateQuestVarRsp extends BasePacket { - - - public PacketQuestUpdateQuestVarRsp(int questId) { - super(PacketOpcodes.QuestUpdateQuestVarRsp); - var rsp = QuestUpdateQuestVarRspOuterClass.QuestUpdateQuestVarRsp.newBuilder() - .setQuestId(questId).build(); - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestUpdateQuestVarRspOuterClass; + +@Opcodes(PacketOpcodes.QuestUpdateQuestVarReq) +public class PacketQuestUpdateQuestVarRsp extends BasePacket { + + public PacketQuestUpdateQuestVarRsp(int questId) { + super(PacketOpcodes.QuestUpdateQuestVarRsp); + var rsp = + QuestUpdateQuestVarRspOuterClass.QuestUpdateQuestVarRsp.newBuilder() + .setQuestId(questId) + .build(); + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryDecomposeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryDecomposeRsp.java index 66a1c7c6d..285e73361 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryDecomposeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryDecomposeRsp.java @@ -1,30 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ReliquaryDecomposeRspOuterClass.ReliquaryDecomposeRsp; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; - -import java.util.List; - -public class PacketReliquaryDecomposeRsp extends BasePacket { - public PacketReliquaryDecomposeRsp(Retcode retcode) { - super(PacketOpcodes.ReliquaryDecomposeRsp); - - ReliquaryDecomposeRsp proto = ReliquaryDecomposeRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(proto); - } - - public PacketReliquaryDecomposeRsp(List output) { - super(PacketOpcodes.ReliquaryDecomposeRsp); - - ReliquaryDecomposeRsp proto = ReliquaryDecomposeRsp.newBuilder() - .addAllGuidList(output) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ReliquaryDecomposeRspOuterClass.ReliquaryDecomposeRsp; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import java.util.List; + +public class PacketReliquaryDecomposeRsp extends BasePacket { + public PacketReliquaryDecomposeRsp(Retcode retcode) { + super(PacketOpcodes.ReliquaryDecomposeRsp); + + ReliquaryDecomposeRsp proto = + ReliquaryDecomposeRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } + + public PacketReliquaryDecomposeRsp(List output) { + super(PacketOpcodes.ReliquaryDecomposeRsp); + + ReliquaryDecomposeRsp proto = ReliquaryDecomposeRsp.newBuilder().addAllGuidList(output).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryUpgradeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryUpgradeRsp.java index 266cb9b2b..42690c1a5 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryUpgradeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketReliquaryUpgradeRsp.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ReliquaryUpgradeRspOuterClass.ReliquaryUpgradeRsp; - -import java.util.List; - -public class PacketReliquaryUpgradeRsp extends BasePacket { - - public PacketReliquaryUpgradeRsp(GameItem relic, int rate, int oldLevel, List oldAppendPropIdList) { - super(PacketOpcodes.ReliquaryUpgradeRsp); - - ReliquaryUpgradeRsp proto = ReliquaryUpgradeRsp.newBuilder() - .setTargetReliquaryGuid(relic.getGuid()) - .setOldLevel(oldLevel) - .setCurLevel(relic.getLevel()) - .setPowerUpRate(rate) - .addAllOldAppendPropList(oldAppendPropIdList) - .addAllCurAppendPropList(relic.getAppendPropIdList()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ReliquaryUpgradeRspOuterClass.ReliquaryUpgradeRsp; +import java.util.List; + +public class PacketReliquaryUpgradeRsp extends BasePacket { + + public PacketReliquaryUpgradeRsp( + GameItem relic, int rate, int oldLevel, List oldAppendPropIdList) { + super(PacketOpcodes.ReliquaryUpgradeRsp); + + ReliquaryUpgradeRsp proto = + ReliquaryUpgradeRsp.newBuilder() + .setTargetReliquaryGuid(relic.getGuid()) + .setOldLevel(oldLevel) + .setCurLevel(relic.getLevel()) + .setPowerUpRate(rate) + .addAllOldAppendPropList(oldAppendPropIdList) + .addAllCurAppendPropList(relic.getAppendPropIdList()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketResinChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketResinChangeNotify.java index 8387edb7d..e58371f80 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketResinChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketResinChangeNotify.java @@ -1,23 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ResinChangeNotifyOuterClass.ResinChangeNotify; - -public class PacketResinChangeNotify extends BasePacket { - - public PacketResinChangeNotify(Player player) { - super(PacketOpcodes.ResinChangeNotify); - - ResinChangeNotify proto = ResinChangeNotify.newBuilder() - .setCurValue(player.getProperty(PlayerProperty.PROP_PLAYER_RESIN)) - .setNextAddTimestamp(player.getNextResinRefresh()) - .build(); - - // ToDo: Add ability to buy resin with primogems, has to be included here. - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ResinChangeNotifyOuterClass.ResinChangeNotify; + +public class PacketResinChangeNotify extends BasePacket { + + public PacketResinChangeNotify(Player player) { + super(PacketOpcodes.ResinChangeNotify); + + ResinChangeNotify proto = + ResinChangeNotify.newBuilder() + .setCurValue(player.getProperty(PlayerProperty.PROP_PLAYER_RESIN)) + .setNextAddTimestamp(player.getNextResinRefresh()) + .build(); + + // ToDo: Add ability to buy resin with primogems, has to be included here. + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaUnlockNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaUnlockNotify.java index 0aa51ce0e..d42b2f324 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaUnlockNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaUnlockNotify.java @@ -1,27 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneAreaUnlockNotifyOuterClass.SceneAreaUnlockNotify; - -public class PacketSceneAreaUnlockNotify extends BasePacket { - public PacketSceneAreaUnlockNotify(int sceneId, int areaId) { - super(PacketOpcodes.SceneAreaUnlockNotify); - - SceneAreaUnlockNotify.Builder p = SceneAreaUnlockNotify.newBuilder() - .setSceneId(sceneId) - .addAreaList(areaId); - - this.setData(p); - } - - public PacketSceneAreaUnlockNotify(int sceneId, Iterable areaIds) { - super(PacketOpcodes.SceneAreaUnlockNotify); - - SceneAreaUnlockNotify.Builder p = SceneAreaUnlockNotify.newBuilder() - .setSceneId(sceneId) - .addAllAreaList(areaIds); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneAreaUnlockNotifyOuterClass.SceneAreaUnlockNotify; + +public class PacketSceneAreaUnlockNotify extends BasePacket { + public PacketSceneAreaUnlockNotify(int sceneId, int areaId) { + super(PacketOpcodes.SceneAreaUnlockNotify); + + SceneAreaUnlockNotify.Builder p = + SceneAreaUnlockNotify.newBuilder().setSceneId(sceneId).addAreaList(areaId); + + this.setData(p); + } + + public PacketSceneAreaUnlockNotify(int sceneId, Iterable areaIds) { + super(PacketOpcodes.SceneAreaUnlockNotify); + + SceneAreaUnlockNotify.Builder p = + SceneAreaUnlockNotify.newBuilder().setSceneId(sceneId).addAllAreaList(areaIds); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java index 03c2ead20..9202c05e8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneAreaWeatherNotifyOuterClass.SceneAreaWeatherNotify; - -public class PacketSceneAreaWeatherNotify extends BasePacket { - - public PacketSceneAreaWeatherNotify(Player player) { - super(PacketOpcodes.SceneAreaWeatherNotify); - - SceneAreaWeatherNotify proto = SceneAreaWeatherNotify.newBuilder() - .setWeatherAreaId(player.getWeatherId()) - .setClimateType(player.getClimate().getValue()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneAreaWeatherNotifyOuterClass.SceneAreaWeatherNotify; + +public class PacketSceneAreaWeatherNotify extends BasePacket { + + public PacketSceneAreaWeatherNotify(Player player) { + super(PacketOpcodes.SceneAreaWeatherNotify); + + SceneAreaWeatherNotify proto = + SceneAreaWeatherNotify.newBuilder() + .setWeatherAreaId(player.getWeatherId()) + .setClimateType(player.getClimate().getValue()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java index 8c8f13a72..4a72f8ffe 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java @@ -1,49 +1,51 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneEntityAppearNotifyOuterClass.SceneEntityAppearNotify; -import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; - -import java.util.Collection; - -public class PacketSceneEntityAppearNotify extends BasePacket { - - public PacketSceneEntityAppearNotify(GameEntity entity) { - super(PacketOpcodes.SceneEntityAppearNotify, true); - - SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder() - .setAppearType(VisionType.VISION_TYPE_BORN) - .addEntityList(entity.toProto()); - - this.setData(proto.build()); - } - - public PacketSceneEntityAppearNotify(GameEntity entity, VisionType vision, int param) { - super(PacketOpcodes.SceneEntityAppearNotify, true); - - SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder() - .setAppearType(vision) - .setParam(param) - .addEntityList(entity.toProto()); - - this.setData(proto.build()); - } - - public PacketSceneEntityAppearNotify(Player player) { - this(player.getTeamManager().getCurrentAvatarEntity()); - } - - public PacketSceneEntityAppearNotify(Collection entities, VisionType visionType) { - super(PacketOpcodes.SceneEntityAppearNotify, true); - - SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder() - .setAppearType(visionType); - - entities.forEach(e -> proto.addEntityList(e.toProto())); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneEntityAppearNotifyOuterClass.SceneEntityAppearNotify; +import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; +import java.util.Collection; + +public class PacketSceneEntityAppearNotify extends BasePacket { + + public PacketSceneEntityAppearNotify(GameEntity entity) { + super(PacketOpcodes.SceneEntityAppearNotify, true); + + SceneEntityAppearNotify.Builder proto = + SceneEntityAppearNotify.newBuilder() + .setAppearType(VisionType.VISION_TYPE_BORN) + .addEntityList(entity.toProto()); + + this.setData(proto.build()); + } + + public PacketSceneEntityAppearNotify(GameEntity entity, VisionType vision, int param) { + super(PacketOpcodes.SceneEntityAppearNotify, true); + + SceneEntityAppearNotify.Builder proto = + SceneEntityAppearNotify.newBuilder() + .setAppearType(vision) + .setParam(param) + .addEntityList(entity.toProto()); + + this.setData(proto.build()); + } + + public PacketSceneEntityAppearNotify(Player player) { + this(player.getTeamManager().getCurrentAvatarEntity()); + } + + public PacketSceneEntityAppearNotify( + Collection entities, VisionType visionType) { + super(PacketOpcodes.SceneEntityAppearNotify, true); + + SceneEntityAppearNotify.Builder proto = + SceneEntityAppearNotify.newBuilder().setAppearType(visionType); + + entities.forEach(e -> proto.addEntityList(e.toProto())); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDisappearNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDisappearNotify.java index a6c78ce4f..8d5f8ac0a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDisappearNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDisappearNotify.java @@ -1,34 +1,35 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneEntityDisappearNotifyOuterClass.SceneEntityDisappearNotify; -import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; - -import java.util.Collection; - -public class PacketSceneEntityDisappearNotify extends BasePacket { - - public PacketSceneEntityDisappearNotify(GameEntity entity, VisionType disappearType) { - super(PacketOpcodes.SceneEntityDisappearNotify); - - SceneEntityDisappearNotify proto = SceneEntityDisappearNotify.newBuilder() - .setDisappearType(disappearType) - .addEntityList(entity.getId()) - .build(); - - this.setData(proto); - } - - public PacketSceneEntityDisappearNotify(Collection entities, VisionType disappearType) { - super(PacketOpcodes.SceneEntityDisappearNotify); - - SceneEntityDisappearNotify.Builder proto = SceneEntityDisappearNotify.newBuilder() - .setDisappearType(disappearType); - - entities.forEach(e -> proto.addEntityList(e.getId())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneEntityDisappearNotifyOuterClass.SceneEntityDisappearNotify; +import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; +import java.util.Collection; + +public class PacketSceneEntityDisappearNotify extends BasePacket { + + public PacketSceneEntityDisappearNotify(GameEntity entity, VisionType disappearType) { + super(PacketOpcodes.SceneEntityDisappearNotify); + + SceneEntityDisappearNotify proto = + SceneEntityDisappearNotify.newBuilder() + .setDisappearType(disappearType) + .addEntityList(entity.getId()) + .build(); + + this.setData(proto); + } + + public PacketSceneEntityDisappearNotify( + Collection entities, VisionType disappearType) { + super(PacketOpcodes.SceneEntityDisappearNotify); + + SceneEntityDisappearNotify.Builder proto = + SceneEntityDisappearNotify.newBuilder().setDisappearType(disappearType); + + entities.forEach(e -> proto.addEntityList(e.getId())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDrownRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDrownRsp.java index 20b1f4963..11439996a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDrownRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDrownRsp.java @@ -14,5 +14,3 @@ public class PacketSceneEntityDrownRsp extends BasePacket { this.setData(proto); } } - - diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityMoveNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityMoveNotify.java index a89ee244b..1a55fe862 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityMoveNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityMoveNotify.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; -import emu.grasscutter.net.proto.SceneEntityMoveNotifyOuterClass.SceneEntityMoveNotify; - -public class PacketSceneEntityMoveNotify extends BasePacket { - - public PacketSceneEntityMoveNotify(EntityMoveInfo moveInfo) { - super(PacketOpcodes.SceneEntityMoveNotify, true); - - SceneEntityMoveNotify proto = SceneEntityMoveNotify.newBuilder() - .setMotionInfo(moveInfo.getMotionInfo()) - .setEntityId(moveInfo.getEntityId()) - .setSceneTime(moveInfo.getSceneTime()) - .setReliableSeq(moveInfo.getReliableSeq()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; +import emu.grasscutter.net.proto.SceneEntityMoveNotifyOuterClass.SceneEntityMoveNotify; + +public class PacketSceneEntityMoveNotify extends BasePacket { + + public PacketSceneEntityMoveNotify(EntityMoveInfo moveInfo) { + super(PacketOpcodes.SceneEntityMoveNotify, true); + + SceneEntityMoveNotify proto = + SceneEntityMoveNotify.newBuilder() + .setMotionInfo(moveInfo.getMotionInfo()) + .setEntityId(moveInfo.getEntityId()) + .setSceneTime(moveInfo.getSceneTime()) + .setReliableSeq(moveInfo.getReliableSeq()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneInitFinishRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneInitFinishRsp.java index f17d95e34..12552190e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneInitFinishRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneInitFinishRsp.java @@ -1,17 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneInitFinishRspOuterClass.SceneInitFinishRsp; - -public class PacketSceneInitFinishRsp extends BasePacket { - - public PacketSceneInitFinishRsp(Player player) { - super(PacketOpcodes.SceneInitFinishRsp, 11); - - SceneInitFinishRsp p = SceneInitFinishRsp.newBuilder().setEnterSceneToken(player.getEnterSceneToken()).build(); - - this.setData(p.toByteArray()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneInitFinishRspOuterClass.SceneInitFinishRsp; + +public class PacketSceneInitFinishRsp extends BasePacket { + + public PacketSceneInitFinishRsp(Player player) { + super(PacketOpcodes.SceneInitFinishRsp, 11); + + SceneInitFinishRsp p = + SceneInitFinishRsp.newBuilder().setEnterSceneToken(player.getEnterSceneToken()).build(); + + this.setData(p.toByteArray()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneKickPlayerRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneKickPlayerRsp.java index d4493a2ef..6c56b89d6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneKickPlayerRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneKickPlayerRsp.java @@ -1,29 +1,28 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.SceneKickPlayerRspOuterClass.SceneKickPlayerRsp; - -public class PacketSceneKickPlayerRsp extends BasePacket { - - public PacketSceneKickPlayerRsp(int targetUid) { - super(PacketOpcodes.SceneKickPlayerRsp); - - SceneKickPlayerRsp proto = SceneKickPlayerRsp.newBuilder() - .setTargetUid(targetUid) - .build(); - - this.setData(proto); - } - - public PacketSceneKickPlayerRsp() { - super(PacketOpcodes.SceneKickPlayerRsp); - - SceneKickPlayerRsp proto = SceneKickPlayerRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.SceneKickPlayerRspOuterClass.SceneKickPlayerRsp; + +public class PacketSceneKickPlayerRsp extends BasePacket { + + public PacketSceneKickPlayerRsp(int targetUid) { + super(PacketOpcodes.SceneKickPlayerRsp); + + SceneKickPlayerRsp proto = SceneKickPlayerRsp.newBuilder().setTargetUid(targetUid).build(); + + this.setData(proto); + } + + public PacketSceneKickPlayerRsp() { + super(PacketOpcodes.SceneKickPlayerRsp); + + SceneKickPlayerRsp proto = + SceneKickPlayerRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerInfoNotify.java index 8e04a8a1d..1ab99a309 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerInfoNotify.java @@ -1,33 +1,34 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ScenePlayerInfoNotifyOuterClass.ScenePlayerInfoNotify; -import emu.grasscutter.net.proto.ScenePlayerInfoOuterClass.ScenePlayerInfo; - -public class PacketScenePlayerInfoNotify extends BasePacket { - - public PacketScenePlayerInfoNotify(World world) { - super(PacketOpcodes.ScenePlayerInfoNotify); - - ScenePlayerInfoNotify.Builder proto = ScenePlayerInfoNotify.newBuilder(); - - for (int i = 0; i < world.getPlayers().size(); i++) { - Player p = world.getPlayers().get(i); - - ScenePlayerInfo pInfo = ScenePlayerInfo.newBuilder() - .setUid(p.getUid()) - .setPeerId(p.getPeerId()) - .setName(p.getNickname()) - .setSceneId(p.getSceneId()) - .setOnlinePlayerInfo(p.getOnlinePlayerInfo()) - .build(); - - proto.addPlayerInfoList(pInfo); - } - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ScenePlayerInfoNotifyOuterClass.ScenePlayerInfoNotify; +import emu.grasscutter.net.proto.ScenePlayerInfoOuterClass.ScenePlayerInfo; + +public class PacketScenePlayerInfoNotify extends BasePacket { + + public PacketScenePlayerInfoNotify(World world) { + super(PacketOpcodes.ScenePlayerInfoNotify); + + ScenePlayerInfoNotify.Builder proto = ScenePlayerInfoNotify.newBuilder(); + + for (int i = 0; i < world.getPlayers().size(); i++) { + Player p = world.getPlayers().get(i); + + ScenePlayerInfo pInfo = + ScenePlayerInfo.newBuilder() + .setUid(p.getUid()) + .setPeerId(p.getPeerId()) + .setName(p.getNickname()) + .setSceneId(p.getSceneId()) + .setOnlinePlayerInfo(p.getOnlinePlayerInfo()) + .build(); + + proto.addPlayerInfoList(pInfo); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java index c9f7e5c33..f925c043c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java @@ -1,23 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ScenePlayerLocationNotifyOuterClass.ScenePlayerLocationNotify; - -public class PacketScenePlayerLocationNotify extends BasePacket { - - public PacketScenePlayerLocationNotify(Scene scene) { - super(PacketOpcodes.ScenePlayerLocationNotify); - - ScenePlayerLocationNotify.Builder proto = ScenePlayerLocationNotify.newBuilder() - .setSceneId(scene.getId()); - - for (Player p : scene.getPlayers()) { - proto.addPlayerLocList(p.getPlayerLocationInfo()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ScenePlayerLocationNotifyOuterClass.ScenePlayerLocationNotify; + +public class PacketScenePlayerLocationNotify extends BasePacket { + + public PacketScenePlayerLocationNotify(Scene scene) { + super(PacketOpcodes.ScenePlayerLocationNotify); + + ScenePlayerLocationNotify.Builder proto = + ScenePlayerLocationNotify.newBuilder().setSceneId(scene.getId()); + + for (Player p : scene.getPlayers()) { + proto.addPlayerLocList(p.getPlayerLocationInfo()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePointUnlockNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePointUnlockNotify.java index 41a9e8b0a..3dba4a4f1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePointUnlockNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePointUnlockNotify.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ScenePointUnlockNotifyOuterClass.ScenePointUnlockNotify; - -public class PacketScenePointUnlockNotify extends BasePacket { - public PacketScenePointUnlockNotify(int sceneId, int pointId) { - super(PacketOpcodes.ScenePointUnlockNotify); - - ScenePointUnlockNotify.Builder p = ScenePointUnlockNotify.newBuilder() - .setSceneId(sceneId) - .addPointList(pointId) - .addUnhidePointList(pointId); - - this.setData(p); - } - - public PacketScenePointUnlockNotify(int sceneId, Iterable pointIds) { - super(PacketOpcodes.ScenePointUnlockNotify); - - ScenePointUnlockNotify.Builder p = ScenePointUnlockNotify.newBuilder() - .setSceneId(sceneId) - .addAllPointList(pointIds) - .addAllUnhidePointList(pointIds); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ScenePointUnlockNotifyOuterClass.ScenePointUnlockNotify; + +public class PacketScenePointUnlockNotify extends BasePacket { + public PacketScenePointUnlockNotify(int sceneId, int pointId) { + super(PacketOpcodes.ScenePointUnlockNotify); + + ScenePointUnlockNotify.Builder p = + ScenePointUnlockNotify.newBuilder() + .setSceneId(sceneId) + .addPointList(pointId) + .addUnhidePointList(pointId); + + this.setData(p); + } + + public PacketScenePointUnlockNotify(int sceneId, Iterable pointIds) { + super(PacketOpcodes.ScenePointUnlockNotify); + + ScenePointUnlockNotify.Builder p = + ScenePointUnlockNotify.newBuilder() + .setSceneId(sceneId) + .addAllPointList(pointIds) + .addAllUnhidePointList(pointIds); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java index fe2b22127..f1cf8c77d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java @@ -1,46 +1,47 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.SceneTeamAvatarOuterClass.SceneTeamAvatar; -import emu.grasscutter.net.proto.SceneTeamUpdateNotifyOuterClass.SceneTeamUpdateNotify; - -public class PacketSceneTeamUpdateNotify extends BasePacket { - - public PacketSceneTeamUpdateNotify(Player player) { - super(PacketOpcodes.SceneTeamUpdateNotify); - - SceneTeamUpdateNotify.Builder proto = SceneTeamUpdateNotify.newBuilder() - .setIsInMp(player.getWorld().isMultiplayer()); - - for (Player p : player.getWorld().getPlayers()) { - for (EntityAvatar entityAvatar : p.getTeamManager().getActiveTeam()) { - SceneTeamAvatar.Builder avatarProto = SceneTeamAvatar.newBuilder() - .setPlayerUid(p.getUid()) - .setAvatarGuid(entityAvatar.getAvatar().getGuid()) - .setSceneId(p.getSceneId()) - .setEntityId(entityAvatar.getId()) - .setSceneEntityInfo(entityAvatar.toProto()) - .setWeaponGuid(entityAvatar.getAvatar().getWeapon().getGuid()) - .setWeaponEntityId(entityAvatar.getWeaponEntityId()) - .setIsPlayerCurAvatar(p.getTeamManager().getCurrentAvatarEntity() == entityAvatar) - .setIsOnScene(p.getTeamManager().getCurrentAvatarEntity() == entityAvatar) - .setAvatarAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setWeaponAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .setAbilityControlBlock(entityAvatar.getAbilityControlBlock()); - - if (player.getWorld().isMultiplayer()) { - avatarProto.setAvatarInfo(entityAvatar.getAvatar().toProto()); - avatarProto.setSceneAvatarInfo(entityAvatar.getSceneAvatarInfo()); // why mihoyo... - } - - proto.addSceneTeamAvatarList(avatarProto); - } - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.SceneTeamAvatarOuterClass.SceneTeamAvatar; +import emu.grasscutter.net.proto.SceneTeamUpdateNotifyOuterClass.SceneTeamUpdateNotify; + +public class PacketSceneTeamUpdateNotify extends BasePacket { + + public PacketSceneTeamUpdateNotify(Player player) { + super(PacketOpcodes.SceneTeamUpdateNotify); + + SceneTeamUpdateNotify.Builder proto = + SceneTeamUpdateNotify.newBuilder().setIsInMp(player.getWorld().isMultiplayer()); + + for (Player p : player.getWorld().getPlayers()) { + for (EntityAvatar entityAvatar : p.getTeamManager().getActiveTeam()) { + SceneTeamAvatar.Builder avatarProto = + SceneTeamAvatar.newBuilder() + .setPlayerUid(p.getUid()) + .setAvatarGuid(entityAvatar.getAvatar().getGuid()) + .setSceneId(p.getSceneId()) + .setEntityId(entityAvatar.getId()) + .setSceneEntityInfo(entityAvatar.toProto()) + .setWeaponGuid(entityAvatar.getAvatar().getWeapon().getGuid()) + .setWeaponEntityId(entityAvatar.getWeaponEntityId()) + .setIsPlayerCurAvatar(p.getTeamManager().getCurrentAvatarEntity() == entityAvatar) + .setIsOnScene(p.getTeamManager().getCurrentAvatarEntity() == entityAvatar) + .setAvatarAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setWeaponAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .setAbilityControlBlock(entityAvatar.getAbilityControlBlock()); + + if (player.getWorld().isMultiplayer()) { + avatarProto.setAvatarInfo(entityAvatar.getAvatar().toProto()); + avatarProto.setSceneAvatarInfo(entityAvatar.getSceneAvatarInfo()); // why mihoyo... + } + + proto.addSceneTeamAvatarList(avatarProto); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTimeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTimeNotify.java index bb232f658..64aa54ef8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTimeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTimeNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneTimeNotifyOuterClass.SceneTimeNotify; - -public class PacketSceneTimeNotify extends BasePacket { - - public PacketSceneTimeNotify(Player player) { - super(PacketOpcodes.SceneTimeNotify); - - SceneTimeNotify proto = SceneTimeNotify.newBuilder() - .setIsPaused(player.isPaused()) - .setSceneId(player.getSceneId()) - .setSceneTime(player.getScene().getSceneTime()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SceneTimeNotifyOuterClass.SceneTimeNotify; + +public class PacketSceneTimeNotify extends BasePacket { + + public PacketSceneTimeNotify(Player player) { + super(PacketOpcodes.SceneTimeNotify); + + SceneTimeNotify proto = + SceneTimeNotify.newBuilder() + .setIsPaused(player.isPaused()) + .setSceneId(player.getSceneId()) + .setSceneTime(player.getScene().getSceneTime()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java index 7a8e11a71..9ffe45d65 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java @@ -1,32 +1,34 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp; - -public class PacketSceneTransToPointRsp extends BasePacket { - - public PacketSceneTransToPointRsp(Player player, int pointId, int sceneId) { - super(PacketOpcodes.SceneTransToPointRsp); - - SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder() - .setRetcode(0) - .setPointId(pointId) - .setSceneId(sceneId) - .build(); - - this.setData(proto); - } - - public PacketSceneTransToPointRsp() { - super(PacketOpcodes.SceneTransToPointRsp); - - SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) // Internal server error - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp; + +public class PacketSceneTransToPointRsp extends BasePacket { + + public PacketSceneTransToPointRsp(Player player, int pointId, int sceneId) { + super(PacketOpcodes.SceneTransToPointRsp); + + SceneTransToPointRsp proto = + SceneTransToPointRsp.newBuilder() + .setRetcode(0) + .setPointId(pointId) + .setSceneId(sceneId) + .build(); + + this.setData(proto); + } + + public PacketSceneTransToPointRsp() { + super(PacketOpcodes.SceneTransToPointRsp); + + SceneTransToPointRsp proto = + SceneTransToPointRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) // Internal server error + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSelectWorktopOptionRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSelectWorktopOptionRsp.java index 367a779d0..e65a85c6b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSelectWorktopOptionRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSelectWorktopOptionRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SelectWorktopOptionRspOuterClass.SelectWorktopOptionRsp; - -public class PacketSelectWorktopOptionRsp extends BasePacket { - - public PacketSelectWorktopOptionRsp(int entityId, int optionId) { - super(PacketOpcodes.SelectWorktopOptionRsp); - - SelectWorktopOptionRsp proto = SelectWorktopOptionRsp.newBuilder() - .setGadgetEntityId(entityId) - .setOptionId(optionId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SelectWorktopOptionRspOuterClass.SelectWorktopOptionRsp; + +public class PacketSelectWorktopOptionRsp extends BasePacket { + + public PacketSelectWorktopOptionRsp(int entityId, int optionId) { + super(PacketOpcodes.SelectWorktopOptionRsp); + + SelectWorktopOptionRsp proto = + SelectWorktopOptionRsp.newBuilder() + .setGadgetEntityId(entityId) + .setOptionId(optionId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceNotify.java index bd707c652..790fa1254 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceNotify.java @@ -1,38 +1,38 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AnnounceDataOuterClass; -import emu.grasscutter.net.proto.ServerAnnounceNotifyOuterClass; -import emu.grasscutter.utils.Utils; - -import java.util.List; - -public class PacketServerAnnounceNotify extends BasePacket { - - public PacketServerAnnounceNotify(List data) { - super(PacketOpcodes.ServerAnnounceNotify); - - var proto = ServerAnnounceNotifyOuterClass.ServerAnnounceNotify.newBuilder(); - - proto.addAllAnnounceDataList(data); - - this.setData(proto); - } - - public PacketServerAnnounceNotify(String msg, int configId) { - super(PacketOpcodes.ServerAnnounceNotify); - - var proto = ServerAnnounceNotifyOuterClass.ServerAnnounceNotify.newBuilder(); - - proto.addAnnounceDataList(AnnounceDataOuterClass.AnnounceData.newBuilder() - .setConfigId(configId) - .setBeginTime(Utils.getCurrentSeconds() + 1) - .setEndTime(Utils.getCurrentSeconds() + 2) - .setCenterSystemText(msg) - .setCenterSystemFrequency(1) - .build()); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AnnounceDataOuterClass; +import emu.grasscutter.net.proto.ServerAnnounceNotifyOuterClass; +import emu.grasscutter.utils.Utils; +import java.util.List; + +public class PacketServerAnnounceNotify extends BasePacket { + + public PacketServerAnnounceNotify(List data) { + super(PacketOpcodes.ServerAnnounceNotify); + + var proto = ServerAnnounceNotifyOuterClass.ServerAnnounceNotify.newBuilder(); + + proto.addAllAnnounceDataList(data); + + this.setData(proto); + } + + public PacketServerAnnounceNotify(String msg, int configId) { + super(PacketOpcodes.ServerAnnounceNotify); + + var proto = ServerAnnounceNotifyOuterClass.ServerAnnounceNotify.newBuilder(); + + proto.addAnnounceDataList( + AnnounceDataOuterClass.AnnounceData.newBuilder() + .setConfigId(configId) + .setBeginTime(Utils.getCurrentSeconds() + 1) + .setEndTime(Utils.getCurrentSeconds() + 2) + .setCenterSystemText(msg) + .setCenterSystemFrequency(1) + .build()); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceRevokeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceRevokeNotify.java index 70eb64c32..a66178a1b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceRevokeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerAnnounceRevokeNotify.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ServerAnnounceRevokeNotifyOuterClass; - -public class PacketServerAnnounceRevokeNotify extends BasePacket { - - public PacketServerAnnounceRevokeNotify(int tplId) { - super(PacketOpcodes.ServerAnnounceRevokeNotify); - - var proto = ServerAnnounceRevokeNotifyOuterClass.ServerAnnounceRevokeNotify.newBuilder(); - - proto.addConfigIdList(tplId); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ServerAnnounceRevokeNotifyOuterClass; + +public class PacketServerAnnounceRevokeNotify extends BasePacket { + + public PacketServerAnnounceRevokeNotify(int tplId) { + super(PacketOpcodes.ServerAnnounceRevokeNotify); + + var proto = ServerAnnounceRevokeNotifyOuterClass.ServerAnnounceRevokeNotify.newBuilder(); + + proto.addConfigIdList(tplId); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerBuffChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerBuffChangeNotify.java index 0281469b5..18d5964be 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketServerBuffChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerBuffChangeNotify.java @@ -1,38 +1,39 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.PlayerBuffManager.PlayerBuff; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify; -import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType; - -import java.util.Collection; -import java.util.stream.Stream; - -public class PacketServerBuffChangeNotify extends BasePacket { - - public PacketServerBuffChangeNotify(Player player, ServerBuffChangeType changeType, PlayerBuff buff) { - this(player, changeType, Stream.of(buff)); - } - - public PacketServerBuffChangeNotify(Player player, ServerBuffChangeType changeType, Collection buffs) { - this(player, changeType, buffs.stream()); - } - - public PacketServerBuffChangeNotify(Player player, ServerBuffChangeType changeType, Stream buffs) { - super(PacketOpcodes.ServerBuffChangeNotify); - - var proto = ServerBuffChangeNotify.newBuilder(); - - player.getTeamManager().getActiveTeam().stream() - .mapToLong(entity -> entity.getAvatar().getGuid()) - .forEach(proto::addAvatarGuidList); - - proto.setServerBuffChangeType(changeType); - buffs.map(PlayerBuff::toProto) - .forEach(proto::addServerBuffList); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.PlayerBuffManager.PlayerBuff; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify; +import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType; +import java.util.Collection; +import java.util.stream.Stream; + +public class PacketServerBuffChangeNotify extends BasePacket { + + public PacketServerBuffChangeNotify( + Player player, ServerBuffChangeType changeType, PlayerBuff buff) { + this(player, changeType, Stream.of(buff)); + } + + public PacketServerBuffChangeNotify( + Player player, ServerBuffChangeType changeType, Collection buffs) { + this(player, changeType, buffs.stream()); + } + + public PacketServerBuffChangeNotify( + Player player, ServerBuffChangeType changeType, Stream buffs) { + super(PacketOpcodes.ServerBuffChangeNotify); + + var proto = ServerBuffChangeNotify.newBuilder(); + + player.getTeamManager().getActiveTeam().stream() + .mapToLong(entity -> entity.getAvatar().getGuid()) + .forEach(proto::addAvatarGuidList); + + proto.setServerBuffChangeType(changeType); + buffs.map(PlayerBuff::toProto).forEach(proto::addServerBuffList); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerTimeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerTimeNotify.java index 0233d4b17..f88c7c7f1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketServerTimeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerTimeNotify.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ServerTimeNotifyOuterClass.ServerTimeNotify; - -public class PacketServerTimeNotify extends BasePacket { - - public PacketServerTimeNotify() { - super(PacketOpcodes.ServerTimeNotify); - - ServerTimeNotify proto = ServerTimeNotify.newBuilder() - .setServerTime(System.currentTimeMillis()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ServerTimeNotifyOuterClass.ServerTimeNotify; + +public class PacketServerTimeNotify extends BasePacket { + + public PacketServerTimeNotify() { + super(PacketOpcodes.ServerTimeNotify); + + ServerTimeNotify proto = + ServerTimeNotify.newBuilder().setServerTime(System.currentTimeMillis()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetBattlePassViewedRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetBattlePassViewedRsp.java index b7161049f..7a119a88c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetBattlePassViewedRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetBattlePassViewedRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetBattlePassViewedRspOuterClass.SetBattlePassViewedRsp; - -public class PacketSetBattlePassViewedRsp extends BasePacket { - - public PacketSetBattlePassViewedRsp(int scheduleId) { - super(PacketOpcodes.SetBattlePassViewedRsp); - - SetBattlePassViewedRsp proto = SetBattlePassViewedRsp.newBuilder() - .setScheduleId(scheduleId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetBattlePassViewedRspOuterClass.SetBattlePassViewedRsp; + +public class PacketSetBattlePassViewedRsp extends BasePacket { + + public PacketSetBattlePassViewedRsp(int scheduleId) { + super(PacketOpcodes.SetBattlePassViewedRsp); + + SetBattlePassViewedRsp proto = + SetBattlePassViewedRsp.newBuilder().setScheduleId(scheduleId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetEquipLockStateRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetEquipLockStateRsp.java index f78c9e868..6267d85dd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetEquipLockStateRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetEquipLockStateRsp.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetEquipLockStateRspOuterClass.SetEquipLockStateRsp; - -public class PacketSetEquipLockStateRsp extends BasePacket { - - public PacketSetEquipLockStateRsp(GameItem equip) { - super(PacketOpcodes.SetEquipLockStateRsp); - - this.buildHeader(0); - - SetEquipLockStateRsp proto = SetEquipLockStateRsp.newBuilder() - .setTargetEquipGuid(equip.getGuid()) - .setIsLocked(equip.isLocked()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetEquipLockStateRspOuterClass.SetEquipLockStateRsp; + +public class PacketSetEquipLockStateRsp extends BasePacket { + + public PacketSetEquipLockStateRsp(GameItem equip) { + super(PacketOpcodes.SetEquipLockStateRsp); + + this.buildHeader(0); + + SetEquipLockStateRsp proto = + SetEquipLockStateRsp.newBuilder() + .setTargetEquipGuid(equip.getGuid()) + .setIsLocked(equip.isLocked()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetNameCardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetNameCardRsp.java index 5930f3594..28fee035f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetNameCardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetNameCardRsp.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetNameCardRspOuterClass.SetNameCardRsp; - -public class PacketSetNameCardRsp extends BasePacket { - - public PacketSetNameCardRsp(int nameCardId) { - super(PacketOpcodes.SetNameCardRsp); - - SetNameCardRsp proto = SetNameCardRsp.newBuilder() - .setNameCardId(nameCardId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetNameCardRspOuterClass.SetNameCardRsp; + +public class PacketSetNameCardRsp extends BasePacket { + + public PacketSetNameCardRsp(int nameCardId) { + super(PacketOpcodes.SetNameCardRsp); + + SetNameCardRsp proto = SetNameCardRsp.newBuilder().setNameCardId(nameCardId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetOpenStateRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetOpenStateRsp.java index a49467dda..af1aa153c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetOpenStateRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetOpenStateRsp.java @@ -1,26 +1,24 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.net.proto.SetOpenStateRspOuterClass.SetOpenStateRsp; - -public class PacketSetOpenStateRsp extends BasePacket { - public PacketSetOpenStateRsp(int openState, int value) { - super(PacketOpcodes.SetOpenStateRsp); - - SetOpenStateRsp proto = SetOpenStateRsp.newBuilder() - .setKey(openState).setValue(value).build(); - - this.setData(proto); - } - - public PacketSetOpenStateRsp(Retcode retcode) { - super(PacketOpcodes.SetOpenStateRsp); - - SetOpenStateRsp proto = SetOpenStateRsp.newBuilder() - .setRetcode(retcode.getNumber()).build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.net.proto.SetOpenStateRspOuterClass.SetOpenStateRsp; + +public class PacketSetOpenStateRsp extends BasePacket { + public PacketSetOpenStateRsp(int openState, int value) { + super(PacketOpcodes.SetOpenStateRsp); + + SetOpenStateRsp proto = SetOpenStateRsp.newBuilder().setKey(openState).setValue(value).build(); + + this.setData(proto); + } + + public PacketSetOpenStateRsp(Retcode retcode) { + super(PacketOpcodes.SetOpenStateRsp); + + SetOpenStateRsp proto = SetOpenStateRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerBirthdayRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerBirthdayRsp.java index d4ce659a5..02d4cf7c1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerBirthdayRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerBirthdayRsp.java @@ -1,29 +1,26 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp; - -public class PacketSetPlayerBirthdayRsp extends BasePacket { - - public PacketSetPlayerBirthdayRsp(int retCode) { - super(PacketOpcodes.SetPlayerBirthdayRsp); - - SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder() - .setRetcode(retCode) - .build(); - - this.setData(proto); - } - - public PacketSetPlayerBirthdayRsp(Player player) { - super(PacketOpcodes.SetPlayerBirthdayRsp); - - SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder() - .setBirthday(player.getBirthday().toProto()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp; + +public class PacketSetPlayerBirthdayRsp extends BasePacket { + + public PacketSetPlayerBirthdayRsp(int retCode) { + super(PacketOpcodes.SetPlayerBirthdayRsp); + + SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder().setRetcode(retCode).build(); + + this.setData(proto); + } + + public PacketSetPlayerBirthdayRsp(Player player) { + super(PacketOpcodes.SetPlayerBirthdayRsp); + + SetPlayerBirthdayRsp proto = + SetPlayerBirthdayRsp.newBuilder().setBirthday(player.getBirthday().toProto()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerHeadImageRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerHeadImageRsp.java index 671bcd0ce..b23b6d2db 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerHeadImageRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerHeadImageRsp.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; -import emu.grasscutter.net.proto.SetPlayerHeadImageRspOuterClass.SetPlayerHeadImageRsp; - -public class PacketSetPlayerHeadImageRsp extends BasePacket { - - public PacketSetPlayerHeadImageRsp(Player player) { - super(PacketOpcodes.SetPlayerHeadImageRsp); - - SetPlayerHeadImageRsp proto = SetPlayerHeadImageRsp.newBuilder() - .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(player.getHeadImage())) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; +import emu.grasscutter.net.proto.SetPlayerHeadImageRspOuterClass.SetPlayerHeadImageRsp; + +public class PacketSetPlayerHeadImageRsp extends BasePacket { + + public PacketSetPlayerHeadImageRsp(Player player) { + super(PacketOpcodes.SetPlayerHeadImageRsp); + + SetPlayerHeadImageRsp proto = + SetPlayerHeadImageRsp.newBuilder() + .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(player.getHeadImage())) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerNameRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerNameRsp.java index be5ddd96b..d2d09ce05 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerNameRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerNameRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerNameRspOuterClass.SetPlayerNameRsp; - -public class PacketSetPlayerNameRsp extends BasePacket { - - public PacketSetPlayerNameRsp(Player player) { - super(PacketOpcodes.SetPlayerNameRsp); - - SetPlayerNameRsp proto = SetPlayerNameRsp.newBuilder() - .setNickName(player.getNickname()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerNameRspOuterClass.SetPlayerNameRsp; + +public class PacketSetPlayerNameRsp extends BasePacket { + + public PacketSetPlayerNameRsp(Player player) { + super(PacketOpcodes.SetPlayerNameRsp); + + SetPlayerNameRsp proto = + SetPlayerNameRsp.newBuilder().setNickName(player.getNickname()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerPropRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerPropRsp.java index 6bdb75514..a67c6721e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerPropRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerPropRsp.java @@ -1,17 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerPropRspOuterClass; - -public class PacketSetPlayerPropRsp extends BasePacket { - - public PacketSetPlayerPropRsp(int retCode) { - super(PacketOpcodes.SetPlayerPropRsp); - SetPlayerPropRspOuterClass.SetPlayerPropRsp.Builder proto = SetPlayerPropRspOuterClass.SetPlayerPropRsp.newBuilder(); - if (retCode != 0) { - proto.setRetcode(retCode); - } - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerPropRspOuterClass; + +public class PacketSetPlayerPropRsp extends BasePacket { + + public PacketSetPlayerPropRsp(int retCode) { + super(PacketOpcodes.SetPlayerPropRsp); + SetPlayerPropRspOuterClass.SetPlayerPropRsp.Builder proto = + SetPlayerPropRspOuterClass.SetPlayerPropRsp.newBuilder(); + if (retCode != 0) { + proto.setRetcode(retCode); + } + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerSignatureRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerSignatureRsp.java index 43c582136..90f0199fa 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerSignatureRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetPlayerSignatureRsp.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetPlayerSignatureRspOuterClass.SetPlayerSignatureRsp; - -public class PacketSetPlayerSignatureRsp extends BasePacket { - - public PacketSetPlayerSignatureRsp(Player player) { - super(PacketOpcodes.SetPlayerSignatureRsp); - - SetPlayerSignatureRsp proto = SetPlayerSignatureRsp.newBuilder() - .setSignature(player.getSignature()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetPlayerSignatureRspOuterClass.SetPlayerSignatureRsp; + +public class PacketSetPlayerSignatureRsp extends BasePacket { + + public PacketSetPlayerSignatureRsp(Player player) { + super(PacketOpcodes.SetPlayerSignatureRsp); + + SetPlayerSignatureRsp proto = + SetPlayerSignatureRsp.newBuilder().setSignature(player.getSignature()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpAvatarTeamRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpAvatarTeamRsp.java index 212c0fa05..b6eec924b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpAvatarTeamRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpAvatarTeamRsp.java @@ -1,24 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.player.TeamInfo; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetUpAvatarTeamRspOuterClass.SetUpAvatarTeamRsp; - -public class PacketSetUpAvatarTeamRsp extends BasePacket { - - public PacketSetUpAvatarTeamRsp(Player player, int teamId, TeamInfo teamInfo) { - super(PacketOpcodes.SetUpAvatarTeamRsp); - - SetUpAvatarTeamRsp.Builder proto = SetUpAvatarTeamRsp.newBuilder() - .setTeamId(teamId) - .setCurAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()); - - for (int avatarId : teamInfo.getAvatars()) { - proto.addAvatarTeamGuidList(player.getAvatars().getAvatarById(avatarId).getGuid()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.TeamInfo; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetUpAvatarTeamRspOuterClass.SetUpAvatarTeamRsp; + +public class PacketSetUpAvatarTeamRsp extends BasePacket { + + public PacketSetUpAvatarTeamRsp(Player player, int teamId, TeamInfo teamInfo) { + super(PacketOpcodes.SetUpAvatarTeamRsp); + + SetUpAvatarTeamRsp.Builder proto = + SetUpAvatarTeamRsp.newBuilder() + .setTeamId(teamId) + .setCurAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()); + + for (int avatarId : teamInfo.getAvatars()) { + proto.addAvatarTeamGuidList(player.getAvatars().getAvatarById(avatarId).getGuid()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpLunchBoxWidgetRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpLunchBoxWidgetRsp.java index 6c6bd22a7..bfe2f1d63 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpLunchBoxWidgetRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetUpLunchBoxWidgetRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.LunchBoxDataOuterClass; -import emu.grasscutter.net.proto.SetUpLunchBoxWidgetRspOuterClass; - -public class PacketSetUpLunchBoxWidgetRsp extends BasePacket { - - public PacketSetUpLunchBoxWidgetRsp(LunchBoxDataOuterClass.LunchBoxData lunchBoxData) { - super(PacketOpcodes.SetUpLunchBoxWidgetRsp); - var rsp - = SetUpLunchBoxWidgetRspOuterClass.SetUpLunchBoxWidgetRsp.newBuilder(); - rsp.setLunchBoxData(lunchBoxData); - - setData(rsp.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.LunchBoxDataOuterClass; +import emu.grasscutter.net.proto.SetUpLunchBoxWidgetRspOuterClass; + +public class PacketSetUpLunchBoxWidgetRsp extends BasePacket { + + public PacketSetUpLunchBoxWidgetRsp(LunchBoxDataOuterClass.LunchBoxData lunchBoxData) { + super(PacketOpcodes.SetUpLunchBoxWidgetRsp); + var rsp = SetUpLunchBoxWidgetRspOuterClass.SetUpLunchBoxWidgetRsp.newBuilder(); + rsp.setLunchBoxData(lunchBoxData); + + setData(rsp.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java index d20efcad0..7dbb7746a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SetWidgetSlotRspOuterClass; - -public class PacketSetWidgetSlotRsp extends BasePacket { - - public PacketSetWidgetSlotRsp(int materialId) { - super(PacketOpcodes.SetWidgetSlotRsp); - - SetWidgetSlotRspOuterClass.SetWidgetSlotRsp proto = SetWidgetSlotRspOuterClass.SetWidgetSlotRsp.newBuilder() - .setMaterialId(materialId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetWidgetSlotRspOuterClass; + +public class PacketSetWidgetSlotRsp extends BasePacket { + + public PacketSetWidgetSlotRsp(int materialId) { + super(PacketOpcodes.SetWidgetSlotRsp); + + SetWidgetSlotRspOuterClass.SetWidgetSlotRsp proto = + SetWidgetSlotRspOuterClass.SetWidgetSlotRsp.newBuilder().setMaterialId(materialId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSkipPlayerGameTimeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSkipPlayerGameTimeRsp.java index db22a1687..b89b6cf96 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSkipPlayerGameTimeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSkipPlayerGameTimeRsp.java @@ -1,19 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SkipPlayerGameTimeReqOuterClass; -import emu.grasscutter.net.proto.SkipPlayerGameTimeRspOuterClass; - -public class PacketSkipPlayerGameTimeRsp extends BasePacket { - public PacketSkipPlayerGameTimeRsp(SkipPlayerGameTimeReqOuterClass.SkipPlayerGameTimeReq req) { - super(PacketOpcodes.SkipPlayerGameTimeRsp); - - var proto = SkipPlayerGameTimeRspOuterClass.SkipPlayerGameTimeRsp.newBuilder() - .setClientGameTime(req.getClientGameTime()) - .setGameTime(req.getGameTime()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SkipPlayerGameTimeReqOuterClass; +import emu.grasscutter.net.proto.SkipPlayerGameTimeRspOuterClass; + +public class PacketSkipPlayerGameTimeRsp extends BasePacket { + public PacketSkipPlayerGameTimeRsp(SkipPlayerGameTimeReqOuterClass.SkipPlayerGameTimeReq req) { + super(PacketOpcodes.SkipPlayerGameTimeRsp); + + var proto = + SkipPlayerGameTimeRspOuterClass.SkipPlayerGameTimeRsp.newBuilder() + .setClientGameTime(req.getClientGameTime()) + .setGameTime(req.getGameTime()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java index 997005347..6f691db84 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java @@ -1,37 +1,37 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.StoreItemChangeNotifyOuterClass.StoreItemChangeNotify; -import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; - -import java.util.Collection; - -public class PacketStoreItemChangeNotify extends BasePacket { - - private PacketStoreItemChangeNotify() { - super(PacketOpcodes.StoreItemChangeNotify); - } - - public PacketStoreItemChangeNotify(GameItem item) { - this(); - - StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK) - .addItemList(item.toProto()); - - this.setData(proto); - } - - public PacketStoreItemChangeNotify(Collection items) { - this(); - - StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK); - - items.forEach(item -> proto.addItemList(item.toProto())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.StoreItemChangeNotifyOuterClass.StoreItemChangeNotify; +import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; +import java.util.Collection; + +public class PacketStoreItemChangeNotify extends BasePacket { + + private PacketStoreItemChangeNotify() { + super(PacketOpcodes.StoreItemChangeNotify); + } + + public PacketStoreItemChangeNotify(GameItem item) { + this(); + + StoreItemChangeNotify.Builder proto = + StoreItemChangeNotify.newBuilder() + .setStoreType(StoreType.STORE_TYPE_PACK) + .addItemList(item.toProto()); + + this.setData(proto); + } + + public PacketStoreItemChangeNotify(Collection items) { + this(); + + StoreItemChangeNotify.Builder proto = + StoreItemChangeNotify.newBuilder().setStoreType(StoreType.STORE_TYPE_PACK); + + items.forEach(item -> proto.addItemList(item.toProto())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java index 2915f7153..daa566357 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java @@ -1,37 +1,37 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.StoreItemDelNotifyOuterClass.StoreItemDelNotify; -import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; - -import java.util.Collection; - -public class PacketStoreItemDelNotify extends BasePacket { - - private PacketStoreItemDelNotify() { - super(PacketOpcodes.StoreItemDelNotify); - } - - public PacketStoreItemDelNotify(GameItem item) { - this(); - - StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK) - .addGuidList(item.getGuid()); - - this.setData(proto); - } - - public PacketStoreItemDelNotify(Collection items) { - this(); - - StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK); - - items.stream().forEach(item -> proto.addGuidList(item.getGuid())); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.StoreItemDelNotifyOuterClass.StoreItemDelNotify; +import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; +import java.util.Collection; + +public class PacketStoreItemDelNotify extends BasePacket { + + private PacketStoreItemDelNotify() { + super(PacketOpcodes.StoreItemDelNotify); + } + + public PacketStoreItemDelNotify(GameItem item) { + this(); + + StoreItemDelNotify.Builder proto = + StoreItemDelNotify.newBuilder() + .setStoreType(StoreType.STORE_TYPE_PACK) + .addGuidList(item.getGuid()); + + this.setData(proto); + } + + public PacketStoreItemDelNotify(Collection items) { + this(); + + StoreItemDelNotify.Builder proto = + StoreItemDelNotify.newBuilder().setStoreType(StoreType.STORE_TYPE_PACK); + + items.stream().forEach(item -> proto.addGuidList(item.getGuid())); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java index b980d6214..964afcceb 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; -import emu.grasscutter.net.proto.StoreWeightLimitNotifyOuterClass.StoreWeightLimitNotify; - -import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; - -public class PacketStoreWeightLimitNotify extends BasePacket { - - public PacketStoreWeightLimitNotify() { - super(PacketOpcodes.StoreWeightLimitNotify); - - StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder() - .setStoreType(StoreType.STORE_TYPE_PACK) - .setWeightLimit(INVENTORY_LIMITS.all) - .setWeaponCountLimit(INVENTORY_LIMITS.weapons) - .setReliquaryCountLimit(INVENTORY_LIMITS.relics) - .setMaterialCountLimit(INVENTORY_LIMITS.materials) - .setFurnitureCountLimit(INVENTORY_LIMITS.furniture) - .build(); - - this.setData(p); - } -} +package emu.grasscutter.server.packet.send; + +import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; +import emu.grasscutter.net.proto.StoreWeightLimitNotifyOuterClass.StoreWeightLimitNotify; + +public class PacketStoreWeightLimitNotify extends BasePacket { + + public PacketStoreWeightLimitNotify() { + super(PacketOpcodes.StoreWeightLimitNotify); + + StoreWeightLimitNotify p = + StoreWeightLimitNotify.newBuilder() + .setStoreType(StoreType.STORE_TYPE_PACK) + .setWeightLimit(INVENTORY_LIMITS.all) + .setWeaponCountLimit(INVENTORY_LIMITS.weapons) + .setReliquaryCountLimit(INVENTORY_LIMITS.relics) + .setMaterialCountLimit(INVENTORY_LIMITS.materials) + .setFurnitureCountLimit(INVENTORY_LIMITS.furniture) + .build(); + + this.setData(p); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSyncScenePlayTeamEntityNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSyncScenePlayTeamEntityNotify.java index 2a4147909..0bc2303de 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSyncScenePlayTeamEntityNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSyncScenePlayTeamEntityNotify.java @@ -1,19 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SyncScenePlayTeamEntityNotifyOuterClass.SyncScenePlayTeamEntityNotify; - -public class PacketSyncScenePlayTeamEntityNotify extends BasePacket { - - public PacketSyncScenePlayTeamEntityNotify(Player player) { - super(PacketOpcodes.SyncScenePlayTeamEntityNotify); - - SyncScenePlayTeamEntityNotify proto = SyncScenePlayTeamEntityNotify.newBuilder() - .setSceneId(player.getSceneId()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SyncScenePlayTeamEntityNotifyOuterClass.SyncScenePlayTeamEntityNotify; + +public class PacketSyncScenePlayTeamEntityNotify extends BasePacket { + + public PacketSyncScenePlayTeamEntityNotify(Player player) { + super(PacketOpcodes.SyncScenePlayTeamEntityNotify); + + SyncScenePlayTeamEntityNotify proto = + SyncScenePlayTeamEntityNotify.newBuilder().setSceneId(player.getSceneId()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSyncTeamEntityNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSyncTeamEntityNotify.java index f24a9b6af..517d663b0 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSyncTeamEntityNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSyncTeamEntityNotify.java @@ -1,38 +1,39 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; -import emu.grasscutter.net.proto.SyncTeamEntityNotifyOuterClass.SyncTeamEntityNotify; -import emu.grasscutter.net.proto.TeamEntityInfoOuterClass.TeamEntityInfo; - -public class PacketSyncTeamEntityNotify extends BasePacket { - - public PacketSyncTeamEntityNotify(Player player) { - super(PacketOpcodes.SyncTeamEntityNotify); - - SyncTeamEntityNotify.Builder proto = SyncTeamEntityNotify.newBuilder() - .setSceneId(player.getSceneId()); - - if (player.getWorld().isMultiplayer()) { - for (Player p : player.getWorld().getPlayers()) { - // Skip if same player - if (player == p) { - continue; - } - - // Set info - TeamEntityInfo info = TeamEntityInfo.newBuilder() - .setTeamEntityId(p.getTeamManager().getEntityId()) - .setAuthorityPeerId(p.getPeerId()) - .setTeamAbilityInfo(AbilitySyncStateInfo.newBuilder()) - .build(); - - proto.addTeamEntityInfoList(info); - } - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; +import emu.grasscutter.net.proto.SyncTeamEntityNotifyOuterClass.SyncTeamEntityNotify; +import emu.grasscutter.net.proto.TeamEntityInfoOuterClass.TeamEntityInfo; + +public class PacketSyncTeamEntityNotify extends BasePacket { + + public PacketSyncTeamEntityNotify(Player player) { + super(PacketOpcodes.SyncTeamEntityNotify); + + SyncTeamEntityNotify.Builder proto = + SyncTeamEntityNotify.newBuilder().setSceneId(player.getSceneId()); + + if (player.getWorld().isMultiplayer()) { + for (Player p : player.getWorld().getPlayers()) { + // Skip if same player + if (player == p) { + continue; + } + + // Set info + TeamEntityInfo info = + TeamEntityInfo.newBuilder() + .setTeamEntityId(p.getTeamManager().getEntityId()) + .setAuthorityPeerId(p.getPeerId()) + .setTeamAbilityInfo(AbilitySyncStateInfo.newBuilder()) + .build(); + + proto.addTeamEntityInfoList(info); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementGoalRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementGoalRewardRsp.java index f70535b2e..7fb2e8a90 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementGoalRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementGoalRewardRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.TakeAchievementGoalRewardRspOuterClass; - -import java.util.List; - -public class PacketTakeAchievementGoalRewardRsp extends BasePacket { - public PacketTakeAchievementGoalRewardRsp() { - super(PacketOpcodes.TakeAchievementGoalRewardRsp); - this.setData(TakeAchievementGoalRewardRspOuterClass.TakeAchievementGoalRewardRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_REWARD_HAS_TAKEN_VALUE) - .build()); - } - - public PacketTakeAchievementGoalRewardRsp(List ids, List items) { - super(PacketOpcodes.TakeAchievementGoalRewardRsp); - - var rsp = TakeAchievementGoalRewardRspOuterClass.TakeAchievementGoalRewardRsp.newBuilder() - .addAllIdList(ids) - .addAllItemList(items) - .build(); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.TakeAchievementGoalRewardRspOuterClass; +import java.util.List; + +public class PacketTakeAchievementGoalRewardRsp extends BasePacket { + public PacketTakeAchievementGoalRewardRsp() { + super(PacketOpcodes.TakeAchievementGoalRewardRsp); + this.setData( + TakeAchievementGoalRewardRspOuterClass.TakeAchievementGoalRewardRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_REWARD_HAS_TAKEN_VALUE) + .build()); + } + + public PacketTakeAchievementGoalRewardRsp( + List ids, List items) { + super(PacketOpcodes.TakeAchievementGoalRewardRsp); + + var rsp = + TakeAchievementGoalRewardRspOuterClass.TakeAchievementGoalRewardRsp.newBuilder() + .addAllIdList(ids) + .addAllItemList(items) + .build(); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardReq.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardReq.java index 02f879622..a49bdd347 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardReq.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeAchievementRewardReqOuterClass.TakeAchievementRewardReq; -import emu.grasscutter.server.game.GameSession; - -public class PacketTakeAchievementRewardReq extends BasePacket { - - public PacketTakeAchievementRewardReq(GameSession session) { - super(PacketOpcodes.TakeAchievementRewardReq); - - TakeAchievementRewardReq proto = TakeAchievementRewardReq.newBuilder().build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeAchievementRewardReqOuterClass.TakeAchievementRewardReq; +import emu.grasscutter.server.game.GameSession; + +public class PacketTakeAchievementRewardReq extends BasePacket { + + public PacketTakeAchievementRewardReq(GameSession session) { + super(PacketOpcodes.TakeAchievementRewardReq); + + TakeAchievementRewardReq proto = TakeAchievementRewardReq.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardRsp.java index 54f9b7664..651a70579 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeAchievementRewardRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.TakeAchievementRewardRspOuterClass; - -import java.util.List; - -public class PacketTakeAchievementRewardRsp extends BasePacket { - public PacketTakeAchievementRewardRsp() { - super(PacketOpcodes.TakeAchievementRewardRsp); - this.setData(TakeAchievementRewardRspOuterClass.TakeAchievementRewardRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_REWARD_HAS_TAKEN_VALUE) - .build()); - } - - public PacketTakeAchievementRewardRsp(List idList, List items) { - super(PacketOpcodes.TakeAchievementRewardRsp); - - var rsp = TakeAchievementRewardRspOuterClass.TakeAchievementRewardRsp.newBuilder() - .addAllIdList(idList) - .addAllItemList(items) - .build(); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.TakeAchievementRewardRspOuterClass; +import java.util.List; + +public class PacketTakeAchievementRewardRsp extends BasePacket { + public PacketTakeAchievementRewardRsp() { + super(PacketOpcodes.TakeAchievementRewardRsp); + this.setData( + TakeAchievementRewardRspOuterClass.TakeAchievementRewardRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_REWARD_HAS_TAKEN_VALUE) + .build()); + } + + public PacketTakeAchievementRewardRsp( + List idList, List items) { + super(PacketOpcodes.TakeAchievementRewardRsp); + + var rsp = + TakeAchievementRewardRspOuterClass.TakeAchievementRewardRsp.newBuilder() + .addAllIdList(idList) + .addAllItemList(items) + .build(); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassMissionPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassMissionPointRsp.java index faeefd7de..d1d6d52e3 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassMissionPointRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassMissionPointRsp.java @@ -1,10 +1,10 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; - -public class PacketTakeBattlePassMissionPointRsp extends BasePacket { - public PacketTakeBattlePassMissionPointRsp() { - super(PacketOpcodes.TakeBattlePassMissionPointRsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; + +public class PacketTakeBattlePassMissionPointRsp extends BasePacket { + public PacketTakeBattlePassMissionPointRsp() { + super(PacketOpcodes.TakeBattlePassMissionPointRsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java index 2c2df0137..2340e32ab 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java @@ -1,27 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.TakeBattlePassRewardRspOuterClass.TakeBattlePassRewardRsp; - -import java.util.List; - -public class PacketTakeBattlePassRewardRsp extends BasePacket { - public PacketTakeBattlePassRewardRsp(List takeOptionList, List rewardItems) { - super(PacketOpcodes.TakeBattlePassRewardRsp); - - var proto = TakeBattlePassRewardRsp.newBuilder() - .addAllTakeOptionList(takeOptionList); - - if (rewardItems != null) { - for (var item : rewardItems) { - proto.addItemList(ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount())); - } - } - - setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.TakeBattlePassRewardRspOuterClass.TakeBattlePassRewardRsp; +import java.util.List; + +public class PacketTakeBattlePassRewardRsp extends BasePacket { + public PacketTakeBattlePassRewardRsp( + List takeOptionList, List rewardItems) { + super(PacketOpcodes.TakeBattlePassRewardRsp); + + var proto = TakeBattlePassRewardRsp.newBuilder().addAllTakeOptionList(takeOptionList); + + if (rewardItems != null) { + for (var item : rewardItems) { + proto.addItemList( + ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount())); + } + } + + setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java index 27b1a3c6b..ecb1aa8ca 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeFurnitureMakeRsp.java @@ -1,37 +1,37 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; -import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.TakeFurnitureMakeRspOuterClass; - -import java.util.List; - -public class PacketTakeFurnitureMakeRsp extends BasePacket { - - public PacketTakeFurnitureMakeRsp(int ret, - int makeId, - List output, - List others) { - super(PacketOpcodes.TakeFurnitureMakeRsp); - - var proto = TakeFurnitureMakeRspOuterClass.TakeFurnitureMakeRsp.newBuilder(); - - proto.setRetcode(ret) - .setMakeId(makeId); - - if (output != null) { - proto.addAllOutputItemList(output); - } - - if (others != null) { - proto.setFurnitureMakeSlot(FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() - .addAllFurnitureMakeDataList(others) - .build()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FurnitureMakeDataOuterClass; +import emu.grasscutter.net.proto.FurnitureMakeSlotOuterClass; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.TakeFurnitureMakeRspOuterClass; +import java.util.List; + +public class PacketTakeFurnitureMakeRsp extends BasePacket { + + public PacketTakeFurnitureMakeRsp( + int ret, + int makeId, + List output, + List others) { + super(PacketOpcodes.TakeFurnitureMakeRsp); + + var proto = TakeFurnitureMakeRspOuterClass.TakeFurnitureMakeRsp.newBuilder(); + + proto.setRetcode(ret).setMakeId(makeId); + + if (output != null) { + proto.addAllOutputItemList(output); + } + + if (others != null) { + proto.setFurnitureMakeSlot( + FurnitureMakeSlotOuterClass.FurnitureMakeSlot.newBuilder() + .addAllFurnitureMakeDataList(others) + .build()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakePlayerLevelRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakePlayerLevelRewardRsp.java index 685f315b6..98754094e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakePlayerLevelRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakePlayerLevelRewardRsp.java @@ -1,26 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakePlayerLevelRewardRspOuterClass.TakePlayerLevelRewardRsp; - -public class PacketTakePlayerLevelRewardRsp extends BasePacket { - - public PacketTakePlayerLevelRewardRsp(int level, int rewardId) { - super(PacketOpcodes.TakePlayerLevelRewardRsp); - - int retcode = 0; - - if (rewardId == 0) { - retcode = 1; - } - - TakePlayerLevelRewardRsp proto = TakePlayerLevelRewardRsp.newBuilder() - .setLevel(level) - .setRewardId(rewardId) - .setRetcode(retcode) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakePlayerLevelRewardRspOuterClass.TakePlayerLevelRewardRsp; + +public class PacketTakePlayerLevelRewardRsp extends BasePacket { + + public PacketTakePlayerLevelRewardRsp(int level, int rewardId) { + super(PacketOpcodes.TakePlayerLevelRewardRsp); + + int retcode = 0; + + if (rewardId == 0) { + retcode = 1; + } + + TakePlayerLevelRewardRsp proto = + TakePlayerLevelRewardRsp.newBuilder() + .setLevel(level) + .setRewardId(rewardId) + .setRetcode(retcode) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeoffEquipRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeoffEquipRsp.java index f2562ed9c..69285b537 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeoffEquipRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeoffEquipRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TakeoffEquipRspOuterClass.TakeoffEquipRsp; - -public class PacketTakeoffEquipRsp extends BasePacket { - - public PacketTakeoffEquipRsp(long avatarGuid, int slot) { - super(PacketOpcodes.TakeoffEquipRsp); - - TakeoffEquipRsp proto = TakeoffEquipRsp.newBuilder() - .setAvatarGuid(avatarGuid) - .setSlot(slot) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TakeoffEquipRspOuterClass.TakeoffEquipRsp; + +public class PacketTakeoffEquipRsp extends BasePacket { + + public PacketTakeoffEquipRsp(long avatarGuid, int slot) { + super(PacketOpcodes.TakeoffEquipRsp); + + TakeoffEquipRsp proto = + TakeoffEquipRsp.newBuilder().setAvatarGuid(avatarGuid).setSlot(slot).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java index 9d098e35f..6702a7173 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java @@ -1,64 +1,74 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.tower.TowerManager; -import emu.grasscutter.game.tower.TowerSystem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerAllDataRspOuterClass.TowerAllDataRsp; -import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; -import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; -import emu.grasscutter.net.proto.TowerLevelRecordOuterClass; -import emu.grasscutter.utils.DateHelper; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class PacketTowerAllDataRsp extends BasePacket { - - public PacketTowerAllDataRsp(TowerSystem towerScheduleManager, TowerManager towerManager) { - super(PacketOpcodes.TowerAllDataRsp); - - var recordList = towerManager.getRecordMap().values().stream() - .map(rec -> TowerFloorRecord.newBuilder() - .setFloorId(rec.getFloorId()) - .setFloorStarRewardProgress(rec.getFloorStarRewardProgress()) - .putAllPassedLevelMap(rec.getPassedLevelMap()) - .addAllPassedLevelRecordList(buildFromPassedLevelMap(rec.getPassedLevelMap())) - .build() - ) - .toList(); - - var openTimeMap = towerScheduleManager.getScheduleFloors().stream() - .collect(Collectors.toMap(x -> x, - y -> DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() - .getScheduleStartTime())) - ); - - TowerAllDataRsp proto = TowerAllDataRsp.newBuilder() - .setTowerScheduleId(towerScheduleManager.getCurrentTowerScheduleData().getScheduleId()) - .addAllTowerFloorRecordList(recordList) - .setCurLevelRecord(TowerCurLevelRecord.newBuilder().setIsEmpty(true)) - .setScheduleStartTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() - .getScheduleStartTime())) - .setNextScheduleChangeTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() - .getNextScheduleChangeTime())) - .putAllFloorOpenTimeMap(openTimeMap) - .setIsFinishedEntranceFloor(towerManager.canEnterScheduleFloor()) - .build(); - - this.setData(proto); - } - - private List buildFromPassedLevelMap(Map map) { - return map.entrySet().stream() - .map(item -> TowerLevelRecordOuterClass.TowerLevelRecord.newBuilder() - .setLevelId(item.getKey()) - .addAllSatisfiedCondList(IntStream.range(1, item.getValue() + 1).boxed().toList()) - .build()) - .toList(); - - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.tower.TowerManager; +import emu.grasscutter.game.tower.TowerSystem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerAllDataRspOuterClass.TowerAllDataRsp; +import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; +import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; +import emu.grasscutter.net.proto.TowerLevelRecordOuterClass; +import emu.grasscutter.utils.DateHelper; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PacketTowerAllDataRsp extends BasePacket { + + public PacketTowerAllDataRsp(TowerSystem towerScheduleManager, TowerManager towerManager) { + super(PacketOpcodes.TowerAllDataRsp); + + var recordList = + towerManager.getRecordMap().values().stream() + .map( + rec -> + TowerFloorRecord.newBuilder() + .setFloorId(rec.getFloorId()) + .setFloorStarRewardProgress(rec.getFloorStarRewardProgress()) + .putAllPassedLevelMap(rec.getPassedLevelMap()) + .addAllPassedLevelRecordList( + buildFromPassedLevelMap(rec.getPassedLevelMap())) + .build()) + .toList(); + + var openTimeMap = + towerScheduleManager.getScheduleFloors().stream() + .collect( + Collectors.toMap( + x -> x, + y -> + DateHelper.getUnixTime( + towerScheduleManager.getTowerScheduleConfig().getScheduleStartTime()))); + + TowerAllDataRsp proto = + TowerAllDataRsp.newBuilder() + .setTowerScheduleId(towerScheduleManager.getCurrentTowerScheduleData().getScheduleId()) + .addAllTowerFloorRecordList(recordList) + .setCurLevelRecord(TowerCurLevelRecord.newBuilder().setIsEmpty(true)) + .setScheduleStartTime( + DateHelper.getUnixTime( + towerScheduleManager.getTowerScheduleConfig().getScheduleStartTime())) + .setNextScheduleChangeTime( + DateHelper.getUnixTime( + towerScheduleManager.getTowerScheduleConfig().getNextScheduleChangeTime())) + .putAllFloorOpenTimeMap(openTimeMap) + .setIsFinishedEntranceFloor(towerManager.canEnterScheduleFloor()) + .build(); + + this.setData(proto); + } + + private List buildFromPassedLevelMap( + Map map) { + return map.entrySet().stream() + .map( + item -> + TowerLevelRecordOuterClass.TowerLevelRecord.newBuilder() + .setLevelId(item.getKey()) + .addAllSatisfiedCondList( + IntStream.range(1, item.getValue() + 1).boxed().toList()) + .build()) + .toList(); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java index 133e41785..53ed3508e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java @@ -1,23 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerCurLevelRecordChangeNotifyOuterClass.TowerCurLevelRecordChangeNotify; -import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; - -public class PacketTowerCurLevelRecordChangeNotify extends BasePacket { - - public PacketTowerCurLevelRecordChangeNotify(int curFloorId, int curLevelIndex) { - super(PacketOpcodes.TowerCurLevelRecordChangeNotify); - - TowerCurLevelRecordChangeNotify proto = TowerCurLevelRecordChangeNotify.newBuilder() - .setCurLevelRecord(TowerCurLevelRecord.newBuilder() - .setCurFloorId(curFloorId) - .setCurLevelIndex(curLevelIndex) - // TODO team info - .build()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerCurLevelRecordChangeNotifyOuterClass.TowerCurLevelRecordChangeNotify; +import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; + +public class PacketTowerCurLevelRecordChangeNotify extends BasePacket { + + public PacketTowerCurLevelRecordChangeNotify(int curFloorId, int curLevelIndex) { + super(PacketOpcodes.TowerCurLevelRecordChangeNotify); + + TowerCurLevelRecordChangeNotify proto = + TowerCurLevelRecordChangeNotify.newBuilder() + .setCurLevelRecord( + TowerCurLevelRecord.newBuilder() + .setCurFloorId(curFloorId) + .setCurLevelIndex(curLevelIndex) + // TODO team info + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java index a7314cead..eae82e783 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java @@ -1,22 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerEnterLevelRspOuterClass.TowerEnterLevelRsp; - -public class PacketTowerEnterLevelRsp extends BasePacket { - - public PacketTowerEnterLevelRsp(int floorId, int levelIndex) { - super(PacketOpcodes.TowerEnterLevelRsp); - - TowerEnterLevelRsp proto = TowerEnterLevelRsp.newBuilder() - .setFloorId(floorId) - .setLevelIndex(levelIndex) - .addTowerBuffIdList(4) - .addTowerBuffIdList(28) - .addTowerBuffIdList(18) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerEnterLevelRspOuterClass.TowerEnterLevelRsp; + +public class PacketTowerEnterLevelRsp extends BasePacket { + + public PacketTowerEnterLevelRsp(int floorId, int levelIndex) { + super(PacketOpcodes.TowerEnterLevelRsp); + + TowerEnterLevelRsp proto = + TowerEnterLevelRsp.newBuilder() + .setFloorId(floorId) + .setLevelIndex(levelIndex) + .addTowerBuffIdList(4) + .addTowerBuffIdList(28) + .addTowerBuffIdList(18) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java index 10db0cf9a..7b343f7b1 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java @@ -1,30 +1,33 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerFloorRecordChangeNotifyOuterClass.TowerFloorRecordChangeNotify; -import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; -import emu.grasscutter.net.proto.TowerLevelRecordOuterClass.TowerLevelRecord; - -public class PacketTowerFloorRecordChangeNotify extends BasePacket { - - public PacketTowerFloorRecordChangeNotify(int floorId, int stars, boolean canEnterScheduleFloor) { - super(PacketOpcodes.TowerFloorRecordChangeNotify); - - TowerFloorRecordChangeNotify proto = TowerFloorRecordChangeNotify.newBuilder() - .addTowerFloorRecordList(TowerFloorRecord.newBuilder() - .setFloorId(floorId) - .setFloorStarRewardProgress(stars) - .addPassedLevelRecordList(TowerLevelRecord.newBuilder() - .setLevelId(1) - .addSatisfiedCondList(1) - .addSatisfiedCondList(2) - .addSatisfiedCondList(3) - .build()) - .build()) - .setIsFinishedEntranceFloor(canEnterScheduleFloor) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerFloorRecordChangeNotifyOuterClass.TowerFloorRecordChangeNotify; +import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; +import emu.grasscutter.net.proto.TowerLevelRecordOuterClass.TowerLevelRecord; + +public class PacketTowerFloorRecordChangeNotify extends BasePacket { + + public PacketTowerFloorRecordChangeNotify(int floorId, int stars, boolean canEnterScheduleFloor) { + super(PacketOpcodes.TowerFloorRecordChangeNotify); + + TowerFloorRecordChangeNotify proto = + TowerFloorRecordChangeNotify.newBuilder() + .addTowerFloorRecordList( + TowerFloorRecord.newBuilder() + .setFloorId(floorId) + .setFloorStarRewardProgress(stars) + .addPassedLevelRecordList( + TowerLevelRecord.newBuilder() + .setLevelId(1) + .addSatisfiedCondList(1) + .addSatisfiedCondList(2) + .addSatisfiedCondList(3) + .build()) + .build()) + .setIsFinishedEntranceFloor(canEnterScheduleFloor) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java index dd37292e7..f04e5ed70 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java @@ -1,32 +1,33 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerLevelStarCondDataOuterClass.TowerLevelStarCondData; -import emu.grasscutter.net.proto.TowerLevelStarCondNotifyOuterClass.TowerLevelStarCondNotify; - -public class PacketTowerLevelStarCondNotify extends BasePacket { - - public PacketTowerLevelStarCondNotify(int floorId, int levelIndex) { - super(PacketOpcodes.TowerLevelStarCondNotify); - - TowerLevelStarCondNotify proto = TowerLevelStarCondNotify.newBuilder() - .setFloorId(floorId) - .setLevelIndex(levelIndex) - .addCondDataList(TowerLevelStarCondData.newBuilder() - //.setCondValue(1) - .build() - ) - .addCondDataList(TowerLevelStarCondData.newBuilder() - //.setCondValue(2) - .build() - ) - .addCondDataList(TowerLevelStarCondData.newBuilder() - //.setCondValue(3) - .build() - ) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerLevelStarCondDataOuterClass.TowerLevelStarCondData; +import emu.grasscutter.net.proto.TowerLevelStarCondNotifyOuterClass.TowerLevelStarCondNotify; + +public class PacketTowerLevelStarCondNotify extends BasePacket { + + public PacketTowerLevelStarCondNotify(int floorId, int levelIndex) { + super(PacketOpcodes.TowerLevelStarCondNotify); + + TowerLevelStarCondNotify proto = + TowerLevelStarCondNotify.newBuilder() + .setFloorId(floorId) + .setLevelIndex(levelIndex) + .addCondDataList( + TowerLevelStarCondData.newBuilder() + // .setCondValue(1) + .build()) + .addCondDataList( + TowerLevelStarCondData.newBuilder() + // .setCondValue(2) + .build()) + .addCondDataList( + TowerLevelStarCondData.newBuilder() + // .setCondValue(3) + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java index d6c08ef1f..c20bd1ad5 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerMiddleLevelChangeTeamNotifyOuterClass; - -public class PacketTowerMiddleLevelChangeTeamNotify extends BasePacket { - - public PacketTowerMiddleLevelChangeTeamNotify() { - super(PacketOpcodes.TowerMiddleLevelChangeTeamNotify); - - TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify proto = - TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify.newBuilder() - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerMiddleLevelChangeTeamNotifyOuterClass; + +public class PacketTowerMiddleLevelChangeTeamNotify extends BasePacket { + + public PacketTowerMiddleLevelChangeTeamNotify() { + super(PacketOpcodes.TowerMiddleLevelChangeTeamNotify); + + TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify proto = + TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify.newBuilder() + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java index 49bf824db..93ab0a16d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java @@ -1,17 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.TowerTeamSelectRspOuterClass.TowerTeamSelectRsp; - -public class PacketTowerTeamSelectRsp extends BasePacket { - - public PacketTowerTeamSelectRsp() { - super(PacketOpcodes.TowerTeamSelectRsp); - - TowerTeamSelectRsp proto = TowerTeamSelectRsp.newBuilder() - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerTeamSelectRspOuterClass.TowerTeamSelectRsp; + +public class PacketTowerTeamSelectRsp extends BasePacket { + + public PacketTowerTeamSelectRsp() { + super(PacketOpcodes.TowerTeamSelectRsp); + + TowerTeamSelectRsp proto = TowerTeamSelectRsp.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java index 2aca6630d..dad190498 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java @@ -1,41 +1,44 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.TryEnterHomeRspOuterClass; - -public class PacketTryEnterHomeRsp extends BasePacket { - - public PacketTryEnterHomeRsp() { - super(PacketOpcodes.TryEnterHomeRsp); - - TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() - .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) - .build(); - - this.setData(proto); - } - - public PacketTryEnterHomeRsp(int uid) { - super(PacketOpcodes.TryEnterHomeRsp); - - TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() - .setRetcode(0) - .setTargetUid(uid) - .build(); - - this.setData(proto); - } - - public PacketTryEnterHomeRsp(int retCode, int uid) { - super(PacketOpcodes.TryEnterHomeRsp); - - TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() - .setRetcode(retCode) - .setTargetUid(uid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.TryEnterHomeRspOuterClass; + +public class PacketTryEnterHomeRsp extends BasePacket { + + public PacketTryEnterHomeRsp() { + super(PacketOpcodes.TryEnterHomeRsp); + + TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = + TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } + + public PacketTryEnterHomeRsp(int uid) { + super(PacketOpcodes.TryEnterHomeRsp); + + TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = + TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() + .setRetcode(0) + .setTargetUid(uid) + .build(); + + this.setData(proto); + } + + public PacketTryEnterHomeRsp(int retCode, int uid) { + super(PacketOpcodes.TryEnterHomeRsp); + + TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = + TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() + .setRetcode(retCode) + .setTargetUid(uid) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockAvatarTalentRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockAvatarTalentRsp.java index d8c613cc9..eb1ddfeea 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockAvatarTalentRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockAvatarTalentRsp.java @@ -1,20 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockAvatarTalentRspOuterClass.UnlockAvatarTalentRsp; - -public class PacketUnlockAvatarTalentRsp extends BasePacket { - - public PacketUnlockAvatarTalentRsp(Avatar avatar, int talentId) { - super(PacketOpcodes.UnlockAvatarTalentRsp); - - UnlockAvatarTalentRsp proto = UnlockAvatarTalentRsp.newBuilder() - .setAvatarGuid(avatar.getGuid()) - .setTalentId(talentId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockAvatarTalentRspOuterClass.UnlockAvatarTalentRsp; + +public class PacketUnlockAvatarTalentRsp extends BasePacket { + + public PacketUnlockAvatarTalentRsp(Avatar avatar, int talentId) { + super(PacketOpcodes.UnlockAvatarTalentRsp); + + UnlockAvatarTalentRsp proto = + UnlockAvatarTalentRsp.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setTalentId(talentId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockNameCardNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockNameCardNotify.java index c631d169d..f626badec 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockNameCardNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockNameCardNotify.java @@ -1,18 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockNameCardNotifyOuterClass.UnlockNameCardNotify; - -public class PacketUnlockNameCardNotify extends BasePacket { - - public PacketUnlockNameCardNotify(int nameCard) { - super(PacketOpcodes.UnlockNameCardNotify); - - UnlockNameCardNotify proto = UnlockNameCardNotify.newBuilder() - .setNameCardId(nameCard) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockNameCardNotifyOuterClass.UnlockNameCardNotify; + +public class PacketUnlockNameCardNotify extends BasePacket { + + public PacketUnlockNameCardNotify(int nameCard) { + super(PacketOpcodes.UnlockNameCardNotify); + + UnlockNameCardNotify proto = UnlockNameCardNotify.newBuilder().setNameCardId(nameCard).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockPersonalLineRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockPersonalLineRsp.java index 9128d6f09..cd9ca0c88 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockPersonalLineRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockPersonalLineRsp.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockPersonalLineRspOuterClass; - -public class PacketUnlockPersonalLineRsp extends BasePacket { - - public PacketUnlockPersonalLineRsp(int id, int level, int chapterId) { - super(PacketOpcodes.UnlockPersonalLineRsp); - - var proto = UnlockPersonalLineRspOuterClass.UnlockPersonalLineRsp.newBuilder(); - - proto.setPersonalLineId(id) - .setLevel(level) - .setChapterId(chapterId); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockPersonalLineRspOuterClass; + +public class PacketUnlockPersonalLineRsp extends BasePacket { + + public PacketUnlockPersonalLineRsp(int id, int level, int chapterId) { + super(PacketOpcodes.UnlockPersonalLineRsp); + + var proto = UnlockPersonalLineRspOuterClass.UnlockPersonalLineRsp.newBuilder(); + + proto.setPersonalLineId(id).setLevel(level).setChapterId(chapterId); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockTransPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockTransPointRsp.java index 8a07fd1c0..650f678f7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockTransPointRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockTransPointRsp.java @@ -1,18 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; -import emu.grasscutter.net.proto.UnlockTransPointRspOuterClass.UnlockTransPointRsp; - -public class PacketUnlockTransPointRsp extends BasePacket { - public PacketUnlockTransPointRsp(Retcode retcode) { - super(PacketOpcodes.UnlockTransPointRsp); - - UnlockTransPointRsp proto = UnlockTransPointRsp.newBuilder() - .setRetcode(retcode.getNumber()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.net.proto.UnlockTransPointRspOuterClass.UnlockTransPointRsp; + +public class PacketUnlockTransPointRsp extends BasePacket { + public PacketUnlockTransPointRsp(Retcode retcode) { + super(PacketOpcodes.UnlockTransPointRsp); + + UnlockTransPointRsp proto = + UnlockTransPointRsp.newBuilder().setRetcode(retcode.getNumber()).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java index 5e6a3e4e8..285c785ee 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureFormulaDataNotify.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockedFurnitureFormulaDataNotifyOuterClass; - -import java.util.Set; - -public class PacketUnlockedFurnitureFormulaDataNotify extends BasePacket { - - public PacketUnlockedFurnitureFormulaDataNotify(Set unlockList) { - super(PacketOpcodes.UnlockedFurnitureFormulaDataNotify); - - var proto = UnlockedFurnitureFormulaDataNotifyOuterClass.UnlockedFurnitureFormulaDataNotify.newBuilder(); - - proto.addAllFurnitureIdList(unlockList); - proto.setIsAll(true); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockedFurnitureFormulaDataNotifyOuterClass; +import java.util.Set; + +public class PacketUnlockedFurnitureFormulaDataNotify extends BasePacket { + + public PacketUnlockedFurnitureFormulaDataNotify(Set unlockList) { + super(PacketOpcodes.UnlockedFurnitureFormulaDataNotify); + + var proto = + UnlockedFurnitureFormulaDataNotifyOuterClass.UnlockedFurnitureFormulaDataNotify + .newBuilder(); + + proto.addAllFurnitureIdList(unlockList); + proto.setIsAll(true); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java index 496b8b853..93ff73476 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUnlockedFurnitureSuiteDataNotify.java @@ -1,21 +1,21 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UnlockedFurnitureSuiteDataNotifyOuterClass; - -import java.util.Set; - -public class PacketUnlockedFurnitureSuiteDataNotify extends BasePacket { - - public PacketUnlockedFurnitureSuiteDataNotify(Set unlockList) { - super(PacketOpcodes.UnlockedFurnitureSuiteDataNotify); - - var proto = UnlockedFurnitureSuiteDataNotifyOuterClass.UnlockedFurnitureSuiteDataNotify.newBuilder(); - - proto.addAllFurnitureSuiteIdList(unlockList); - proto.setIsAll(true); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UnlockedFurnitureSuiteDataNotifyOuterClass; +import java.util.Set; + +public class PacketUnlockedFurnitureSuiteDataNotify extends BasePacket { + + public PacketUnlockedFurnitureSuiteDataNotify(Set unlockList) { + super(PacketOpcodes.UnlockedFurnitureSuiteDataNotify); + + var proto = + UnlockedFurnitureSuiteDataNotifyOuterClass.UnlockedFurnitureSuiteDataNotify.newBuilder(); + + proto.addAllFurnitureSuiteIdList(unlockList); + proto.setIsAll(true); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowAvatarListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowAvatarListRsp.java index 1e698db25..405aa86a5 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowAvatarListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowAvatarListRsp.java @@ -1,22 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UpdatePlayerShowAvatarListRspOuterClass.UpdatePlayerShowAvatarListRsp; - -import java.util.List; - -public class PacketUpdatePlayerShowAvatarListRsp extends BasePacket { - - public PacketUpdatePlayerShowAvatarListRsp(boolean isShowAvatar, List avatarIds) { - super(PacketOpcodes.UpdatePlayerShowAvatarListRsp); - - UpdatePlayerShowAvatarListRsp proto = UpdatePlayerShowAvatarListRsp.newBuilder() - .setIsShowAvatar(isShowAvatar) - .addAllShowAvatarIdList(avatarIds) - .setRetcode(0) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UpdatePlayerShowAvatarListRspOuterClass.UpdatePlayerShowAvatarListRsp; +import java.util.List; + +public class PacketUpdatePlayerShowAvatarListRsp extends BasePacket { + + public PacketUpdatePlayerShowAvatarListRsp(boolean isShowAvatar, List avatarIds) { + super(PacketOpcodes.UpdatePlayerShowAvatarListRsp); + + UpdatePlayerShowAvatarListRsp proto = + UpdatePlayerShowAvatarListRsp.newBuilder() + .setIsShowAvatar(isShowAvatar) + .addAllShowAvatarIdList(avatarIds) + .setRetcode(0) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowNameCardListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowNameCardListRsp.java index 29f2eb07b..736d39535 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowNameCardListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUpdatePlayerShowNameCardListRsp.java @@ -1,20 +1,20 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.UpdatePlayerShowNameCardListRspOuterClass; - -import java.util.List; - -public class PacketUpdatePlayerShowNameCardListRsp extends BasePacket { - public PacketUpdatePlayerShowNameCardListRsp(List cardIds) { - super(PacketOpcodes.UpdatePlayerShowNameCardListRsp); - - var rsp = UpdatePlayerShowNameCardListRspOuterClass.UpdatePlayerShowNameCardListRsp.newBuilder() - .addAllShowNameCardIdList(cardIds) - .setRetcode(0) - .build(); - - this.setData(rsp); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.UpdatePlayerShowNameCardListRspOuterClass; +import java.util.List; + +public class PacketUpdatePlayerShowNameCardListRsp extends BasePacket { + public PacketUpdatePlayerShowNameCardListRsp(List cardIds) { + super(PacketOpcodes.UpdatePlayerShowNameCardListRsp); + + var rsp = + UpdatePlayerShowNameCardListRspOuterClass.UpdatePlayerShowNameCardListRsp.newBuilder() + .addAllShowNameCardIdList(cardIds) + .setRetcode(0) + .build(); + + this.setData(rsp); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketUseItemRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketUseItemRsp.java index 04c3ba2cd..8841c09cf 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketUseItemRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketUseItemRsp.java @@ -1,30 +1,32 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.RetcodeOuterClass; -import emu.grasscutter.net.proto.UseItemRspOuterClass.UseItemRsp; - -public class PacketUseItemRsp extends BasePacket { - - public PacketUseItemRsp(long targetGuid, GameItem useItem) { - super(PacketOpcodes.UseItemRsp); - - UseItemRsp proto = UseItemRsp.newBuilder() - .setTargetGuid(targetGuid) - .setItemId(useItem.getItemId()) - .setGuid(useItem.getGuid()) - .build(); - - this.setData(proto); - } - - public PacketUseItemRsp() { - super(PacketOpcodes.UseItemRsp); - - UseItemRsp proto = UseItemRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.UseItemRspOuterClass.UseItemRsp; + +public class PacketUseItemRsp extends BasePacket { + + public PacketUseItemRsp(long targetGuid, GameItem useItem) { + super(PacketOpcodes.UseItemRsp); + + UseItemRsp proto = + UseItemRsp.newBuilder() + .setTargetGuid(targetGuid) + .setItemId(useItem.getItemId()) + .setGuid(useItem.getGuid()) + .build(); + + this.setData(proto); + } + + public PacketUseItemRsp() { + super(PacketOpcodes.UseItemRsp); + + UseItemRsp proto = + UseItemRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java index 7cc3cc93c..dcc37b460 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java @@ -1,67 +1,67 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityVehicle; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.VehicleInteractRspOuterClass.VehicleInteractRsp; -import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass.VehicleInteractType; -import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; - -public class PacketVehicleInteractRsp extends BasePacket { - - public PacketVehicleInteractRsp(Player player, int entityId, VehicleInteractType interactType) { - super(PacketOpcodes.VehicleInteractRsp); - VehicleInteractRsp.Builder proto = VehicleInteractRsp.newBuilder(); - - GameEntity vehicle = player.getScene().getEntityById(entityId); - - if (vehicle instanceof EntityVehicle) { - proto.setEntityId(vehicle.getId()); - - VehicleMember vehicleMember = VehicleMember.newBuilder() - .setUid(player.getUid()) - .setAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()) - .build(); - - proto.setInteractType(interactType); - proto.setMember(vehicleMember); - - switch (interactType) { - case VEHICLE_INTERACT_TYPE_IN -> { - ((EntityVehicle) vehicle).getVehicleMembers().add(vehicleMember); - } - case VEHICLE_INTERACT_TYPE_OUT -> { - ((EntityVehicle) vehicle).getVehicleMembers().remove(vehicleMember); - } - default -> { - } - } - } - this.setData(proto.build()); - } - - public PacketVehicleInteractRsp(EntityVehicle vehicle, VehicleMember vehicleMember, VehicleInteractType interactType) { - super(PacketOpcodes.VehicleInteractRsp); - VehicleInteractRsp.Builder proto = VehicleInteractRsp.newBuilder(); - - if (vehicle != null) { - proto.setEntityId(vehicle.getId()); - proto.setInteractType(interactType); - proto.setMember(vehicleMember); - - switch (interactType) { - case VEHICLE_INTERACT_TYPE_IN -> { - vehicle.getVehicleMembers().add(vehicleMember); - } - case VEHICLE_INTERACT_TYPE_OUT -> { - vehicle.getVehicleMembers().remove(vehicleMember); - } - default -> { - } - } - } - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VehicleInteractRspOuterClass.VehicleInteractRsp; +import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass.VehicleInteractType; +import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; + +public class PacketVehicleInteractRsp extends BasePacket { + + public PacketVehicleInteractRsp(Player player, int entityId, VehicleInteractType interactType) { + super(PacketOpcodes.VehicleInteractRsp); + VehicleInteractRsp.Builder proto = VehicleInteractRsp.newBuilder(); + + GameEntity vehicle = player.getScene().getEntityById(entityId); + + if (vehicle instanceof EntityVehicle) { + proto.setEntityId(vehicle.getId()); + + VehicleMember vehicleMember = + VehicleMember.newBuilder() + .setUid(player.getUid()) + .setAvatarGuid(player.getTeamManager().getCurrentCharacterGuid()) + .build(); + + proto.setInteractType(interactType); + proto.setMember(vehicleMember); + + switch (interactType) { + case VEHICLE_INTERACT_TYPE_IN -> { + ((EntityVehicle) vehicle).getVehicleMembers().add(vehicleMember); + } + case VEHICLE_INTERACT_TYPE_OUT -> { + ((EntityVehicle) vehicle).getVehicleMembers().remove(vehicleMember); + } + default -> {} + } + } + this.setData(proto.build()); + } + + public PacketVehicleInteractRsp( + EntityVehicle vehicle, VehicleMember vehicleMember, VehicleInteractType interactType) { + super(PacketOpcodes.VehicleInteractRsp); + VehicleInteractRsp.Builder proto = VehicleInteractRsp.newBuilder(); + + if (vehicle != null) { + proto.setEntityId(vehicle.getId()); + proto.setInteractType(interactType); + proto.setMember(vehicleMember); + + switch (interactType) { + case VEHICLE_INTERACT_TYPE_IN -> { + vehicle.getVehicleMembers().add(vehicleMember); + } + case VEHICLE_INTERACT_TYPE_OUT -> { + vehicle.getVehicleMembers().remove(vehicleMember); + } + default -> {} + } + } + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java index 1510b1cc9..af596dbbd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java @@ -1,18 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.VehicleStaminaNotifyOuterClass.VehicleStaminaNotify; - -public class PacketVehicleStaminaNotify extends BasePacket { - - public PacketVehicleStaminaNotify(int vehicleId, float newStamina) { - super(PacketOpcodes.VehicleStaminaNotify); - VehicleStaminaNotify.Builder proto = VehicleStaminaNotify.newBuilder(); - - proto.setEntityId(vehicleId); - proto.setCurStamina(newStamina); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VehicleStaminaNotifyOuterClass.VehicleStaminaNotify; + +public class PacketVehicleStaminaNotify extends BasePacket { + + public PacketVehicleStaminaNotify(int vehicleId, float newStamina) { + super(PacketOpcodes.VehicleStaminaNotify); + VehicleStaminaNotify.Builder proto = VehicleStaminaNotify.newBuilder(); + + proto.setEntityId(vehicleId); + proto.setCurStamina(newStamina); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponAwakenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponAwakenRsp.java index e8557fb0d..5ef496539 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponAwakenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponAwakenRsp.java @@ -1,29 +1,31 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WeaponAwakenRspOuterClass.WeaponAwakenRsp; - -public class PacketWeaponAwakenRsp extends BasePacket { - - public PacketWeaponAwakenRsp(Avatar avatar, GameItem item, GameItem feedWeapon, int oldRefineLevel) { - super(PacketOpcodes.WeaponAwakenRsp); - - WeaponAwakenRsp.Builder proto = WeaponAwakenRsp.newBuilder() - .setTargetWeaponGuid(item.getGuid()) - .setTargetWeaponAwakenLevel(item.getRefinement()); - - for (int affixId : item.getAffixes()) { - proto.putOldAffixLevelMap(affixId, oldRefineLevel); - proto.putCurAffixLevelMap(affixId, item.getRefinement()); - } - - if (avatar != null) { - proto.setAvatarGuid(avatar.getGuid()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WeaponAwakenRspOuterClass.WeaponAwakenRsp; + +public class PacketWeaponAwakenRsp extends BasePacket { + + public PacketWeaponAwakenRsp( + Avatar avatar, GameItem item, GameItem feedWeapon, int oldRefineLevel) { + super(PacketOpcodes.WeaponAwakenRsp); + + WeaponAwakenRsp.Builder proto = + WeaponAwakenRsp.newBuilder() + .setTargetWeaponGuid(item.getGuid()) + .setTargetWeaponAwakenLevel(item.getRefinement()); + + for (int affixId : item.getAffixes()) { + proto.putOldAffixLevelMap(affixId, oldRefineLevel); + proto.putCurAffixLevelMap(affixId, item.getRefinement()); + } + + if (avatar != null) { + proto.setAvatarGuid(avatar.getGuid()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponPromoteRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponPromoteRsp.java index 6bc17fdca..7ea85b386 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponPromoteRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponPromoteRsp.java @@ -1,21 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WeaponPromoteRspOuterClass.WeaponPromoteRsp; - -public class PacketWeaponPromoteRsp extends BasePacket { - - public PacketWeaponPromoteRsp(GameItem item, int oldPromoteLevel) { - super(PacketOpcodes.WeaponPromoteRsp); - - WeaponPromoteRsp proto = WeaponPromoteRsp.newBuilder() - .setTargetWeaponGuid(item.getGuid()) - .setCurPromoteLevel(item.getPromoteLevel()) - .setOldPromoteLevel(oldPromoteLevel) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WeaponPromoteRspOuterClass.WeaponPromoteRsp; + +public class PacketWeaponPromoteRsp extends BasePacket { + + public PacketWeaponPromoteRsp(GameItem item, int oldPromoteLevel) { + super(PacketOpcodes.WeaponPromoteRsp); + + WeaponPromoteRsp proto = + WeaponPromoteRsp.newBuilder() + .setTargetWeaponGuid(item.getGuid()) + .setCurPromoteLevel(item.getPromoteLevel()) + .setOldPromoteLevel(oldPromoteLevel) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponUpgradeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponUpgradeRsp.java index 5cd301177..4e70f5365 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponUpgradeRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWeaponUpgradeRsp.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.inventory.GameItem; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; -import emu.grasscutter.net.proto.WeaponUpgradeRspOuterClass.WeaponUpgradeRsp; - -import java.util.List; - -public class PacketWeaponUpgradeRsp extends BasePacket { - - public PacketWeaponUpgradeRsp(GameItem item, int oldLevel, List leftoverOres) { - super(PacketOpcodes.WeaponUpgradeRsp); - - WeaponUpgradeRsp proto = WeaponUpgradeRsp.newBuilder() - .setTargetWeaponGuid(item.getGuid()) - .setCurLevel(item.getLevel()) - .setOldLevel(oldLevel) - .addAllItemParamList(leftoverOres) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; +import emu.grasscutter.net.proto.WeaponUpgradeRspOuterClass.WeaponUpgradeRsp; +import java.util.List; + +public class PacketWeaponUpgradeRsp extends BasePacket { + + public PacketWeaponUpgradeRsp(GameItem item, int oldLevel, List leftoverOres) { + super(PacketOpcodes.WeaponUpgradeRsp); + + WeaponUpgradeRsp proto = + WeaponUpgradeRsp.newBuilder() + .setTargetWeaponGuid(item.getGuid()) + .setCurLevel(item.getLevel()) + .setOldLevel(oldLevel) + .addAllItemParamList(leftoverOres) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWearEquipRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWearEquipRsp.java index 0a208716f..49adfaa11 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWearEquipRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWearEquipRsp.java @@ -1,19 +1,17 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WearEquipRspOuterClass.WearEquipRsp; - -public class PacketWearEquipRsp extends BasePacket { - - public PacketWearEquipRsp(long avatarGuid, long equipGuid) { - super(PacketOpcodes.WearEquipRsp); - - WearEquipRsp proto = WearEquipRsp.newBuilder() - .setAvatarGuid(avatarGuid) - .setEquipGuid(equipGuid) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WearEquipRspOuterClass.WearEquipRsp; + +public class PacketWearEquipRsp extends BasePacket { + + public PacketWearEquipRsp(long avatarGuid, long equipGuid) { + super(PacketOpcodes.WearEquipRsp); + + WearEquipRsp proto = + WearEquipRsp.newBuilder().setAvatarGuid(avatarGuid).setEquipGuid(equipGuid).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java index 7042236cd..407e7c398 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WidgetCoolDownDataOuterClass; -import emu.grasscutter.net.proto.WidgetCoolDownNotifyOuterClass; - -public class PacketWidgetCoolDownNotify extends BasePacket { - - public PacketWidgetCoolDownNotify(int id, long coolDownTime, boolean isSuccess) { - super(PacketOpcodes.WidgetCoolDownNotify); - - WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify proto = WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify.newBuilder() - .addGroupCoolDownDataList( - WidgetCoolDownDataOuterClass.WidgetCoolDownData.newBuilder() - .setId(id) - .setCoolDownTime(coolDownTime) - .setIsSuccess(isSuccess) - .build() - ) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetCoolDownDataOuterClass; +import emu.grasscutter.net.proto.WidgetCoolDownNotifyOuterClass; + +public class PacketWidgetCoolDownNotify extends BasePacket { + + public PacketWidgetCoolDownNotify(int id, long coolDownTime, boolean isSuccess) { + super(PacketOpcodes.WidgetCoolDownNotify); + + WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify proto = + WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify.newBuilder() + .addGroupCoolDownDataList( + WidgetCoolDownDataOuterClass.WidgetCoolDownData.newBuilder() + .setId(id) + .setCoolDownTime(coolDownTime) + .setIsSuccess(isSuccess) + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java index e48ad8602..37f74ade2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java @@ -1,28 +1,29 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WidgetDoBagRspOuterClass; - -public class PacketWidgetDoBagRsp extends BasePacket { - - public PacketWidgetDoBagRsp(int materialId) { - super(PacketOpcodes.WidgetDoBagRsp); - - WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder() - .setMaterialId(materialId) - .setRetcode(0) - .build(); - - this.setData(proto); - } - - public PacketWidgetDoBagRsp() { - super(PacketOpcodes.WidgetDoBagRsp); - - WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder() - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetDoBagRspOuterClass; + +public class PacketWidgetDoBagRsp extends BasePacket { + + public PacketWidgetDoBagRsp(int materialId) { + super(PacketOpcodes.WidgetDoBagRsp); + + WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = + WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder() + .setMaterialId(materialId) + .setRetcode(0) + .build(); + + this.setData(proto); + } + + public PacketWidgetDoBagRsp() { + super(PacketOpcodes.WidgetDoBagRsp); + + WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = + WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java index 88a66a981..bef05ba6c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java @@ -1,42 +1,42 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WidgetGadgetDataNotifyOuterClass; -import emu.grasscutter.net.proto.WidgetGadgetDataOuterClass; - -import java.io.IOException; -import java.util.List; - -public class PacketWidgetGadgetDataNotify extends BasePacket { - - public PacketWidgetGadgetDataNotify(int gadgetId, List gadgetEntityIdList) throws IOException { - super(PacketOpcodes.WidgetGadgetDataNotify); - - WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify proto = WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify.newBuilder() - .setWidgetGadgetData( - WidgetGadgetDataOuterClass.WidgetGadgetData.newBuilder() - .setGadgetId(gadgetId) - .addAllGadgetEntityIdList(gadgetEntityIdList) - .build() - ) - .build(); - - this.setData(proto); - } - - public PacketWidgetGadgetDataNotify(int gadgetId, int gadgetEntityIdList) throws IOException { - super(PacketOpcodes.WidgetGadgetDataNotify); - - WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify proto = WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify.newBuilder() - .setWidgetGadgetData( - WidgetGadgetDataOuterClass.WidgetGadgetData.newBuilder() - .setGadgetId(gadgetId) - .addGadgetEntityIdList(gadgetEntityIdList) - .build() - ) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetGadgetDataNotifyOuterClass; +import emu.grasscutter.net.proto.WidgetGadgetDataOuterClass; +import java.io.IOException; +import java.util.List; + +public class PacketWidgetGadgetDataNotify extends BasePacket { + + public PacketWidgetGadgetDataNotify(int gadgetId, List gadgetEntityIdList) + throws IOException { + super(PacketOpcodes.WidgetGadgetDataNotify); + + WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify proto = + WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify.newBuilder() + .setWidgetGadgetData( + WidgetGadgetDataOuterClass.WidgetGadgetData.newBuilder() + .setGadgetId(gadgetId) + .addAllGadgetEntityIdList(gadgetEntityIdList) + .build()) + .build(); + + this.setData(proto); + } + + public PacketWidgetGadgetDataNotify(int gadgetId, int gadgetEntityIdList) throws IOException { + super(PacketOpcodes.WidgetGadgetDataNotify); + + WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify proto = + WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify.newBuilder() + .setWidgetGadgetData( + WidgetGadgetDataOuterClass.WidgetGadgetData.newBuilder() + .setGadgetId(gadgetId) + .addGadgetEntityIdList(gadgetEntityIdList) + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java index a2fef29b9..8448b288c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java @@ -1,47 +1,44 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WidgetSlotChangeNotifyOuterClass; -import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; -import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; - -public class PacketWidgetSlotChangeNotify extends BasePacket { - - public PacketWidgetSlotChangeNotify(WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto) { - super(PacketOpcodes.WidgetSlotChangeNotify); - - this.setData(proto); - } - - public PacketWidgetSlotChangeNotify(WidgetSlotOpOuterClass.WidgetSlotOp op) { - super(PacketOpcodes.WidgetSlotChangeNotify); - - WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() - .setOp(op) - .setSlot( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setIsActive(true) - .build() - ) - .build(); - - this.setData(proto); - } - - public PacketWidgetSlotChangeNotify(int materialId) { - super(PacketOpcodes.WidgetSlotChangeNotify); - - WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() - .setSlot( - WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() - .setIsActive(true) - .setMaterialId(materialId) - .build() - ) - .build(); - - this.setData(proto); - } - -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetSlotChangeNotifyOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; + +public class PacketWidgetSlotChangeNotify extends BasePacket { + + public PacketWidgetSlotChangeNotify( + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + this.setData(proto); + } + + public PacketWidgetSlotChangeNotify(WidgetSlotOpOuterClass.WidgetSlotOp op) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() + .setOp(op) + .setSlot(WidgetSlotDataOuterClass.WidgetSlotData.newBuilder().setIsActive(true).build()) + .build(); + + this.setData(proto); + } + + public PacketWidgetSlotChangeNotify(int materialId) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() + .setSlot( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(materialId) + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorktopOptionNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorktopOptionNotify.java index c2e032b0c..06762a0e7 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorktopOptionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorktopOptionNotify.java @@ -1,23 +1,23 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.gadget.GadgetWorktop; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WorktopOptionNotifyOuterClass.WorktopOptionNotify; - -public class PacketWorktopOptionNotify extends BasePacket { - - public PacketWorktopOptionNotify(EntityGadget gadget) { - super(PacketOpcodes.WorktopOptionNotify); - - WorktopOptionNotify.Builder proto = WorktopOptionNotify.newBuilder() - .setGadgetEntityId(gadget.getId()); - - if (gadget.getContent() instanceof GadgetWorktop worktop) { - proto.addAllOptionList(worktop.getWorktopOptions()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.EntityGadget; +import emu.grasscutter.game.entity.gadget.GadgetWorktop; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WorktopOptionNotifyOuterClass.WorktopOptionNotify; + +public class PacketWorktopOptionNotify extends BasePacket { + + public PacketWorktopOptionNotify(EntityGadget gadget) { + super(PacketOpcodes.WorktopOptionNotify); + + WorktopOptionNotify.Builder proto = + WorktopOptionNotify.newBuilder().setGadgetEntityId(gadget.getId()); + + if (gadget.getContent() instanceof GadgetWorktop worktop) { + proto.addAllOptionList(worktop.getWorktopOptions()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldDataNotify.java index f05aa2937..176844954 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldDataNotify.java @@ -1,24 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; -import emu.grasscutter.net.proto.WorldDataNotifyOuterClass.WorldDataNotify; - -public class PacketWorldDataNotify extends BasePacket { - - public PacketWorldDataNotify(World world) { - super(PacketOpcodes.WorldDataNotify); - - int worldLevel = world.getWorldLevel(); - int isMp = world.isMultiplayer() ? 1 : 0; - - WorldDataNotify proto = WorldDataNotify.newBuilder() - .putWorldPropMap(1, PropValue.newBuilder().setType(1).setIval(worldLevel).setVal(worldLevel).build()) - .putWorldPropMap(2, PropValue.newBuilder().setType(2).setIval(isMp).setVal(isMp).build()) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; +import emu.grasscutter.net.proto.WorldDataNotifyOuterClass.WorldDataNotify; + +public class PacketWorldDataNotify extends BasePacket { + + public PacketWorldDataNotify(World world) { + super(PacketOpcodes.WorldDataNotify); + + int worldLevel = world.getWorldLevel(); + int isMp = world.isMultiplayer() ? 1 : 0; + + WorldDataNotify proto = + WorldDataNotify.newBuilder() + .putWorldPropMap( + 1, PropValue.newBuilder().setType(1).setIval(worldLevel).setVal(worldLevel).build()) + .putWorldPropMap( + 2, PropValue.newBuilder().setType(2).setIval(isMp).setVal(isMp).build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerDieNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerDieNotify.java index aeead50ea..1ed6935f2 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerDieNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerDieNotify.java @@ -1,20 +1,18 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.net.proto.WorldPlayerDieNotifyOuterClass.WorldPlayerDieNotify; - -public class PacketWorldPlayerDieNotify extends BasePacket { - - public PacketWorldPlayerDieNotify(PlayerDieType playerDieType, int killerId) { - super(PacketOpcodes.WorldPlayerDieNotify); - - WorldPlayerDieNotify proto = WorldPlayerDieNotify.newBuilder() - .setDieType(playerDieType) - .setMonsterId(killerId) - .build(); - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; +import emu.grasscutter.net.proto.WorldPlayerDieNotifyOuterClass.WorldPlayerDieNotify; + +public class PacketWorldPlayerDieNotify extends BasePacket { + + public PacketWorldPlayerDieNotify(PlayerDieType playerDieType, int killerId) { + super(PacketOpcodes.WorldPlayerDieNotify); + + WorldPlayerDieNotify proto = + WorldPlayerDieNotify.newBuilder().setDieType(playerDieType).setMonsterId(killerId).build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerInfoNotify.java index a1e44e8b3..40357fe0c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerInfoNotify.java @@ -1,25 +1,25 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WorldPlayerInfoNotifyOuterClass.WorldPlayerInfoNotify; - -public class PacketWorldPlayerInfoNotify extends BasePacket { - - public PacketWorldPlayerInfoNotify(World world) { - super(PacketOpcodes.WorldPlayerInfoNotify); - - WorldPlayerInfoNotify.Builder proto = WorldPlayerInfoNotify.newBuilder(); - - for (int i = 0; i < world.getPlayers().size(); i++) { - Player p = world.getPlayers().get(i); - - proto.addPlayerInfoList(p.getOnlinePlayerInfo()); - proto.addPlayerUidList(p.getUid()); - } - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WorldPlayerInfoNotifyOuterClass.WorldPlayerInfoNotify; + +public class PacketWorldPlayerInfoNotify extends BasePacket { + + public PacketWorldPlayerInfoNotify(World world) { + super(PacketOpcodes.WorldPlayerInfoNotify); + + WorldPlayerInfoNotify.Builder proto = WorldPlayerInfoNotify.newBuilder(); + + for (int i = 0; i < world.getPlayers().size(); i++) { + Player p = world.getPlayers().get(i); + + proto.addPlayerInfoList(p.getOnlinePlayerInfo()); + proto.addPlayerUidList(p.getUid()); + } + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java index 25d8b673f..96b91c685 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java @@ -1,22 +1,22 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WorldPlayerLocationNotifyOuterClass.WorldPlayerLocationNotify; - -public class PacketWorldPlayerLocationNotify extends BasePacket { - - public PacketWorldPlayerLocationNotify(World world) { - super(PacketOpcodes.WorldPlayerLocationNotify); - - WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder(); - - for (Player p : world.getPlayers()) { - proto.addPlayerWorldLocList(p.getWorldPlayerLocationInfo()); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WorldPlayerLocationNotifyOuterClass.WorldPlayerLocationNotify; + +public class PacketWorldPlayerLocationNotify extends BasePacket { + + public PacketWorldPlayerLocationNotify(World world) { + super(PacketOpcodes.WorldPlayerLocationNotify); + + WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder(); + + for (Player p : world.getPlayers()) { + proto.addPlayerWorldLocList(p.getWorldPlayerLocationInfo()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerRTTNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerRTTNotify.java index 238b80f8b..c7ef9b18c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerRTTNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerRTTNotify.java @@ -1,27 +1,27 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.PlayerRTTInfoOuterClass.PlayerRTTInfo; -import emu.grasscutter.net.proto.WorldPlayerRTTNotifyOuterClass.WorldPlayerRTTNotify; - -public class PacketWorldPlayerRTTNotify extends BasePacket { - - public PacketWorldPlayerRTTNotify(World world) { - super(PacketOpcodes.WorldPlayerRTTNotify); - - WorldPlayerRTTNotify.Builder proto = WorldPlayerRTTNotify.newBuilder(); - - for (Player player : world.getPlayers()) { - proto.addPlayerRttList( - PlayerRTTInfo.newBuilder() - .setUid(player.getUid()) - .setRtt(10) // TODO - put player ping here - ); - } - - this.setData(proto); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.World; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerRTTInfoOuterClass.PlayerRTTInfo; +import emu.grasscutter.net.proto.WorldPlayerRTTNotifyOuterClass.WorldPlayerRTTNotify; + +public class PacketWorldPlayerRTTNotify extends BasePacket { + + public PacketWorldPlayerRTTNotify(World world) { + super(PacketOpcodes.WorldPlayerRTTNotify); + + WorldPlayerRTTNotify.Builder proto = WorldPlayerRTTNotify.newBuilder(); + + for (Player player : world.getPlayers()) { + proto.addPlayerRttList( + PlayerRTTInfo.newBuilder() + .setUid(player.getUid()) + .setRtt(10) // TODO - put player ping here + ); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerReviveRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerReviveRsp.java index 4c57f3f13..0621ba10f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerReviveRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerReviveRsp.java @@ -1,16 +1,16 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.WorldPlayerReviveRspOuterClass.WorldPlayerReviveRsp; - -public class PacketWorldPlayerReviveRsp extends BasePacket { - - public PacketWorldPlayerReviveRsp() { - super(PacketOpcodes.WorldPlayerReviveRsp); - - WorldPlayerReviveRsp.Builder proto = WorldPlayerReviveRsp.newBuilder(); - - this.setData(proto.build()); - } -} +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WorldPlayerReviveRspOuterClass.WorldPlayerReviveRsp; + +public class PacketWorldPlayerReviveRsp extends BasePacket { + + public PacketWorldPlayerReviveRsp() { + super(PacketOpcodes.WorldPlayerReviveRsp); + + WorldPlayerReviveRsp.Builder proto = WorldPlayerReviveRsp.newBuilder(); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/scheduler/AsyncServerTask.java b/src/main/java/emu/grasscutter/server/scheduler/AsyncServerTask.java index c4149de6e..7d4929801 100644 --- a/src/main/java/emu/grasscutter/server/scheduler/AsyncServerTask.java +++ b/src/main/java/emu/grasscutter/server/scheduler/AsyncServerTask.java @@ -1,109 +1,97 @@ -package emu.grasscutter.server.scheduler; - -import lombok.Getter; - -import javax.annotation.Nullable; - -/** - * A server task that should be run asynchronously. - */ -public final class AsyncServerTask implements Runnable { - /* The runnable to run. */ - private final Runnable task; - /* This ID is assigned by the scheduler. */ - @Getter - private final int taskId; - /* The result callback to run. */ - @Nullable - private final Runnable callback; - - /* Has the task already been started? */ - private boolean started = false; - /* Has the task finished execution? */ - private boolean finished = false; - /* The result produced in the async task. */ - @Nullable - private Object result = null; - - /** - * For tasks without a callback. - * - * @param task The task to run. - */ - public AsyncServerTask(Runnable task, int taskId) { - this(task, null, taskId); - } - - /** - * For tasks with a callback. - * - * @param task The task to run. - * @param callback The task to run after the task is complete. - */ - public AsyncServerTask(Runnable task, @Nullable Runnable callback, int taskId) { - this.task = task; - this.callback = callback; - this.taskId = taskId; - } - - /** - * Returns the state of the task. - * - * @return True if the task has been started, false otherwise. - */ - public boolean hasStarted() { - return this.started; - } - - /** - * Returns the state of the task. - * - * @return True if the task has finished execution, false otherwise. - */ - public boolean isFinished() { - return this.finished; - } - - /** - * Runs the task. - */ - @Override - public void run() { - // Declare the task as started. - this.started = true; - - // Run the runnable. - this.task.run(); - - // Declare the task as finished. - this.finished = true; - } - - /** - * Runs the callback. - */ - public void complete() { - // Run the callback. - if (this.callback != null) - this.callback.run(); - } - - /** - * Returns the set result of the async task. - * - * @return The result, or null if it has not been set. - */ - @Nullable - public Object getResult() { - return this.result; - } - - /** - * Sets the result of the async task. - * - * @param result The result of the async task. - */ - public void setResult(@Nullable Object result) { - this.result = result; - } -} +package emu.grasscutter.server.scheduler; + +import javax.annotation.Nullable; +import lombok.Getter; + +/** A server task that should be run asynchronously. */ +public final class AsyncServerTask implements Runnable { + /* The runnable to run. */ + private final Runnable task; + /* This ID is assigned by the scheduler. */ + @Getter private final int taskId; + /* The result callback to run. */ + @Nullable private final Runnable callback; + + /* Has the task already been started? */ + private boolean started = false; + /* Has the task finished execution? */ + private boolean finished = false; + /* The result produced in the async task. */ + @Nullable private Object result = null; + + /** + * For tasks without a callback. + * + * @param task The task to run. + */ + public AsyncServerTask(Runnable task, int taskId) { + this(task, null, taskId); + } + + /** + * For tasks with a callback. + * + * @param task The task to run. + * @param callback The task to run after the task is complete. + */ + public AsyncServerTask(Runnable task, @Nullable Runnable callback, int taskId) { + this.task = task; + this.callback = callback; + this.taskId = taskId; + } + + /** + * Returns the state of the task. + * + * @return True if the task has been started, false otherwise. + */ + public boolean hasStarted() { + return this.started; + } + + /** + * Returns the state of the task. + * + * @return True if the task has finished execution, false otherwise. + */ + public boolean isFinished() { + return this.finished; + } + + /** Runs the task. */ + @Override + public void run() { + // Declare the task as started. + this.started = true; + + // Run the runnable. + this.task.run(); + + // Declare the task as finished. + this.finished = true; + } + + /** Runs the callback. */ + public void complete() { + // Run the callback. + if (this.callback != null) this.callback.run(); + } + + /** + * Returns the set result of the async task. + * + * @return The result, or null if it has not been set. + */ + @Nullable public Object getResult() { + return this.result; + } + + /** + * Sets the result of the async task. + * + * @param result The result of the async task. + */ + public void setResult(@Nullable Object result) { + this.result = result; + } +} diff --git a/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java b/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java index 60a63dba7..95fdda484 100644 --- a/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java +++ b/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java @@ -1,70 +1,62 @@ -package emu.grasscutter.server.scheduler; - -import emu.grasscutter.Grasscutter; -import lombok.Getter; - -/** - * This class works the same as a runnable, except with more information. - */ -public final class ServerTask implements Runnable { - /* The runnable to run. */ - private final Runnable runnable; - /* This ID is assigned by the scheduler. */ - @Getter - private final int taskId; - /* The period at which the task should be run. */ - /* The delay between the first execute. */ - private final int period, delay; - /* The amount of times the task has been run. */ - @Getter - private int ticks = 0; - /* Should the check consider delay? */ - private boolean considerDelay = true; - public ServerTask(Runnable runnable, int taskId, int period, int delay) { - this.runnable = runnable; - this.taskId = taskId; - this.period = period; - this.delay = delay; - } - - /** - * Cancels the task from running the next time. - */ - public void cancel() { - Grasscutter.getGameServer().getScheduler().cancelTask(this.taskId); - } - - /** - * Checks if the task should run at the current tick. - * - * @return True if the task should run, false otherwise. - */ - public boolean shouldRun() { - if (this.delay != -1 && this.considerDelay) { - this.considerDelay = false; - return this.ticks == this.delay; - } else if (this.period != -1) - return this.ticks % this.period == 0; - else return true; - } - - /** - * Checks if the task should be canceled. - * - * @return True if the task should be canceled, false otherwise. - */ - public boolean shouldCancel() { - return this.period == -1; - } - - /** - * Runs the task. - */ - @Override - public void run() { - // Run the runnable. - this.runnable.run(); - // Increase tick count. - this.ticks++; - } -} +package emu.grasscutter.server.scheduler; + +import emu.grasscutter.Grasscutter; +import lombok.Getter; + +/** This class works the same as a runnable, except with more information. */ +public final class ServerTask implements Runnable { + /* The runnable to run. */ + private final Runnable runnable; + /* This ID is assigned by the scheduler. */ + @Getter private final int taskId; + /* The period at which the task should be run. */ + /* The delay between the first execute. */ + private final int period, delay; + /* The amount of times the task has been run. */ + @Getter private int ticks = 0; + /* Should the check consider delay? */ + private boolean considerDelay = true; + + public ServerTask(Runnable runnable, int taskId, int period, int delay) { + this.runnable = runnable; + this.taskId = taskId; + this.period = period; + this.delay = delay; + } + + /** Cancels the task from running the next time. */ + public void cancel() { + Grasscutter.getGameServer().getScheduler().cancelTask(this.taskId); + } + + /** + * Checks if the task should run at the current tick. + * + * @return True if the task should run, false otherwise. + */ + public boolean shouldRun() { + if (this.delay != -1 && this.considerDelay) { + this.considerDelay = false; + return this.ticks == this.delay; + } else if (this.period != -1) return this.ticks % this.period == 0; + else return true; + } + + /** + * Checks if the task should be canceled. + * + * @return True if the task should be canceled, false otherwise. + */ + public boolean shouldCancel() { + return this.period == -1; + } + + /** Runs the task. */ + @Override + public void run() { + // Run the runnable. + this.runnable.run(); + // Increase tick count. + this.ticks++; + } +} diff --git a/src/main/java/emu/grasscutter/server/scheduler/ServerTaskScheduler.java b/src/main/java/emu/grasscutter/server/scheduler/ServerTaskScheduler.java index d8fae5bae..cb0fa2bb6 100644 --- a/src/main/java/emu/grasscutter/server/scheduler/ServerTaskScheduler.java +++ b/src/main/java/emu/grasscutter/server/scheduler/ServerTaskScheduler.java @@ -1,156 +1,151 @@ -package emu.grasscutter.server.scheduler; - -import java.util.concurrent.ConcurrentHashMap; - -/** - * A class to manage all time-based tasks scheduled on the server. - * This handles both synchronous and asynchronous tasks. - *

- * Developers note: A server tick is ONE REAL-TIME SECOND. - */ -public final class ServerTaskScheduler { - /* A map to contain all running tasks. */ - private final ConcurrentHashMap tasks - = new ConcurrentHashMap<>(); - /* A map to contain all async tasks. */ - private final ConcurrentHashMap asyncTasks - = new ConcurrentHashMap<>(); - - /* The ID assigned to the next runnable. */ - private int nextTaskId = 0; - - /** - * Ran every server tick. - * Attempts to run all scheduled tasks. - * This method is synchronous and will block until all tasks are complete. - */ - public void runTasks() { - // Skip if there are no tasks. - if (this.tasks.size() == 0) - return; - - // Run all tasks. - for (ServerTask task : this.tasks.values()) { - // Check if the task should run. - if (task.shouldRun()) { - // Run the task. - task.run(); - } - - // Check if the task should be canceled. - if (task.shouldCancel()) { - // Cancel the task. - this.cancelTask(task.getTaskId()); - } - } - - // Run all async tasks. - for (AsyncServerTask task : this.asyncTasks.values()) { - if (!task.hasStarted()) { - // Create a thread for the task. - Thread thread = new Thread(task); - // Start the thread. - thread.start(); - } else if (task.isFinished()) { - // Cancel the task. - this.asyncTasks.remove(task.getTaskId()); - // Run the task's callback. - task.complete(); - } - } - } - - /** - * Gets a task from the scheduler. - * - * @param taskId The ID of the task to get. - * @return The task, or null if it does not exist. - */ - public ServerTask getTask(int taskId) { - return this.tasks.get(taskId); - } - - /** - * Gets an async task from the scheduler. - * - * @param taskId The ID of the task to get. - * @return The task, or null if it does not exist. - */ - public AsyncServerTask getAsyncTask(int taskId) { - return this.asyncTasks.get(taskId); - } - - /** - * Removes a task from the scheduler. - * - * @param taskId The ID of the task to remove. - */ - public void cancelTask(int taskId) { - this.tasks.remove(taskId); - } - - /** - * Schedules a task to be run on a separate thread. - * The task runs on the next server tick. - * - * @param runnable The runnable to run. - * @return The ID of the task. - */ - public int scheduleAsyncTask(Runnable runnable) { - // Get the next task ID. - var taskId = this.nextTaskId++; - // Create a new task. - this.asyncTasks.put(taskId, new AsyncServerTask(runnable, taskId)); - // Return the task ID. - return taskId; - } - - /** - * Schedules a task to be run on the next server tick. - * - * @param runnable The runnable to run. - * @return The ID of the task. - */ - public int scheduleTask(Runnable runnable) { - return this.scheduleDelayedRepeatingTask(runnable, -1, -1); - } - - /** - * Schedules a task to be run after the amount of ticks has passed. - * - * @param runnable The runnable to run. - * @param delay The amount of ticks to wait before running. - * @return The ID of the task. - */ - public int scheduleDelayedTask(Runnable runnable, int delay) { - return this.scheduleDelayedRepeatingTask(runnable, -1, delay); - } - - /** - * Schedules a task to be run every amount of ticks. - * - * @param runnable The runnable to run. - * @param period The amount of ticks to wait before running again. - * @return The ID of the task. - */ - public int scheduleRepeatingTask(Runnable runnable, int period) { - return this.scheduleDelayedRepeatingTask(runnable, period, 0); - } - - /** - * Schedules a task to be run after the amount of ticks has passed. - * - * @param runnable The runnable to run. - * @param period The amount of ticks to wait before running again. - * @param delay The amount of ticks to wait before running the first time. - * @return The ID of the task. - */ - public int scheduleDelayedRepeatingTask(Runnable runnable, int period, int delay) { - // Get the next task ID. - var taskId = this.nextTaskId++; - // Create a new task. - this.tasks.put(taskId, new ServerTask(runnable, taskId, period, delay)); - // Return the task ID. - return taskId; - } -} +package emu.grasscutter.server.scheduler; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * A class to manage all time-based tasks scheduled on the server. This handles both synchronous and + * asynchronous tasks. + * + *

Developers note: A server tick is ONE REAL-TIME SECOND. + */ +public final class ServerTaskScheduler { + /* A map to contain all running tasks. */ + private final ConcurrentHashMap tasks = new ConcurrentHashMap<>(); + /* A map to contain all async tasks. */ + private final ConcurrentHashMap asyncTasks = new ConcurrentHashMap<>(); + + /* The ID assigned to the next runnable. */ + private int nextTaskId = 0; + + /** + * Ran every server tick. Attempts to run all scheduled tasks. This method is synchronous and will + * block until all tasks are complete. + */ + public void runTasks() { + // Skip if there are no tasks. + if (this.tasks.size() == 0) return; + + // Run all tasks. + for (ServerTask task : this.tasks.values()) { + // Check if the task should run. + if (task.shouldRun()) { + // Run the task. + task.run(); + } + + // Check if the task should be canceled. + if (task.shouldCancel()) { + // Cancel the task. + this.cancelTask(task.getTaskId()); + } + } + + // Run all async tasks. + for (AsyncServerTask task : this.asyncTasks.values()) { + if (!task.hasStarted()) { + // Create a thread for the task. + Thread thread = new Thread(task); + // Start the thread. + thread.start(); + } else if (task.isFinished()) { + // Cancel the task. + this.asyncTasks.remove(task.getTaskId()); + // Run the task's callback. + task.complete(); + } + } + } + + /** + * Gets a task from the scheduler. + * + * @param taskId The ID of the task to get. + * @return The task, or null if it does not exist. + */ + public ServerTask getTask(int taskId) { + return this.tasks.get(taskId); + } + + /** + * Gets an async task from the scheduler. + * + * @param taskId The ID of the task to get. + * @return The task, or null if it does not exist. + */ + public AsyncServerTask getAsyncTask(int taskId) { + return this.asyncTasks.get(taskId); + } + + /** + * Removes a task from the scheduler. + * + * @param taskId The ID of the task to remove. + */ + public void cancelTask(int taskId) { + this.tasks.remove(taskId); + } + + /** + * Schedules a task to be run on a separate thread. The task runs on the next server tick. + * + * @param runnable The runnable to run. + * @return The ID of the task. + */ + public int scheduleAsyncTask(Runnable runnable) { + // Get the next task ID. + var taskId = this.nextTaskId++; + // Create a new task. + this.asyncTasks.put(taskId, new AsyncServerTask(runnable, taskId)); + // Return the task ID. + return taskId; + } + + /** + * Schedules a task to be run on the next server tick. + * + * @param runnable The runnable to run. + * @return The ID of the task. + */ + public int scheduleTask(Runnable runnable) { + return this.scheduleDelayedRepeatingTask(runnable, -1, -1); + } + + /** + * Schedules a task to be run after the amount of ticks has passed. + * + * @param runnable The runnable to run. + * @param delay The amount of ticks to wait before running. + * @return The ID of the task. + */ + public int scheduleDelayedTask(Runnable runnable, int delay) { + return this.scheduleDelayedRepeatingTask(runnable, -1, delay); + } + + /** + * Schedules a task to be run every amount of ticks. + * + * @param runnable The runnable to run. + * @param period The amount of ticks to wait before running again. + * @return The ID of the task. + */ + public int scheduleRepeatingTask(Runnable runnable, int period) { + return this.scheduleDelayedRepeatingTask(runnable, period, 0); + } + + /** + * Schedules a task to be run after the amount of ticks has passed. + * + * @param runnable The runnable to run. + * @param period The amount of ticks to wait before running again. + * @param delay The amount of ticks to wait before running the first time. + * @return The ID of the task. + */ + public int scheduleDelayedRepeatingTask(Runnable runnable, int period, int delay) { + // Get the next task ID. + var taskId = this.nextTaskId++; + // Create a new task. + this.tasks.put(taskId, new ServerTask(runnable, taskId, period, delay)); + // Return the task ID. + return taskId; + } +} diff --git a/src/main/java/emu/grasscutter/task/Task.java b/src/main/java/emu/grasscutter/task/Task.java index 5dc2e6555..b74b6d114 100644 --- a/src/main/java/emu/grasscutter/task/Task.java +++ b/src/main/java/emu/grasscutter/task/Task.java @@ -1,36 +1,35 @@ -package emu.grasscutter.task; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/* -* So what is cron expression? -The format of a Cron expression is as follows. -Second Minute Hour Day Month Week Year -Seconds: 0-59 -Minute: 0-59 -hour: 0-23 -Day: 1-31 -Month: 1-12 -Week: 1-7 (0-6 sometimes) -Year: Specify your own - -If you want to express every second or every minute or something like that, use the * symbol in that position; -if you want to express more than one such as every 15 minutes and every 30 minutes, you can write:`15, 30`. - -For the rest of the wildcard characters, please Google them yourself -*/ - -@Retention(RetentionPolicy.RUNTIME) -public @interface Task { - String taskName() default "NO_NAME"; - - String taskCronExpression() default "0 0 0 0 0 ?"; - - String triggerName() default "NO_NAME"; - - boolean executeImmediatelyAfterReset() default false; - - boolean executeImmediately() default false; -} +package emu.grasscutter.task; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/* +* So what is cron expression? +The format of a Cron expression is as follows. +Second Minute Hour Day Month Week Year +Seconds: 0-59 +Minute: 0-59 +hour: 0-23 +Day: 1-31 +Month: 1-12 +Week: 1-7 (0-6 sometimes) +Year: Specify your own + +If you want to express every second or every minute or something like that, use the * symbol in that position; +if you want to express more than one such as every 15 minutes and every 30 minutes, you can write:`15, 30`. + +For the rest of the wildcard characters, please Google them yourself +*/ + +@Retention(RetentionPolicy.RUNTIME) +public @interface Task { + String taskName() default "NO_NAME"; + + String taskCronExpression() default "0 0 0 0 0 ?"; + + String triggerName() default "NO_NAME"; + + boolean executeImmediatelyAfterReset() default false; + + boolean executeImmediately() default false; +} diff --git a/src/main/java/emu/grasscutter/task/TaskHandler.java b/src/main/java/emu/grasscutter/task/TaskHandler.java index e60a81fa6..6ff2a9327 100644 --- a/src/main/java/emu/grasscutter/task/TaskHandler.java +++ b/src/main/java/emu/grasscutter/task/TaskHandler.java @@ -1,16 +1,16 @@ -package emu.grasscutter.task; - -import org.quartz.Job; -import org.quartz.JobExecutionException; -import org.quartz.PersistJobDataAfterExecution; - -@PersistJobDataAfterExecution -public abstract class TaskHandler implements Job { - public void restartExecute() throws JobExecutionException { - execute(null); - } - - public abstract void onEnable(); - - public abstract void onDisable(); -} +package emu.grasscutter.task; + +import org.quartz.Job; +import org.quartz.JobExecutionException; +import org.quartz.PersistJobDataAfterExecution; + +@PersistJobDataAfterExecution +public abstract class TaskHandler implements Job { + public void restartExecute() throws JobExecutionException { + execute(null); + } + + public abstract void onEnable(); + + public abstract void onDisable(); +} diff --git a/src/main/java/emu/grasscutter/task/TaskMap.java b/src/main/java/emu/grasscutter/task/TaskMap.java index 75e23f05a..a65e0e251 100644 --- a/src/main/java/emu/grasscutter/task/TaskMap.java +++ b/src/main/java/emu/grasscutter/task/TaskMap.java @@ -1,173 +1,173 @@ -package emu.grasscutter.task; - -import emu.grasscutter.Grasscutter; -import org.quartz.*; -import org.quartz.impl.StdSchedulerFactory; -import org.reflections.Reflections; - -import java.util.*; - -@SuppressWarnings({"UnusedReturnValue", "unused"}) -public final class TaskMap { - private final Map tasks = new HashMap<>(); - private final Map annotations = new HashMap<>(); - private final Map afterReset = new HashMap<>(); - private final SchedulerFactory schedulerFactory = new StdSchedulerFactory(); - - public TaskMap() { - this(false); - } - - public TaskMap(boolean scan) { - if (scan) this.scan(); - } - - public static TaskMap getInstance() { - return Grasscutter.getGameServer().getTaskMap(); - } - - public void resetNow() { - // Unregister all tasks - for (TaskHandler task : this.tasks.values()) { - unregisterTask(task); - } - - // Run all afterReset tasks - for (TaskHandler task : this.afterReset.values()) { - try { - task.restartExecute(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Remove all afterReset tasks - this.afterReset.clear(); - - // Register all tasks - for (TaskHandler task : this.tasks.values()) { - registerTask(task.getClass().getAnnotation(Task.class).taskName(), task); - } - } - - public TaskMap unregisterTask(TaskHandler task) { - this.tasks.remove(task.getClass().getAnnotation(Task.class).taskName()); - this.annotations.remove(task.getClass().getAnnotation(Task.class).taskName()); - - try { - Scheduler scheduler = schedulerFactory.getScheduler(); - scheduler.deleteJob(new JobKey(task.getClass().getAnnotation(Task.class).taskName())); - } catch (SchedulerException e) { - e.printStackTrace(); - } - - task.onDisable(); - - return this; - } - - public boolean pauseTask(String taskName) { - try { - Scheduler scheduler = schedulerFactory.getScheduler(); - scheduler.pauseJob(new JobKey(taskName)); - } catch (SchedulerException e) { - e.printStackTrace(); - return false; - } - return true; - } - - public boolean resumeTask(String taskName) { - try { - Scheduler scheduler = schedulerFactory.getScheduler(); - scheduler.resumeJob(new JobKey(taskName)); - } catch (SchedulerException e) { - e.printStackTrace(); - return false; - } - return true; - } - - public boolean cancelTask(String taskName) { - Task task = this.annotations.get(taskName); - if (task == null) return false; - try { - this.unregisterTask(this.tasks.get(taskName)); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; - } - - public TaskMap registerTask(String taskName, TaskHandler task) { - Task annotation = task.getClass().getAnnotation(Task.class); - this.annotations.put(taskName, annotation); - this.tasks.put(taskName, task); - - // register task - try { - Scheduler scheduler = schedulerFactory.getScheduler(); - JobDetail job = JobBuilder - .newJob(task.getClass()) - .withIdentity(taskName) - .build(); - - Trigger convTrigger = TriggerBuilder.newTrigger() - .withIdentity(annotation.triggerName()) - .withSchedule(CronScheduleBuilder.cronSchedule(annotation.taskCronExpression())) - .build(); - - scheduler.scheduleJob(job, convTrigger); - - if (annotation.executeImmediately()) { - task.execute(null); - } - task.onEnable(); - } catch (SchedulerException e) { - e.printStackTrace(); - } - - return this; - } - - public List getHandlersAsList() { - return new ArrayList<>(this.tasks.values()); - } - - public HashMap getHandlers() { - return new LinkedHashMap<>(this.tasks); - } - - public TaskHandler getHandler(String taskName) { - return this.tasks.get(taskName); - } - - private void scan() { - Reflections reflector = Grasscutter.reflector; - Set> classes = reflector.getTypesAnnotatedWith(Task.class); - classes.forEach(annotated -> { - try { - Task taskData = annotated.getAnnotation(Task.class); - Object object = annotated.getDeclaredConstructor().newInstance(); - if (object instanceof TaskHandler) { - this.registerTask(taskData.taskName(), (TaskHandler) object); - if (taskData.executeImmediatelyAfterReset()) { - this.afterReset.put(taskData.taskName(), (TaskHandler) object); - } - } else { - Grasscutter.getLogger().error("Class " + annotated.getName() + " is not a TaskHandler!"); - } - } catch (Exception exception) { - Grasscutter.getLogger().error("Failed to register task handler for " + annotated.getSimpleName(), exception); - } - }); - try { - Scheduler scheduler = schedulerFactory.getScheduler(); - scheduler.start(); - } catch (SchedulerException e) { - e.printStackTrace(); - } - - } -} +package emu.grasscutter.task; + +import emu.grasscutter.Grasscutter; +import java.util.*; +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; +import org.reflections.Reflections; + +@SuppressWarnings({"UnusedReturnValue", "unused"}) +public final class TaskMap { + private final Map tasks = new HashMap<>(); + private final Map annotations = new HashMap<>(); + private final Map afterReset = new HashMap<>(); + private final SchedulerFactory schedulerFactory = new StdSchedulerFactory(); + + public TaskMap() { + this(false); + } + + public TaskMap(boolean scan) { + if (scan) this.scan(); + } + + public static TaskMap getInstance() { + return Grasscutter.getGameServer().getTaskMap(); + } + + public void resetNow() { + // Unregister all tasks + for (TaskHandler task : this.tasks.values()) { + unregisterTask(task); + } + + // Run all afterReset tasks + for (TaskHandler task : this.afterReset.values()) { + try { + task.restartExecute(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Remove all afterReset tasks + this.afterReset.clear(); + + // Register all tasks + for (TaskHandler task : this.tasks.values()) { + registerTask(task.getClass().getAnnotation(Task.class).taskName(), task); + } + } + + public TaskMap unregisterTask(TaskHandler task) { + this.tasks.remove(task.getClass().getAnnotation(Task.class).taskName()); + this.annotations.remove(task.getClass().getAnnotation(Task.class).taskName()); + + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.deleteJob(new JobKey(task.getClass().getAnnotation(Task.class).taskName())); + } catch (SchedulerException e) { + e.printStackTrace(); + } + + task.onDisable(); + + return this; + } + + public boolean pauseTask(String taskName) { + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.pauseJob(new JobKey(taskName)); + } catch (SchedulerException e) { + e.printStackTrace(); + return false; + } + return true; + } + + public boolean resumeTask(String taskName) { + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.resumeJob(new JobKey(taskName)); + } catch (SchedulerException e) { + e.printStackTrace(); + return false; + } + return true; + } + + public boolean cancelTask(String taskName) { + Task task = this.annotations.get(taskName); + if (task == null) return false; + try { + this.unregisterTask(this.tasks.get(taskName)); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + public TaskMap registerTask(String taskName, TaskHandler task) { + Task annotation = task.getClass().getAnnotation(Task.class); + this.annotations.put(taskName, annotation); + this.tasks.put(taskName, task); + + // register task + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + JobDetail job = JobBuilder.newJob(task.getClass()).withIdentity(taskName).build(); + + Trigger convTrigger = + TriggerBuilder.newTrigger() + .withIdentity(annotation.triggerName()) + .withSchedule(CronScheduleBuilder.cronSchedule(annotation.taskCronExpression())) + .build(); + + scheduler.scheduleJob(job, convTrigger); + + if (annotation.executeImmediately()) { + task.execute(null); + } + task.onEnable(); + } catch (SchedulerException e) { + e.printStackTrace(); + } + + return this; + } + + public List getHandlersAsList() { + return new ArrayList<>(this.tasks.values()); + } + + public HashMap getHandlers() { + return new LinkedHashMap<>(this.tasks); + } + + public TaskHandler getHandler(String taskName) { + return this.tasks.get(taskName); + } + + private void scan() { + Reflections reflector = Grasscutter.reflector; + Set> classes = reflector.getTypesAnnotatedWith(Task.class); + classes.forEach( + annotated -> { + try { + Task taskData = annotated.getAnnotation(Task.class); + Object object = annotated.getDeclaredConstructor().newInstance(); + if (object instanceof TaskHandler) { + this.registerTask(taskData.taskName(), (TaskHandler) object); + if (taskData.executeImmediatelyAfterReset()) { + this.afterReset.put(taskData.taskName(), (TaskHandler) object); + } + } else { + Grasscutter.getLogger() + .error("Class " + annotated.getName() + " is not a TaskHandler!"); + } + } catch (Exception exception) { + Grasscutter.getLogger() + .error( + "Failed to register task handler for " + annotated.getSimpleName(), exception); + } + }); + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.start(); + } catch (SchedulerException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/task/tasks/AnnouncementTask.java b/src/main/java/emu/grasscutter/task/tasks/AnnouncementTask.java index c8741c571..da0b8bf9c 100644 --- a/src/main/java/emu/grasscutter/task/tasks/AnnouncementTask.java +++ b/src/main/java/emu/grasscutter/task/tasks/AnnouncementTask.java @@ -1,53 +1,65 @@ -package emu.grasscutter.task.tasks; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.systems.AnnouncementSystem; -import emu.grasscutter.task.Task; -import emu.grasscutter.task.TaskHandler; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -import java.util.Date; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -@Task(taskName = "Announcement", taskCronExpression = "0 * * * * ?", triggerName = "AnnouncementTrigger") -public final class AnnouncementTask extends TaskHandler { - - static Map intervalMap = new ConcurrentHashMap<>(); - - @Override - public void onEnable() { - Grasscutter.getLogger().debug("[Task] Announcement task enabled."); - } - - @Override - public void onDisable() { - Grasscutter.getLogger().debug("[Task] Announcement task disabled."); - } - - @Override - public synchronized void execute(JobExecutionContext context) throws JobExecutionException { - var current = new Date(); - var announceConfigItems = Grasscutter.getGameServer().getAnnouncementSystem().getAnnounceConfigItemMap().values().stream() - .filter(AnnouncementSystem.AnnounceConfigItem::isTick) - .filter(i -> current.after(i.getBeginTime())) - .filter(i -> current.before(i.getEndTime())) - .collect(Collectors.toMap(AnnouncementSystem.AnnounceConfigItem::getTemplateId, y -> y)); - - announceConfigItems.values().forEach(i -> intervalMap.compute(i.getTemplateId(), (k, v) -> v == null ? 1 : v + 1)); - - var toSend = intervalMap.entrySet().stream() - .filter(i -> announceConfigItems.containsKey(i.getKey())) - .filter(i -> i.getValue() >= announceConfigItems.get(i.getKey()).getInterval()) - .map(i -> announceConfigItems.get(i.getKey())) - .toList(); - - Grasscutter.getGameServer().getAnnouncementSystem().broadcast(toSend); - Grasscutter.getLogger().debug("Broadcast {} announcement(s) to all online players", toSend.size()); - - // clear the interval count - toSend.forEach(i -> intervalMap.put(i.getTemplateId(), 0)); - } -} +package emu.grasscutter.task.tasks; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.systems.AnnouncementSystem; +import emu.grasscutter.task.Task; +import emu.grasscutter.task.TaskHandler; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +@Task( + taskName = "Announcement", + taskCronExpression = "0 * * * * ?", + triggerName = "AnnouncementTrigger") +public final class AnnouncementTask extends TaskHandler { + + static Map intervalMap = new ConcurrentHashMap<>(); + + @Override + public void onEnable() { + Grasscutter.getLogger().debug("[Task] Announcement task enabled."); + } + + @Override + public void onDisable() { + Grasscutter.getLogger().debug("[Task] Announcement task disabled."); + } + + @Override + public synchronized void execute(JobExecutionContext context) throws JobExecutionException { + var current = new Date(); + var announceConfigItems = + Grasscutter.getGameServer() + .getAnnouncementSystem() + .getAnnounceConfigItemMap() + .values() + .stream() + .filter(AnnouncementSystem.AnnounceConfigItem::isTick) + .filter(i -> current.after(i.getBeginTime())) + .filter(i -> current.before(i.getEndTime())) + .collect( + Collectors.toMap(AnnouncementSystem.AnnounceConfigItem::getTemplateId, y -> y)); + + announceConfigItems + .values() + .forEach(i -> intervalMap.compute(i.getTemplateId(), (k, v) -> v == null ? 1 : v + 1)); + + var toSend = + intervalMap.entrySet().stream() + .filter(i -> announceConfigItems.containsKey(i.getKey())) + .filter(i -> i.getValue() >= announceConfigItems.get(i.getKey()).getInterval()) + .map(i -> announceConfigItems.get(i.getKey())) + .toList(); + + Grasscutter.getGameServer().getAnnouncementSystem().broadcast(toSend); + Grasscutter.getLogger() + .debug("Broadcast {} announcement(s) to all online players", toSend.size()); + + // clear the interval count + toSend.forEach(i -> intervalMap.put(i.getTemplateId(), 0)); + } +} diff --git a/src/main/java/emu/grasscutter/task/tasks/MoonCard.java b/src/main/java/emu/grasscutter/task/tasks/MoonCard.java index b9fb176be..9faa3b83c 100644 --- a/src/main/java/emu/grasscutter/task/tasks/MoonCard.java +++ b/src/main/java/emu/grasscutter/task/tasks/MoonCard.java @@ -1,33 +1,36 @@ -package emu.grasscutter.task.tasks; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.task.Task; -import emu.grasscutter.task.TaskHandler; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -@Task(taskName = "MoonCard", taskCronExpression = "0 0 0 * * ?", triggerName = "MoonCardTrigger") -// taskCronExpression: Fixed time period: 0:0:0 every day (twenty-four hour system) -public final class MoonCard extends TaskHandler { - - @Override - public void onEnable() { - Grasscutter.getLogger().debug("[Task] MoonCard task enabled."); - } - - @Override - public void onDisable() { - Grasscutter.getLogger().debug("[Task] MoonCard task disabled."); - } - - @Override - public synchronized void execute(JobExecutionContext context) throws JobExecutionException { - Grasscutter.getGameServer().getPlayers().forEach((uid, player) -> { - if (player.isOnline()) { - if (player.inMoonCard()) { - player.getTodayMoonCard(); - } - } - }); - } -} +package emu.grasscutter.task.tasks; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.task.Task; +import emu.grasscutter.task.TaskHandler; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +@Task(taskName = "MoonCard", taskCronExpression = "0 0 0 * * ?", triggerName = "MoonCardTrigger") +// taskCronExpression: Fixed time period: 0:0:0 every day (twenty-four hour system) +public final class MoonCard extends TaskHandler { + + @Override + public void onEnable() { + Grasscutter.getLogger().debug("[Task] MoonCard task enabled."); + } + + @Override + public void onDisable() { + Grasscutter.getLogger().debug("[Task] MoonCard task disabled."); + } + + @Override + public synchronized void execute(JobExecutionContext context) throws JobExecutionException { + Grasscutter.getGameServer() + .getPlayers() + .forEach( + (uid, player) -> { + if (player.isOnline()) { + if (player.inMoonCard()) { + player.getTodayMoonCard(); + } + } + }); + } +} diff --git a/src/main/java/emu/grasscutter/tools/Dumpers.java b/src/main/java/emu/grasscutter/tools/Dumpers.java index 75df3b17e..e1d0b7089 100644 --- a/src/main/java/emu/grasscutter/tools/Dumpers.java +++ b/src/main/java/emu/grasscutter/tools/Dumpers.java @@ -1,16 +1,16 @@ -package emu.grasscutter.tools; - -import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp; -import emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp; - -public final class Dumpers { - public static void extractBanner(byte[] data) throws Exception { - GetGachaInfoRsp proto = GetGachaInfoRsp.parseFrom(data); - System.out.println(proto); - } - - public static void extractShop(byte[] data) throws Exception { - GetShopRsp proto = GetShopRsp.parseFrom(data); - System.out.println(proto); - } -} +package emu.grasscutter.tools; + +import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp; +import emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp; + +public final class Dumpers { + public static void extractBanner(byte[] data) throws Exception { + GetGachaInfoRsp proto = GetGachaInfoRsp.parseFrom(data); + System.out.println(proto); + } + + public static void extractShop(byte[] data) throws Exception { + GetShopRsp proto = GetShopRsp.parseFrom(data); + System.out.println(proto); + } +} diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index 2bb6e4167..cc30db94c 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -1,326 +1,391 @@ -package emu.grasscutter.tools; - -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.ResourceLoader; -import emu.grasscutter.data.excels.AchievementData; -import emu.grasscutter.data.excels.AvatarData; -import emu.grasscutter.data.excels.ItemData; -import emu.grasscutter.game.inventory.MaterialType; -import emu.grasscutter.utils.Language; -import emu.grasscutter.utils.Language.TextStrings; -import it.unimi.dsi.fastutil.ints.Int2IntRBTreeMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; -import lombok.val; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.LongStream; - -import static emu.grasscutter.utils.FileUtils.getResourcePath; -import static emu.grasscutter.utils.Language.getTextMapKey; - -public final class Tools { - /** - * This generates the GM handbooks with a message by default. - * - * @throws Exception If an error occurs while generating the handbooks. - */ - public static void createGmHandbooks() throws Exception { - Tools.createGmHandbooks(true); - } - - /** - * Generates a GM handbook for each language. - * - * @param message Should a message be printed to the console? - * @throws Exception If an error occurs while generating the handbooks. - */ - public static void createGmHandbooks(boolean message) throws Exception { - val languages = Language.TextStrings.getLanguages(); - - ResourceLoader.loadAll(); - val mainQuestTitles = new Int2IntRBTreeMap(GameData.getMainQuestDataMap().int2ObjectEntrySet().stream().collect(Collectors.toMap(e -> e.getIntKey(), e -> (int) e.getValue().getTitleTextMapHash()))); - // val questDescs = new Int2IntRBTreeMap(GameData.getQuestDataMap().int2ObjectEntrySet().stream().collect(Collectors.toMap(e -> (int) e.getIntKey(), e -> (int) e.getValue().getDescTextMapHash()))); - - val avatarDataMap = new Int2ObjectRBTreeMap<>(GameData.getAvatarDataMap()); - val itemDataMap = new Int2ObjectRBTreeMap<>(GameData.getItemDataMap()); - val monsterDataMap = new Int2ObjectRBTreeMap<>(GameData.getMonsterDataMap()); - val sceneDataMap = new Int2ObjectRBTreeMap<>(GameData.getSceneDataMap()); - val questDataMap = new Int2ObjectRBTreeMap<>(GameData.getQuestDataMap()); - val achievementDataMap = new Int2ObjectRBTreeMap<>(GameData.getAchievementDataMap()); - - Function, String> getPad = m -> "%" + m.lastKey().toString().length() + "s : "; - - // Create builders and helper functions - val handbookBuilders = IntStream.range(0, TextStrings.NUM_LANGUAGES).mapToObj(i -> new StringBuilder()).toList(); - var h = new Object() { - void newLine(String line) { - handbookBuilders.forEach(b -> b.append(line + "\n")); - } - - void newSection(String title) { - newLine("\n\n// " + title); - } - - void newTranslatedLine(String template, TextStrings... textstrings) { - for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { - String s = template; - for (int j = 0; j < textstrings.length; j++) - s = s.replace("{" + j + "}", textstrings[j].strings[i]); - handbookBuilders.get(i).append(s + "\n"); - } - } - - void newTranslatedLine(String template, long... hashes) { - newTranslatedLine(template, LongStream.of(hashes).mapToObj(hash -> getTextMapKey(hash)).toArray(TextStrings[]::new)); - } - }; - - // Preamble - h.newLine("// Grasscutter " + GameConstants.VERSION + " GM Handbook"); - h.newLine("// Created " + DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss").format(LocalDateTime.now())); - - // Commands - h.newSection("Commands"); - final List cmdList = CommandMap.getInstance().getHandlersAsList(); - final String padCmdLabel = "%" + cmdList.stream().map(CommandHandler::getLabel).map(String::length).max(Integer::compare).get() + "s : "; - for (CommandHandler cmd : cmdList) { - final String label = padCmdLabel.formatted(cmd.getLabel()); - final String descKey = cmd.getDescriptionKey(); - for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { - String desc = languages.get(i).get(descKey).replace("\n", "\n\t\t\t\t").replace("\t", " "); - handbookBuilders.get(i).append(label + desc + "\n"); - } - } - // Avatars - h.newSection("Avatars"); - val avatarPre = getPad.apply(avatarDataMap); - avatarDataMap.forEach((id, data) -> h.newTranslatedLine(avatarPre.formatted(id) + "{0}", data.getNameTextMapHash())); - // Items - h.newSection("Items"); - val itemPre = getPad.apply(itemDataMap); - itemDataMap.forEach((id, data) -> { - val name = getTextMapKey(data.getNameTextMapHash()); - if (Objects.requireNonNull(data.getMaterialType()) == MaterialType.MATERIAL_BGM) { - val bgmName = Optional.ofNullable(data.getItemUse()) - .map(u -> u.get(0)) - .map(u -> u.getUseParam()) - .filter(u -> u.length > 0) - .map(u -> Integer.parseInt(u[0])) - .map(bgmId -> GameData.getHomeWorldBgmDataMap().get(bgmId)) - .map(bgm -> bgm.getBgmNameTextMapHash()) - .map(hash -> getTextMapKey(hash)); - if (bgmName.isPresent()) { - h.newTranslatedLine(itemPre.formatted(id) + "{0} - {1}", name, bgmName.get()); - return; - } // Fall-through - } - h.newTranslatedLine(itemPre.formatted(id) + "{0}", name); - }); - // Monsters - h.newSection("Monsters"); - val monsterPre = getPad.apply(monsterDataMap); - monsterDataMap.forEach((id, data) -> h.newTranslatedLine( - monsterPre.formatted(id) + data.getMonsterName() + " - {0}", - data.getNameTextMapHash())); - // Scenes - no translations - h.newSection("Scenes"); - val padSceneId = getPad.apply(sceneDataMap); - sceneDataMap.forEach((id, data) -> h.newLine(padSceneId.formatted(id) + data.getScriptData())); - // Quests - h.newSection("Quests"); - val padQuestId = getPad.apply(questDataMap); - questDataMap.forEach((id, data) -> h.newTranslatedLine( - padQuestId.formatted(id) + "{0} - {1}", - mainQuestTitles.get(data.getMainId()), - data.getDescTextMapHash())); - // Achievements - h.newSection("Achievements"); - val padAchievementId = getPad.apply(achievementDataMap); - achievementDataMap.values().stream() - .filter(AchievementData::isUsed) - .forEach(data -> { - h.newTranslatedLine(padAchievementId.formatted(data.getId()) + "{0} - {1}", data.getTitleTextMapHash(), data.getDescTextMapHash()); - }); - - // Write txt files - for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { - File GMHandbookOutputpath = new File("./GM Handbook"); - GMHandbookOutputpath.mkdir(); - final String fileName = "./GM Handbook/GM Handbook - %s.txt".formatted(TextStrings.ARR_LANGUAGES[i]); - try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) { - writer.write(handbookBuilders.get(i).toString()); - } - } - - if (message) Grasscutter.getLogger().info("GM Handbooks generated!"); - } - - public static List createGachaMappingJsons() { - final int NUM_LANGUAGES = Language.TextStrings.NUM_LANGUAGES; - final Language.TextStrings CHARACTER = Language.getTextMapKey(4233146695L); // "Character" in EN - final Language.TextStrings WEAPON = Language.getTextMapKey(4231343903L); // "Weapon" in EN - final Language.TextStrings STANDARD_WISH = Language.getTextMapKey(332935371L); // "Standard Wish" in EN - final Language.TextStrings CHARACTER_EVENT_WISH = Language.getTextMapKey(2272170627L); // "Character Event Wish" in EN - final Language.TextStrings CHARACTER_EVENT_WISH_2 = Language.getTextMapKey(3352513147L); // "Character Event Wish-2" in EN - final Language.TextStrings WEAPON_EVENT_WISH = Language.getTextMapKey(2864268523L); // "Weapon Event Wish" in EN - final List sbs = new ArrayList<>(NUM_LANGUAGES); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) - sbs.add(new StringBuilder("{\n")); // Web requests should never need Windows line endings - - // Avatars - GameData.getAvatarDataMap().keySet().intStream().sorted().forEach(id -> { - AvatarData data = GameData.getAvatarDataMap().get(id); - int avatarID = data.getId(); - if (avatarID >= 11000000) { // skip test avatar - return; - } - String color = switch (data.getQualityType()) { - case "QUALITY_PURPLE" -> "purple"; - case "QUALITY_ORANGE" -> "yellow"; - case "QUALITY_BLUE" -> "blue"; - default -> ""; - }; - Language.TextStrings avatarName = Language.getTextMapKey(data.getNameTextMapHash()); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { - sbs.get(langIdx) - .append("\t\"") - .append(avatarID % 1000 + 1000) - .append("\": [\"") - .append(avatarName.get(langIdx)) - .append(" (") - .append(CHARACTER.get(langIdx)) - .append(")\", \"") - .append(color) - .append("\"],\n"); - } - }); - - // Weapons - GameData.getItemDataMap().keySet().intStream().sorted().forEach(id -> { - ItemData data = GameData.getItemDataMap().get(id); - if (data.getId() <= 11101 || data.getId() >= 20000) { - return; //skip non weapon items - } - String color = switch (data.getRankLevel()) { - case 3 -> "blue"; - case 4 -> "purple"; - case 5 -> "yellow"; - default -> null; - }; - if (color == null) return; // skip unnecessary entries - Language.TextStrings weaponName = Language.getTextMapKey(data.getNameTextMapHash()); - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { - sbs.get(langIdx) - .append("\t\"") - .append(data.getId()) - .append("\": [\"") - .append(weaponName.get(langIdx).replaceAll("\"", "\\\\\"")) - .append(" (") - .append(WEAPON.get(langIdx)) - .append(")\", \"") - .append(color) - .append("\"],\n"); - } - }); - - for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { - sbs.get(langIdx) - .append("\t\"200\": \"") - .append(STANDARD_WISH.get(langIdx)) - .append("\",\n\t\"301\": \"") - .append(CHARACTER_EVENT_WISH.get(langIdx)) - .append("\",\n\t\"400\": \"") - .append(CHARACTER_EVENT_WISH_2.get(langIdx)) - .append("\",\n\t\"302\": \"") - .append(WEAPON_EVENT_WISH.get(langIdx)) - .append("\"\n}"); - } - return sbs.stream().map(StringBuilder::toString).toList(); - } - - public static void createGachaMappings(Path location) throws IOException { - ResourceLoader.loadResources(); - List jsons = createGachaMappingJsons(); - var usedLocales = new HashSet(); - StringBuilder sb = new StringBuilder("mappings = {\n"); - for (int i = 0; i < Language.TextStrings.NUM_LANGUAGES; i++) { - String locale = Language.TextStrings.ARR_GC_LANGUAGES[i].toLowerCase(); // TODO: change the templates to not use lowercased locale codes - if (usedLocales.add(locale)) { // Some locales fallback to en-us, we don't want to redefine en-us with vietnamese strings - sb.append("\t\"%s\": ".formatted(locale)); - sb.append(jsons.get(i).replace("\n", "\n\t") + ",\n"); - } - } - sb.setLength(sb.length() - 2); // Delete trailing ",\n" - sb.append("\n}"); - - Files.createDirectories(location.getParent()); - Files.writeString(location, sb); - Grasscutter.getLogger().debug("Mappings generated to " + location); - } - - public static List getAvailableLanguage() { - List availableLangList = new ArrayList<>(); - try { - Files.newDirectoryStream(getResourcePath("TextMap"), "TextMap*.json").forEach(path -> { - availableLangList.add(path.getFileName().toString().replace("TextMap", "").replace(".json", "").toLowerCase()); - }); - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to get available languages:", e); - } - return availableLangList; - } - - @Deprecated(forRemoval = true, since = "1.2.3") - public static String getLanguageOption() { - List availableLangList = getAvailableLanguage(); - - // Use system out for better format - if (availableLangList.size() == 1) { - return availableLangList.get(0).toUpperCase(); - } - StringBuilder stagedMessage = new StringBuilder(); - stagedMessage.append("The following languages mappings are available, please select one: [default: EN] \n"); - - StringBuilder groupedLangList = new StringBuilder(">\t"); - String input; - int groupedLangCount = 0; - - for (String availableLanguage : availableLangList) { - groupedLangCount++; - groupedLangList.append(availableLanguage).append("\t"); - - if (groupedLangCount == 6) { - stagedMessage.append(groupedLangList).append("\n"); - groupedLangCount = 0; - groupedLangList = new StringBuilder(">\t"); - } - } - - if (groupedLangCount > 0) { - stagedMessage.append(groupedLangList).append("\n"); - } - - stagedMessage.append("\nYour choice: [EN] "); - - input = Grasscutter.getConsole().readLine(stagedMessage.toString()); - if (availableLangList.contains(input.toLowerCase())) { - return input.toUpperCase(); - } - - Grasscutter.getLogger().info("Invalid option. Will use EN (English) as fallback."); - return "EN"; - } -} +package emu.grasscutter.tools; + +import static emu.grasscutter.utils.FileUtils.getResourcePath; +import static emu.grasscutter.utils.Language.getTextMapKey; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.ResourceLoader; +import emu.grasscutter.data.excels.AchievementData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.inventory.MaterialType; +import emu.grasscutter.utils.Language; +import emu.grasscutter.utils.Language.TextStrings; +import it.unimi.dsi.fastutil.ints.Int2IntRBTreeMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import lombok.val; + +public final class Tools { + /** + * This generates the GM handbooks with a message by default. + * + * @throws Exception If an error occurs while generating the handbooks. + */ + public static void createGmHandbooks() throws Exception { + Tools.createGmHandbooks(true); + } + + /** + * Generates a GM handbook for each language. + * + * @param message Should a message be printed to the console? + * @throws Exception If an error occurs while generating the handbooks. + */ + public static void createGmHandbooks(boolean message) throws Exception { + val languages = Language.TextStrings.getLanguages(); + + ResourceLoader.loadAll(); + val mainQuestTitles = + new Int2IntRBTreeMap( + GameData.getMainQuestDataMap().int2ObjectEntrySet().stream() + .collect( + Collectors.toMap( + e -> e.getIntKey(), e -> (int) e.getValue().getTitleTextMapHash()))); + // val questDescs = new + // Int2IntRBTreeMap(GameData.getQuestDataMap().int2ObjectEntrySet().stream().collect(Collectors.toMap(e -> (int) e.getIntKey(), e -> (int) e.getValue().getDescTextMapHash()))); + + val avatarDataMap = new Int2ObjectRBTreeMap<>(GameData.getAvatarDataMap()); + val itemDataMap = new Int2ObjectRBTreeMap<>(GameData.getItemDataMap()); + val monsterDataMap = new Int2ObjectRBTreeMap<>(GameData.getMonsterDataMap()); + val sceneDataMap = new Int2ObjectRBTreeMap<>(GameData.getSceneDataMap()); + val questDataMap = new Int2ObjectRBTreeMap<>(GameData.getQuestDataMap()); + val achievementDataMap = new Int2ObjectRBTreeMap<>(GameData.getAchievementDataMap()); + + Function, String> getPad = m -> "%" + m.lastKey().toString().length() + "s : "; + + // Create builders and helper functions + val handbookBuilders = + IntStream.range(0, TextStrings.NUM_LANGUAGES).mapToObj(i -> new StringBuilder()).toList(); + var h = + new Object() { + void newLine(String line) { + handbookBuilders.forEach(b -> b.append(line + "\n")); + } + + void newSection(String title) { + newLine("\n\n// " + title); + } + + void newTranslatedLine(String template, TextStrings... textstrings) { + for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { + String s = template; + for (int j = 0; j < textstrings.length; j++) + s = s.replace("{" + j + "}", textstrings[j].strings[i]); + handbookBuilders.get(i).append(s + "\n"); + } + } + + void newTranslatedLine(String template, long... hashes) { + newTranslatedLine( + template, + LongStream.of(hashes) + .mapToObj(hash -> getTextMapKey(hash)) + .toArray(TextStrings[]::new)); + } + }; + + // Preamble + h.newLine("// Grasscutter " + GameConstants.VERSION + " GM Handbook"); + h.newLine( + "// Created " + + DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss").format(LocalDateTime.now())); + + // Commands + h.newSection("Commands"); + final List cmdList = CommandMap.getInstance().getHandlersAsList(); + final String padCmdLabel = + "%" + + cmdList.stream() + .map(CommandHandler::getLabel) + .map(String::length) + .max(Integer::compare) + .get() + + "s : "; + for (CommandHandler cmd : cmdList) { + final String label = padCmdLabel.formatted(cmd.getLabel()); + final String descKey = cmd.getDescriptionKey(); + for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { + String desc = + languages.get(i).get(descKey).replace("\n", "\n\t\t\t\t").replace("\t", " "); + handbookBuilders.get(i).append(label + desc + "\n"); + } + } + // Avatars + h.newSection("Avatars"); + val avatarPre = getPad.apply(avatarDataMap); + avatarDataMap.forEach( + (id, data) -> + h.newTranslatedLine(avatarPre.formatted(id) + "{0}", data.getNameTextMapHash())); + // Items + h.newSection("Items"); + val itemPre = getPad.apply(itemDataMap); + itemDataMap.forEach( + (id, data) -> { + val name = getTextMapKey(data.getNameTextMapHash()); + if (Objects.requireNonNull(data.getMaterialType()) == MaterialType.MATERIAL_BGM) { + val bgmName = + Optional.ofNullable(data.getItemUse()) + .map(u -> u.get(0)) + .map(u -> u.getUseParam()) + .filter(u -> u.length > 0) + .map(u -> Integer.parseInt(u[0])) + .map(bgmId -> GameData.getHomeWorldBgmDataMap().get(bgmId)) + .map(bgm -> bgm.getBgmNameTextMapHash()) + .map(hash -> getTextMapKey(hash)); + if (bgmName.isPresent()) { + h.newTranslatedLine(itemPre.formatted(id) + "{0} - {1}", name, bgmName.get()); + return; + } // Fall-through + } + h.newTranslatedLine(itemPre.formatted(id) + "{0}", name); + }); + // Monsters + h.newSection("Monsters"); + val monsterPre = getPad.apply(monsterDataMap); + monsterDataMap.forEach( + (id, data) -> + h.newTranslatedLine( + monsterPre.formatted(id) + data.getMonsterName() + " - {0}", + data.getNameTextMapHash())); + // Scenes - no translations + h.newSection("Scenes"); + val padSceneId = getPad.apply(sceneDataMap); + sceneDataMap.forEach((id, data) -> h.newLine(padSceneId.formatted(id) + data.getScriptData())); + // Quests + h.newSection("Quests"); + val padQuestId = getPad.apply(questDataMap); + questDataMap.forEach( + (id, data) -> + h.newTranslatedLine( + padQuestId.formatted(id) + "{0} - {1}", + mainQuestTitles.get(data.getMainId()), + data.getDescTextMapHash())); + // Achievements + h.newSection("Achievements"); + val padAchievementId = getPad.apply(achievementDataMap); + achievementDataMap.values().stream() + .filter(AchievementData::isUsed) + .forEach( + data -> { + h.newTranslatedLine( + padAchievementId.formatted(data.getId()) + "{0} - {1}", + data.getTitleTextMapHash(), + data.getDescTextMapHash()); + }); + + // Write txt files + for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { + File GMHandbookOutputpath = new File("./GM Handbook"); + GMHandbookOutputpath.mkdir(); + final String fileName = + "./GM Handbook/GM Handbook - %s.txt".formatted(TextStrings.ARR_LANGUAGES[i]); + try (PrintWriter writer = + new PrintWriter( + new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), + false)) { + writer.write(handbookBuilders.get(i).toString()); + } + } + + if (message) Grasscutter.getLogger().info("GM Handbooks generated!"); + } + + public static List createGachaMappingJsons() { + final int NUM_LANGUAGES = Language.TextStrings.NUM_LANGUAGES; + final Language.TextStrings CHARACTER = Language.getTextMapKey(4233146695L); // "Character" in EN + final Language.TextStrings WEAPON = Language.getTextMapKey(4231343903L); // "Weapon" in EN + final Language.TextStrings STANDARD_WISH = + Language.getTextMapKey(332935371L); // "Standard Wish" in EN + final Language.TextStrings CHARACTER_EVENT_WISH = + Language.getTextMapKey(2272170627L); // "Character Event Wish" in EN + final Language.TextStrings CHARACTER_EVENT_WISH_2 = + Language.getTextMapKey(3352513147L); // "Character Event Wish-2" in EN + final Language.TextStrings WEAPON_EVENT_WISH = + Language.getTextMapKey(2864268523L); // "Weapon Event Wish" in EN + final List sbs = new ArrayList<>(NUM_LANGUAGES); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) + sbs.add(new StringBuilder("{\n")); // Web requests should never need Windows line endings + + // Avatars + GameData.getAvatarDataMap() + .keySet() + .intStream() + .sorted() + .forEach( + id -> { + AvatarData data = GameData.getAvatarDataMap().get(id); + int avatarID = data.getId(); + if (avatarID >= 11000000) { // skip test avatar + return; + } + String color = + switch (data.getQualityType()) { + case "QUALITY_PURPLE" -> "purple"; + case "QUALITY_ORANGE" -> "yellow"; + case "QUALITY_BLUE" -> "blue"; + default -> ""; + }; + Language.TextStrings avatarName = Language.getTextMapKey(data.getNameTextMapHash()); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { + sbs.get(langIdx) + .append("\t\"") + .append(avatarID % 1000 + 1000) + .append("\": [\"") + .append(avatarName.get(langIdx)) + .append(" (") + .append(CHARACTER.get(langIdx)) + .append(")\", \"") + .append(color) + .append("\"],\n"); + } + }); + + // Weapons + GameData.getItemDataMap() + .keySet() + .intStream() + .sorted() + .forEach( + id -> { + ItemData data = GameData.getItemDataMap().get(id); + if (data.getId() <= 11101 || data.getId() >= 20000) { + return; // skip non weapon items + } + String color = + switch (data.getRankLevel()) { + case 3 -> "blue"; + case 4 -> "purple"; + case 5 -> "yellow"; + default -> null; + }; + if (color == null) return; // skip unnecessary entries + Language.TextStrings weaponName = Language.getTextMapKey(data.getNameTextMapHash()); + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { + sbs.get(langIdx) + .append("\t\"") + .append(data.getId()) + .append("\": [\"") + .append(weaponName.get(langIdx).replaceAll("\"", "\\\\\"")) + .append(" (") + .append(WEAPON.get(langIdx)) + .append(")\", \"") + .append(color) + .append("\"],\n"); + } + }); + + for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) { + sbs.get(langIdx) + .append("\t\"200\": \"") + .append(STANDARD_WISH.get(langIdx)) + .append("\",\n\t\"301\": \"") + .append(CHARACTER_EVENT_WISH.get(langIdx)) + .append("\",\n\t\"400\": \"") + .append(CHARACTER_EVENT_WISH_2.get(langIdx)) + .append("\",\n\t\"302\": \"") + .append(WEAPON_EVENT_WISH.get(langIdx)) + .append("\"\n}"); + } + return sbs.stream().map(StringBuilder::toString).toList(); + } + + public static void createGachaMappings(Path location) throws IOException { + ResourceLoader.loadResources(); + List jsons = createGachaMappingJsons(); + var usedLocales = new HashSet(); + StringBuilder sb = new StringBuilder("mappings = {\n"); + for (int i = 0; i < Language.TextStrings.NUM_LANGUAGES; i++) { + String locale = + Language.TextStrings.ARR_GC_LANGUAGES[i] + .toLowerCase(); // TODO: change the templates to not use lowercased locale codes + if (usedLocales.add( + locale)) { // Some locales fallback to en-us, we don't want to redefine en-us with + // vietnamese strings + sb.append("\t\"%s\": ".formatted(locale)); + sb.append(jsons.get(i).replace("\n", "\n\t") + ",\n"); + } + } + sb.setLength(sb.length() - 2); // Delete trailing ",\n" + sb.append("\n}"); + + Files.createDirectories(location.getParent()); + Files.writeString(location, sb); + Grasscutter.getLogger().debug("Mappings generated to " + location); + } + + public static List getAvailableLanguage() { + List availableLangList = new ArrayList<>(); + try { + Files.newDirectoryStream(getResourcePath("TextMap"), "TextMap*.json") + .forEach( + path -> { + availableLangList.add( + path.getFileName() + .toString() + .replace("TextMap", "") + .replace(".json", "") + .toLowerCase()); + }); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to get available languages:", e); + } + return availableLangList; + } + + @Deprecated(forRemoval = true, since = "1.2.3") + public static String getLanguageOption() { + List availableLangList = getAvailableLanguage(); + + // Use system out for better format + if (availableLangList.size() == 1) { + return availableLangList.get(0).toUpperCase(); + } + StringBuilder stagedMessage = new StringBuilder(); + stagedMessage.append( + "The following languages mappings are available, please select one: [default: EN] \n"); + + StringBuilder groupedLangList = new StringBuilder(">\t"); + String input; + int groupedLangCount = 0; + + for (String availableLanguage : availableLangList) { + groupedLangCount++; + groupedLangList.append(availableLanguage).append("\t"); + + if (groupedLangCount == 6) { + stagedMessage.append(groupedLangList).append("\n"); + groupedLangCount = 0; + groupedLangList = new StringBuilder(">\t"); + } + } + + if (groupedLangCount > 0) { + stagedMessage.append(groupedLangList).append("\n"); + } + + stagedMessage.append("\nYour choice: [EN] "); + + input = Grasscutter.getConsole().readLine(stagedMessage.toString()); + if (availableLangList.contains(input.toLowerCase())) { + return input.toUpperCase(); + } + + Grasscutter.getLogger().info("Invalid option. Will use EN (English) as fallback."); + return "EN"; + } +} diff --git a/src/main/java/emu/grasscutter/utils/Crypto.java b/src/main/java/emu/grasscutter/utils/Crypto.java index d483dd4a5..d57f78433 100644 --- a/src/main/java/emu/grasscutter/utils/Crypto.java +++ b/src/main/java/emu/grasscutter/utils/Crypto.java @@ -1,75 +1,77 @@ -package emu.grasscutter.utils; - -import emu.grasscutter.Grasscutter; - -import java.nio.file.Path; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -public final class Crypto { - private static final SecureRandom secureRandom = new SecureRandom(); - - public static byte[] DISPATCH_KEY; - public static byte[] DISPATCH_SEED; - - public static byte[] ENCRYPT_KEY; - public static long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968"); - public static byte[] ENCRYPT_SEED_BUFFER = new byte[0]; - - public static PrivateKey CUR_SIGNING_KEY; - - public static Map EncryptionKeys = new HashMap<>(); - - public static void loadKeys() { - DISPATCH_KEY = FileUtils.readResource("/keys/dispatchKey.bin"); - DISPATCH_SEED = FileUtils.readResource("/keys/dispatchSeed.bin"); - - ENCRYPT_KEY = FileUtils.readResource("/keys/secretKey.bin"); - ENCRYPT_SEED_BUFFER = FileUtils.readResource("/keys/secretKeyBuffer.bin"); - - try { - CUR_SIGNING_KEY = KeyFactory.getInstance("RSA") - .generatePrivate(new PKCS8EncodedKeySpec(FileUtils.readResource("/keys/SigningKey.der"))); - - Pattern pattern = Pattern.compile("([0-9]*)_Pub\\.der"); - for (Path path : FileUtils.getPathsFromResource("/keys/game_keys")) { - if (path.toString().endsWith("_Pub.der")) { - - var m = pattern.matcher(path.getFileName().toString()); - - if (m.matches()) { - var key = KeyFactory.getInstance("RSA") - .generatePublic(new X509EncodedKeySpec(FileUtils.read(path))); - - EncryptionKeys.put(Integer.valueOf(m.group(1)), key); - } - } - } - } catch (Exception e) { - Grasscutter.getLogger().error("An error occurred while loading keys.", e); - } - } - - public static void xor(byte[] packet, byte[] key) { - try { - for (int i = 0; i < packet.length; i++) { - packet[i] ^= key[i % key.length]; - } - } catch (Exception e) { - Grasscutter.getLogger().error("Crypto error.", e); - } - } - - public static byte[] createSessionKey(int length) { - byte[] bytes = new byte[length]; - secureRandom.nextBytes(bytes); - return bytes; - } -} +package emu.grasscutter.utils; + +import emu.grasscutter.Grasscutter; +import java.nio.file.Path; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +public final class Crypto { + private static final SecureRandom secureRandom = new SecureRandom(); + + public static byte[] DISPATCH_KEY; + public static byte[] DISPATCH_SEED; + + public static byte[] ENCRYPT_KEY; + public static long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968"); + public static byte[] ENCRYPT_SEED_BUFFER = new byte[0]; + + public static PrivateKey CUR_SIGNING_KEY; + + public static Map EncryptionKeys = new HashMap<>(); + + public static void loadKeys() { + DISPATCH_KEY = FileUtils.readResource("/keys/dispatchKey.bin"); + DISPATCH_SEED = FileUtils.readResource("/keys/dispatchSeed.bin"); + + ENCRYPT_KEY = FileUtils.readResource("/keys/secretKey.bin"); + ENCRYPT_SEED_BUFFER = FileUtils.readResource("/keys/secretKeyBuffer.bin"); + + try { + CUR_SIGNING_KEY = + KeyFactory.getInstance("RSA") + .generatePrivate( + new PKCS8EncodedKeySpec(FileUtils.readResource("/keys/SigningKey.der"))); + + Pattern pattern = Pattern.compile("([0-9]*)_Pub\\.der"); + for (Path path : FileUtils.getPathsFromResource("/keys/game_keys")) { + if (path.toString().endsWith("_Pub.der")) { + + var m = pattern.matcher(path.getFileName().toString()); + + if (m.matches()) { + var key = + KeyFactory.getInstance("RSA") + .generatePublic(new X509EncodedKeySpec(FileUtils.read(path))); + + EncryptionKeys.put(Integer.valueOf(m.group(1)), key); + } + } + } + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while loading keys.", e); + } + } + + public static void xor(byte[] packet, byte[] key) { + try { + for (int i = 0; i < packet.length; i++) { + packet[i] ^= key[i % key.length]; + } + } catch (Exception e) { + Grasscutter.getLogger().error("Crypto error.", e); + } + } + + public static byte[] createSessionKey(int length) { + byte[] bytes = new byte[length]; + secureRandom.nextBytes(bytes); + return bytes; + } +} diff --git a/src/main/java/emu/grasscutter/utils/DateHelper.java b/src/main/java/emu/grasscutter/utils/DateHelper.java index f78eec584..a8a0062b3 100644 --- a/src/main/java/emu/grasscutter/utils/DateHelper.java +++ b/src/main/java/emu/grasscutter/utils/DateHelper.java @@ -1,20 +1,20 @@ -package emu.grasscutter.utils; - -import java.util.Calendar; -import java.util.Date; - -public final class DateHelper { - public static Date onlyYearMonthDay(Date now) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(now); - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - return calendar.getTime(); - } - - public static int getUnixTime(Date localDateTime) { - return (int) (localDateTime.getTime() / 1000L); - } -} +package emu.grasscutter.utils; + +import java.util.Calendar; +import java.util.Date; + +public final class DateHelper { + public static Date onlyYearMonthDay(Date now) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + return calendar.getTime(); + } + + public static int getUnixTime(Date localDateTime) { + return (int) (localDateTime.getTime() / 1000L); + } +} diff --git a/src/main/java/emu/grasscutter/utils/FileUtils.java b/src/main/java/emu/grasscutter/utils/FileUtils.java index 78bbabe7f..c6d00402d 100644 --- a/src/main/java/emu/grasscutter/utils/FileUtils.java +++ b/src/main/java/emu/grasscutter/utils/FileUtils.java @@ -1,250 +1,265 @@ -package emu.grasscutter.utils; - -import emu.grasscutter.Grasscutter; -import lombok.val; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public final class FileUtils { - private static final Path DATA_DEFAULT_PATH; - private static final Path DATA_USER_PATH = Path.of(Grasscutter.config.folderStructure.data); - private static final Path PACKETS_PATH = Path.of(Grasscutter.config.folderStructure.packets); - private static final Path PLUGINS_PATH = Path.of(Grasscutter.config.folderStructure.plugins); - private static final Path RESOURCES_PATH; - private static final Path SCRIPTS_PATH; - private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"}; - - static { - FileSystem fs = null; - Path path = null; - // Setup access to jar resources - try { - var uri = Grasscutter.class.getResource("/defaults/data").toURI(); - switch (uri.getScheme()) { - case "jar": // When running normally, as a jar - case "zip": // Honestly I have no idea what setup would result in this, but this should work regardless - fs = FileSystems.newFileSystem(uri, Map.of()); // Have to mount zip filesystem. This leaks, but we want to keep it forever anyway. - // Fall-through - case "file": // When running in an IDE - path = Path.of(uri); // Can access directly - break; - default: - Grasscutter.getLogger().error("Invalid URI scheme for class resources: " + uri.getScheme()); - break; - } - } catch (URISyntaxException | IOException e) { - // Failed to load this jar. How? - Grasscutter.getLogger().error("Failed to load jar?!"); - } finally { - DATA_DEFAULT_PATH = path; - Grasscutter.getLogger().debug("Setting path for default data: " + path.toAbsolutePath()); - } - - // Setup Resources path - final String resources = Grasscutter.config.folderStructure.resources; - fs = null; - path = Path.of(resources); - if (resources.endsWith(".zip")) { // Would be nice to support .tar.gz too at some point, but it doesn't come for free in Java - try { - fs = FileSystems.newFileSystem(path); - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to load resources zip \"" + resources + "\""); - } - } - - if (fs != null) { - var root = fs.getPath(""); - try (Stream pathStream = Files.find(root, 3, (p, a) -> { - var filename = p.getFileName(); - if (filename == null) return false; - return filename.toString().equals("ExcelBinOutput"); - })) { - var excelBinOutput = pathStream.findFirst(); - if (excelBinOutput.isPresent()) { - path = excelBinOutput.get().getParent(); - if (path == null) - path = root; - Grasscutter.getLogger().debug("Resources will be loaded from \"" + resources + "/" + path + "\""); - } else { - Grasscutter.getLogger().error("Failed to find ExcelBinOutput in resources zip \"" + resources + "\""); - } - } catch (IOException e) { - Grasscutter.getLogger().error("Failed to scan resources zip \"" + resources + "\""); - } - } - RESOURCES_PATH = path; - - // Setup Scripts path - final String scripts = Grasscutter.config.folderStructure.scripts; - SCRIPTS_PATH = (scripts.startsWith("resources:")) - ? RESOURCES_PATH.resolve(scripts.substring("resources:".length())) - : Path.of(scripts); - } - - /* Apply after initialization. */ - private static final Path[] DATA_PATHS = {DATA_USER_PATH, DATA_DEFAULT_PATH}; - - public static Path getDataPathTsjJsonTsv(String filename) { - return getDataPathTsjJsonTsv(filename, true); - } - - public static Path getDataPathTsjJsonTsv(String filename, boolean fallback) { - val name = getFilenameWithoutExtension(filename); - for (val data_path : DATA_PATHS) { - for (val ext : TSJ_JSON_TSV) { - val path = data_path.resolve(name + "." + ext); - if (Files.exists(path)) return path; - } - } - return fallback ? DATA_USER_PATH.resolve(name + ".tsj") : null; // Maybe they want to write to a new file - } - - public static Path getDataPath(String path) { - Path userPath = DATA_USER_PATH.resolve(path); - if (Files.exists(userPath)) return userPath; - Path defaultPath = DATA_DEFAULT_PATH.resolve(path); - if (Files.exists(defaultPath)) return defaultPath; - return userPath; // Maybe they want to write to a new file - } - - public static Path getDataUserPath(String path) { - return DATA_USER_PATH.resolve(path); - } - - public static Path getPacketPath(String path) { - return PACKETS_PATH.resolve(path); - } - - public static Path getPluginPath(String path) { - return PLUGINS_PATH.resolve(path); - } - - public static Path getResourcePath(String path) { - return RESOURCES_PATH.resolve(path); - } - - public static Path getExcelPath(String filename) { - return getTsjJsonTsv(RESOURCES_PATH.resolve("ExcelBinOutput"), filename); - } - - // Gets path of a resource. - // If multiple formats of it exist, priority is TSJ > JSON > TSV - // If none exist, return the TSJ path, in case it wants to create a file - public static Path getTsjJsonTsv(Path root, String filename) { - val name = getFilenameWithoutExtension(filename); - for (val ext : TSJ_JSON_TSV) { - val path = root.resolve(name + "." + ext); - if (Files.exists(path)) return path; - } - return root.resolve(name + ".tsj"); - } - - public static Path getScriptPath(String path) { - return SCRIPTS_PATH.resolve(path); - } - - public static void write(String dest, byte[] bytes) { - Path path = Path.of(dest); - - try { - Files.write(path, bytes); - } catch (IOException e) { - Grasscutter.getLogger().warn("Failed to write file: " + dest); - } - } - - public static byte[] read(String dest) { - return read(Path.of(dest)); - } - - public static byte[] read(Path path) { - try { - return Files.readAllBytes(path); - } catch (IOException e) { - Grasscutter.getLogger().warn("Failed to read file: " + path); - } - - return new byte[0]; - } - - public static InputStream readResourceAsStream(String resourcePath) { - return Grasscutter.class.getResourceAsStream(resourcePath); - } - - public static byte[] readResource(String resourcePath) { - try (InputStream is = Grasscutter.class.getResourceAsStream(resourcePath)) { - return is.readAllBytes(); - } catch (Exception exception) { - Grasscutter.getLogger().warn("Failed to read resource: " + resourcePath); - exception.printStackTrace(); - } - - return new byte[0]; - } - - public static byte[] read(File file) { - return read(file.getPath()); - } - - public static void copyResource(String resourcePath, String destination) { - try { - byte[] resource = FileUtils.readResource(resourcePath); - FileUtils.write(destination, resource); - } catch (Exception exception) { - Grasscutter.getLogger().warn("Failed to copy resource: " + resourcePath + "\n" + exception); - } - } - - @Deprecated // Misnamed legacy function - public static String getFilenameWithoutPath(String filename) { - return getFilenameWithoutExtension(filename); - } - - public static String getFilenameWithoutExtension(String filename) { - int i = filename.lastIndexOf("."); - return (i < 0) ? filename : filename.substring(0, i); - } - - public static String getFileExtension(Path path) { - val filename = path.toString(); - int i = filename.lastIndexOf("."); - return (i < 0) ? "" : filename.substring(i + 1); - } - - public static List getPathsFromResource(String folder) throws URISyntaxException { - try { - // file walks JAR - return Files.walk(Path.of(Grasscutter.class.getResource(folder).toURI())) - .filter(Files::isRegularFile) - .collect(Collectors.toList()); - } catch (IOException e) { - // Eclipse puts resources in its bin folder - try { - return Files.walk(Path.of(System.getProperty("user.dir"), folder)) - .filter(Files::isRegularFile) - .collect(Collectors.toList()); - } catch (IOException ignored) { - return null; - } - } - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - public static String readToString(InputStream file) throws IOException { - byte[] content = file.readAllBytes(); - - return new String(content, StandardCharsets.UTF_8); - } -} +package emu.grasscutter.utils; + +import emu.grasscutter.Grasscutter; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lombok.val; + +public final class FileUtils { + private static final Path DATA_DEFAULT_PATH; + private static final Path DATA_USER_PATH = Path.of(Grasscutter.config.folderStructure.data); + private static final Path PACKETS_PATH = Path.of(Grasscutter.config.folderStructure.packets); + private static final Path PLUGINS_PATH = Path.of(Grasscutter.config.folderStructure.plugins); + private static final Path RESOURCES_PATH; + private static final Path SCRIPTS_PATH; + private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"}; + + static { + FileSystem fs = null; + Path path = null; + // Setup access to jar resources + try { + var uri = Grasscutter.class.getResource("/defaults/data").toURI(); + switch (uri.getScheme()) { + case "jar": // When running normally, as a jar + case "zip": // Honestly I have no idea what setup would result in this, but this should work + // regardless + fs = + FileSystems.newFileSystem( + uri, + Map.of()); // Have to mount zip filesystem. This leaks, but we want to keep it + // forever anyway. + // Fall-through + case "file": // When running in an IDE + path = Path.of(uri); // Can access directly + break; + default: + Grasscutter.getLogger() + .error("Invalid URI scheme for class resources: " + uri.getScheme()); + break; + } + } catch (URISyntaxException | IOException e) { + // Failed to load this jar. How? + Grasscutter.getLogger().error("Failed to load jar?!"); + } finally { + DATA_DEFAULT_PATH = path; + Grasscutter.getLogger().debug("Setting path for default data: " + path.toAbsolutePath()); + } + + // Setup Resources path + final String resources = Grasscutter.config.folderStructure.resources; + fs = null; + path = Path.of(resources); + if (resources.endsWith( + ".zip")) { // Would be nice to support .tar.gz too at some point, but it doesn't come for + // free in Java + try { + fs = FileSystems.newFileSystem(path); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to load resources zip \"" + resources + "\""); + } + } + + if (fs != null) { + var root = fs.getPath(""); + try (Stream pathStream = + Files.find( + root, + 3, + (p, a) -> { + var filename = p.getFileName(); + if (filename == null) return false; + return filename.toString().equals("ExcelBinOutput"); + })) { + var excelBinOutput = pathStream.findFirst(); + if (excelBinOutput.isPresent()) { + path = excelBinOutput.get().getParent(); + if (path == null) path = root; + Grasscutter.getLogger() + .debug("Resources will be loaded from \"" + resources + "/" + path + "\""); + } else { + Grasscutter.getLogger() + .error("Failed to find ExcelBinOutput in resources zip \"" + resources + "\""); + } + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to scan resources zip \"" + resources + "\""); + } + } + RESOURCES_PATH = path; + + // Setup Scripts path + final String scripts = Grasscutter.config.folderStructure.scripts; + SCRIPTS_PATH = + (scripts.startsWith("resources:")) + ? RESOURCES_PATH.resolve(scripts.substring("resources:".length())) + : Path.of(scripts); + } + + /* Apply after initialization. */ + private static final Path[] DATA_PATHS = {DATA_USER_PATH, DATA_DEFAULT_PATH}; + + public static Path getDataPathTsjJsonTsv(String filename) { + return getDataPathTsjJsonTsv(filename, true); + } + + public static Path getDataPathTsjJsonTsv(String filename, boolean fallback) { + val name = getFilenameWithoutExtension(filename); + for (val data_path : DATA_PATHS) { + for (val ext : TSJ_JSON_TSV) { + val path = data_path.resolve(name + "." + ext); + if (Files.exists(path)) return path; + } + } + return fallback + ? DATA_USER_PATH.resolve(name + ".tsj") + : null; // Maybe they want to write to a new file + } + + public static Path getDataPath(String path) { + Path userPath = DATA_USER_PATH.resolve(path); + if (Files.exists(userPath)) return userPath; + Path defaultPath = DATA_DEFAULT_PATH.resolve(path); + if (Files.exists(defaultPath)) return defaultPath; + return userPath; // Maybe they want to write to a new file + } + + public static Path getDataUserPath(String path) { + return DATA_USER_PATH.resolve(path); + } + + public static Path getPacketPath(String path) { + return PACKETS_PATH.resolve(path); + } + + public static Path getPluginPath(String path) { + return PLUGINS_PATH.resolve(path); + } + + public static Path getResourcePath(String path) { + return RESOURCES_PATH.resolve(path); + } + + public static Path getExcelPath(String filename) { + return getTsjJsonTsv(RESOURCES_PATH.resolve("ExcelBinOutput"), filename); + } + + // Gets path of a resource. + // If multiple formats of it exist, priority is TSJ > JSON > TSV + // If none exist, return the TSJ path, in case it wants to create a file + public static Path getTsjJsonTsv(Path root, String filename) { + val name = getFilenameWithoutExtension(filename); + for (val ext : TSJ_JSON_TSV) { + val path = root.resolve(name + "." + ext); + if (Files.exists(path)) return path; + } + return root.resolve(name + ".tsj"); + } + + public static Path getScriptPath(String path) { + return SCRIPTS_PATH.resolve(path); + } + + public static void write(String dest, byte[] bytes) { + Path path = Path.of(dest); + + try { + Files.write(path, bytes); + } catch (IOException e) { + Grasscutter.getLogger().warn("Failed to write file: " + dest); + } + } + + public static byte[] read(String dest) { + return read(Path.of(dest)); + } + + public static byte[] read(Path path) { + try { + return Files.readAllBytes(path); + } catch (IOException e) { + Grasscutter.getLogger().warn("Failed to read file: " + path); + } + + return new byte[0]; + } + + public static InputStream readResourceAsStream(String resourcePath) { + return Grasscutter.class.getResourceAsStream(resourcePath); + } + + public static byte[] readResource(String resourcePath) { + try (InputStream is = Grasscutter.class.getResourceAsStream(resourcePath)) { + return is.readAllBytes(); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to read resource: " + resourcePath); + exception.printStackTrace(); + } + + return new byte[0]; + } + + public static byte[] read(File file) { + return read(file.getPath()); + } + + public static void copyResource(String resourcePath, String destination) { + try { + byte[] resource = FileUtils.readResource(resourcePath); + FileUtils.write(destination, resource); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to copy resource: " + resourcePath + "\n" + exception); + } + } + + @Deprecated // Misnamed legacy function + public static String getFilenameWithoutPath(String filename) { + return getFilenameWithoutExtension(filename); + } + + public static String getFilenameWithoutExtension(String filename) { + int i = filename.lastIndexOf("."); + return (i < 0) ? filename : filename.substring(0, i); + } + + public static String getFileExtension(Path path) { + val filename = path.toString(); + int i = filename.lastIndexOf("."); + return (i < 0) ? "" : filename.substring(i + 1); + } + + public static List getPathsFromResource(String folder) throws URISyntaxException { + try { + // file walks JAR + return Files.walk(Path.of(Grasscutter.class.getResource(folder).toURI())) + .filter(Files::isRegularFile) + .collect(Collectors.toList()); + } catch (IOException e) { + // Eclipse puts resources in its bin folder + try { + return Files.walk(Path.of(System.getProperty("user.dir"), folder)) + .filter(Files::isRegularFile) + .collect(Collectors.toList()); + } catch (IOException ignored) { + return null; + } + } + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static String readToString(InputStream file) throws IOException { + byte[] content = file.readAllBytes(); + + return new String(content, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/emu/grasscutter/utils/JlineLogbackAppender.java b/src/main/java/emu/grasscutter/utils/JlineLogbackAppender.java index 2d066dcd3..d841cf6c2 100644 --- a/src/main/java/emu/grasscutter/utils/JlineLogbackAppender.java +++ b/src/main/java/emu/grasscutter/utils/JlineLogbackAppender.java @@ -1,19 +1,17 @@ -package emu.grasscutter.utils; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.ConsoleAppender; -import emu.grasscutter.Grasscutter; - -import java.util.Arrays; - -public class JlineLogbackAppender extends ConsoleAppender { - @Override - protected void append(ILoggingEvent eventObject) { - if (!started) { - return; - } - Arrays.stream( - new String(encoder.encode(eventObject)).split("\n\r") - ).forEach(Grasscutter.getConsole()::printAbove); - } -} +package emu.grasscutter.utils; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.ConsoleAppender; +import emu.grasscutter.Grasscutter; +import java.util.Arrays; + +public class JlineLogbackAppender extends ConsoleAppender { + @Override + protected void append(ILoggingEvent eventObject) { + if (!started) { + return; + } + Arrays.stream(new String(encoder.encode(eventObject)).split("\n\r")) + .forEach(Grasscutter.getConsole()::printAbove); + } +} diff --git a/src/main/java/emu/grasscutter/utils/JsonAdapters.java b/src/main/java/emu/grasscutter/utils/JsonAdapters.java index 457c8315e..ed7f504c0 100644 --- a/src/main/java/emu/grasscutter/utils/JsonAdapters.java +++ b/src/main/java/emu/grasscutter/utils/JsonAdapters.java @@ -1,177 +1,171 @@ -package emu.grasscutter.utils; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import emu.grasscutter.data.common.DynamicFloat; -import it.unimi.dsi.fastutil.floats.FloatArrayList; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import lombok.val; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Objects; - -public class JsonAdapters { - static class DynamicFloatAdapter extends TypeAdapter { - @Override - public DynamicFloat read(JsonReader reader) throws IOException { - switch (reader.peek()) { - case STRING: - return new DynamicFloat(reader.nextString()); - case NUMBER: - return new DynamicFloat((float) reader.nextDouble()); - case BOOLEAN: - return new DynamicFloat(reader.nextBoolean()); - case BEGIN_ARRAY: - reader.beginArray(); - val opStack = new ArrayList(); - while (reader.hasNext()) { - opStack.add(switch (reader.peek()) { - case STRING -> new DynamicFloat.StackOp(reader.nextString()); - case NUMBER -> new DynamicFloat.StackOp((float) reader.nextDouble()); - case BOOLEAN -> new DynamicFloat.StackOp(reader.nextBoolean()); - default -> - throw new IOException("Invalid DynamicFloat definition - " + reader.peek().name()); - }); - } - reader.endArray(); - return new DynamicFloat(opStack); - default: - throw new IOException("Invalid DynamicFloat definition - " + reader.peek().name()); - } - } - - @Override - public void write(JsonWriter writer, DynamicFloat f) { - } - - } - - static class IntListAdapter extends TypeAdapter { - @Override - public IntList read(JsonReader reader) throws IOException { - if (Objects.requireNonNull(reader.peek()) == JsonToken.BEGIN_ARRAY) { - reader.beginArray(); - val i = new IntArrayList(); - while (reader.hasNext()) - i.add(reader.nextInt()); - reader.endArray(); - i.trim(); // We might have a ton of these from resources and almost all of them immutable, don't overprovision! - return i; - } - throw new IOException("Invalid IntList definition - " + reader.peek().name()); - } - - @Override - public void write(JsonWriter writer, IntList l) throws IOException { - writer.beginArray(); - for (val i : l) // .forEach() doesn't appreciate exceptions - writer.value(i); - writer.endArray(); - } - - } - - static class PositionAdapter extends TypeAdapter { - @Override - public Position read(JsonReader reader) throws IOException { - switch (reader.peek()) { - case BEGIN_ARRAY: // "pos": [x,y,z] - reader.beginArray(); - val array = new FloatArrayList(3); - while (reader.hasNext()) - array.add(reader.nextInt()); - reader.endArray(); - return new Position(array); - case BEGIN_OBJECT: // "pos": {"x": x, "y": y, "z": z} - float x = 0f; - float y = 0f; - float z = 0f; - reader.beginObject(); - for (var next = reader.peek(); next != JsonToken.END_OBJECT; next = reader.peek()) { - val name = reader.nextName(); - switch (name) { - case "x", "X", "_x" -> x = (float) reader.nextDouble(); - case "y", "Y", "_y" -> y = (float) reader.nextDouble(); - case "z", "Z", "_z" -> z = (float) reader.nextDouble(); - default -> throw new IOException("Invalid field in Position definition - " + name); - } - } - reader.endObject(); - return new Position(x, y, z); - default: - throw new IOException("Invalid Position definition - " + reader.peek().name()); - } - } - - @Override - public void write(JsonWriter writer, Position i) throws IOException { - writer.beginArray(); - writer.value(i.getX()); - writer.value(i.getY()); - writer.value(i.getZ()); - writer.endArray(); - } - - } - - static class EnumTypeAdapterFactory implements TypeAdapterFactory { - @SuppressWarnings("unchecked") - public TypeAdapter create(Gson gson, TypeToken type) { - Class enumClass = (Class) type.getRawType(); - if (!enumClass.isEnum()) return null; - - // Make mappings of (string) names to enum constants - val map = new HashMap(); - val enumConstants = enumClass.getEnumConstants(); - for (val constant : enumConstants) - map.put(constant.toString(), constant); - - // If the enum also has a numeric value, map those to the constants too - // System.out.println("Looking for enum value field"); - for (Field f : enumClass.getDeclaredFields()) { - if (switch (f.getName()) { - case "value", "id" -> true; - default -> false; - }) { - // System.out.println("Enum value field found - " + f.getName()); - boolean acc = f.isAccessible(); - f.setAccessible(true); - try { - for (val constant : enumConstants) - map.put(String.valueOf(f.getInt(constant)), constant); - } catch (IllegalAccessException e) { - // System.out.println("Failed to access enum id field."); - } - f.setAccessible(acc); - break; - } - } - - return new TypeAdapter() { - public T read(JsonReader reader) throws IOException { - switch (reader.peek()) { - case STRING: - return map.get(reader.nextString()); - case NUMBER: - return map.get(String.valueOf(reader.nextInt())); - default: - throw new IOException("Invalid Enum definition - " + reader.peek().name()); - } - } - - public void write(JsonWriter writer, T value) throws IOException { - writer.value(value.toString()); - } - }; - } - } -} +package emu.grasscutter.utils; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import emu.grasscutter.data.common.DynamicFloat; +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Objects; +import lombok.val; + +public class JsonAdapters { + static class DynamicFloatAdapter extends TypeAdapter { + @Override + public DynamicFloat read(JsonReader reader) throws IOException { + switch (reader.peek()) { + case STRING: + return new DynamicFloat(reader.nextString()); + case NUMBER: + return new DynamicFloat((float) reader.nextDouble()); + case BOOLEAN: + return new DynamicFloat(reader.nextBoolean()); + case BEGIN_ARRAY: + reader.beginArray(); + val opStack = new ArrayList(); + while (reader.hasNext()) { + opStack.add( + switch (reader.peek()) { + case STRING -> new DynamicFloat.StackOp(reader.nextString()); + case NUMBER -> new DynamicFloat.StackOp((float) reader.nextDouble()); + case BOOLEAN -> new DynamicFloat.StackOp(reader.nextBoolean()); + default -> throw new IOException( + "Invalid DynamicFloat definition - " + reader.peek().name()); + }); + } + reader.endArray(); + return new DynamicFloat(opStack); + default: + throw new IOException("Invalid DynamicFloat definition - " + reader.peek().name()); + } + } + + @Override + public void write(JsonWriter writer, DynamicFloat f) {} + } + + static class IntListAdapter extends TypeAdapter { + @Override + public IntList read(JsonReader reader) throws IOException { + if (Objects.requireNonNull(reader.peek()) == JsonToken.BEGIN_ARRAY) { + reader.beginArray(); + val i = new IntArrayList(); + while (reader.hasNext()) i.add(reader.nextInt()); + reader.endArray(); + i.trim(); // We might have a ton of these from resources and almost all of them + // immutable, don't overprovision! + return i; + } + throw new IOException("Invalid IntList definition - " + reader.peek().name()); + } + + @Override + public void write(JsonWriter writer, IntList l) throws IOException { + writer.beginArray(); + for (val i : l) // .forEach() doesn't appreciate exceptions + writer.value(i); + writer.endArray(); + } + } + + static class PositionAdapter extends TypeAdapter { + @Override + public Position read(JsonReader reader) throws IOException { + switch (reader.peek()) { + case BEGIN_ARRAY: // "pos": [x,y,z] + reader.beginArray(); + val array = new FloatArrayList(3); + while (reader.hasNext()) array.add(reader.nextInt()); + reader.endArray(); + return new Position(array); + case BEGIN_OBJECT: // "pos": {"x": x, "y": y, "z": z} + float x = 0f; + float y = 0f; + float z = 0f; + reader.beginObject(); + for (var next = reader.peek(); next != JsonToken.END_OBJECT; next = reader.peek()) { + val name = reader.nextName(); + switch (name) { + case "x", "X", "_x" -> x = (float) reader.nextDouble(); + case "y", "Y", "_y" -> y = (float) reader.nextDouble(); + case "z", "Z", "_z" -> z = (float) reader.nextDouble(); + default -> throw new IOException("Invalid field in Position definition - " + name); + } + } + reader.endObject(); + return new Position(x, y, z); + default: + throw new IOException("Invalid Position definition - " + reader.peek().name()); + } + } + + @Override + public void write(JsonWriter writer, Position i) throws IOException { + writer.beginArray(); + writer.value(i.getX()); + writer.value(i.getY()); + writer.value(i.getZ()); + writer.endArray(); + } + } + + static class EnumTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + public TypeAdapter create(Gson gson, TypeToken type) { + Class enumClass = (Class) type.getRawType(); + if (!enumClass.isEnum()) return null; + + // Make mappings of (string) names to enum constants + val map = new HashMap(); + val enumConstants = enumClass.getEnumConstants(); + for (val constant : enumConstants) map.put(constant.toString(), constant); + + // If the enum also has a numeric value, map those to the constants too + // System.out.println("Looking for enum value field"); + for (Field f : enumClass.getDeclaredFields()) { + if (switch (f.getName()) { + case "value", "id" -> true; + default -> false; + }) { + // System.out.println("Enum value field found - " + f.getName()); + boolean acc = f.isAccessible(); + f.setAccessible(true); + try { + for (val constant : enumConstants) + map.put(String.valueOf(f.getInt(constant)), constant); + } catch (IllegalAccessException e) { + // System.out.println("Failed to access enum id field."); + } + f.setAccessible(acc); + break; + } + } + + return new TypeAdapter() { + public T read(JsonReader reader) throws IOException { + switch (reader.peek()) { + case STRING: + return map.get(reader.nextString()); + case NUMBER: + return map.get(String.valueOf(reader.nextInt())); + default: + throw new IOException("Invalid Enum definition - " + reader.peek().name()); + } + } + + public void write(JsonWriter writer, T value) throws IOException { + writer.value(value.toString()); + } + }; + } + } +} diff --git a/src/main/java/emu/grasscutter/utils/JsonUtils.java b/src/main/java/emu/grasscutter/utils/JsonUtils.java index a7bc65e62..64b43abca 100644 --- a/src/main/java/emu/grasscutter/utils/JsonUtils.java +++ b/src/main/java/emu/grasscutter/utils/JsonUtils.java @@ -1,118 +1,129 @@ -package emu.grasscutter.utils; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonSyntaxException; -import com.google.gson.reflect.TypeToken; -import emu.grasscutter.data.common.DynamicFloat; -import emu.grasscutter.utils.JsonAdapters.DynamicFloatAdapter; -import emu.grasscutter.utils.JsonAdapters.EnumTypeAdapterFactory; -import emu.grasscutter.utils.JsonAdapters.IntListAdapter; -import emu.grasscutter.utils.JsonAdapters.PositionAdapter; -import it.unimi.dsi.fastutil.ints.IntList; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -public final class JsonUtils { - static final Gson gson = new GsonBuilder() - .setPrettyPrinting() - .registerTypeAdapter(DynamicFloat.class, new DynamicFloatAdapter()) - .registerTypeAdapter(IntList.class, new IntListAdapter()) - .registerTypeAdapter(Position.class, new PositionAdapter()) - .registerTypeAdapterFactory(new EnumTypeAdapterFactory()) - .create(); - - /* - * Encode an object to a JSON string - */ - public static String encode(Object object) { - return gson.toJson(object); - } - - public static T decode(JsonElement jsonElement, Class classType) throws JsonSyntaxException { - return gson.fromJson(jsonElement, classType); - } - - public static T loadToClass(Reader fileReader, Class classType) throws IOException { - return gson.fromJson(fileReader, classType); - } - - @Deprecated(forRemoval = true) - public static T loadToClass(String filename, Class classType) throws IOException { - try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { - return loadToClass(fileReader, classType); - } - } - - public static T loadToClass(Path filename, Class classType) throws IOException { - try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - return loadToClass(fileReader, classType); - } - } - - public static List loadToList(Reader fileReader, Class classType) throws IOException { - return gson.fromJson(fileReader, TypeToken.getParameterized(List.class, classType).getType()); - } - - @Deprecated(forRemoval = true) - public static List loadToList(String filename, Class classType) throws IOException { - try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { - return loadToList(fileReader, classType); - } - } - - public static List loadToList(Path filename, Class classType) throws IOException { - try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - return loadToList(fileReader, classType); - } - } - - public static Map loadToMap(Reader fileReader, Class keyType, Class valueType) throws IOException { - return gson.fromJson(fileReader, TypeToken.getParameterized(Map.class, keyType, valueType).getType()); - } - - @Deprecated(forRemoval = true) - public static Map loadToMap(String filename, Class keyType, Class valueType) throws IOException { - try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { - return loadToMap(fileReader, keyType, valueType); - } - } - - public static Map loadToMap(Path filename, Class keyType, Class valueType) throws IOException { - try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - return loadToMap(fileReader, keyType, valueType); - } - } - - /** - * Safely JSON decodes a given string. - * - * @param jsonData The JSON-encoded data. - * @return JSON decoded data, or null if an exception occurred. - */ - public static T decode(String jsonData, Class classType) { - try { - return gson.fromJson(jsonData, classType); - } catch (Exception ignored) { - return null; - } - } - - public static T decode(String jsonData, Type type) { - try { - return gson.fromJson(jsonData, type); - } catch (Exception ignored) { - return null; - } - } -} +package emu.grasscutter.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import emu.grasscutter.data.common.DynamicFloat; +import emu.grasscutter.utils.JsonAdapters.DynamicFloatAdapter; +import emu.grasscutter.utils.JsonAdapters.EnumTypeAdapterFactory; +import emu.grasscutter.utils.JsonAdapters.IntListAdapter; +import emu.grasscutter.utils.JsonAdapters.PositionAdapter; +import it.unimi.dsi.fastutil.ints.IntList; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +public final class JsonUtils { + static final Gson gson = + new GsonBuilder() + .setPrettyPrinting() + .registerTypeAdapter(DynamicFloat.class, new DynamicFloatAdapter()) + .registerTypeAdapter(IntList.class, new IntListAdapter()) + .registerTypeAdapter(Position.class, new PositionAdapter()) + .registerTypeAdapterFactory(new EnumTypeAdapterFactory()) + .create(); + + /* + * Encode an object to a JSON string + */ + public static String encode(Object object) { + return gson.toJson(object); + } + + public static T decode(JsonElement jsonElement, Class classType) + throws JsonSyntaxException { + return gson.fromJson(jsonElement, classType); + } + + public static T loadToClass(Reader fileReader, Class classType) throws IOException { + return gson.fromJson(fileReader, classType); + } + + @Deprecated(forRemoval = true) + public static T loadToClass(String filename, Class classType) throws IOException { + try (InputStreamReader fileReader = + new InputStreamReader( + new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadToClass(fileReader, classType); + } + } + + public static T loadToClass(Path filename, Class classType) throws IOException { + try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + return loadToClass(fileReader, classType); + } + } + + public static List loadToList(Reader fileReader, Class classType) throws IOException { + return gson.fromJson(fileReader, TypeToken.getParameterized(List.class, classType).getType()); + } + + @Deprecated(forRemoval = true) + public static List loadToList(String filename, Class classType) throws IOException { + try (InputStreamReader fileReader = + new InputStreamReader( + new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadToList(fileReader, classType); + } + } + + public static List loadToList(Path filename, Class classType) throws IOException { + try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + return loadToList(fileReader, classType); + } + } + + public static Map loadToMap( + Reader fileReader, Class keyType, Class valueType) throws IOException { + return gson.fromJson( + fileReader, TypeToken.getParameterized(Map.class, keyType, valueType).getType()); + } + + @Deprecated(forRemoval = true) + public static Map loadToMap( + String filename, Class keyType, Class valueType) throws IOException { + try (InputStreamReader fileReader = + new InputStreamReader( + new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) { + return loadToMap(fileReader, keyType, valueType); + } + } + + public static Map loadToMap( + Path filename, Class keyType, Class valueType) throws IOException { + try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + return loadToMap(fileReader, keyType, valueType); + } + } + + /** + * Safely JSON decodes a given string. + * + * @param jsonData The JSON-encoded data. + * @return JSON decoded data, or null if an exception occurred. + */ + public static T decode(String jsonData, Class classType) { + try { + return gson.fromJson(jsonData, classType); + } catch (Exception ignored) { + return null; + } + } + + public static T decode(String jsonData, Type type) { + try { + return gson.fromJson(jsonData, type); + } catch (Exception ignored) { + return null; + } + } +} diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index f92bdc090..3199d98b1 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -1,466 +1,513 @@ -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 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 static emu.grasscutter.config.Configuration.FALLBACK_LANGUAGE; -import static emu.grasscutter.utils.FileUtils.getResourcePath; - -public final class Language { - private static final Map 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 textMapStrings; - private final String languageCode; - private final Map 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 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 loadTextMapFile(String language, IntSet nameHashes) { - Int2ObjectMap 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 loadTextMapFiles(IntSet nameHashes) { - Map> 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> languageMaps = - IntStream.range(0, TextStrings.NUM_LANGUAGES) - .mapToObj(i -> mapLanguageMaps.get(i)) - .collect(Collectors.toList()); - - Map canonicalTextStrings = new HashMap<>(); - return new Int2ObjectOpenHashMap( - 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 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) file.readObject(); - } - } - - private static void saveTextMapsCache(Int2ObjectMap 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 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 LIST_LANGUAGES = Arrays.asList(ARR_LANGUAGES); - public static final Object2IntMap 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 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 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 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 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 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 textMapStrings; + private final String languageCode; + private final Map 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 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 loadTextMapFile(String language, IntSet nameHashes) { + Int2ObjectMap 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 loadTextMapFiles(IntSet nameHashes) { + Map> + 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> languageMaps = + IntStream.range(0, TextStrings.NUM_LANGUAGES) + .mapToObj(i -> mapLanguageMaps.get(i)) + .collect(Collectors.toList()); + + Map canonicalTextStrings = new HashMap<>(); + return new Int2ObjectOpenHashMap( + 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 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) file.readObject(); + } + } + + private static void saveTextMapsCache(Int2ObjectMap 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 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 LIST_LANGUAGES = Arrays.asList(ARR_LANGUAGES); + public static final Object2IntMap + 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 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 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 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; + } + } +} diff --git a/src/main/java/emu/grasscutter/utils/Location.java b/src/main/java/emu/grasscutter/utils/Location.java index c3811ff68..00718bf9c 100644 --- a/src/main/java/emu/grasscutter/utils/Location.java +++ b/src/main/java/emu/grasscutter/utils/Location.java @@ -1,43 +1,40 @@ -package emu.grasscutter.utils; - -import dev.morphia.annotations.Entity; -import dev.morphia.annotations.Transient; -import emu.grasscutter.game.world.Scene; -import lombok.Getter; -import lombok.Setter; - -@Entity -public class Location extends Position { - @Transient - @Getter - @Setter - private Scene scene; - - public Location(Scene scene, Position position) { - this.set(position); - - this.scene = scene; - } - - public Location(Scene scene, float x, float y) { - this.set(x, y); - - this.scene = scene; - } - - public Location(Scene scene, float x, float y, float z) { - this.set(x, y, z); - - this.scene = scene; - } - - @Override - public Location clone() { - return new Location(this.scene, super.clone()); - } - - @Override - public String toString() { - return String.format("%s:%s,%s,%s", this.scene.getId(), this.getX(), this.getY(), this.getZ()); - } -} +package emu.grasscutter.utils; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.game.world.Scene; +import lombok.Getter; +import lombok.Setter; + +@Entity +public class Location extends Position { + @Transient @Getter @Setter private Scene scene; + + public Location(Scene scene, Position position) { + this.set(position); + + this.scene = scene; + } + + public Location(Scene scene, float x, float y) { + this.set(x, y); + + this.scene = scene; + } + + public Location(Scene scene, float x, float y, float z) { + this.set(x, y, z); + + this.scene = scene; + } + + @Override + public Location clone() { + return new Location(this.scene, super.clone()); + } + + @Override + public String toString() { + return String.format("%s:%s,%s,%s", this.scene.getId(), this.getX(), this.getY(), this.getZ()); + } +} diff --git a/src/main/java/emu/grasscutter/utils/MessageHandler.java b/src/main/java/emu/grasscutter/utils/MessageHandler.java index 19c795731..db4e9f527 100644 --- a/src/main/java/emu/grasscutter/utils/MessageHandler.java +++ b/src/main/java/emu/grasscutter/utils/MessageHandler.java @@ -1,21 +1,21 @@ -package emu.grasscutter.utils; - -public class MessageHandler { - private String message; - - public MessageHandler() { - this.message = ""; - } - - public void append(String message) { - this.message += message + "\r\n\r\n"; - } - - public String getMessage() { - return this.message; - } - - public void setMessage(String message) { - this.message = message; - } -} +package emu.grasscutter.utils; + +public class MessageHandler { + private String message; + + public MessageHandler() { + this.message = ""; + } + + public void append(String message) { + this.message += message + "\r\n\r\n"; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/emu/grasscutter/utils/Position.java b/src/main/java/emu/grasscutter/utils/Position.java index 17d6bcaed..fe2a6c42f 100644 --- a/src/main/java/emu/grasscutter/utils/Position.java +++ b/src/main/java/emu/grasscutter/utils/Position.java @@ -1,201 +1,196 @@ -package emu.grasscutter.utils; - -import com.github.davidmoten.rtreemulti.geometry.Point; -import com.google.gson.annotations.SerializedName; -import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; -import lombok.Getter; -import lombok.Setter; - -import java.io.Serializable; -import java.util.List; - -@Entity -public class Position implements Serializable { - private static final long serialVersionUID = -2001232313615923575L; - - @SerializedName(value = "x", alternate = {"_x", "X"}) - @Getter - @Setter - private float x; - - @SerializedName(value = "y", alternate = {"_y", "Y"}) - @Getter - @Setter - private float y; - - @SerializedName(value = "z", alternate = {"_z", "Z"}) - @Getter - @Setter - private float z; - - public Position() { - } - - public Position(float x, float y) { - set(x, y); - } - - public Position(float x, float y, float z) { - set(x, y, z); - } - - public Position(List xyz) { - switch (xyz.size()) { - default: // Might want to error on excess elements, but maybe we want to extend to 3+3 representation later. - case 3: - this.z = xyz.get(2); // Fall-through - case 2: - this.y = xyz.get(1); // Fall-through - case 1: - this.y = xyz.get(0); // pointless fall-through - case 0: - break; - } - } - - public Position(String p) { - String[] split = p.split(","); - if (split.length >= 2) { - this.x = Float.parseFloat(split[0]); - this.y = Float.parseFloat(split[1]); - } - if (split.length >= 3) { - this.z = Float.parseFloat(split[2]); - } - } - - public Position(Vector vector) { - this.set(vector); - } - - public Position(Position pos) { - this.set(pos); - } - - public Position set(float x, float y) { - this.x = x; - this.y = y; - return this; - } - - // Deep copy - public Position set(Position pos) { - return this.set(pos.getX(), pos.getY(), pos.getZ()); - } - - public Position set(Vector pos) { - return this.set(pos.getX(), pos.getY(), pos.getZ()); - } - - public Position set(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - public Position add(Position add) { - this.x += add.getX(); - this.y += add.getY(); - this.z += add.getZ(); - return this; - } - - public Position addX(float d) { - this.x += d; - return this; - } - - public Position addY(float d) { - this.y += d; - return this; - } - - public Position addZ(float d) { - this.z += d; - return this; - } - - public Position subtract(Position sub) { - this.x -= sub.getX(); - this.y -= sub.getY(); - this.z -= sub.getZ(); - return this; - } - - /** - * In radians - */ - public Position translate(float dist, float angle) { - this.x += dist * Math.sin(angle); - this.y += dist * Math.cos(angle); - return this; - } - - public boolean equal2d(Position other) { - // Y is height - return getX() == other.getX() && getZ() == other.getZ(); - } - - public boolean equal3d(Position other) { - return getX() == other.getX() && getY() == other.getY() && getZ() == other.getZ(); - } - - public double computeDistance(Position b) { - double detX = getX() - b.getX(); - double detY = getY() - b.getY(); - double detZ = getZ() - b.getZ(); - return Math.sqrt(detX * detX + detY * detY + detZ * detZ); - } - - public Position nearby2d(float range) { - Position position = clone(); - position.z += Utils.randomFloatRange(-range, range); - position.x += Utils.randomFloatRange(-range, range); - return position; - } - - public Position translateWithDegrees(float dist, float angle) { - angle = (float) Math.toRadians(angle); - this.x += dist * Math.sin(angle); - this.y += -dist * Math.cos(angle); - return this; - } - - @Override - public Position clone() { - return new Position(x, y, z); - } - - @Override - public String toString() { - return "(" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")"; - } - - public Vector toProto() { - return Vector.newBuilder() - .setX(this.getX()) - .setY(this.getY()) - .setZ(this.getZ()) - .build(); - } - - public Point toPoint() { - return Point.create(x, y, z); - } - - /** - * To XYZ array for Spatial Index - */ - public double[] toDoubleArray() { - return new double[]{x, y, z}; - } - - /** - * To XZ array for Spatial Index (Blocks) - */ - public double[] toXZDoubleArray() { - return new double[]{x, z}; - } -} +package emu.grasscutter.utils; + +import com.github.davidmoten.rtreemulti.geometry.Point; +import com.google.gson.annotations.SerializedName; +import dev.morphia.annotations.Entity; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import java.io.Serializable; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Entity +public class Position implements Serializable { + private static final long serialVersionUID = -2001232313615923575L; + + @SerializedName( + value = "x", + alternate = {"_x", "X"}) + @Getter + @Setter + private float x; + + @SerializedName( + value = "y", + alternate = {"_y", "Y"}) + @Getter + @Setter + private float y; + + @SerializedName( + value = "z", + alternate = {"_z", "Z"}) + @Getter + @Setter + private float z; + + public Position() {} + + public Position(float x, float y) { + set(x, y); + } + + public Position(float x, float y, float z) { + set(x, y, z); + } + + public Position(List xyz) { + switch (xyz.size()) { + default: // Might want to error on excess elements, but maybe we want to extend to 3+3 + // representation later. + case 3: + this.z = xyz.get(2); // Fall-through + case 2: + this.y = xyz.get(1); // Fall-through + case 1: + this.y = xyz.get(0); // pointless fall-through + case 0: + break; + } + } + + public Position(String p) { + String[] split = p.split(","); + if (split.length >= 2) { + this.x = Float.parseFloat(split[0]); + this.y = Float.parseFloat(split[1]); + } + if (split.length >= 3) { + this.z = Float.parseFloat(split[2]); + } + } + + public Position(Vector vector) { + this.set(vector); + } + + public Position(Position pos) { + this.set(pos); + } + + public Position set(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + // Deep copy + public Position set(Position pos) { + return this.set(pos.getX(), pos.getY(), pos.getZ()); + } + + public Position set(Vector pos) { + return this.set(pos.getX(), pos.getY(), pos.getZ()); + } + + public Position set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + + public Position add(Position add) { + this.x += add.getX(); + this.y += add.getY(); + this.z += add.getZ(); + return this; + } + + public Position addX(float d) { + this.x += d; + return this; + } + + public Position addY(float d) { + this.y += d; + return this; + } + + public Position addZ(float d) { + this.z += d; + return this; + } + + public Position subtract(Position sub) { + this.x -= sub.getX(); + this.y -= sub.getY(); + this.z -= sub.getZ(); + return this; + } + + /** In radians */ + public Position translate(float dist, float angle) { + this.x += dist * Math.sin(angle); + this.y += dist * Math.cos(angle); + return this; + } + + public boolean equal2d(Position other) { + // Y is height + return getX() == other.getX() && getZ() == other.getZ(); + } + + public boolean equal3d(Position other) { + return getX() == other.getX() && getY() == other.getY() && getZ() == other.getZ(); + } + + public double computeDistance(Position b) { + double detX = getX() - b.getX(); + double detY = getY() - b.getY(); + double detZ = getZ() - b.getZ(); + return Math.sqrt(detX * detX + detY * detY + detZ * detZ); + } + + public Position nearby2d(float range) { + Position position = clone(); + position.z += Utils.randomFloatRange(-range, range); + position.x += Utils.randomFloatRange(-range, range); + return position; + } + + public Position translateWithDegrees(float dist, float angle) { + angle = (float) Math.toRadians(angle); + this.x += dist * Math.sin(angle); + this.y += -dist * Math.cos(angle); + return this; + } + + @Override + public Position clone() { + return new Position(x, y, z); + } + + @Override + public String toString() { + return "(" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")"; + } + + public Vector toProto() { + return Vector.newBuilder().setX(this.getX()).setY(this.getY()).setZ(this.getZ()).build(); + } + + public Point toPoint() { + return Point.create(x, y, z); + } + + /** To XYZ array for Spatial Index */ + public double[] toDoubleArray() { + return new double[] {x, y, z}; + } + + /** To XZ array for Spatial Index (Blocks) */ + public double[] toXZDoubleArray() { + return new double[] {x, z}; + } +} diff --git a/src/main/java/emu/grasscutter/utils/ProtoHelper.java b/src/main/java/emu/grasscutter/utils/ProtoHelper.java index 9a79161fd..9ecd76ac6 100644 --- a/src/main/java/emu/grasscutter/utils/ProtoHelper.java +++ b/src/main/java/emu/grasscutter/utils/ProtoHelper.java @@ -1,10 +1,10 @@ -package emu.grasscutter.utils; - -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; - -public final class ProtoHelper { - public static PropValue newPropValue(PlayerProperty key, int value) { - return PropValue.newBuilder().setType(key.getId()).setIval(value).setVal(value).build(); - } -} +package emu.grasscutter.utils; + +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.proto.PropValueOuterClass.PropValue; + +public final class ProtoHelper { + public static PropValue newPropValue(PlayerProperty key, int value) { + return PropValue.newBuilder().setType(key.getId()).setIval(value).setVal(value).build(); + } +} diff --git a/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java b/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java index 7ee833b3c..7c0287faa 100644 --- a/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java +++ b/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java @@ -1,27 +1,27 @@ -package emu.grasscutter.utils; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import ch.qos.logback.core.encoder.Encoder; -import emu.grasscutter.server.event.internal.ServerLogEvent; - -import java.nio.charset.StandardCharsets; - -public class ServerLogEventAppender extends AppenderBase { - protected Encoder encoder; - - @Override - protected void append(E event) { - byte[] byteArray = this.encoder.encode(event); - ServerLogEvent sle = new ServerLogEvent((ILoggingEvent) event, new String(byteArray, StandardCharsets.UTF_8)); - sle.call(); - } - - public Encoder getEncoder() { - return this.encoder; - } - - public void setEncoder(Encoder encoder) { - this.encoder = encoder; - } -} +package emu.grasscutter.utils; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.encoder.Encoder; +import emu.grasscutter.server.event.internal.ServerLogEvent; +import java.nio.charset.StandardCharsets; + +public class ServerLogEventAppender extends AppenderBase { + protected Encoder encoder; + + @Override + protected void append(E event) { + byte[] byteArray = this.encoder.encode(event); + ServerLogEvent sle = + new ServerLogEvent((ILoggingEvent) event, new String(byteArray, StandardCharsets.UTF_8)); + sle.call(); + } + + public Encoder getEncoder() { + return this.encoder; + } + + public void setEncoder(Encoder encoder) { + this.encoder = encoder; + } +} diff --git a/src/main/java/emu/grasscutter/utils/SparseSet.java b/src/main/java/emu/grasscutter/utils/SparseSet.java index 64119498b..be536b121 100644 --- a/src/main/java/emu/grasscutter/utils/SparseSet.java +++ b/src/main/java/emu/grasscutter/utils/SparseSet.java @@ -1,59 +1,67 @@ -package emu.grasscutter.utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -public final class SparseSet { - private final List rangeEntries; - private final Set denseEntries; - public SparseSet(String csv) { - this.rangeEntries = new ArrayList<>(); - this.denseEntries = new TreeSet<>(); - - for (String token : csv.replace("\n", "").replace(" ", "").split(",")) { - String[] tokens = token.split("-"); - switch (tokens.length) { - case 1: - this.denseEntries.add(Integer.parseInt(tokens[0])); - break; - case 2: - this.rangeEntries.add(new Range(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]))); - break; - default: - throw new IllegalArgumentException("Invalid token passed to SparseSet initializer - " + token + " (split length " + tokens.length + ")"); - } - } - } - - public boolean contains(int i) { - for (Range range : this.rangeEntries) { - if (range.check(i)) { - return true; - } - } - return this.denseEntries.contains(i); - } - - /* - * A convenience class for constructing integer sets out of large ranges - * Designed to be fed literal strings from this project only - - * can and will throw exceptions to tell you to fix your code if you feed it garbage. :) - */ - private static class Range { - private final int min, max; - - public Range(int min, int max) { - if (min > max) { - throw new IllegalArgumentException("Range passed minimum higher than maximum - " + min + " > " + max); - } - this.min = min; - this.max = max; - } - - public boolean check(int value) { - return value >= this.min && value <= this.max; - } - } -} +package emu.grasscutter.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public final class SparseSet { + private final List rangeEntries; + private final Set denseEntries; + + public SparseSet(String csv) { + this.rangeEntries = new ArrayList<>(); + this.denseEntries = new TreeSet<>(); + + for (String token : csv.replace("\n", "").replace(" ", "").split(",")) { + String[] tokens = token.split("-"); + switch (tokens.length) { + case 1: + this.denseEntries.add(Integer.parseInt(tokens[0])); + break; + case 2: + this.rangeEntries.add( + new Range(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]))); + break; + default: + throw new IllegalArgumentException( + "Invalid token passed to SparseSet initializer - " + + token + + " (split length " + + tokens.length + + ")"); + } + } + } + + public boolean contains(int i) { + for (Range range : this.rangeEntries) { + if (range.check(i)) { + return true; + } + } + return this.denseEntries.contains(i); + } + + /* + * A convenience class for constructing integer sets out of large ranges + * Designed to be fed literal strings from this project only - + * can and will throw exceptions to tell you to fix your code if you feed it garbage. :) + */ + private static class Range { + private final int min, max; + + public Range(int min, int max) { + if (min > max) { + throw new IllegalArgumentException( + "Range passed minimum higher than maximum - " + min + " > " + max); + } + this.min = min; + this.max = max; + } + + public boolean check(int value) { + return value >= this.min && value <= this.max; + } + } +} diff --git a/src/main/java/emu/grasscutter/utils/StartupArguments.java b/src/main/java/emu/grasscutter/utils/StartupArguments.java index 757609816..0adfee7bd 100644 --- a/src/main/java/emu/grasscutter/utils/StartupArguments.java +++ b/src/main/java/emu/grasscutter/utils/StartupArguments.java @@ -1,131 +1,129 @@ -package emu.grasscutter.utils; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import emu.grasscutter.BuildConfig; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.net.packet.PacketOpcodesUtils; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.function.Function; - -import static emu.grasscutter.config.Configuration.*; - -/** - * A parser for start-up arguments. - */ -public final class StartupArguments { - /* A map of parameter -> argument handler. */ - private static final Map> argumentHandlers = Map.of( - "-dumppacketids", parameter -> { - PacketOpcodesUtils.dumpPacketIds(); - return true; - }, - "-version", StartupArguments::printVersion, - "-debug", StartupArguments::enableDebug, - "-lang", parameter -> { - Grasscutter.setPreferredLanguage(parameter); - return false; - }, - "-game", parameter -> { - Grasscutter.setRunModeOverride(ServerRunMode.GAME_ONLY); - return false; - }, - "-dispatch", parameter -> { - Grasscutter.setRunModeOverride(ServerRunMode.DISPATCH_ONLY); - return false; - }, - "-test", parameter -> { - // Disable the console. - SERVER.game.enableConsole = false; - // Disable HTTP encryption. - SERVER.http.encryption.useEncryption = false; - return false; - }, - - // Aliases. - "-v", StartupArguments::printVersion, - "-debugall", parameter -> { - StartupArguments.enableDebug("all"); - return false; - } - ); - - private StartupArguments() { - // This class is not meant to be instantiated. - } - - /** - * Parses the provided start-up arguments. - * - * @param args The application start-up arguments. - * @return If the application should exit. - */ - public static boolean parse(String[] args) { - boolean exitEarly = false; - - // Parse the arguments. - for (var input : args) { - var containsParameter = input.contains("="); - - var argument = containsParameter ? input.split("=")[0] : input; - var handler = argumentHandlers.get(argument.toLowerCase()); - - if (handler != null) { - exitEarly |= handler.apply(containsParameter ? input.split("=")[1] : null); - } - } - - return exitEarly; - } - - /** - * Prints the server version. - * - * @param parameter Additional parameters. - * @return True to exit early. - */ - private static boolean printVersion(String parameter) { - System.out.println("Grasscutter version: " + BuildConfig.VERSION + "-" + BuildConfig.GIT_HASH); - return true; - } - - /** - * Enables debug logging. - * - * @param parameter Additional parameters. - * @return False to continue execution. - */ - private static boolean enableDebug(String parameter) { - if (parameter != null && parameter.equals("all")) { - // Override default debug configs - GAME_INFO.isShowLoopPackets = DEBUG_MODE_INFO.isShowLoopPackets; - GAME_INFO.isShowPacketPayload = DEBUG_MODE_INFO.isShowPacketPayload; - GAME_INFO.logPackets = DEBUG_MODE_INFO.logPackets; - DISPATCH_INFO.logRequests = DEBUG_MODE_INFO.logRequests; - } - - // Set the main logger to debug. - Grasscutter.getLogger().setLevel(DEBUG_MODE_INFO.serverLoggerLevel); - Grasscutter.getLogger().debug("The logger is now running in debug mode."); - - // Log level to other third-party services - Level loggerLevel = DEBUG_MODE_INFO.servicesLoggersLevel; - - // Change loggers to debug. - ((Logger) LoggerFactory.getLogger("io.javalin")) - .setLevel(loggerLevel); - ((Logger) LoggerFactory.getLogger("org.quartz")) - .setLevel(loggerLevel); - ((Logger) LoggerFactory.getLogger("org.reflections")) - .setLevel(loggerLevel); - ((Logger) LoggerFactory.getLogger("org.eclipse.jetty")) - .setLevel(loggerLevel); - ((Logger) LoggerFactory.getLogger("org.mongodb.driver")) - .setLevel(loggerLevel); - - return false; - } -} +package emu.grasscutter.utils; + +import static emu.grasscutter.config.Configuration.*; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import emu.grasscutter.BuildConfig; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.net.packet.PacketOpcodesUtils; +import java.util.Map; +import java.util.function.Function; +import org.slf4j.LoggerFactory; + +/** A parser for start-up arguments. */ +public final class StartupArguments { + /* A map of parameter -> argument handler. */ + private static final Map> argumentHandlers = + Map.of( + "-dumppacketids", + parameter -> { + PacketOpcodesUtils.dumpPacketIds(); + return true; + }, + "-version", StartupArguments::printVersion, + "-debug", StartupArguments::enableDebug, + "-lang", + parameter -> { + Grasscutter.setPreferredLanguage(parameter); + return false; + }, + "-game", + parameter -> { + Grasscutter.setRunModeOverride(ServerRunMode.GAME_ONLY); + return false; + }, + "-dispatch", + parameter -> { + Grasscutter.setRunModeOverride(ServerRunMode.DISPATCH_ONLY); + return false; + }, + "-test", + parameter -> { + // Disable the console. + SERVER.game.enableConsole = false; + // Disable HTTP encryption. + SERVER.http.encryption.useEncryption = false; + return false; + }, + + // Aliases. + "-v", StartupArguments::printVersion, + "-debugall", + parameter -> { + StartupArguments.enableDebug("all"); + return false; + }); + + private StartupArguments() { + // This class is not meant to be instantiated. + } + + /** + * Parses the provided start-up arguments. + * + * @param args The application start-up arguments. + * @return If the application should exit. + */ + public static boolean parse(String[] args) { + boolean exitEarly = false; + + // Parse the arguments. + for (var input : args) { + var containsParameter = input.contains("="); + + var argument = containsParameter ? input.split("=")[0] : input; + var handler = argumentHandlers.get(argument.toLowerCase()); + + if (handler != null) { + exitEarly |= handler.apply(containsParameter ? input.split("=")[1] : null); + } + } + + return exitEarly; + } + + /** + * Prints the server version. + * + * @param parameter Additional parameters. + * @return True to exit early. + */ + private static boolean printVersion(String parameter) { + System.out.println("Grasscutter version: " + BuildConfig.VERSION + "-" + BuildConfig.GIT_HASH); + return true; + } + + /** + * Enables debug logging. + * + * @param parameter Additional parameters. + * @return False to continue execution. + */ + private static boolean enableDebug(String parameter) { + if (parameter != null && parameter.equals("all")) { + // Override default debug configs + GAME_INFO.isShowLoopPackets = DEBUG_MODE_INFO.isShowLoopPackets; + GAME_INFO.isShowPacketPayload = DEBUG_MODE_INFO.isShowPacketPayload; + GAME_INFO.logPackets = DEBUG_MODE_INFO.logPackets; + DISPATCH_INFO.logRequests = DEBUG_MODE_INFO.logRequests; + } + + // Set the main logger to debug. + Grasscutter.getLogger().setLevel(DEBUG_MODE_INFO.serverLoggerLevel); + Grasscutter.getLogger().debug("The logger is now running in debug mode."); + + // Log level to other third-party services + Level loggerLevel = DEBUG_MODE_INFO.servicesLoggersLevel; + + // Change loggers to debug. + ((Logger) LoggerFactory.getLogger("io.javalin")).setLevel(loggerLevel); + ((Logger) LoggerFactory.getLogger("org.quartz")).setLevel(loggerLevel); + ((Logger) LoggerFactory.getLogger("org.reflections")).setLevel(loggerLevel); + ((Logger) LoggerFactory.getLogger("org.eclipse.jetty")).setLevel(loggerLevel); + ((Logger) LoggerFactory.getLogger("org.mongodb.driver")).setLevel(loggerLevel); + + return false; + } +} diff --git a/src/main/java/emu/grasscutter/utils/TsvUtils.java b/src/main/java/emu/grasscutter/utils/TsvUtils.java index 691422388..4c0c96fc5 100644 --- a/src/main/java/emu/grasscutter/utils/TsvUtils.java +++ b/src/main/java/emu/grasscutter/utils/TsvUtils.java @@ -1,590 +1,682 @@ -package emu.grasscutter.utils; - -import com.google.gson.*; -import com.google.gson.annotations.SerializedName; -import emu.grasscutter.Grasscutter; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap; -import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; -import lombok.val; - -import java.io.IOException; -import java.lang.reflect.*; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.*; -import java.util.function.Function; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static emu.grasscutter.utils.Utils.nonRegexSplit; - -// Throughout this file, commented System.out.println debug log calls are left in. -// This is because the default logger will deadlock when operating on parallel streams. -public class TsvUtils { - private static final Map defaultValues = Map.ofEntries( - // Map.entry(String.class, null), // builder hates null values - Map.entry(Integer.class, 0), - Map.entry(int.class, 0), - Map.entry(Long.class, 0L), - Map.entry(long.class, 0L), - Map.entry(Float.class, 0f), - Map.entry(float.class, 0f), - Map.entry(Double.class, 0d), - Map.entry(double.class, 0d), - Map.entry(Boolean.class, false), - Map.entry(boolean.class, false) - ); - private static final Set primitiveTypes = Set.of(String.class, Integer.class, int.class, Long.class, long.class, Float.class, float.class, Double.class, double.class, Boolean.class, boolean.class); - - private static final Function parseString = value -> value; - private static final Function parseInt = value -> (int) Double.parseDouble(value); //Integer::parseInt; - private static final Function parseLong = value -> (long) Double.parseDouble(value); //Long::parseLong; - private static final Map, Function> enumTypeParsers = new HashMap<>(); - private static final Map> primitiveTypeParsers = Map.ofEntries( - Map.entry(String.class, parseString), - Map.entry(Integer.class, parseInt), - Map.entry(int.class, parseInt), - Map.entry(Long.class, parseLong), - Map.entry(long.class, parseLong), - Map.entry(Float.class, Float::parseFloat), - Map.entry(float.class, Float::parseFloat), - Map.entry(Double.class, Double::parseDouble), - Map.entry(double.class, Double::parseDouble), - Map.entry(Boolean.class, Boolean::parseBoolean), - Map.entry(boolean.class, Boolean::parseBoolean) - ); - private static final Map> typeParsers = new HashMap<>(primitiveTypeParsers); - private static final Map, Map> cachedClassFieldMaps = new HashMap<>(); - - @SuppressWarnings("unchecked") - private static T parsePrimitive(Class type, String string) { - if (string == null || string.isEmpty()) return (T) defaultValues.get(type); - return (T) primitiveTypeParsers.get(type).apply(string); - } - - // This is more expensive than parsing as the correct types, but it is more tolerant of mismatched data like ints with .0 - private static double parseNumber(String string) { - if (string == null || string.isEmpty()) return 0d; - return Double.parseDouble(string); - } - - @SuppressWarnings("unchecked") - private static T parseEnum(Class enumType, String string) { - if (string == null || string.isEmpty()) return null; - return (T) getEnumTypeParser(enumType).apply(string); - } - - // This is idiotic. I hate it. I'll have to look into how Gson beats the JVM into submission over classes where reflection magically fails to find the NoArgsConstructor later. - public static T newObj(Class objClass) { - try { - return objClass.getDeclaredConstructor().newInstance(); - } catch (Exception ignored) { - return JsonUtils.decode("{}", objClass); - } - } - - @SuppressWarnings("deprecated") - // Field::isAccessible is deprecated because it doesn't do what people think it does. It does what we want it to, however. - private static Function makeEnumTypeParser(Class enumClass) { - if (!enumClass.isEnum()) { - // System.out.println("Called makeEnumTypeParser with non-enum enumClass "+enumClass); - return null; - } - - // Make mappings of (string) names to enum constants - val map = new HashMap(); - val enumConstants = enumClass.getEnumConstants(); - for (val constant : enumConstants) - map.put(constant.toString(), constant); - - // If the enum also has a numeric value, map those to the constants too - // System.out.println("Looking for enum value field"); - for (Field f : enumClass.getDeclaredFields()) { - if (switch (f.getName()) { - case "value", "id" -> true; - default -> false; - }) { - // System.out.println("Enum value field found - " + f.getName()); - boolean acc = f.isAccessible(); - f.setAccessible(true); - try { - for (val constant : enumConstants) - map.put(String.valueOf(f.getInt(constant)), constant); - } catch (IllegalAccessException e) { - // System.out.println("Failed to access enum id field."); - } - f.setAccessible(acc); - break; - } - } - return map::get; - } - - private static synchronized Function getEnumTypeParser(Class enumType) { - if (enumType == null) { - // System.out.println("Called getEnumTypeParser with null enumType"); - return null; - } - return enumTypeParsers.computeIfAbsent(enumType, TsvUtils::makeEnumTypeParser); - } - - private static synchronized Function getTypeParser(Type type) { - if (type == null) return parseString; - return typeParsers.computeIfAbsent(type, t -> value -> JsonUtils.decode(value, t)); - } - - private static Type class2Type(Class classType) { - return classType.getGenericSuperclass(); - } - - private static Class type2Class(Type type) { - if (type instanceof Class) { - return (Class) type; - } else if (type instanceof ParameterizedType) { - return (Class) ((ParameterizedType) type).getRawType(); - } else { - return type.getClass(); // Probably incorrect - } - } - - private static Map makeClassFieldMap(Class classType) { - val fieldMap = new HashMap(); - for (Field field : classType.getDeclaredFields()) { - field.setAccessible(true); // Yes, we don't bother setting this back. No, it doesn't matter for this project. - val fieldParser = new FieldParser(field); - - val a = field.getDeclaredAnnotation(SerializedName.class); - if (a == null) { // No annotation, use raw field name - fieldMap.put(field.getName(), fieldParser); - } else { // Handle SerializedNames and alternatives - fieldMap.put(a.value(), fieldParser); - for (val alt : a.alternate()) { - fieldMap.put(alt, fieldParser); - } - } - } - return fieldMap; - } - - private static synchronized Map getClassFieldMap(Class classType) { - return cachedClassFieldMaps.computeIfAbsent(classType, TsvUtils::makeClassFieldMap); - } - - // Flat tab-separated value tables. - // Arrays are represented as arrayName.0, arrayName.1, etc. columns. - // Maps/POJOs are represented as objName.fieldOneName, objName.fieldTwoName, etc. columns. - // This is currently about 25x as slow as TSJ and Gson parsers, likely due to the tree spam. - public static List loadTsvToListSetField(Path filename, Class classType) { - try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - // val fieldMap = getClassFieldMap(classType); - // val constructor = classType.getDeclaredConstructor(); - - val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); - val columns = headerNames.size(); - // If we just crawled through all fields to expand potential subobjects, we might hit recursive data structure explosions (e.g. if something has a Player object) - // So we'll only crawl through objects referenced by the header columns - val stringTree = new StringTree(); - headerNames.forEach(stringTree::addPath); - - return fileReader.lines().parallel().map(line -> { - // return fileReader.lines().map(line -> { - // System.out.println("Processing line of "+filename+" - "+line); - val tokens = nonRegexSplit(line, '\t'); - val m = Math.min(tokens.size(), columns); - int t = 0; - StringValueTree tree = new StringValueTree(stringTree); - try { - for (t = 0; t < m; t++) { - String token = tokens.get(t); - if (!token.isEmpty()) { - tree.setValue(headerNames.get(t), token); - } - } - // return JsonUtils.decode(tree.toJson(), classType); - return tree.toClass(classType, null); - } catch (Exception e) { - Grasscutter.getLogger().warn("Error deserializing an instance of class " + classType.getCanonicalName()); - Grasscutter.getLogger().warn("At token #" + t + " of #" + m); - Grasscutter.getLogger().warn("Header names are: " + headerNames); - Grasscutter.getLogger().warn("Tokens are: " + tokens); - Grasscutter.getLogger().warn("Stacktrace is: ", e); - // System.out.println("Error deserializing an instance of class "+classType.getCanonicalName()); - // System.out.println("At token #"+t+" of #"+m); - // System.out.println("Header names are: "+headerNames.toString()); - // System.out.println("Tokens are: "+tokens.toString()); - // System.out.println("Json is: "+tree.toJson().toString()); - // System.out.println("Stacktrace is: "+ e); - return null; - } - }).toList(); - } catch (Exception e) { - Grasscutter.getLogger().error("Error loading file '" + filename + "' - Stacktrace is: ", e); - return null; - } - } - - // This uses a hybrid format where columns can hold JSON-encoded values. - // I'll term it TSJ (tab-separated JSON) for now, it has convenient properties. - public static List loadTsjToListSetField(Path filename, Class classType) { - try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - val fieldMap = getClassFieldMap(classType); - val constructor = classType.getDeclaredConstructor(); - - val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); - val columns = headerNames.size(); - val fieldParsers = headerNames.stream().map(fieldMap::get).toList(); - - return fileReader.lines().parallel().map(line -> { - val tokens = nonRegexSplit(line, '\t'); - val m = Math.min(tokens.size(), columns); - int t = 0; - try { - T obj = constructor.newInstance(); - for (t = 0; t < m; t++) { - val fieldParser = fieldParsers.get(t); - if (fieldParser == null) continue; - - String token = tokens.get(t); - if (!token.isEmpty()) { - fieldParser.parse(obj, token); - } - } - return obj; - } catch (Exception e) { - Grasscutter.getLogger().warn("Error deserializing an instance of class " + classType.getCanonicalName()); - Grasscutter.getLogger().warn("At token #" + t + " of #" + m); - Grasscutter.getLogger().warn("Header names are: " + headerNames); - Grasscutter.getLogger().warn("Tokens are: " + tokens); - Grasscutter.getLogger().warn("Stacktrace is: ", e); - return null; - } - }).toList(); - } catch (NoSuchFileException e) { - Grasscutter.getLogger().error("Error loading file '" + filename + "' - File does not exist. You are missing resources. Note that this file may exist in JSON, TSV, or TSJ format, any of which are suitable."); - return null; - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading file '" + filename + "' - Stacktrace is: ", e); - return null; - } catch (NoSuchMethodException e) { - Grasscutter.getLogger().error("Error loading file '" + filename + "' - Class is missing NoArgsConstructor"); - return null; - } - } - - // ----------------------------------------------------------------- - // Everything below here is for the AllArgsConstructor TSJ parser - // ----------------------------------------------------------------- - // Sadly, this is a little bit slower than the SetField version. - // I've left it in as an example of an optimization attempt that didn't work out, since the naive reflection version will tempt people to try things like this. - @SuppressWarnings("unchecked") - private static Pair, String[]> getAllArgsConstructor(Class classType) { - for (var c : classType.getDeclaredConstructors()) { - val consParameters = (java.beans.ConstructorProperties) c.getAnnotation(java.beans.ConstructorProperties.class); - if (consParameters != null) { - return Pair.of((Constructor) c, consParameters.value()); - } - } - return null; - } - - public static List> loadTsjsToListsConstructor(Class classType, Path... filenames) throws Exception { - val pair = getAllArgsConstructor(classType); - if (pair == null) { - Grasscutter.getLogger().error("No AllArgsContructor found for class: " + classType); - return null; - } - val constructor = pair.left(); - val conArgNames = pair.right(); - val numArgs = constructor.getParameterCount(); - - val argMap = new Object2IntArrayMap(); - for (int i = 0; i < conArgNames.length; i++) { - argMap.put(conArgNames[i], i); - } - - val argTypes = new Type[numArgs]; // constructor.getParameterTypes() returns base types like java.util.List instead of java.util.List - for (Field field : classType.getDeclaredFields()) { - int index = argMap.getOrDefault(field.getName(), -1); - if (index < 0) continue; - - argTypes[index] = field.getGenericType(); // returns specialized type info e.g. java.util.List - - val a = field.getDeclaredAnnotation(SerializedName.class); - if (a != null) { // Handle SerializedNames and alternatives - argMap.put(a.value(), index); - for (val alt : a.alternate()) { - argMap.put(alt, index); - } - } - } - val argParsers = Stream.of(argTypes).map(TsvUtils::getTypeParser).toList(); - - val defaultArgs = new Object[numArgs]; - for (int i = 0; i < numArgs; i++) { - defaultArgs[i] = defaultValues.get(argTypes[i]); - } - - return Stream.of(filenames).parallel().map(filename -> { - try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { - val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); - val columns = headerNames.size(); - val argPositions = headerNames.stream().mapToInt(name -> argMap.getOrDefault(name, -1)).toArray(); - - return fileReader.lines().parallel().map(line -> { - val tokens = nonRegexSplit(line, '\t'); - val args = defaultArgs.clone(); - val m = Math.min(tokens.size(), columns); - int t = 0; - try { - for (t = 0; t < m; t++) { - val argIndex = argPositions[t]; - if (argIndex < 0) continue; - - String token = tokens.get(t); - if (!token.isEmpty()) { - args[argIndex] = argParsers.get(argIndex).apply(token); - } - } - return constructor.newInstance(args); - } catch (Exception e) { - Grasscutter.getLogger().warn("Error deserializing an instance of class " + classType.getCanonicalName() + " : " + constructor.getName()); - Grasscutter.getLogger().warn("At token #" + t + " of #" + m); - Grasscutter.getLogger().warn("Arg names are: " + Arrays.toString(conArgNames)); - Grasscutter.getLogger().warn("Arg types are: " + Arrays.toString(argTypes)); - Grasscutter.getLogger().warn("Default Args are: " + Arrays.toString(defaultArgs)); - Grasscutter.getLogger().warn("Args are: " + Arrays.toString(args)); - Grasscutter.getLogger().warn("Header names are: " + headerNames); - Grasscutter.getLogger().warn("Header types are: " + IntStream.of(argPositions).mapToObj(i -> (i >= 0) ? argTypes[i] : null).toList()); - Grasscutter.getLogger().warn("Tokens are: " + tokens); - Grasscutter.getLogger().warn("Stacktrace is: ", e); - return null; - } - }).toList(); - } catch (IOException e) { - Grasscutter.getLogger().error("Error loading file '" + filename + "' - Stacktrace is: ", e); - return null; - } - }).toList(); - } - - // A helper object that contains a Field and the function to parse a String to create the value for the Field. - private static class FieldParser { - public final Field field; - public final Type type; - public final Class classType; - public final Function parser; - - FieldParser(Field field) { - this.field = field; - this.type = field.getGenericType(); // returns specialized type info e.g. java.util.List - this.classType = field.getType(); - this.parser = getTypeParser(this.type); - } - - public Object parse(String token) { - return this.parser.apply(token); - } - - public void parse(Object obj, String token) throws IllegalAccessException { - this.field.set(obj, this.parser.apply(token)); - } - } - - private static class StringTree { - public final Map children = new TreeMap<>(); - - public void addPath(String path) { - if (path.isEmpty()) return; - - val firstDot = path.indexOf('.'); - val fieldPath = (firstDot < 0) ? path : path.substring(0, firstDot); - val remainder = (firstDot < 0) ? "" : path.substring(firstDot + 1); - this.children.computeIfAbsent(fieldPath, k -> new StringTree()).addPath(remainder); - } - } - - @SuppressWarnings("unchecked") - private static class StringValueTree { - public final SortedMap children = new TreeMap<>(); - public final Int2ObjectSortedMap arrayChildren = new Int2ObjectRBTreeMap<>(); - public String value; - - public StringValueTree(StringTree from) { - from.children.forEach((k, v) -> { - try { - this.arrayChildren.put(Integer.parseInt(k), new StringValueTree(v)); - } catch (NumberFormatException e) { - this.children.put(k, new StringValueTree(v)); - } - }); - } - - public void setValue(String path, String value) { - if (path.isEmpty()) { - this.value = value; - return; - } - - val firstDot = path.indexOf('.'); - val fieldPath = (firstDot < 0) ? path : path.substring(0, firstDot); - val remainder = (firstDot < 0) ? "" : path.substring(firstDot + 1); - try { - this.arrayChildren.get(Integer.parseInt(fieldPath)).setValue(remainder, value); - } catch (NumberFormatException e) { - this.children.get(fieldPath).setValue(remainder, value); - } - } - - public JsonElement toJson() { - // Determine if this is an object, an array, or a value - if (this.value != null) { // - return new JsonPrimitive(this.value); - } - if (!this.arrayChildren.isEmpty()) { - val arr = new JsonArray(this.arrayChildren.lastIntKey() + 1); - arrayChildren.forEach((k, v) -> arr.set(k, v.toJson())); - return arr; - } else if (this.children.isEmpty()) { - return JsonNull.INSTANCE; - } else { - val obj = new JsonObject(); - children.forEach((k, v) -> { - val j = v.toJson(); - if (j != JsonNull.INSTANCE) - obj.add(k, v.toJson()); - }); - return obj; - } - } - - public T toClass(Class classType, Type type) { - // System.out.println("toClass called with Class: "+classType+" \tType: "+type); - if (type == null) - type = class2Type(classType); - - if (primitiveTypeParsers.containsKey(classType)) { - return parsePrimitive(classType, this.value); - } else if (classType.isEnum()) { - return parseEnum(classType, this.value); - } else if (classType.isArray()) { - return this.toArray(classType); - } else if (List.class.isAssignableFrom(classType)) { - // if (type instanceof ParameterizedType) - val elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; - return (T) this.toList(type2Class(elementType), elementType); - } else if (Map.class.isAssignableFrom(classType)) { - // System.out.println("Class: "+classType+" \tClassTypeParams: "+Arrays.toString(classType.getTypeParameters())+" \tType: "+type+" \tTypeArguments: "+Arrays.toString(((ParameterizedType) type).getActualTypeArguments())); - // if (type instanceof ParameterizedType) - val keyType = ((ParameterizedType) type).getActualTypeArguments()[0]; - val valueType = ((ParameterizedType) type).getActualTypeArguments()[1]; - return (T) this.toMap(type2Class(keyType), type2Class(valueType), valueType); - } else { - return this.toObj(classType, type); - } - } - - private T toObj(Class objClass, Type objType) { - try { - // val obj = objClass.getDeclaredConstructor().newInstance(); - val obj = newObj(objClass); - val fieldMap = getClassFieldMap(objClass); - this.children.forEach((name, tree) -> { - val field = fieldMap.get(name); - if (field == null) return; - try { - if (primitiveTypes.contains(field.type)) { - if ((tree.value != null) && !tree.value.isEmpty()) - field.parse(obj, tree.value); - } else { - val value = tree.toClass(field.classType, field.type); - // System.out.println("Setting field "+name+" to "+value); - field.field.set(obj, value); - // field.field.set(obj, tree.toClass(field.classType, field.type)); - } - } catch (Exception e) { - // System.out.println("Exception while setting field "+name+" for class "+objClass+" - "+e); - Grasscutter.getLogger().error("Exception while setting field " + name + " (" + field.classType + ")" + " for class " + objClass + " - ", e); - } - }); - return obj; - } catch (Exception e) { - // System.out.println("Exception while creating object of class "+objClass+" - "+e); - Grasscutter.getLogger().error("Exception while creating object of class " + objClass + " - ", e); - return null; - } - } - - public T toArray(Class classType) { - // Primitives don't play so nice with generics, so we handle all of them individually. - val containedClass = classType.getComponentType(); - // val arraySize = this.arrayChildren.size(); // Assume dense 0-indexed - val arraySize = this.arrayChildren.lastIntKey() + 1; // Could be sparse! - // System.out.println("toArray called with Class: "+classType+" \tContains: "+containedClass+" \tof size: "+arraySize); - if (containedClass == int.class) { - val output = new int[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (int) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == long.class) { - val output = new long[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (long) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == float.class) { - val output = new float[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (float) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == double.class) { - val output = new double[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = parseNumber(tree.value)); - return (T) output; - } else if (containedClass == byte.class) { - val output = new byte[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (byte) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == char.class) { - val output = new char[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (char) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == short.class) { - val output = new short[arraySize]; - this.arrayChildren.forEach((idx, tree) -> output[idx] = (short) parseNumber(tree.value)); - return (T) output; - } else if (containedClass == boolean.class) { - val output = new boolean[arraySize]; - this.arrayChildren.forEach((idx, tree) -> { - val value = (tree.value != null) && !tree.value.isEmpty() && Boolean.parseBoolean(tree.value); - output[idx] = value; - }); - return (T) output; - } else { - val output = Array.newInstance(containedClass, arraySize); - this.arrayChildren.forEach((idx, tree) -> ((Object[]) output)[idx] = tree.toClass(containedClass, null)); - return (T) output; - } - } - - private List toList(Class valueClass, Type valueType) { - val arraySize = this.arrayChildren.lastIntKey() + 1; // Could be sparse! - // System.out.println("toList called with valueClass: "+valueClass+" \tvalueType: "+valueType+" \tof size: "+arraySize); - val list = new ArrayList(arraySize); - // Safe sparse version - for (int i = 0; i < arraySize; i++) - list.add(null); - this.arrayChildren.forEach((idx, tree) -> list.set(idx, tree.toClass(valueClass, valueType))); - return list; - } - - private Map toMap(Class keyClass, Class valueClass, Type valueType) { - val map = new HashMap(); - val keyParser = getTypeParser(keyClass); - this.children.forEach((key, tree) -> { - if ((key != null) && !key.isEmpty()) - map.put((K) keyParser.apply(key), tree.toClass(valueClass, valueType)); - }); - return map; - } - } -} +package emu.grasscutter.utils; + +import static emu.grasscutter.utils.Utils.nonRegexSplit; + +import com.google.gson.*; +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.Grasscutter; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap; +import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; +import java.io.IOException; +import java.lang.reflect.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Function; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import lombok.val; + +// Throughout this file, commented System.out.println debug log calls are left in. +// This is because the default logger will deadlock when operating on parallel streams. +public class TsvUtils { + private static final Map defaultValues = + Map.ofEntries( + // Map.entry(String.class, null), // builder hates null values + Map.entry(Integer.class, 0), + Map.entry(int.class, 0), + Map.entry(Long.class, 0L), + Map.entry(long.class, 0L), + Map.entry(Float.class, 0f), + Map.entry(float.class, 0f), + Map.entry(Double.class, 0d), + Map.entry(double.class, 0d), + Map.entry(Boolean.class, false), + Map.entry(boolean.class, false)); + private static final Set primitiveTypes = + Set.of( + String.class, + Integer.class, + int.class, + Long.class, + long.class, + Float.class, + float.class, + Double.class, + double.class, + Boolean.class, + boolean.class); + + private static final Function parseString = value -> value; + private static final Function parseInt = + value -> (int) Double.parseDouble(value); // Integer::parseInt; + private static final Function parseLong = + value -> (long) Double.parseDouble(value); // Long::parseLong; + private static final Map, Function> enumTypeParsers = new HashMap<>(); + private static final Map> primitiveTypeParsers = + Map.ofEntries( + Map.entry(String.class, parseString), + Map.entry(Integer.class, parseInt), + Map.entry(int.class, parseInt), + Map.entry(Long.class, parseLong), + Map.entry(long.class, parseLong), + Map.entry(Float.class, Float::parseFloat), + Map.entry(float.class, Float::parseFloat), + Map.entry(Double.class, Double::parseDouble), + Map.entry(double.class, Double::parseDouble), + Map.entry(Boolean.class, Boolean::parseBoolean), + Map.entry(boolean.class, Boolean::parseBoolean)); + private static final Map> typeParsers = + new HashMap<>(primitiveTypeParsers); + private static final Map, Map> cachedClassFieldMaps = + new HashMap<>(); + + @SuppressWarnings("unchecked") + private static T parsePrimitive(Class type, String string) { + if (string == null || string.isEmpty()) return (T) defaultValues.get(type); + return (T) primitiveTypeParsers.get(type).apply(string); + } + + // This is more expensive than parsing as the correct types, but it is more tolerant of mismatched + // data like ints with .0 + private static double parseNumber(String string) { + if (string == null || string.isEmpty()) return 0d; + return Double.parseDouble(string); + } + + @SuppressWarnings("unchecked") + private static T parseEnum(Class enumType, String string) { + if (string == null || string.isEmpty()) return null; + return (T) getEnumTypeParser(enumType).apply(string); + } + + // This is idiotic. I hate it. I'll have to look into how Gson beats the JVM into submission over + // classes where reflection magically fails to find the NoArgsConstructor later. + public static T newObj(Class objClass) { + try { + return objClass.getDeclaredConstructor().newInstance(); + } catch (Exception ignored) { + return JsonUtils.decode("{}", objClass); + } + } + + @SuppressWarnings("deprecated") + // Field::isAccessible is deprecated because it doesn't do what people think it does. It does what + // we want it to, however. + private static Function makeEnumTypeParser(Class enumClass) { + if (!enumClass.isEnum()) { + // System.out.println("Called makeEnumTypeParser with non-enum enumClass "+enumClass); + return null; + } + + // Make mappings of (string) names to enum constants + val map = new HashMap(); + val enumConstants = enumClass.getEnumConstants(); + for (val constant : enumConstants) map.put(constant.toString(), constant); + + // If the enum also has a numeric value, map those to the constants too + // System.out.println("Looking for enum value field"); + for (Field f : enumClass.getDeclaredFields()) { + if (switch (f.getName()) { + case "value", "id" -> true; + default -> false; + }) { + // System.out.println("Enum value field found - " + f.getName()); + boolean acc = f.isAccessible(); + f.setAccessible(true); + try { + for (val constant : enumConstants) map.put(String.valueOf(f.getInt(constant)), constant); + } catch (IllegalAccessException e) { + // System.out.println("Failed to access enum id field."); + } + f.setAccessible(acc); + break; + } + } + return map::get; + } + + private static synchronized Function getEnumTypeParser(Class enumType) { + if (enumType == null) { + // System.out.println("Called getEnumTypeParser with null enumType"); + return null; + } + return enumTypeParsers.computeIfAbsent(enumType, TsvUtils::makeEnumTypeParser); + } + + private static synchronized Function getTypeParser(Type type) { + if (type == null) return parseString; + return typeParsers.computeIfAbsent(type, t -> value -> JsonUtils.decode(value, t)); + } + + private static Type class2Type(Class classType) { + return classType.getGenericSuperclass(); + } + + private static Class type2Class(Type type) { + if (type instanceof Class) { + return (Class) type; + } else if (type instanceof ParameterizedType) { + return (Class) ((ParameterizedType) type).getRawType(); + } else { + return type.getClass(); // Probably incorrect + } + } + + private static Map makeClassFieldMap(Class classType) { + val fieldMap = new HashMap(); + for (Field field : classType.getDeclaredFields()) { + field.setAccessible( + true); // Yes, we don't bother setting this back. No, it doesn't matter for this project. + val fieldParser = new FieldParser(field); + + val a = field.getDeclaredAnnotation(SerializedName.class); + if (a == null) { // No annotation, use raw field name + fieldMap.put(field.getName(), fieldParser); + } else { // Handle SerializedNames and alternatives + fieldMap.put(a.value(), fieldParser); + for (val alt : a.alternate()) { + fieldMap.put(alt, fieldParser); + } + } + } + return fieldMap; + } + + private static synchronized Map getClassFieldMap(Class classType) { + return cachedClassFieldMaps.computeIfAbsent(classType, TsvUtils::makeClassFieldMap); + } + + // Flat tab-separated value tables. + // Arrays are represented as arrayName.0, arrayName.1, etc. columns. + // Maps/POJOs are represented as objName.fieldOneName, objName.fieldTwoName, etc. columns. + // This is currently about 25x as slow as TSJ and Gson parsers, likely due to the tree spam. + public static List loadTsvToListSetField(Path filename, Class classType) { + try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + // val fieldMap = getClassFieldMap(classType); + // val constructor = classType.getDeclaredConstructor(); + + val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); + val columns = headerNames.size(); + // If we just crawled through all fields to expand potential subobjects, we might hit + // recursive data structure explosions (e.g. if something has a Player object) + // So we'll only crawl through objects referenced by the header columns + val stringTree = new StringTree(); + headerNames.forEach(stringTree::addPath); + + return fileReader + .lines() + .parallel() + .map( + line -> { + // return fileReader.lines().map(line -> { + // System.out.println("Processing line of "+filename+" - "+line); + val tokens = nonRegexSplit(line, '\t'); + val m = Math.min(tokens.size(), columns); + int t = 0; + StringValueTree tree = new StringValueTree(stringTree); + try { + for (t = 0; t < m; t++) { + String token = tokens.get(t); + if (!token.isEmpty()) { + tree.setValue(headerNames.get(t), token); + } + } + // return JsonUtils.decode(tree.toJson(), classType); + return tree.toClass(classType, null); + } catch (Exception e) { + Grasscutter.getLogger() + .warn( + "Error deserializing an instance of class " + + classType.getCanonicalName()); + Grasscutter.getLogger().warn("At token #" + t + " of #" + m); + Grasscutter.getLogger().warn("Header names are: " + headerNames); + Grasscutter.getLogger().warn("Tokens are: " + tokens); + Grasscutter.getLogger().warn("Stacktrace is: ", e); + // System.out.println("Error deserializing an instance of class + // "+classType.getCanonicalName()); + // System.out.println("At token #"+t+" of #"+m); + // System.out.println("Header names are: "+headerNames.toString()); + // System.out.println("Tokens are: "+tokens.toString()); + // System.out.println("Json is: "+tree.toJson().toString()); + // System.out.println("Stacktrace is: "+ e); + return null; + } + }) + .toList(); + } catch (Exception e) { + Grasscutter.getLogger().error("Error loading file '" + filename + "' - Stacktrace is: ", e); + return null; + } + } + + // This uses a hybrid format where columns can hold JSON-encoded values. + // I'll term it TSJ (tab-separated JSON) for now, it has convenient properties. + public static List loadTsjToListSetField(Path filename, Class classType) { + try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + val fieldMap = getClassFieldMap(classType); + val constructor = classType.getDeclaredConstructor(); + + val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); + val columns = headerNames.size(); + val fieldParsers = headerNames.stream().map(fieldMap::get).toList(); + + return fileReader + .lines() + .parallel() + .map( + line -> { + val tokens = nonRegexSplit(line, '\t'); + val m = Math.min(tokens.size(), columns); + int t = 0; + try { + T obj = constructor.newInstance(); + for (t = 0; t < m; t++) { + val fieldParser = fieldParsers.get(t); + if (fieldParser == null) continue; + + String token = tokens.get(t); + if (!token.isEmpty()) { + fieldParser.parse(obj, token); + } + } + return obj; + } catch (Exception e) { + Grasscutter.getLogger() + .warn( + "Error deserializing an instance of class " + + classType.getCanonicalName()); + Grasscutter.getLogger().warn("At token #" + t + " of #" + m); + Grasscutter.getLogger().warn("Header names are: " + headerNames); + Grasscutter.getLogger().warn("Tokens are: " + tokens); + Grasscutter.getLogger().warn("Stacktrace is: ", e); + return null; + } + }) + .toList(); + } catch (NoSuchFileException e) { + Grasscutter.getLogger() + .error( + "Error loading file '" + + filename + + "' - File does not exist. You are missing resources. Note that this file may exist in JSON, TSV, or TSJ format, any of which are suitable."); + return null; + } catch (IOException e) { + Grasscutter.getLogger().error("Error loading file '" + filename + "' - Stacktrace is: ", e); + return null; + } catch (NoSuchMethodException e) { + Grasscutter.getLogger() + .error("Error loading file '" + filename + "' - Class is missing NoArgsConstructor"); + return null; + } + } + + // ----------------------------------------------------------------- + // Everything below here is for the AllArgsConstructor TSJ parser + // ----------------------------------------------------------------- + // Sadly, this is a little bit slower than the SetField version. + // I've left it in as an example of an optimization attempt that didn't work out, since the naive + // reflection version will tempt people to try things like this. + @SuppressWarnings("unchecked") + private static Pair, String[]> getAllArgsConstructor(Class classType) { + for (var c : classType.getDeclaredConstructors()) { + val consParameters = + (java.beans.ConstructorProperties) + c.getAnnotation(java.beans.ConstructorProperties.class); + if (consParameters != null) { + return Pair.of((Constructor) c, consParameters.value()); + } + } + return null; + } + + public static List> loadTsjsToListsConstructor(Class classType, Path... filenames) + throws Exception { + val pair = getAllArgsConstructor(classType); + if (pair == null) { + Grasscutter.getLogger().error("No AllArgsContructor found for class: " + classType); + return null; + } + val constructor = pair.left(); + val conArgNames = pair.right(); + val numArgs = constructor.getParameterCount(); + + val argMap = new Object2IntArrayMap(); + for (int i = 0; i < conArgNames.length; i++) { + argMap.put(conArgNames[i], i); + } + + val argTypes = + new Type[numArgs]; // constructor.getParameterTypes() returns base types like java.util.List + // instead of java.util.List + for (Field field : classType.getDeclaredFields()) { + int index = argMap.getOrDefault(field.getName(), -1); + if (index < 0) continue; + + argTypes[index] = field.getGenericType(); // returns specialized type info e.g. + // java.util.List + + val a = field.getDeclaredAnnotation(SerializedName.class); + if (a != null) { // Handle SerializedNames and alternatives + argMap.put(a.value(), index); + for (val alt : a.alternate()) { + argMap.put(alt, index); + } + } + } + val argParsers = Stream.of(argTypes).map(TsvUtils::getTypeParser).toList(); + + val defaultArgs = new Object[numArgs]; + for (int i = 0; i < numArgs; i++) { + defaultArgs[i] = defaultValues.get(argTypes[i]); + } + + return Stream.of(filenames) + .parallel() + .map( + filename -> { + try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { + val headerNames = nonRegexSplit(fileReader.readLine(), '\t'); + val columns = headerNames.size(); + val argPositions = + headerNames.stream().mapToInt(name -> argMap.getOrDefault(name, -1)).toArray(); + + return fileReader + .lines() + .parallel() + .map( + line -> { + val tokens = nonRegexSplit(line, '\t'); + val args = defaultArgs.clone(); + val m = Math.min(tokens.size(), columns); + int t = 0; + try { + for (t = 0; t < m; t++) { + val argIndex = argPositions[t]; + if (argIndex < 0) continue; + + String token = tokens.get(t); + if (!token.isEmpty()) { + args[argIndex] = argParsers.get(argIndex).apply(token); + } + } + return constructor.newInstance(args); + } catch (Exception e) { + Grasscutter.getLogger() + .warn( + "Error deserializing an instance of class " + + classType.getCanonicalName() + + " : " + + constructor.getName()); + Grasscutter.getLogger().warn("At token #" + t + " of #" + m); + Grasscutter.getLogger() + .warn("Arg names are: " + Arrays.toString(conArgNames)); + Grasscutter.getLogger() + .warn("Arg types are: " + Arrays.toString(argTypes)); + Grasscutter.getLogger() + .warn("Default Args are: " + Arrays.toString(defaultArgs)); + Grasscutter.getLogger().warn("Args are: " + Arrays.toString(args)); + Grasscutter.getLogger().warn("Header names are: " + headerNames); + Grasscutter.getLogger() + .warn( + "Header types are: " + + IntStream.of(argPositions) + .mapToObj(i -> (i >= 0) ? argTypes[i] : null) + .toList()); + Grasscutter.getLogger().warn("Tokens are: " + tokens); + Grasscutter.getLogger().warn("Stacktrace is: ", e); + return null; + } + }) + .toList(); + } catch (IOException e) { + Grasscutter.getLogger() + .error("Error loading file '" + filename + "' - Stacktrace is: ", e); + return null; + } + }) + .toList(); + } + + // A helper object that contains a Field and the function to parse a String to create the value + // for the Field. + private static class FieldParser { + public final Field field; + public final Type type; + public final Class classType; + public final Function parser; + + FieldParser(Field field) { + this.field = field; + this.type = field.getGenericType(); // returns specialized type info e.g. + // java.util.List + this.classType = field.getType(); + this.parser = getTypeParser(this.type); + } + + public Object parse(String token) { + return this.parser.apply(token); + } + + public void parse(Object obj, String token) throws IllegalAccessException { + this.field.set(obj, this.parser.apply(token)); + } + } + + private static class StringTree { + public final Map children = new TreeMap<>(); + + public void addPath(String path) { + if (path.isEmpty()) return; + + val firstDot = path.indexOf('.'); + val fieldPath = (firstDot < 0) ? path : path.substring(0, firstDot); + val remainder = (firstDot < 0) ? "" : path.substring(firstDot + 1); + this.children.computeIfAbsent(fieldPath, k -> new StringTree()).addPath(remainder); + } + } + + @SuppressWarnings("unchecked") + private static class StringValueTree { + public final SortedMap children = new TreeMap<>(); + public final Int2ObjectSortedMap arrayChildren = new Int2ObjectRBTreeMap<>(); + public String value; + + public StringValueTree(StringTree from) { + from.children.forEach( + (k, v) -> { + try { + this.arrayChildren.put(Integer.parseInt(k), new StringValueTree(v)); + } catch (NumberFormatException e) { + this.children.put(k, new StringValueTree(v)); + } + }); + } + + public void setValue(String path, String value) { + if (path.isEmpty()) { + this.value = value; + return; + } + + val firstDot = path.indexOf('.'); + val fieldPath = (firstDot < 0) ? path : path.substring(0, firstDot); + val remainder = (firstDot < 0) ? "" : path.substring(firstDot + 1); + try { + this.arrayChildren.get(Integer.parseInt(fieldPath)).setValue(remainder, value); + } catch (NumberFormatException e) { + this.children.get(fieldPath).setValue(remainder, value); + } + } + + public JsonElement toJson() { + // Determine if this is an object, an array, or a value + if (this.value != null) { // + return new JsonPrimitive(this.value); + } + if (!this.arrayChildren.isEmpty()) { + val arr = new JsonArray(this.arrayChildren.lastIntKey() + 1); + arrayChildren.forEach((k, v) -> arr.set(k, v.toJson())); + return arr; + } else if (this.children.isEmpty()) { + return JsonNull.INSTANCE; + } else { + val obj = new JsonObject(); + children.forEach( + (k, v) -> { + val j = v.toJson(); + if (j != JsonNull.INSTANCE) obj.add(k, v.toJson()); + }); + return obj; + } + } + + public T toClass(Class classType, Type type) { + // System.out.println("toClass called with Class: "+classType+" \tType: "+type); + if (type == null) type = class2Type(classType); + + if (primitiveTypeParsers.containsKey(classType)) { + return parsePrimitive(classType, this.value); + } else if (classType.isEnum()) { + return parseEnum(classType, this.value); + } else if (classType.isArray()) { + return this.toArray(classType); + } else if (List.class.isAssignableFrom(classType)) { + // if (type instanceof ParameterizedType) + val elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; + return (T) this.toList(type2Class(elementType), elementType); + } else if (Map.class.isAssignableFrom(classType)) { + // System.out.println("Class: "+classType+" \tClassTypeParams: + // "+Arrays.toString(classType.getTypeParameters())+" \tType: "+type+" \tTypeArguments: + // "+Arrays.toString(((ParameterizedType) type).getActualTypeArguments())); + // if (type instanceof ParameterizedType) + val keyType = ((ParameterizedType) type).getActualTypeArguments()[0]; + val valueType = ((ParameterizedType) type).getActualTypeArguments()[1]; + return (T) this.toMap(type2Class(keyType), type2Class(valueType), valueType); + } else { + return this.toObj(classType, type); + } + } + + private T toObj(Class objClass, Type objType) { + try { + // val obj = objClass.getDeclaredConstructor().newInstance(); + val obj = newObj(objClass); + val fieldMap = getClassFieldMap(objClass); + this.children.forEach( + (name, tree) -> { + val field = fieldMap.get(name); + if (field == null) return; + try { + if (primitiveTypes.contains(field.type)) { + if ((tree.value != null) && !tree.value.isEmpty()) field.parse(obj, tree.value); + } else { + val value = tree.toClass(field.classType, field.type); + // System.out.println("Setting field "+name+" to "+value); + field.field.set(obj, value); + // field.field.set(obj, tree.toClass(field.classType, field.type)); + } + } catch (Exception e) { + // System.out.println("Exception while setting field "+name+" for class "+objClass+" + // - "+e); + Grasscutter.getLogger() + .error( + "Exception while setting field " + + name + + " (" + + field.classType + + ")" + + " for class " + + objClass + + " - ", + e); + } + }); + return obj; + } catch (Exception e) { + // System.out.println("Exception while creating object of class "+objClass+" - "+e); + Grasscutter.getLogger() + .error("Exception while creating object of class " + objClass + " - ", e); + return null; + } + } + + public T toArray(Class classType) { + // Primitives don't play so nice with generics, so we handle all of them individually. + val containedClass = classType.getComponentType(); + // val arraySize = this.arrayChildren.size(); // Assume dense 0-indexed + val arraySize = this.arrayChildren.lastIntKey() + 1; // Could be sparse! + // System.out.println("toArray called with Class: "+classType+" \tContains: "+containedClass+" + // \tof size: "+arraySize); + if (containedClass == int.class) { + val output = new int[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (int) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == long.class) { + val output = new long[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (long) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == float.class) { + val output = new float[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (float) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == double.class) { + val output = new double[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = parseNumber(tree.value)); + return (T) output; + } else if (containedClass == byte.class) { + val output = new byte[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (byte) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == char.class) { + val output = new char[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (char) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == short.class) { + val output = new short[arraySize]; + this.arrayChildren.forEach((idx, tree) -> output[idx] = (short) parseNumber(tree.value)); + return (T) output; + } else if (containedClass == boolean.class) { + val output = new boolean[arraySize]; + this.arrayChildren.forEach( + (idx, tree) -> { + val value = + (tree.value != null) && !tree.value.isEmpty() && Boolean.parseBoolean(tree.value); + output[idx] = value; + }); + return (T) output; + } else { + val output = Array.newInstance(containedClass, arraySize); + this.arrayChildren.forEach( + (idx, tree) -> ((Object[]) output)[idx] = tree.toClass(containedClass, null)); + return (T) output; + } + } + + private List toList(Class valueClass, Type valueType) { + val arraySize = this.arrayChildren.lastIntKey() + 1; // Could be sparse! + // System.out.println("toList called with valueClass: "+valueClass+" \tvalueType: + // "+valueType+" \tof size: "+arraySize); + val list = new ArrayList(arraySize); + // Safe sparse version + for (int i = 0; i < arraySize; i++) list.add(null); + this.arrayChildren.forEach((idx, tree) -> list.set(idx, tree.toClass(valueClass, valueType))); + return list; + } + + private Map toMap(Class keyClass, Class valueClass, Type valueType) { + val map = new HashMap(); + val keyParser = getTypeParser(keyClass); + this.children.forEach( + (key, tree) -> { + if ((key != null) && !key.isEmpty()) + map.put((K) keyParser.apply(key), tree.toClass(valueClass, valueType)); + }); + return map; + } + } +} diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index b804893d9..edd99d940 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -1,436 +1,449 @@ -package emu.grasscutter.utils; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.config.ConfigContainer; -import emu.grasscutter.data.DataLoader; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import org.slf4j.Logger; - -import javax.annotation.Nullable; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.time.DayOfWeek; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.temporal.TemporalAdjusters; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; - -import static emu.grasscutter.utils.FileUtils.getResourcePath; -import static emu.grasscutter.utils.Language.translate; - -@SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) -public final class Utils { - public static final Random random = new Random(); - private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray(); - - public static int randomRange(int min, int max) { - return random.nextInt(max - min + 1) + min; - } - - public static float randomFloatRange(float min, float max) { - return random.nextFloat() * (max - min) + min; - } - - public static double getDist(Position pos1, Position pos2) { - double xs = pos1.getX() - pos2.getX(); - xs = xs * xs; - - double ys = pos1.getY() - pos2.getY(); - ys = ys * ys; - - double zs = pos1.getZ() - pos2.getZ(); - zs = zs * zs; - - return Math.sqrt(xs + zs + ys); - } - - public static int getCurrentSeconds() { - return (int) (System.currentTimeMillis() / 1000.0); - } - - public static String lowerCaseFirstChar(String s) { - StringBuilder sb = new StringBuilder(s); - sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); - return sb.toString(); - } - - public static String toString(InputStream inputStream) throws IOException { - BufferedInputStream bis = new BufferedInputStream(inputStream); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - for (int result = bis.read(); result != -1; result = bis.read()) { - buf.write((byte) result); - } - return buf.toString(); - } - - public static void logByteArray(byte[] array) { - ByteBuf b = Unpooled.wrappedBuffer(array); - Grasscutter.getLogger().info("\n" + ByteBufUtil.prettyHexDump(b)); - b.release(); - } - - public static String bytesToHex(byte[] bytes) { - if (bytes == null) return ""; - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = HEX_ARRAY[v >>> 4]; - hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; - } - return new String(hexChars); - } - - public static String bytesToHex(ByteBuf buf) { - return bytesToHex(byteBufToArray(buf)); - } - - public static byte[] byteBufToArray(ByteBuf buf) { - byte[] bytes = new byte[buf.capacity()]; - buf.getBytes(0, bytes); - return bytes; - } - - public static int abilityHash(String str) { - int v7 = 0; - int v8 = 0; - while (v8 < str.length()) { - v7 = str.charAt(v8++) + 131 * v7; - } - return v7; - } - - /** - * Creates a string with the path to a file. - * - * @param path The path to the file. - * @return A path using the operating system's file separator. - */ - public static String toFilePath(String path) { - return path.replace("/", File.separator); - } - - /** - * Checks if a file exists on the file system. - * - * @param path The path to the file. - * @return True if the file exists, false otherwise. - */ - public static boolean fileExists(String path) { - return new File(path).exists(); - } - - /** - * Creates a folder on the file system. - * - * @param path The path to the folder. - * @return True if the folder was created, false otherwise. - */ - public static boolean createFolder(String path) { - return new File(path).mkdirs(); - } - - /** - * Copies a file from the archive's resources to the file system. - * - * @param resource The path to the resource. - * @param destination The path to copy the resource to. - * @return True if the file was copied, false otherwise. - */ - public static boolean copyFromResources(String resource, String destination) { - try (InputStream stream = Grasscutter.class.getResourceAsStream(resource)) { - if (stream == null) { - Grasscutter.getLogger().warn("Could not find resource: " + resource); - return false; - } - - Files.copy(stream, new File(destination).toPath(), StandardCopyOption.REPLACE_EXISTING); - return true; - } catch (Exception exception) { - Grasscutter.getLogger().warn("Unable to copy resource " + resource + " to " + destination, exception); - return false; - } - } - - /** - * Logs an object to the console. - * - * @param object The object to log. - */ - public static void logObject(Object object) { - Grasscutter.getLogger().info(JsonUtils.encode(object)); - } - - /** - * Checks for required files and folders before startup. - */ - public static void startupCheck() { - ConfigContainer config = Grasscutter.getConfig(); - Logger logger = Grasscutter.getLogger(); - boolean exit = false; - - String dataFolder = config.folderStructure.data; - - // Check for resources folder. - if (!Files.exists(getResourcePath(""))) { - logger.info(translate("messages.status.create_resources")); - logger.info(translate("messages.status.resources_error")); - createFolder(config.folderStructure.resources); - exit = true; - } - - // Check for BinOutput + ExcelBinOutput. - if (!Files.exists(getResourcePath("BinOutput")) || - !Files.exists(getResourcePath("ExcelBinOutput"))) { - logger.info(translate("messages.status.resources_error")); - exit = true; - } - - // Check for game data. - if (!fileExists(dataFolder)) - createFolder(dataFolder); - - // Make sure the data folder is populated, if there are any missing files copy them from resources - DataLoader.checkAllFiles(); - - if (exit) System.exit(1); - } - - /** - * Gets the timestamp of the next hour. - * - * @return The timestamp in UNIX seconds. - */ - public static int getNextTimestampOfThisHour(int hour, String timeZone, int param) { - ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); - for (int i = 0; i < param; i++) { - if (zonedDateTime.getHour() < hour) { - zonedDateTime = zonedDateTime.withHour(hour).withMinute(0).withSecond(0); - } else { - zonedDateTime = zonedDateTime.plusDays(1).withHour(hour).withMinute(0).withSecond(0); - } - } - return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); - } - - /** - * Gets the timestamp of the next hour in a week. - * - * @return The timestamp in UNIX seconds. - */ - public static int getNextTimestampOfThisHourInNextWeek(int hour, String timeZone, int param) { - ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); - for (int i = 0; i < param; i++) { - if (zonedDateTime.getDayOfWeek() == DayOfWeek.MONDAY && zonedDateTime.getHour() < hour) { - zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)).withHour(hour).withMinute(0).withSecond(0); - } else { - zonedDateTime = zonedDateTime.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).withHour(hour).withMinute(0).withSecond(0); - } - } - return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); - } - - /** - * Gets the timestamp of the next hour in a month. - * - * @return The timestamp in UNIX seconds. - */ - public static int getNextTimestampOfThisHourInNextMonth(int hour, String timeZone, int param) { - ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); - for (int i = 0; i < param; i++) { - if (zonedDateTime.getDayOfMonth() == 1 && zonedDateTime.getHour() < hour) { - zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)).withHour(hour).withMinute(0).withSecond(0); - } else { - zonedDateTime = zonedDateTime.with(TemporalAdjusters.firstDayOfNextMonth()).withHour(hour).withMinute(0).withSecond(0); - } - } - return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); - } - - /** - * Retrieves a string from an input stream. - * - * @param stream The input stream. - * @return The string. - */ - public static String readFromInputStream(@Nullable InputStream stream) { - if (stream == null) return "empty"; - - StringBuilder stringBuilder = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { - String line; - while ((line = reader.readLine()) != null) { - stringBuilder.append(line); - } - stream.close(); - } catch (IOException e) { - Grasscutter.getLogger().warn("Failed to read from input stream."); - } catch (NullPointerException ignored) { - return "empty"; - } - return stringBuilder.toString(); - } - - /** - * Performs a linear interpolation using a table of fixed points to create an effective piecewise f(x) = y function. - * - * @param x The x value. - * @param xyArray Array of points in [[x0,y0], ... [xN, yN]] format - * @return f(x) = y - */ - public static int lerp(int x, int[][] xyArray) { - try { - if (x <= xyArray[0][0]) { // Clamp to first point - return xyArray[0][1]; - } else if (x >= xyArray[xyArray.length - 1][0]) { // Clamp to last point - return xyArray[xyArray.length - 1][1]; - } - // At this point we're guaranteed to have two lerp points, and pity be somewhere between them. - for (int i = 0; i < xyArray.length - 1; i++) { - if (x == xyArray[i + 1][0]) { - return xyArray[i + 1][1]; - } - if (x < xyArray[i + 1][0]) { - // We are between [i] and [i+1], interpolation time! - // Using floats would be slightly cleaner but we can just as easily use ints if we're careful with order of operations. - int position = x - xyArray[i][0]; - int fullDist = xyArray[i + 1][0] - xyArray[i][0]; - int prevValue = xyArray[i][1]; - int fullDelta = xyArray[i + 1][1] - prevValue; - return prevValue + ((position * fullDelta) / fullDist); - } - } - } catch (IndexOutOfBoundsException e) { - Grasscutter.getLogger().error("Malformed lerp point array. Must be of form [[x0, y0], ..., [xN, yN]]."); - } - return 0; - } - - /** - * Checks if an int is in an int[] - * - * @param key int to look for - * @param array int[] to look in - * @return key in array - */ - public static boolean intInArray(int key, int[] array) { - for (int i : array) { - if (i == key) { - return true; - } - } - return false; - } - - /** - * Return a copy of minuend without any elements found in subtrahend. - * - * @param minuend The array we want elements from - * @param subtrahend The array whose elements we don't want - * @return The array with only the elements we want, in the order that minuend had them - */ - public static int[] setSubtract(int[] minuend, int[] subtrahend) { - IntList temp = new IntArrayList(); - for (int i : minuend) { - if (!intInArray(i, subtrahend)) { - temp.add(i); - } - } - return temp.toIntArray(); - } - - /** - * Gets the language code from a given locale. - * - * @param locale A locale. - * @return A string in the format of 'XX-XX'. - */ - public static String getLanguageCode(Locale locale) { - return String.format("%s-%s", locale.getLanguage(), locale.getCountry()); - } - - /** - * Base64 encodes a given byte array. - * - * @param toEncode An array of bytes. - * @return A base64 encoded string. - */ - public static String base64Encode(byte[] toEncode) { - return Base64.getEncoder().encodeToString(toEncode); - } - - /** - * Base64 decodes a given string. - * - * @param toDecode A base64 encoded string. - * @return An array of bytes. - */ - public static byte[] base64Decode(String toDecode) { - return Base64.getDecoder().decode(toDecode); - } - - /*** - * Draws a random element from the given list, following the given probability distribution, if given. - * @param list The list from which to draw the element. - * @param probabilities The probability distribution. This is given as a list of probabilities of the same length it `list`. - * @return A randomly drawn element from the given list. - */ - public static T drawRandomListElement(List list, List probabilities) { - // If we don't have a probability distribution, or the size of the distribution does not match - // the size of the list, we assume uniform distribution. - if (probabilities == null || probabilities.size() <= 1 || probabilities.size() != list.size()) { - int index = ThreadLocalRandom.current().nextInt(0, list.size()); - return list.get(index); - } - - // Otherwise, we roll with the given distribution. - int totalProbabilityMass = probabilities.stream().reduce(Integer::sum).get(); - int roll = ThreadLocalRandom.current().nextInt(1, totalProbabilityMass + 1); - - int currentTotalChance = 0; - for (int i = 0; i < list.size(); i++) { - currentTotalChance += probabilities.get(i); - - if (roll <= currentTotalChance) { - return list.get(i); - } - } - - // Should never happen. - return list.get(0); - } - - /*** - * Draws a random element from the given list, following a uniform probability distribution. - * @param list The list from which to draw the element. - * @return A randomly drawn element from the given list. - */ - public static T drawRandomListElement(List list) { - return drawRandomListElement(list, null); - } - - /*** - * Splits a string by a character, into a list - * @param input The string to split - * @param separator The character to use as the split points - * @return A list of all the substrings - */ - public static List nonRegexSplit(String input, int separator) { - var output = new ArrayList(); - int start = 0; - for (int next = input.indexOf(separator); next > 0; next = input.indexOf(separator, start)) { - output.add(input.substring(start, next)); - start = next + 1; - } - if (start < input.length()) - output.add(input.substring(start)); - return output; - } -} +package emu.grasscutter.utils; + +import static emu.grasscutter.utils.FileUtils.getResourcePath; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.config.ConfigContainer; +import emu.grasscutter.data.DataLoader; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.time.DayOfWeek; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import javax.annotation.Nullable; +import org.slf4j.Logger; + +@SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) +public final class Utils { + public static final Random random = new Random(); + private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray(); + + public static int randomRange(int min, int max) { + return random.nextInt(max - min + 1) + min; + } + + public static float randomFloatRange(float min, float max) { + return random.nextFloat() * (max - min) + min; + } + + public static double getDist(Position pos1, Position pos2) { + double xs = pos1.getX() - pos2.getX(); + xs = xs * xs; + + double ys = pos1.getY() - pos2.getY(); + ys = ys * ys; + + double zs = pos1.getZ() - pos2.getZ(); + zs = zs * zs; + + return Math.sqrt(xs + zs + ys); + } + + public static int getCurrentSeconds() { + return (int) (System.currentTimeMillis() / 1000.0); + } + + public static String lowerCaseFirstChar(String s) { + StringBuilder sb = new StringBuilder(s); + sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); + return sb.toString(); + } + + public static String toString(InputStream inputStream) throws IOException { + BufferedInputStream bis = new BufferedInputStream(inputStream); + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + for (int result = bis.read(); result != -1; result = bis.read()) { + buf.write((byte) result); + } + return buf.toString(); + } + + public static void logByteArray(byte[] array) { + ByteBuf b = Unpooled.wrappedBuffer(array); + Grasscutter.getLogger().info("\n" + ByteBufUtil.prettyHexDump(b)); + b.release(); + } + + public static String bytesToHex(byte[] bytes) { + if (bytes == null) return ""; + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } + + public static String bytesToHex(ByteBuf buf) { + return bytesToHex(byteBufToArray(buf)); + } + + public static byte[] byteBufToArray(ByteBuf buf) { + byte[] bytes = new byte[buf.capacity()]; + buf.getBytes(0, bytes); + return bytes; + } + + public static int abilityHash(String str) { + int v7 = 0; + int v8 = 0; + while (v8 < str.length()) { + v7 = str.charAt(v8++) + 131 * v7; + } + return v7; + } + + /** + * Creates a string with the path to a file. + * + * @param path The path to the file. + * @return A path using the operating system's file separator. + */ + public static String toFilePath(String path) { + return path.replace("/", File.separator); + } + + /** + * Checks if a file exists on the file system. + * + * @param path The path to the file. + * @return True if the file exists, false otherwise. + */ + public static boolean fileExists(String path) { + return new File(path).exists(); + } + + /** + * Creates a folder on the file system. + * + * @param path The path to the folder. + * @return True if the folder was created, false otherwise. + */ + public static boolean createFolder(String path) { + return new File(path).mkdirs(); + } + + /** + * Copies a file from the archive's resources to the file system. + * + * @param resource The path to the resource. + * @param destination The path to copy the resource to. + * @return True if the file was copied, false otherwise. + */ + public static boolean copyFromResources(String resource, String destination) { + try (InputStream stream = Grasscutter.class.getResourceAsStream(resource)) { + if (stream == null) { + Grasscutter.getLogger().warn("Could not find resource: " + resource); + return false; + } + + Files.copy(stream, new File(destination).toPath(), StandardCopyOption.REPLACE_EXISTING); + return true; + } catch (Exception exception) { + Grasscutter.getLogger() + .warn("Unable to copy resource " + resource + " to " + destination, exception); + return false; + } + } + + /** + * Logs an object to the console. + * + * @param object The object to log. + */ + public static void logObject(Object object) { + Grasscutter.getLogger().info(JsonUtils.encode(object)); + } + + /** Checks for required files and folders before startup. */ + public static void startupCheck() { + ConfigContainer config = Grasscutter.getConfig(); + Logger logger = Grasscutter.getLogger(); + boolean exit = false; + + String dataFolder = config.folderStructure.data; + + // Check for resources folder. + if (!Files.exists(getResourcePath(""))) { + logger.info(translate("messages.status.create_resources")); + logger.info(translate("messages.status.resources_error")); + createFolder(config.folderStructure.resources); + exit = true; + } + + // Check for BinOutput + ExcelBinOutput. + if (!Files.exists(getResourcePath("BinOutput")) + || !Files.exists(getResourcePath("ExcelBinOutput"))) { + logger.info(translate("messages.status.resources_error")); + exit = true; + } + + // Check for game data. + if (!fileExists(dataFolder)) createFolder(dataFolder); + + // Make sure the data folder is populated, if there are any missing files copy them from + // resources + DataLoader.checkAllFiles(); + + if (exit) System.exit(1); + } + + /** + * Gets the timestamp of the next hour. + * + * @return The timestamp in UNIX seconds. + */ + public static int getNextTimestampOfThisHour(int hour, String timeZone, int param) { + ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); + for (int i = 0; i < param; i++) { + if (zonedDateTime.getHour() < hour) { + zonedDateTime = zonedDateTime.withHour(hour).withMinute(0).withSecond(0); + } else { + zonedDateTime = zonedDateTime.plusDays(1).withHour(hour).withMinute(0).withSecond(0); + } + } + return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); + } + + /** + * Gets the timestamp of the next hour in a week. + * + * @return The timestamp in UNIX seconds. + */ + public static int getNextTimestampOfThisHourInNextWeek(int hour, String timeZone, int param) { + ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); + for (int i = 0; i < param; i++) { + if (zonedDateTime.getDayOfWeek() == DayOfWeek.MONDAY && zonedDateTime.getHour() < hour) { + zonedDateTime = + ZonedDateTime.now(ZoneId.of(timeZone)).withHour(hour).withMinute(0).withSecond(0); + } else { + zonedDateTime = + zonedDateTime + .with(TemporalAdjusters.next(DayOfWeek.MONDAY)) + .withHour(hour) + .withMinute(0) + .withSecond(0); + } + } + return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); + } + + /** + * Gets the timestamp of the next hour in a month. + * + * @return The timestamp in UNIX seconds. + */ + public static int getNextTimestampOfThisHourInNextMonth(int hour, String timeZone, int param) { + ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(timeZone)); + for (int i = 0; i < param; i++) { + if (zonedDateTime.getDayOfMonth() == 1 && zonedDateTime.getHour() < hour) { + zonedDateTime = + ZonedDateTime.now(ZoneId.of(timeZone)).withHour(hour).withMinute(0).withSecond(0); + } else { + zonedDateTime = + zonedDateTime + .with(TemporalAdjusters.firstDayOfNextMonth()) + .withHour(hour) + .withMinute(0) + .withSecond(0); + } + } + return (int) zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); + } + + /** + * Retrieves a string from an input stream. + * + * @param stream The input stream. + * @return The string. + */ + public static String readFromInputStream(@Nullable InputStream stream) { + if (stream == null) return "empty"; + + StringBuilder stringBuilder = new StringBuilder(); + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + stream.close(); + } catch (IOException e) { + Grasscutter.getLogger().warn("Failed to read from input stream."); + } catch (NullPointerException ignored) { + return "empty"; + } + return stringBuilder.toString(); + } + + /** + * Performs a linear interpolation using a table of fixed points to create an effective piecewise + * f(x) = y function. + * + * @param x The x value. + * @param xyArray Array of points in [[x0,y0], ... [xN, yN]] format + * @return f(x) = y + */ + public static int lerp(int x, int[][] xyArray) { + try { + if (x <= xyArray[0][0]) { // Clamp to first point + return xyArray[0][1]; + } else if (x >= xyArray[xyArray.length - 1][0]) { // Clamp to last point + return xyArray[xyArray.length - 1][1]; + } + // At this point we're guaranteed to have two lerp points, and pity be somewhere between them. + for (int i = 0; i < xyArray.length - 1; i++) { + if (x == xyArray[i + 1][0]) { + return xyArray[i + 1][1]; + } + if (x < xyArray[i + 1][0]) { + // We are between [i] and [i+1], interpolation time! + // Using floats would be slightly cleaner but we can just as easily use ints if we're + // careful with order of operations. + int position = x - xyArray[i][0]; + int fullDist = xyArray[i + 1][0] - xyArray[i][0]; + int prevValue = xyArray[i][1]; + int fullDelta = xyArray[i + 1][1] - prevValue; + return prevValue + ((position * fullDelta) / fullDist); + } + } + } catch (IndexOutOfBoundsException e) { + Grasscutter.getLogger() + .error("Malformed lerp point array. Must be of form [[x0, y0], ..., [xN, yN]]."); + } + return 0; + } + + /** + * Checks if an int is in an int[] + * + * @param key int to look for + * @param array int[] to look in + * @return key in array + */ + public static boolean intInArray(int key, int[] array) { + for (int i : array) { + if (i == key) { + return true; + } + } + return false; + } + + /** + * Return a copy of minuend without any elements found in subtrahend. + * + * @param minuend The array we want elements from + * @param subtrahend The array whose elements we don't want + * @return The array with only the elements we want, in the order that minuend had them + */ + public static int[] setSubtract(int[] minuend, int[] subtrahend) { + IntList temp = new IntArrayList(); + for (int i : minuend) { + if (!intInArray(i, subtrahend)) { + temp.add(i); + } + } + return temp.toIntArray(); + } + + /** + * Gets the language code from a given locale. + * + * @param locale A locale. + * @return A string in the format of 'XX-XX'. + */ + public static String getLanguageCode(Locale locale) { + return String.format("%s-%s", locale.getLanguage(), locale.getCountry()); + } + + /** + * Base64 encodes a given byte array. + * + * @param toEncode An array of bytes. + * @return A base64 encoded string. + */ + public static String base64Encode(byte[] toEncode) { + return Base64.getEncoder().encodeToString(toEncode); + } + + /** + * Base64 decodes a given string. + * + * @param toDecode A base64 encoded string. + * @return An array of bytes. + */ + public static byte[] base64Decode(String toDecode) { + return Base64.getDecoder().decode(toDecode); + } + + /*** + * Draws a random element from the given list, following the given probability distribution, if given. + * @param list The list from which to draw the element. + * @param probabilities The probability distribution. This is given as a list of probabilities of the same length it `list`. + * @return A randomly drawn element from the given list. + */ + public static T drawRandomListElement(List list, List probabilities) { + // If we don't have a probability distribution, or the size of the distribution does not match + // the size of the list, we assume uniform distribution. + if (probabilities == null || probabilities.size() <= 1 || probabilities.size() != list.size()) { + int index = ThreadLocalRandom.current().nextInt(0, list.size()); + return list.get(index); + } + + // Otherwise, we roll with the given distribution. + int totalProbabilityMass = probabilities.stream().reduce(Integer::sum).get(); + int roll = ThreadLocalRandom.current().nextInt(1, totalProbabilityMass + 1); + + int currentTotalChance = 0; + for (int i = 0; i < list.size(); i++) { + currentTotalChance += probabilities.get(i); + + if (roll <= currentTotalChance) { + return list.get(i); + } + } + + // Should never happen. + return list.get(0); + } + + /*** + * Draws a random element from the given list, following a uniform probability distribution. + * @param list The list from which to draw the element. + * @return A randomly drawn element from the given list. + */ + public static T drawRandomListElement(List list) { + return drawRandomListElement(list, null); + } + + /*** + * Splits a string by a character, into a list + * @param input The string to split + * @param separator The character to use as the split points + * @return A list of all the substrings + */ + public static List nonRegexSplit(String input, int separator) { + var output = new ArrayList(); + int start = 0; + for (int next = input.indexOf(separator); next > 0; next = input.indexOf(separator, start)) { + output.add(input.substring(start, next)); + start = next + 1; + } + if (start < input.length()) output.add(input.substring(start)); + return output; + } +} diff --git a/src/main/java/emu/grasscutter/utils/WeightedList.java b/src/main/java/emu/grasscutter/utils/WeightedList.java index f6a2e257c..cfdbaecea 100644 --- a/src/main/java/emu/grasscutter/utils/WeightedList.java +++ b/src/main/java/emu/grasscutter/utils/WeightedList.java @@ -1,30 +1,28 @@ -package emu.grasscutter.utils; - -import java.util.NavigableMap; -import java.util.TreeMap; -import java.util.concurrent.ThreadLocalRandom; - -public class WeightedList { - private final NavigableMap map = new TreeMap(); - private double total = 0; - - public WeightedList() { - - } - - public WeightedList add(double weight, E result) { - if (weight <= 0) return this; - total += weight; - map.put(total, result); - return this; - } - - public E next() { - double value = ThreadLocalRandom.current().nextDouble() * total; - return map.higherEntry(value).getValue(); - } - - public int size() { - return map.size(); - } -} +package emu.grasscutter.utils; + +import java.util.NavigableMap; +import java.util.TreeMap; +import java.util.concurrent.ThreadLocalRandom; + +public class WeightedList { + private final NavigableMap map = new TreeMap(); + private double total = 0; + + public WeightedList() {} + + public WeightedList add(double weight, E result) { + if (weight <= 0) return this; + total += weight; + map.put(total, result); + return this; + } + + public E next() { + double value = ThreadLocalRandom.current().nextDouble() * total; + return map.higherEntry(value).getValue(); + } + + public int size() { + return map.size(); + } +}