Small teardown tweaks for familiar POH entry

This commit is contained in:
dam 2026-07-20 12:34:35 +03:00
parent 8f855105b9
commit bf3953325e
No known key found for this signature in database
GPG key ID: 4AF4E722399663FB
4 changed files with 100 additions and 12 deletions

View file

@ -43,6 +43,11 @@ public final class HouseManager {
*/
private DynamicRegion dungeonRegion;
/**
* If the current regions have been handed off to delayed teardown.
*/
private boolean teardownPending;
/**
* The house location.
*/
@ -368,9 +373,21 @@ public final class HouseManager {
}
ZoneBuilder.configure(zone);
teardownPending = false;
return houseRegion;
}
/**
* Marks the current regions as unavailable for new entrants and returns the
* exact instances that the delayed teardown must remove.
*
* @return The current house region followed by its optional dungeon region.
*/
Region[] beginTeardown() {
teardownPending = true;
return new Region[] { houseRegion, dungeonRegion };
}
private DynamicRegion getPreparedRegion() {
ZoneBorders borders = DynamicRegion.reserveArea(8,8);
DynamicRegion region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
@ -708,7 +725,7 @@ public final class HouseManager {
// return (houseRegion != null) || (dungeonRegion != null);
//}
public boolean isLoaded() {
return (houseRegion != null && houseRegion.isActive()) || (dungeonRegion != null && dungeonRegion.isActive());
return !teardownPending && ((houseRegion != null && houseRegion.isActive()) || (dungeonRegion != null && dungeonRegion.isActive()));
}
/**

View file

@ -128,19 +128,16 @@ public final class HouseZone extends MapZone {
// The below tears down the house if the owner was the one who left
if (house == p.getHouseManager()) {
house.expelGuests(p);
int toRemove = previousRegion;
int dungRemove = previousDungeon;
Region[] regions = house.beginTeardown();
Region houseToRemove = regions[0];
Region dungeonToRemove = regions[1];
submitWorldPulse(new Pulse(1) {
public boolean pulse() {
Region r = RegionManager.forId(toRemove);
Region dr = dungRemove != -1 ? RegionManager.forId(dungRemove) : null;
RegionManager.removeRegion(toRemove);
unregisterRegion(toRemove);
r.flagInactive();
if (dungRemove != -1) {
RegionManager.removeRegion(dungRemove);
unregisterRegion(dungRemove);
dr.flagInactive();
RegionManager.removeRegion(houseToRemove);
unregisterRegion(houseToRemove.getId());
if (dungeonToRemove != null) {
RegionManager.removeRegion(dungeonToRemove);
unregisterRegion(dungeonToRemove.getId());
}
return true;
}

View file

@ -907,6 +907,23 @@ object RegionManager {
}
}
/**
* Removes a region only if it is still the cached instance for its id.
*
* Delayed cleanup tasks must use this overload so they cannot remove a newer
* dynamic region that has since been assigned the same coordinates.
*/
@JvmStatic
fun removeRegion(region: Region) {
if (lock.tryLock() || LOCK.tryLock(10000, TimeUnit.MILLISECONDS)) {
if (REGION_CACHE[region.id] === region) {
REGION_CACHE.remove(region.id)
}
region.flagInactive(true)
LOCK.unlock()
}
}
/**
* Gets the regionCache.
* @return The regionCache.

View file

@ -0,0 +1,57 @@
package content.global.skill.construction
import TestUtils
import core.game.world.map.Region
import core.game.world.map.RegionManager
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNotSame
import org.junit.jupiter.api.Assertions.assertSame
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
class HouseRegionLifecycleTests {
companion object {
init {
TestUtils.preTestSetup()
}
}
@Test
fun regionPendingTeardownIsNotReusedByImmediateReentry() {
TestUtils.getMockPlayer("house-region-reentry").use { player ->
val house = player.houseManager
house.createNewHouseAt(HouseLocation.RIMMINGTON)
val oldRegion = house.construct()
val regionsToRemove = house.beginTeardown()
assertSame(oldRegion, regionsToRemove[0])
assertFalse(house.isLoaded)
house.preEnter(player, false)
val replacement = house.houseRegion
assertNotSame(oldRegion, replacement)
assertTrue(house.isLoaded)
RegionManager.removeRegion(oldRegion)
assertSame(replacement, house.houseRegion)
assertTrue(replacement.isActive)
RegionManager.removeRegion(replacement)
}
}
@Test
fun delayedRemovalDoesNotEvictAReplacementAtTheSameRegionId() {
val house = HouseManager()
house.createNewHouseAt(HouseLocation.RIMMINGTON)
val oldRegion = house.construct()
val replacement = Region(oldRegion.x, oldRegion.y)
RegionManager.addRegion(replacement.id, replacement)
RegionManager.removeRegion(oldRegion)
assertSame(replacement, RegionManager.regionCache[replacement.id])
RegionManager.removeRegion(replacement.id)
}
}