mirror of
https://github.com/Melledy/Nebula.git
synced 2026-09-19 17:19:58 +02:00
Implement event story
This commit is contained in:
@@ -188,6 +188,9 @@ public class GameData {
|
||||
// Activity: Task
|
||||
@Getter private static DataTable<ActivityTaskDef> ActivityTaskDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<ActivityTaskGroupDef> ActivityTaskGroupDataTable = new DataTable<>();
|
||||
|
||||
// Activity: Story
|
||||
@Getter private static DataTable<ActivityStoryDef> ActivityStoryDataTable = new DataTable<>();
|
||||
|
||||
// Activity: Shop
|
||||
@Getter private static DataTable<ActivityShopDef> ActivityShopDataTable = new DataTable<>();
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "ActivityStory.json")
|
||||
public class ActivityStoryDef extends BaseDef {
|
||||
private int Id;
|
||||
private int ChapterId;
|
||||
|
||||
private String FirstCompleteReward;
|
||||
|
||||
private transient ItemParamMap rewards;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.rewards = ItemParamMap.fromJsonString(this.FirstCompleteReward);
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,7 @@ public class ActivityManager extends PlayerManager implements GameDatabaseObject
|
||||
case Task -> new TaskActivity(this, data);
|
||||
case Shop -> new ShopActivity(this, data);
|
||||
case TrekkerVersus -> new TrekkerVersusActivity(this, data);
|
||||
case Story -> new StoryActivity(this, data);
|
||||
case PenguinCard -> new PenguinCardActivity(this, data);
|
||||
case Soldier -> new SoldierActivity(this, data);
|
||||
default -> null;
|
||||
|
||||
@@ -81,6 +81,7 @@ public class ActivityModule extends GameContextModule {
|
||||
|
||||
// Go, My Lady! Training Handbook Plus!
|
||||
this.activities.add(1011101);
|
||||
this.activities.add(1011102);
|
||||
this.activities.add(1011103);
|
||||
this.activities.add(1011104);
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package emu.nebula.game.activity.type;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.ActivityDef;
|
||||
import emu.nebula.game.activity.ActivityManager;
|
||||
import emu.nebula.game.activity.GameActivity;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.proto.ActivityDetail.ActivityMsg;
|
||||
import emu.nebula.proto.ActivityStorySettleOuterClass.ActivityStorySettle;
|
||||
import emu.nebula.proto.Public.ActivityStory;
|
||||
import emu.nebula.proto.Public.ActivityStoryChoice;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import us.hebi.quickbuf.RepeatedInt;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
public class StoryActivity extends GameActivity {
|
||||
private Map<Integer, ActivityStoryInfo> stories;
|
||||
private IntSet evidences;
|
||||
private long buildId;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public StoryActivity() {
|
||||
|
||||
}
|
||||
|
||||
public StoryActivity(ActivityManager manager, ActivityDef data) {
|
||||
super(manager, data);
|
||||
this.stories = new HashMap<>();
|
||||
this.evidences = new IntOpenHashSet();
|
||||
}
|
||||
|
||||
private int getChapterId() {
|
||||
return (int) Math.floor(this.getId() / 100);
|
||||
}
|
||||
|
||||
public boolean apply(int storyId, long buildId) {
|
||||
// Check story id
|
||||
var story = GameData.getActivityStoryDataTable().get(storyId);
|
||||
|
||||
if (story == null || story.getChapterId() != this.getChapterId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set build id
|
||||
if (buildId != 0) {
|
||||
this.buildId = buildId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PlayerChangeInfo settle(Iterable<ActivityStorySettle> list, RepeatedInt evidences) {
|
||||
// Create change info
|
||||
var change = new PlayerChangeInfo();
|
||||
|
||||
// Boolean flag to check if any data was changed/added
|
||||
boolean hasChanged = false;
|
||||
|
||||
// Handle settle info
|
||||
for (var settle : list) {
|
||||
// Get story data
|
||||
var story = GameData.getActivityStoryDataTable().get(settle.getStoryId());
|
||||
|
||||
// Validate story
|
||||
if (story == null || story.getChapterId() != this.getChapterId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if we have already completed this story
|
||||
if (this.getStories().containsKey(story.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create story info
|
||||
var info = new ActivityStoryInfo(story.getId());
|
||||
|
||||
for (var option : settle.getMajor()) {
|
||||
info.addMajor(option.getGroup(), option.getChoice());
|
||||
}
|
||||
|
||||
for (var option : settle.getPersonality()) {
|
||||
info.addPersonality(option.getGroup(), option.getChoice());
|
||||
}
|
||||
|
||||
// Add to story log
|
||||
this.stories.put(story.getId(), info);
|
||||
|
||||
// Set changed flag
|
||||
hasChanged = true;
|
||||
|
||||
// Add rewards
|
||||
this.getPlayer().getInventory().addItems(story.getRewards(), change);
|
||||
}
|
||||
|
||||
// Add evidences
|
||||
for (int i : evidences) {
|
||||
this.getEvidences().add(i);
|
||||
|
||||
// Set changed flag
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
// Save to database if anything has changed
|
||||
if (hasChanged) {
|
||||
this.save();
|
||||
}
|
||||
|
||||
// Success
|
||||
return change;
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
@Override
|
||||
public void encodeActivityMsg(ActivityMsg msg) {
|
||||
var proto = msg.getMutableStoryChapter()
|
||||
.setBuildId(this.getBuildId());
|
||||
|
||||
for (int i : this.getEvidences()) {
|
||||
proto.addEvidences(i);
|
||||
}
|
||||
|
||||
for (var info : this.getStories().values()) {
|
||||
proto.addStories(info.toProto());
|
||||
}
|
||||
}
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@Entity(useDiscriminator = false)
|
||||
public static class ActivityStoryInfo {
|
||||
private int id;
|
||||
private Int2IntMap major;
|
||||
private Int2IntMap personality;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public ActivityStoryInfo() {
|
||||
|
||||
}
|
||||
|
||||
public ActivityStoryInfo(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void addMajor(int group, int choice) {
|
||||
if (this.major == null) {
|
||||
this.major = new Int2IntOpenHashMap();
|
||||
}
|
||||
|
||||
this.major.put(group, choice);
|
||||
}
|
||||
|
||||
public void addPersonality(int group, int choice) {
|
||||
if (this.personality == null) {
|
||||
this.personality = new Int2IntOpenHashMap();
|
||||
}
|
||||
|
||||
this.personality.put(group, choice);
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public ActivityStory toProto() {
|
||||
var proto = ActivityStory.newInstance()
|
||||
.setId(this.id);
|
||||
|
||||
if (this.major != null) {
|
||||
for (var entry : this.major.int2IntEntrySet()) {
|
||||
var choice = ActivityStoryChoice.newInstance()
|
||||
.setGroup(entry.getIntKey())
|
||||
.setValue(entry.getIntValue());
|
||||
|
||||
proto.addMajor(choice);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.personality != null) {
|
||||
for (var entry : this.personality.int2IntEntrySet()) {
|
||||
var choice = ActivityStoryChoice.newInstance()
|
||||
.setGroup(entry.getIntKey())
|
||||
.setValue(entry.getIntValue());
|
||||
|
||||
proto.addPersonality(choice);
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,8 +149,10 @@ public class ItemParamMap extends Int2IntLinkedOpenHashMap implements ObjectBidi
|
||||
var map = new ItemParamMap();
|
||||
var json = JsonUtils.decodeMap(jsonString, Integer.class, Integer.class);
|
||||
|
||||
for (var entry : json.entrySet()) {
|
||||
map.add(entry.getKey(), entry.getValue());
|
||||
if (json != null) {
|
||||
for (var entry : json.entrySet()) {
|
||||
map.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.ActivityStoryApply.ActivityStoryApplyReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.StoryActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.activity_story_apply_req)
|
||||
public class HandlerActivityStoryApplyReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse req
|
||||
var req = ActivityStoryApplyReq.parseFrom(message);
|
||||
|
||||
// Get activity
|
||||
var activity = session.getPlayer().getActivityManager().getActivity(StoryActivity.class, req.getActivityId());
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.activity_story_apply_failed_ack);
|
||||
}
|
||||
|
||||
// Apply
|
||||
boolean success = activity.apply(req.getStoryId(), req.getBuildId());
|
||||
|
||||
if (success == false) {
|
||||
return session.encodeMsg(NetMsgId.activity_story_apply_failed_ack);
|
||||
}
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.activity_story_apply_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.ActivityStorySettleOuterClass.ActivityStorySettleReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.StoryActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.activity_story_settle_req)
|
||||
public class HandlerActivityStorySettleReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse req
|
||||
var req = ActivityStorySettleReq.parseFrom(message);
|
||||
|
||||
// Get activity
|
||||
var activity = session.getPlayer().getActivityManager().getActivity(StoryActivity.class, req.getActivityId());
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.activity_story_settle_failed_ack);
|
||||
}
|
||||
|
||||
// Apply
|
||||
var change = activity.settle(req.getMutableList(), req.getMutableEvidences());
|
||||
|
||||
if (change == null) {
|
||||
return session.encodeMsg(NetMsgId.activity_story_settle_failed_ack);
|
||||
}
|
||||
|
||||
// Handle client events for achievements
|
||||
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.activity_story_settle_succeed_ack, change.toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
"global": 134,
|
||||
"kr": 139,
|
||||
"jp": 137,
|
||||
"tw": 142,
|
||||
"tw": 143,
|
||||
"cn": 133
|
||||
}
|
||||
Reference in New Issue
Block a user