mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-10 18:33:20 +08:00
Show available story dungeons to the player
This commit is contained in:
parent
b0ab0c68ad
commit
0de69cd1fa
@ -61,16 +61,27 @@ public class DungeonSystem extends BaseGameSystem {
|
||||
}
|
||||
}
|
||||
|
||||
public void getEntryInfo(Player player, int pointId) {
|
||||
ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId);
|
||||
|
||||
/**
|
||||
* Sends the entry info for the given dungeon point to the player.
|
||||
*
|
||||
* @param player The player to send the entry info to.
|
||||
* @param pointId The dungeon point ID.
|
||||
*/
|
||||
public void sendEntryInfoFor(Player player, int pointId) {
|
||||
var entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId);
|
||||
if (entry == null) {
|
||||
// Error
|
||||
// An invalid point ID was sent.
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp());
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
|
||||
// Check if the player has quests with dungeon IDs.
|
||||
var questDungeons = player.getQuestManager().questsForDungeon(entry);
|
||||
if (questDungeons.size() > 0) {
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp(entry.getPointData(), questDungeons));
|
||||
} else {
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp(entry.getPointData()));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean triggerCondition(
|
||||
|
@ -21,8 +21,11 @@ import emu.grasscutter.server.packet.send.PacketDelQuestNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.script.Bindings;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
@ -281,6 +284,26 @@ public class GameQuest {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A list of dungeon IDs associated with the quest's 'QUEST_CONTENT_ENTER_DUNGEON' triggers.
|
||||
* The first element of the pair is the dungeon ID.
|
||||
* The second element of the pair is the dungeon's scene point.
|
||||
*/
|
||||
public List<IntIntImmutablePair> getDungeonIds() {
|
||||
var conditions = this.getQuestData().getFinishCond().stream()
|
||||
.filter(cond -> cond.getType() == QuestContent.QUEST_CONTENT_ENTER_DUNGEON)
|
||||
.toList();
|
||||
|
||||
return conditions.stream()
|
||||
.map(condition -> {
|
||||
var params = condition.getParam();
|
||||
// The first parameter is the ID of the dungeon.
|
||||
// The second parameter is the dungeon entry's scene point.
|
||||
// ex. [1, 1] = dungeon ID 1, scene point 1 or 'KaeyaDungeon'.
|
||||
return new IntIntImmutablePair(params[0], params[1]);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
getMainQuest().save();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package emu.grasscutter.game.quest;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.MainQuestData;
|
||||
import emu.grasscutter.data.binout.ScenePointEntry;
|
||||
import emu.grasscutter.data.excels.QuestData;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.BasePlayerManager;
|
||||
@ -13,6 +14,7 @@ import emu.grasscutter.utils.Position;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
|
||||
@ -443,4 +445,35 @@ public class QuestManager extends BasePlayerManager {
|
||||
public List<GameMainQuest> getActiveMainQuests() {
|
||||
return getMainQuests().values().stream().filter(p -> !p.isFinished()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches dungeon IDs for quests which have a dungeon.
|
||||
*
|
||||
* @param point The associated scene point of the dungeon.
|
||||
* @return A list of dungeon IDs, or an empty list if none are found.
|
||||
*/
|
||||
public List<Integer> questsForDungeon(ScenePointEntry point) {
|
||||
var pointId = point.getPointData().getId();
|
||||
// Get the active quests.
|
||||
return this.getActiveMainQuests().stream()
|
||||
// Get the sub-quests of the main quest.
|
||||
.map(GameMainQuest::getChildQuests)
|
||||
// Get the values of the sub-quests map.
|
||||
.map(Map::values)
|
||||
.map(quests -> quests.stream()
|
||||
// Get the dungeon IDs of each quest.
|
||||
.map(GameQuest::getDungeonIds)
|
||||
.map(ids -> ids.stream()
|
||||
// Find entry points which match this dungeon.
|
||||
.filter(id -> id.rightInt() == pointId)
|
||||
.toList())
|
||||
.map(ids -> ids.stream()
|
||||
// Of the remaining dungeons, find the ID of the quest dungeon.
|
||||
.map(IntIntImmutablePair::leftInt)
|
||||
.toList())
|
||||
.flatMap(Collection::stream)
|
||||
.toList())
|
||||
.flatMap(Collection::stream)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
@ -105,11 +105,11 @@ public class ScriptLib {
|
||||
configId,gadgetState);
|
||||
GameEntity entity = getSceneScriptManager().getScene().getEntityByConfigId(configId);
|
||||
|
||||
if (!(entity instanceof EntityGadget)) {
|
||||
if (!(entity instanceof EntityGadget gadget)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
((EntityGadget) entity).updateState(gadgetState);
|
||||
gadget.updateState(gadgetState);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -118,10 +118,10 @@ public class ScriptLib {
|
||||
groupId,configId,gadgetState);
|
||||
|
||||
val entity = getSceneScriptManager().getScene().getEntityByConfigId(configId, groupId);
|
||||
if(!(entity instanceof EntityGadget)){
|
||||
if(!(entity instanceof EntityGadget gadget)){
|
||||
return -1;
|
||||
}
|
||||
((EntityGadget) entity).updateState(gadgetState);
|
||||
gadget.updateState(gadgetState);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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.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().sendEntryInfoFor(session.getPlayer(), req.getPointId());
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,63 @@
|
||||
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.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo;
|
||||
import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PacketDungeonEntryInfoRsp extends BasePacket {
|
||||
|
||||
public PacketDungeonEntryInfoRsp(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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in conjunction with quest-related dungeons.
|
||||
*
|
||||
* @param pointData The data associated with the dungeon.
|
||||
* @param additional A collection of additional quest-related dungeon IDs.
|
||||
*/
|
||||
public PacketDungeonEntryInfoRsp(PointData pointData, List<Integer> additional) {
|
||||
super(PacketOpcodes.DungeonEntryInfoRsp);
|
||||
|
||||
var packet = DungeonEntryInfoRsp.newBuilder()
|
||||
.setPointId(pointData.getId());
|
||||
|
||||
// Add dungeon IDs from the point data.
|
||||
if (pointData.getDungeonIds() != null) {
|
||||
Arrays.stream(pointData.getDungeonIds())
|
||||
.forEach(id -> packet.addDungeonEntryList(
|
||||
DungeonEntryInfo.newBuilder().setDungeonId(id)));
|
||||
}
|
||||
|
||||
// Add additional dungeon IDs.
|
||||
additional.forEach(id -> packet.addDungeonEntryList(
|
||||
DungeonEntryInfo.newBuilder().setDungeonId(id)));
|
||||
|
||||
this.setData(packet);
|
||||
}
|
||||
|
||||
public PacketDungeonEntryInfoRsp() {
|
||||
super(PacketOpcodes.DungeonEntryInfoRsp);
|
||||
|
||||
DungeonEntryInfoRsp proto = DungeonEntryInfoRsp.newBuilder().setRetcode(1).build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user