Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tower Dungeons Handoff between levels #594

Merged
10 commits merged into from
May 6, 2022
Prev Previous commit
Next Next commit
Tower Dungeons Handoff between level and floor
  • Loading branch information
Akka0 committed May 6, 2022
commit 6144f4712789c35d357daae7003cf3609cb760f6
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