From 484ec7823dcd74c514c74f8ae73f8782122a727b Mon Sep 17 00:00:00 2001 From: MobiusDev <8391001+MobiusDevelopment@users.noreply.github.com> Date: Tue, 4 Sep 2018 19:27:09 +0000 Subject: [PATCH] L2World related rework. --- .../ai/areas/IsleOfSouls/HillsOfGold.java | 2 +- .../SeedOfAnnihilation.java | 2 +- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../ai/areas/IsleOfSouls/HillsOfGold.java | 2 +- .../SeedOfAnnihilation.java | 2 +- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../ai/areas/IsleOfSouls/HillsOfGold.java | 2 +- .../SeedOfAnnihilation.java | 2 +- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../ai/areas/IsleOfSouls/HillsOfGold.java | 2 +- .../SeedOfAnnihilation.java | 2 +- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../admincommandhandlers/AdminSpawn.java | 34 ++- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- .../admincommandhandlers/AdminSpawn.java | 30 ++- .../admincommandhandlers/AdminTeleport.java | 2 +- .../gameserver/data/xml/impl/FenceData.java | 2 +- .../instancemanager/ItemsOnGroundManager.java | 2 +- .../l2jmobius/gameserver/model/L2Object.java | 10 +- .../l2jmobius/gameserver/model/L2World.java | 208 ++++++++---------- .../gameserver/model/L2WorldRegion.java | 82 ++----- .../gameserver/model/actor/L2Character.java | 28 +-- .../com/l2jmobius/gameserver/util/Util.java | 44 ---- 79 files changed, 1137 insertions(+), 2145 deletions(-) diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java index caac4f6dad..4ecf55b342 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java @@ -61,7 +61,7 @@ public final class HillsOfGold extends AbstractNpcAI { if ((npc != null) && !npc.isDead()) { - L2World.getInstance().forEachVisibleObject(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> + L2World.getInstance().forEachVisibleObjectInRange(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> { if (npc.isInCombat()) { diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java index cc9a31b203..95d4fd9202 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java @@ -344,7 +344,7 @@ public final class SeedOfAnnihilation extends AbstractNpcAI { final Location teleLoc = TELEPORT_ZONES.get(zone.getId()); // Conditions for Quest 454 - L2World.getInstance().forEachVisibleObject(character, L2Npc.class, 500, npc -> + L2World.getInstance().forEachVisibleObjectInRange(character, L2Npc.class, 500, npc -> { if ((npc.getId() == 32738) && (npc.getTarget() != null)) { diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 5517cb573f..ff252416e6 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java index caac4f6dad..4ecf55b342 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java @@ -61,7 +61,7 @@ public final class HillsOfGold extends AbstractNpcAI { if ((npc != null) && !npc.isDead()) { - L2World.getInstance().forEachVisibleObject(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> + L2World.getInstance().forEachVisibleObjectInRange(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> { if (npc.isInCombat()) { diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java index cc9a31b203..95d4fd9202 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java @@ -344,7 +344,7 @@ public final class SeedOfAnnihilation extends AbstractNpcAI { final Location teleLoc = TELEPORT_ZONES.get(zone.getId()); // Conditions for Quest 454 - L2World.getInstance().forEachVisibleObject(character, L2Npc.class, 500, npc -> + L2World.getInstance().forEachVisibleObjectInRange(character, L2Npc.class, 500, npc -> { if ((npc.getId() == 32738) && (npc.getTarget() != null)) { diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 5517cb573f..ff252416e6 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java index caac4f6dad..4ecf55b342 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java @@ -61,7 +61,7 @@ public final class HillsOfGold extends AbstractNpcAI { if ((npc != null) && !npc.isDead()) { - L2World.getInstance().forEachVisibleObject(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> + L2World.getInstance().forEachVisibleObjectInRange(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> { if (npc.isInCombat()) { diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java index cc9a31b203..95d4fd9202 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java @@ -344,7 +344,7 @@ public final class SeedOfAnnihilation extends AbstractNpcAI { final Location teleLoc = TELEPORT_ZONES.get(zone.getId()); // Conditions for Quest 454 - L2World.getInstance().forEachVisibleObject(character, L2Npc.class, 500, npc -> + L2World.getInstance().forEachVisibleObjectInRange(character, L2Npc.class, 500, npc -> { if ((npc.getId() == 32738) && (npc.getTarget() != null)) { diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 5517cb573f..ff252416e6 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java index caac4f6dad..4ecf55b342 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/IsleOfSouls/HillsOfGold.java @@ -61,7 +61,7 @@ public final class HillsOfGold extends AbstractNpcAI { if ((npc != null) && !npc.isDead()) { - L2World.getInstance().forEachVisibleObject(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> + L2World.getInstance().forEachVisibleObjectInRange(npc, L2MonsterInstance.class, npc.getAggroRange(), nearby -> { if (npc.isInCombat()) { diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java index cc9a31b203..95d4fd9202 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/areas/SeedOfAnnihilation/SeedOfAnnihilation.java @@ -344,7 +344,7 @@ public final class SeedOfAnnihilation extends AbstractNpcAI { final Location teleLoc = TELEPORT_ZONES.get(zone.getId()); // Conditions for Quest 454 - L2World.getInstance().forEachVisibleObject(character, L2Npc.class, 500, npc -> + L2World.getInstance().forEachVisibleObjectInRange(character, L2Npc.class, 500, npc -> { if ((npc.getId() == 32738) && (npc.getTarget() != null)) { diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 5517cb573f..ff252416e6 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index e4635fde72..83ec37f6fa 100644 --- a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -218,8 +218,21 @@ public class AdminSpawn implements IAdminCommandHandler Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); RaidBossSpawnManager.getInstance().cleanUp(); DayNightSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); - AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } + AdminData.getInstance().broadcastMessageToGMs("NPC unspawn completed!"); } else if (command.startsWith("admin_spawnday")) { @@ -234,7 +247,20 @@ public class AdminSpawn implements IAdminCommandHandler // make sure all spawns are deleted RaidBossSpawnManager.getInstance().cleanUp(); DayNightSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); SpawnTable.getInstance().load(); @@ -242,7 +268,7 @@ public class AdminSpawn implements IAdminCommandHandler AutoSpawnHandler.getInstance().reload(); SevenSigns.getInstance().spawnSevenSignsNPC(); QuestManager.getInstance().reloadAllScripts(); - AdminData.getInstance().broadcastMessageToGMs("NPC Respawn completed!"); + AdminData.getInstance().broadcastMessageToGMs("NPC respawn completed!"); } else if (command.startsWith("admin_spawn_monster") || command.startsWith("admin_spawn")) { diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index b7a68ad605..e504f588d3 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -182,7 +182,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index 7b29d65274..f8245be14b 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2Object.java index c32500ec02..2fea6dc474 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2Object.java @@ -171,7 +171,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -209,14 +209,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2World.java index 0a9d4adbae..c1a46e3dec 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2World.java @@ -34,14 +34,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -53,11 +52,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 26; @@ -66,23 +64,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -95,7 +90,7 @@ public final class L2World /** Map with the pets instances and their owner ID. */ private final Map _petsInstance = new ConcurrentHashMap<>(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -104,14 +99,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -135,7 +127,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -172,7 +164,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -305,7 +297,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -580,47 +572,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceId() != object.getInstanceId()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -636,62 +590,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceId() != object.getInstanceId()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceId() != object.getInstanceId()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -718,24 +659,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -744,7 +692,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -754,31 +702,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } /** diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index e58ef16934..649e291f45 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 7f76fe1b81..4574eeffc8 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -62,7 +62,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -72,7 +71,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.actor.instance.L2QuestGuardInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; import com.l2jmobius.gameserver.model.actor.tasks.character.FlyToLocationTask; @@ -3983,31 +3981,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/util/Util.java index ae3d7cc408..839e8c8b07 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/com/l2jmobius/gameserver/util/Util.java @@ -235,50 +235,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param str - the String to count * @return the number of "words" in a given string. diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 4b83d3f027..8c027b3ded 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 4b83d3f027..8c027b3ded 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java index 8e8135cb0a..5c219e3877 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java +++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminSpawn.java @@ -213,14 +213,40 @@ public class AdminSpawn implements IAdminCommandHandler { Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.THE_NPC_SERVER_IS_NOT_OPERATING_AT_THIS_TIME)); DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } AdminData.getInstance().broadcastMessageToGMs("NPC Unspawn completed!"); } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) { // make sure all spawns are deleted DBSpawnManager.getInstance().cleanUp(); - L2World.getInstance().deleteVisibleNpcSpawns(); + for (L2Object obj : L2World.getInstance().getVisibleObjects()) + { + if ((obj != null) && obj.isNpc()) + { + final L2Npc target = (L2Npc) obj; + target.deleteMe(); + final L2Spawn spawn = target.getSpawn(); + if (spawn != null) + { + spawn.stopRespawn(); + SpawnTable.getInstance().deleteSpawn(spawn, false); + } + } + } // now respawn all NpcData.getInstance().load(); DBSpawnManager.getInstance().load(); diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java index 0faf9ac01d..d6809021ab 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java +++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/admincommandhandlers/AdminTeleport.java @@ -190,7 +190,7 @@ public class AdminTeleport implements IAdminCommandHandler st.nextToken(); final int x = (int) Float.parseFloat(st.nextToken()); final int y = (int) Float.parseFloat(st.nextToken()); - final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, L2World.MAP_MAX_Z); + final int z = st.hasMoreTokens() ? ((int) Float.parseFloat(st.nextToken())) : GeoEngine.getInstance().getHeight(x, y, 10000); activeChar.teleToLocation(x, y, z); } diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java index 7ef186ee29..d894837d33 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FenceData.java @@ -184,7 +184,7 @@ public final class FenceData implements IGameXmlReader return false; }; - final L2WorldRegion region = L2World.getInstance().getRegion(x, y, z); // FIXME: Should not be null. + final L2WorldRegion region = L2World.getInstance().getRegion(x, y); // Should never be null. return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter); } diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java index c7290b6912..fba190d620 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/instancemanager/ItemsOnGroundManager.java @@ -115,7 +115,7 @@ public final class ItemsOnGroundManager implements Runnable item.setEnchantLevel(rs.getInt(4)); } item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7)); - item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation())); + item.setWorldRegion(L2World.getInstance().getRegion(item)); item.getWorldRegion().addVisibleObject(item); final long dropTime = rs.getLong(8); item.setDropTime(dropTime); diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2Object.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2Object.java index 70a2a9e6e2..dd202f8a4e 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2Object.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2Object.java @@ -169,7 +169,7 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { // Set the x,y,z position of the L2Object spawn and update its _worldregion _isSpawned = true; - setWorldRegion(L2World.getInstance().getRegion(getLocation())); + setWorldRegion(L2World.getInstance().getRegion(this)); // Add the L2Object spawn in the _allobjects of L2World L2World.getInstance().addObject(this); @@ -207,14 +207,6 @@ public abstract class L2Object extends ListenersContainer implements IIdentifiab { y = L2World.MAP_MIN_Y + 5000; } - if (z > L2World.MAP_MAX_Z) - { - z = L2World.MAP_MAX_Z - 1000; - } - if (z < L2World.MAP_MIN_Z) - { - z = L2World.MAP_MIN_Z + 1000; - } // Set the x,y,z position of the WorldObject. If flagged with _isSpawned, setXYZ will automatically update world region, so avoid that. setXYZ(x, y, z); diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2World.java index bea222354b..57c1140da4 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2World.java @@ -35,14 +35,13 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.instancemanager.PlayerCountManager; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; +import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; -import com.l2jmobius.gameserver.model.interfaces.ILocational; import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; -import com.l2jmobius.gameserver.util.Util; public final class L2World { @@ -54,11 +53,10 @@ public final class L2World /** Bit shift, defines number of regions note, shifting by 15 will result in regions corresponding to map tiles shifting by 11 divides one tile to 16x16 regions. */ public static final int SHIFT_BY = 11; - public static final int SHIFT_BY_Z = 10; public static final int TILE_SIZE = 32768; - /** Map dimensions */ + /** Map dimensions. */ public static final int TILE_X_MIN = 11; public static final int TILE_Y_MIN = 10; public static final int TILE_X_MAX = 28; @@ -67,23 +65,20 @@ public final class L2World public static final int TILE_ZERO_COORD_Y = 18; public static final int MAP_MIN_X = (TILE_X_MIN - TILE_ZERO_COORD_X) * TILE_SIZE; public static final int MAP_MIN_Y = (TILE_Y_MIN - TILE_ZERO_COORD_Y) * TILE_SIZE; - public static final int MAP_MIN_Z = -TILE_SIZE / 2; public static final int MAP_MAX_X = ((TILE_X_MAX - TILE_ZERO_COORD_X) + 1) * TILE_SIZE; public static final int MAP_MAX_Y = ((TILE_Y_MAX - TILE_ZERO_COORD_Y) + 1) * TILE_SIZE; - public static final int MAP_MAX_Z = TILE_SIZE / 2; - /** calculated offset used so top left region is 0,0 */ + /** Calculated offset used so top left region is 0,0 */ public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY); public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY); - public static final int OFFSET_Z = Math.abs(MAP_MIN_Z >> SHIFT_BY_Z); - /** number of regions */ + /** Number of regions. */ private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X; private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y; - private static final int REGIONS_Z = (MAP_MAX_Z >> SHIFT_BY_Z) + OFFSET_Z; - public static final int REGION_MIN_DIMENSION = Math.min(TILE_SIZE / (TILE_SIZE >> SHIFT_BY_Z), TILE_SIZE / (TILE_SIZE >> SHIFT_BY)); + /** Max client visibility distance. **/ + private static final int VISIBILITY_RANGE = 3000; /** Map containing all the players in game. */ private final Map _allPlayers = new ConcurrentHashMap<>(); @@ -99,7 +94,7 @@ public final class L2World private final AtomicInteger _partyNumber = new AtomicInteger(); private final AtomicInteger _memberInPartyNumber = new AtomicInteger(); - private final L2WorldRegion[][][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1][REGIONS_Z + 1]; + private final L2WorldRegion[][] _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1]; /** Constructor of L2World. */ protected L2World() @@ -108,14 +103,11 @@ public final class L2World { for (int y = 0; y <= REGIONS_Y; y++) { - for (int z = 0; z <= REGIONS_Z; z++) - { - _worldRegions[x][y][z] = new L2WorldRegion(x, y, z); - } + _worldRegions[x][y] = new L2WorldRegion(x, y); } } - LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + " by " + REGIONS_Z + ") World Region Grid set up."); + LOGGER.info(getClass().getSimpleName() + ": (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up."); } /** @@ -139,7 +131,7 @@ public final class L2World PlayerCountManager.getInstance().incConnectedCount(); final L2PcInstance newPlayer = (L2PcInstance) object; - if (newPlayer.isTeleporting()) // TODO: drop when we stop removing player from the world while teleporting. + if (newPlayer.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -176,7 +168,7 @@ public final class L2World PlayerCountManager.getInstance().decConnectedCount(); final L2PcInstance player = (L2PcInstance) object; - if (player.isTeleporting()) // TODO: drop when we stop removing player from the world while teleportingq. + if (player.isTeleporting()) // TODO: Drop when we stop removing player from the world while teleporting. { return; } @@ -309,7 +301,7 @@ public final class L2World return; } - forEachVisibleObject(object, L2Object.class, 1, wo -> + forEachVisibleObject(object, L2Object.class, wo -> { if (object.isPlayer() && wo.isVisibleFor((L2PcInstance) object)) { @@ -584,47 +576,9 @@ public final class L2World }); } - public void forEachVisibleObject(L2Object object, Class clazz, int depth, Consumer c) - { - if (object == null) - { - return; - } - - final L2WorldRegion centerWorldRegion = getRegion(object); - if (centerWorldRegion == null) - { - return; - } - - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) - { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) - { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) - { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) - { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - c.accept(clazz.cast(visibleObject)); - } - } - } - } - } - public void forEachVisibleObject(L2Object object, Class clazz, Consumer c) { - forEachVisibleObject(object, clazz, 1, c); + forEachVisibleObjectInRange(object, clazz, VISIBILITY_RANGE, c); } public void forEachVisibleObjectInRange(L2Object object, Class clazz, int range, Consumer c) @@ -640,62 +594,49 @@ public final class L2World return; } - final int depth = (range / REGION_MIN_DIMENSION) + 1; - for (int x = Math.max(centerWorldRegion.getRegionX() - depth, 0); x <= Math.min(centerWorldRegion.getRegionX() + depth, REGIONS_X); x++) + final int regionX = centerWorldRegion.getRegionX(); + final int regionY = centerWorldRegion.getRegionY(); + for (int x = regionX - 1; x <= (regionX + 1); x++) { - for (int y = Math.max(centerWorldRegion.getRegionY() - depth, 0); y <= Math.min(centerWorldRegion.getRegionY() + depth, REGIONS_Y); y++) + for (int y = regionY - 1; y <= (regionY + 1); y++) { - for (int z = Math.max(centerWorldRegion.getRegionZ() - depth, 0); z <= Math.min(centerWorldRegion.getRegionZ() + depth, REGIONS_Z); z++) + if (validRegion(x, y)) { - final int x1 = (x - OFFSET_X) << SHIFT_BY; - final int y1 = (y - OFFSET_Y) << SHIFT_BY; - final int z1 = (z - OFFSET_Z) << SHIFT_BY_Z; - final int x2 = ((x + 1) - OFFSET_X) << SHIFT_BY; - final int y2 = ((y + 1) - OFFSET_Y) << SHIFT_BY; - final int z2 = ((z + 1) - OFFSET_Z) << SHIFT_BY_Z; - if (Util.cubeIntersectsSphere(x1, y1, z1, x2, y2, z2, object.getX(), object.getY(), object.getZ(), range)) + for (L2Object visibleObject : _worldRegions[x][y].getVisibleObjects().values()) { - for (L2Object visibleObject : _worldRegions[x][y][z].getVisibleObjects().values()) + if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) { - if ((visibleObject == null) || (visibleObject == object) || !clazz.isInstance(visibleObject)) - { - continue; - } - - if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) - { - continue; - } - - if (visibleObject.calculateDistance(object, true, false) <= range) - { - c.accept(clazz.cast(visibleObject)); - } + continue; + } + + if (visibleObject.getInstanceWorld() != object.getInstanceWorld()) + { + continue; + } + + if (visibleObject.calculateDistance(object, true, false) <= range) + { + c.accept(clazz.cast(visibleObject)); } } } + else if ((x == regionX) && (y == regionY)) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return; + } } } } public List getVisibleObjects(L2Object object, Class clazz) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, result::add); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE); } public List getVisibleObjects(L2Object object, Class clazz, Predicate predicate) { - final List result = new LinkedList<>(); - forEachVisibleObject(object, clazz, o -> - { - if (predicate.test(o)) - { - result.add(o); - } - }); - return result; + return getVisibleObjects(object, clazz, VISIBILITY_RANGE, predicate); } public List getVisibleObjects(L2Object object, Class clazz, int range) @@ -722,24 +663,31 @@ public final class L2World * Calculate the current L2WorldRegions of the object according to its position (x,y). Example of use : *
  • Set position of a new L2Object (drop, spawn...)
  • *
  • Update position of a L2Object after a movement

  • - * @param point position of the object + * @param object the object * @return */ - public L2WorldRegion getRegion(ILocational point) - { - return getRegion(point.getX(), point.getY(), point.getZ()); - } - - public L2WorldRegion getRegion(int x, int y, int z) + public L2WorldRegion getRegion(L2Object object) { try { - return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y][(z >> SHIFT_BY_Z) + OFFSET_Z]; + return _worldRegions[(object.getX() >> SHIFT_BY) + OFFSET_X][(object.getY() >> SHIFT_BY) + OFFSET_Y]; + } + catch (ArrayIndexOutOfBoundsException e) // Precaution. Moved at invalid region? + { + disposeOutOfBoundsObject(object); + return null; + } + } + + public L2WorldRegion getRegion(int x, int y) + { + try + { + return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y]; } catch (ArrayIndexOutOfBoundsException e) { - // TODO: Find when this can be null. (Bad geodata? Check GeoEngine hasGeoPos method.) - // LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y) + " Z: " + ((z >> SHIFT_BY_Z) + OFFSET_Z) + " for coordinates x: " + x + " y: " + y + " z: " + z); + LOGGER.warning(getClass().getSimpleName() + ": Incorrect world region X: " + ((x >> SHIFT_BY) + OFFSET_X) + " Y: " + ((y >> SHIFT_BY) + OFFSET_Y)); return null; } } @@ -748,7 +696,7 @@ public final class L2World * Returns the whole 3d array containing the world regions used by ZoneData.java to setup zones inside the world regions * @return */ - public L2WorldRegion[][][] getWorldRegions() + public L2WorldRegion[][] getWorldRegions() { return _worldRegions; } @@ -758,31 +706,49 @@ public final class L2World *
  • Init L2WorldRegions

  • * @param x X position of the object * @param y Y position of the object - * @param z Z position of the object * @return True if the L2WorldRegion is valid */ - public static boolean validRegion(int x, int y, int z) + public static boolean validRegion(int x, int y) { - return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)) && (z >= 0) && (z <= REGIONS_Z); + return ((x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y)); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() + public synchronized void disposeOutOfBoundsObject(L2Object object) { - LOGGER.info(getClass().getSimpleName() + ": Deleting all visible NPCs."); - for (int x = 0; x <= REGIONS_X; x++) + if (object.isPlayer()) { - for (int y = 0; y <= REGIONS_Y; y++) + ((L2Character) object).stopMove(((L2PcInstance) object).getLastServerPosition()); + } + else if (object.isSummon()) + { + final L2Summon summon = (L2Summon) object; + summon.unSummon(summon.getOwner()); + } + else if (_allObjects.remove(object.getObjectId()) != null) + { + if (object.isNpc()) { - for (int z = 0; z <= REGIONS_Z; z++) + final L2Npc npc = (L2Npc) object; + LOGGER.warning("Deleting npc " + object.getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + npc.deleteMe(); + + final L2Spawn spawn = npc.getSpawn(); + if (spawn != null) { - _worldRegions[x][y][z].deleteVisibleNpcSpawns(); + LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); } } + else if (object.isCharacter()) + { + LOGGER.warning("Deleting object " + object.getName() + " OID[" + object.getObjectId() + "] from invalid location X:" + object.getX() + " Y:" + object.getY() + " Z:" + object.getZ()); + ((L2Character) object).deleteMe(); + } + + if (object.getWorldRegion() != null) + { + object.getWorldRegion().removeVisibleObject(object); + } } - LOGGER.info(getClass().getSimpleName() + ": All visible NPCs deleted."); } public void incrementParty() diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2WorldRegion.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2WorldRegion.java index 0850de02ed..0c2db3c88f 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2WorldRegion.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/L2WorldRegion.java @@ -25,7 +25,6 @@ import java.util.logging.Logger; import com.l2jmobius.Config; import com.l2jmobius.commons.concurrent.ThreadPool; -import com.l2jmobius.gameserver.datatables.SpawnTable; import com.l2jmobius.gameserver.model.actor.L2Attackable; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.L2Vehicle; @@ -38,17 +37,15 @@ public final class L2WorldRegion private volatile Map _visibleObjects; private final int _regionX; private final int _regionY; - private final int _regionZ; private boolean _active = false; private ScheduledFuture _neighborsTask = null; - public L2WorldRegion(int regionX, int regionY, int regionZ) + public L2WorldRegion(int regionX, int regionY) { _regionX = regionX; _regionY = regionY; - _regionZ = regionZ; - // default a newly initialized region to inactive, unless always on is specified + // Default a newly initialized region to inactive, unless always on is specified. _active = Config.GRIDS_ALWAYS_ON; } @@ -93,19 +90,19 @@ public final class L2WorldRegion c++; final L2Attackable mob = (L2Attackable) o; - // Set target to null and cancel Attack or Cast + // Set target to null and cancel attack or cast. mob.setTarget(null); - // Stop movement + // Stop movement. mob.stopMove(null); - // Stop all active skills effects in progress on the L2Character + // Stop all active skills effects in progress on the L2Character. mob.stopAllEffects(); mob.clearAggroList(); mob.getAttackByList().clear(); - // stop the ai tasks + // Stop the AI tasks. if (mob.hasAI()) { mob.getAI().setIntention(com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE); @@ -126,7 +123,7 @@ public final class L2WorldRegion if (o.isAttackable()) { c++; - // Start HP/MP/CP Regeneration task + // Start HP/MP/CP regeneration task. ((L2Attackable) o).getStatus().startHpMpRegeneration(); } else if (o instanceof L2Npc) @@ -161,7 +158,7 @@ public final class L2WorldRegion _active = value; - // turn the AI on or off to match the region's activation. + // Turn the AI on or off to match the region's activation. switchAI(value); LOGGER.finer((value ? "Starting" : "Stopping") + " Grid " + this); @@ -172,10 +169,10 @@ public final class L2WorldRegion */ private void startActivation() { - // first set self to active and do self-tasks... + // First set self to active and do self-tasks... setActive(true); - // if the timer to deactivate neighbors is running, cancel it. + // If the timer to deactivate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -184,7 +181,7 @@ public final class L2WorldRegion _neighborsTask = null; } - // then, set a timer to activate the neighbors + // Then, set a timer to activate the neighbors. _neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME); } } @@ -194,7 +191,7 @@ public final class L2WorldRegion */ private void startDeactivation() { - // if the timer to activate neighbors is running, cancel it. + // If the timer to activate neighbors is running, cancel it. synchronized (this) { if (_neighborsTask != null) @@ -203,8 +200,8 @@ public final class L2WorldRegion _neighborsTask = null; } - // start a timer to "suggest" a deactivate to self and neighbors. - // suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. + // Start a timer to "suggest" a deactivate to self and neighbors. + // Suggest means: first check if a neighbor has L2PcInstances in it. If not, deactivate. _neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME); } } @@ -235,7 +232,7 @@ public final class L2WorldRegion if (object.isPlayable()) { - // if this is the first player to enter the region, activate self & neighbors + // If this is the first player to enter the region, activate self and neighbors. if (!_active && (!Config.GRIDS_ALWAYS_ON)) { startActivation(); @@ -274,50 +271,18 @@ public final class L2WorldRegion return _visibleObjects != null ? _visibleObjects : Collections.emptyMap(); } - /** - * Deleted all spawns in the world. - */ - public void deleteVisibleNpcSpawns() - { - if (_visibleObjects == null) - { - return; - } - - LOGGER.info("Deleting all visible NPCs in Region: " + this); - for (L2Object obj : _visibleObjects.values()) - { - if (obj instanceof L2Npc) - { - final L2Npc target = (L2Npc) obj; - target.deleteMe(); - final L2Spawn spawn = target.getSpawn(); - if (spawn != null) - { - spawn.stopRespawn(); - SpawnTable.getInstance().deleteSpawn(spawn, false); - } - LOGGER.finest("Removed NPC " + target.getObjectId()); - } - } - LOGGER.info("All visible NPCs deleted in Region: " + this); - } - public boolean forEachSurroundingRegion(Predicate p) { for (int x = _regionX - 1; x <= (_regionX + 1); x++) { for (int y = _regionY - 1; y <= (_regionY + 1); y++) { - for (int z = _regionZ - 1; z <= (_regionZ + 1); z++) + if (L2World.validRegion(x, y)) { - if (L2World.validRegion(x, y, z)) + final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y]; + if (!p.test(worldRegion)) { - final L2WorldRegion worldRegion = L2World.getInstance().getWorldRegions()[x][y][z]; - if (!p.test(worldRegion)) - { - return false; - } + return false; } } } @@ -335,19 +300,14 @@ public final class L2WorldRegion return _regionY; } - public int getRegionZ() - { - return _regionZ; - } - public boolean isSurroundingRegion(L2WorldRegion region) { - return (region != null) && (getRegionX() >= (region.getRegionX() - 1)) && (getRegionX() <= (region.getRegionX() + 1)) && (getRegionY() >= (region.getRegionY() - 1)) && (getRegionY() <= (region.getRegionY() + 1)) && (getRegionZ() >= (region.getRegionZ() - 1)) && (getRegionZ() <= (region.getRegionZ() + 1)); + return (region != null) && (_regionX >= (region.getRegionX() - 1)) && (_regionX <= (region.getRegionX() + 1)) && (_regionY >= (region.getRegionY() - 1)) && (_regionY <= (region.getRegionY() + 1)); } @Override public String toString() { - return "(" + _regionX + ", " + _regionY + ", " + _regionZ + ")"; + return "(" + _regionX + ", " + _regionY + ")"; } } diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 4b83d3f027..8c027b3ded 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -73,7 +73,6 @@ import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.L2Party; -import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2WorldRegion; import com.l2jmobius.gameserver.model.Location; @@ -83,7 +82,6 @@ import com.l2jmobius.gameserver.model.TimeStamp; import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance; import com.l2jmobius.gameserver.model.actor.instance.L2TrapInstance; import com.l2jmobius.gameserver.model.actor.stat.CharStat; import com.l2jmobius.gameserver.model.actor.status.CharStatus; @@ -2981,31 +2979,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe } else // Precaution. Moved at invalid region? { - if (isPlayer()) - { - stopMove(((L2PcInstance) this).getLastServerPosition()); - } - else if (isServitor()) - { - final L2ServitorInstance servitor = (L2ServitorInstance) this; - servitor.unSummon(servitor.getOwner()); - } - else if (isNpc()) - { - final L2Npc npc = (L2Npc) this; - LOGGER.warning("Deleting npc " + getName() + " NPCID[" + npc.getId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - final L2Spawn spawn = npc.getSpawn(); - if (spawn != null) - { - LOGGER.warning("Spawn location X:" + spawn.getX() + " Y:" + spawn.getY() + " Z:" + spawn.getZ() + " Heading:" + spawn.getHeading()); - } - deleteMe(); - } - else - { - LOGGER.warning("Deleting object " + getName() + " OID[" + getObjectId() + "] from invalid location X:" + getX() + " Y:" + getY() + " Z:" + getZ()); - deleteMe(); - } + L2World.getInstance().disposeOutOfBoundsObject(this); } } diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/util/Util.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/util/Util.java index 98856a3927..eb2fcfe3ac 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/util/Util.java +++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/util/Util.java @@ -226,50 +226,6 @@ public final class Util return calculateDistance(obj1, obj2, includeZAxis, false) <= range; } - /** - * Checks if the cube intersects the sphere. - * @param x1 the cube's first point x - * @param y1 the cube's first point y - * @param z1 the cube's first point z - * @param x2 the cube's second point x - * @param y2 the cube's second point y - * @param z2 the cube's second point z - * @param sX the sphere's middle x - * @param sY the sphere's middle y - * @param sZ the sphere's middle z - * @param radius the sphere's radius - * @return {@code true} if cube intersects sphere, {@code false} otherwise - */ - public static boolean cubeIntersectsSphere(int x1, int y1, int z1, int x2, int y2, int z2, int sX, int sY, int sZ, int radius) - { - double d = radius * radius; - if (sX < x1) - { - d -= Math.pow(sX - x1, 2); - } - else if (sX > x2) - { - d -= Math.pow(sX - x2, 2); - } - if (sY < y1) - { - d -= Math.pow(sY - y1, 2); - } - else if (sY > y2) - { - d -= Math.pow(sY - y2, 2); - } - if (sZ < z1) - { - d -= Math.pow(sZ - z1, 2); - } - else if (sZ > z2) - { - d -= Math.pow(sZ - z2, 2); - } - return d > 0; - } - /** * @param text - the text to check * @return {@code true} if {@code text} contains only numbers, {@code false} otherwise