diff --git a/src/engine/ai/MobileFSMManager.java b/src/engine/ai/MobileFSMManager.java index c4bd7624..39d89849 100644 --- a/src/engine/ai/MobileFSMManager.java +++ b/src/engine/ai/MobileFSMManager.java @@ -94,13 +94,6 @@ public class MobileFSMManager { for (Zone zone : ZoneManager.getAllZones()) { - if(zone.respawnQue.size() > 0 && zone.lastRespawn + 100 < System.currentTimeMillis()){ - if(zone.respawnQue.get(0) != null) { - zone.respawnQue.get(0).respawn(); - zone.respawnQue.remove(0); - zone.lastRespawn = System.currentTimeMillis(); - } - } for (Mob mob : zone.zoneMobSet) { try { diff --git a/src/engine/objects/Zone.java b/src/engine/objects/Zone.java index 8fbd4990..45314553 100644 --- a/src/engine/objects/Zone.java +++ b/src/engine/objects/Zone.java @@ -58,7 +58,8 @@ public class Zone extends AbstractGameObject { private String hash; private float worldAltitude = 0; private float seaLevel = 0; - public static ArrayList respawnQue = new ArrayList<>(); + //public static ArrayList respawnQue = new ArrayList<>(); + public static final Set respawnQue = Collections.newSetFromMap(new ConcurrentHashMap<>()); public static long lastRespawn = 0; /** * ResultSet Constructor diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index 48c2edfd..15acc575 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -18,6 +18,7 @@ import engine.InterestManagement.HeightMap; import engine.InterestManagement.RealmMap; import engine.InterestManagement.WorldGrid; import engine.ai.MobileFSMManager; +import engine.workthreads.MobRespawnThread; import engine.db.archive.DataWarehouse; import engine.exception.MsgSendException; import engine.gameManager.*; @@ -57,6 +58,7 @@ import java.net.InetAddress; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -479,7 +481,10 @@ public class WorldServer { Logger.info("Initializing Client Connection Manager"); initClientConnectionManager(); - + + //intiate mob respawn thread + Logger.info("Starting network Dispatcher"); + MobRespawnThread.startRespawnThread(); // Run maintenance MaintenanceManager.dailyMaintenance(); @@ -494,7 +499,7 @@ public class WorldServer { // Calculate bootstrap time and rest boot time to current time. - java.time.Duration bootDuration = java.time.Duration.between(LocalDateTime.now(), bootTime); + Duration bootDuration = Duration.between(LocalDateTime.now(), bootTime); long bootSeconds = Math.abs(bootDuration.getSeconds()); String boottime = String.format("%d hours %02d minutes %02d seconds", bootSeconds / 3600, (bootSeconds % 3600) / 60, (bootSeconds % 60)); Logger.info("Bootstrap time was " + boottime); diff --git a/src/engine/workthreads/MobRespawnThread.java b/src/engine/workthreads/MobRespawnThread.java new file mode 100644 index 00000000..a0a6affa --- /dev/null +++ b/src/engine/workthreads/MobRespawnThread.java @@ -0,0 +1,74 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2022 +// www.magicbane.com + + +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2022 +// www.magicbane.com + + +package engine.workthreads; + +import engine.Enum.DispatchChannel; +import engine.gameManager.ZoneManager; +import engine.net.Dispatch; +import engine.objects.Mob; +import engine.objects.Zone; +import org.pmw.tinylog.Logger; + +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * 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 class MobRespawnThread implements Runnable { + + // Instance variables + + + // Thread constructor + + public MobRespawnThread() { + + Logger.info(" MobRespawnThread thread has started!"); + + } + + @Override + public void run() { + for (Zone zone : ZoneManager.getAllZones()) { + if (zone.respawnQue.isEmpty() == false && zone.lastRespawn + 100 < System.currentTimeMillis()) { + if (zone.respawnQue.iterator().next() != null) { + Mob respawner = zone.respawnQue.iterator().next(); + respawner.respawn(); + zone.respawnQue.remove(respawner); + zone.lastRespawn = System.currentTimeMillis(); + } + } + } + } + public static void startRespawnThread() { + + Thread respawnThread; + respawnThread = new Thread(new PurgeOprhans()); + + respawnThread.setName("respawnThread"); + respawnThread.start(); + } +}