diff --git a/src/engine/InterestManagement/RealmMap.java b/src/engine/InterestManagement/RealmMap.java index 89d7b4ad..57b3c71c 100644 --- a/src/engine/InterestManagement/RealmMap.java +++ b/src/engine/InterestManagement/RealmMap.java @@ -8,10 +8,6 @@ package engine.InterestManagement; -/* This class is the main interface for Magicbane's - * Interest management facilities. - */ - import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.net.Dispatch; @@ -31,10 +27,17 @@ import static engine.objects.Realm.getRealm; public enum RealmMap { - REALM_MAP; + // MB Dev Notes: + // This class loads and caches realm maps used by each + // map set for its realm overlay. The RealmMap loaded is + // controlled by config entry MB_WORLD_REALMMAP + // + // Unlike a Heightmap this is a just color lookup; identical to + // the old image maps used in 90s web technology. + // + // Realm Map images are stored on disk in /mb.data/realmmaps/ - // Spatial hashmap. Used for determining which Realm - // a player is currently located within. + REALM_MAP; private static final HashMap _rgbToIDMap = new HashMap<>(); public static int[][] _realmImageMap; diff --git a/src/engine/InterestManagement/Terrain.java b/src/engine/InterestManagement/Terrain.java index abd0e638..c52f84a7 100644 --- a/src/engine/InterestManagement/Terrain.java +++ b/src/engine/InterestManagement/Terrain.java @@ -18,6 +18,14 @@ import java.util.HashMap; import static java.lang.Math.PI; + +// MB Dev Notes: +// The Terrain class handles lookups into the Heightmap data. +// It supports all current maps along with the differences in +// their parenting configuration. +// +// Heightmap images are stored on disk in /mb.data/heightmaps/ + public class Terrain { public static final HashMap _heightmap_pixel_cache = new HashMap<>(); public short[][] terrain_pixel_data; diff --git a/src/engine/gameManager/SimulationManager.java b/src/engine/gameManager/SimulationManager.java index 1ac64199..cbe9f13d 100644 --- a/src/engine/gameManager/SimulationManager.java +++ b/src/engine/gameManager/SimulationManager.java @@ -24,10 +24,16 @@ import java.time.Duration; import java.time.Instant; import java.util.Collection; -/* - * This class contains all methods necessary to drive periodic - * updates of the game simulation from the main _exec loop. - */ +// MB Dev Notes: +// +// Class models timers that drive Magicbane simulation ticks used +// for movement updates, triggers and more. Eventually we hope to +// refactor to more of a traditional simulation appropriate for a +// mmo with a transform class and other bells and whistles. +// +// Do as little as possible in here. For any tick you do not want +// deltaTime to approach 1.0f. + public enum SimulationManager { SERVERHEARTBEAT; @@ -35,15 +41,14 @@ public enum SimulationManager { private static final long CITY_PULSE = 2000; private static final long RUNEGATE_PULSE = 3000; private static final long UPDATE_PULSE = 1000; - private static final long FlIGHT_PULSE = 100; + private static final long FLIGHT_PULSE = 100; public static Duration executionTime = Duration.ofNanos(1); public static Duration executionMax = Duration.ofNanos(1); - private static SimulationManager instance = null; private long _cityPulseTime = System.currentTimeMillis() + CITY_PULSE; private long _runegatePulseTime = System.currentTimeMillis() + RUNEGATE_PULSE; private long _updatePulseTime = System.currentTimeMillis() + UPDATE_PULSE; - private long _flightPulseTime = System.currentTimeMillis() + FlIGHT_PULSE; + private long _flightPulseTime = System.currentTimeMillis() + FLIGHT_PULSE; private SimulationManager() { @@ -181,7 +186,7 @@ public enum SimulationManager { player.updateFlight(); } - _flightPulseTime = System.currentTimeMillis() + FlIGHT_PULSE; + _flightPulseTime = System.currentTimeMillis() + FLIGHT_PULSE; } private void pulseCities() { diff --git a/src/engine/loot/WorkOrder.java b/src/engine/loot/WorkOrder.java index 9b12f22e..ebd2fc83 100644 --- a/src/engine/loot/WorkOrder.java +++ b/src/engine/loot/WorkOrder.java @@ -33,7 +33,7 @@ public class WorkOrder implements Delayed { // MB Dev notes: // Class defines a Forge rolling request made through a - // vendor and then passed to the ForgeManager singleton + // vendor; then passed to the ForgeManager singleton // for completion. // // A workOrder once created will last until all items are diff --git a/src/engine/net/MessageDispatcher.java b/src/engine/net/MessageDispatcher.java index 3466b161..6d774ae5 100644 --- a/src/engine/net/MessageDispatcher.java +++ b/src/engine/net/MessageDispatcher.java @@ -17,29 +17,31 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.LongAdder; import java.util.regex.Pattern; -/** - * 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. - */ +// MB Dev Notes: +// All outgoing Protocol messages to the player are managed through the MessageDispatcher.class. +// All incoming Protocol messages from the player are managed by the Protocol.class. +// +// A DispatchMessage is configured then wrapped in a Dispatch for a distribution list. +// A Dispatch can be submitted to the Dispatcher from any thread. +// +// Dispatches are interleaved between channels. This is to ensure +// a combat or movement message is not delayed by spam clicking a +// larger message. Choose your channel wisely. public class MessageDispatcher implements Runnable { // Instance variables - @SuppressWarnings("unchecked") // Cannot have arrays of generics in java. private static final ConcurrentLinkedQueue[] _messageQueue = new ConcurrentLinkedQueue[DispatchChannel.values().length]; private static final LinkedBlockingQueue _blockingQueue = new LinkedBlockingQueue<>(); // Class variables + public static volatile long[] messageCount = new long[DispatchChannel.values().length]; public static LongAdder[] dispatchCount = new LongAdder[DispatchChannel.values().length]; // Performance metrics + public static volatile long[] maxRecipients = new long[DispatchChannel.values().length]; public static LongAdder itemPoolSize = new LongAdder(); private final Pattern filterPattern; // Unused, but just in case @@ -61,6 +63,35 @@ public class MessageDispatcher implements Runnable { } + @Override + public void run() { + + boolean shouldBlock; + + while (true) { + try { + + shouldBlock = true; + + for (DispatchChannel dispatchChannel : DispatchChannel.values()) { + + this.messageDispatch = _messageQueue[dispatchChannel.getChannelID()].poll(); + + if (this.messageDispatch != null) { + DispatchMessage.serializeDispatch(this.messageDispatch); + shouldBlock = false; + } + } + + if (shouldBlock == true) + shouldBlock = _blockingQueue.take(); + } catch (Exception e) { + Logger.error(e); + } + + } + } + public static void send(Dispatch messageDispatch, DispatchChannel dispatchChannel) { // Don't queue up empty dispatches! @@ -74,12 +105,11 @@ public class MessageDispatcher implements Runnable { // Update performance metrics messageCount[dispatchChannel.getChannelID()]++; - } public static String getNetstatString() { - String outString = null; + String outString; String newLine = System.getProperty("line.separator"); outString = "[LUA_NETSTA()]" + newLine; outString += "poolSize: " + itemPoolSize.longValue() + '\n'; @@ -94,37 +124,6 @@ public class MessageDispatcher implements Runnable { return outString; } - @Override - public void run() { - - boolean shouldBlock; - - while (true) { - try { - - shouldBlock = true; - - for (DispatchChannel dispatchChannel : DispatchChannel.values()) { - - this.messageDispatch = _messageQueue[dispatchChannel.getChannelID()].poll(); - - if (this.messageDispatch != null) { - DispatchMessage.serializeDispatch(this.messageDispatch); - shouldBlock = false; - } - - } - - if (shouldBlock == true) - shouldBlock = _blockingQueue.take(); - - } catch (Exception e) { - Logger.error(e); - } - - } - } - // For Debugging: //Logger.error("MessageDispatcher", messageDispatch.msg.getOpcodeAsString() + " sent to " + messageDispatch.playerList.size() + " players"); } diff --git a/src/engine/net/Protocol.java b/src/engine/net/Protocol.java index ec9ef72e..a6e94ddd 100644 --- a/src/engine/net/Protocol.java +++ b/src/engine/net/Protocol.java @@ -1,8 +1,12 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2022 +// www.magicbane.com package engine.net; -/* This class defines Magicbane's application network protocol. ---> Name / Opcode / Message / Handler - */ import engine.net.client.handlers.*; import engine.net.client.msg.*; @@ -16,6 +20,13 @@ import org.pmw.tinylog.Logger; import java.lang.reflect.Constructor; import java.util.HashMap; +// MB Dev Notes: +// This class defines the application network protocol used by SB. +// --> Name / Opcode / Message / Handler +// +// All incoming Protocol messages from the player are managed by the Protocol.class. +// All outgoing Protocol messages to the player are managed through the MessageDispatcher.class. + public enum Protocol { NONE(0x0, null, null), @@ -286,9 +297,7 @@ public enum Protocol { public static boolean handleClientMsg(ClientNetMsg msg) { - // Main message handler for Magicbane. All messages - // incoming from the client are executed here for - // both the login and world servers. + // Process incoming Protocol message from client. if (msg == null) return false;