diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index d705cba..abd75fb 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -99,6 +99,7 @@ public class GameData { // Star tower @Getter private static DataTable StarTowerDataTable = new DataTable<>(); @Getter private static DataTable StarTowerStageDataTable = new DataTable<>(); + @Getter private static DataTable StarTowerGrowthNodeDataTable = new DataTable<>(); @Getter private static DataTable PotentialDataTable = new DataTable<>(); @Getter private static DataTable SubNoteSkillPromoteGroupDataTable = new DataTable<>(); diff --git a/src/main/java/emu/nebula/data/resources/StarTowerGrowthNodeDef.java b/src/main/java/emu/nebula/data/resources/StarTowerGrowthNodeDef.java new file mode 100644 index 0000000..8dfef28 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/StarTowerGrowthNodeDef.java @@ -0,0 +1,21 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.ResourceType; +import lombok.Getter; + +@Getter +@ResourceType(name = "StarTowerGrowthNode.json") +public class StarTowerGrowthNodeDef extends BaseDef { + private int Id; + private int NodeId; + private int Group; + + private int ItemId1; + private int ItemQty1; + + @Override + public int getId() { + return Id; + } +} diff --git a/src/main/java/emu/nebula/game/player/PlayerProgress.java b/src/main/java/emu/nebula/game/player/PlayerProgress.java index 08d3772..306c0b5 100644 --- a/src/main/java/emu/nebula/game/player/PlayerProgress.java +++ b/src/main/java/emu/nebula/game/player/PlayerProgress.java @@ -5,6 +5,7 @@ import java.util.Map; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Id; +import dev.morphia.annotations.PostLoad; import emu.nebula.Nebula; import emu.nebula.data.GameData; import emu.nebula.database.GameDatabaseObject; @@ -32,6 +33,7 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject // Star Tower private IntSet starTowerLog; + private int[] starTowerGrowth; // Instances private Int2IntMap dailyInstanceLog; @@ -64,6 +66,7 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject // Star Tower this.starTowerLog = new IntOpenHashSet(); + this.starTowerGrowth = new int[3]; // Instances this.dailyInstanceLog = new Int2IntOpenHashMap(); @@ -100,6 +103,25 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject Nebula.getGameDatabase().addToSet(this, this.getUid(), "starTowerLog", id); } + public boolean setStarTowerGrowthNode(int group, int nodeId) { + // Get index + int index = group - 1; + if (index < 0) return false; + + // Grow growth if its too small + if (index >= this.starTowerGrowth.length) { + var old = this.starTowerGrowth; + this.starTowerGrowth = new int[index + 1]; + System.arraycopy(old, 0, this.starTowerGrowth, 0, old.length); + } + + // Set + this.starTowerGrowth[index] |= (1 << nodeId); + + // Success + return true; + } + public void addInfinityArenaLog(int levelId) { // Calculate arena id int id = (int) Math.floor(levelId / 10000D); @@ -234,4 +256,13 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject proto.addTutorialLevels(tutorial.toProto()); } } + + // Database fix + + @PostLoad + public void postLoad() { + if (this.starTowerGrowth == null) { + this.starTowerGrowth = new int[1]; + } + } } diff --git a/src/main/java/emu/nebula/game/tower/StarTowerManager.java b/src/main/java/emu/nebula/game/tower/StarTowerManager.java index fa648b8..e98a90b 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerManager.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerManager.java @@ -2,12 +2,14 @@ package emu.nebula.game.tower; import emu.nebula.Nebula; import emu.nebula.data.GameData; +import emu.nebula.data.resources.StarTowerGrowthNodeDef; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.game.player.PlayerManager; +import emu.nebula.game.player.PlayerProgress; import emu.nebula.game.quest.QuestCondType; import emu.nebula.proto.StarTowerApply.StarTowerApplyReq; - +import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -26,6 +28,121 @@ public class StarTowerManager extends PlayerManager { super(player); } + public PlayerProgress getProgress() { + return this.getPlayer().getProgress(); + } + + // Growth nodes (talents/research) + + public boolean hasGrowthNode(int id) { + // Get growth node data + var data = GameData.getStarTowerGrowthNodeDataTable().get(id); + if (data == null) return false; + + // Check if bit is set + return hasGrowthNode(data); + } + + public boolean hasGrowthNode(StarTowerGrowthNodeDef data) { + // Get current growth nodes + var growth = getPlayer().getProgress().getStarTowerGrowth(); + + // Get group index + int groupIndex = data.getGroup() - 1; + if (groupIndex >= growth.length) { + return false; + } + + // Get nodes bits + int nodes = growth[groupIndex]; + int test = (1 << data.getNodeId()); + + // Check if bit is set + return (nodes & test) != 0; + } + + public PlayerChangeInfo unlockGrowthNode(int id) { + // Get growth node data + var data = GameData.getStarTowerGrowthNodeDataTable().get(id); + if (data == null) return null; + + // Make sure node is not already set + if (this.hasGrowthNode(data)) { + return null; + } + + // Check if we have the required items to unlock + if (!getPlayer().getInventory().hasItem(data.getItemId1(), data.getItemQty1())) { + return null; + } + + // Set node + this.getProgress().setStarTowerGrowthNode(data.getGroup(), data.getNodeId()); + + // Save to database + Nebula.getGameDatabase().update( + this.getProgress(), + this.getPlayerUid(), + "starTowerGrowth", + this.getProgress().getStarTowerGrowth() + ); + + // Remove items + return getPlayer().getInventory().removeItem(data.getItemId1(), data.getItemQty1()); + } + + public PlayerChangeInfo unlockGrowthNodeGroup(int group) { + // Create variables + var change = new PlayerChangeInfo(); + var unlocked = new IntArrayList(); + + // Filter data + for (var data : GameData.getStarTowerGrowthNodeDataTable()) { + // Filter out nodes that are not from our group + if (data.getGroup() != group) { + continue; + } + + // Filter out set growth nodes + if (this.hasGrowthNode(data)) { + continue; + } + + // Check if we have the required items to unlock + if (!getPlayer().getInventory().hasItem(data.getItemId1(), data.getItemQty1())) { + continue; + } + + // Set node + this.getProgress().setStarTowerGrowthNode(data.getGroup(), data.getNodeId()); + + // Remove items + getPlayer().getInventory().removeItem(data.getItemId1(), data.getItemQty1()); + + // Add to unlocked list + unlocked.add(data.getId()); + } + + // Save to database if any nodes were unlocked + if (unlocked.size() > 0) { + // Save to database + Nebula.getGameDatabase().update( + this.getProgress(), + this.getPlayerUid(), + "starTowerGrowth", + this.getProgress().getStarTowerGrowth() + ); + } + + // Set unlocked list + change.setExtraData(unlocked); + + // Return change + return change; + } + + // Builds + public Long2ObjectMap getBuilds() { if (this.builds == null) { this.loadFromDatabase(); diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthDetailReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthDetailReq.java index c5320a3..f4be4c7 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthDetailReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthDetailReq.java @@ -2,6 +2,7 @@ package emu.nebula.server.handlers; import emu.nebula.net.NetHandler; import emu.nebula.net.NetMsgId; +import emu.nebula.proto.TowerGrowthDetail.TowerGrowthDetailResp; import emu.nebula.net.HandlerId; import emu.nebula.net.GameSession; @@ -10,7 +11,12 @@ public class HandlerTowerGrowthDetailReq extends NetHandler { @Override public byte[] handle(GameSession session, byte[] message) throws Exception { - return session.encodeMsg(NetMsgId.tower_growth_detail_succeed_ack); + // Build response + var rsp = TowerGrowthDetailResp.newInstance() + .addAllDetail(session.getPlayer().getProgress().getStarTowerGrowth()); + + // Encode and send + return session.encodeMsg(NetMsgId.tower_growth_detail_succeed_ack, rsp); } } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthGroupNodeUnlockReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthGroupNodeUnlockReq.java new file mode 100644 index 0000000..c6be2f7 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthGroupNodeUnlockReq.java @@ -0,0 +1,41 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.Public.UI32; +import emu.nebula.proto.TowerGrowthGroupNodeUnlock.TowerGrowthGroupNodeUnlockResp; +import it.unimi.dsi.fastutil.ints.IntList; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.tower_growth_group_node_unlock_req) +public class HandlerTowerGrowthGroupNodeUnlockReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = UI32.parseFrom(message); + + // Quick unlock + var change = session.getPlayer().getStarTowerManager().unlockGrowthNodeGroup(req.getValue()); + + if (change == null) { + session.encodeMsg(NetMsgId.tower_growth_group_node_unlock_failed_ack); + } + + // Get list of unlocked nodes + var unlocked = (IntList) change.getExtraData(); + + // Build response + var rsp = TowerGrowthGroupNodeUnlockResp.newInstance() + .setChangeInfo(change.toProto()); + + for (int nodeId : unlocked) { + rsp.addNodes(nodeId); + } + + // Encode and send + return session.encodeMsg(NetMsgId.tower_growth_group_node_unlock_succeed_ack, rsp); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthNodeUnlockReq.java b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthNodeUnlockReq.java new file mode 100644 index 0000000..025f309 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerTowerGrowthNodeUnlockReq.java @@ -0,0 +1,28 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.Public.UI32; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.tower_growth_node_unlock_req) +public class HandlerTowerGrowthNodeUnlockReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = UI32.parseFrom(message); + + // Unlock tower growth node + var change = session.getPlayer().getStarTowerManager().unlockGrowthNode(req.getValue()); + + if (change == null) { + return session.encodeMsg(NetMsgId.tower_growth_node_unlock_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.tower_growth_node_unlock_succeed_ack, change.toProto()); + } + +}