// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.mobileAI.Threads; import engine.gameManager.ZoneManager; import engine.objects.Mob; import engine.objects.Zone; import org.pmw.tinylog.Logger; import java.util.ArrayList; import java.util.Collection; /** * 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 { private volatile boolean running = true; private static final long RESPAWN_INTERVAL = 100; // Configurable interval public MobRespawnThread() { Logger.info("MobRespawnThread initialized."); } @Override public void run() { while (running) { try { Collection zones = ZoneManager.getAllZones(); if (zones != null) { for (Zone zone : zones) { synchronized (zone) { // Optional: Synchronize on zone if (!zone.respawnQue.isEmpty() && zone.lastRespawn + RESPAWN_INTERVAL < System.currentTimeMillis()) { Mob respawner = zone.respawnQue.iterator().next(); if (respawner != null) { respawner.respawn(); zone.respawnQue.remove(respawner); zone.lastRespawn = System.currentTimeMillis(); } } } } } Thread.sleep(100); // Prevent busy-waiting } catch (Exception e) { Logger.error("Error in MobRespawnThread", e); } } Logger.info("MobRespawnThread stopped."); } public void stop() { running = false; } public static void startRespawnThread() { Thread respawnThread = new Thread(new MobRespawnThread()); respawnThread.setName("respawnThread"); respawnThread.start(); } }