diff --git a/src/main/java/emu/nebula/GameConstants.java b/src/main/java/emu/nebula/GameConstants.java index aada45d..6fb36ba 100644 --- a/src/main/java/emu/nebula/GameConstants.java +++ b/src/main/java/emu/nebula/GameConstants.java @@ -22,6 +22,10 @@ public class GameConstants { public static final int MAX_ENERGY = 240; public static final int ENERGY_REGEN_TIME = 360; // Seconds + public static final int CHARACTER_MAX_GEMS_PER_SLOT = 4; + public static final int CHARACTER_MAX_GEM_PRESETS = 3; + public static final int CHARACTER_MAX_GEM_SLOTS = 3; + public static final int MAX_FORMATIONS = 5; public static final int MAX_SHOWCASE_IDS = 5; diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index e0b7ffc..d705cba 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -28,6 +28,12 @@ public class GameData { @Getter private static DataTable TalentGroupDataTable = new DataTable<>(); @Getter private static DataTable TalentDataTable = new DataTable<>(); + @Getter private static DataTable CharGemDataTable = new DataTable<>(); + @Getter private static DataTable CharGemSlotControlDataTable = new DataTable<>(); + @Getter private static DataTable CharGemAttrGroupDataTable = new DataTable<>(); + @Getter private static DataTable CharGemAttrTypeDataTable = new DataTable<>(); + @Getter private static DataTable CharGemAttrValueDataTable = new DataTable<>(); + @Getter private static DataTable ChatDataTable = new DataTable<>(); // Discs diff --git a/src/main/java/emu/nebula/data/resources/CharGemAttrGroupDef.java b/src/main/java/emu/nebula/data/resources/CharGemAttrGroupDef.java new file mode 100644 index 0000000..6355436 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/CharGemAttrGroupDef.java @@ -0,0 +1,79 @@ +package emu.nebula.data.resources; + +import java.util.List; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import emu.nebula.data.ResourceType.LoadPriority; +import emu.nebula.util.JsonUtils; +import emu.nebula.util.WeightedList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import lombok.Getter; + +@Getter +@ResourceType(name = "CharGemAttrGroup.json", loadPriority = LoadPriority.HIGH) +public class CharGemAttrGroupDef extends BaseDef { + private int GroupId; + private int GroupType; + private int Weight; + private String UniqueAttrNumWeight; + + private transient WeightedList uniqueAttrNum; + private transient List attributeTypes; + + @Override + public int getId() { + return GroupId; + } + + public int getRandomUniqueAttrNum() { + if (this.uniqueAttrNum == null) { + return 0; + } + + return this.uniqueAttrNum.next(); + } + + public CharGemAttrTypeDef getRandomAttributeType(IntList list) { + // Setup blacklist to prevent the same attribute from showing up twice + var blacklist = new IntOpenHashSet(); + + for (int id : list) { + var value = GameData.getCharGemAttrValueDataTable().get(id); + if (value == null) continue; + + int blacklistId = value.getTypeId(); + blacklist.add(blacklistId); + } + + // Create random generator + var random = new WeightedList(); + + for (var type : this.getAttributeTypes()) { + if (blacklist.contains(type.getId())) { + continue; + } + + random.add(100, type); + } + + return random.next(); + } + + @Override + public void onLoad() { + this.uniqueAttrNum = new WeightedList<>(); + this.attributeTypes = new ObjectArrayList<>(); + + if (this.UniqueAttrNumWeight != null) { + var json = JsonUtils.decodeMap(this.UniqueAttrNumWeight, Integer.class, Integer.class); + + for (var entry : json.entrySet()) { + this.uniqueAttrNum.add(entry.getValue(), entry.getKey()); + } + } + } +} diff --git a/src/main/java/emu/nebula/data/resources/CharGemAttrTypeDef.java b/src/main/java/emu/nebula/data/resources/CharGemAttrTypeDef.java new file mode 100644 index 0000000..a2a9bbe --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/CharGemAttrTypeDef.java @@ -0,0 +1,39 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import emu.nebula.util.WeightedList; +import lombok.Getter; + +@Getter +@ResourceType(name = "CharGemAttrType.json") +public class CharGemAttrTypeDef extends BaseDef { + private int Id; + private int GroupId; + + private transient WeightedList values; + + @Override + public int getId() { + return Id; + } + + public CharGemAttrValueDef getRandomValueData() { + return this.getValues().next(); + } + + public int getRandomValue() { + return this.getRandomValueData().getId(); + } + + @Override + public void onLoad() { + this.values = new WeightedList<>(); + + var data = GameData.getCharGemAttrGroupDataTable().get(this.GroupId); + if (data != null) { + data.getAttributeTypes().add(this); + } + } +} diff --git a/src/main/java/emu/nebula/data/resources/CharGemAttrValueDef.java b/src/main/java/emu/nebula/data/resources/CharGemAttrValueDef.java new file mode 100644 index 0000000..83c65c5 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/CharGemAttrValueDef.java @@ -0,0 +1,31 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import emu.nebula.data.ResourceType.LoadPriority; +import lombok.Getter; + +@Getter +@ResourceType(name = "CharGemAttrValue.json", loadPriority = LoadPriority.LOW) +public class CharGemAttrValueDef extends BaseDef { + private int Id; + private int TypeId; + private int AttrType; + private int AttrTypeFirstSubtype; + private int AttrTypeSecondSubtype; + private int Rarity; + + @Override + public int getId() { + return Id; + } + + @Override + public void onLoad() { + var data = GameData.getCharGemAttrTypeDataTable().get(this.TypeId); + if (data != null) { + data.getValues().add(this.getRarity(), this); + } + } +} diff --git a/src/main/java/emu/nebula/data/resources/CharGemDef.java b/src/main/java/emu/nebula/data/resources/CharGemDef.java new file mode 100644 index 0000000..57b09e7 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/CharGemDef.java @@ -0,0 +1,24 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import lombok.Getter; + +@Getter +@ResourceType(name = "CharGem.json") +public class CharGemDef extends BaseDef { + private int Id; + private int GenerateCostTid; + private int RefreshCostTid; + private int Type; + + @Override + public int getId() { + return Id; + } + + public CharGemSlotControlDef getControlData() { + return GameData.getCharGemSlotControlDataTable().get(this.Type); + } +} diff --git a/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java b/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java new file mode 100644 index 0000000..8eaf209 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java @@ -0,0 +1,78 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import emu.nebula.util.WeightedList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import lombok.Getter; + +@Getter +@ResourceType(name = "CharGemSlotControl.json") +public class CharGemSlotControlDef extends BaseDef { + private int Id; + private int Position; + private int MaxAlterNum; + private int UnlockLevel; + + private int GeneratenCostQty; + private int RefreshCostQty; + + private int UniqueAttrGroupProb; + private int UniqueAttrGroupId; + private int GuaranteeCount; + + private int[] AttrGroupId; + + private int LockableNum; + private int LockItemTid; + private int LockItemQty; + + @Override + public int getId() { + return Id; + } + + public IntList generateAttributes() { + // Generate list of attributes + var list = new IntArrayList(); + + // Add unique attributes + if (this.UniqueAttrGroupId > 0) { + var group = GameData.getCharGemAttrGroupDataTable().get(this.UniqueAttrGroupId); + int num = group.getRandomUniqueAttrNum(); + + for (int i = 0; i < num; i++) { + var attributeType = group.getRandomAttributeType(list); + list.add(attributeType.getRandomValue()); + } + + if (list.size() >= 4) { + return list; + } + } + + // Get random attributes + var random = new WeightedList(); + + for (var groupId : this.AttrGroupId) { + var group = GameData.getCharGemAttrGroupDataTable().get(groupId); + if (group == null || group.getWeight() == 0) { + continue; + } + + random.add(group.getWeight(), group); + } + + // Add up to 4 attributes + while (list.size() < 4) { + var group = random.next(); + var attributeType = group.getRandomAttributeType(list); + list.add(attributeType.getRandomValue()); + } + + // Complete + return list; + } +} diff --git a/src/main/java/emu/nebula/data/resources/CharacterDef.java b/src/main/java/emu/nebula/data/resources/CharacterDef.java index 33c719e..2bdc228 100644 --- a/src/main/java/emu/nebula/data/resources/CharacterDef.java +++ b/src/main/java/emu/nebula/data/resources/CharacterDef.java @@ -3,6 +3,7 @@ package emu.nebula.data.resources; import java.util.List; import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; import emu.nebula.data.ResourceType; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.Getter; @@ -24,6 +25,8 @@ public class CharacterDef extends BaseDef { private int FragmentsId; private int TransformQty; + private int[] GemSlots; + private transient List chats; @Override @@ -39,6 +42,11 @@ public class CharacterDef extends BaseDef { return this.SkillsUpgradeGroup[index]; } + public CharGemDef getCharGemData(int slotId) { + int id = this.GemSlots[slotId - 1]; + return GameData.getCharGemDataTable().get(id); + } + @Override public void onLoad() { this.chats = new ObjectArrayList<>(); diff --git a/src/main/java/emu/nebula/game/character/Character.java b/src/main/java/emu/nebula/game/character/Character.java index b22ae42..a65fe3b 100644 --- a/src/main/java/emu/nebula/game/character/Character.java +++ b/src/main/java/emu/nebula/game/character/Character.java @@ -1,5 +1,8 @@ package emu.nebula.game.character; +import java.util.ArrayList; +import java.util.List; + import org.bson.Document; import org.bson.types.Binary; import org.bson.types.ObjectId; @@ -7,6 +10,7 @@ import org.bson.types.ObjectId; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Id; import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.PostLoad; import dev.morphia.annotations.PreLoad; import emu.nebula.GameConstants; import emu.nebula.Nebula; @@ -49,9 +53,14 @@ public class Character implements GameDatabaseObject { private int skin; private int[] skills; private Bitset talents; - private CharacterContact contact; private long createTime; + private int gemPresetIndex; + private List gemPresets; + private CharacterGemSlot[] gemSlots; + + private CharacterContact contact; + @Deprecated // Morphia only! public Character() { @@ -66,12 +75,13 @@ public class Character implements GameDatabaseObject { this.playerUid = player.getUid(); this.charId = data.getId(); this.data = data; - this.createTime = Nebula.getCurrentTime(); this.level = 1; this.skin = data.getDefaultSkinId(); this.skills = new int[] {1, 1, 1, 1, 1}; this.talents = new Bitset(); + this.createTime = Nebula.getCurrentTime(); + this.contact = new CharacterContact(this); } @@ -352,6 +362,152 @@ public class Character implements GameDatabaseObject { return true; } + // Gems + + public boolean hasGemPreset(int index) { + return index >= 0 && index < this.getGemPresets().size(); + } + + public CharacterGemPreset getCurrentGemPreset() { + return this.getGemPreset(this.getGemPresetIndex()); + } + + public CharacterGemPreset getGemPreset(int presetIndex) { + while (this.getGemPresetIndex() >= this.getGemPresets().size()) { + this.getGemPresets().add(new CharacterGemPreset(this)); + } + + return this.getGemPresets().get(presetIndex); + } + + public boolean setCurrentGemPreset(int index) { + // Sanity check + if (index < 0 || index >= GameConstants.CHARACTER_MAX_GEM_PRESETS) { + return false; + } + + // Set current preset and save to database + this.gemPresetIndex = index; + this.save(); + + // Success + return true; + } + + public CharacterGem getGem(CharacterGemPreset preset, int slotId) { + // Get gem index + int gemIndex = preset.getGemIndex(slotId - 1); + + if (gemIndex <= 0) { + return null; + } + + // Get gem slot + var slot = this.getGemSlot(slotId); + + if (slot == null) { + return null; + } + + // Get gem from the slot using preset index + return slot.getGem(gemIndex); + } + + public boolean equipGem(int presetIndex, int slotId, int gemIndex) { + // Sanity check + if (presetIndex < 0 || presetIndex >= GameConstants.CHARACTER_MAX_GEM_PRESETS) { + return false; + } + + // Get preset + var preset = this.getGemPreset(presetIndex); + + // Set gem index in preset + boolean success = preset.setGemIndex(slotId, gemIndex); + + // Save if successful + if (success) { + this.save(); + } + + return success; + } + + public boolean hasGemSlot(int slotId) { + // Calculate index from slot id + int index = slotId - 1; + + // Sanity check + if (index < 0 || index >= this.getGemSlots().length) { + return false; + } + + return this.gemSlots[index] != null; + } + + public CharacterGemSlot getGemSlot(int slotId) { + // Calculate index from slot id + int index = slotId - 1; + + // Sanity check + if (index < 0 || index >= this.getGemSlots().length) { + return null; + } + + // Create gem slot object if it doesnt exist + if (this.gemSlots[index] == null) { + this.gemSlots[index] = new CharacterGemSlot(slotId); + } + + return this.gemSlots[index]; + } + + public synchronized PlayerChangeInfo generateGem(int slotId) { + // Get gem slot + var slot = this.getGemSlot(slotId); + if (slot == null) { + return null; + } + + // Skip if slot is full + if (slot.isFull()) { + 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.getGenerateCostTid(), gemControl.getGeneratenCostQty())) { + return null; + } + + // Generate attributes and create gem + var attributes = gemControl.generateAttributes(); + var gem = new CharacterGem(attributes); + + // Add gem to slot + slot.getGems().add(gem); + + // Save to database + this.save(); + + // Consume materials + var change = getPlayer().getInventory().removeItem(gemData.getGenerateCostTid(), gemControl.getGeneratenCostQty()); + + // Set change info extra info + change.setExtraData(gem); + + // Success + return change; + } + // Proto public Char toProto() { @@ -363,24 +519,36 @@ public class Character implements GameDatabaseObject { .setTalentNodes(this.getTalents().toByteArray()) .addAllSkillLvs(this.getSkills()) .setCreateTime(this.getCreateTime()); - + + // Encode gem presets var gemPresets = proto.getMutableCharGemPresets() - .getMutableCharGemPresets(); + .setInUsePresetIndex(this.getGemPresetIndex()) + .getMutableCharGemPresets(); - for (int i = 0; i < 3; i++) { - var preset = CharGemPreset.newInstance() - .addAllSlotGem(-1, -1, -1); + for (int i = 0; i < GameConstants.CHARACTER_MAX_GEM_PRESETS; i++) { + CharGemPreset info = null; + + if (this.hasGemPreset(i)) { + info = getGemPresets().get(i).toProto(); + } else { + info = CharGemPreset.newInstance() + .addAllSlotGem(-1, -1, -1); + } - gemPresets.add(preset); + gemPresets.add(info); } - for (int i = 1; i <= 3; i++) { - var slot = CharGemSlot.newInstance() - .setId(i); - - proto.addCharGemSlots(slot); + // Encode gems + for (int i = 1; i <= GameConstants.CHARACTER_MAX_GEM_SLOTS; i++) { + if (this.hasGemSlot(i)) { + var slot = this.getGemSlot(i); + proto.addCharGemSlots(slot.toProto()); + } else { + proto.addCharGemSlots(CharGemSlot.newInstance().setId(i)); + } } + // Affinity quests proto.getMutableAffinityQuests(); return proto; @@ -394,12 +562,21 @@ public class Character implements GameDatabaseObject { .setTalentNodes(this.getTalents().toByteArray()) .addAllSkillLvs(this.getSkills()); - for (int i = 1; i <= 3; i++) { - var slot = StarTowerCharGem.newInstance() - .setSlotId(i) - .addAllAttributes(new int[] {0, 0, 0, 0}); + // Encode gems + var preset = this.getCurrentGemPreset(); + + for (int i = 1; i <= preset.getLength(); i++) { + var gem = this.getGem(preset, i); + var info = StarTowerCharGem.newInstance() + .setSlotId(i); - proto.addGems(slot); + if (gem != null) { + info.addAllAttributes(gem.getAttributes()); + } else { + info.addAllAttributes(new int[] {0, 0, 0, 0}); + } + + proto.addGems(info); } return proto; @@ -408,11 +585,24 @@ public class Character implements GameDatabaseObject { // Database fix @PreLoad - public void onLoad(Document doc) { + public void preLoad(Document doc) { var talents = doc.get("talents"); if (talents != null && talents.getClass() == Binary.class) { doc.remove("talents"); this.talents = new Bitset(); } } + + @PostLoad + public void postLoad() { + if (this.gemSlots == null) { + // Create gem slots array if it didn't exist + this.gemSlots = new CharacterGemSlot[GameConstants.CHARACTER_MAX_GEM_SLOTS]; + } + + if (this.gemPresets == null) { + // Create gem presets list if it didn't exist + this.gemPresets = new ArrayList<>(); + } + } } diff --git a/src/main/java/emu/nebula/game/character/CharacterGem.java b/src/main/java/emu/nebula/game/character/CharacterGem.java new file mode 100644 index 0000000..5d6219d --- /dev/null +++ b/src/main/java/emu/nebula/game/character/CharacterGem.java @@ -0,0 +1,39 @@ +package emu.nebula.game.character; + +import dev.morphia.annotations.Entity; +import emu.nebula.proto.Public.CharGem; +import it.unimi.dsi.fastutil.ints.IntList; +import lombok.Getter; + +@Getter +@Entity(useDiscriminator = false) +public class CharacterGem { + private boolean locked; + private int[] attributes; + private int[] alterAttributes; + + @Deprecated // Morphia only + public CharacterGem() { + + } + + public CharacterGem(IntList attributes) { + this.attributes = attributes.toIntArray(); + this.alterAttributes = new int[4]; + } + + public void setLocked(boolean locked) { + this.locked = locked; + } + + // Proto + + public CharGem toProto() { + var proto = CharGem.newInstance() + .setLock(this.isLocked()) + .addAllAttributes(this.getAttributes()) + .addAllAlterAttributes(this.getAlterAttributes()); + + return proto; + } +} diff --git a/src/main/java/emu/nebula/game/character/CharacterGemPreset.java b/src/main/java/emu/nebula/game/character/CharacterGemPreset.java new file mode 100644 index 0000000..4b45c63 --- /dev/null +++ b/src/main/java/emu/nebula/game/character/CharacterGemPreset.java @@ -0,0 +1,58 @@ +package emu.nebula.game.character; + +import dev.morphia.annotations.Entity; +import emu.nebula.proto.Public.CharGemPreset; +import lombok.Getter; + +@Getter +@Entity(useDiscriminator = false) +public class CharacterGemPreset { + private String name; + private int[] gems; + + @Deprecated // Morphia only + public CharacterGemPreset() { + + } + + public CharacterGemPreset(Character character) { + this.gems = new int[] {-1, -1, -1}; + } + + public int getLength() { + return this.getGems().length; + } + + public int getGemIndex(int slotIndex) { + if (slotIndex < 0 || slotIndex >= this.getLength()) { + return -1; + } + + return this.getGems()[slotIndex]; + } + + public boolean setGemIndex(int slotId, int gemIndex) { + int slotIndex = slotId - 1; + + if (slotIndex < 0 || slotIndex >= this.getLength()) { + return false; + } + + this.getGems()[slotIndex] = gemIndex; + + return true; + } + + // Proto + + public CharGemPreset toProto() { + var proto = CharGemPreset.newInstance() + .addAllSlotGem(this.getGems()); + + if (this.getName() != null) { + proto.setName(this.getName()); + } + + return proto; + } +} diff --git a/src/main/java/emu/nebula/game/character/CharacterGemSlot.java b/src/main/java/emu/nebula/game/character/CharacterGemSlot.java new file mode 100644 index 0000000..86f6d66 --- /dev/null +++ b/src/main/java/emu/nebula/game/character/CharacterGemSlot.java @@ -0,0 +1,51 @@ +package emu.nebula.game.character; + +import java.util.ArrayList; +import java.util.List; + +import dev.morphia.annotations.Entity; +import emu.nebula.GameConstants; +import emu.nebula.proto.Public.CharGemSlot; +import lombok.Getter; + +@Getter +@Entity(useDiscriminator = false) +public class CharacterGemSlot { + private int id; + private List gems; + + @Deprecated // Morphia only + public CharacterGemSlot() { + + } + + public CharacterGemSlot(int id) { + this.id = id; + this.gems = new ArrayList<>(); + } + + public CharacterGem getGem(int gemId) { + if (gemId < 0 || gemId >= this.getGems().size()) { + return null; + } + + return this.getGems().get(gemId); + } + + public boolean isFull() { + return getGems().size() >= GameConstants.CHARACTER_MAX_GEMS_PER_SLOT; + } + + // Proto + + public CharGemSlot toProto() { + var proto = CharGemSlot.newInstance() + .setId(this.getId()); + + for (var gem : this.getGems()) { + proto.addAlterGems(gem.toProto()); + } + + return proto; + } +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemEquipGemReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemEquipGemReq.java new file mode 100644 index 0000000..3b655a9 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemEquipGemReq.java @@ -0,0 +1,35 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemEquipGem.CharGemEquipGemReq; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_equip_gem_req) +public class HandlerCharGemEquipGemReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemEquipGemReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_equip_gem_failed_ack); + } + + // Equip gem + boolean success = character.equipGem(req.getPresetId(), req.getSlotId(), req.getGemIndex()); + + if (success == false) { + return session.encodeMsg(NetMsgId.char_gem_equip_gem_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_equip_gem_succeed_ack); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java new file mode 100644 index 0000000..3f9bfcf --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java @@ -0,0 +1,43 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemGenerate.CharGemGenerateReq; +import emu.nebula.proto.CharGemGenerate.CharGemGenerateResp; +import emu.nebula.net.HandlerId; +import emu.nebula.game.character.CharacterGem; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_generate_req) +public class HandlerCharGemGenerateReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemGenerateReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_generate_failed_ack); + } + + // Generate gem + var change = character.generateGem(req.getSlotId()); + + if (change == null) { + return session.encodeMsg(NetMsgId.char_gem_generate_failed_ack); + } + + var gem = (CharacterGem) change.getExtraData(); + + // Build response + var rsp = CharGemGenerateResp.newInstance() + .setChangeInfo(change.toProto()) + .setCharGem(gem.toProto()); + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_generate_succeed_ack, rsp); + } + +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemUsePresetReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemUsePresetReq.java new file mode 100644 index 0000000..cbb766d --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemUsePresetReq.java @@ -0,0 +1,35 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.CharGemUsePreset.CharGemUsePresetReq; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.char_gem_use_preset_req) +public class HandlerCharGemUsePresetReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = CharGemUsePresetReq.parseFrom(message); + + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId()); + + if (character == null) { + return session.encodeMsg(NetMsgId.char_gem_use_preset_failed_ack); + } + + // Use preset + boolean success = character.setCurrentGemPreset(req.getPresetId()); + + if (success == false) { + return session.encodeMsg(NetMsgId.char_gem_use_preset_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.char_gem_use_preset_succeed_ack); + } + +}