From f618486ced526844a5b5f0137a7ddb55ff3aaaa5 Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:39:12 -0700 Subject: [PATCH] Implement story --- src/main/java/emu/nebula/data/GameData.java | 1 + .../emu/nebula/data/resources/StoryDef.java | 34 +++++++++++++ .../data/resources/StorySetSectionDef.java | 27 ++++++++++ .../emu/nebula/game/inventory/ItemParam.java | 5 ++ .../nebula/game/inventory/ItemParamMap.java | 12 ++++- .../java/emu/nebula/game/player/Player.java | 21 +++++++- .../emu/nebula/game/story/StoryManager.java | 50 +++++++++++++++++++ .../handlers/HandlerActivityDetailReq.java | 3 ++ .../server/handlers/HandlerStoryApplyReq.java | 16 ++++++ .../handlers/HandlerStorySetInfoReq.java | 28 +++++++++++ .../handlers/HandlerStorySettleReq.java | 32 ++++++++++++ 11 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 src/main/java/emu/nebula/data/resources/StoryDef.java create mode 100644 src/main/java/emu/nebula/data/resources/StorySetSectionDef.java create mode 100644 src/main/java/emu/nebula/server/handlers/HandlerStoryApplyReq.java create mode 100644 src/main/java/emu/nebula/server/handlers/HandlerStorySetInfoReq.java create mode 100644 src/main/java/emu/nebula/server/handlers/HandlerStorySettleReq.java diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index 10448fb..5628303 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -39,6 +39,7 @@ public class GameData { @Getter private static DataTable WorldClassDataTable = new DataTable<>(); @Getter private static DataTable GuideGroupDataTable = new DataTable<>(); + @Getter private static DataTable StoryDataTable = new DataTable<>(); @Getter private static DataTable StarTowerDataTable = new DataTable<>(); @Getter private static DataTable StarTowerStageDataTable = new DataTable<>(); diff --git a/src/main/java/emu/nebula/data/resources/StoryDef.java b/src/main/java/emu/nebula/data/resources/StoryDef.java new file mode 100644 index 0000000..ab7f06b --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/StoryDef.java @@ -0,0 +1,34 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.ResourceType; +import emu.nebula.game.inventory.ItemParam; +import emu.nebula.game.inventory.ItemParamMap; +import emu.nebula.util.JsonUtils; +import lombok.Getter; + +@Getter +@ResourceType(name = "Story.json") +public class StoryDef extends BaseDef { + private int Id; + private int Chapter; + private String RewardDisplay; + + private transient ItemParamMap rewards; + + @Override + public int getId() { + return Id; + } + + @Override + public void onLoad() { + var list = JsonUtils.decodeList(this.getRewardDisplay(), ItemParam.class); + + if (list != null) { + rewards = ItemParamMap.fromItemParams(list); + } else { + rewards = new ItemParamMap(); + } + } +} diff --git a/src/main/java/emu/nebula/data/resources/StorySetSectionDef.java b/src/main/java/emu/nebula/data/resources/StorySetSectionDef.java new file mode 100644 index 0000000..acdd6c2 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/StorySetSectionDef.java @@ -0,0 +1,27 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.ResourceType; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import lombok.Getter; + +@Getter +@ResourceType(name = "StorySetSection.json") +public class StorySetSectionDef extends BaseDef { + private int Id; + private int ChapterId; + + @Getter + private static IntSet chapterIds = new IntOpenHashSet(); + + @Override + public int getId() { + return Id; + } + + @Override + public void onLoad() { + chapterIds.add(this.getChapterId()); + } +} diff --git a/src/main/java/emu/nebula/game/inventory/ItemParam.java b/src/main/java/emu/nebula/game/inventory/ItemParam.java index 63c9783..2636dfd 100644 --- a/src/main/java/emu/nebula/game/inventory/ItemParam.java +++ b/src/main/java/emu/nebula/game/inventory/ItemParam.java @@ -1,5 +1,7 @@ package emu.nebula.game.inventory; +import com.google.gson.annotations.SerializedName; + import dev.morphia.annotations.Entity; import emu.nebula.proto.Public.ItemTpl; import lombok.Getter; @@ -7,7 +9,10 @@ import lombok.Getter; @Getter @Entity(useDiscriminator = false) public class ItemParam { + @SerializedName("Tid") public int id; + + @SerializedName("Qty") public int count; @Deprecated // Morphia only diff --git a/src/main/java/emu/nebula/game/inventory/ItemParamMap.java b/src/main/java/emu/nebula/game/inventory/ItemParamMap.java index caca6be..ac3d0fd 100644 --- a/src/main/java/emu/nebula/game/inventory/ItemParamMap.java +++ b/src/main/java/emu/nebula/game/inventory/ItemParamMap.java @@ -76,7 +76,7 @@ public class ItemParamMap extends Int2IntOpenHashMap { .map(e -> ItemTpl.newInstance().setTid(e.getIntKey()).setQty(e.getIntValue())); } - // Proto + // Helpers public static ItemParamMap fromTemplates(RepeatedMessage items) { var map = new ItemParamMap(); @@ -97,4 +97,14 @@ public class ItemParamMap extends Int2IntOpenHashMap { return map; } + + public static ItemParamMap fromItemParams(List items) { + var map = new ItemParamMap(); + + for (var template : items) { + map.add(template.getId(), template.getCount()); + } + + return map; + } } diff --git a/src/main/java/emu/nebula/game/player/Player.java b/src/main/java/emu/nebula/game/player/Player.java index c20878e..f80d15f 100644 --- a/src/main/java/emu/nebula/game/player/Player.java +++ b/src/main/java/emu/nebula/game/player/Player.java @@ -16,11 +16,13 @@ import emu.nebula.game.character.CharacterStorage; import emu.nebula.game.formation.FormationManager; import emu.nebula.game.inventory.Inventory; import emu.nebula.game.mail.Mailbox; +import emu.nebula.game.story.StoryManager; import emu.nebula.game.tower.StarTowerManager; import emu.nebula.net.GameSession; import emu.nebula.proto.PlayerData.PlayerInfo; import emu.nebula.proto.Public.NewbieInfo; import emu.nebula.proto.Public.QuestType; +import emu.nebula.proto.Public.Story; import emu.nebula.proto.Public.WorldClass; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; @@ -62,6 +64,7 @@ public class Player implements GameDatabaseObject { private transient FormationManager formations; private transient Mailbox mailbox; private transient StarTowerManager starTowerManager; + private transient StoryManager storyManager; @Deprecated // Morphia only public Player() { @@ -257,6 +260,13 @@ public class Player implements GameDatabaseObject { } else { this.starTowerManager.setPlayer(this); } + + this.storyManager = Nebula.getGameDatabase().getObjectByField(StoryManager.class, "_id", this.getUid()); + if (this.storyManager == null) { + this.storyManager = new StoryManager(this); + } else { + this.storyManager.setPlayer(this); + } } // Proto @@ -337,6 +347,16 @@ public class Player implements GameDatabaseObject { } acc.addNewbies(NewbieInfo.newInstance().setGroupId(GameConstants.INTRO_GUIDE_ID).setStepId(-1)); + + // Story + var story = proto.getMutableStory(); + + for (int storyId : this.getStoryManager().getCompletedStories()) { + var storyProto = Story.newInstance() + .setIdx(storyId); + + story.addStories(storyProto); + } // proto.addBoard(410301); @@ -351,7 +371,6 @@ public class Player implements GameDatabaseObject { proto.getMutableQuests(); proto.getMutableAgent(); proto.getMutablePhone(); - proto.getMutableStory(); return proto; } diff --git a/src/main/java/emu/nebula/game/story/StoryManager.java b/src/main/java/emu/nebula/game/story/StoryManager.java index 8553f8b..33049ab 100644 --- a/src/main/java/emu/nebula/game/story/StoryManager.java +++ b/src/main/java/emu/nebula/game/story/StoryManager.java @@ -1,12 +1,62 @@ package emu.nebula.game.story; import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import emu.nebula.Nebula; +import emu.nebula.data.GameData; import emu.nebula.database.GameDatabaseObject; +import emu.nebula.game.player.Player; +import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.game.player.PlayerManager; + +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + import lombok.Getter; @Getter @Entity(value = "story", useDiscriminator = false) public class StoryManager extends PlayerManager implements GameDatabaseObject { + @Id + private int uid; + + private IntSet completedStories; + + @Deprecated // Morphia only + public StoryManager() { + + } + + public StoryManager(Player player) { + super(player); + this.uid = player.getUid(); + this.completedStories = new IntOpenHashSet(); + } + public PlayerChangeInfo settle(IntList list) { + var changes = new PlayerChangeInfo(); + + for (int id : list) { + // Get story data + var data = GameData.getStoryDataTable().get(id); + if (data == null) continue; + + // Check if we already completed the story + if (this.getCompletedStories().contains(id)) { + continue; + } + + // Complete story and get rewards + this.getCompletedStories().add(id); + + // Add rewards + this.getPlayer().getInventory().addItems(data.getRewards(), changes); + + // Save to db + Nebula.getGameDatabase().addToList(this, this.getPlayerUid(), "completedStories", id); + } + + return changes; + } } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerActivityDetailReq.java b/src/main/java/emu/nebula/server/handlers/HandlerActivityDetailReq.java index 1c087fe..0067efa 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerActivityDetailReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerActivityDetailReq.java @@ -8,6 +8,7 @@ import emu.nebula.proto.Public.ActivityTrial; import emu.nebula.net.HandlerId; import emu.nebula.net.GameSession; +@SuppressWarnings("unused") @HandlerId(NetMsgId.activity_detail_req) public class HandlerActivityDetailReq extends NetHandler { @@ -15,11 +16,13 @@ public class HandlerActivityDetailReq extends NetHandler { public byte[] handle(GameSession session, byte[] message) throws Exception { var rsp = ActivityResp.newInstance(); + /* var activity = ActivityMsg.newInstance() .setId(700101) .setTrial(ActivityTrial.newInstance()); rsp.addList(activity); + */ return this.encodeMsg(NetMsgId.activity_detail_succeed_ack, rsp); } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerStoryApplyReq.java b/src/main/java/emu/nebula/server/handlers/HandlerStoryApplyReq.java new file mode 100644 index 0000000..16e92b1 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerStoryApplyReq.java @@ -0,0 +1,16 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.story_apply_req) +public class HandlerStoryApplyReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + return this.encodeMsg(NetMsgId.story_apply_succeed_ack); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerStorySetInfoReq.java b/src/main/java/emu/nebula/server/handlers/HandlerStorySetInfoReq.java new file mode 100644 index 0000000..5bbcfc7 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerStorySetInfoReq.java @@ -0,0 +1,28 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.StorySetInfo.StorySetChapter; +import emu.nebula.proto.StorySetInfo.StorySetInfoResp; +import emu.nebula.net.HandlerId; +import emu.nebula.data.resources.StorySetSectionDef; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.story_set_info_req) +public class HandlerStorySetInfoReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + var rsp = StorySetInfoResp.newInstance(); + + for (int chapterId : StorySetSectionDef.getChapterIds()) { + var chapter = StorySetChapter.newInstance() + .setChapterId(chapterId); + + rsp.addChapters(chapter); + } + + return this.encodeMsg(NetMsgId.story_set_info_succeed_ack, rsp); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerStorySettleReq.java b/src/main/java/emu/nebula/server/handlers/HandlerStorySettleReq.java new file mode 100644 index 0000000..25d0e17 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerStorySettleReq.java @@ -0,0 +1,32 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.StorySett.StorySettleReq; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.story_settle_req) +public class HandlerStorySettleReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = StorySettleReq.parseFrom(message); + + // Get list of settled story ids + var list = new IntArrayList(); + + for (var settle : req.getList()) { + list.add(settle.getIdx()); + } + + // Settle + var changes = session.getPlayer().getStoryManager().settle(list); + + // Finish + return this.encodeMsg(NetMsgId.story_settle_succeed_ack, changes.toProto()); + } + +}