diff --git a/Server/src/main/java/core/game/world/map/Region.java b/Server/src/main/java/core/game/world/map/Region.java index 03a67a65e..d5e89f1d6 100644 --- a/Server/src/main/java/core/game/world/map/Region.java +++ b/Server/src/main/java/core/game/world/map/Region.java @@ -149,6 +149,18 @@ public class Region { } } + public void remove(RegionZone zone) { + regionZones.remove(zone); + for (RegionPlane plane : planes) { + for (NPC npc : plane.getNpcs()) { + npc.getZoneMonitor().updateLocation(npc.getLocation()); + } + for (Player p : plane.getPlayers()) { + p.getZoneMonitor().updateLocation(p.getLocation()); + } + } + } + /** * Adds a player to this region. * @param player The player. diff --git a/Server/src/main/java/core/game/world/map/zone/MapZone.java b/Server/src/main/java/core/game/world/map/zone/MapZone.java index 48d93b0fb..8ab49ec8a 100644 --- a/Server/src/main/java/core/game/world/map/zone/MapZone.java +++ b/Server/src/main/java/core/game/world/map/zone/MapZone.java @@ -14,6 +14,7 @@ import core.game.world.map.Region; import core.game.world.map.RegionManager; import java.util.Iterator; +import java.util.Objects; /** * Represents a map zone. @@ -299,6 +300,15 @@ public abstract class MapZone implements Zone { } } + public void unregister(ZoneBorders borders) { + for (Integer id : borders.getRegionIds()) { + Region r = RegionManager.forId(id); + if (r != null) { + r.remove(new RegionZone(this, borders)); + } + } + } + /** * Registers this zone in the region for the given id. * @param regionId The region id. @@ -378,7 +388,7 @@ public abstract class MapZone implements Zone { * @return The uid. */ public int getUid() { - return uid; + return getName().hashCode(); } /** @@ -455,4 +465,17 @@ public abstract class MapZone implements Zone { this.zoneType = type; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MapZone mapZone = (MapZone) o; + return getUid() == mapZone.getUid(); + } + + @Override + public int hashCode() { + return Objects.hash(uid, name, overlappable, fireRandomEvents, restriction, zoneType); + } } \ No newline at end of file diff --git a/Server/src/main/java/core/game/world/map/zone/RegionZone.java b/Server/src/main/java/core/game/world/map/zone/RegionZone.java index 102755f10..4c4c112e5 100644 --- a/Server/src/main/java/core/game/world/map/zone/RegionZone.java +++ b/Server/src/main/java/core/game/world/map/zone/RegionZone.java @@ -1,5 +1,7 @@ package core.game.world.map.zone; +import java.util.Objects; + /** * Represents a zone inside a single region of the world map. * @author Emperor @@ -42,4 +44,16 @@ public final class RegionZone { return zone; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RegionZone that = (RegionZone) o; + return Objects.equals(zone, that.zone) && Objects.equals(borders, that.borders); + } + + @Override + public int hashCode() { + return Objects.hash(zone, borders); + } } \ No newline at end of file diff --git a/Server/src/main/java/core/game/world/map/zone/ZoneBorders.java b/Server/src/main/java/core/game/world/map/zone/ZoneBorders.java index cb1bd8917..ee3e55e94 100644 --- a/Server/src/main/java/core/game/world/map/zone/ZoneBorders.java +++ b/Server/src/main/java/core/game/world/map/zone/ZoneBorders.java @@ -6,6 +6,7 @@ import core.tools.RandomFunction; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Random; /** @@ -268,4 +269,17 @@ public final class ZoneBorders { public boolean insideRegion(Node n) { return insideBorder(n.getLocation().getRegionX(), n.getLocation().getRegionY()); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ZoneBorders that = (ZoneBorders) o; + return southWestX == that.southWestX && southWestY == that.southWestY && northEastX == that.northEastX && northEastY == that.northEastY && plane == that.plane && zeroPlaneCheck == that.zeroPlaneCheck && Objects.equals(exceptions, that.exceptions); + } + + @Override + public int hashCode() { + return Objects.hash(southWestX, southWestY, northEastX, northEastY, plane, exceptions, zeroPlaneCheck); + } } \ No newline at end of file diff --git a/Server/src/main/kotlin/api/MapArea.kt b/Server/src/main/kotlin/api/MapArea.kt index 1888c1fc1..0a1945695 100644 --- a/Server/src/main/kotlin/api/MapArea.kt +++ b/Server/src/main/kotlin/api/MapArea.kt @@ -2,6 +2,8 @@ package api import core.game.node.entity.Entity import core.game.world.map.Location +import core.game.world.map.zone.MapZone +import core.game.world.map.zone.RegionZone import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction @@ -10,9 +12,21 @@ import core.game.world.map.zone.ZoneRestriction * Optionally-overridable methods include [getRestrictions], [areaEnter], [areaLeave] and [entityStep] */ interface MapArea { + var zone: MapZone + get(){ + return zoneMaps[this.javaClass.simpleName + "MapArea"]!! + } + set(value) { + zoneMaps[this.javaClass.simpleName + "MapArea"] = value + } + fun defineAreaBorders() : Array fun getRestrictions() : Array {return arrayOf()} fun areaEnter(entity: Entity) {} fun areaLeave(entity: Entity, logout: Boolean) {} fun entityStep(entity: Entity, location: Location, lastLocation: Location) {} + + companion object { + val zoneMaps = HashMap() + } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/activity/fishingtrawler/FishingTrawlerSession.kt b/Server/src/main/kotlin/rs09/game/content/activity/fishingtrawler/FishingTrawlerSession.kt index ece074601..67810b1c1 100644 --- a/Server/src/main/kotlin/rs09/game/content/activity/fishingtrawler/FishingTrawlerSession.kt +++ b/Server/src/main/kotlin/rs09/game/content/activity/fishingtrawler/FishingTrawlerSession.kt @@ -1,7 +1,10 @@ package rs09.game.content.activity.fishingtrawler import api.LogoutListener +import api.MapArea +import api.getRegionBorders import core.game.component.Component +import core.game.node.entity.Entity import core.game.node.scenery.Scenery import core.game.node.scenery.SceneryBuilder import core.game.node.entity.npc.NPC @@ -12,6 +15,8 @@ import core.game.system.task.Pulse import rs09.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.build.DynamicRegion +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction import core.game.world.update.flag.context.Animation import core.plugin.Plugin import core.tools.* @@ -20,6 +25,7 @@ import org.rs09.consts.Items import rs09.game.node.entity.player.info.stats.FISHING_TRAWLER_GAMES_WON import rs09.game.node.entity.player.info.stats.FISHING_TRAWLER_SHIPS_SANK import rs09.game.node.entity.player.info.stats.STATS_BASE +import rs09.game.system.SystemLogger import rs09.tools.secondsToTicks import rs09.tools.ticksToSeconds import java.util.concurrent.TimeUnit @@ -38,7 +44,7 @@ private const val HOLE_SOUTH_Y = 23 private const val LEAKING_ID = 2167 private const val PATCHED_ID = 2168 -class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : LogoutListener { +class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : LogoutListener, MapArea { constructor(region: DynamicRegion, activity: FishingTrawlerActivity) : this(activity) {this.region = region; this.base = region.baseLocation} var players: ArrayList = ArrayList() var netRipped = false @@ -77,6 +83,7 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo player.setAttribute("ft-session",this) player.stateManager.set(EntityState.TELEBLOCK,timeLeft) } + zone.register(getRegionBorders(region.id)) } fun swapBoatType(fromRegion: Int){ @@ -129,6 +136,7 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo session.boatSank = true session.isActive = false session.swapBoatType(7755) + session.zone.unregister(getRegionBorders(session.region.id)) } if(RandomFunction.random(100) <= 9){ @@ -142,6 +150,7 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo player.properties.teleportLocation = Location.create(2666, 3162, 0) player.incrementAttribute("/save:$STATS_BASE:$FISHING_TRAWLER_GAMES_WON") } + session.zone.unregister(getRegionBorders(session.region.id)) } for(player in session.players){ @@ -275,4 +284,22 @@ class FishingTrawlerSession(val activity: FishingTrawlerActivity? = null) : Logo player.location = Location.create(2667, 3161, 0) session.players.remove(player) } + + override fun defineAreaBorders(): Array { + return arrayOf() + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.CANNON, ZoneRestriction.FIRES, ZoneRestriction.RANDOM_EVENTS) + } + + override fun areaEnter(entity: Entity) { + super.areaEnter(entity) + SystemLogger.logInfo("ENTERED FTZ") + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + super.areaLeave(entity, logout) + SystemLogger.logInfo("EXITED FTZ") + } } diff --git a/Server/src/main/kotlin/rs09/game/content/ame/RandomEventManager.kt b/Server/src/main/kotlin/rs09/game/content/ame/RandomEventManager.kt index 3995fb24d..55d90efe2 100644 --- a/Server/src/main/kotlin/rs09/game/content/ame/RandomEventManager.kt +++ b/Server/src/main/kotlin/rs09/game/content/ame/RandomEventManager.kt @@ -46,6 +46,7 @@ class RandomEventManager(val player: Player? = null) : LoginListener, EventHook< nextSpawn = GameWorld.ticks + 3000 return } + if (getAttribute(player, "re-npc", null) != null) return val currentAction = player.pulseManager.current.toString() val ame: RandomEvents = if(currentAction.contains("WoodcuttingSkillPulse") && Random.nextBoolean()){ RandomEvents.TREE_SPIRIT diff --git a/Server/src/main/kotlin/rs09/game/content/ame/RandomEventNPC.kt b/Server/src/main/kotlin/rs09/game/content/ame/RandomEventNPC.kt index 192abefe6..0d17b92e2 100644 --- a/Server/src/main/kotlin/rs09/game/content/ame/RandomEventNPC.kt +++ b/Server/src/main/kotlin/rs09/game/content/ame/RandomEventNPC.kt @@ -54,6 +54,10 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { override fun tick() { super.tick() + if(player.getAttribute("re-npc", null) != this){ + terminate() + return + } if (!player.getAttribute("random:pause", false)) { ticksLeft-- } @@ -76,6 +80,7 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { timerPaused = false spawnLocation ?: terminate() location = spawnLocation + player.setAttribute("re-npc", this) super.init() } @@ -100,5 +105,10 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { player.graphics(SMOKE_GRAPHICS) } + override fun clear() { + super.clear() + if(player.getAttribute("re-npc", null) == this) player.removeAttribute("re-npc") + } + abstract fun talkTo(npc: NPC) } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/plugin/ClassScanner.kt b/Server/src/main/kotlin/rs09/plugin/ClassScanner.kt index 4d5bf1c90..8ec560e9f 100644 --- a/Server/src/main/kotlin/rs09/plugin/ClassScanner.kt +++ b/Server/src/main/kotlin/rs09/plugin/ClassScanner.kt @@ -112,6 +112,8 @@ object ClassScanner { } for(border in clazz.defineAreaBorders()) zone.register(border) ZoneBuilder.configure(zone) + SystemLogger.logInfo("Configured zone: ${clazz.javaClass.simpleName + "MapArea"}") + MapArea.zoneMaps[clazz.javaClass.simpleName + "MapArea"] = zone } } catch (e: Exception) { SystemLogger.logErr("Error loading content: ${it.simpleName}, ${e.localizedMessage}")