Browse Source

More integration work

combat-2
MagicBot 8 months ago
parent
commit
9464500e95
  1. 83
      src/engine/db/handlers/dbNPCHandler.java
  2. 3
      src/engine/devcmd/cmds/CreateItemCmd.java
  3. 15
      src/engine/gameManager/ForgeManager.java
  4. 135
      src/engine/net/ItemProductionManager.java
  5. 86
      src/engine/net/ItemQueue.java
  6. 12
      src/engine/net/client/handlers/ItemProductionMsgHandler.java
  7. 45
      src/engine/net/client/msg/ItemProductionMsg.java
  8. 3
      src/engine/net/client/msg/ManageNPCMsg.java
  9. 32
      src/engine/objects/CharacterItemManager.java
  10. 1029
      src/engine/objects/ItemFactory.java
  11. 188
      src/engine/objects/NPC.java
  12. 225
      src/engine/objects/ProducedItem.java
  13. 6
      src/engine/server/world/WorldServer.java

83
src/engine/db/handlers/dbNPCHandler.java

@ -9,13 +9,12 @@
package engine.db.handlers; package engine.db.handlers;
import engine.mbEnums;
import engine.mbEnums.ProfitType;
import engine.gameManager.DbManager; import engine.gameManager.DbManager;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.mbEnums.ProfitType;
import engine.objects.NPC; import engine.objects.NPC;
import engine.objects.NPCProfits; import engine.objects.NPCProfits;
import engine.objects.ProducedItem;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
@ -346,29 +345,6 @@ public class dbNPCHandler extends dbHandlerBase {
+ NPC._pirateNames.size() + " mobBases"); + NPC._pirateNames.size() + " mobBases");
} }
public boolean ADD_TO_PRODUCTION_LIST(final long ID, final long npcUID, final long templateID, DateTime dateTime, String prefix, String suffix, String name, boolean isRandom, int playerID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_npc_production` (`ID`,`npcUID`, `templateID`,`dateToUpgrade`, `isRandom`, `prefix`, `suffix`, `name`,`playerID`) VALUES (?,?,?,?,?,?,?,?,?)")) {
preparedStatement.setLong(1, ID);
preparedStatement.setLong(2, npcUID);
preparedStatement.setLong(3, templateID);
preparedStatement.setTimestamp(4, new java.sql.Timestamp(dateTime.getMillis()));
preparedStatement.setBoolean(5, isRandom);
preparedStatement.setString(6, prefix);
preparedStatement.setString(7, suffix);
preparedStatement.setString(8, name);
preparedStatement.setInt(9, playerID);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public boolean REMOVE_FROM_PRODUCTION_LIST(final long ID, final long npcUID) { public boolean REMOVE_FROM_PRODUCTION_LIST(final long ID, final long npcUID) {
try (Connection connection = DbManager.getConnection(); try (Connection connection = DbManager.getConnection();
@ -385,23 +361,6 @@ public class dbNPCHandler extends dbHandlerBase {
} }
} }
public boolean UPDATE_ITEM_TO_INVENTORY(final long ID, final long npcUID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_npc_production` SET `inForge`=? WHERE `ID`=? AND `npcUID`=?;")) {
preparedStatement.setByte(1, (byte) 0);
preparedStatement.setLong(2, ID);
preparedStatement.setLong(3, npcUID);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public boolean UPDATE_ITEM_PRICE(final long ID, final long npcUID, int value) { public boolean UPDATE_ITEM_PRICE(final long ID, final long npcUID, int value) {
try (Connection connection = DbManager.getConnection(); try (Connection connection = DbManager.getConnection();
@ -419,44 +378,6 @@ public class dbNPCHandler extends dbHandlerBase {
} }
} }
public boolean UPDATE_ITEM_ID(final long ID, final long npcUID, final long value) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_npc_production` SET `ID`=? WHERE `ID`=? AND `npcUID`=? LIMIT 1;")) {
preparedStatement.setLong(1, value);
preparedStatement.setLong(2, ID);
preparedStatement.setLong(3, npcUID);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public void LOAD_ALL_ITEMS_TO_PRODUCE(NPC npc) {
if (npc == null)
return;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `dyn_npc_production` WHERE `npcUID` = ?")) {
preparedStatement.setInt(1, npc.getObjectUUID());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
ProducedItem producedItem = new ProducedItem(rs);
npc.forgedItems.add(producedItem);
}
} catch (SQLException e) {
Logger.error(e);
}
}
public boolean UPDATE_PROFITS(NPC npc, ProfitType profitType, float value) { public boolean UPDATE_PROFITS(NPC npc, ProfitType profitType, float value) {
try (Connection connection = DbManager.getConnection(); try (Connection connection = DbManager.getConnection();

3
src/engine/devcmd/cmds/CreateItemCmd.java

@ -11,7 +11,6 @@ package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd; import engine.devcmd.AbstractDevCmd;
import engine.objects.AbstractGameObject; import engine.objects.AbstractGameObject;
import engine.objects.ItemFactory;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
/** /**
@ -39,7 +38,7 @@ public class CreateItemCmd extends AbstractDevCmd {
if (words.length == 2) if (words.length == 2)
size = Integer.parseInt(words[1]); size = Integer.parseInt(words[1]);
ItemFactory.fillInventory(pc, templateID, size);
} }
@Override @Override

15
src/engine/gameManager/ForgeManager.java

@ -17,6 +17,7 @@ import engine.powers.EffectsBase;
import engine.powers.poweractions.AbstractPowerAction; import engine.powers.poweractions.AbstractPowerAction;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue; import java.util.concurrent.DelayQueue;
@ -30,9 +31,12 @@ public enum ForgeManager implements Runnable {
private static final BlockingQueue<WorkOrder> forge = new DelayQueue<>(); private static final BlockingQueue<WorkOrder> forge = new DelayQueue<>();
public static final AtomicInteger wordOrderCounter = new AtomicInteger(0); public static final AtomicInteger wordOrderCounter = new AtomicInteger(0);
public static final HashMap<Item, WorkOrder> workOrderMap = new HashMap<Item, WorkOrder>(); public static final HashMap<Integer, Item> inMemoryItemLookup = new HashMap<>();
public static final HashMap<NPC, ArrayList<Item>> vendorItemLookup = new HashMap<>();
public static final HashMap<NPC, ArrayList<WorkOrder>> vendorWorkOrderLookup = new HashMap<>();
@Override @Override
public void run() { public void run() {
while (true) { while (true) {
@ -71,10 +75,7 @@ public enum ForgeManager implements Runnable {
// worker after first removing the negative id item from all // worker after first removing the negative id item from all
// collections. // collections.
// Add new item to the vendors inventory
workOrder.runCompleted = true; workOrder.runCompleted = true;
workOrder.vendor.workOrders.remove(workOrder);
continue; continue;
} }
@ -124,7 +125,6 @@ public enum ForgeManager implements Runnable {
forgeItems(workOrder); forgeItems(workOrder);
Logger.info(workOrder.toString()); Logger.info(workOrder.toString());
workOrder.vendor.workOrders.add(workOrder);
forge.add(workOrder); forge.add(workOrder);
return validation_result; return validation_result;
@ -180,7 +180,7 @@ public enum ForgeManager implements Runnable {
// Slots currently used up by the npc workOrders // Slots currently used up by the npc workOrders
for (WorkOrder npcWorkOrder : workOrder.vendor.workOrders) for (WorkOrder npcWorkOrder : ForgeManager.vendorWorkOrderLookup.get(workOrder.vendor))
availableSlots = availableSlots - npcWorkOrder.slots_used; availableSlots = availableSlots - npcWorkOrder.slots_used;
// Single item rolls are msg_size of 0; // Single item rolls are msg_size of 0;
@ -287,9 +287,10 @@ public enum ForgeManager implements Runnable {
for (int i = 0; i < workOrder.slots_used; ++i) { for (int i = 0; i < workOrder.slots_used; ++i) {
Item forged_item = forgeItem(workOrder); Item forged_item = forgeItem(workOrder);
ForgeManager.workOrderMap.put(forged_item, workOrder); ForgeManager.inMemoryItemLookup.put(forged_item.objectUUID, forged_item);
workOrder.cooking.add(forged_item); workOrder.cooking.add(forged_item);
vendorItemLookup.get(workOrder.vendor).add(forged_item);
Logger.info("Forging item: " + forged_item.objectUUID + " (" + forged_item.templateID + ") " + forged_item.template.item_base_name); Logger.info("Forging item: " + forged_item.objectUUID + " (" + forged_item.templateID + ") " + forged_item.template.item_base_name);
workOrder.total_produced = workOrder.total_produced + 1; workOrder.total_produced = workOrder.total_produced + 1;

135
src/engine/net/ItemProductionManager.java

@ -1,135 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.net;
import engine.mbEnums.DispatchChannel;
import engine.objects.ProducedItem;
import org.pmw.tinylog.Logger;
import java.util.HashSet;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.atomic.LongAdder;
/**
* Thread blocks until MagicBane dispatch messages are
* enqueued then processes them in FIFO order. The collection
* is thread safe.
* <p>
* Any large messages not time sensitive such as load object
* sent to more than a single individual should be spawned
* individually on a DispatchMessageThread.
*/
public enum ItemProductionManager implements Runnable {
ITEMPRODUCTIONMANAGER;
// Instance variables
@SuppressWarnings("unchecked") // Cannot have arrays of generics in java.
private static final DelayQueue<ItemQueue> producedQueue = new DelayQueue<>();
public static volatile long[] messageCount = new long[DispatchChannel.values().length];
// Class variables
public static LongAdder[] dispatchCount = new LongAdder[DispatchChannel.values().length];
// Performance metrics
public static volatile long[] maxRecipients = new long[DispatchChannel.values().length];
public static LongAdder dispatchPoolSize = new LongAdder();
public static HashSet<ProducedItem> FailedItems = new HashSet<>();
public Thread itemProductionThread = null;
private ItemQueue itemQueue;
private long nextFailedItemAudit;
// Thread constructor
public static void send(ItemQueue item) {
// Don't queue up empty dispatches!
if (item == null)
return;
producedQueue.add(item);
}
public static String getNetstatString() {
String outString = null;
String newLine = System.getProperty("line.separator");
outString = "[LUA_NETSTA()]" + newLine;
outString += "poolSize: " + dispatchPoolSize.longValue() + '\n';
for (DispatchChannel dispatchChannel : DispatchChannel.values()) {
outString += "Channel: " + dispatchChannel.name() + '\n';
outString += "Dispatches: " + dispatchCount[dispatchChannel.getChannelID()].longValue() + '\n';
outString += "Messages: " + messageCount[dispatchChannel.getChannelID()] + '\n';
outString += "maxRecipients: " + maxRecipients[dispatchChannel.getChannelID()] + '\n';
}
return outString;
}
public void startMessagePump() {
itemProductionThread = new Thread(this);
itemProductionThread.setName("ItemProductionManager");
}
public void initialize() {
itemProductionThread.start();
}
@Override
public void run() {
while (true) {
try {
this.itemQueue = producedQueue.take();
if (this.itemQueue == null) {
return;
}
if (this.itemQueue != null) {
if (this.itemQueue.item == null) {
this.itemQueue.release();
return;
}
boolean created = this.itemQueue.item.finishProduction();
if (!created)
FailedItems.add(this.itemQueue.item);
this.itemQueue.release();
}
} catch (Exception e) {
Logger.error(e);
}
}
}
// For Debugging:
//Logger.error("MessageDispatcher", messageDispatch.msg.getOpcodeAsString() + " sent to " + messageDispatch.playerList.size() + " players");
}

86
src/engine/net/ItemQueue.java

@ -1,86 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.net;
import engine.objects.ProducedItem;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import static engine.net.MessageDispatcher.itemPoolSize;
/**
* Data class holds a message and a distribution list
*/
public class ItemQueue implements Delayed {
private static final ConcurrentLinkedQueue<ItemQueue> itemPool = new ConcurrentLinkedQueue<>();
public ProducedItem item;
public long delayTime;
public ItemQueue(ProducedItem item, long delayTime) {
this.item = item;
this.delayTime = System.currentTimeMillis() + delayTime;
}
public static ItemQueue borrow(ProducedItem item, long delayTime) {
ItemQueue itemQueue;
itemQueue = itemPool.poll();
if (itemQueue == null) {
itemQueue = new ItemQueue(item, delayTime);
} else {
itemQueue.item = item;
itemQueue.delayTime = System.currentTimeMillis() + delayTime;
itemPoolSize.decrement();
}
return itemQueue;
}
public void reset() {
this.item = null;
this.delayTime = 0;
}
public void release() {
this.reset();
itemPool.add(this);
itemPoolSize.increment();
}
@Override
public int compareTo(Delayed another) {
ItemQueue anotherTask = (ItemQueue) another;
if (this.delayTime < anotherTask.delayTime) {
return -1;
}
if (this.delayTime > anotherTask.delayTime) {
return 1;
}
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
long difference = delayTime - System.currentTimeMillis();
return unit.convert(difference, TimeUnit.MILLISECONDS);
}
}

12
src/engine/net/client/handlers/ItemProductionMsgHandler.java

@ -82,7 +82,7 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
WorkOrder workOrder = new WorkOrder(); WorkOrder workOrder = new WorkOrder();
workOrder.total_to_produce = msg.total_to_produce; workOrder.total_to_produce = msg.total_to_produce;
workOrder.vendor = vendorNPC; workOrder.vendor = vendorNPC;
workOrder.templateID = msg.templateID; workOrder.templateID = msg.itemUUID;
workOrder.prefixToken = msg.pToken; workOrder.prefixToken = msg.pToken;
workOrder.suffixToken = msg.sToken; workOrder.suffixToken = msg.sToken;
workOrder.item_name_override = msg.name; workOrder.item_name_override = msg.name;
@ -101,7 +101,7 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
} }
break; break;
case JUNK: case JUNK:
junkItem(msg.templateID, vendorNPC, origin); junkItem(msg.itemUUID, vendorNPC, origin);
break; break;
case RECYCLE: case RECYCLE:
recycleItem(msg.items, vendorNPC, origin); recycleItem(msg.items, vendorNPC, origin);
@ -110,13 +110,13 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
break; break;
case COMPLETE: case COMPLETE:
vendorNPC.completeItem(msg.templateID); // todo fix vendorNPC.completeItem(msg.itemUUID);
break; break;
case DEPOSIT: case DEPOSIT:
depositItem(msg.templateID, vendorNPC, origin); depositItem(msg.itemUUID, vendorNPC, origin);
break; break;
case SETPRICE: case SETPRICE:
setItemPrice(msg.itemType, msg.templateID, msg.itemPrice, vendorNPC, origin); setItemPrice(msg.itemType, msg.itemUUID, msg.itemPrice, vendorNPC, origin);
break; break;
case TAKE: case TAKE:
takeItem(msg.items, vendorNPC, origin); takeItem(msg.items, vendorNPC, origin);
@ -364,7 +364,7 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
// Delete the item and cancel any pending rolling timer jobs // Delete the item and cancel any pending rolling timer jobs
targetItem.recycle(vendor); targetItem.recycle(vendor);
vendor.removeItemFromForge(targetItem); // todo fix vendor.removeItemFromForge(targetItem);
// Refresh vendor's inventory to client // Refresh vendor's inventory to client

45
src/engine/net/client/msg/ItemProductionMsg.java

@ -10,6 +10,7 @@
package engine.net.client.msg; package engine.net.client.msg;
import engine.gameManager.BuildingManager; import engine.gameManager.BuildingManager;
import engine.gameManager.ForgeManager;
import engine.gameManager.PowersManager; import engine.gameManager.PowersManager;
import engine.mbEnums; import engine.mbEnums;
import engine.mbEnums.GameObjectType; import engine.mbEnums.GameObjectType;
@ -27,7 +28,7 @@ public class ItemProductionMsg extends ClientNetMsg {
public int size; public int size;
public int buildingUUID; public int buildingUUID;
public int unknown01; public int unknown01;
public int templateID; public int itemUUID;
public int itemType; public int itemType;
public int total_to_produce; public int total_to_produce;
public int unknown03; public int unknown03;
@ -50,7 +51,7 @@ public class ItemProductionMsg extends ClientNetMsg {
this.size = 0; this.size = 0;
this.buildingUUID = 0; this.buildingUUID = 0;
this.unknown01 = 0; this.unknown01 = 0;
this.templateID = 0; this.itemUUID = 0;
this.total_to_produce = 0; this.total_to_produce = 0;
this.unknown03 = 0; this.unknown03 = 0;
this.pToken = 0; this.pToken = 0;
@ -70,7 +71,7 @@ public class ItemProductionMsg extends ClientNetMsg {
this.buildingUUID = building.getObjectUUID(); this.buildingUUID = building.getObjectUUID();
this.npcUUID = vendor.getObjectUUID(); this.npcUUID = vendor.getObjectUUID();
this.itemType = item.getObjectType().ordinal(); this.itemType = item.getObjectType().ordinal();
this.templateID = item.getObjectUUID(); this.itemUUID = item.getObjectUUID();
this.unknown01 = 0; this.unknown01 = 0;
this.total_to_produce = 0; this.total_to_produce = 0;
this.unknown03 = 0; this.unknown03 = 0;
@ -128,7 +129,7 @@ public class ItemProductionMsg extends ClientNetMsg {
if (!add) { if (!add) {
writer.put((byte) 1); writer.put((byte) 1);
Item item = Item.getFromCache(this.templateID); Item item = Item.getFromCache(this.itemUUID);
if (item != null) if (item != null)
Item.serializeForClientMsgWithoutSlot(item, writer); Item.serializeForClientMsgWithoutSlot(item, writer);
writer.putInt(building.getStrongboxValue()); writer.putInt(building.getStrongboxValue());
@ -142,12 +143,14 @@ public class ItemProductionMsg extends ClientNetMsg {
writer.putInt(0); writer.putInt(0);
writer.put((byte) 1); writer.put((byte) 1);
Item item; Item item;
if (this.itemType == GameObjectType.Item.ordinal()) if (this.itemUUID > 0)
item = Item.getFromCache(this.templateID); item = Item.getFromCache(this.itemUUID);
else else
item = MobLoot.getFromCache(this.templateID); item = ForgeManager.inMemoryItemLookup.get(this.itemUUID);
if (item != null) if (item != null)
Item.serializeForClientMsgWithoutSlot(item, writer); Item.serializeForClientMsgWithoutSlot(item, writer);
writer.putInt(building.getStrongboxValue()); writer.putInt(building.getStrongboxValue());
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
@ -155,7 +158,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case CONFIRM_TAKE: case CONFIRM_TAKE:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(1); writer.putInt(1);
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
@ -167,7 +170,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case SETPRICE: case SETPRICE:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(1); writer.putInt(1);
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
@ -180,7 +183,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case CONFIRM_SETPRICE: case CONFIRM_SETPRICE:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(1); writer.putInt(1);
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
@ -194,7 +197,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case DEPOSIT: case DEPOSIT:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(1); writer.putInt(1);
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
@ -234,7 +237,7 @@ public class ItemProductionMsg extends ClientNetMsg {
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
writer.putInt(1); writer.putInt(1);
MobLoot toRoll = MobLoot.getFromCache(this.templateID); MobLoot toRoll = MobLoot.getFromCache(this.itemUUID);
writer.putInt(-1497023830); writer.putInt(-1497023830);
if (toRoll != null && toRoll.getPrefix() != null && !toRoll.getPrefix().isEmpty()) { if (toRoll != null && toRoll.getPrefix() != null && !toRoll.getPrefix().isEmpty()) {
@ -262,7 +265,7 @@ public class ItemProductionMsg extends ClientNetMsg {
writer.putString(toRoll.name); writer.putString(toRoll.name);
writer.putInt(GameObjectType.MobLoot.ordinal()); writer.putInt(GameObjectType.MobLoot.ordinal());
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(0); //items left to produce? writer.putInt(0); //items left to produce?
writer.putInt(toRoll.templateID); writer.putInt(toRoll.templateID);
@ -306,7 +309,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case COMPLETE: case COMPLETE:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(this.total_to_produce); writer.putInt(this.total_to_produce);
writer.putInt(this.unknown03); writer.putInt(this.unknown03);
writer.putInt(this.pToken); writer.putInt(this.pToken);
@ -318,7 +321,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case JUNK: case JUNK:
writer.putInt(this.itemType); writer.putInt(this.itemType);
writer.putInt(this.templateID); writer.putInt(this.itemUUID);
writer.putInt(this.total_to_produce); writer.putInt(this.total_to_produce);
writer.putInt(this.unknown03); writer.putInt(this.unknown03);
writer.putInt(this.pToken); writer.putInt(this.pToken);
@ -355,7 +358,7 @@ public class ItemProductionMsg extends ClientNetMsg {
switch (this.actionType) { switch (this.actionType) {
case SETPRICE: case SETPRICE:
this.itemType = reader.getInt(); this.itemType = reader.getInt();
this.templateID = reader.getInt(); this.itemUUID = reader.getInt();
reader.getInt(); reader.getInt();
reader.getInt(); reader.getInt();
reader.getInt(); reader.getInt();
@ -380,15 +383,15 @@ public class ItemProductionMsg extends ClientNetMsg {
HashMap<Integer, Integer> tempIDs = new HashMap<>(); HashMap<Integer, Integer> tempIDs = new HashMap<>();
for (int i = 0; i < this.size; i++) { for (int i = 0; i < this.size; i++) {
int type = reader.getInt(); // Item type padding int type = reader.getInt(); // Item type padding
this.templateID = reader.getInt(); this.itemUUID = reader.getInt();
tempIDs.put(this.templateID, type); tempIDs.put(this.itemUUID, type);
} }
reader.getInt(); reader.getInt();
this.items = tempIDs; this.items = tempIDs;
break; break;
case DEPOSIT: case DEPOSIT:
this.itemType = reader.getInt(); this.itemType = reader.getInt();
this.templateID = reader.getInt(); this.itemUUID = reader.getInt();
reader.getInt(); reader.getInt();
reader.getInt(); reader.getInt();
reader.getInt(); reader.getInt();
@ -400,7 +403,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
case JUNK: case JUNK:
this.itemType = reader.getInt(); this.itemType = reader.getInt();
this.templateID = reader.getInt(); this.itemUUID = reader.getInt();
this.total_to_produce = reader.getInt(); this.total_to_produce = reader.getInt();
this.unknown03 = reader.getInt(); this.unknown03 = reader.getInt();
this.pToken = reader.getInt(); this.pToken = reader.getInt();
@ -412,7 +415,7 @@ public class ItemProductionMsg extends ClientNetMsg {
break; break;
default: default:
this.itemType = reader.getInt(); this.itemType = reader.getInt();
this.templateID = reader.getInt(); this.itemUUID = reader.getInt();
this.total_to_produce = reader.getInt(); this.total_to_produce = reader.getInt();
this.unknown03 = reader.getInt(); this.unknown03 = reader.getInt();
this.pToken = reader.getInt(); this.pToken = reader.getInt();

3
src/engine/net/client/msg/ManageNPCMsg.java

@ -9,6 +9,7 @@
package engine.net.client.msg; package engine.net.client.msg;
import engine.gameManager.ForgeManager;
import engine.gameManager.NPCManager; import engine.gameManager.NPCManager;
import engine.gameManager.PowersManager; import engine.gameManager.PowersManager;
import engine.mbEnums.GameObjectType; import engine.mbEnums.GameObjectType;
@ -435,7 +436,7 @@ public class ManageNPCMsg extends ClientNetMsg {
writer.put((byte) template.modTable);//EffectItemType writer.put((byte) template.modTable);//EffectItemType
} }
List<MobLoot> itemList = npc.getRolling(); List<Item> itemList = ForgeManager.vendorItemLookup.get(npc);
itemList = itemList.stream().limit(npc.getRank()).collect(Collectors.toList()); itemList = itemList.stream().limit(npc.getRank()).collect(Collectors.toList());
writer.putInt(itemList.size()); writer.putInt(itemList.size());

32
src/engine/objects/CharacterItemManager.java

@ -1341,28 +1341,28 @@ public class CharacterItemManager {
/* /*
* Delegates * Delegates
*/ */
public synchronized boolean bankContains(Item i) { public synchronized boolean bankContains(Item item) {
if (i.template.item_type.equals(ItemType.GOLD)) if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldBank() != null && this.goldBank.getObjectUUID() == i.getObjectUUID()); return (this.getGoldBank() != null && this.goldBank.getObjectUUID() == item.getObjectUUID());
return bank.contains(i); return bank.contains(item);
} }
public synchronized boolean inventoryContains(Item i) { public synchronized boolean inventoryContains(Item item) {
if (i.template.item_type.equals(ItemType.GOLD)) if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == i.getObjectUUID()); return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == item.getObjectUUID());
return inventory.contains(i); return inventory.contains(item);
} }
public synchronized boolean forgeContains(Item i, NPC vendor) { public synchronized boolean forgeContains(Item item, NPC vendor) {
if (i.template.item_type.equals(ItemType.GOLD)) if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == i.getObjectUUID()); return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == item.getObjectUUID());
return vendor.getRolling().contains(i); return ForgeManager.vendorItemLookup.get(vendor).contains(item);
} }
public synchronized boolean vaultContains(Item i) { public synchronized boolean vaultContains(Item item) {
if (i.template.item_type.equals(ItemType.GOLD)) if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldVault() != null && this.goldVault.getObjectUUID() == i.getObjectUUID()); return (this.getGoldVault() != null && this.goldVault.getObjectUUID() == item.getObjectUUID());
return this.account.getVault().contains(i); return this.account.getVault().contains(item);
} }
public synchronized boolean equippedContains(Item i) { public synchronized boolean equippedContains(Item i) {

1029
src/engine/objects/ItemFactory.java

File diff suppressed because it is too large Load Diff

188
src/engine/objects/NPC.java

@ -15,7 +15,6 @@ import engine.gameManager.*;
import engine.job.JobContainer; import engine.job.JobContainer;
import engine.job.JobScheduler; import engine.job.JobScheduler;
import engine.jobs.UpgradeNPCJob; import engine.jobs.UpgradeNPCJob;
import engine.loot.WorkOrder;
import engine.math.Bounds; import engine.math.Bounds;
import engine.math.Vector3f; import engine.math.Vector3f;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
@ -24,8 +23,6 @@ import engine.mbEnums.*;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
import engine.net.Dispatch; import engine.net.Dispatch;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.ItemProductionMsg;
import engine.net.client.msg.PetMsg; import engine.net.client.msg.PetMsg;
import engine.net.client.msg.PlaceAssetMsg; import engine.net.client.msg.PlaceAssetMsg;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
@ -50,9 +47,7 @@ public class NPC extends AbstractCharacter {
public static HashMap<Integer, ArrayList<String>> _pirateNames = new HashMap<>(); public static HashMap<Integer, ArrayList<String>> _pirateNames = new HashMap<>();
// Used for thread safety // Used for thread safety
public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ArrayList<MobLoot> rolling = new ArrayList<>();
public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock(); public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock();
public ArrayList<ProducedItem> forgedItems = new ArrayList<>();
public int runeSetID = 0; public int runeSetID = 0;
public int extraRune2 = 0; public int extraRune2 = 0;
protected int loadID; protected int loadID;
@ -79,7 +74,6 @@ public class NPC extends AbstractCharacter {
public int parentZoneUUID; public int parentZoneUUID;
public int equipmentSetID = 0; public int equipmentSetID = 0;
private int repairCost = 5; private int repairCost = 5;
public ArrayList<WorkOrder> workOrders = new ArrayList<>();
// New NPC constructor. Fill in the blanks and then call // New NPC constructor. Fill in the blanks and then call
// PERSIST. // PERSIST.
@ -915,58 +909,6 @@ public class NPC extends AbstractCharacter {
this.charItemManager.equipped = loadEquipmentSet(this.equipmentSetID); this.charItemManager.equipped = loadEquipmentSet(this.equipmentSetID);
try {
DbManager.NPCQueries.LOAD_ALL_ITEMS_TO_PRODUCE(this);
for (ProducedItem producedItem : this.forgedItems) {
MobLoot ml = new MobLoot(this, ItemTemplate.templates.get(producedItem.getTemplateID()), false);
DbManager.NPCQueries.UPDATE_ITEM_ID(producedItem.getID(), currentID, ml.getObjectUUID());
if (producedItem.isInForge()) {
if (producedItem.getPrefix() != null && !producedItem.getPrefix().isEmpty()) {
ml.addPermanentEnchantment(producedItem.getPrefix(), 0, 0, true);
ml.setPrefix(producedItem.getPrefix());
}
if (producedItem.getSuffix() != null && !producedItem.getSuffix().isEmpty()) {
ml.addPermanentEnchantment(producedItem.getSuffix(), 0, 0, false);
ml.setSuffix(producedItem.getSuffix());
}
if (!producedItem.isRandom())
ml.flags.add(ItemFlags.Identified);
ml.loadEnchantments();
ml.setValue(producedItem.getValue());
ml.setDateToUpgrade(producedItem.getDateToUpgrade().getMillis());
ml.containerType = mbEnums.ItemContainerType.FORGE;
this.addItemToForge(ml);
} else {
if (producedItem.getPrefix() != null && !producedItem.getPrefix().isEmpty()) {
ml.addPermanentEnchantment(producedItem.getPrefix(), 0, 0, true);
ml.setPrefix(producedItem.getPrefix());
}
if (producedItem.getSuffix() != null && !producedItem.getSuffix().isEmpty()) {
ml.addPermanentEnchantment(producedItem.getSuffix(), 0, 0, false);
ml.setSuffix(producedItem.getSuffix());
}
ml.setDateToUpgrade(producedItem.getDateToUpgrade().getMillis());
ml.containerType = mbEnums.ItemContainerType.INVENTORY;
ml.flags.add(ItemFlags.Identified);
this.charItemManager.addItemToInventory(ml);
}
ml.setValue(producedItem.getValue());
}
// Create NPC bounds object // Create NPC bounds object
Bounds npcBounds = Bounds.borrow(); Bounds npcBounds = Bounds.borrow();
npcBounds.setBounds(this.getLoc()); npcBounds.setBounds(this.getLoc());
@ -975,9 +917,6 @@ public class NPC extends AbstractCharacter {
NPCManager.applyRunesForNPC(this); NPCManager.applyRunesForNPC(this);
this.resists.setImmuneToAll(true); this.resists.setImmuneToAll(true);
} catch (Exception e) {
Logger.error(e.getMessage());
}
} }
public void removeFromZone() { public void removeFromZone() {
@ -1008,30 +947,6 @@ public class NPC extends AbstractCharacter {
this.upgradeDateTime = upgradeDateTime; this.upgradeDateTime = upgradeDateTime;
} }
public ArrayList<MobLoot> getRolling() {
synchronized (rolling) {
return rolling;
}
}
public int getRollingCount() {
synchronized (this.rolling) {
return rolling.size();
}
}
public void addItemToForge(MobLoot item) {
synchronized (this.rolling) {
this.rolling.add(item);
}
}
public void removeItemFromForge(Item item) {
synchronized (this.rolling) {
this.rolling.remove(item);
}
}
@Override @Override
public Guild getGuild() { public Guild getGuild() {
if (this.building != null) if (this.building != null)
@ -1166,109 +1081,6 @@ public class NPC extends AbstractCharacter {
return 0; return 0;
} }
public synchronized Item produceItem(int playerID, int amount, boolean isRandom, int pToken, int sToken, String customName, int itemID) {
Zone serverZone;
City city;
Item item = null;
PlayerCharacter player = null;
if (playerID != 0)
player = SessionManager.getPlayerCharacterByID(playerID);
try {
if (this.getRollingCount() >= this.getRank()) {
if (player != null)
ChatManager.chatSystemInfo(player, this.getName() + " " + this.getContract().getName() + " slots are full");
return null;
}
// Cannot roll items without a warehouse.
// Due to the fact fillForge references the
// warehouse and early exits. *** Refactor???
serverZone = this.building.getParentZone();
if (serverZone == null)
return null;
city = City.GetCityFromCache(serverZone.playerCityUUID);
if (city == null) {
if (player != null)
ErrorPopupMsg.sendErrorMsg(player, "Could not find city."); // Production denied: This building must be protected to gain access to warehouse resources.
return null;
}
if (this.building == null) {
if (player != null)
ErrorPopupMsg.sendErrorMsg(player, "Could not find building."); // Production denied: This building must be protected to gain ac
return null;
}
//TODO create Normal Items.
if (amount == 0)
amount = 1;
if (isRandom)
item = ItemFactory.randomRoll(this, player, amount, itemID);
else
item = ItemFactory.fillForge(this, player, amount, itemID, pToken, sToken, customName);
if (item == null)
return null;
ItemProductionMsg outMsg = new ItemProductionMsg(this.building, this, item, 8, true);
DispatchMessage.dispatchMsgToInterestArea(this, outMsg, DispatchChannel.SECONDARY, 700, false, false);
} catch (Exception e) {
Logger.error(e);
}
return item;
}
public synchronized boolean completeItem(int itemUUID) {
MobLoot targetItem;
try {
targetItem = MobLoot.getFromCache(itemUUID);
if (targetItem == null)
return false;
if (!this.charItemManager.forgeContains(targetItem, this))
return false;
if (!DbManager.NPCQueries.UPDATE_ITEM_TO_INVENTORY(targetItem.getObjectUUID(), currentID))
return false;
targetItem.flags.add(ItemFlags.Identified);
this.rolling.remove(targetItem);
this.charItemManager.addItemToInventory(targetItem);
//remove from client forge window
ItemProductionMsg outMsg1 = new ItemProductionMsg(this.building, this, targetItem, 9, true);
DispatchMessage.dispatchMsgToInterestArea(this, outMsg1, DispatchChannel.SECONDARY, MBServerStatics.STRUCTURE_LOAD_RANGE, false, false);
ItemProductionMsg outMsg = new ItemProductionMsg(this.building, this, targetItem, 10, true);
DispatchMessage.dispatchMsgToInterestArea(this, outMsg, DispatchChannel.SECONDARY, MBServerStatics.STRUCTURE_LOAD_RANGE, false, false);
} catch (Exception e) {
Logger.error(e.getMessage());
}
return true;
}
public int getEquipmentSetID() { public int getEquipmentSetID() {
return equipmentSetID; return equipmentSetID;

225
src/engine/objects/ProducedItem.java

@ -1,225 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.objects;
import engine.gameManager.PowersManager;
import engine.mbEnums.DispatchChannel;
import engine.net.DispatchMessage;
import engine.net.client.msg.ItemProductionMsg;
import engine.powers.EffectsBase;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class ProducedItem {
private int ID;
private int npcUID;
private int templateID;
private DateTime dateToUpgrade;
private boolean isRandom;
private String prefix;
private String suffix;
private String name;
private int amount;
private int producedItemID = 0;
private boolean inForge;
private int value;
private int playerID;
/**
* ResultSet Constructor
*/
public ProducedItem(ResultSet rs) throws SQLException {
this.ID = rs.getInt("ID");
this.npcUID = rs.getInt("npcUID");
this.templateID = rs.getInt("templateID");
Date sqlDateTime = rs.getTimestamp("dateToUpgrade");
if (sqlDateTime != null)
this.dateToUpgrade = new DateTime(sqlDateTime);
else
dateToUpgrade = null;
this.isRandom = rs.getBoolean("isRandom");
this.prefix = rs.getString("prefix");
this.suffix = rs.getString("suffix");
this.name = rs.getString("name");
this.inForge = rs.getBoolean("inForge");
this.value = rs.getInt("value");
this.playerID = rs.getInt("playerID");
}
public ProducedItem(int ID, int npcUID, int templateID, DateTime dateToUpgrade, boolean isRandom, String prefix, String suffix, String name, int playerID) {
super();
this.ID = ID;
this.npcUID = npcUID;
this.templateID = templateID;
this.dateToUpgrade = dateToUpgrade;
this.isRandom = isRandom;
this.prefix = prefix;
this.suffix = suffix;
this.name = name;
this.value = 0;
this.playerID = playerID;
}
public int getNpcUID() {
return npcUID;
}
public DateTime getDateToUpgrade() {
return dateToUpgrade;
}
public int getTemplateID() {
return templateID;
}
public void setTemplateID(int templateID) {
this.templateID = templateID;
}
public boolean isRandom() {
return isRandom;
}
public void setRandom(boolean isRandom) {
this.isRandom = isRandom;
}
public String getPrefix() {
return prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getProducedItemID() {
return producedItemID;
}
public void setProducedItemID(int producedItemID) {
this.producedItemID = producedItemID;
}
public boolean isInForge() {
return inForge;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean finishProduction() {
NPC npc = NPC.getFromCache(this.getNpcUID());
if (npc == null)
return false;
//update the client to ID the item in the window when item finishes rolling.
//If there is more than 1 item left to roll, complete the item and throw it in inventory
//and reproduce next item.
try {
if (this.getAmount() > 1) {
this.setAmount(this.getAmount() - 1);
npc.completeItem(this.getProducedItemID());
int pToken = 0;
int sToken = 0;
if (!this.isRandom()) {
EffectsBase eb = PowersManager.getEffectByIDString(this.getPrefix());
if (eb != null)
pToken = eb.getToken();
eb = PowersManager.getEffectByIDString(this.getSuffix());
if (eb != null)
sToken = eb.getToken();
}
Item item = npc.produceItem(0, this.getAmount(), this.isRandom(), pToken, sToken, this.getName(), this.getTemplateID());
if (item == null)
return false;
} else {
//update item to complete
MobLoot targetItem = MobLoot.getFromCache(this.getProducedItemID());
if (targetItem == null)
return false;
ItemProductionMsg outMsg = new ItemProductionMsg(npc.getBuilding(), npc, targetItem, 8, true);
DispatchMessage.dispatchMsgToInterestArea(npc, outMsg, DispatchChannel.SECONDARY, 700, false, false);
}
} catch (Exception e) {
Logger.error(e);
return false;
}
return true;
}
public int getPlayerID() {
return playerID;
}
}

6
src/engine/server/world/WorldServer.java

@ -26,7 +26,6 @@ import engine.mbEnums.SupportMsgType;
import engine.mobileAI.Threads.MobAIThread; import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.Threads.Respawner; import engine.mobileAI.Threads.Respawner;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.ItemProductionManager;
import engine.net.Network; import engine.net.Network;
import engine.net.Protocol; import engine.net.Protocol;
import engine.net.client.ClientConnection; import engine.net.client.ClientConnection;
@ -267,9 +266,6 @@ public class WorldServer {
Logger.info("Setting cross server session behavior"); Logger.info("Setting cross server session behavior");
SessionManager.setCrossServerBehavior(1); // Sets cross server behavior SessionManager.setCrossServerBehavior(1); // Sets cross server behavior
Logger.info("Starting Item Production thread");
ItemProductionManager.ITEMPRODUCTIONMANAGER.startMessagePump();
Logger.info("Initializing Errant Guild"); Logger.info("Initializing Errant Guild");
Guild.getErrantGuild(); Guild.getErrantGuild();
@ -427,8 +423,6 @@ public class WorldServer {
//pick a startup Hotzone //pick a startup Hotzone
ZoneManager.generateAndSetRandomHotzone(); ZoneManager.generateAndSetRandomHotzone();
ItemProductionManager.ITEMPRODUCTIONMANAGER.initialize();
Logger.info("Loading Player Heraldries"); Logger.info("Loading Player Heraldries");
DbManager.PlayerCharacterQueries.LOAD_HERALDY(); DbManager.PlayerCharacterQueries.LOAD_HERALDY();

Loading…
Cancel
Save