Merge branch 'development' into unstable

# Conflicts:
#	src/main/java/emu/grasscutter/game/dungeons/DungeonSystem.java
#	src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java
#	src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java
This commit is contained in:
KingRainbow44
2023-04-18 15:32:50 -04:00
4 changed files with 332 additions and 331 deletions

View File

@@ -1 +1,2 @@
org.gradle.jvmargs=-Xmx1024m org.gradle.jvmargs=-Xmx1024m
# spikehd was here :)

View File

@@ -1,122 +1,122 @@
package emu.grasscutter.game.dungeons; package emu.grasscutter.game.dungeons;
import emu.grasscutter.GameConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.ScenePointEntry; import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.excels.DungeonData; import emu.grasscutter.data.excels.DungeonData;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.SceneType; import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.server.game.BaseGameSystem; import emu.grasscutter.server.game.BaseGameSystem;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp; import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp; import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import java.util.List; import java.util.List;
public class DungeonSystem extends BaseGameSystem { public class DungeonSystem extends BaseGameSystem {
private static final BasicDungeonSettleListener basicDungeonSettleObserver = private static final BasicDungeonSettleListener basicDungeonSettleObserver =
new BasicDungeonSettleListener(); new BasicDungeonSettleListener();
public DungeonSystem(GameServer server) { public DungeonSystem(GameServer server) {
super(server); super(server);
} }
public void getEntryInfo(Player player, int pointId) { public void getEntryInfo(Player player, int pointId, int sceneId) {
ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId); ScenePointEntry entry = GameData.getScenePointEntryById(sceneId, pointId);
if (entry == null) { if (entry == null) {
// Error // Error
player.sendPacket(new PacketDungeonEntryInfoRsp()); player.sendPacket(new PacketDungeonEntryInfoRsp());
return; return;
} }
player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData())); player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
} }
public boolean enterDungeon(Player player, int pointId, int dungeonId) { public boolean enterDungeon(Player player, int pointId, int dungeonId) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId); DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
if (data == null) { if (data == null) {
return false; return false;
} }
Grasscutter.getLogger() Grasscutter.getLogger()
.info( .info(
"{}({}) is trying to enter dungeon {}", "{}({}) is trying to enter dungeon {}",
player.getNickname(), player.getNickname(),
player.getUid(), player.getUid(),
dungeonId); dungeonId);
int sceneId = data.getSceneId(); int sceneId = data.getSceneId();
player.getScene().setPrevScene(sceneId); player.getScene().setPrevScene(sceneId);
if (player.getWorld().transferPlayerToScene(player, sceneId, data)) { if (player.getWorld().transferPlayerToScene(player, sceneId, data)) {
player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver);
player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId()); player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId());
} }
player.getScene().setPrevScenePoint(pointId); player.getScene().setPrevScenePoint(pointId);
player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId)); player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId));
return true; return true;
} }
/** used in tower dungeons handoff */ /** used in tower dungeons handoff */
public boolean handoffDungeon( public boolean handoffDungeon(
Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) { Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId); DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
if (data == null) { if (data == null) {
return false; return false;
} }
Grasscutter.getLogger() Grasscutter.getLogger()
.info( .info(
"{}({}) is trying to enter tower dungeon {}", "{}({}) is trying to enter tower dungeon {}",
player.getNickname(), player.getNickname(),
player.getUid(), player.getUid(),
dungeonId); dungeonId);
if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) { if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) {
dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver); dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver);
} }
return true; return true;
} }
public void exitDungeon(Player player) { public void exitDungeon(Player player) {
Scene scene = player.getScene(); Scene scene = player.getScene();
if (scene == null || scene.getSceneType() != SceneType.SCENE_DUNGEON) { if (scene == null || scene.getSceneType() != SceneType.SCENE_DUNGEON) {
return; return;
} }
// Get previous scene // Get previous scene
int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3; int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3;
// Get previous position // Get previous position
DungeonData dungeonData = scene.getDungeonData(); DungeonData dungeonData = scene.getDungeonData();
Position prevPos = new Position(GameConstants.START_POSITION); Position prevPos = new Position(GameConstants.START_POSITION);
if (dungeonData != null) { if (dungeonData != null) {
ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint()); ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint());
if (entry != null) { if (entry != null) {
prevPos.set(entry.getPointData().getTranPos()); prevPos.set(entry.getPointData().getTranPos());
} }
} }
// clean temp team if it has // clean temp team if it has
player.getTeamManager().cleanTemporaryTeam(); player.getTeamManager().cleanTemporaryTeam();
player.getTowerManager().clearEntry(); player.getTowerManager().clearEntry();
// Transfer player back to world // Transfer player back to world
player.getWorld().transferPlayerToScene(player, prevScene, prevPos); player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp)); player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp));
} }
public void updateDailyDungeons() { public void updateDailyDungeons() {
GameData.getScenePointEntries() GameData.getScenePointEntries()
.forEach((id, entry) -> entry.getPointData().updateDailyDungeon()); .forEach((id, entry) -> entry.getPointData().updateDailyDungeon());
} }
} }

