// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.net.client.msg; import engine.gameManager.BuildingManager; import engine.gameManager.ForgeManager; import engine.loot.WorkOrder; import engine.mbEnums; import engine.mbEnums.GameObjectType; import engine.net.*; import engine.objects.Building; import engine.objects.Item; import engine.objects.NPC; import java.util.HashMap; public class ItemProductionMsg extends ClientNetMsg { public int size; public int buildingUUID; public int unknown01; public int itemUUID; public int itemType; public int total_to_produce; public int unknown03; public int pToken; public int sToken; public String name; public mbEnums.ProductionActionType actionType; public int npcUUID; public boolean add; public int itemPrice; public HashMap items; /** * This is the general purpose constructor. */ public ItemProductionMsg() { super(Protocol.ITEMPRODUCTION); this.actionType = mbEnums.ProductionActionType.NONE; this.size = 0; this.buildingUUID = 0; this.unknown01 = 0; this.itemUUID = 0; this.total_to_produce = 0; this.unknown03 = 0; this.pToken = 0; this.sToken = 0; this.name = ""; this.itemPrice = 0; this.itemType = 0; } public ItemProductionMsg(Building building, NPC vendor, Item item, mbEnums.ProductionActionType actionType, boolean add) { super(Protocol.ITEMPRODUCTION); this.actionType = actionType; this.size = 0; this.buildingUUID = building.getObjectUUID(); this.npcUUID = vendor.getObjectUUID(); this.itemType = item.getObjectType().ordinal(); this.itemUUID = item.getObjectUUID(); this.unknown01 = 0; this.total_to_produce = 0; this.unknown03 = 0; this.pToken = 0; this.sToken = 0; this.name = ""; this.add = add; this.itemPrice = item.getValue(); } /** * This constructor is used by NetMsgFactory. It attempts to deserialize the * ByteBuffer into a message. If a BufferUnderflow occurs (based on reading * past the limit) then this constructor Throws that Exception to the * caller. */ public ItemProductionMsg(AbstractConnection origin, ByteBufferReader reader) { super(Protocol.ITEMPRODUCTION, origin, reader); } /** * @see AbstractNetMsg#getPowerOfTwoBufferSize() */ @Override protected int getPowerOfTwoBufferSize() { //Larger size for historically larger opcodes return (16); // 2^16 == 64k } /** * Serializes the subclass specific items to the supplied NetMsgWriter. */ @Override protected void _serialize(ByteBufferWriter writer) { Building building = BuildingManager.getBuildingFromCache(this.buildingUUID); if (building == null) return; // Common Header writer.putInt(this.actionType.ordinal()); writer.putInt(GameObjectType.Building.ordinal()); writer.putInt(this.buildingUUID); writer.putInt(GameObjectType.NPC.ordinal()); writer.putInt(this.npcUUID); switch (this.actionType) { case CONFIRM_DEPOSIT: writer.putInt(0); // Not item ordinal? writer.putInt(0); // Not item uuid? writer.putInt(1); writer.putInt(0); if (!add) { writer.put((byte) 1); Item item; item = Item.getFromCache(this.itemUUID); // Negative ID items not sent here. Deposit virtual item? if (item != null) Item.serializeForClientMsgWithoutSlot(item, writer); writer.putInt(building.getStrongboxValue()); writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; } writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 1); Item item = Item.getFromCache(this.itemUUID); if (item != null) Item.serializeForClientMsgWithoutSlot(item, writer); writer.putInt(building.getStrongboxValue()); writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; case CONFIRM_TAKE: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(1); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; case SETPRICE: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(1); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(this.itemPrice); // new price writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; case CONFIRM_SETPRICE: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(1); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 1); writer.putInt(building.getStrongboxValue()); // new price writer.putInt(0); writer.putInt(0); //writer.put((byte) 0); break; case DEPOSIT: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(1); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; case TAKE: case RECYCLE: writer.putInt(0); writer.putInt(0); writer.putInt(1); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 1); writer.putInt(building.getStrongboxValue()); if (this.items != null) { writer.putInt(this.items.size()); for (int itemID : this.items.keySet()) { writer.putInt(this.items.get(itemID)); writer.putInt(itemID); } } else writer.putInt(0); writer.putInt(0); break; case CONFIRM_PRODUCE: writer.putInt(0); writer.putInt(0); writer.putInt(1); Item toRoll = Item.getFromCache(this.itemUUID); writer.putInt(-1497023830); WorkOrder workOrder = ForgeManager.itemWorkOrderLookup.get(toRoll); this.pToken = toRoll.prefixToken; this.sToken = toRoll.suffixToken; if (toRoll.isComplete() || (workOrder.prefixToken != 0 && workOrder.suffixToken != 0)) { writer.putInt(this.pToken); writer.putInt(this.sToken); } else { writer.putInt(0); writer.putInt(0); } writer.putString(toRoll.name); writer.putInt(toRoll.getObjectType().ordinal()); writer.putInt(this.itemUUID); writer.putInt(0); //items left to produce? writer.putInt(toRoll.templateID); writer.putInt(toRoll.getValue()); NPC vendor = NPC.getFromCache(this.npcUUID); if (vendor != null) { if (toRoll.isComplete()) { writer.putInt(0); writer.putInt(0); } else { long timeLeft = toRoll.getDateToUpgrade() - System.currentTimeMillis(); timeLeft /= 1000; writer.putInt((int) timeLeft); writer.putInt(vendor.getRollingTimeInSeconds(toRoll.templateID)); } } else { writer.putInt(0); writer.putInt(0); } if (toRoll.isComplete()) writer.putInt(0); else writer.putInt(1); writer.put((byte) 0); if (toRoll != null && toRoll.isComplete()) writer.put((byte) 1); else writer.put((byte) 0); writer.put((byte) 0); writer.put((byte) 1); writer.putInt(vendor.getBuilding().getStrongboxValue()); writer.putInt(0); writer.putInt(0); //writer.putInt(0); //error popup break; case COMPLETE: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(this.total_to_produce); writer.putInt(this.unknown03); writer.putInt(this.pToken); writer.putInt(this.sToken); writer.putInt(0); writer.putInt(0); writer.putInt(0); writer.put((byte) 0); break; case JUNK: writer.putInt(this.itemType); writer.putInt(this.itemUUID); writer.putInt(this.total_to_produce); writer.putInt(this.unknown03); writer.putInt(this.pToken); writer.putInt(this.sToken); writer.putString(this.name); writer.putInt(0); writer.putInt(0); writer.putShort((short) 0); writer.put((byte) 0); break; default: writer.putInt(0); writer.putInt(1); writer.putInt(0); writer.putInt(0); break; } } /** * Deserializes the subclass specific items from the supplied NetMsgReader. */ @Override protected void _deserialize(ByteBufferReader reader) { // Common header this.actionType = mbEnums.ProductionActionType.values()[reader.getInt()]; reader.getInt(); // Building type padding this.buildingUUID = reader.getInt(); reader.getInt(); // NPC type padding this.npcUUID = reader.getInt(); switch (this.actionType) { case SETPRICE: this.itemType = reader.getInt(); this.itemUUID = reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); this.itemPrice = reader.getInt(); reader.getInt(); reader.getInt(); reader.get(); break; case RECYCLE: case TAKE: reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.get(); this.size = reader.getInt(); HashMap tempIDs = new HashMap<>(); for (int i = 0; i < this.size; i++) { int type = reader.getInt(); // Item type padding this.itemUUID = reader.getInt(); tempIDs.put(this.itemUUID, type); } reader.getInt(); this.items = tempIDs; break; case DEPOSIT: this.itemType = reader.getInt(); this.itemUUID = reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.getInt(); reader.get(); break; case JUNK: this.itemType = reader.getInt(); this.itemUUID = reader.getInt(); this.total_to_produce = reader.getInt(); this.unknown03 = reader.getInt(); this.pToken = reader.getInt(); this.sToken = reader.getInt(); this.name = reader.getString(); reader.getInt(); reader.getInt(); reader.get(); break; default: this.itemType = reader.getInt(); this.itemUUID = reader.getInt(); this.total_to_produce = reader.getInt(); this.unknown03 = reader.getInt(); this.pToken = reader.getInt(); this.sToken = reader.getInt(); this.name = reader.getString(); this.size = reader.getInt(); reader.getInt(); if (this.actionType == mbEnums.ProductionActionType.COMPLETE || this.actionType == mbEnums.ProductionActionType.JUNK) reader.get(); else reader.getShort(); break; } } }