Show available story dungeons to the player

This commit is contained in:
KingRainbow44 2023-04-12 02:01:22 -04:00
parent b0ab0c68ad
commit 0de69cd1fa
No known key found for this signature in database
GPG Key ID: FC2CB64B00D257BE
6 changed files with 157 additions and 62 deletions

View File

@ -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) { if (entry == null) {
// Error // An invalid point ID was sent.
player.sendPacket(new PacketDungeonEntryInfoRsp()); player.sendPacket(new PacketDungeonEntryInfoRsp());
return; 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( public boolean triggerCondition(

View File

@ -21,8 +21,11 @@ import emu.grasscutter.server.packet.send.PacketDelQuestNotify;
import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.script.Bindings; import javax.script.Bindings;
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.val; import lombok.val;
@ -281,6 +284,26 @@ public class GameQuest {
return true; 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() { public void save() {
getMainQuest().save(); getMainQuest().save();
} }

View File

@ -3,6 +3,7 @@ package emu.grasscutter.game.quest;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData; import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.binout.ScenePointEntry;
import emu.grasscutter.data.excels.QuestData; import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.BasePlayerManager; import emu.grasscutter.game.player.BasePlayerManager;
@ -13,6 +14,7 @@ import emu.grasscutter.utils.Position;
import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.concurrent.FastThreadLocalThread;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntIntImmutablePair;
import lombok.Getter; import lombok.Getter;
import lombok.val; import lombok.val;
@ -443,4 +445,35 @@ public class QuestManager extends BasePlayerManager {
public List<GameMainQuest> getActiveMainQuests() { public List<GameMainQuest> getActiveMainQuests() {
return getMainQuests().values().stream().filter(p -> !p.isFinished()).toList(); 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();
}
} }

View File

@ -105,11 +105,11 @@ public class ScriptLib {
configId,gadgetState); configId,gadgetState);
GameEntity entity = getSceneScriptManager().getScene().getEntityByConfigId(configId); GameEntity entity = getSceneScriptManager().getScene().getEntityByConfigId(configId);
if (!(entity instanceof EntityGadget)) { if (!(entity instanceof EntityGadget gadget)) {
return 1; return 1;
} }
((EntityGadget) entity).updateState(gadgetState); gadget.updateState(gadgetState);
return 0; return 0;
} }
@ -118,10 +118,10 @@ public class ScriptLib {
groupId,configId,gadgetState); groupId,configId,gadgetState);
val entity = getSceneScriptManager().getScene().getEntityByConfigId(configId, groupId); val entity = getSceneScriptManager().getScene().getEntityByConfigId(configId, groupId);
if(!(entity instanceof EntityGadget)){ if(!(entity instanceof EntityGadget gadget)){
return -1; return -1;
} }
((EntityGadget) entity).updateState(gadgetState); gadget.updateState(gadgetState);
return 0; return 0;
} }

View File

@ -13,6 +13,6 @@ public class HandlerDungeonEntryInfoReq extends PacketHandler {
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().sendEntryInfoFor(session.getPlayer(), req.getPointId());
} }
} }

View File

@ -1,15 +1,17 @@
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.data.common.PointData; import emu.grasscutter.data.common.PointData;
import emu.grasscutter.game.player.Player;
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.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo; import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo;
import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp; import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp;
import java.util.Arrays;
import java.util.List;
public class PacketDungeonEntryInfoRsp extends BasePacket { public class PacketDungeonEntryInfoRsp extends BasePacket {
public PacketDungeonEntryInfoRsp(Player player, PointData pointData) { public PacketDungeonEntryInfoRsp(PointData pointData) {
super(PacketOpcodes.DungeonEntryInfoRsp); super(PacketOpcodes.DungeonEntryInfoRsp);
DungeonEntryInfoRsp.Builder proto = DungeonEntryInfoRsp.Builder proto =
@ -25,6 +27,32 @@ public class PacketDungeonEntryInfoRsp extends BasePacket {
this.setData(proto); 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() { public PacketDungeonEntryInfoRsp() {
super(PacketOpcodes.DungeonEntryInfoRsp); super(PacketOpcodes.DungeonEntryInfoRsp);