View File

@@ -1,191 +1,191 @@
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify;
import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo;
import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; import emu.grasscutter.net.proto.EvtAnimatorParameterInfoOuterClass.EvtAnimatorParameterInfo;
import emu.grasscutter.net.proto.EvtAnimatorParameterInfoOuterClass.EvtAnimatorParameterInfo; import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo;
import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass;
import emu.grasscutter.server.event.entity.EntityMoveEvent; import emu.grasscutter.server.event.entity.EntityMoveEvent;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
@Opcodes(PacketOpcodes.CombatInvocationsNotify) @Opcodes(PacketOpcodes.CombatInvocationsNotify)
public class HandlerCombatInvocationsNotify extends PacketHandler { public class HandlerCombatInvocationsNotify extends PacketHandler {
private float cachedLandingSpeed = 0; private float cachedLandingSpeed = 0;
private long cachedLandingTimeMillisecond = 0; private long cachedLandingTimeMillisecond = 0;
private boolean monitorLandingEvent = false; private boolean monitorLandingEvent = false;
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload);
for (CombatInvokeEntry entry : notif.getInvokeListList()) { for (CombatInvokeEntry entry : notif.getInvokeListList()) {
// Handle combat invoke // Handle combat invoke
switch (entry.getArgumentType()) { switch (entry.getArgumentType()) {
case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT -> { case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT -> {
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
AttackResult attackResult = hitInfo.getAttackResult(); AttackResult attackResult = hitInfo.getAttackResult();
Player player = session.getPlayer(); Player player = session.getPlayer();
// Check if the player is invulnerable. // Check if the player is invulnerable.
if (attackResult.getAttackerId() if (attackResult.getAttackerId()
!= player.getTeamManager().getCurrentAvatarEntity().getId() != player.getTeamManager().getCurrentAvatarEntity().getId()
&& player.getAbilityManager().isAbilityInvulnerable()) break; && player.getAbilityManager().isAbilityInvulnerable()) break;
// Handle damage // Handle damage
player.getAttackResults().add(attackResult); player.getAttackResults().add(attackResult);
player.getEnergyManager().handleAttackHit(hitInfo); player.getEnergyManager().handleAttackHit(hitInfo);
} }
case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE -> { case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE -> {
// Handle movement // Handle movement
EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData());
GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId());
if (entity != null) { if (entity != null) {
// Move player // Move player
MotionInfo motionInfo = moveInfo.getMotionInfo(); MotionInfo motionInfo = moveInfo.getMotionInfo();
MotionState motionState = motionInfo.getState(); MotionState motionState = motionInfo.getState();
// Call entity move event. // Call entity move event.
EntityMoveEvent event = EntityMoveEvent event =
new EntityMoveEvent( new EntityMoveEvent(
entity, entity,
new Position(motionInfo.getPos()), new Position(motionInfo.getPos()),
new Position(motionInfo.getRot()), new Position(motionInfo.getRot()),
motionState); motionState);
event.call(); event.call();
entity.move(event.getPosition(), event.getRotation()); entity.move(event.getPosition(), event.getRotation());
entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime());
entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); entity.setLastMoveReliableSeq(moveInfo.getReliableSeq());
entity.setMotionState(motionState); entity.setMotionState(motionState);
session session
.getPlayer() .getPlayer()
.getStaminaManager() .getStaminaManager()
.handleCombatInvocationsNotify(session, moveInfo, entity); .handleCombatInvocationsNotify(session, moveInfo, entity);
// TODO: handle MOTION_FIGHT landing which has a different damage factor // TODO: handle MOTION_FIGHT landing which has a different damage factor
// Also, for plunge attacks, LAND_SPEED is always -30 and is not useful. // Also, for plunge attacks, LAND_SPEED is always -30 and is not useful.
// May need the height when starting plunge attack. // May need the height when starting plunge attack.
// MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets. // MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets.
// Cache land speed for later use. // Cache land speed for later use.
if (motionState == MotionState.MOTION_STATE_LAND_SPEED) { if (motionState == MotionState.MOTION_STATE_LAND_SPEED) {
cachedLandingSpeed = motionInfo.getSpeed().getY(); cachedLandingSpeed = motionInfo.getSpeed().getY();
cachedLandingTimeMillisecond = System.currentTimeMillis(); cachedLandingTimeMillisecond = System.currentTimeMillis();
monitorLandingEvent = true; monitorLandingEvent = true;
} }
if (monitorLandingEvent) { if (monitorLandingEvent) {
if (motionState == MotionState.MOTION_STATE_FALL_ON_GROUND) { if (motionState == MotionState.MOTION_STATE_FALL_ON_GROUND) {
monitorLandingEvent = false; monitorLandingEvent = false;
handleFallOnGround(session, entity, motionState); handleFallOnGround(session, entity, motionState);
} }
} }
// MOTION_STATE_NOTIFY = Dont send to other players // as long as one of these two packets be forwarded to client, the animation of avatar will be interrupted
if (motionState == MotionState.MOTION_STATE_NOTIFY) { if (motionState == MotionState.MOTION_STATE_NOTIFY || motionState == MotionState.MOTION_STATE_FIGHT) {
continue; continue;
} }
} }
} }
case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED -> { case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED -> {
EvtAnimatorParameterInfo paramInfo = var paramInfo =
EvtAnimatorParameterInfo.parseFrom(entry.getCombatData()); EvtAnimatorParameterInfo.parseFrom(entry.getCombatData());
if (paramInfo.getIsServerCache()) { if (paramInfo.getIsServerCache()) {
paramInfo = paramInfo.toBuilder().setIsServerCache(false).build(); paramInfo = paramInfo.toBuilder().setIsServerCache(false).build();
entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build(); entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build();
} }
} }
default -> {} default -> {}
} }
session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry);
} }
} }
private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) { private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) {
if (session.getPlayer().inGodmode()) { if (session.getPlayer().inGodmode()) {
return; return;
} }
// People have reported that after plunge attack (client sends a FIGHT instead of // People have reported that after plunge attack (client sends a FIGHT instead of
// FALL_ON_GROUND) they will die // FALL_ON_GROUND) they will die
// if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping // if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping
// again. // again.
// A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet. // A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet.
// 200ms seems to be a reasonable delay. // 200ms seems to be a reasonable delay.
int maxDelay = 200; int maxDelay = 200;
long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond; long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond;
Grasscutter.getLogger() Grasscutter.getLogger()
.trace( .trace(
"MOTION_FALL_ON_GROUND received after " "MOTION_FALL_ON_GROUND received after "
+ actualDelay + actualDelay
+ "/" + "/"
+ maxDelay + maxDelay
+ "ms." + "ms."
+ (actualDelay > maxDelay ? " Discard" : "")); + (actualDelay > maxDelay ? " Discard" : ""));
if (actualDelay > maxDelay) { if (actualDelay > maxDelay) {
return; return;
} }
float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
float damageFactor = 0; float damageFactor = 0;
if (cachedLandingSpeed < -23.5) { if (cachedLandingSpeed < -23.5) {
damageFactor = 0.33f; damageFactor = 0.33f;
} }
if (cachedLandingSpeed < -25) { if (cachedLandingSpeed < -25) {
damageFactor = 0.5f; damageFactor = 0.5f;
} }
if (cachedLandingSpeed < -26.5) { if (cachedLandingSpeed < -26.5) {
damageFactor = 0.66f; damageFactor = 0.66f;
} }
if (cachedLandingSpeed < -28) { if (cachedLandingSpeed < -28) {
damageFactor = 1f; damageFactor = 1f;
} }
float damage = maxHP * damageFactor; float damage = maxHP * damageFactor;
float newHP = currentHP - damage; float newHP = currentHP - damage;
if (newHP < 0) { if (newHP < 0) {
newHP = 0; newHP = 0;
} }
if (damageFactor > 0) { if (damageFactor > 0) {
Grasscutter.getLogger() Grasscutter.getLogger()
.debug( .debug(
currentHP currentHP
+ "/" + "/"
+ maxHP + maxHP
+ "\tLandingSpeed: " + "\tLandingSpeed: "
+ cachedLandingSpeed + cachedLandingSpeed
+ "\tDamageFactor: " + "\tDamageFactor: "
+ damageFactor + damageFactor
+ "\tDamage: " + "\tDamage: "
+ damage + damage
+ "\tNewHP: " + "\tNewHP: "
+ newHP); + newHP);
} else { } else {
Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage"); Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage");
} }
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP);
entity entity
.getWorld() .getWorld()
.broadcastPacket( .broadcastPacket(
new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
if (newHP == 0) { if (newHP == 0) {
session session
.getPlayer() .getPlayer()
.getStaminaManager() .getStaminaManager()
.killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_TYPE_FALL); .killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_TYPE_FALL);
} }
cachedLandingSpeed = 0; cachedLandingSpeed = 0;
} }
} }

View File

@@ -1,18 +1,18 @@
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq; import emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.DungeonEntryInfoReq) @Opcodes(PacketOpcodes.DungeonEntryInfoReq)
public class HandlerDungeonEntryInfoReq extends PacketHandler { public class HandlerDungeonEntryInfoReq extends PacketHandler {
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
DungeonEntryInfoReq req = DungeonEntryInfoReq.parseFrom(payload); DungeonEntryInfoReq req = DungeonEntryInfoReq.parseFrom(payload);
session.getServer().getDungeonSystem().getEntryInfo(session.getPlayer(), req.getPointId()); session.getServer().getDungeonSystem().getEntryInfo(session.getPlayer(), req.getPointId(), req.getSceneId());
} }
} }