From b53e3ec9668647a690b7a5f857d5f0c1b00707e2 Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Sun, 8 Oct 2023 04:23:54 -0700 Subject: [PATCH] Challenges now spawn the right monsters and can be completed --- .../emu/lunarcore/data/config/GroupInfo.java | 4 + .../lunarcore/data/excel/ChallengeExcel.java | 1 + .../emu/lunarcore/game/battle/Battle.java | 4 + .../lunarcore/game/battle/BattleService.java | 17 +- .../game/challenge/ChallengeData.java | 158 +++++++++++++ .../game/challenge/ChallengeService.java | 14 +- .../lunarcore/game/player/LineupManager.java | 33 +-- .../emu/lunarcore/game/player/Player.java | 10 +- .../lunarcore/game/player/PlayerLineup.java | 11 +- .../java/emu/lunarcore/game/scene/Scene.java | 211 ++++++++++-------- .../game/scene/entity/EntityMonster.java | 2 +- .../recv/HandlerGetCurChallengeCsReq.java | 22 ++ .../recv/HandlerLeaveChallengeCsReq.java | 2 +- .../recv/HandlerPVEBattleResultCsReq.java | 2 +- .../recv/HandlerReplaceLineupCsReq.java | 2 +- .../send/PacketChallengeLineupNotify.java | 18 ++ .../send/PacketChallengeSettleNotify.java | 22 ++ .../send/PacketGetCurChallengeScRsp.java | 23 ++ .../send/PacketStartChallengeScRsp.java | 16 +- 19 files changed, 438 insertions(+), 134 deletions(-) create mode 100644 src/main/java/emu/lunarcore/game/challenge/ChallengeData.java create mode 100644 src/main/java/emu/lunarcore/server/packet/recv/HandlerGetCurChallengeCsReq.java create mode 100644 src/main/java/emu/lunarcore/server/packet/send/PacketChallengeLineupNotify.java create mode 100644 src/main/java/emu/lunarcore/server/packet/send/PacketChallengeSettleNotify.java create mode 100644 src/main/java/emu/lunarcore/server/packet/send/PacketGetCurChallengeScRsp.java diff --git a/src/main/java/emu/lunarcore/data/config/GroupInfo.java b/src/main/java/emu/lunarcore/data/config/GroupInfo.java index 863dfea..8fcc425 100644 --- a/src/main/java/emu/lunarcore/data/config/GroupInfo.java +++ b/src/main/java/emu/lunarcore/data/config/GroupInfo.java @@ -20,6 +20,10 @@ public class GroupInfo { if (this.id == 0) this.id = id; } + public MonsterInfo getMonsterById(int configId) { + return MonsterList.stream().filter(m -> m.getID() == configId).findFirst().orElse(null); + } + public static enum GroupLoadSide { Client, Server; } diff --git a/src/main/java/emu/lunarcore/data/excel/ChallengeExcel.java b/src/main/java/emu/lunarcore/data/excel/ChallengeExcel.java index 096fa06..a284cfc 100644 --- a/src/main/java/emu/lunarcore/data/excel/ChallengeExcel.java +++ b/src/main/java/emu/lunarcore/data/excel/ChallengeExcel.java @@ -10,6 +10,7 @@ public class ChallengeExcel extends GameResource { private int ID; private int MapEntranceID; private int StageNum; + private int ChallengeCountDown; private int MazeBuffID; private int MazeGroupID1; diff --git a/src/main/java/emu/lunarcore/game/battle/Battle.java b/src/main/java/emu/lunarcore/game/battle/Battle.java index 5d564bd..1babf89 100644 --- a/src/main/java/emu/lunarcore/game/battle/Battle.java +++ b/src/main/java/emu/lunarcore/game/battle/Battle.java @@ -22,6 +22,7 @@ import emu.lunarcore.util.Utils; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.IntList; import lombok.Getter; +import lombok.Setter; @Getter public class Battle { @@ -34,6 +35,8 @@ public class Battle { private final List drops; private final long timestamp; + @Setter private int roundsLimit; + private Battle(Player player, PlayerLineup lineup) { this.id = player.getNextBattleId(); this.player = player; @@ -158,6 +161,7 @@ public class Battle { // Build battle info var proto = SceneBattleInfo.newInstance() .setBattleId(this.getId()) + .setRoundsLimit(this.getRoundsLimit()) .setLogicRandomSeed(Utils.randomRange(1, Short.MAX_VALUE)) .setWorldLevel(player.getWorldLevel()); diff --git a/src/main/java/emu/lunarcore/game/battle/BattleService.java b/src/main/java/emu/lunarcore/game/battle/BattleService.java index fb2cd9e..4943131 100644 --- a/src/main/java/emu/lunarcore/game/battle/BattleService.java +++ b/src/main/java/emu/lunarcore/game/battle/BattleService.java @@ -12,9 +12,9 @@ import emu.lunarcore.game.player.Player; import emu.lunarcore.game.scene.entity.EntityMonster; import emu.lunarcore.game.scene.entity.EntityProp; import emu.lunarcore.game.scene.entity.GameEntity; -import emu.lunarcore.proto.AvatarBattleInfoOuterClass.AvatarBattleInfo; import emu.lunarcore.proto.AvatarPropertyOuterClass.AvatarProperty; import emu.lunarcore.proto.BattleEndStatusOuterClass.BattleEndStatus; +import emu.lunarcore.proto.BattleStatisticsOuterClass.BattleStatistics; import emu.lunarcore.server.game.BaseGameService; import emu.lunarcore.server.game.GameServer; import emu.lunarcore.server.packet.send.PacketReEnterLastElementStageScRsp; @@ -23,7 +23,6 @@ import emu.lunarcore.server.packet.send.PacketStartCocoonStageScRsp; import emu.lunarcore.server.packet.send.PacketSyncLineupNotify; import us.hebi.quickbuf.RepeatedInt; -import us.hebi.quickbuf.RepeatedMessage; public class BattleService extends BaseGameService { @@ -126,6 +125,11 @@ public class BattleService extends BaseGameService { } } + // Challenge + if (player.getChallengeData() != null) { + player.getChallengeData().onBattleStart(battle); + } + // Set battle and send rsp packet player.setBattle(battle); player.sendPacket(new PacketSceneCastSkillScRsp(battle, attackedGroupId)); @@ -179,7 +183,7 @@ public class BattleService extends BaseGameService { player.sendPacket(new PacketStartCocoonStageScRsp(battle, cocoonId, wave)); } - public Battle finishBattle(Player player, BattleEndStatus result, RepeatedMessage battleAvatars) { + public Battle finishBattle(Player player, BattleEndStatus result, BattleStatistics stats) { // Sanity check to make sure player is in a battle if (!player.isInBattle()) { return null; @@ -222,7 +226,7 @@ public class BattleService extends BaseGameService { // Check if avatar hp/sp should be updated after a battle if (updateStatus) { // Set health/energy for player avatars - for (var battleAvatar : battleAvatars) { + for (var battleAvatar : stats.getBattleAvatarList()) { GameAvatar avatar = player.getAvatarById(battleAvatar.getId()); if (avatar == null) continue; @@ -253,6 +257,11 @@ public class BattleService extends BaseGameService { } } + // Challenge + if (player.getChallengeData() != null) { + player.getChallengeData().onBattleFinish(battle, result, stats); + } + // Done - Clear battle object from player player.setBattle(null); return battle; diff --git a/src/main/java/emu/lunarcore/game/challenge/ChallengeData.java b/src/main/java/emu/lunarcore/game/challenge/ChallengeData.java new file mode 100644 index 0000000..975ff1e --- /dev/null +++ b/src/main/java/emu/lunarcore/game/challenge/ChallengeData.java @@ -0,0 +1,158 @@ +package emu.lunarcore.game.challenge; + +import emu.lunarcore.data.GameData; +import emu.lunarcore.data.config.GroupInfo; +import emu.lunarcore.data.config.MonsterInfo; +import emu.lunarcore.data.excel.ChallengeExcel; +import emu.lunarcore.data.excel.NpcMonsterExcel; +import emu.lunarcore.game.battle.Battle; +import emu.lunarcore.game.player.Player; +import emu.lunarcore.game.scene.Scene; +import emu.lunarcore.game.scene.entity.EntityMonster; +import emu.lunarcore.proto.BattleEndStatusOuterClass.BattleEndStatus; +import emu.lunarcore.proto.BattleStatisticsOuterClass.BattleStatistics; +import emu.lunarcore.proto.ChallengeInfoOuterClass.ChallengeInfo; +import emu.lunarcore.proto.ChallengeStatusOuterClass.ChallengeStatus; +import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType; +import emu.lunarcore.server.packet.send.PacketChallengeLineupNotify; +import emu.lunarcore.server.packet.send.PacketChallengeSettleNotify; +import emu.lunarcore.util.Position; +import lombok.Getter; +import lombok.Setter; + +@Getter +public class ChallengeData { + private final Player player; + private final Scene scene; + private final ChallengeExcel excel; + private final Position startPos; + + private int currentStage; + private ExtraLineupType currentExtraLineup; + private ChallengeStatus status; + + @Setter private int roundsLimit; + @Setter private int stars; + + public ChallengeData(Player player, ChallengeExcel excel) { + this.player = player; + this.scene = player.getScene(); + this.excel = excel; + this.startPos = player.getPos().clone(); + this.currentStage = 1; + this.roundsLimit = excel.getChallengeCountDown(); + this.status = ChallengeStatus.CHALLENGE_DOING; + this.currentExtraLineup = ExtraLineupType.LINEUP_CHALLENGE; + + // Setup first stage + this.setupStage1(); + } + + private void setupStage1() { + this.setupStage( + excel.getMazeGroupID1(), + excel.getConfigList1(), + excel.getNpcMonsterIDList1(), + excel.getEventIDList1(), + false + ); + } + + private void setupStage2() { + this.setupStage( + excel.getMazeGroupID2(), + excel.getConfigList2(), + excel.getNpcMonsterIDList2(), + excel.getEventIDList2(), + true + ); + } + + private void setupStage(int groupId, int[] configs, int[] npcMonsters, int[] eventIds, boolean sendPacket) { + // Load group + GroupInfo group = getScene().getFloorInfo().getGroups().get(groupId); + + // Replace monsters in scene + for (int i = 0; i < configs.length; i++) { + // Setup vars + int instId = configs[i]; + int npcMonster = npcMonsters[i]; + int eventId = eventIds[i]; + + // Get monster info + MonsterInfo monsterInfo = group.getMonsterById(instId); + if (monsterInfo == null) continue; + + // Get excels from game data + NpcMonsterExcel npcMonsterExcel = GameData.getNpcMonsterExcelMap().get(npcMonster); + if (npcMonsterExcel == null) continue; + + // Create monster with excels + EntityMonster monster = new EntityMonster(getScene(), npcMonsterExcel, monsterInfo.clonePos()); + monster.getRot().setY((int) (monsterInfo.getRotY() * 1000f)); + monster.setInstId(instId); + monster.setEventId(eventId); + monster.setOverrideStageId(eventId); + monster.setGroupId(group.getId()); + monster.setWorldLevel(this.getPlayer().getWorldLevel()); + + // Add to scene + getScene().addEntity(monster, sendPacket); + } + } + + public boolean isWin() { + return status == ChallengeStatus.CHALLENGE_FINISH; + } + + public void onBattleStart(Battle battle) { + battle.setRoundsLimit(player.getChallengeData().getRoundsLimit()); + } + + public void onBattleFinish(Battle battle, BattleEndStatus result, BattleStatistics stats) { + if (result == BattleEndStatus.BATTLE_END_WIN) { + // Get monster count in stage + long monsters = player.getScene().getEntities().values().stream().filter(e -> e instanceof EntityMonster).count(); + + if (monsters == 0) { + // Progress to the next stage + if (this.currentStage >= excel.getStageNum()) { + // Last stage + this.status = ChallengeStatus.CHALLENGE_FINISH; + this.stars = 9; // TODO calculate the right amount stars + // Send challenge result data + player.sendPacket(new PacketChallengeSettleNotify(this)); + } else { + // Increment and reset stage + this.currentStage++; + this.setupStage2(); + // Change player line up + this.currentExtraLineup = ExtraLineupType.LINEUP_CHALLENGE_2; + player.getLineupManager().setCurrentExtraLineup(this.getCurrentExtraLineup(), true); + player.sendPacket(new PacketChallengeLineupNotify(this.getCurrentExtraLineup())); + // Move player + player.moveTo(this.getStartPos()); + } + } + } else { + // Fail challenge + this.status = ChallengeStatus.CHALLENGE_FAILED; + } + } + + public void onUpdate() { + // End challenge if its done + if (status != ChallengeStatus.CHALLENGE_DOING) { + getPlayer().setChallengeData(null); + } + } + + public ChallengeInfo toProto() { + var proto = ChallengeInfo.newInstance() + .setChallengeId(this.getExcel().getId()) + .setStatus(this.getStatus()) + .setExtraLineupType(this.getCurrentExtraLineup()); + + return proto; + } +} \ No newline at end of file diff --git a/src/main/java/emu/lunarcore/game/challenge/ChallengeService.java b/src/main/java/emu/lunarcore/game/challenge/ChallengeService.java index fc9618b..6e59841 100644 --- a/src/main/java/emu/lunarcore/game/challenge/ChallengeService.java +++ b/src/main/java/emu/lunarcore/game/challenge/ChallengeService.java @@ -20,7 +20,19 @@ public class ChallengeService extends BaseGameService { return; } - player.enterScene(excel.getMapEntranceID(), 0, false); + // Sanity check lineups TODO + + // Enter scene + boolean success = player.enterScene(excel.getMapEntranceID(), 0, false); + if (success == false) { + return; + } + + // Set challenge data for player + ChallengeData data = new ChallengeData(player, excel); + + player.setChallengeData(data); + player.getLineupManager().setCurrentExtraLineup(data.getCurrentExtraLineup(), false); // Send packet player.sendPacket(new PacketStartChallengeScRsp(player, challengeId)); diff --git a/src/main/java/emu/lunarcore/game/player/LineupManager.java b/src/main/java/emu/lunarcore/game/player/LineupManager.java index 9934b0b..9d906f2 100644 --- a/src/main/java/emu/lunarcore/game/player/LineupManager.java +++ b/src/main/java/emu/lunarcore/game/player/LineupManager.java @@ -5,6 +5,7 @@ import java.util.List; import dev.morphia.annotations.Entity; import emu.lunarcore.GameConstants; import emu.lunarcore.game.avatar.GameAvatar; +import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType; import emu.lunarcore.server.packet.send.PacketSyncLineupNotify; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -43,8 +44,21 @@ public class LineupManager { this.mp = Math.max(this.mp - i, 0); } - public void setCurrentExtraLineup(int i) { - this.currentExtraLineup = i; + /** + * Sets the player's current extra lineup type. + * @param type Extra lineup type + * @param sync Whether or not to sync lineup with scene. Not needed when changing scenes. + */ + public void setCurrentExtraLineup(int type, boolean sync) { + this.currentExtraLineup = type; + + if (sync) { + this.getPlayer().getScene().syncLineup(); + } + } + + public void setCurrentExtraLineup(ExtraLineupType type, boolean sync) { + this.setCurrentExtraLineup(type.getNumber(), sync); } public PlayerLineup getLineupByIndex(int index, int extraLineup) { @@ -74,15 +88,7 @@ public class LineupManager { * @return */ private PlayerLineup getExtraLineupByType(int extraLineupType) { - PlayerLineup lineup = this.extraLineups.get(extraLineupType); - - if (lineup == null) { - lineup = new PlayerLineup(0, extraLineupType); - lineup.setOwnerAndIndex(this.getPlayer(), 0); - this.extraLineups.put(extraLineupType, lineup); - } - - return lineup; + return getExtraLineups().computeIfAbsent(extraLineupType, type -> new PlayerLineup(getPlayer(), 0, type)); } public PlayerLineup getCurrentLineup() { @@ -309,9 +315,10 @@ public class LineupManager { // Create new lineups for any missing ones for (int i = 0; i < this.lineups.length; i++) { if (this.lineups[i] == null) { - this.lineups[i] = new PlayerLineup(i); + this.lineups[i] = new PlayerLineup(getPlayer(), i, 0); + } else { + this.lineups[i].setOwnerAndIndex(getPlayer(), i); } - this.lineups[i].setOwnerAndIndex(getPlayer(), i); } // Set current index if out of bounds diff --git a/src/main/java/emu/lunarcore/game/player/Player.java b/src/main/java/emu/lunarcore/game/player/Player.java index 58d6751..eac153c 100644 --- a/src/main/java/emu/lunarcore/game/player/Player.java +++ b/src/main/java/emu/lunarcore/game/player/Player.java @@ -20,6 +20,7 @@ import emu.lunarcore.game.avatar.AvatarStorage; import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.avatar.HeroPath; import emu.lunarcore.game.battle.Battle; +import emu.lunarcore.game.challenge.ChallengeData; import emu.lunarcore.game.chat.ChatManager; import emu.lunarcore.game.chat.ChatMessage; import emu.lunarcore.game.enums.PropState; @@ -84,10 +85,12 @@ public class Player { private PlayerGachaInfo gachaInfo; // Etc - @Setter private transient boolean paused; private transient boolean inAnchorRange; private transient int nextBattleId; - + + @Setter private transient boolean paused; + @Setter private transient ChallengeData challengeData; + @Deprecated // Morphia only public Player() { this.curBasicType = GameConstants.TRAILBLAZER_AVATAR_ID; @@ -443,6 +446,9 @@ public class Player { } else { nextScene = new Scene(this, planeExcel, floorId); } + + // Clear any extra data the player might have + this.setChallengeData(null); // Set positions if player has logged in if (this.getSession().getState() != SessionState.WAITING_FOR_TOKEN) { diff --git a/src/main/java/emu/lunarcore/game/player/PlayerLineup.java b/src/main/java/emu/lunarcore/game/player/PlayerLineup.java index 9103b1c..20a730f 100644 --- a/src/main/java/emu/lunarcore/game/player/PlayerLineup.java +++ b/src/main/java/emu/lunarcore/game/player/PlayerLineup.java @@ -6,7 +6,6 @@ import java.util.List; import dev.morphia.annotations.Entity; import emu.lunarcore.GameConstants; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType; import emu.lunarcore.proto.LineupInfoOuterClass.LineupInfo; import emu.lunarcore.server.packet.send.PacketSyncLineupNotify; import lombok.Getter; @@ -26,11 +25,9 @@ public class PlayerLineup { } - public PlayerLineup(int index) { - this(index, 0); - } - - public PlayerLineup(int index, int extraLineupType) { + public PlayerLineup(Player player, int index, int extraLineupType) { + this.owner = player; + this.index = index; this.extraLineupType = extraLineupType; this.avatars = new ArrayList<>(GameConstants.MAX_AVATARS_IN_TEAM); @@ -93,7 +90,7 @@ public class PlayerLineup { .setLeaderSlot(this.getOwner().getLineupManager().getCurrentLeader()) .setMp(this.getOwner().getLineupManager().getMp()) .setMaxMp(GameConstants.MAX_MP) - .setExtraLineupType(ExtraLineupType.LINEUP_NONE); + .setExtraLineupTypeValue(this.getExtraLineupType()); for (int slot = 0; slot < this.getAvatars().size(); slot++) { GameAvatar avatar = owner.getAvatars().getAvatarById(getAvatars().get(slot)); diff --git a/src/main/java/emu/lunarcore/game/scene/Scene.java b/src/main/java/emu/lunarcore/game/scene/Scene.java index 593bf3c..e459a69 100644 --- a/src/main/java/emu/lunarcore/game/scene/Scene.java +++ b/src/main/java/emu/lunarcore/game/scene/Scene.java @@ -10,6 +10,7 @@ import emu.lunarcore.data.excel.MazePlaneExcel; import emu.lunarcore.data.excel.NpcMonsterExcel; import emu.lunarcore.data.excel.PropExcel; import emu.lunarcore.game.avatar.GameAvatar; +import emu.lunarcore.game.enums.GameModeType; import emu.lunarcore.game.enums.PropState; import emu.lunarcore.game.enums.PropType; import emu.lunarcore.game.player.PlayerLineup; @@ -78,110 +79,122 @@ public class Scene { this.avatarEntityIds.add(avatar.getEntityId()); } - // Spawn monsters + // Set floor info this.floorInfo = GameData.getFloorInfo(this.planeId, this.floorId); if (floorInfo == null) return; - for (GroupInfo group : floorInfo.getGroups().values()) { - // Skip non-server groups - if (group.getLoadSide() != GroupLoadSide.Server) { - continue; - } - - // Add monsters - if (group.getMonsterList() != null && group.getMonsterList().size() > 0) { - for (MonsterInfo monsterInfo : group.getMonsterList()) { - // Get excels from game data - NpcMonsterExcel npcMonsterExcel = GameData.getNpcMonsterExcelMap().get(monsterInfo.getNPCMonsterID()); - if (npcMonsterExcel == null) continue; - - // Create monster with excels - EntityMonster monster = new EntityMonster(this, npcMonsterExcel, monsterInfo.clonePos()); - monster.getRot().setY((int) (monsterInfo.getRotY() * 1000f)); - monster.setInstId(monsterInfo.getID()); - monster.setEventId(monsterInfo.getEventID()); - monster.setGroupId(group.getId()); - monster.setWorldLevel(this.getPlayer().getWorldLevel()); - - // Add to monsters - this.addEntity(monster); - } - } - - // Add props - if (group.getPropList() != null && group.getPropList().size() > 0) { - for (PropInfo propInfo : group.getPropList()) { - // Get prop excel - PropExcel propExcel = GameData.getPropExcelMap().get(propInfo.getPropID()); - if (propExcel == null) { - continue; - } - - // Create prop from prop info - EntityProp prop = new EntityProp(this, propExcel, propInfo.clonePos()); - prop.setState(propInfo.getState()); - prop.getRot().set( - (int) (propInfo.getRotX() * 1000f), - (int) (propInfo.getRotY() * 1000f), - (int) (propInfo.getRotZ() * 1000f) - ); - prop.setInstId(propInfo.getID()); - prop.setGroupId(group.getId()); - prop.setPropInfo(propInfo); - - // Hacky fixes - if (prop.getPropId() == 1003) { - // Open simulated universe - prop.setState(PropState.Open); - } else if (prop.getExcel().getPropType() == PropType.PROP_SPRING) { - // Cache teleport anchors - this.getHealingSprings().add(prop); - } - - // Add trigger - if (propInfo.getTrigger() != null) { - this.getTriggers().add(propInfo.getTrigger()); - } - - // Add to monsters - this.addEntity(prop); - } - } - - // Add npcs - if (group.getNPCList() != null && group.getNPCList().size() > 0) { - for (NpcInfo npcInfo : group.getNPCList()) { - // Sanity check - if (!GameData.getNpcExcelMap().containsKey(npcInfo.getNPCID())) { - continue; - } - - // Dont spawn duplicate NPCs - boolean haseDuplicateNpcId = false; - for (GameEntity entity : this.getEntities().values()) { - if (entity instanceof EntityNpc eNpc && eNpc.getNpcId() == npcInfo.getNPCID()) { - haseDuplicateNpcId = true; - break; - } - } - if (haseDuplicateNpcId) continue; - - // Create npc from npc info - EntityNpc npc = new EntityNpc(this, npcInfo.getNPCID(), npcInfo.clonePos()); - npc.getRot().setY((int) (npcInfo.getRotY() * 1000f)); - npc.setInstId(npcInfo.getID()); - npc.setGroupId(group.getId()); - - // Add to monsters - this.addEntity(npc); - } - } + // Spawn from groups + if (this.getExcel().getPlaneType() != GameModeType.Challenge) { + this.initSpawns(); } // Done this.loaded = true; } + private void initSpawns() { + for (GroupInfo group : getFloorInfo().getGroups().values()) { + // Skip non-server groups + if (group.getLoadSide() != GroupLoadSide.Server) { + continue; + } + + // Load group + this.loadGroup(group); + } + } + + private void loadGroup(GroupInfo group) { + // Add monsters + if (group.getMonsterList() != null && group.getMonsterList().size() > 0) { + for (MonsterInfo monsterInfo : group.getMonsterList()) { + // Get excels from game data + NpcMonsterExcel npcMonsterExcel = GameData.getNpcMonsterExcelMap().get(monsterInfo.getNPCMonsterID()); + if (npcMonsterExcel == null) continue; + + // Create monster with excels + EntityMonster monster = new EntityMonster(this, npcMonsterExcel, monsterInfo.clonePos()); + monster.getRot().setY((int) (monsterInfo.getRotY() * 1000f)); + monster.setInstId(monsterInfo.getID()); + monster.setEventId(monsterInfo.getEventID()); + monster.setGroupId(group.getId()); + monster.setWorldLevel(this.getPlayer().getWorldLevel()); + + // Add to monsters + this.addEntity(monster); + } + } + + // Add props + if (group.getPropList() != null && group.getPropList().size() > 0) { + for (PropInfo propInfo : group.getPropList()) { + // Get prop excel + PropExcel propExcel = GameData.getPropExcelMap().get(propInfo.getPropID()); + if (propExcel == null) { + continue; + } + + // Create prop from prop info + EntityProp prop = new EntityProp(this, propExcel, propInfo.clonePos()); + prop.setState(propInfo.getState()); + prop.getRot().set( + (int) (propInfo.getRotX() * 1000f), + (int) (propInfo.getRotY() * 1000f), + (int) (propInfo.getRotZ() * 1000f) + ); + prop.setInstId(propInfo.getID()); + prop.setGroupId(group.getId()); + prop.setPropInfo(propInfo); + + // Hacky fixes + if (prop.getPropId() == 1003) { + // Open simulated universe + prop.setState(PropState.Open); + } else if (prop.getExcel().getPropType() == PropType.PROP_SPRING) { + // Cache teleport anchors + this.getHealingSprings().add(prop); + } + + // Add trigger + if (propInfo.getTrigger() != null) { + this.getTriggers().add(propInfo.getTrigger()); + } + + // Add to monsters + this.addEntity(prop); + } + } + + // Add npcs + if (group.getNPCList() != null && group.getNPCList().size() > 0) { + for (NpcInfo npcInfo : group.getNPCList()) { + // Sanity check + if (!GameData.getNpcExcelMap().containsKey(npcInfo.getNPCID())) { + continue; + } + + // Dont spawn duplicate NPCs + boolean haseDuplicateNpcId = false; + for (GameEntity entity : this.getEntities().values()) { + if (entity instanceof EntityNpc eNpc && eNpc.getNpcId() == npcInfo.getNPCID()) { + haseDuplicateNpcId = true; + break; + } + } + if (haseDuplicateNpcId) continue; + + // Create npc from npc info + EntityNpc npc = new EntityNpc(this, npcInfo.getNPCID(), npcInfo.clonePos()); + npc.getRot().setY((int) (npcInfo.getRotY() * 1000f)); + npc.setInstId(npcInfo.getID()); + npc.setGroupId(group.getId()); + + // Add to monsters + this.addEntity(npc); + } + } + } + public void setEntryId(int entryId) { this.entryId = entryId; } @@ -293,6 +306,10 @@ public class Scene { } public synchronized void addEntity(GameEntity entity) { + this.addEntity(entity, false); + } + + public synchronized void addEntity(GameEntity entity, boolean sendPacket) { // Dont add if monster id already exists if (entity.getEntityId() != 0) return; // Set entity id and add monster to entity map @@ -300,6 +317,10 @@ public class Scene { this.getEntities().put(entity.getEntityId(), entity); // Entity add callback entity.onAdd(); + // Send packet + if (sendPacket) { + player.sendPacket(new PacketSceneGroupRefreshScNotify(entity, null)); + } } public synchronized void removeEntity(GameEntity entity) { diff --git a/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java b/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java index b68c8ae..061d8ff 100644 --- a/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java +++ b/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java @@ -20,9 +20,9 @@ public class EntityMonster implements GameEntity { @Setter private int instId; @Setter private int eventId; @Setter private int overrideStageId; + @Setter private NpcMonsterExcel excel; private final Scene scene; - private final NpcMonsterExcel excel; private final Position pos; private final Position rot; diff --git a/src/main/java/emu/lunarcore/server/packet/recv/HandlerGetCurChallengeCsReq.java b/src/main/java/emu/lunarcore/server/packet/recv/HandlerGetCurChallengeCsReq.java new file mode 100644 index 0000000..da96c11 --- /dev/null +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerGetCurChallengeCsReq.java @@ -0,0 +1,22 @@ +package emu.lunarcore.server.packet.recv; + +import emu.lunarcore.server.game.GameSession; +import emu.lunarcore.server.packet.CmdId; +import emu.lunarcore.server.packet.Opcodes; +import emu.lunarcore.server.packet.PacketHandler; +import emu.lunarcore.server.packet.send.PacketGetCurChallengeScRsp; + +@Opcodes(CmdId.GetCurChallengeCsReq) +public class HandlerGetCurChallengeCsReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] data) throws Exception { + // Send packet first + session.send(new PacketGetCurChallengeScRsp(session.getPlayer())); + // Update challenge details for client + if (session.getPlayer().getChallengeData() != null) { + session.getPlayer().getChallengeData().onUpdate(); + } + } + +} diff --git a/src/main/java/emu/lunarcore/server/packet/recv/HandlerLeaveChallengeCsReq.java b/src/main/java/emu/lunarcore/server/packet/recv/HandlerLeaveChallengeCsReq.java index 853db06..0f3d5cb 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerLeaveChallengeCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerLeaveChallengeCsReq.java @@ -11,7 +11,7 @@ public class HandlerLeaveChallengeCsReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] data) throws Exception { // TODO make sure client is in a challenge mode map - session.getPlayer().getLineupManager().setCurrentExtraLineup(0); + session.getPlayer().getLineupManager().setCurrentExtraLineup(0, false); session.getPlayer().enterScene(100000103, 0, true); session.send(CmdId.LeaveChallengeScRsp); } diff --git a/src/main/java/emu/lunarcore/server/packet/recv/HandlerPVEBattleResultCsReq.java b/src/main/java/emu/lunarcore/server/packet/recv/HandlerPVEBattleResultCsReq.java index 6fba4fb..2d40bfd 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerPVEBattleResultCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerPVEBattleResultCsReq.java @@ -18,7 +18,7 @@ public class HandlerPVEBattleResultCsReq extends PacketHandler { Battle battle = session.getServer().getBattleService().finishBattle( session.getPlayer(), req.getEndStatus(), - req.getStt().getBattleAvatarList() + req.getStt() ); if (battle != null) { diff --git a/src/main/java/emu/lunarcore/server/packet/recv/HandlerReplaceLineupCsReq.java b/src/main/java/emu/lunarcore/server/packet/recv/HandlerReplaceLineupCsReq.java index d1a6de6..8f3b53e 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerReplaceLineupCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerReplaceLineupCsReq.java @@ -23,7 +23,7 @@ public class HandlerReplaceLineupCsReq extends PacketHandler { lineupList.add(slot.getId()); } - session.getPlayer().getLineupManager().replaceLineup(req.getIndex(), req.getExtraLineupType().getNumber(), lineupList); + session.getPlayer().getLineupManager().replaceLineup(req.getIndex(), req.getExtraLineupTypeValue(), lineupList); session.send(new BasePacket(CmdId.ReplaceLineupScRsp)); } diff --git a/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeLineupNotify.java b/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeLineupNotify.java new file mode 100644 index 0000000..76fe439 --- /dev/null +++ b/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeLineupNotify.java @@ -0,0 +1,18 @@ +package emu.lunarcore.server.packet.send; + +import emu.lunarcore.proto.ChallengeLineupNotifyOuterClass.ChallengeLineupNotify; +import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType; +import emu.lunarcore.server.packet.BasePacket; +import emu.lunarcore.server.packet.CmdId; + +public class PacketChallengeLineupNotify extends BasePacket { + + public PacketChallengeLineupNotify(ExtraLineupType type) { + super(CmdId.ChallengeLineupNotify); + + var data = ChallengeLineupNotify.newInstance() + .setExtraLineupType(type); + + this.setData(data); + } +} diff --git a/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeSettleNotify.java b/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeSettleNotify.java new file mode 100644 index 0000000..f06bf92 --- /dev/null +++ b/src/main/java/emu/lunarcore/server/packet/send/PacketChallengeSettleNotify.java @@ -0,0 +1,22 @@ +package emu.lunarcore.server.packet.send; + +import emu.lunarcore.game.challenge.ChallengeData; +import emu.lunarcore.proto.ChallengeSettleNotifyOuterClass.ChallengeSettleNotify; +import emu.lunarcore.proto.ItemListOuterClass.ItemList; +import emu.lunarcore.server.packet.BasePacket; +import emu.lunarcore.server.packet.CmdId; + +public class PacketChallengeSettleNotify extends BasePacket { + + public PacketChallengeSettleNotify(ChallengeData challenge) { + super(CmdId.ChallengeSettleNotify); + + var data = ChallengeSettleNotify.newInstance() + .setChallengeId(challenge.getExcel().getId()) + .setIsWin(challenge.isWin()) + .setReward(ItemList.newInstance()) + .setStars(challenge.getStars()); + + this.setData(data); + } +} diff --git a/src/main/java/emu/lunarcore/server/packet/send/PacketGetCurChallengeScRsp.java b/src/main/java/emu/lunarcore/server/packet/send/PacketGetCurChallengeScRsp.java new file mode 100644 index 0000000..a038646 --- /dev/null +++ b/src/main/java/emu/lunarcore/server/packet/send/PacketGetCurChallengeScRsp.java @@ -0,0 +1,23 @@ +package emu.lunarcore.server.packet.send; + +import emu.lunarcore.game.player.Player; +import emu.lunarcore.proto.GetCurChallengeScRspOuterClass.GetCurChallengeScRsp; +import emu.lunarcore.server.packet.BasePacket; +import emu.lunarcore.server.packet.CmdId; + +public class PacketGetCurChallengeScRsp extends BasePacket { + + public PacketGetCurChallengeScRsp(Player player) { + super(CmdId.GetCurChallengeScRsp); + + var data = GetCurChallengeScRsp.newInstance(); + + if (player.getChallengeData() != null) { + data.setChallengeInfo(player.getChallengeData().toProto()); + } else { + data.setRetcode(1); + } + + this.setData(data); + } +} diff --git a/src/main/java/emu/lunarcore/server/packet/send/PacketStartChallengeScRsp.java b/src/main/java/emu/lunarcore/server/packet/send/PacketStartChallengeScRsp.java index 6c5c911..e8d34c3 100644 --- a/src/main/java/emu/lunarcore/server/packet/send/PacketStartChallengeScRsp.java +++ b/src/main/java/emu/lunarcore/server/packet/send/PacketStartChallengeScRsp.java @@ -22,15 +22,15 @@ public class PacketStartChallengeScRsp extends BasePacket { public PacketStartChallengeScRsp(Player player, int challengeId) { super(CmdId.StartChallengeScRsp); - var challengeInfo = ChallengeInfo.newInstance() - .setChallengeId(challengeId) - .setStatus(ChallengeStatus.CHALLENGE_DOING) - .setExtraLineupType(ExtraLineupType.LINEUP_CHALLENGE); + var data = StartChallengeScRsp.newInstance(); - var data = StartChallengeScRsp.newInstance() - .setLineup(player.getCurrentLineup().toProto().setExtraLineupType(ExtraLineupType.LINEUP_CHALLENGE)) // TODO temporary - .setScene(player.getScene().toProto()) - .setChallengeInfo(challengeInfo); + if (player.getChallengeData() != null) { + data.setLineup(player.getCurrentLineup().toProto()); + data.setScene(player.getScene().toProto()); + data.setChallengeInfo(player.getChallengeData().toProto()); + } else { + data.setRetcode(1); + } this.setData(data); }