Commit 797afd4c authored by Melledy's avatar Melledy Committed by GitHub
Browse files

Merge pull request #1553 from akatatsu27/questing

Major quest framework improvements
parents 1c5c3633 8bdcfb89
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_GLOBAL_VAR)
public class ExecIncQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getOwner().getQuestManager().incQuestGlobalVarValue(Integer.valueOf(paramStr[0]),Integer.valueOf(paramStr[1]));
return true;
}
}
\ No newline at end of file
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_VAR)
public class ExecIncQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().incQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_GLOBAL_VAR)
public class ExecSetQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getOwner().getQuestManager().setQuestGlobalVarValue(Integer.valueOf(paramStr[0]),Integer.valueOf(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_VAR)
public class ExecSetQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().setQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
...@@ -627,8 +627,14 @@ public class Scene { ...@@ -627,8 +627,14 @@ public class Scene {
.flatMap(Collection::stream) .flatMap(Collection::stream)
.toList(); .toList();
onLoadGroup(groups); onLoadGroup(groups);
Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id); Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id);
}
public void loadTriggerFromGroup(SceneGroup group, String triggerName) {
//Load triggers and regions
getScriptManager().registerTrigger(group.triggers.values().stream().filter(p -> p.name.contains(triggerName)).toList());
group.regions.values().stream().filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13))).map(region -> new EntityRegion(this, region))
.forEach(getScriptManager()::registerRegion);
} }
public void onLoadGroup(List<SceneGroup> groups) { public void onLoadGroup(List<SceneGroup> groups) {
......
...@@ -92,6 +92,7 @@ public class SceneScriptManager { ...@@ -92,6 +92,7 @@ public class SceneScriptManager {
} }
public void registerTrigger(SceneTrigger trigger) { public void registerTrigger(SceneTrigger trigger) {
getTriggersByEvent(trigger.event).add(trigger); getTriggersByEvent(trigger.event).add(trigger);
Grasscutter.getLogger().debug("Registered trigger {}", trigger.name);
} }
public void deregisterTrigger(List<SceneTrigger> triggers) { public void deregisterTrigger(List<SceneTrigger> triggers) {
triggers.forEach(this::deregisterTrigger); triggers.forEach(this::deregisterTrigger);
...@@ -122,6 +123,7 @@ public class SceneScriptManager { ...@@ -122,6 +123,7 @@ public class SceneScriptManager {
public void registerRegion(EntityRegion region) { public void registerRegion(EntityRegion region) {
regions.put(region.getId(), region); regions.put(region.getId(), region);
Grasscutter.getLogger().debug("Registered region {} from group {}", region.getMetaRegion().config_id, region.getGroupId());
} }
public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite){ public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite){
suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region)) suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region))
...@@ -195,9 +197,30 @@ public class SceneScriptManager { ...@@ -195,9 +197,30 @@ public class SceneScriptManager {
.filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition())) .filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition()))
.forEach(region::addEntity); .forEach(region::addEntity);
var players = region.getScene().getPlayers();
int targetID = 0;
if(players.size() > 0)
targetID = players.get(0).getUid();
if (region.hasNewEntities()) { if (region.hasNewEntities()) {
Grasscutter.getLogger().trace("Call EVENT_ENTER_REGION_{}",region.getMetaRegion().config_id);
callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId()) callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId())
.setSourceEntityId(region.getId()) .setSourceEntityId(region.getId())
.setTargetEntityId(targetID)
);
region.resetNewEntities();
}
for(int entityId : region.getEntities()) {
if(!region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) {
region.removeEntity(entityId);
}
}
if (region.entityLeave()) {
callEvent(EventType.EVENT_LEAVE_REGION, new ScriptArgs(region.getConfigId())
.setSourceEntityId(region.getId())
.setTargetEntityId(region.getFirstEntityId()) .setTargetEntityId(region.getFirstEntityId())
); );
...@@ -286,27 +309,41 @@ public class SceneScriptManager { ...@@ -286,27 +309,41 @@ public class SceneScriptManager {
} }
private void realCallEvent(int eventType, ScriptArgs params) { private void realCallEvent(int eventType, ScriptArgs params) {
try{ try {
ScriptLoader.getScriptLib().setSceneScriptManager(this); Set<SceneTrigger> relevantTriggers = new HashSet<>();
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) { if(eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) {
try{ List<SceneTrigger> relevantTriggersList = this.getTriggersByEvent(eventType).stream()
ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup); .filter(p -> p.condition.contains(String.valueOf(params.param1))).toList();
relevantTriggers = new HashSet<>(relevantTriggersList);
LuaValue ret = callScriptFunc(trigger.condition, trigger.currentGroup, params); } else {relevantTriggers = this.getTriggersByEvent(eventType);}
Grasscutter.getLogger().trace("Call Condition Trigger {}", trigger.condition); for (SceneTrigger trigger : relevantTriggers) {
try {
if (ret.isboolean() && ret.checkboolean()) { ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup);
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time LuaValue ret = this.callScriptFunc(trigger.condition, trigger.currentGroup, params);
callScriptFunc(trigger.action, trigger.currentGroup, params); Grasscutter.getLogger().trace("Call Condition Trigger {}, [{},{},{}]", trigger.condition, params.param1, params.source_eid, params.target_eid);
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action); if (ret.isboolean() && ret.checkboolean()) {
} // the SetGroupVariableValueByGroup in tower need the param to record the first stage time
//TODO some ret may not bool this.callScriptFunc(trigger.action, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action);
}finally { if (trigger.event == EventType.EVENT_ENTER_REGION) {
ScriptLoader.getScriptLib().removeCurrentGroup(); EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0);
} getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion()));
} deregisterRegion(region.getMetaRegion());
}finally { } else if (trigger.event == EventType.EVENT_LEAVE_REGION) {
EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0);
getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion()));
deregisterRegion(region.getMetaRegion());
}
deregisterTrigger(trigger);
} else {
Grasscutter.getLogger().debug("Condition Trigger {} returned {}", trigger.condition, ret);
}
//TODO some ret do not bool
}finally {
ScriptLoader.getScriptLib().removeCurrentGroup();
}
}
}finally {
// make sure it is removed // make sure it is removed
ScriptLoader.getScriptLib().removeSceneScriptManager(); ScriptLoader.getScriptLib().removeSceneScriptManager();
} }
......
...@@ -26,7 +26,8 @@ public class SceneRegion { ...@@ -26,7 +26,8 @@ public class SceneRegion {
var x = Math.pow(pos.getX() - position.getX(), 2); var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 2); var y = Math.pow(pos.getY() - position.getY(), 2);
var z = Math.pow(pos.getZ() - position.getZ(), 2); var z = Math.pow(pos.getZ() - position.getZ(), 2);
return x + y + z <= (radius ^ 2); // ^ means XOR in java!
return x + y + z <= (radius*radius);
} }
return false; return false;
} }
......
...@@ -29,22 +29,70 @@ public class LuaSerializer implements Serializer { ...@@ -29,22 +29,70 @@ public class LuaSerializer implements Serializer {
public <T> T toObject(Class<T> type, Object obj) { public <T> T toObject(Class<T> type, Object obj) {
return serialize(type, (LuaTable) obj); return serialize(type, (LuaTable) obj);
} }
public <T> List<T> serializeList(Class<T> type, LuaTable table) { @Override
public <T> Map<String, T> toMap(Class<T> type, Object obj) {
return serializeMap(type, (LuaTable) obj);
}
private <T> Map<String,T> serializeMap(Class<T> type, LuaTable table) {
Map<String,T> map = new HashMap<>();
if (table == null) {
return map;
}
try {
LuaValue[] keys = table.keys();
for (LuaValue k : keys) {
try {
LuaValue keyValue = table.get(k);
T object = null;
if (keyValue.istable()) {
object = serialize(type, keyValue.checktable());
} else if (keyValue.isint()) {
object = (T) (Integer) keyValue.toint();
} else if (keyValue.isnumber()) {
object = (T) (Float) keyValue.tofloat(); // terrible...
} else if (keyValue.isstring()) {
object = (T) keyValue.tojstring();
} else if (keyValue.isboolean()) {
object = (T) (Boolean) keyValue.toboolean();
} else {
object = (T) keyValue;
}
if (object != null) {
map.put(String.valueOf(k),object);
}
} catch (Exception ex) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
public <T> List<T> serializeList(Class<T> type, LuaTable table) {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
if (table == null) { if (table == null) {
return list; return list;
} }
try { try {
LuaValue[] keys = table.keys(); LuaValue[] keys = table.keys();
for (LuaValue k : keys) { for (LuaValue k : keys) {
try { try {
LuaValue keyValue = table.get(k); LuaValue keyValue = table.get(k);
T object = null; T object = null;
if (keyValue.istable()) { if (keyValue.istable()) {
object = serialize(type, keyValue.checktable()); object = serialize(type, keyValue.checktable());
} else if (keyValue.isint()) { } else if (keyValue.isint()) {
...@@ -75,7 +123,7 @@ public class LuaSerializer implements Serializer { ...@@ -75,7 +123,7 @@ public class LuaSerializer implements Serializer {
public <T> T serialize(Class<T> type, LuaTable table) { public <T> T serialize(Class<T> type, LuaTable table) {
T object = null; T object = null;
if (type == List.class) { if (type == List.class) {
try { try {
Class<T> listType = (Class<T>) type.getTypeParameters()[0].getClass(); Class<T> listType = (Class<T>) type.getTypeParameters()[0].getClass();
...@@ -85,7 +133,7 @@ public class LuaSerializer implements Serializer { ...@@ -85,7 +133,7 @@ public class LuaSerializer implements Serializer {
return null; return null;
} }
} }
try { try {
if (!methodAccessCache.containsKey(type)) { if (!methodAccessCache.containsKey(type)) {
cacheType(type); cacheType(type);
...@@ -98,7 +146,7 @@ public class LuaSerializer implements Serializer { ...@@ -98,7 +146,7 @@ public class LuaSerializer implements Serializer {
if (table == null) { if (table == null) {
return object; return object;
} }
LuaValue[] keys = table.keys(); LuaValue[] keys = table.keys();
for (LuaValue k : keys) { for (LuaValue k : keys) {
try { try {
...@@ -131,7 +179,7 @@ public class LuaSerializer implements Serializer { ...@@ -131,7 +179,7 @@ public class LuaSerializer implements Serializer {
Grasscutter.getLogger().info(ScriptUtils.toMap(table).toString()); Grasscutter.getLogger().info(ScriptUtils.toMap(table).toString());
e.printStackTrace(); e.printStackTrace();
} }
return object; return object;
} }
......
package emu.grasscutter.scripts.serializer; package emu.grasscutter.scripts.serializer;
import java.util.List; import java.util.List;
import java.util.Map;
import org.luaj.vm2.LuaTable;
public interface Serializer { public interface Serializer {
public <T> List<T> toList(Class<T> type, Object obj); public <T> List<T> toList(Class<T> type, Object obj);
public <T> T toObject(Class<T> type, Object obj); public <T> T toObject(Class<T> type, Object obj);
public <T> Map<String,T> toMap(Class<T> type, Object obj);
} }
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
...@@ -7,6 +10,9 @@ import emu.grasscutter.net.packet.PacketOpcodes; ...@@ -7,6 +10,9 @@ import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass; import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp; import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import java.util.List;
import java.util.stream.Stream;
@Opcodes(PacketOpcodes.AddQuestContentProgressReq) @Opcodes(PacketOpcodes.AddQuestContentProgressReq)
public class HandlerAddQuestContentProgressReq extends PacketHandler { public class HandlerAddQuestContentProgressReq extends PacketHandler {
...@@ -14,9 +20,14 @@ public class HandlerAddQuestContentProgressReq extends PacketHandler { ...@@ -14,9 +20,14 @@ public class HandlerAddQuestContentProgressReq 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 {
var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload); var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload);
//Find all conditions in quest that are the same as the given one
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), req.getParam()); Stream<QuestCondition> finishCond = GameData.getQuestDataMap().get(req.getParam()).getFinishCond().stream();
Stream<QuestCondition> acceptCond = GameData.getQuestDataMap().get(req.getParam()).getAcceptCond().stream();
Stream<QuestCondition> failCond = GameData.getQuestDataMap().get(req.getParam()).getFailCond().stream();
List<QuestCondition> allCondMatch = Stream.concat(Stream.concat(acceptCond,failCond),finishCond).filter(p -> p.getType().getValue() == req.getContentType()).toList();
for(QuestCondition cond : allCondMatch ) {
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), cond.getParam());
}
session.send(new PacketAddQuestContentProgressRsp(req.getContentType())); session.send(new PacketAddQuestContentProgressRsp(req.getContentType()));
} }
......
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.player.Player.SceneLoadState; import emu.grasscutter.game.player.Player.SceneLoadState;
import emu.grasscutter.game.quest.QuestGroupSuite;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
...@@ -16,7 +18,7 @@ public class HandlerEnterSceneDoneReq extends PacketHandler { ...@@ -16,7 +18,7 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
session.getPlayer().setSceneLoadState(SceneLoadState.LOADED); session.getPlayer().setSceneLoadState(SceneLoadState.LOADED);
// Done // Done
session.send(new PacketEnterSceneDoneRsp(session.getPlayer()));
session.send(new PacketPlayerTimeNotify(session.getPlayer())); // Probably not the right place session.send(new PacketPlayerTimeNotify(session.getPlayer())); // Probably not the right place
// Spawn player in world // Spawn player in world
...@@ -35,11 +37,15 @@ public class HandlerEnterSceneDoneReq extends PacketHandler { ...@@ -35,11 +37,15 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
// notify client to load the npc for quest // notify client to load the npc for quest
var questGroupSuites = session.getPlayer().getQuestManager().getSceneGroupSuite(session.getPlayer().getSceneId()); var questGroupSuites = session.getPlayer().getQuestManager().getSceneGroupSuite(session.getPlayer().getSceneId());
session.getPlayer().getScene().loadGroupForQuest(questGroupSuites); session.getPlayer().getScene().loadGroupForQuest(questGroupSuites);
Grasscutter.getLogger().debug("Loaded Scene {} Quest(s) Groupsuite(s): {}", session.getPlayer().getSceneId(), questGroupSuites);
session.send(new PacketGroupSuiteNotify(questGroupSuites)); session.send(new PacketGroupSuiteNotify(questGroupSuites));
// Reset timer for sending player locations // Reset timer for sending player locations
session.getPlayer().resetSendPlayerLocTime(); session.getPlayer().resetSendPlayerLocTime();
//Rsp
session.send(new PacketEnterSceneDoneRsp(session.getPlayer()));
} }
} }
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.enums.ParentQuestState;
import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
...@@ -11,16 +15,28 @@ import emu.grasscutter.server.packet.send.PacketNpcTalkRsp; ...@@ -11,16 +15,28 @@ import emu.grasscutter.server.packet.send.PacketNpcTalkRsp;
@Opcodes(PacketOpcodes.NpcTalkReq) @Opcodes(PacketOpcodes.NpcTalkReq)
public class HandlerNpcTalkReq extends PacketHandler { public class HandlerNpcTalkReq 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 {
NpcTalkReq req = NpcTalkReq.parseFrom(payload); NpcTalkReq req = NpcTalkReq.parseFrom(payload);
//Check if mainQuest exists
// Why are there 2 quest triggers that do the same thing... int talkId = req.getTalkId();
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId()); //remove last 2 digits to get a mainQuestId
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_FINISH_PLOT, req.getTalkId()); int mainQuestId = talkId/100;
MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(mainQuestId);
if(mainQuestData != null) {
MainQuestData.TalkData talk = mainQuestData.getTalks().stream().filter(p -> p.getId() == talkId).toList().get(0);
if(talk != null) {
//talk is finished
session.getPlayer().getQuestManager().getMainQuestById(mainQuestId).getTalks().put(Integer.valueOf(talkId),talk);
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_ANY_TALK,String.valueOf(req.getTalkId()), 0, 0);
// Why are there 2 quest triggers that do the same thing...
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId(),0);
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_FINISH_PLOT, req.getTalkId(),0);
}
}
session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId()));
} }
} }
\ No newline at end of file
...@@ -11,7 +11,7 @@ public class HandlerPersonalLineAllDataReq extends PacketHandler { ...@@ -11,7 +11,7 @@ public class HandlerPersonalLineAllDataReq 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 {
session.send(new PacketPersonalLineAllDataRsp(session.getPlayer().getQuestManager().getQuests().values())); session.send(new PacketPersonalLineAllDataRsp(session.getPlayer().getQuestManager().getMainQuests().values()));
} }
} }
...@@ -14,7 +14,7 @@ public class HandlerPostEnterSceneReq extends PacketHandler { ...@@ -14,7 +14,7 @@ public class HandlerPostEnterSceneReq 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 {
if(session.getPlayer().getScene().getSceneType() == SceneType.SCENE_ROOM){ if(session.getPlayer().getScene().getSceneType() == SceneType.SCENE_ROOM){
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_ROOM, session.getPlayer().getSceneId()); session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_ROOM, session.getPlayer().getSceneId(),0);
} }
session.send(new PacketPostEnterSceneRsp(session.getPlayer())); session.send(new PacketPostEnterSceneRsp(session.getPlayer()));
......
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PacketHeadOuterClass;
import emu.grasscutter.net.proto.PlayerSetPauseReqOuterClass;
import emu.grasscutter.net.proto.QuestUpdateQuestVarReqOuterClass;
import emu.grasscutter.net.proto.QuestVarOpOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketPlayerSetPauseRsp;
import emu.grasscutter.server.packet.send.PacketQuestUpdateQuestVarRsp;
import java.util.List;
@Opcodes(PacketOpcodes.QuestUpdateQuestVarReq)
public class HandlerQuestUpdateQuestVarReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
//Client sends packets. One with the value, and one with the index and the new value to set/inc/dec
var req = QuestUpdateQuestVarReqOuterClass.QuestUpdateQuestVarReq.parseFrom(payload);
GameMainQuest mainQuest = session.getPlayer().getQuestManager().getMainQuestById(req.getQuestId()/100);
List<QuestVarOpOuterClass.QuestVarOp> questVars = req.getQuestVarOpListList();
if (mainQuest.getQuestVarsUpdate().size() == 0) {
for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) {
mainQuest.getQuestVarsUpdate().add(questVar.getValue());
}
} else {
for (QuestVarOpOuterClass.QuestVarOp questVar : questVars) {
if (questVar.getIsAdd()) {
if (questVar.getValue() >= 0) {
mainQuest.incQuestVar(questVar.getIndex(), questVar.getValue());
} else {
mainQuest.decQuestVar(questVar.getIndex(), questVar.getValue());
}
} else {
mainQuest.setQuestVar(questVar.getIndex(), mainQuest.getQuestVarsUpdate().get(0));
}
//remove the first element from the update list
mainQuest.getQuestVarsUpdate().remove(0);
}
}
session.send(new PacketQuestUpdateQuestVarRsp(req.getQuestId()));
}
}
...@@ -2,21 +2,25 @@ package emu.grasscutter.server.packet.send; ...@@ -2,21 +2,25 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameMainQuest; import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.enums.ParentQuestState;
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.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify; import emu.grasscutter.net.proto.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify;
public class PacketFinishedParentQuestNotify extends BasePacket { public class PacketFinishedParentQuestNotify extends BasePacket {
public PacketFinishedParentQuestNotify(Player player) { public PacketFinishedParentQuestNotify(Player player) {
super(PacketOpcodes.FinishedParentQuestNotify, true); super(PacketOpcodes.FinishedParentQuestNotify, true);
FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder(); FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder();
for (GameMainQuest mainQuest : player.getQuestManager().getQuests().values()) { for (GameMainQuest mainQuest : player.getQuestManager().getMainQuests().values()) {
proto.addParentQuestList(mainQuest.toProto()); //Canceled Quests do not appear in this packet
if(mainQuest.getState() != ParentQuestState.PARENT_QUEST_STATE_CANCELED) {
proto.addParentQuestList(mainQuest.toProto());
}
} }
this.setData(proto); this.setData(proto);
} }
} }
...@@ -5,15 +5,29 @@ import emu.grasscutter.net.packet.BasePacket; ...@@ -5,15 +5,29 @@ import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify;
import java.util.List;
public class PacketFinishedParentQuestUpdateNotify extends BasePacket { public class PacketFinishedParentQuestUpdateNotify extends BasePacket {
public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) {
super(PacketOpcodes.FinishedParentQuestUpdateNotify); super(PacketOpcodes.FinishedParentQuestUpdateNotify);
FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder() FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder()
.addParentQuestList(quest.toProto()) .addParentQuestList(quest.toProto())
.build(); .build();
this.setData(proto); this.setData(proto);
} }
public PacketFinishedParentQuestUpdateNotify(List<GameMainQuest> quests) {
super(PacketOpcodes.FinishedParentQuestUpdateNotify);
var proto = FinishedParentQuestUpdateNotify.newBuilder();
for(GameMainQuest mainQuest : quests) {
proto.addParentQuestList(mainQuest.toProto());
}
proto.build();
this.setData(proto);
}
} }
...@@ -23,7 +23,7 @@ public class PacketPersonalLineAllDataRsp extends BasePacket { ...@@ -23,7 +23,7 @@ public class PacketPersonalLineAllDataRsp extends BasePacket {
.map(GameMainQuest::getChildQuests) .map(GameMainQuest::getChildQuests)
.map(Map::values) .map(Map::values)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.map(GameQuest::getQuestId) .map(GameQuest::getSubQuestId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
GameData.getPersonalLineDataMap().values().stream() GameData.getPersonalLineDataMap().values().stream()
......
...@@ -3,21 +3,24 @@ package emu.grasscutter.server.packet.send; ...@@ -3,21 +3,24 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameMainQuest; import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.quest.QuestManager; import emu.grasscutter.game.quest.QuestManager;
import emu.grasscutter.game.quest.enums.QuestState;
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.QuestListNotifyOuterClass.QuestListNotify; import emu.grasscutter.net.proto.QuestListNotifyOuterClass.QuestListNotify;
public class PacketQuestListNotify extends BasePacket { public class PacketQuestListNotify extends BasePacket {
public PacketQuestListNotify(Player player) { public PacketQuestListNotify(Player player) {
super(PacketOpcodes.QuestListNotify, true); super(PacketOpcodes.QuestListNotify, true);
QuestListNotify.Builder proto = QuestListNotify.newBuilder(); QuestListNotify.Builder proto = QuestListNotify.newBuilder();
player.getQuestManager().forEachQuest(quest -> { player.getQuestManager().forEachQuest(quest -> {
proto.addQuestList(quest.toProto()); if(quest.getState() != QuestState.QUEST_STATE_UNSTARTED) {
proto.addQuestList(quest.toProto());
}
}); });
this.setData(proto); this.setData(proto);
} }
} }
...@@ -6,15 +6,28 @@ import emu.grasscutter.net.packet.BasePacket; ...@@ -6,15 +6,28 @@ import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify; import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify;
import java.util.List;
public class PacketQuestListUpdateNotify extends BasePacket { public class PacketQuestListUpdateNotify extends BasePacket {
public PacketQuestListUpdateNotify(GameQuest quest) { public PacketQuestListUpdateNotify(GameQuest quest) {
super(PacketOpcodes.QuestListUpdateNotify); super(PacketOpcodes.QuestListUpdateNotify);
QuestListUpdateNotify proto = QuestListUpdateNotify.newBuilder() QuestListUpdateNotify proto = QuestListUpdateNotify.newBuilder()
.addQuestList(quest.toProto()) .addQuestList(quest.toProto())
.build(); .build();
this.setData(proto); this.setData(proto);
} }
public PacketQuestListUpdateNotify(List<GameQuest> quests) {
super(PacketOpcodes.QuestListUpdateNotify);
var proto = QuestListUpdateNotify.newBuilder();
for(GameQuest quest : quests) {
proto.addQuestList(quest.toProto());
}
proto.build();
this.setData(proto);
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment