diff --git a/src/main/java/emu/nebula/game/character/Character.java b/src/main/java/emu/nebula/game/character/Character.java index a65fe3b..ea49d40 100644 --- a/src/main/java/emu/nebula/game/character/Character.java +++ b/src/main/java/emu/nebula/game/character/Character.java @@ -34,6 +34,7 @@ import emu.nebula.proto.PublicStarTower.StarTowerCharGem; import emu.nebula.util.Bitset; import it.unimi.dsi.fastutil.ints.IntArrayList; import lombok.Getter; +import us.hebi.quickbuf.RepeatedInt; @Getter @Entity(value = "characters", useDiscriminator = false) @@ -394,7 +395,28 @@ public class Character implements GameDatabaseObject { return true; } - public CharacterGem getGem(CharacterGemPreset preset, int slotId) { + public boolean renameGemPreset(int index, String name) { + // Sanity check + if (index < 0 || index >= GameConstants.CHARACTER_MAX_GEM_PRESETS) { + return false; + } + + if (name == null || name.length() > 32) { + return false; + } + + // Rename preset + var preset = this.getGemPreset(index); + preset.setName(name); + + // Update to database + this.save(); + + // Success + return true; + } + + public CharacterGem getGemFromPreset(CharacterGemPreset preset, int slotId) { // Get gem index int gemIndex = preset.getGemIndex(slotId - 1); @@ -413,6 +435,19 @@ public class Character implements GameDatabaseObject { return slot.getGem(gemIndex); } + public CharacterGem getGemFromSlot(int slotId, int gemIndex) { + // Check if gem slot exists + if (!this.hasGemSlot(slotId)) { + return null; + } + + // Get gem from gem slot + var slot = this.getGemSlot(slotId); + var gem = slot.getGem(gemIndex); + + return gem; + } + public boolean equipGem(int presetIndex, int slotId, int gemIndex) { // Sanity check if (presetIndex < 0 || presetIndex >= GameConstants.CHARACTER_MAX_GEM_PRESETS) { @@ -461,6 +496,21 @@ public class Character implements GameDatabaseObject { return this.gemSlots[index]; } + + public boolean lockGem(int slotId, int gemIndex, boolean lock) { + // Get gem from slot + var gem = this.getGemFromSlot(slotId, gemIndex); + if (gem == null) return false; + + // Lock + gem.setLocked(lock); + + // Save to database + this.save(); + + // Success + return true; + } public synchronized PlayerChangeInfo generateGem(int slotId) { // Get gem slot @@ -508,6 +558,59 @@ public class Character implements GameDatabaseObject { return change; } + public synchronized PlayerChangeInfo refreshGem(int slotId, int gemIndex, RepeatedInt lockedAttributes) { + // Get gem from slot + var gem = this.getGemFromSlot(slotId, gemIndex); + if (gem == null) return null; + + // Get gem data + var gemData = this.getData().getCharGemData(slotId); + var gemControl = gemData.getControlData(); + + // Check character level + if (this.getLevel() < gemControl.getUnlockLevel()) { + return null; + } + + // Make sure the player has the materials to craft the emblem + if (!getPlayer().getInventory().hasItem(gemData.getRefreshCostTid(), gemControl.getRefreshCostQty())) { + return null; + } + + // Generate attributes and create gem + var attributes = gemControl.generateAttributes(); + gem.setNewAttributes(attributes); + + // Save to database + this.save(); + + // Consume materials + var change = getPlayer().getInventory().removeItem(gemData.getRefreshCostTid(), gemControl.getRefreshCostQty()); + + // Set change info extra info + change.setExtraData(gem); + + // Success + return change; + } + + public boolean replaceGemAttributes(int slotId, int gemIndex) { + // Get gem from slot + var gem = this.getGemFromSlot(slotId, gemIndex); + if (gem == null) return false; + + // Replace attributes with altered ones + boolean success = gem.replaceAttributes(); + + // Save to database + if (success) { + this.save(); + } + + // Success + return success; + } + // Proto public Char toProto() { @@ -566,7 +669,7 @@ public class Character implements GameDatabaseObject { var preset = this.getCurrentGemPreset(); for (int i = 1; i <= preset.getLength(); i++) { - var gem = this.getGem(preset, i); + var gem = this.getGemFromPreset(preset, i); var info = StarTowerCharGem.newInstance() .setSlotId(i); diff --git a/src/main/java/emu/nebula/game/character/CharacterGem.java b/src/main/java/emu/nebula/game/character/CharacterGem.java index 5d6219d..f88a00d 100644 --- a/src/main/java/emu/nebula/game/character/CharacterGem.java +++ b/src/main/java/emu/nebula/game/character/CharacterGem.java @@ -25,6 +25,34 @@ public class CharacterGem { public void setLocked(boolean locked) { this.locked = locked; } + + public void setNewAttributes(IntList attributes) { + this.alterAttributes = attributes.toIntArray(); + } + + public boolean hasAlterAttributes() { + for (int i = 0; i < this.alterAttributes.length; i++) { + if (this.alterAttributes[i] <= 0) { + return false; + } + } + + return true; + } + + public boolean replaceAttributes() { + // Make sure gem has alter attributes + if (!this.hasAlterAttributes()) { + return false; + } + + // Replace attributes + this.attributes = this.alterAttributes; + this.alterAttributes = new int[4]; + + // Success + return true; + } // Proto diff --git a/src/main/java/emu/nebula/game/character/CharacterGemPreset.java b/src/main/java/emu/nebula/game/character/CharacterGemPreset.java index 4b45c63..1c2e123 100644 --- a/src/main/java/emu/nebula/game/character/CharacterGemPreset.java +++ b/src/main/java/emu/nebula/game/character/CharacterGemPreset.java @@ -19,6 +19,10 @@ public class CharacterGemPreset { this.gems = new int[] {-1, -1, -1}; } + public void setName(String name) { + this.name = name; + } + public int getLength() { return this.getGems().length; } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java new file mode 100644 index 0000000..55af244 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java @@ -0,0 +1,44 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemRefresh.CharGemRefreshReq; +import emu.nebula.proto.CharGemRefresh.CharGemRefreshResp; +import emu.nebula.net.HandlerId; +import emu.nebula.game.character.CharacterGem; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_refresh_req) +public class HandlerCharGemRefreshReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemRefreshReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_refresh_failed_ack); + } + + // Refresh gem attributes + var change = character.refreshGem(req.getSlotId(), req.getGemIndex(), req.getLockAttrs()); + + if (change == null) { + return session.encodeMsg(NetMsgId.char_gem_refresh_failed_ack); + } + + var gem = (CharacterGem) change.getExtraData(); + + // Build response + var rsp = CharGemRefreshResp.newInstance() + .setChangeInfo(change.toProto()) + .addAllAttributes(gem.getAlterAttributes()); + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_refresh_succeed_ack, rsp); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemRenamePresetReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRenamePresetReq.java new file mode 100644 index 0000000..13ae5ca --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRenamePresetReq.java @@ -0,0 +1,35 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemRenamePreset.CharGemRenamePresetReq; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_rename_preset_req) +public class HandlerCharGemRenamePresetReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemRenamePresetReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_rename_preset_failed_ack); + } + + // Rename + boolean success = character.renameGemPreset(req.getPresetId(), req.getNewName()); + + if (success == false) { + return session.encodeMsg(NetMsgId.char_gem_rename_preset_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_rename_preset_succeed_ack); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemReplaceAttributeReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemReplaceAttributeReq.java new file mode 100644 index 0000000..02cae4c --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemReplaceAttributeReq.java @@ -0,0 +1,35 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemReplaceAttribute.CharGemReplaceAttributeReq; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_replace_attribute_req) +public class HandlerCharGemReplaceAttributeReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemReplaceAttributeReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_replace_attribute_failed_ack); + } + + // Replace attributes + boolean success = character.replaceGemAttributes(req.getSlotId(), req.getGemIndex()); + + if (success == false) { + return session.encodeMsg(NetMsgId.char_gem_replace_attribute_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_replace_attribute_succeed_ack); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemUpdateGemLockStatusReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemUpdateGemLockStatusReq.java new file mode 100644 index 0000000..86b2b3f --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemUpdateGemLockStatusReq.java @@ -0,0 +1,35 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemUpdateGemLockStatus.CharGemUpdateGemLockStatusReq; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_update_gem_lock_status_req) +public class HandlerCharGemUpdateGemLockStatusReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemUpdateGemLockStatusReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_update_gem_lock_status_failed_ack); + } + + // Lock gem + boolean success = character.lockGem(req.getSlotId(), req.getGemIndex(), req.getLock()); + + if (success == false) { + return session.encodeMsg(NetMsgId.char_gem_update_gem_lock_status_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_update_gem_lock_status_succeed_ack); + } + +}