// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com // • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.net; import engine.Enum.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. * * 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 private ItemQueue itemQueue; private long nextFailedItemAudit; // Class variables @SuppressWarnings("unchecked") // Cannot have arrays of generics in java. private static final DelayQueue producedQueue = new DelayQueue<>(); // Performance metrics public static volatile long[] messageCount = new long[DispatchChannel.values().length]; public static LongAdder[] dispatchCount = new LongAdder[DispatchChannel.values().length]; public static volatile long[] maxRecipients = new long[DispatchChannel.values().length]; public static LongAdder dispatchPoolSize = new LongAdder(); public static HashSet FailedItems = new HashSet<>(); public Thread itemProductionThread = null; // Thread constructor public void startMessagePump() { itemProductionThread = new Thread(this); itemProductionThread.setName("ItemProductionManager"); } public void initialize(){ itemProductionThread.start(); } public static void send(ItemQueue item) { // Don't queue up empty dispatches! if (item == null) return; producedQueue.add(item); } @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); } } } 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; } // For Debugging: //Logger.error("MessageDispatcher", messageDispatch.msg.getOpcodeAsString() + " sent to " + messageDispatch.playerList.size() + " players"); }