Skip to content

Commit

Permalink
Tower Dungeons Handoff between level and floor
Browse files Browse the repository at this point in the history
  • Loading branch information
Akka0 committed May 6, 2022
1 parent a79e008 commit 6144f47
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 29 deletions.
5 changes: 5 additions & 0 deletions proto/DungeonSettleNotify.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ option java_package = "emu.grasscutter.net.proto";

import "ParamList.proto";
import "StrengthenPointData.proto";
import "TowerLevelEndNotify.proto";

message DungeonSettleNotify {
oneof Detail {
TowerLevelEndNotify tower_level_end_notify = 101;
// it has more!
}
uint32 dungeon_id = 1;
bool is_success = 2;
repeated uint32 fail_cond_list = 3;
Expand Down
18 changes: 18 additions & 0 deletions proto/TowerFloorRecordChangeNotify.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

option java_package = "emu.grasscutter.net.proto";

import "TowerFloorRecord.proto";

message TowerFloorRecordChangeNotify {
enum CmdId {
option allow_alias = true;
NONE = 0;
ENET_CHANNEL_ID = 0;
ENET_IS_RELIABLE = 1;
CMD_ID = 2418;
}

repeated TowerFloorRecord tower_floor_record_list = 1;
bool is_finished_entrance_floor = 2;
}
26 changes: 26 additions & 0 deletions proto/TowerLevelEndNotify.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";

option java_package = "emu.grasscutter.net.proto";
import "ItemParam.proto";

message TowerLevelEndNotify {
enum CmdId {
option allow_alias = true;
NONE = 0;
ENET_CHANNEL_ID = 0;
ENET_IS_RELIABLE = 1;
CMD_ID = 2456;
}

enum ContinueStateType {
CONTINUE_STATE_CAN_NOT_CONTINUE = 0;
CONTINUE_STATE_CAN_ENTER_NEXT_LEVEL = 1;
CONTINUE_STATE_CAN_ENTER_NEXT_FLOOR = 2;
}

bool is_success = 1;
repeated uint32 finished_star_cond_list = 2;
repeated ItemParam reward_item_list = 3;
uint32 continue_state = 4;
uint32 next_floor_id = 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package emu.grasscutter.game.dungeons;

import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
import emu.grasscutter.utils.Utils;

public class BasicDungeonSettleListener implements DungeonSettleListener {

@Override
public void onDungeonSettle(Scene scene) {
scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000);
scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge()));
}
}
19 changes: 5 additions & 14 deletions src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
package emu.grasscutter.game.dungeons;

import java.util.ArrayList;
import java.util.List;

import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.GameEntity;
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.VisionTypeOuterClass.VisionType;
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.server.packet.send.PacketChallengeDataNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify;
import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify;
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;

import java.util.ArrayList;
import java.util.List;

public class DungeonChallenge {
private final Scene scene;
private final SceneGroup group;
Expand All @@ -40,7 +32,7 @@ public class DungeonChallenge {
private int score;
private int objective = 0;
private IntSet rewardedPlayers;

public DungeonChallenge(Scene scene, SceneGroup group) {
this.scene = scene;
this.group = group;
Expand Down Expand Up @@ -129,8 +121,7 @@ public void finish() {
}

private void settle() {
getScene().setAutoCloseTime(Utils.getCurrentSeconds() + 1000);
getScene().broadcastPacket(new PacketDungeonSettleNotify(this));
getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene()));

getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0));
}
Expand Down
28 changes: 25 additions & 3 deletions src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp;
import emu.grasscutter.utils.Position;

import java.util.List;

public class DungeonManager {
private final GameServer server;

private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener();
public DungeonManager(GameServer server) {
this.server = server;
}
Expand Down Expand Up @@ -49,13 +51,32 @@ public boolean enterDungeon(Player player, int pointId, int dungeonId) {
int sceneId = data.getSceneId();
player.getScene().setPrevScene(sceneId);

player.getWorld().transferPlayerToScene(player, sceneId, data);
if(player.getWorld().transferPlayerToScene(player, sceneId, data)){
player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver);
}

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<DungeonSettleListener> dungeonSettleListeners) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId);

if (data == null) {
return false;
}
Grasscutter.getLogger().info(player.getNickname() + " is trying to enter tower dungeon " + dungeonId);

if(player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)){
dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver);
}
return true;
}

