From 25842c75189b4b54260716f508068fe847a887e9 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 28 Jun 2026 21:20:30 +0200 Subject: [PATCH] AI slop fix --- .../core/game/node/entity/player/Player.java | 4 +++ .../main/core/game/world/map/RegionManager.kt | 35 ++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index cb94a83bd..8c90934ba 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -380,6 +380,10 @@ public class Player extends Entity { } interfaceManager.close(); interfaceManager.closeSingleTab(); + if (getAttribute("region-viewcounted", false)) { + RegionManager.decrementViewBlock(getLocation().getRegionX(), getLocation().getRegionY()); + removeAttribute("region-viewcounted"); + } super.clear(); getZoneMonitor().clear(); HouseManager.leave(this); diff --git a/Server/src/main/core/game/world/map/RegionManager.kt b/Server/src/main/core/game/world/map/RegionManager.kt index 0407a569f..63d05f7b2 100644 --- a/Server/src/main/core/game/world/map/RegionManager.kt +++ b/Server/src/main/core/game/world/map/RegionManager.kt @@ -399,23 +399,50 @@ object RegionManager { when (entity) { is Player -> { src.chunk.removePlayer(entity) - src.region.decrementViewAmount() dst.chunk.addPlayer(entity) - dst.region.incrementViewAmount() - dst.region.flagActive() + // Compare at region granularity to detect a region (not just chunk) change. + if ((src.regionX shr 3) != (dst.regionX shr 3) || (src.regionY shr 3) != (dst.regionY shr 3)) { + if (entity.getAttribute("region-viewcounted", false)) { + forViewedRegions(src.regionX, src.regionY) { it.decrementViewAmount(); it.checkInactive() } + } + forViewedRegions(dst.regionX, dst.regionY) { it.incrementViewAmount(); it.flagActive() } + entity.setAttribute("region-viewcounted", true) + } } is NPC -> { src.chunk.remove(entity) dst.chunk.add(entity) } else -> { - throw (IllegalStateException("Tried to move an Entity that was neither Player nor NPC")) + throw IllegalStateException("Tried to move an Entity that was neither Player nor NPC") } } } entity.zoneMonitor.updateLocation(entity.walkingQueue.footPrint) } + /** + * Iterates the 3x3 block of regions surrounding the region containing the given chunk coordinates, + * running the action on each. Mirrors the pre-MR view-counting loop. + * @param chunkRegionX chunk-granularity x (i.e. Location.regionX, which is x >> 3). + * @param chunkRegionY chunk-granularity y (i.e. Location.regionY, which is y >> 3). + */ + private inline fun forViewedRegions(chunkRegionX: Int, chunkRegionY: Int, action: (Region) -> Unit) { + val regionX = chunkRegionX shr 3 // chunk -> region granularity + val regionY = chunkRegionY shr 3 + for (rx in (regionX - 1)..(regionX + 1)) { + for (ry in (regionY - 1)..(regionY + 1)) { + if (rx < 0 || ry < 0) continue + action(forId((rx shl 8) or ry)) + } + } + } + + @JvmStatic + fun decrementViewBlock(chunkRegionX: Int, chunkRegionY: Int) { + forViewedRegions(chunkRegionX, chunkRegionY) { it.decrementViewAmount(); it.checkInactive() } + } + /** * Gets local entities. You never call the below function directly (it's inlined); instead, you use one of the typed helpers defined directly below this function. * @param location the location.