Basic shadow siege implementation

This commit is contained in:
Melledy
2026-07-21 01:47:20 -07:00
parent ee0866e7e4
commit 07b64437ff
18 changed files with 807 additions and 4 deletions
@@ -55,6 +55,13 @@ public class GameConstants {
101, 102, 104, 105, 106, 107, 108, 114, 115, 116, 126, 127, 128 101, 102, 104, 105, 106, 107, 108, 114, 115, 116, 126, 127, 128
}; };
public static final int TRACE_HUNT_TOKEN_ID = 37;
public static final int TRACE_HUNT_REQUEST_ITEM_ID = 38;
public static final int TRACE_HUNT_PERMIT_ITEM_ID = 39;
public static final int[] TRACE_HUNT_TRACE_IDS = {21, 22, 23, 31, 41};
public static final int TRACE_HUNT_MAX_TRACE_PROGRESS = 10_000;
public static final int TRACE_HUNT_MAX_HUNT_PROGRESS = 10_000;
public static final int REFRESH_TYPE_DAILY = 1; public static final int REFRESH_TYPE_DAILY = 1;
public static final int REFRESH_TYPE_WEEKLY = 2; public static final int REFRESH_TYPE_WEEKLY = 2;
public static final int REFRESH_TYPE_MONTHLY = 3; public static final int REFRESH_TYPE_MONTHLY = 3;
@@ -139,6 +139,11 @@ public class GameData {
@Getter private static DataTable<ScoreBossControlDef> ScoreBossControlDataTable = new DataTable<>(); @Getter private static DataTable<ScoreBossControlDef> ScoreBossControlDataTable = new DataTable<>();
@Getter private static DataTable<ScoreBossRewardDef> ScoreBossRewardDataTable = new DataTable<>(); @Getter private static DataTable<ScoreBossRewardDef> ScoreBossRewardDataTable = new DataTable<>();
// ===== Trace Hunt =====
@Getter private static DataTable<TraceHuntControlDef> TraceHuntControlDataTable = new DataTable<>();
@Getter private static DataTable<TraceHuntLevelDef> TraceHuntLevelDataTable = new DataTable<>();
@Getter private static DataTable<TraceHuntSelfHuntExtraCostDef> TraceHuntSelfHuntExtraCostDataTable = new DataTable<>();
// ===== Misc ===== // ===== Misc =====
@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<>();
@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "TraceHuntControl.json")
public class TraceHuntControlDef extends BaseDef {
private int Id;
private int[] BossList;
@Override
public int getId() {
return Id;
}
}
@@ -0,0 +1,20 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "TraceHuntLevel.json")
public class TraceHuntLevelDef extends BaseDef {
private int Level;
private int Exp;
private int WorldClass;
private int MaxStar;
private int TokenRate;
@Override
public int getId() {
return Level;
}
}
@@ -0,0 +1,18 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "TraceHuntSelfHuntExtraCost.json")
public class TraceHuntSelfHuntExtraCostDef extends BaseDef {
private int Times;
private int ExtraCost1Tid;
private int ExtraCost1Qty;
@Override
public int getId() {
return Times;
}
}
@@ -46,6 +46,7 @@ public class Inventory extends PlayerManager implements GameDatabaseObject {
private ItemParamMap shopBuyCount; private ItemParamMap shopBuyCount;
private String2IntMap mallBuyCount; private String2IntMap mallBuyCount;
private String2IntMap mallPackageBuyCount; private String2IntMap mallPackageBuyCount;
/** /**
* Tracks whether a MallGem pack has already consumed its maiden bonus. * Tracks whether a MallGem pack has already consumed its maiden bonus.
* This is the only persisted state MallGem recharge still needs now that * This is the only persisted state MallGem recharge still needs now that
@@ -589,6 +590,34 @@ public class Inventory extends PlayerManager implements GameDatabaseObject {
change.add(proto); change.add(proto);
} }
} }
case TraceRequest -> {
int oldAmount = this.getPlayer().getTraceHuntManager().getTraceRequests();
int newAmount = oldAmount;
int diff = 0;
newAmount = this.getPlayer().getTraceHuntManager().addTraceRequests(amount);
diff = newAmount - oldAmount;
var proto = TraceHuntItem.newInstance()
.setTid(id)
.setGrantQty(diff);
change.add(proto);
}
case HuntPermit -> {
int oldAmount = this.getPlayer().getTraceHuntManager().getHuntPermits();
int newAmount = oldAmount;
int diff = 0;
newAmount = this.getPlayer().getTraceHuntManager().addHuntPermits(amount);
diff = newAmount - oldAmount;
var proto = TraceHuntItem.newInstance()
.setTid(id)
.setGrantQty(diff);
change.add(proto);
}
default -> { default -> {
// Not implemented // Not implemented
} }
@@ -29,6 +29,7 @@ import emu.nebula.game.quest.QuestManager;
import emu.nebula.game.scoreboss.ScoreBossManager; import emu.nebula.game.scoreboss.ScoreBossManager;
import emu.nebula.game.story.StoryManager; import emu.nebula.game.story.StoryManager;
import emu.nebula.game.tower.StarTowerManager; import emu.nebula.game.tower.StarTowerManager;
import emu.nebula.game.tracehunt.TraceHuntManager;
import emu.nebula.game.vampire.VampireSurvivorManager; import emu.nebula.game.vampire.VampireSurvivorManager;
import emu.nebula.net.GameSession; import emu.nebula.net.GameSession;
import emu.nebula.net.NetMsgId; import emu.nebula.net.NetMsgId;
@@ -110,6 +111,7 @@ public class Player implements GameDatabaseObject {
private transient QuestManager questManager; private transient QuestManager questManager;
private transient AchievementManager achievementManager; private transient AchievementManager achievementManager;
private transient AgentManager agentManager; private transient AgentManager agentManager;
private transient TraceHuntManager traceHuntManager;
private transient ActivityManager activityManager; private transient ActivityManager activityManager;
// Extra // Extra
@@ -814,6 +816,7 @@ public class Player implements GameDatabaseObject {
this.questManager = this.loadManagerFromDatabase(QuestManager.class); this.questManager = this.loadManagerFromDatabase(QuestManager.class);
this.achievementManager = this.loadManagerFromDatabase(AchievementManager.class); this.achievementManager = this.loadManagerFromDatabase(AchievementManager.class);
this.agentManager = this.loadManagerFromDatabase(AgentManager.class); this.agentManager = this.loadManagerFromDatabase(AgentManager.class);
this.traceHuntManager = this.loadManagerFromDatabase(TraceHuntManager.class);
this.activityManager = this.loadManagerFromDatabase(ActivityManager.class); this.activityManager = this.loadManagerFromDatabase(ActivityManager.class);
// Database fixes // Database fixes
@@ -1234,7 +1237,7 @@ public class Player implements GameDatabaseObject {
state.getMutableStarTowerBook(); state.getMutableStarTowerBook();
state.getMutableScoreBoss(); state.getMutableScoreBoss();
state.getMutableCharAffinityRewards(); state.getMutableCharAffinityRewards();
state.getMutableTraceHunt(); state.getMutableTraceHunt().setBossRewardCanReceive(this.getTraceHuntManager().isHuntComplete());
// Force complete tutorials // Force complete tutorials
for (var guide : GameData.getGuideGroupDataTable()) { for (var guide : GameData.getGuideGroupDataTable()) {
@@ -1307,8 +1310,13 @@ public class Player implements GameDatabaseObject {
} }
// Trace hunt // Trace hunt
proto.getMutableHuntPermit(); proto.getMutableHuntPermit()
proto.getMutableTraceRequest(); .setTid(GameConstants.TRACE_HUNT_PERMIT_ITEM_ID)
.setGrantedCount(this.getTraceHuntManager().getHuntPermits());
proto.getMutableTraceRequest()
.setTid(GameConstants.TRACE_HUNT_REQUEST_ITEM_ID)
.setGrantedCount(this.getTraceHuntManager().getTraceRequests());
// Complete // Complete
return proto; return proto;
@@ -27,6 +27,7 @@ import emu.nebula.game.quest.QuestManager;
import emu.nebula.game.scoreboss.ScoreBossRankEntry; import emu.nebula.game.scoreboss.ScoreBossRankEntry;
import emu.nebula.game.story.StoryManager; import emu.nebula.game.story.StoryManager;
import emu.nebula.game.tower.StarTowerBuild; import emu.nebula.game.tower.StarTowerBuild;
import emu.nebula.game.tracehunt.TraceHuntManager;
import emu.nebula.net.GameSession; import emu.nebula.net.GameSession;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -183,6 +184,7 @@ public class PlayerModule extends GameContextModule {
datastore.getCollection(StoryManager.class).deleteOne(idFilter); datastore.getCollection(StoryManager.class).deleteOne(idFilter);
datastore.getCollection(QuestManager.class).deleteOne(idFilter); datastore.getCollection(QuestManager.class).deleteOne(idFilter);
datastore.getCollection(AgentManager.class).deleteOne(idFilter); datastore.getCollection(AgentManager.class).deleteOne(idFilter);
datastore.getCollection(TraceHuntManager.class).deleteOne(idFilter);
datastore.getCollection(AchievementManager.class).deleteOne(idFilter); datastore.getCollection(AchievementManager.class).deleteOne(idFilter);
datastore.getCollection(ActivityManager.class).deleteOne(idFilter); datastore.getCollection(ActivityManager.class).deleteOne(idFilter);
@@ -0,0 +1,35 @@
package emu.nebula.game.tracehunt;
import dev.morphia.annotations.Entity;
import emu.nebula.proto.Public.TraceHuntBossCollection;
import lombok.Getter;
@Getter
@Entity(useDiscriminator = false)
public class TraceHuntBoss {
private int id;
private int hunts;
private int assists;
@Deprecated // Morphia only
public TraceHuntBoss() {
}
public TraceHuntBoss(int bossId, int hunts, int assists) {
this.id = bossId;
this.hunts = hunts;
this.assists = assists;
}
// Proto
public TraceHuntBossCollection toProto() {
var proto = TraceHuntBossCollection.newInstance()
.setId(this.getId())
.setHuntCount(this.hunts)
.setAssistHuntCount(this.assists);
return proto;
}
}
@@ -0,0 +1,40 @@
package emu.nebula.game.tracehunt;
import dev.morphia.annotations.Entity;
import emu.nebula.proto.Public.TraceHuntLogEntry;
import lombok.Getter;
@Getter
@Entity(useDiscriminator = false)
public class TraceHuntLog {
private int id;
private String[] args;
@Deprecated // Morphia only
public TraceHuntLog() {
}
public TraceHuntLog(int id) {
this.id = id;
}
public TraceHuntLog(int id, String... args) {
this.id = id;
this.args = args;
}
// Proto
public TraceHuntLogEntry toProto() {
var proto = TraceHuntLogEntry.newInstance()
.setTid(this.getId());
if (this.getArgs() != null) {
proto.addAllArgs(this.getArgs());
}
return proto;
}
}
@@ -0,0 +1,42 @@
package emu.nebula.game.tracehunt;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
public enum TraceHuntLogType {
TraceStart (1),
Tracing (2),
TraceBeforeEnd (3),
TraceEnd (4),
TraceInterrupt (5),
TraceRestart (6),
HuntBeforeStart (7),
HuntStart (8),
HuntPlayer (9),
HuntNPC (10),
HuntPlayerFatal (11),
HuntNPCFatal (12),
HuntEnd (13),
Settlement (14),
HuntAfterStart (15),
HuntInterrupt (16);
@Getter
private final int value;
private final static Int2ObjectMap<TraceHuntLogType> map = new Int2ObjectOpenHashMap<>();
static {
for (TraceHuntLogType type : TraceHuntLogType.values()) {
map.put(type.getValue(), type);
}
}
private TraceHuntLogType(int value) {
this.value = value;
}
public static TraceHuntLogType getByValue(int value) {
return map.get(value);
}
}
@@ -0,0 +1,381 @@
package emu.nebula.game.tracehunt;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import emu.nebula.GameConstants;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.TraceHuntControlDef;
import emu.nebula.data.resources.TraceHuntSelfHuntExtraCostDef;
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.proto.TraceHuntInfoOuterClass.TraceHuntInfo;
import emu.nebula.util.Utils;
import lombok.Getter;
@Getter
@Entity(value = "trace_hunts", useDiscriminator = false)
public class TraceHuntManager extends PlayerManager implements GameDatabaseObject {
@Id
private int uid;
private int controlId;
private int level;
private int exp;
// Requests/Hunt items
private int traceRequests;
private int dailyRequests; // Max of 20 daily
private int huntPermits;
// Current boss
private int bossId;
private long bossCreateTime;
private int traceProgress;
private int huntProgress;
private int huntCount;
private int assistCount;
private List<TraceHuntLog> traceLogs;
private List<TraceHuntLog> huntLogs;
// Current hunt
private transient int huntPlayerUid;
private transient int huntBossId;
private long buildId;
// Collection
private Map<Integer, TraceHuntBoss> bosses;
@Deprecated // Morphia only
public TraceHuntManager() {
}
public TraceHuntManager(Player player) {
this();
this.setPlayer(player);
this.uid = player.getUid();
this.controlId = 3;
this.level = 1;
this.bossId = this.getControlData().getBossList()[0];
this.bossCreateTime = Nebula.getCurrentServerTime();
this.traceLogs = new ArrayList<>();
this.huntLogs = new ArrayList<>();
this.bosses = new HashMap<>();
}
public int getControlId() {
return this.controlId;
}
public TraceHuntControlDef getControlData() {
return GameData.getTraceHuntControlDataTable().get(this.getControlId());
}
public int addTraceRequests(int amount) {
// Add/remove requests
this.traceRequests = Math.max(Math.min(this.traceRequests + amount, 60), 0);
// Save to database
this.save();
// Return amount
return this.traceRequests;
}
public int addHuntPermits(int amount) {
// Add/remove permits
this.huntPermits = Math.max(this.huntPermits + amount, 0);
// Save to database
this.save();
// Return amount
return this.huntPermits;
}
public int getMaxGainableExp() {
if (this.getLevel() >= this.getMaxLevel()) {
return 0;
}
int maxLevel = this.getMaxLevel();
int max = 0;
for (int i = this.getLevel() + 1; i <= maxLevel; i++) {
var data = GameData.getTraceHuntLevelDataTable().get(i);
if (data != null) {
max += data.getExp();
}
}
return Math.max(max - this.getExp(), 0);
}
public int getMaxExp() {
if (this.getLevel() >= this.getMaxLevel()) {
return 0;
}
var data = GameData.getTraceHuntLevelDataTable().get(this.level + 1);
return data != null ? data.getExp() : 0;
}
public int getMaxLevel() {
return GameData.getTraceHuntLevelDataTable().size();
}
public void addExp(int amount) {
// Setup
int expRequired = this.getMaxExp();
// Add exp
this.exp += amount;
// Check for level ups
while (this.exp >= expRequired && expRequired > 0) {
this.level += 1;
this.exp -= expRequired;
expRequired = this.getMaxExp();
}
// Clamp exp
if (this.getLevel() >= this.getMaxLevel()) {
this.exp = 0;
}
// Save to database
this.save();
}
public boolean isHunting() {
return this.traceProgress >= GameConstants.TRACE_HUNT_MAX_TRACE_PROGRESS;
}
public boolean isHuntComplete() {
return this.huntProgress >= GameConstants.TRACE_HUNT_MAX_HUNT_PROGRESS;
}
public TraceHuntSelfHuntExtraCostDef getHuntCost() {
int times = Math.max(this.huntCount, GameData.getTraceHuntSelfHuntExtraCostDataTable().size());
return GameData.getTraceHuntSelfHuntExtraCostDataTable().get(times);
}
public void resetBoss() {
this.bossId = 0;
this.bossCreateTime = 0;
this.traceProgress = 0;
this.huntProgress = 0;
this.huntCount = 0;
this.assistCount = 0;
this.traceLogs.clear();
this.huntLogs.clear();
}
// Game logic
public PlayerChangeInfo trace(int count) {
// Sanity check to make sure we have enough requests
if (this.getTraceRequests() < count) {
return null;
}
// Sanity check to make sure we havent started hunting yet
if (this.isHunting()) {
return null;
}
// Used requests
int consumed = 0;
// Parse log
var logs = new ArrayList<TraceHuntLog>();
for (int i = 0; i < count; i++) {
// Get random trace
int traceId = Utils.randomElement(GameConstants.TRACE_HUNT_TRACE_IDS);
int progress = 0;
if (traceId >= 40) {
progress = 2000;
} else if (traceId >= 30) {
progress = 1000;
} else {
progress = 500;
}
// Add trace log
logs.add(new TraceHuntLog(traceId, Integer.toString(progress)));
// Add progress
this.traceProgress += progress;
// Increment requests we used
consumed++;
// Complete
if (this.isHunting()) {
logs.add(new TraceHuntLog(5));
break;
}
}
// Consume trace requests
var change = this.getPlayer().getInventory().removeItem(GameConstants.TRACE_HUNT_REQUEST_ITEM_ID, consumed);
// Add to logs
this.getTraceLogs().addAll(logs);
// Add logs to change info
change.setExtraData(logs);
// Save
this.save();
// Success
return change;
}
public boolean apply(long ownerUid, int bossId, long buildId) {
// Sanity check
if (!this.isHunting() || this.isHuntComplete()) {
return false;
}
// Set build
this.huntPlayerUid = (int) ownerUid;
this.huntBossId = bossId;
this.buildId = buildId;
// Success
return true;
}
public PlayerChangeInfo settle(int score, int stars) {
// Sanity check
if (this.huntBossId == 0 || this.huntPlayerUid == 0) {
return null;
}
// TODO verify stars
stars = Math.min(Math.max(stars, 0), 7);
// Build change info
var change = new PlayerChangeInfo();
var logs = new ArrayList<TraceHuntLog>();
// Add logs to change info
change.setExtraData(logs);
// Calculate result
if (this.huntPlayerUid == this.getPlayerUid()) {
// Check if we have enough cost items
var cost = this.getHuntCost();
if (cost != null) {
if (!getPlayer().getInventory().hasItem(cost.getExtraCost1Tid(), cost.getExtraCost1Qty())) {
return null;
}
getPlayer().getInventory().removeItem(cost.getExtraCost1Tid(), cost.getExtraCost1Qty(), change);
}
// Our own hunts
int progress = stars * 500;
logs.add(new TraceHuntLog(11, this.getPlayer().getName(), Integer.toString(progress)));
// Add to logs
this.huntProgress = Math.min(this.huntProgress + progress, GameConstants.TRACE_HUNT_MAX_HUNT_PROGRESS);
this.huntCount++;
this.getHuntLogs().addAll(logs);
// Save
this.save();
} else {
// Other player's hunts are not supported yet TODO
return null;
}
// Success
return change;
}
public PlayerChangeInfo claimReward() {
if (!this.isHuntComplete()) {
return null;
}
// Add boss log
var bossLog = new TraceHuntBoss(this.getBossId(), this.getHuntCount(), this.getAssistCount());
this.getBosses().put(this.getBossId(), bossLog);
// Reset boss
this.resetBoss();
// Get next boss from control data
var control = this.getControlData();
for (int bossId : control.getBossList()) {
if (this.getBosses().containsKey(bossId)) {
continue;
}
this.bossId = bossId;
break;
}
// Save
this.save();
// Success
// Test amount of items
return this.getPlayer().getInventory().addItem(37, 1000);
}
// Proto
public TraceHuntInfo toProto() {
var proto = TraceHuntInfo.newInstance()
.setControlID(this.getControlId())
.setLevel(this.getLevel())
.setExp(this.getExp())
.setBossID(this.getBossId())
.setBossCreateTime(this.getBossCreateTime())
.setBuildID(this.getBuildId())
.setTraceProgress(this.getTraceProgress())
.setHuntProgress(this.getHuntProgress())
.setSelfHuntTimes(this.getHuntCount());
for (var boss : this.getBosses().values()) {
proto.addBossCollections(boss.toProto());
}
for (var log : this.getTraceLogs()) {
proto.addTraceLog(log.toProto());
}
for (var log : this.getHuntLogs()) {
proto.addHuntLog(log.toProto());
}
return proto;
}
}
@@ -0,0 +1,28 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.TraceHuntApply.TraceHuntApplyReq;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.trace_hunt_apply_req)
public class HandlerTraceHuntApplyReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse Request
var req = TraceHuntApplyReq.parseFrom(message);
// Hunt
boolean success = session.getPlayer().getTraceHuntManager().apply(req.getOwnerUID(), req.getBossID(), req.getBuildID());
if (!success) {
return session.encodeMsg(NetMsgId.trace_hunt_apply_failed_ack);
}
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_apply_succeed_ack);
}
}
@@ -0,0 +1,34 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.TraceHuntBossRewardReceive.TraceHuntBossRewardReceiveResp;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.trace_hunt_boss_reward_receive_req)
public class HandlerTraceHuntBossRewardReceiveReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Get manager
var manager = session.getPlayer().getTraceHuntManager();
// Claim reward
var change = manager.claimReward();
if (change == null) {
return session.encodeMsg(NetMsgId.trace_hunt_boss_reward_receive_failed_ack);
}
// Build response
var rsp = TraceHuntBossRewardReceiveResp.newInstance()
.setLevel(manager.getLevel())
.setExp(manager.getExp())
.setChangeInfo(change.toProto());
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_boss_reward_receive_succeed_ack, rsp);
}
}
@@ -0,0 +1,17 @@
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.trace_hunt_info_req)
public class HandlerTraceHuntInfoReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_info_succeed_ack, session.getPlayer().getTraceHuntManager().toProto());
}
}
@@ -0,0 +1,23 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.TraceHuntRecommend.TraceHuntRecommendResp;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.trace_hunt_recommend_req)
public class HandlerTraceHuntRecommendReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Build response
var rsp = TraceHuntRecommendResp.newInstance();
// TODO add other players
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_recommend_succeed_ack, rsp);
}
}
@@ -0,0 +1,52 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.TraceHuntSettle.TraceHuntSettleReq;
import emu.nebula.proto.TraceHuntSettle.TraceHuntSettleResp;
import emu.nebula.net.HandlerId;
import java.util.List;
import emu.nebula.game.tracehunt.TraceHuntLog;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.trace_hunt_settle_req)
public class HandlerTraceHuntSettleReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = TraceHuntSettleReq.parseFrom(message);
// Get manager
var manager = session.getPlayer().getTraceHuntManager();
// Hunt
var change = manager.settle(req.getScore(), req.getStar());
if (change == null) {
return session.encodeMsg(NetMsgId.trace_hunt_settle_failed_ack);
}
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Build response
var rsp = TraceHuntSettleResp.newInstance()
.setLevel(manager.getLevel())
.setExp(manager.getExp())
.setSelfHuntTimes(manager.getHuntCount())
.setBossCreateTime(manager.getBossCreateTime());
@SuppressWarnings("unchecked")
var logs = (List<TraceHuntLog>) change.getExtraData();
for (var log : logs) {
rsp.addHuntLog(log.toProto());
}
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_settle_succeed_ack, rsp);
}
}
@@ -0,0 +1,45 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.I32;
import emu.nebula.proto.TraceHuntTrace.TraceHuntTraceResp;
import emu.nebula.net.HandlerId;
import java.util.List;
import emu.nebula.game.tracehunt.TraceHuntLog;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.trace_hunt_trace_req)
public class HandlerTraceHuntTraceReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = I32.parseFrom(message);
// Trace
var change = session.getPlayer().getTraceHuntManager().trace(req.getValue());
// Sanity check
if (change == null) {
return session.encodeMsg(NetMsgId.trace_hunt_apply_failed_ack);
}
// Build response
var rsp = TraceHuntTraceResp.newInstance()
.setBossID(session.getPlayer().getTraceHuntManager().getBossId())
.setChangeInfo(change.toProto());
@SuppressWarnings("unchecked")
var logs = (List<TraceHuntLog>) change.getExtraData();
for (var log : logs) {
rsp.addTraceLog(log.toProto());
}
// Encode and send
return session.encodeMsg(NetMsgId.trace_hunt_apply_succeed_ack, rsp);
}
}