public void exitDungeon(Player player) {
if (player.getScene().getSceneType() != SceneType.SCENE_DUNGEON) {
return;
Expand All @@ -77,6 +98,7 @@ public void exitDungeon(Player player) {
}
// 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));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package emu.grasscutter.game.dungeons;

import emu.grasscutter.game.world.Scene;

public interface DungeonSettleListener {
void onDungeonSettle(Scene scene);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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) {
scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000);
var towerManager = scene.getPlayers().get(0).getTowerManager();

towerManager.notifyCurLevelRecordChangeWhenDone();
scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify(towerManager.getCurrentFloorId()));
scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge(),
true,
towerManager.hasNextLevel(),
towerManager.getNextFloorId()
));

}
}
6 changes: 6 additions & 0 deletions src/main/java/emu/grasscutter/game/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.game.shop.ShopLimit;
import emu.grasscutter.game.managers.MapMarkManager.*;
import emu.grasscutter.game.tower.TowerManager;
Expand Down Expand Up @@ -1048,6 +1049,7 @@ public void resetSendPlayerLocTime() {
@PostLoad
private void onLoad() {
this.getTeamManager().setPlayer(this);
this.getTowerManager().setPlayer(this);
}

public void save() {
Expand Down Expand Up @@ -1117,6 +1119,10 @@ public void onLogin() {
}

public void onLogout() {
// force to leave the dungeon
if(getScene().getSceneType() == SceneType.SCENE_DUNGEON){
this.getServer().getDungeonManager().exitDungeon(this);
}
// Leave world
if (this.getWorld() != null) {
this.getWorld().removePlayer(this);
Expand Down
76 changes: 68 additions & 8 deletions src/main/java/emu/grasscutter/game/tower/TowerManager.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,100 @@
package emu.grasscutter.game.tower;

import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Transient;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.TowerLevelData;
import emu.grasscutter.game.dungeons.DungeonSettleListener;
import emu.grasscutter.game.dungeons.TowerDungeonSettleListener;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify;
import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp;

import java.util.List;

@Entity
public class TowerManager {
private final Player player;
@Transient
private Player player;

public TowerManager(Player player) {
this.player = player;
}
public void setPlayer(Player player) {
this.player = player;
}

private int currentFloorId;
private int currentLevel;
private int currentFloor;
@Transient
private int currentLevelId;

@Transient
private int entryScene;

public int getCurrentFloorId() {
return currentFloorId;
}

private static final List<DungeonSettleListener> towerDungeonSettleListener = List.of(new TowerDungeonSettleListener());
public void teamSelect(int floor, List<List<Long>> towerTeams) {
var floorData = GameData.getTowerFloorDataMap().get(floor);

this.currentFloor = floorData.getFloorId();
this.currentLevel = floorData.getLevelId();
this.currentFloorId = floorData.getFloorId();
this.currentLevel = 0;
this.currentLevelId = GameData.getTowerLevelDataMap().values().stream()
.filter(x -> x.getLevelId() == floorData.getLevelId() && x.getLevelIndex() == 1)
.findFirst()
.map(TowerLevelData::getID)
.orElse(0);

if (entryScene == 0){
entryScene = player.getSceneId();
}

player.getTeamManager().setupTemporaryTeam(towerTeams);
}


public void enterLevel(int enterPointId) {
var levelData = GameData.getTowerLevelDataMap().get(currentLevel);
var levelData = GameData.getTowerLevelDataMap().get(currentLevelId + currentLevel);

this.currentLevel++;
var id = levelData.getDungeonId();

notifyCurLevelRecordChange();
// use team user choose
player.getTeamManager().useTemporaryTeam(0);
player.getServer().getDungeonManager()
.enterDungeon(player, enterPointId, id);
player.getServer().getDungeonManager().handoffDungeon(player, id,
towerDungeonSettleListener);

// make sure user can exit dungeon correctly
player.getScene().setPrevScene(entryScene);
player.getScene().setPrevScenePoint(enterPointId);

player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel));

}

public void notifyCurLevelRecordChange(){
player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel));
}
public void notifyCurLevelRecordChangeWhenDone(){
player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel + 1));
}
public boolean hasNextLevel(){
return this.currentLevel < 3;
}

public int getNextFloorId() {
if(hasNextLevel()){
return 0;
}
this.currentFloorId++;
return this.currentFloorId;
}

player.getSession().send(new PacketTowerEnterLevelRsp(currentFloor, currentLevel));
public void clearEntry() {
this.entryScene = 0;
}
}
Loading

0 comments on commit 6144f47

Please sign in to comment.