Implement story

This commit is contained in:
Melledy
2025-10-27 21:39:12 -07:00
parent 08feedc766
commit f618486ced
11 changed files with 227 additions and 2 deletions

View File

@@ -39,6 +39,7 @@ public class GameData {
@Getter private static DataTable<WorldClassDef> WorldClassDataTable = new DataTable<>(); @Getter private static DataTable<WorldClassDef> WorldClassDataTable = new DataTable<>();
@Getter private static DataTable<GuideGroupDef> GuideGroupDataTable = new DataTable<>(); @Getter private static DataTable<GuideGroupDef> GuideGroupDataTable = new DataTable<>();
@Getter private static DataTable<StoryDef> StoryDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerDef> StarTowerDataTable = new DataTable<>(); @Getter private static DataTable<StarTowerDef> StarTowerDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerStageDef> StarTowerStageDataTable = new DataTable<>(); @Getter private static DataTable<StarTowerStageDef> StarTowerStageDataTable = new DataTable<>();

View File

@@ -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();
}
}
}

View File

@@ -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());
}
}

View File

@@ -1,5 +1,7 @@
package emu.nebula.game.inventory; package emu.nebula.game.inventory;
import com.google.gson.annotations.SerializedName;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import emu.nebula.proto.Public.ItemTpl; import emu.nebula.proto.Public.ItemTpl;
import lombok.Getter; import lombok.Getter;
@@ -7,7 +9,10 @@ import lombok.Getter;
@Getter @Getter
@Entity(useDiscriminator = false) @Entity(useDiscriminator = false)
public class ItemParam { public class ItemParam {
@SerializedName("Tid")
public int id; public int id;
@SerializedName("Qty")
public int count; public int count;
@Deprecated // Morphia only @Deprecated // Morphia only

View File

@@ -76,7 +76,7 @@ public class ItemParamMap extends Int2IntOpenHashMap {
.map(e -> ItemTpl.newInstance().setTid(e.getIntKey()).setQty(e.getIntValue())); .map(e -> ItemTpl.newInstance().setTid(e.getIntKey()).setQty(e.getIntValue()));
} }
// Proto // Helpers
public static ItemParamMap fromTemplates(RepeatedMessage<ItemTpl> items) { public static ItemParamMap fromTemplates(RepeatedMessage<ItemTpl> items) {
var map = new ItemParamMap(); var map = new ItemParamMap();
@@ -97,4 +97,14 @@ public class ItemParamMap extends Int2IntOpenHashMap {
return map; return map;
} }
public static ItemParamMap fromItemParams(List<ItemParam> items) {
var map = new ItemParamMap();
for (var template : items) {
map.add(template.getId(), template.getCount());
}
return map;
}
} }

View File

@@ -16,11 +16,13 @@ import emu.nebula.game.character.CharacterStorage;
import emu.nebula.game.formation.FormationManager; import emu.nebula.game.formation.FormationManager;
import emu.nebula.game.inventory.Inventory; import emu.nebula.game.inventory.Inventory;
import emu.nebula.game.mail.Mailbox; import emu.nebula.game.mail.Mailbox;
import emu.nebula.game.story.StoryManager;
import emu.nebula.game.tower.StarTowerManager; import emu.nebula.game.tower.StarTowerManager;
import emu.nebula.net.GameSession; import emu.nebula.net.GameSession;
import emu.nebula.proto.PlayerData.PlayerInfo; import emu.nebula.proto.PlayerData.PlayerInfo;
import emu.nebula.proto.Public.NewbieInfo; import emu.nebula.proto.Public.NewbieInfo;
import emu.nebula.proto.Public.QuestType; import emu.nebula.proto.Public.QuestType;
import emu.nebula.proto.Public.Story;
import emu.nebula.proto.Public.WorldClass; import emu.nebula.proto.Public.WorldClass;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
@@ -62,6 +64,7 @@ public class Player implements GameDatabaseObject {
private transient FormationManager formations; private transient FormationManager formations;
private transient Mailbox mailbox; private transient Mailbox mailbox;
private transient StarTowerManager starTowerManager; private transient StarTowerManager starTowerManager;
private transient StoryManager storyManager;
@Deprecated // Morphia only @Deprecated // Morphia only
public Player() { public Player() {
@@ -257,6 +260,13 @@ public class Player implements GameDatabaseObject {
} else { } else {
this.starTowerManager.setPlayer(this); 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 // Proto
@@ -337,6 +347,16 @@ public class Player implements GameDatabaseObject {
} }
acc.addNewbies(NewbieInfo.newInstance().setGroupId(GameConstants.INTRO_GUIDE_ID).setStepId(-1)); 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); proto.addBoard(410301);
@@ -351,7 +371,6 @@ public class Player implements GameDatabaseObject {
proto.getMutableQuests(); proto.getMutableQuests();
proto.getMutableAgent(); proto.getMutableAgent();
proto.getMutablePhone(); proto.getMutablePhone();
proto.getMutableStory();
return proto; return proto;
} }

View File

@@ -1,12 +1,62 @@
package emu.nebula.game.story; package emu.nebula.game.story;
import dev.morphia.annotations.Entity; 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.database.GameDatabaseObject;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.player.PlayerManager; 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; import lombok.Getter;
@Getter @Getter
@Entity(value = "story", useDiscriminator = false) @Entity(value = "story", useDiscriminator = false)
public class StoryManager extends PlayerManager implements GameDatabaseObject { 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;
}
} }

View File

@@ -8,6 +8,7 @@ import emu.nebula.proto.Public.ActivityTrial;
import emu.nebula.net.HandlerId; import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession; import emu.nebula.net.GameSession;
@SuppressWarnings("unused")
@HandlerId(NetMsgId.activity_detail_req) @HandlerId(NetMsgId.activity_detail_req)
public class HandlerActivityDetailReq extends NetHandler { public class HandlerActivityDetailReq extends NetHandler {
@@ -15,11 +16,13 @@ public class HandlerActivityDetailReq extends NetHandler {
public byte[] handle(GameSession session, byte[] message) throws Exception { public byte[] handle(GameSession session, byte[] message) throws Exception {
var rsp = ActivityResp.newInstance(); var rsp = ActivityResp.newInstance();
/*
var activity = ActivityMsg.newInstance() var activity = ActivityMsg.newInstance()
.setId(700101) .setId(700101)
.setTrial(ActivityTrial.newInstance()); .setTrial(ActivityTrial.newInstance());
rsp.addList(activity); rsp.addList(activity);
*/
return this.encodeMsg(NetMsgId.activity_detail_succeed_ack, rsp); return this.encodeMsg(NetMsgId.activity_detail_succeed_ack, rsp);
} }

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}