diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 24b9cbb7e93..2f9f7763be3 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -214,6 +214,14 @@ public final class GameData { private static final Int2ObjectMap cookRecipeDataMap = new Int2ObjectOpenHashMap<>(); + @Getter + private static final Int2ObjectMap coopChapterDataMap = + new Int2ObjectOpenHashMap<>(); + + @Getter + private static final Int2ObjectMap coopPointDataMap = + new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap compoundDataMap = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/emu/grasscutter/data/excels/CoopChapterData.java b/src/main/java/emu/grasscutter/data/excels/CoopChapterData.java new file mode 100644 index 00000000000..ba56218e0a1 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CoopChapterData.java @@ -0,0 +1,45 @@ +package emu.grasscutter.data.excels; + +import com.google.gson.annotations.SerializedName; +import emu.grasscutter.data.*; +import java.util.List; +import lombok.*; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "CoopChapterExcelConfigData.json") +@Getter +@Setter // TODO: remove setters next API break +@FieldDefaults(level = AccessLevel.PRIVATE) +public class CoopChapterData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + int avatarId; +// int chapterNameTextMapHash; +// int coopPageTitleTextMapHash; +// int chapterSortId; +// int avatarSortId; +// String chapterIcon; + List unlockCond; +// int [] unlockCondTips; +// int openMaterialId; +// int openMaterialNum; +// String beginTimeStr; +// int confidenceValue; +// String pointGraphPath; +// Double graphXRatio; +// Double graphYRatio; + + @Data + @FieldDefaults(level = AccessLevel.PRIVATE) + private static class CoopCondition { + @SerializedName( + value = "_condType", + alternate = {"condType"}) + String type = "COOP_COND_NONE"; + + @SerializedName( + value = "_args", + alternate = {"args"}) + int[] args; + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/data/excels/CoopPointData.java b/src/main/java/emu/grasscutter/data/excels/CoopPointData.java new file mode 100644 index 00000000000..5b6dcabb7f2 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CoopPointData.java @@ -0,0 +1,23 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.*; +import lombok.*; +import lombok.experimental.FieldDefaults; + +@ResourceType(name = "CoopPointExcelConfigData.json") +@Getter +@Setter // TODO: remove setters next API break +@FieldDefaults(level = AccessLevel.PRIVATE) +public class CoopPointData extends GameResource { + @Getter(onMethod_ = @Override) + int id; + int chapterId; + String type; + int acceptQuest; + int [] postPointList; +// int pointNameTextMapHash; +// int pointDecTextMapHash; + int pointPosId; +// long photoMaleHash; +// long photoFemaleHash; +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java index 50acd0d9c2b..1352594a6b2 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java @@ -33,12 +33,9 @@ public final class PlayerProgressManager extends BasePlayerDataManager { public static final Set IGNORED_OPEN_STATES = Set.of( - 1404, // OPEN_STATE_MENGDE_INFUSEDCRYSTAL, causes quest 'Mine Craft' to be given to the + 1404 // OPEN_STATE_MENGDE_INFUSEDCRYSTAL, causes quest 'Mine Craft' to be given to the // player at the start of the game. // This should be removed when city reputation is implemented. - 57 // OPEN_STATE_PERSONAL_LINE, causes the prompt for showing character hangout quests to - // be permanently shown. - // This should be removed when character story quests are implemented. ); // Set of open states that are set per default for all accounts. Can be overwritten by an entry in // `map`. diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionMainCoopStart.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionMainCoopStart.java new file mode 100644 index 00000000000..d2eb8e425f3 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionMainCoopStart.java @@ -0,0 +1,21 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.data.excels.quest.QuestData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.QuestValueCond; +import emu.grasscutter.game.quest.enums.QuestCond; + +@QuestValueCond(QuestCond.QUEST_COND_MAIN_COOP_START) +public class ConditionMainCoopStart extends BaseCondition { + + @Override + public boolean execute( + Player owner, + QuestData questData, + QuestData.QuestAcceptCondition condition, + String paramStr, + int... params) { + return condition.getParam()[0] == params[0] + && (condition.getParam()[1] == 0 || condition.getParam()[1] == params[1]); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestCond.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestCond.java index 7b43c442d47..24d8fcf075a 100644 --- a/src/main/java/emu/grasscutter/game/quest/enums/QuestCond.java +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestCond.java @@ -54,7 +54,7 @@ public enum QuestCond implements QuestTrigger { QUEST_COND_QUEST_GLOBAL_VAR_LESS(46), QUEST_COND_PERSONAL_LINE_UNLOCK(47), QUEST_COND_CITY_REPUTATION_REQUEST(48), // missing - QUEST_COND_MAIN_COOP_START(49), // missing + QUEST_COND_MAIN_COOP_START(49), QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), // missing QUEST_COND_CITY_REPUTATION_LEVEL(51), // missing, only NPC groups QUEST_COND_CITY_REPUTATION_UNLOCK(52), // missing, currently unused diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCancelCoopTaskReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCancelCoopTaskReq.java new file mode 100644 index 00000000000..4a19e0cbee6 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCancelCoopTaskReq.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.CancelCoopTaskReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCancelCoopTaskRsp; + +@Opcodes(PacketOpcodes.CancelCoopTaskReq) +public class HandlerCancelCoopTaskReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CancelCoopTaskReqOuterClass.CancelCoopTaskReq req = CancelCoopTaskReqOuterClass.CancelCoopTaskReq.parseFrom(payload); + var chapterId = req.getChapterId(); + Grasscutter.getLogger().warn("Call to unimplemented packet CancelCoopTaskReq"); + // TODO: Actually cancel the quests. + session.send(new PacketCancelCoopTaskRsp(chapterId)); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java index 278bc7b542f..4afbf557319 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalLineAllDataReq.java @@ -2,6 +2,7 @@ import emu.grasscutter.net.packet.*; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCoopDataNotify; import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp; @Opcodes(PacketOpcodes.PersonalLineAllDataReq) @@ -12,5 +13,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex session.send( new PacketPersonalLineAllDataRsp( session.getPlayer().getQuestManager().getMainQuests().values())); + // TODO: this should maybe be at player login? + session.send(new PacketCoopDataNotify()); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerStartCoopPointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerStartCoopPointReq.java new file mode 100644 index 00000000000..45baf014036 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerStartCoopPointReq.java @@ -0,0 +1,26 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.quest.enums.QuestCond; +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.StartCoopPointReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketStartCoopPointRsp; + +@Opcodes(PacketOpcodes.StartCoopPointReq) +public class HandlerStartCoopPointReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + StartCoopPointReqOuterClass.StartCoopPointReq req = StartCoopPointReqOuterClass.StartCoopPointReq.parseFrom(payload); + var coopPoint = req.getCoopPoint(); + + var coopPointData = GameData.getCoopPointDataMap().values().stream().filter(i -> i.getId() == coopPoint).toList(); + if (!coopPointData.isEmpty()) { + var player = session.getPlayer(); + var questManager = player.getQuestManager(); + questManager.queueEvent(QuestCond.QUEST_COND_MAIN_COOP_START, coopPointData.get(0).getChapterId(), 0); + } + session.send(new PacketStartCoopPointRsp(coopPoint)); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCancelCoopTaskRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCancelCoopTaskRsp.java new file mode 100644 index 00000000000..a8e0d9a31b2 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCancelCoopTaskRsp.java @@ -0,0 +1,16 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.CancelCoopTaskRspOuterClass; + +public class PacketCancelCoopTaskRsp extends BasePacket { + + public PacketCancelCoopTaskRsp(int chapterId) { + super(PacketOpcodes.SetCoopChapterViewedRsp); + + CancelCoopTaskRspOuterClass.CancelCoopTaskRsp proto = + CancelCoopTaskRspOuterClass.CancelCoopTaskRsp.newBuilder().setChapterId(chapterId).build(); + + this.setData(proto); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCoopDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCoopDataNotify.java new file mode 100644 index 00000000000..e1823f66b17 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCoopDataNotify.java @@ -0,0 +1,45 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.CoopChapterOuterClass; +import emu.grasscutter.net.proto.CoopDataNotifyOuterClass; +import emu.grasscutter.net.proto.CoopPointOuterClass; + +public class PacketCoopDataNotify extends BasePacket { + + public PacketCoopDataNotify() { + super(PacketOpcodes.CoopDataNotify); + + var proto = CoopDataNotifyOuterClass.CoopDataNotify.newBuilder(); + proto.setIsHaveProgress(false); + + + + // TODO: implement: determine the actual current progress point. + // Add every chapter and add the start point to each chapter regardless of actual progress. + GameData.getCoopChapterDataMap().values().forEach(i -> { + var chapter = CoopChapterOuterClass.CoopChapter.newBuilder(); + chapter.setId(i.getId()); + + // TODO: implement: look at unlockCond to determine what state each chapter should be in. + // Set every chapter to "Accept" regardless of accept conditions. + chapter.setStateValue(3); // 3 == STATE_ACCEPT + + var point = CoopPointOuterClass.CoopPoint.newBuilder(); + var pointList = GameData.getCoopPointDataMap().values().stream() + .filter(j -> j.getChapterId() == i.getId() && j.getType().equals("POINT_START")) + .toList(); + + if (!pointList.isEmpty()) { + int pointId = pointList.get(0).getId(); + point.setId(pointId); + chapter.addCoopPointList(point); + } + + proto.addChapterList(chapter); + }); + + this.setData(proto); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStartCoopPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStartCoopPointRsp.java new file mode 100644 index 00000000000..78429e2757b --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStartCoopPointRsp.java @@ -0,0 +1,16 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.*; +import emu.grasscutter.net.proto.StartCoopPointRspOuterClass; + +public class PacketStartCoopPointRsp extends BasePacket { + + public PacketStartCoopPointRsp(int coopPoint) { + super(PacketOpcodes.StartCoopPointRsp); + + StartCoopPointRspOuterClass.StartCoopPointRsp proto = + StartCoopPointRspOuterClass.StartCoopPointRsp.newBuilder().setCoopPoint(coopPoint).build(); + + this.setData(proto); + } +} \ No newline at end of file