diff --git a/Server/src/main/java/core/game/node/entity/skill/construction/HouseManager.java b/Server/src/main/java/core/game/node/entity/skill/construction/HouseManager.java index c2a912fbb..6165205c7 100644 --- a/Server/src/main/java/core/game/node/entity/skill/construction/HouseManager.java +++ b/Server/src/main/java/core/game/node/entity/skill/construction/HouseManager.java @@ -198,11 +198,19 @@ public final class HouseManager { player.lock(1); player.sendMessage("House location: " + region.getBaseLocation() + ", entry: " + getEnterLocation()); player.getProperties().setTeleportLocation(getEnterLocation()); - player.getInterfaceManager().openComponent(399); + openLoadInterface(player); player.getConfigManager().set(261, buildingMode); player.getConfigManager().set(262, getRoomAmount()); - player.getAudioManager().send(new Audio(984)); player.getMusicPlayer().unlock(454, true); + } + + public void openLoadInterface(Player player) { + player.getInterfaceManager().openComponent(399); + player.getAudioManager().send(new Audio(984)); + submitCloseLoadInterfacePulse(player); + } + + public void submitCloseLoadInterfacePulse(Player player) { GameWorld.getPulser().submit(new Pulse(1, player) { @Override public boolean pulse() { @@ -212,7 +220,6 @@ public final class HouseManager { player.getDialogueInterpreter().sendDialogues(servant.getType().getId(), servant.getType().getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "Welcome."); } } -// player.getInterfaceManager().switchWindowMode(1); player.getInterfaceManager().close(); return true; } @@ -685,7 +692,7 @@ public final class HouseManager { * @return {@code True} if an active region for the house exists. */ public boolean isLoaded() { - return region != null && region.isActive() || dungeon != null && dungeon.isActive(); + return (region != null) || (dungeon != null); } /** diff --git a/Server/src/main/java/core/net/packet/PacketRepository.java b/Server/src/main/java/core/net/packet/PacketRepository.java index 0f872f18f..d95c537d8 100644 --- a/Server/src/main/java/core/net/packet/PacketRepository.java +++ b/Server/src/main/java/core/net/packet/PacketRepository.java @@ -187,6 +187,7 @@ public final class PacketRepository { */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void send(Class clazz, Context context) { + if(context.getPlayer().getSession() == null) return; OutgoingPacket p = OUTGOING_PACKETS.get(clazz); if (p == null) { SystemLogger.logErr("Invalid outgoing packet [handler=" + clazz + ", context=" + context + "]."); diff --git a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt index 509599ce9..147ef28a2 100644 --- a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt +++ b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt @@ -41,55 +41,9 @@ class MajorUpdateWorker { Thread.sleep(600L) while(true){ val start = System.currentTimeMillis() - val rmlist = ArrayList() - val list = ArrayList(GameWorld.Pulser.TASKS) Server.heartbeat() - GlobalScope.launch { - //run our pulses - for (pulse in list) { - val b = System.currentTimeMillis() - if (pulse == null || pulse.update()) rmlist.add(pulse) - - val time = System.currentTimeMillis() - b - - if (time >= 100) { - if (pulse is GeneralBotCreator.BotScriptPulse) { - SystemLogger.logWarn("CRITICALLY Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms") - } else { - SystemLogger.logWarn("CRITICALLY long running pulse: ${pulse.javaClass.name} - $time ms") - } - } else if (time >= 30) { - if (pulse is GeneralBotCreator.BotScriptPulse) { - SystemLogger.logWarn("Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms") - } else { - SystemLogger.logWarn("Long Running Pulse: ${pulse.javaClass.name} - $time ms") - } - } - } - - //remove all null or finished pulses from the list - rmlist.forEach { - if (GameWorld.Pulser.TASKS.contains(it)) GameWorld.Pulser.TASKS.remove(it) - } - - rmlist.clear() - //perform our update sequence where we write masks, etc - try { - sequence.start() - sequence.run() - sequence.end() - } catch (e: Exception) { - e.printStackTrace() - } - //increment global ticks variable - GameWorld.pulse() - //disconnect all players waiting to be disconnected - Repository.disconnectionQueue.update() - GameWorld.tickListeners.forEach { it.tick() } - //tick all manager plugins - Managers.tick() - } + GlobalScope.launch { handleTickActions() } //Handle daily restart if enabled if(sdf.format(Date()).toInt() == 0){ @@ -123,6 +77,54 @@ class MajorUpdateWorker { } } + fun handleTickActions() { + val rmlist = ArrayList() + val list = ArrayList(GameWorld.Pulser.TASKS) + //run our pulses + for (pulse in list) { + val b = System.currentTimeMillis() + if (pulse == null || pulse.update()) rmlist.add(pulse) + + val time = System.currentTimeMillis() - b + + if (time >= 100) { + if (pulse is GeneralBotCreator.BotScriptPulse) { + SystemLogger.logWarn("CRITICALLY Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms") + } else { + SystemLogger.logWarn("CRITICALLY long running pulse: ${pulse.javaClass.name} - $time ms") + } + } else if (time >= 30) { + if (pulse is GeneralBotCreator.BotScriptPulse) { + SystemLogger.logWarn("Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms") + } else { + SystemLogger.logWarn("Long Running Pulse: ${pulse.javaClass.name} - $time ms") + } + } + } + + //remove all null or finished pulses from the list + rmlist.forEach { + if (GameWorld.Pulser.TASKS.contains(it)) GameWorld.Pulser.TASKS.remove(it) + } + + rmlist.clear() + //perform our update sequence where we write masks, etc + try { + sequence.start() + sequence.run() + sequence.end() + } catch (e: Exception) { + e.printStackTrace() + } + //increment global ticks variable + GameWorld.pulse() + //disconnect all players waiting to be disconnected + Repository.disconnectionQueue.update() + GameWorld.tickListeners.forEach { it.tick() } + //tick all manager plugins + Managers.tick() + } + fun start() { if(!started){ worker.start() diff --git a/Server/src/test/kotlin/HouseManagerTests.kt b/Server/src/test/kotlin/HouseManagerTests.kt new file mode 100644 index 000000000..352516dca --- /dev/null +++ b/Server/src/test/kotlin/HouseManagerTests.kt @@ -0,0 +1,24 @@ +import core.game.node.entity.skill.construction.HouseManager +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +class HouseManagerTests { + companion object { + init {TestUtils.preTestSetup()} + } + + val manager = HouseManager() + val testPlayer = TestUtils.getMockPlayer("test") + + @Test fun enterShouldConstructDynamicRegionIfItHasNotBeenConstructed() { + manager.enter(testPlayer, false) + Assertions.assertEquals(true, manager.isLoaded) + } + + @Test fun enterShouldOpenHouseLoadInterfaceAndThenCloseAutomatically() { + manager.enter(testPlayer, false) + Assertions.assertEquals(399, testPlayer.interfaceManager.opened.id) + TestUtils.advanceTicks(5) + Assertions.assertNotEquals(null, testPlayer.interfaceManager.opened) + } +} \ No newline at end of file diff --git a/Server/src/test/kotlin/RegionTests.kt b/Server/src/test/kotlin/RegionTests.kt index 60beed27a..8d957fbd3 100644 --- a/Server/src/test/kotlin/RegionTests.kt +++ b/Server/src/test/kotlin/RegionTests.kt @@ -12,11 +12,7 @@ import rs09.game.system.config.XteaParser class RegionTests { companion object { - init { - ServerConfigParser.parse("worldprops/default.conf") - XteaParser().load() - Cache.init(this::class.java.getResource("cache")?.path.toString()) - } + init {TestUtils.preTestSetup();} } @Test fun testRegionLoad() { diff --git a/Server/src/test/kotlin/TestUtils.kt b/Server/src/test/kotlin/TestUtils.kt index b80c57069..f36db4413 100644 --- a/Server/src/test/kotlin/TestUtils.kt +++ b/Server/src/test/kotlin/TestUtils.kt @@ -1,20 +1,41 @@ +import core.cache.Cache import core.game.node.entity.player.Player import core.game.node.entity.player.info.PlayerDetails import core.game.node.entity.player.link.IronmanMode import core.game.node.item.Item +import rs09.ServerConstants import rs09.game.ai.ArtificialSession import rs09.game.content.global.shops.Shop import rs09.game.content.global.shops.ShopItem +import rs09.game.system.config.ServerConfigParser +import rs09.game.system.config.XteaParser +import rs09.game.world.GameWorld +import rs09.game.world.repository.Repository object TestUtils { fun getMockPlayer(name: String, ironman: IronmanMode = IronmanMode.NONE): Player { val p = Player(PlayerDetails(name, name)) p.details.session = ArtificialSession.getSingleton() p.ironmanManager.mode = ironman + Repository.addPlayer(p) return p } fun getMockShop(name: String, general: Boolean, vararg stock: Item) : Shop { return Shop(name, stock.map { ShopItem(it.id, it.amount, 100) }.toTypedArray(), general) } + + fun preTestSetup() { + if(ServerConstants.DATA_PATH == null) { + ServerConfigParser.parse("worldprops/test.conf") + XteaParser().load() + Cache.init(this::class.java.getResource("cache").path.toString()) + } + } + + fun advanceTicks(amount: Int) { + for(i in 0 until amount) { + GameWorld.majorUpdateWorker.handleTickActions() + } + } } \ No newline at end of file