diff --git a/src/main/java/emu/nebula/GameConstants.java b/src/main/java/emu/nebula/GameConstants.java index 03b78aa..406dfd8 100644 --- a/src/main/java/emu/nebula/GameConstants.java +++ b/src/main/java/emu/nebula/GameConstants.java @@ -54,7 +54,14 @@ public class GameConstants { public static final int[] TOWER_EVENTS_IDS = new int[] { 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_WEEKLY = 2; public static final int REFRESH_TYPE_MONTHLY = 3; diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index a0106e8..c5cd757 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -139,6 +139,11 @@ public class GameData { @Getter private static DataTable ScoreBossControlDataTable = new DataTable<>(); @Getter private static DataTable ScoreBossRewardDataTable = new DataTable<>(); + // ===== Trace Hunt ===== + @Getter private static DataTable TraceHuntControlDataTable = new DataTable<>(); + @Getter private static DataTable TraceHuntLevelDataTable = new DataTable<>(); + @Getter private static DataTable TraceHuntSelfHuntExtraCostDataTable = new DataTable<>(); + // ===== Misc ===== @Getter private static DataTable WorldClassDataTable = new DataTable<>(); @Getter private static DataTable GuideGroupDataTable = new DataTable<>(); diff --git a/src/main/java/emu/nebula/data/resources/TraceHuntControlDef.java b/src/main/java/emu/nebula/data/resources/TraceHuntControlDef.java new file mode 100644 index 0000000..fec3d9d --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/TraceHuntControlDef.java @@ -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; + } +} diff --git a/src/main/java/emu/nebula/data/resources/TraceHuntLevelDef.java b/src/main/java/emu/nebula/data/resources/TraceHuntLevelDef.java new file mode 100644 index 0000000..fb06859 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/TraceHuntLevelDef.java @@ -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; + } +} diff --git a/src/main/java/emu/nebula/data/resources/TraceHuntSelfHuntExtraCostDef.java b/src/main/java/emu/nebula/data/resources/TraceHuntSelfHuntExtraCostDef.java new file mode 100644 index 0000000..4483f16 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/TraceHuntSelfHuntExtraCostDef.java @@ -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; + } +} diff --git a/src/main/java/emu/nebula/game/inventory/Inventory.java b/src/main/java/emu/nebula/game/inventory/Inventory.java index 7a3cea0..d853915 100644 --- a/src/main/java/emu/nebula/game/inventory/Inventory.java +++ b/src/main/java/emu/nebula/game/inventory/Inventory.java @@ -46,6 +46,7 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { private ItemParamMap shopBuyCount; private String2IntMap mallBuyCount; private String2IntMap mallPackageBuyCount; + /** * Tracks whether a MallGem pack has already consumed its maiden bonus. * 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); } } + 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 -> { // Not implemented } diff --git a/src/main/java/emu/nebula/game/player/Player.java b/src/main/java/emu/nebula/game/player/Player.java index 64ebc66..ad4eae8 100644 --- a/src/main/java/emu/nebula/game/player/Player.java +++ b/src/main/java/emu/nebula/game/player/Player.java @@ -29,6 +29,7 @@ import emu.nebula.game.quest.QuestManager; import emu.nebula.game.scoreboss.ScoreBossManager; import emu.nebula.game.story.StoryManager; import emu.nebula.game.tower.StarTowerManager; +import emu.nebula.game.tracehunt.TraceHuntManager; import emu.nebula.game.vampire.VampireSurvivorManager; import emu.nebula.net.GameSession; import emu.nebula.net.NetMsgId; @@ -110,6 +111,7 @@ public class Player implements GameDatabaseObject { private transient QuestManager questManager; private transient AchievementManager achievementManager; private transient AgentManager agentManager; + private transient TraceHuntManager traceHuntManager; private transient ActivityManager activityManager; // Extra @@ -814,6 +816,7 @@ public class Player implements GameDatabaseObject { this.questManager = this.loadManagerFromDatabase(QuestManager.class); this.achievementManager = this.loadManagerFromDatabase(AchievementManager.class); this.agentManager = this.loadManagerFromDatabase(AgentManager.class); + this.traceHuntManager = this.loadManagerFromDatabase(TraceHuntManager.class); this.activityManager = this.loadManagerFromDatabase(ActivityManager.class); // Database fixes @@ -1234,7 +1237,7 @@ public class Player implements GameDatabaseObject { state.getMutableStarTowerBook(); state.getMutableScoreBoss(); state.getMutableCharAffinityRewards(); - state.getMutableTraceHunt(); + state.getMutableTraceHunt().setBossRewardCanReceive(this.getTraceHuntManager().isHuntComplete()); // Force complete tutorials for (var guide : GameData.getGuideGroupDataTable()) { @@ -1307,8 +1310,13 @@ public class Player implements GameDatabaseObject { } // Trace hunt - proto.getMutableHuntPermit(); - proto.getMutableTraceRequest(); + proto.getMutableHuntPermit() + .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 return proto; diff --git a/src/main/java/emu/nebula/game/player/PlayerModule.java b/src/main/java/emu/nebula/game/player/PlayerModule.java index c4ce6c6..681ce3b 100644 --- a/src/main/java/emu/nebula/game/player/PlayerModule.java +++ b/src/main/java/emu/nebula/game/player/PlayerModule.java @@ -27,6 +27,7 @@ import emu.nebula.game.quest.QuestManager; import emu.nebula.game.scoreboss.ScoreBossRankEntry; import emu.nebula.game.story.StoryManager; import emu.nebula.game.tower.StarTowerBuild; +import emu.nebula.game.tracehunt.TraceHuntManager; import emu.nebula.net.GameSession; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -183,6 +184,7 @@ public class PlayerModule extends GameContextModule { datastore.getCollection(StoryManager.class).deleteOne(idFilter); datastore.getCollection(QuestManager.class).deleteOne(idFilter); datastore.getCollection(AgentManager.class).deleteOne(idFilter); + datastore.getCollection(TraceHuntManager.class).deleteOne(idFilter); datastore.getCollection(AchievementManager.class).deleteOne(idFilter); datastore.getCollection(ActivityManager.class).deleteOne(idFilter); diff --git a/src/main/java/emu/nebula/game/tracehunt/TraceHuntBoss.java b/src/main/java/emu/nebula/game/tracehunt/TraceHuntBoss.java new file mode 100644 index 0000000..4f48f32 --- /dev/null +++ b/src/main/java/emu/nebula/game/tracehunt/TraceHuntBoss.java @@ -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; + } +} diff --git a/src/main/java/emu/nebula/game/tracehunt/TraceHuntLog.java b/src/main/java/emu/nebula/game/tracehunt/TraceHuntLog.java new file mode 100644 index 0000000..a27613f --- /dev/null +++ b/src/main/java/emu/nebula/game/tracehunt/TraceHuntLog.java @@ -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; + } + +} diff --git a/src/main/java/emu/nebula/game/tracehunt/TraceHuntLogType.java b/src/main/java/emu/nebula/game/tracehunt/TraceHuntLogType.java new file mode 100644 index 0000000..ed02813 --- /dev/null +++ b/src/main/java/emu/nebula/game/tracehunt/TraceHuntLogType.java @@ -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 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); + } +} diff --git a/src/main/java/emu/nebula/game/tracehunt/TraceHuntManager.java b/src/main/java/emu/nebula/game/tracehunt/TraceHuntManager.java new file mode 100644 index 0000000..a6f57e4 --- /dev/null +++ b/src/main/java/emu/nebula/game/tracehunt/TraceHuntManager.java @@ -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 traceLogs; + private List huntLogs; + + // Current hunt + private transient int huntPlayerUid; + private transient int huntBossId; + private long buildId; + + // Collection + private Map 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(); + + 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(); + + // 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; + } +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntApplyReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntApplyReq.java new file mode 100644 index 0000000..07ab86b --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntApplyReq.java @@ -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); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntBossRewardReceiveReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntBossRewardReceiveReq.java new file mode 100644 index 0000000..0510850 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntBossRewardReceiveReq.java @@ -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); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntInfoReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntInfoReq.java new file mode 100644 index 0000000..e0f00db --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntInfoReq.java @@ -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()); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntRecommendReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntRecommendReq.java new file mode 100644 index 0000000..5ddff1f --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntRecommendReq.java @@ -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); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntSettleReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntSettleReq.java new file mode 100644 index 0000000..3f0a264 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntSettleReq.java @@ -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) change.getExtraData(); + for (var log : logs) { + rsp.addHuntLog(log.toProto()); + } + + // Encode and send + return session.encodeMsg(NetMsgId.trace_hunt_settle_succeed_ack, rsp); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntTraceReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntTraceReq.java new file mode 100644 index 0000000..f4170fa --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTraceHuntTraceReq.java @@ -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) change.getExtraData(); + for (var log : logs) { + rsp.addTraceLog(log.toProto()); + } + + // Encode and send + return session.encodeMsg(NetMsgId.trace_hunt_apply_succeed_ack, rsp); + } + +}