WorldRegion class simplifications.
This commit is contained in:
parent
d2e926851d
commit
9233a76402
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1,12 +1,3 @@
|
||||
# Allows selection of new Classes for storage of World Objects.
|
||||
# This may help servers with large amounts of players receiving error
|
||||
# messages related to the L2ObjectHashMap and L2ObjectHashSet classes.
|
||||
#
|
||||
# By default it uses the new method, to use the old classes add the
|
||||
# comment at the front of each line.
|
||||
Map = WorldObjectMap
|
||||
Set = WorldObjectSet
|
||||
|
||||
# Tell server which IDFactory Class to use
|
||||
# Options are:
|
||||
# Compaction (Original method),
|
||||
|
@ -216,8 +216,6 @@ public class Config
|
||||
|
||||
public static IdFactoryType IDFACTORY_TYPE;
|
||||
public static boolean BAD_ID_CHECKING;
|
||||
public static ObjectMapType MAP_TYPE;
|
||||
public static ObjectSetType SET_TYPE;
|
||||
|
||||
public static boolean JAIL_IS_PVP;
|
||||
public static boolean JAIL_DISABLE_CHAT;
|
||||
@ -1312,8 +1310,6 @@ public class Config
|
||||
idSettings.load(is);
|
||||
is.close();
|
||||
|
||||
MAP_TYPE = ObjectMapType.valueOf(idSettings.getProperty("Map", "WorldObjectMap"));
|
||||
SET_TYPE = ObjectSetType.valueOf(idSettings.getProperty("Set", "WorldObjectSet"));
|
||||
IDFACTORY_TYPE = IdFactoryType.valueOf(idSettings.getProperty("IDFactory", "Compaction"));
|
||||
BAD_ID_CHECKING = Boolean.valueOf(idSettings.getProperty("BadIdChecking", "true"));
|
||||
}
|
||||
@ -3718,20 +3714,6 @@ public class Config
|
||||
Stack
|
||||
}
|
||||
|
||||
/** Enumeration for type of maps object */
|
||||
public enum ObjectMapType
|
||||
{
|
||||
WorldObjectTree,
|
||||
WorldObjectMap
|
||||
}
|
||||
|
||||
/** Enumeration for type of set object */
|
||||
public enum ObjectSetType
|
||||
{
|
||||
L2ObjectHashSet,
|
||||
WorldObjectSet
|
||||
}
|
||||
|
||||
public static void saveHexid(int serverId, String string)
|
||||
{
|
||||
saveHexid(serverId, string, HEXID_FILE);
|
||||
|
@ -1,510 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* This class is a highly optimized hashtable, where keys are integers. The main goal of this class is to allow concurent read/iterate and write access to this table, plus minimal used memory. This class uses plain array as the table of values, and keys are used to get position in the table. If the
|
||||
* position is already busy, we iterate to the next position, unil we find the needed element or null. To iterate over the table (read access) we may simply iterate throgh table array. In case we remove an element from the table, we check - if the next position is null, we reset table's slot to
|
||||
* null, otherwice we assign it to a dummy value
|
||||
* @author mkizub
|
||||
* @param <T> type of values stored in this hashtable
|
||||
*/
|
||||
public class L2ObjectHashMap<T extends WorldObject>extends L2ObjectMap<T>
|
||||
{
|
||||
protected static final Logger LOGGER = Logger.getLogger(L2ObjectHashMap.class.getName());
|
||||
|
||||
private static final boolean TRACE = false;
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int[] PRIMES =
|
||||
{
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
17,
|
||||
23,
|
||||
29,
|
||||
37,
|
||||
47,
|
||||
59,
|
||||
71,
|
||||
89,
|
||||
107,
|
||||
131,
|
||||
163,
|
||||
197,
|
||||
239,
|
||||
293,
|
||||
353,
|
||||
431,
|
||||
521,
|
||||
631,
|
||||
761,
|
||||
919,
|
||||
1103,
|
||||
1327,
|
||||
1597,
|
||||
1931,
|
||||
2333,
|
||||
2801,
|
||||
3371,
|
||||
4049,
|
||||
4861,
|
||||
5839,
|
||||
7013,
|
||||
8419,
|
||||
10103,
|
||||
12143,
|
||||
14591,
|
||||
17519,
|
||||
21023,
|
||||
25229,
|
||||
30293,
|
||||
36353,
|
||||
43627,
|
||||
52361,
|
||||
62851,
|
||||
75431,
|
||||
90523,
|
||||
108631,
|
||||
130363,
|
||||
156437,
|
||||
187751,
|
||||
225307,
|
||||
270371,
|
||||
324449,
|
||||
389357,
|
||||
467237,
|
||||
560689,
|
||||
672827,
|
||||
807403,
|
||||
968897,
|
||||
1162687,
|
||||
1395263,
|
||||
1674319,
|
||||
2009191,
|
||||
2411033,
|
||||
2893249,
|
||||
3471899,
|
||||
4166287,
|
||||
4999559,
|
||||
5999471,
|
||||
7199369
|
||||
};
|
||||
|
||||
private T[] _table;
|
||||
private int[] _keys;
|
||||
private int _count;
|
||||
|
||||
private static int getPrime(int min)
|
||||
{
|
||||
for (int element : PRIMES)
|
||||
{
|
||||
if (element >= min)
|
||||
{
|
||||
return element;
|
||||
}
|
||||
}
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public L2ObjectHashMap()
|
||||
{
|
||||
final int size = PRIMES[0];
|
||||
_table = (T[]) new WorldObject[size];
|
||||
_keys = new int[size];
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#size()
|
||||
*/
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _count == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#clear()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void clear()
|
||||
{
|
||||
final int size = PRIMES[0];
|
||||
_table = (T[]) new WorldObject[size];
|
||||
_keys = new int[size];
|
||||
_count = 0;
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
||||
private void check()
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < _table.length; i++)
|
||||
{
|
||||
final WorldObject obj = _table[i];
|
||||
if (obj == null)
|
||||
{
|
||||
assert (_keys[i] == 0) || (_keys[i] == 0x80000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt++;
|
||||
assert obj.getObjectId() == (_keys[i] & 0x7FFFFFFF);
|
||||
}
|
||||
}
|
||||
assert cnt == _count;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#put(T)
|
||||
*/
|
||||
@Override
|
||||
public synchronized void put(T obj)
|
||||
{
|
||||
if (_count >= (_table.length / 2))
|
||||
{
|
||||
expand();
|
||||
}
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
|
||||
int ntry = 0;
|
||||
int slot = -1; // keep last found slot
|
||||
do
|
||||
{
|
||||
final int pos = (seed % _table.length) & 0x7FFFFFFF;
|
||||
if (_table[pos] == null)
|
||||
{
|
||||
if (slot < 0)
|
||||
{
|
||||
slot = pos;
|
||||
}
|
||||
if (_keys[pos] >= 0)
|
||||
{
|
||||
// found an empty slot without previous collisions,
|
||||
// but use previously found slot
|
||||
_keys[slot] = hashcode;
|
||||
_table[slot] = obj;
|
||||
_count++;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: put obj id=" + hashcode + " at slot=" + slot);
|
||||
}
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if we are adding the same object
|
||||
if (_table[pos] == obj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if there was no collisions at this slot, and we found a free
|
||||
// slot previously - use found slot
|
||||
if ((slot >= 0) && (_keys[pos] > 0))
|
||||
{
|
||||
_keys[slot] |= hashcode; // preserve collision bit
|
||||
_table[slot] = obj;
|
||||
_count++;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: put obj id=" + hashcode + " at slot=" + slot);
|
||||
}
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set collision bit
|
||||
_keys[pos] |= 0x80000000;
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < _table.length);
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#remove(T)
|
||||
*/
|
||||
@Override
|
||||
public synchronized void remove(T obj)
|
||||
{
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % _table.length) & 0x7FFFFFFF;
|
||||
if (_table[pos] == obj)
|
||||
{
|
||||
// found the object
|
||||
_keys[pos] &= 0x80000000; // preserve collision bit
|
||||
_table[pos] = null;
|
||||
_count--;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: remove obj id=" + hashcode + " from slot=" + pos);
|
||||
}
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// check for collision (if we previously deleted element)
|
||||
if ((_table[pos] == null) && (_keys[pos] >= 0))
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
return; // throw new IllegalArgumentException();
|
||||
}
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < _table.length);
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#get(int)
|
||||
*/
|
||||
@Override
|
||||
public T get(int id)
|
||||
{
|
||||
final int size = _table.length;
|
||||
if (id <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (size <= 11)
|
||||
{
|
||||
// for small tables linear check is fast
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if ((_keys[i] & 0x7FFFFFFF) == id)
|
||||
{
|
||||
return _table[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
int seed = id;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (size - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % size) & 0x7FFFFFFF;
|
||||
if ((_keys[pos] & 0x7FFFFFFF) == id)
|
||||
{
|
||||
return _table[pos];
|
||||
}
|
||||
// check for collision (if we previously deleted element)
|
||||
if ((_table[pos] == null) && (_keys[pos] >= 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < size);
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#contains(T)
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(T obj)
|
||||
{
|
||||
return get(obj.getObjectId()) != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private/* already synchronized in put() */void expand()
|
||||
{
|
||||
final int newSize = getPrime(_table.length + 1);
|
||||
final WorldObject[] newTable = new WorldObject[newSize];
|
||||
final int[] newKeys = new int[newSize];
|
||||
|
||||
// over all old entries
|
||||
next_entry: for (int i = 0; i < _table.length; i++)
|
||||
{
|
||||
final WorldObject obj = _table[i];
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
final int hashcode = _keys[i] & 0x7FFFFFFF;
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % newSize) & 0x7FFFFFFF;
|
||||
if (newTable[pos] == null)
|
||||
{
|
||||
// found an empty slot without previous collisions,
|
||||
// but use previously found slot
|
||||
newKeys[pos] = hashcode;
|
||||
newTable[pos] = obj;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: move obj id=" + hashcode + " from slot=" + i + " to slot=" + pos);
|
||||
}
|
||||
continue next_entry;
|
||||
}
|
||||
// set collision bit
|
||||
newKeys[pos] |= 0x80000000;
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < newSize);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
_table = (T[]) newTable;
|
||||
_keys = newKeys;
|
||||
if (DEBUG)
|
||||
{
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
return new Itr(_table);
|
||||
}
|
||||
|
||||
class Itr implements Iterator<T>
|
||||
{
|
||||
private final T[] _array;
|
||||
private int _nextIdx;
|
||||
private T _nextObj;
|
||||
private T _lastRet;
|
||||
|
||||
Itr(T[] pArray)
|
||||
{
|
||||
this._array = pArray;
|
||||
for (; _nextIdx < _array.length; _nextIdx++)
|
||||
{
|
||||
_nextObj = _array[_nextIdx];
|
||||
if (_nextObj != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return _nextObj != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next()
|
||||
{
|
||||
if (_nextObj == null)
|
||||
{
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
_lastRet = _nextObj;
|
||||
for (_nextIdx++; _nextIdx < _array.length; _nextIdx++)
|
||||
{
|
||||
_nextObj = _array[_nextIdx];
|
||||
if (_nextObj != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_nextIdx >= _array.length)
|
||||
{
|
||||
_nextObj = null;
|
||||
}
|
||||
return _lastRet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
if (_lastRet == null)
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
L2ObjectHashMap.this.remove(_lastRet);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,428 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* This class is a highly optimized hashtable, where keys are integers. The main goal of this class is to allow concurent read/iterate and write access to this table, plus minimal used memory. This class uses plain array as the table of values, and keys are used to get position in the table. If the
|
||||
* position is already busy, we iterate to the next position, unil we find the needed element or null. To iterate over the table (read access) we may simply iterate throgh table array. In case we remove an element from the table, we check - if the next position is null, we reset table's slot to
|
||||
* null, otherwice we assign it to a dummy value
|
||||
* @author mkizub
|
||||
* @param <T> type of values stored in this hashtable
|
||||
*/
|
||||
public class L2ObjectHashSet<T extends WorldObject>extends L2ObjectSet<T>
|
||||
{
|
||||
protected static final Logger LOGGER = Logger.getLogger(L2ObjectHashSet.class.getName());
|
||||
|
||||
private static final boolean TRACE = false;
|
||||
|
||||
private static final int[] PRIMES =
|
||||
{
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
17,
|
||||
23,
|
||||
29,
|
||||
37,
|
||||
47,
|
||||
59,
|
||||
71,
|
||||
89,
|
||||
107,
|
||||
131,
|
||||
163,
|
||||
197,
|
||||
239,
|
||||
293,
|
||||
353,
|
||||
431,
|
||||
521,
|
||||
631,
|
||||
761,
|
||||
919,
|
||||
1103,
|
||||
1327,
|
||||
1597,
|
||||
1931,
|
||||
2333,
|
||||
2801,
|
||||
3371,
|
||||
4049,
|
||||
4861,
|
||||
5839,
|
||||
7013,
|
||||
8419,
|
||||
10103,
|
||||
12143,
|
||||
14591,
|
||||
17519,
|
||||
21023,
|
||||
25229,
|
||||
30293,
|
||||
36353,
|
||||
43627,
|
||||
52361,
|
||||
62851,
|
||||
75431,
|
||||
90523,
|
||||
108631,
|
||||
130363,
|
||||
156437,
|
||||
187751,
|
||||
225307,
|
||||
270371,
|
||||
324449,
|
||||
389357,
|
||||
467237,
|
||||
560689,
|
||||
672827,
|
||||
807403,
|
||||
968897,
|
||||
1162687,
|
||||
1395263,
|
||||
1674319,
|
||||
2009191,
|
||||
2411033,
|
||||
2893249,
|
||||
3471899,
|
||||
4166287,
|
||||
4999559,
|
||||
5999471,
|
||||
7199369
|
||||
};
|
||||
|
||||
private T[] _table;
|
||||
private int[] _collisions;
|
||||
private int _count;
|
||||
|
||||
private static int getPrime(int min)
|
||||
{
|
||||
for (int element : PRIMES)
|
||||
{
|
||||
if (element >= min)
|
||||
{
|
||||
return element;
|
||||
}
|
||||
}
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public L2ObjectHashSet()
|
||||
{
|
||||
final int size = PRIMES[0];
|
||||
_table = (T[]) new WorldObject[size];
|
||||
_collisions = new int[(size + 31) >> 5];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _count == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void clear()
|
||||
{
|
||||
final int size = PRIMES[0];
|
||||
_table = (T[]) new WorldObject[size];
|
||||
_collisions = new int[(size + 31) >> 5];
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void put(T obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (contains(obj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_count >= (_table.length / 2))
|
||||
{
|
||||
expand();
|
||||
}
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
|
||||
int ntry = 0;
|
||||
int slot = -1; // keep last found slot
|
||||
do
|
||||
{
|
||||
final int pos = (seed % _table.length) & 0x7FFFFFFF;
|
||||
if (_table[pos] == null)
|
||||
{
|
||||
if (slot < 0)
|
||||
{
|
||||
slot = pos;
|
||||
}
|
||||
if ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0)
|
||||
{
|
||||
// found an empty slot without previous collisions,
|
||||
// but use previously found slot
|
||||
_table[slot] = obj;
|
||||
_count++;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: put obj id=" + hashcode + " at slot=" + slot);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if we are adding the same object
|
||||
if (_table[pos] == obj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if there was no collisions at this slot, and we found a free
|
||||
// slot previously - use found slot
|
||||
if ((slot >= 0) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
|
||||
{
|
||||
_table[slot] = obj;
|
||||
_count++;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: put obj id=" + hashcode + " at slot=" + slot);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set collision bit
|
||||
_collisions[pos >> 5] |= 1 << (pos & 31);
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < _table.length);
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void remove(T obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!contains(obj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % _table.length) & 0x7FFFFFFF;
|
||||
if (_table[pos] == obj)
|
||||
{
|
||||
// found the object
|
||||
_table[pos] = null;
|
||||
_count--;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: remove obj id=" + hashcode + " from slot=" + pos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// check for collision (if we previously deleted element)
|
||||
if ((_table[pos] == null) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
|
||||
{
|
||||
return; // throw new IllegalArgumentException();
|
||||
}
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < _table.length);
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#contains(T)
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(T obj)
|
||||
{
|
||||
final int size = _table.length;
|
||||
if (size <= 11)
|
||||
{
|
||||
// for small tables linear check is fast
|
||||
for (T a_table : _table)
|
||||
{
|
||||
if (a_table == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (size - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % size) & 0x7FFFFFFF;
|
||||
if (_table[pos] == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// check for collision (if we previously deleted element)
|
||||
if ((_table[pos] == null) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < size);
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private/* already synchronized in put() */void expand()
|
||||
{
|
||||
final int newSize = getPrime(_table.length + 1);
|
||||
final WorldObject[] newTable = new WorldObject[newSize];
|
||||
final int[] newCollisions = new int[(newSize + 31) >> 5];
|
||||
|
||||
// over all old entries
|
||||
next_entry: for (int i = 0; i < _table.length; i++)
|
||||
{
|
||||
final WorldObject obj = _table[i];
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
final int hashcode = obj.getObjectId();
|
||||
int seed = hashcode;
|
||||
final int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
|
||||
int ntry = 0;
|
||||
do
|
||||
{
|
||||
final int pos = (seed % newSize) & 0x7FFFFFFF;
|
||||
if (newTable[pos] == null)
|
||||
{
|
||||
// found an empty slot without previous collisions,
|
||||
// but use previously found slot
|
||||
newTable[pos] = obj;
|
||||
if (TRACE)
|
||||
{
|
||||
LOGGER.warning("ht: move obj id=" + hashcode + " from slot=" + i + " to slot=" + pos);
|
||||
}
|
||||
continue next_entry;
|
||||
}
|
||||
// set collision bit
|
||||
newCollisions[pos >> 5] |= 1 << (pos & 31);
|
||||
// calculate next slot
|
||||
seed += incr;
|
||||
}
|
||||
while (++ntry < newSize);
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
_table = (T[]) newTable;
|
||||
_collisions = newCollisions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
return new Itr(_table);
|
||||
}
|
||||
|
||||
class Itr implements Iterator<T>
|
||||
{
|
||||
private final T[] _array;
|
||||
private int _nextIdx;
|
||||
private T _nextObj;
|
||||
private T _lastRet;
|
||||
|
||||
Itr(T[] pArray)
|
||||
{
|
||||
this._array = pArray;
|
||||
for (; _nextIdx < _array.length; _nextIdx++)
|
||||
{
|
||||
_nextObj = _array[_nextIdx];
|
||||
if (_nextObj != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return _nextObj != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next()
|
||||
{
|
||||
if (_nextObj == null)
|
||||
{
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
_lastRet = _nextObj;
|
||||
for (_nextIdx++; _nextIdx < _array.length; _nextIdx++)
|
||||
{
|
||||
_nextObj = _array[_nextIdx];
|
||||
if (_nextObj != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_nextIdx >= _array.length)
|
||||
{
|
||||
_nextObj = null;
|
||||
}
|
||||
return _lastRet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
if (_lastRet == null)
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
L2ObjectHashSet.this.remove(_lastRet);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* @author luisantonioa
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class L2ObjectMap<T extends WorldObject> implements Iterable<T>
|
||||
{
|
||||
public abstract int size();
|
||||
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
public abstract void clear();
|
||||
|
||||
public abstract void put(T obj);
|
||||
|
||||
public abstract void remove(T obj);
|
||||
|
||||
public abstract T get(int id);
|
||||
|
||||
public abstract boolean contains(T obj);
|
||||
|
||||
@Override
|
||||
public abstract Iterator<T> iterator();
|
||||
|
||||
public static L2ObjectMap<WorldObject> createL2ObjectMap()
|
||||
{
|
||||
switch (Config.MAP_TYPE)
|
||||
{
|
||||
case WorldObjectMap:
|
||||
{
|
||||
return new WorldObjectMap<>();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return new WorldObjectTree<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||
|
||||
/**
|
||||
* @author luisantonioa
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class L2ObjectSet<T extends WorldObject> implements Iterable<T>
|
||||
{
|
||||
public static L2ObjectSet<WorldObject> createL2ObjectSet()
|
||||
{
|
||||
switch (Config.SET_TYPE)
|
||||
{
|
||||
case WorldObjectSet:
|
||||
{
|
||||
return new WorldObjectSet<>();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return new L2ObjectHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static L2ObjectSet<Playable> createL2PlayerSet()
|
||||
{
|
||||
switch (Config.SET_TYPE)
|
||||
{
|
||||
case WorldObjectSet:
|
||||
{
|
||||
return new WorldObjectSet<>();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return new L2ObjectHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract int size();
|
||||
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
public abstract void clear();
|
||||
|
||||
public abstract void put(T obj);
|
||||
|
||||
public abstract void remove(T obj);
|
||||
|
||||
public abstract boolean contains(T obj);
|
||||
|
||||
@Override
|
||||
public abstract Iterator<T> iterator();
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* @author luisantonioa
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
* @param <T>
|
||||
*/
|
||||
public class WorldObjectMap<T extends WorldObject>extends L2ObjectMap<T>
|
||||
{
|
||||
Map<Integer, T> _objectMap = new ConcurrentHashMap<>();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#size()
|
||||
*/
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _objectMap.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _objectMap.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_objectMap.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#put(T)
|
||||
*/
|
||||
@Override
|
||||
public void put(T obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
_objectMap.put(obj.getObjectId(), obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#remove(T)
|
||||
*/
|
||||
@Override
|
||||
public void remove(T obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
_objectMap.remove(obj.getObjectId());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#get(int)
|
||||
*/
|
||||
@Override
|
||||
public T get(int id)
|
||||
{
|
||||
return _objectMap.get(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#contains(T)
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(T obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _objectMap.get(obj.getObjectId()) != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectMap#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
return _objectMap.values().iterator();
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
* @param <T>
|
||||
*/
|
||||
public class WorldObjectSet<T extends WorldObject>extends L2ObjectSet<T>
|
||||
{
|
||||
private final Map<Integer, T> _objectMap;
|
||||
|
||||
public WorldObjectSet()
|
||||
{
|
||||
_objectMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#size()
|
||||
*/
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return _objectMap.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _objectMap.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#clear()
|
||||
*/
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_objectMap.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#put(T)
|
||||
*/
|
||||
@Override
|
||||
public void put(T obj)
|
||||
{
|
||||
_objectMap.put(obj.getObjectId(), obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#remove(T)
|
||||
*/
|
||||
@Override
|
||||
public void remove(T obj)
|
||||
{
|
||||
_objectMap.remove(obj.getObjectId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#contains(T)
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(T obj)
|
||||
{
|
||||
return _objectMap.containsKey(obj.getObjectId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.l2jmobius.util.L2ObjectSet#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
return _objectMap.values().iterator();
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.commons.util.object;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
|
||||
/**
|
||||
* @author dishkols
|
||||
* @param <T>
|
||||
*/
|
||||
public class WorldObjectTree<T extends WorldObject>extends L2ObjectMap<T>
|
||||
{
|
||||
private final TreeMap<Integer, T> _objectMap = new TreeMap<>();
|
||||
private final ReentrantReadWriteLock _rwl = new ReentrantReadWriteLock();
|
||||
private final Lock _r = _rwl.readLock();
|
||||
private final Lock _w = _rwl.writeLock();
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
_r.lock();
|
||||
try
|
||||
{
|
||||
return _objectMap.size();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
_r.lock();
|
||||
try
|
||||
{
|
||||
return _objectMap.isEmpty();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_w.lock();
|
||||
try
|
||||
{
|
||||
_objectMap.clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(T obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
_w.lock();
|
||||
try
|
||||
{
|
||||
_objectMap.put(obj.getObjectId(), obj);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_w.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(T obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
_w.lock();
|
||||
try
|
||||
{
|
||||
_objectMap.remove(obj.getObjectId());
|
||||
}
|
||||
finally
|
||||
{
|
||||
_w.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int id)
|
||||
{
|
||||
_r.lock();
|
||||
try
|
||||
{
|
||||
return _objectMap.get(id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(T obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_r.lock();
|
||||
try
|
||||
{
|
||||
return _objectMap.containsValue(obj);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
_r.lock();
|
||||
try
|
||||
{
|
||||
return _objectMap.values().iterator();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_r.unlock();
|
||||
}
|
||||
}
|
||||
}
|
@ -339,12 +339,6 @@ public class AttackableAI extends CreatureAI
|
||||
@Override
|
||||
public void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
|
||||
{
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((intention == AI_INTENTION_IDLE) || (intention == AI_INTENTION_ACTIVE))
|
||||
{
|
||||
// Check if actor is not dead
|
||||
@ -678,9 +672,9 @@ public class AttackableAI extends CreatureAI
|
||||
}
|
||||
|
||||
/*
|
||||
* // Handle all WorldObject of its Faction inside the Faction Range if (_actor instanceof NpcInstance && ((NpcInstance) _actor).getFactionId() != null) { String faction_id = ((NpcInstance) _actor).getFactionId(); // Go through all WorldObject that belong to its faction Collection<WorldObject>
|
||||
* objs = _actor.getKnownList().getKnownObjects().values(); //synchronized (_actor.getKnownList().getKnownObjects()) try { for (WorldObject obj : objs) { if (obj instanceof NpcInstance) { NpcInstance npc = (NpcInstance) obj; //Handle SevenSigns mob Factions String npcfaction =
|
||||
* npc.getFactionId(); boolean sevenSignFaction = false; // TODO: Unhardcode this by AI scripts (DrHouse) //Catacomb mobs should assist lilim and nephilim other than dungeon if ("c_dungeon_clan".equals(faction_id) && ("c_dungeon_lilim".equals(npcfaction) ||
|
||||
* // Handle all WorldObject of its Faction inside the Faction Range if (_actor instanceof NpcInstance && ((NpcInstance) _actor).getFactionId() != null) { String faction_id = ((NpcInstance) _actor).getFactionId(); // Go through all WorldObject that belong to its faction
|
||||
* Collection<WorldObject> objs = _actor.getKnownList().getKnownObjects().values(); //synchronized (_actor.getKnownList().getKnownObjects()) try { for (WorldObject obj : objs) { if (obj instanceof NpcInstance) { NpcInstance npc = (NpcInstance) obj; //Handle SevenSigns mob Factions String
|
||||
* npcfaction = npc.getFactionId(); boolean sevenSignFaction = false; // TODO: Unhardcode this by AI scripts (DrHouse) //Catacomb mobs should assist lilim and nephilim other than dungeon if ("c_dungeon_clan".equals(faction_id) && ("c_dungeon_lilim".equals(npcfaction) ||
|
||||
* "c_dungeon_nephi".equals(npcfaction))) sevenSignFaction = true; //Lilim mobs should assist other Lilim and catacomb mobs else if ("c_dungeon_lilim".equals(faction_id) && "c_dungeon_clan".equals(npcfaction)) sevenSignFaction = true; //Nephilim mobs should assist other Nephilim and catacomb
|
||||
* mobs else if ("c_dungeon_nephi".equals(faction_id) && "c_dungeon_clan".equals(npcfaction)) sevenSignFaction = true; if (!faction_id.equals(npc.getFactionId()) && !sevenSignFaction) continue; // Check if the WorldObject is inside the Faction Range of // the actor if
|
||||
* (_actor.isInsideRadius(npc, npc.getFactionRange() + npc.getTemplate().collisionRadius, true, false) && npc.getAI() != null) { if (Math.abs(originalAttackTarget.getZ() - npc.getZ()) < 600 && _actor.getAttackByList().contains(originalAttackTarget) && (npc.getAI()._intention ==
|
||||
|
@ -18,18 +18,14 @@ package org.l2jmobius.gameserver.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.commons.util.object.L2ObjectMap;
|
||||
import org.l2jmobius.commons.util.object.L2ObjectSet;
|
||||
import org.l2jmobius.gameserver.datatables.GmListTable;
|
||||
import org.l2jmobius.gameserver.instancemanager.PlayerCountManager;
|
||||
import org.l2jmobius.gameserver.model.actor.Creature;
|
||||
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PetInstance;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||
|
||||
@ -71,10 +67,10 @@ public class World
|
||||
private static Map<String, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
|
||||
/** WorldObjectHashMap(WorldObject) containing all visible objects. */
|
||||
private static L2ObjectMap<WorldObject> _allObjects;
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
|
||||
/** List with the pets instances and their owner id. */
|
||||
private final Map<Integer, PetInstance> _petsInstance;
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
/** The _instance. */
|
||||
private static World _instance = null;
|
||||
@ -84,9 +80,6 @@ public class World
|
||||
|
||||
private World()
|
||||
{
|
||||
_petsInstance = new ConcurrentHashMap<>();
|
||||
_allObjects = L2ObjectMap.createL2ObjectMap();
|
||||
|
||||
initRegions();
|
||||
}
|
||||
|
||||
@ -114,25 +107,7 @@ public class World
|
||||
*/
|
||||
public void storeObject(WorldObject object)
|
||||
{
|
||||
if (_allObjects.get(object.getObjectId()) != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_allObjects.put(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time store object.
|
||||
* @param object the object
|
||||
* @return the long
|
||||
*/
|
||||
public long timeStoreObject(WorldObject object)
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
_allObjects.put(object);
|
||||
time -= System.currentTimeMillis();
|
||||
|
||||
return time;
|
||||
_allObjects.putIfAbsent(object.getObjectId(), object);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,7 +122,7 @@ public class World
|
||||
*/
|
||||
public void removeObject(WorldObject object)
|
||||
{
|
||||
_allObjects.remove(object);
|
||||
_allObjects.remove(object.getObjectId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,7 +133,7 @@ public class World
|
||||
{
|
||||
for (WorldObject o : list)
|
||||
{
|
||||
_allObjects.remove(o);
|
||||
_allObjects.remove(o.getObjectId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,24 +145,10 @@ public class World
|
||||
{
|
||||
for (WorldObject o : objects)
|
||||
{
|
||||
_allObjects.remove(o);
|
||||
_allObjects.remove(o.getObjectId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time remove object.
|
||||
* @param object the object
|
||||
* @return the long
|
||||
*/
|
||||
public long timeRemoveObject(WorldObject object)
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
_allObjects.remove(object);
|
||||
time -= System.currentTimeMillis();
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the WorldObject object that belongs to an ID or null if no object found.<BR>
|
||||
* <BR>
|
||||
@ -202,27 +163,13 @@ public class World
|
||||
return _allObjects.get(oID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time find object.
|
||||
* @param objectID the object id
|
||||
* @return the long
|
||||
*/
|
||||
public long timeFindObject(int objectID)
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
_allObjects.get(objectID);
|
||||
time -= System.currentTimeMillis();
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Added by Tempy - 08 Aug 05 Allows easy retrevial of all visible objects in world. -- do not use that fucntion, its unsafe!
|
||||
* @return the all visible objects
|
||||
*/
|
||||
public L2ObjectMap<WorldObject> getAllVisibleObjects()
|
||||
public Collection<WorldObject> getAllVisibleObjects()
|
||||
{
|
||||
return _allObjects;
|
||||
return _allObjects.values();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,15 +349,11 @@ public class World
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Get all visible objects contained in the _visibleObjects of WorldRegions
|
||||
// in a circular area of 2000 units
|
||||
final List<WorldObject> visibles = getVisibleObjects(object, 2000);
|
||||
|
||||
// tell the player about the surroundings
|
||||
// Go through the visible objects contained in the circular area
|
||||
for (WorldObject visible : visibles)
|
||||
for (WorldObject wo : getVisibleObjects(object, 2000))
|
||||
{
|
||||
if (visible == null)
|
||||
if (wo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -420,11 +363,11 @@ public class World
|
||||
// - object is not already known
|
||||
// - object is in the watch distance
|
||||
// If WorldObject is a PlayerInstance, add WorldObject in WorldObjectHashSet(PlayerInstance) _knownPlayer of the visible Creature
|
||||
visible.getKnownList().addKnownObject(object);
|
||||
wo.getKnownList().addKnownObject(object);
|
||||
|
||||
// Add the visible WorldObject in WorldObjectHashSet(WorldObject) _knownObjects of the object according to conditions
|
||||
// If visible WorldObject is a PlayerInstance, add visible WorldObject in WorldObjectHashSet(PlayerInstance) _knownPlayer of the object
|
||||
object.getKnownList().addKnownObject(visible);
|
||||
object.getKnownList().addKnownObject(wo);
|
||||
}
|
||||
|
||||
if (!player.isTeleporting())
|
||||
@ -445,23 +388,19 @@ public class World
|
||||
}
|
||||
}
|
||||
|
||||
// Get all visible objects contained in the _visibleObjects of WorldRegions in a circular area of 2000 units
|
||||
List<WorldObject> visibles = getVisibleObjects(object, 2000);
|
||||
|
||||
// tell the player about the surroundings
|
||||
// Go through the visible objects contained in the circular area
|
||||
for (WorldObject visible : visibles)
|
||||
for (WorldObject wo : getVisibleObjects(object, 2000))
|
||||
{
|
||||
// Add the object in WorldObjectHashSet(WorldObject) _knownObjects of the visible Creature according to conditions :
|
||||
// - Creature is visible
|
||||
// - object is not already known
|
||||
// - object is in the watch distance
|
||||
// If WorldObject is a PlayerInstance, add WorldObject in WorldObjectHashSet(PlayerInstance) _knownPlayer of the visible Creature
|
||||
visible.getKnownList().addKnownObject(object, dropper);
|
||||
wo.getKnownList().addKnownObject(object, dropper);
|
||||
|
||||
// Add the visible WorldObject in WorldObjectHashSet(WorldObject) _knownObjects of the object according to conditions
|
||||
// If visible WorldObject is a PlayerInstance, add visible WorldObject in WorldObjectHashSet(PlayerInstance) _knownPlayer of the object
|
||||
object.getKnownList().addKnownObject(visible, dropper);
|
||||
object.getKnownList().addKnownObject(wo, dropper);
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,28 +460,26 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
// Remove the object from the WorldObjectHashSet(WorldObject) _visibleObjects of WorldRegion
|
||||
// If object is a PlayerInstance, remove it from the WorldObjectHashSet(PlayerInstance) _allPlayers of this WorldRegion
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
for (WorldRegion reg : oldRegion.getSurroundingRegions())
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject obj : reg.getVisibleObjects())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects())
|
||||
{
|
||||
// Remove the WorldObject from the WorldObjectHashSet(WorldObject) _knownObjects of the surrounding WorldRegion Creatures
|
||||
// If object is a PlayerInstance, remove the WorldObject from the WorldObjectHashSet(PlayerInstance) _knownPlayer of the surrounding WorldRegion Creatures
|
||||
// If object is targeted by one of the surrounding WorldRegion Creatures, cancel ATTACK and cast
|
||||
if ((obj != null) && (obj.getKnownList() != null))
|
||||
if ((wo != null) && (wo.getKnownList() != null))
|
||||
{
|
||||
obj.getKnownList().removeKnownObject(object);
|
||||
wo.getKnownList().removeKnownObject(object);
|
||||
}
|
||||
|
||||
// Remove surrounding WorldRegion Creatures from the WorldObjectHashSet(WorldObject) _KnownObjects of object
|
||||
@ -550,7 +487,7 @@ public class World
|
||||
//
|
||||
if (object.getKnownList() != null)
|
||||
{
|
||||
object.getKnownList().removeKnownObject(obj);
|
||||
object.getKnownList().removeKnownObject(wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -575,7 +512,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all visible objects of the WorldRegion object's and of its surrounding WorldRegion.<BR>
|
||||
@ -598,50 +534,36 @@ public class World
|
||||
return null;
|
||||
}
|
||||
|
||||
final WorldRegion reg = object.getWorldRegion();
|
||||
|
||||
if (reg == null)
|
||||
final WorldRegion region = object.getWorldRegion();
|
||||
if (region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create an FastList in order to contain all visible WorldObject
|
||||
// Create a list in order to contain all visible WorldObject
|
||||
final List<WorldObject> result = new ArrayList<>();
|
||||
|
||||
// Create a FastList containing all regions around the current region
|
||||
List<WorldRegion> regions = reg.getSurroundingRegions();
|
||||
|
||||
// Go through the FastList of region
|
||||
for (int i = 0; (regions != null) && (i < regions.size()); i++)
|
||||
// Go through the list of region
|
||||
for (WorldRegion worldRegion : region.getSurroundingRegions())
|
||||
{
|
||||
// Go through visible objects of the selected region
|
||||
L2ObjectSet<WorldObject> actual_objectSet = null;
|
||||
if (regions.get(i) != null)
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects())
|
||||
{
|
||||
actual_objectSet = regions.get(i).getVisibleObjects();
|
||||
}
|
||||
|
||||
if ((actual_objectSet != null) && (actual_objectSet.size() > 0))
|
||||
{
|
||||
for (WorldObject _object : actual_objectSet)
|
||||
{
|
||||
if (_object == null)
|
||||
if (wo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_object.equals(object))
|
||||
if (wo.equals(object))
|
||||
{
|
||||
continue; // skip our own character
|
||||
}
|
||||
|
||||
if (!_object.isVisible())
|
||||
if (!wo.isVisible())
|
||||
{
|
||||
continue; // skip dying objects
|
||||
}
|
||||
|
||||
result.add(_object);
|
||||
}
|
||||
result.add(wo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -673,7 +595,6 @@ public class World
|
||||
}
|
||||
|
||||
final WorldRegion region = object.getWorldRegion();
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
return new ArrayList<>();
|
||||
@ -683,38 +604,35 @@ public class World
|
||||
final int y = object.getY();
|
||||
final int sqRadius = radius * radius;
|
||||
|
||||
// Create an FastList in order to contain all visible WorldObject
|
||||
// Create a list in order to contain all visible WorldObject
|
||||
final List<WorldObject> result = new ArrayList<>();
|
||||
|
||||
// Create an FastList containing all regions around the current region
|
||||
List<WorldRegion> regions = region.getSurroundingRegions();
|
||||
|
||||
// Go through the FastList of region
|
||||
for (int i = 0; (regions != null) && (i < regions.size()); i++)
|
||||
// Go through the list of region
|
||||
for (WorldRegion worldRegion : region.getSurroundingRegions())
|
||||
{
|
||||
// Go through visible objects of the selected region
|
||||
for (WorldObject _object : regions.get(i).getVisibleObjects())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects())
|
||||
{
|
||||
if (_object == null)
|
||||
if (wo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_object.equals(object))
|
||||
if (wo.equals(object))
|
||||
{
|
||||
continue; // skip our own character
|
||||
}
|
||||
|
||||
final int x1 = _object.getX();
|
||||
final int y1 = _object.getY();
|
||||
final int x1 = wo.getX();
|
||||
final int y1 = wo.getY();
|
||||
|
||||
final double dx = x1 - x;
|
||||
final double dy = y1 - y;
|
||||
|
||||
// If the visible object is inside the circular area add the object to the FastList result
|
||||
// If the visible object is inside the circular area add the object to the list result
|
||||
if (((dx * dx) + (dy * dy)) < sqRadius)
|
||||
{
|
||||
result.add(_object);
|
||||
result.add(wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -751,30 +669,27 @@ public class World
|
||||
final int z = object.getZ();
|
||||
final int sqRadius = radius * radius;
|
||||
|
||||
// Create an FastList in order to contain all visible WorldObject
|
||||
// Create a list in order to contain all visible WorldObject
|
||||
final List<WorldObject> result = new ArrayList<>();
|
||||
|
||||
// Create an FastList containing all regions around the current region
|
||||
List<WorldRegion> regions = object.getWorldRegion().getSurroundingRegions();
|
||||
|
||||
// Go through visible object of the selected region
|
||||
for (WorldRegion region : regions)
|
||||
for (WorldRegion worldRegion : object.getWorldRegion().getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject _object : region.getVisibleObjects())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects())
|
||||
{
|
||||
if (_object == null)
|
||||
if (wo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_object.equals(object))
|
||||
if (wo.equals(object))
|
||||
{
|
||||
continue; // skip our own character
|
||||
}
|
||||
|
||||
final int x1 = _object.getX();
|
||||
final int y1 = _object.getY();
|
||||
final int z1 = _object.getZ();
|
||||
final int x1 = wo.getX();
|
||||
final int y1 = wo.getY();
|
||||
final int z1 = wo.getZ();
|
||||
|
||||
final long dx = x1 - x;
|
||||
final long dy = y1 - y;
|
||||
@ -782,7 +697,7 @@ public class World
|
||||
|
||||
if (((dx * dx) + (dy * dy) + (dz * dz)) < sqRadius)
|
||||
{
|
||||
result.add(_object);
|
||||
result.add(wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -801,53 +716,44 @@ public class World
|
||||
* <B><U> Example of use </U> :</B><BR>
|
||||
* <BR>
|
||||
* <li>Find Close Objects for Creature</li><BR>
|
||||
* @param object L2object that determine the current WorldRegion
|
||||
* @param object WorldObject that determine the current WorldRegion
|
||||
* @return the visible playable
|
||||
*/
|
||||
public List<Playable> getVisiblePlayable(WorldObject object)
|
||||
public List<PlayerInstance> getVisiblePlayers(WorldObject object)
|
||||
{
|
||||
WorldRegion reg = object.getWorldRegion();
|
||||
|
||||
if (reg == null)
|
||||
final WorldRegion region = object.getWorldRegion();
|
||||
if (region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create an FastList in order to contain all visible WorldObject
|
||||
final List<Playable> result = new ArrayList<>();
|
||||
// Create a list in order to contain all visible WorldObject
|
||||
final List<PlayerInstance> result = new ArrayList<>();
|
||||
|
||||
// Create a FastList containing all regions around the current region
|
||||
List<WorldRegion> regions = reg.getSurroundingRegions();
|
||||
|
||||
// Go through the FastList of region
|
||||
for (WorldRegion region : regions)
|
||||
// Go through the list of region
|
||||
for (WorldRegion worldRegion : region.getSurroundingRegions())
|
||||
{
|
||||
// Create an Iterator to go through the visible WorldObject of the WorldRegion
|
||||
Iterator<Playable> playables = region.iterateAllPlayers();
|
||||
|
||||
// Go through visible object of the selected region
|
||||
while (playables.hasNext())
|
||||
for (PlayerInstance playable : worldRegion.getAllPlayers())
|
||||
{
|
||||
Playable _object = playables.next();
|
||||
|
||||
if (_object == null)
|
||||
if (playable == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_object.equals(object))
|
||||
if (playable.equals(object))
|
||||
{
|
||||
continue; // skip our own character
|
||||
}
|
||||
|
||||
if (!_object.isVisible())
|
||||
if (!playable.isVisible())
|
||||
{
|
||||
continue; // skip dying objects
|
||||
}
|
||||
|
||||
result.add(_object);
|
||||
result.add(playable);
|
||||
|
||||
_object = null;
|
||||
playable = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -889,21 +795,6 @@ public class World
|
||||
return _worldRegions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current WorldRegions of the object is valid according to its position (x,y).<BR>
|
||||
* <BR>
|
||||
* <B><U> Example of use </U> :</B><BR>
|
||||
* <BR>
|
||||
* <li>Init WorldRegions</li><BR>
|
||||
* @param x X position of the object
|
||||
* @param y Y position of the object
|
||||
* @return True if the WorldRegion is valid
|
||||
*/
|
||||
private boolean validRegion(int x, int y)
|
||||
{
|
||||
return (x >= 0) && (x <= REGIONS_X) && (y >= 0) && (y <= REGIONS_Y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init each WorldRegion and their surrounding table.<BR>
|
||||
* <BR>
|
||||
@ -921,30 +812,36 @@ public class World
|
||||
|
||||
_worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
for (int i = 0; i <= REGIONS_X; i++)
|
||||
{
|
||||
for (int j = 0; j <= REGIONS_Y; j++)
|
||||
{
|
||||
_worldRegions[i][j] = new WorldRegion(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x <= REGIONS_X; x++)
|
||||
{
|
||||
for (int y = 0; y <= REGIONS_Y; y++)
|
||||
{
|
||||
for (int a = -1; a <= 1; a++)
|
||||
_worldRegions[x][y] = new WorldRegion(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// Set surrounding regions.
|
||||
for (int rx = 0; rx <= REGIONS_X; rx++)
|
||||
{
|
||||
for (int b = -1; b <= 1; b++)
|
||||
for (int ry = 0; ry <= REGIONS_Y; ry++)
|
||||
{
|
||||
if (validRegion(x + a, y + b))
|
||||
final List<WorldRegion> surroundingRegions = new ArrayList<>();
|
||||
for (int sx = rx - 1; sx <= (rx + 1); sx++)
|
||||
{
|
||||
_worldRegions[x + a][y + b].addSurroundingRegion(_worldRegions[x][y]);
|
||||
for (int sy = ry - 1; sy <= (ry + 1); sy++)
|
||||
{
|
||||
if (((sx >= 0) && (sx < REGIONS_X) && (sy >= 0) && (sy < REGIONS_Y)))
|
||||
{
|
||||
surroundingRegions.add(_worldRegions[sx][sy]);
|
||||
}
|
||||
}
|
||||
}
|
||||
WorldRegion[] regionArray = new WorldRegion[surroundingRegions.size()];
|
||||
regionArray = surroundingRegions.toArray(regionArray);
|
||||
_worldRegions[rx][ry].setSurroundingRegions(regionArray);
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("World: (" + REGIONS_X + "x" + REGIONS_Y + ") World Region Grid set up.");
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,13 @@
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
import org.l2jmobius.commons.util.object.L2ObjectSet;
|
||||
import org.l2jmobius.gameserver.ai.AttackableAI;
|
||||
import org.l2jmobius.gameserver.ai.FortSiegeGuardAI;
|
||||
import org.l2jmobius.gameserver.ai.SiegeGuardAI;
|
||||
@ -33,6 +31,7 @@ import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||
import org.l2jmobius.gameserver.model.actor.Creature;
|
||||
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||
import org.l2jmobius.gameserver.model.spawn.Spawn;
|
||||
import org.l2jmobius.gameserver.model.zone.ZoneManager;
|
||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||
@ -43,33 +42,19 @@ public class WorldRegion
|
||||
{
|
||||
private static Logger LOGGER = Logger.getLogger(WorldRegion.class.getName());
|
||||
|
||||
private final L2ObjectSet<Playable> _allPlayable;
|
||||
private final L2ObjectSet<WorldObject> _visibleObjects;
|
||||
private final List<WorldRegion> _surroundingRegions;
|
||||
private final int _tileX;
|
||||
private final int _tileY;
|
||||
private Boolean _active = false;
|
||||
private final Collection<PlayerInstance> _playerObjects = ConcurrentHashMap.newKeySet();
|
||||
private final Collection<WorldObject> _visibleObjects = ConcurrentHashMap.newKeySet();
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private Boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
private ZoneManager _zoneManager;
|
||||
|
||||
public WorldRegion(int pTileX, int pTileY)
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_allPlayable = L2ObjectSet.createL2PlayerSet();
|
||||
_visibleObjects = L2ObjectSet.createL2ObjectSet();
|
||||
_surroundingRegions = new ArrayList<>();
|
||||
|
||||
_tileX = pTileX;
|
||||
_tileY = pTileY;
|
||||
|
||||
// default a newly initialized region to inactive, unless always on is specified
|
||||
if (Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
_active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_active = false;
|
||||
}
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
}
|
||||
|
||||
public void addZone(ZoneType zone)
|
||||
@ -143,55 +128,15 @@ public class WorldRegion
|
||||
}
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (_isActivating)
|
||||
{
|
||||
// for each neighbor, if it's not active, activate.
|
||||
for (WorldRegion neighbor : getSurroundingRegions())
|
||||
{
|
||||
neighbor.setActive(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (areNeighborsEmpty())
|
||||
{
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
// check and deactivate
|
||||
for (WorldRegion neighbor : getSurroundingRegions())
|
||||
{
|
||||
if (neighbor.areNeighborsEmpty())
|
||||
{
|
||||
neighbor.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(Boolean isOn)
|
||||
{
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects)
|
||||
for (WorldObject wo : _visibleObjects)
|
||||
{
|
||||
if (o instanceof Attackable)
|
||||
if (wo instanceof Attackable)
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel Attack or Cast
|
||||
mob.setTarget(null);
|
||||
@ -226,25 +171,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof NpcInstance)
|
||||
else if (wo instanceof NpcInstance)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((NpcInstance) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((NpcInstance) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects)
|
||||
for (WorldObject wo : _visibleObjects)
|
||||
{
|
||||
if (o instanceof Attackable)
|
||||
if (wo instanceof Attackable)
|
||||
{
|
||||
// Start HP/MP/CP Regeneration task
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((NpcInstance) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((NpcInstance) wo);
|
||||
}
|
||||
else if (o instanceof NpcInstance)
|
||||
else if (wo instanceof NpcInstance)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((NpcInstance) o);
|
||||
RandomAnimationTaskManager.getInstance().add((NpcInstance) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,22 +204,13 @@ public class WorldRegion
|
||||
// returns true if the above condition is met.
|
||||
public Boolean areNeighborsEmpty()
|
||||
{
|
||||
// if this region is occupied, return false.
|
||||
if (_active && (_allPlayable.size() > 0))
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// if any one of the neighbors is occupied, return false
|
||||
for (WorldRegion neighbor : _surroundingRegions)
|
||||
{
|
||||
if (neighbor.isActive() && (neighbor._allPlayable.size() > 0))
|
||||
if (worldRegion.isActive() && !worldRegion.getAllPlayers().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// in all other cases, return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -300,18 +236,27 @@ public class WorldRegion
|
||||
*/
|
||||
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)
|
||||
{
|
||||
_neighborsTask.cancel(true);
|
||||
_neighborsTask = null;
|
||||
}
|
||||
|
||||
// then, set a timer to activate the neighbors
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,16 +264,28 @@ public class WorldRegion
|
||||
*/
|
||||
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)
|
||||
{
|
||||
_neighborsTask.cancel(true);
|
||||
_neighborsTask = null;
|
||||
}
|
||||
|
||||
// start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,14 +301,14 @@ public class WorldRegion
|
||||
return;
|
||||
}
|
||||
|
||||
_visibleObjects.put(object);
|
||||
_visibleObjects.add(object);
|
||||
|
||||
if (object instanceof Playable)
|
||||
if (object instanceof PlayerInstance)
|
||||
{
|
||||
_allPlayable.put((Playable) object);
|
||||
_playerObjects.add((PlayerInstance) object);
|
||||
|
||||
// if this is the first player to enter the region, activate self & neighbors
|
||||
if ((_allPlayable.size() == 1) && !Config.GRIDS_ALWAYS_ON)
|
||||
if ((_playerObjects.size() == 1) && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -376,41 +333,41 @@ public class WorldRegion
|
||||
|
||||
if (object instanceof Playable)
|
||||
{
|
||||
_allPlayable.remove((Playable) object);
|
||||
_playerObjects.remove(object);
|
||||
|
||||
if ((_allPlayable.size() == 0) && !Config.GRIDS_ALWAYS_ON)
|
||||
if (_playerObjects.isEmpty() && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startDeactivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addSurroundingRegion(WorldRegion region)
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions.add(region);
|
||||
_surroundingRegions = regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list _surroundingRegions containing all WorldRegion around the current WorldRegion
|
||||
*/
|
||||
public List<WorldRegion> getSurroundingRegions()
|
||||
public WorldRegion[] getSurroundingRegions()
|
||||
{
|
||||
return _surroundingRegions;
|
||||
}
|
||||
|
||||
public Iterator<Playable> iterateAllPlayers()
|
||||
public Collection<PlayerInstance> getAllPlayers()
|
||||
{
|
||||
return _allPlayable.iterator();
|
||||
return _playerObjects;
|
||||
}
|
||||
|
||||
public L2ObjectSet<WorldObject> getVisibleObjects()
|
||||
public Collection<WorldObject> getVisibleObjects()
|
||||
{
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return "(" + _tileX + ", " + _tileY + ")";
|
||||
return "(" + _regionX + ", " + _regionY + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.actor.knownlist;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -117,19 +116,10 @@ public class WorldObjectKnownList
|
||||
|
||||
private final void findCloseObjects()
|
||||
{
|
||||
final boolean isActiveObjectPlayable = _activeObject instanceof Playable;
|
||||
|
||||
if (isActiveObjectPlayable)
|
||||
if (_activeObject instanceof Playable)
|
||||
{
|
||||
Collection<WorldObject> objects = World.getInstance().getVisibleObjects(getActiveObject());
|
||||
|
||||
if (objects == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through all visible WorldObject near the Creature
|
||||
for (WorldObject object : objects)
|
||||
for (WorldObject object : World.getInstance().getVisibleObjects(_activeObject))
|
||||
{
|
||||
if (object == null)
|
||||
{
|
||||
@ -150,15 +140,8 @@ public class WorldObjectKnownList
|
||||
}
|
||||
else
|
||||
{
|
||||
Collection<Playable> playables = World.getInstance().getVisiblePlayable(getActiveObject());
|
||||
|
||||
if (playables == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through all visible WorldObject near the Creature
|
||||
for (WorldObject playable : playables)
|
||||
for (WorldObject playable : World.getInstance().getVisiblePlayers(_activeObject))
|
||||
{
|
||||
if (playable == null)
|
||||
{
|
||||
@ -176,14 +159,7 @@ public class WorldObjectKnownList
|
||||
public void forgetObjects()
|
||||
{
|
||||
// Go through knownObjects
|
||||
Collection<WorldObject> knownObjects = getKnownObjects().values();
|
||||
|
||||
if ((knownObjects == null) || (knownObjects.size() == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (WorldObject object : knownObjects)
|
||||
for (WorldObject object : getKnownObjects().values())
|
||||
{
|
||||
if (object == null)
|
||||
{
|
||||
|
@ -46,7 +46,6 @@ import java.util.logging.Logger;
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
import org.l2jmobius.commons.database.DatabaseFactory;
|
||||
import org.l2jmobius.commons.util.object.L2ObjectMap;
|
||||
import org.l2jmobius.gameserver.GameTimeController;
|
||||
import org.l2jmobius.gameserver.Shutdown;
|
||||
import org.l2jmobius.gameserver.cache.HtmCache;
|
||||
@ -1028,10 +1027,7 @@ public class GameStatusThread extends Thread
|
||||
int summonCount = 0;
|
||||
int AICount = 0;
|
||||
|
||||
final L2ObjectMap<WorldObject> objs = World.getInstance().getAllVisibleObjects();
|
||||
// synchronized (World.getInstance().getAllVisibleObjects())
|
||||
{
|
||||
for (WorldObject obj : objs)
|
||||
for (WorldObject obj : World.getInstance().getAllVisibleObjects())
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
@ -1089,7 +1085,7 @@ public class GameStatusThread extends Thread
|
||||
charCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Server Status: ");
|
||||
sb.append("\r\n ---> Player Count: " + playerCount + "/" + max);
|
||||
|
@ -2262,12 +2262,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -77,17 +77,17 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -399,19 +399,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -458,8 +456,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,11 +467,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -523,14 +522,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceId() != object.getInstanceId()))
|
||||
{
|
||||
@ -588,8 +588,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
@ -1174,12 +1174,6 @@ public class AttackableAI extends CreatureAI
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent thinking in non active regions.
|
||||
if (!_actor.isInActiveRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start thinking action
|
||||
_thinking = true;
|
||||
|
||||
|
@ -78,20 +78,20 @@ public class World
|
||||
private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
|
||||
|
||||
/** Map containing all the players in game. */
|
||||
private final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PlayerInstance> _allPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Good players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allGoodPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all the Evil players in game. */
|
||||
private static final Map<Integer, PlayerInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, WorldObject> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _partyNumber = new AtomicInteger();
|
||||
private static final AtomicInteger _memberInPartyNumber = new AtomicInteger();
|
||||
|
||||
private final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
private static final WorldRegion[][] _worldRegions = new WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
|
||||
|
||||
/** Constructor of World. */
|
||||
protected World()
|
||||
@ -403,19 +403,17 @@ public class World
|
||||
*/
|
||||
public void removeVisibleObject(WorldObject object, WorldRegion oldRegion)
|
||||
{
|
||||
if (object == null)
|
||||
if ((object == null) || (oldRegion == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldRegion != null)
|
||||
{
|
||||
oldRegion.removeVisibleObject(object);
|
||||
|
||||
// Go through all surrounding WorldRegion Creatures
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -462,8 +460,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,11 +471,14 @@ public class World
|
||||
return;
|
||||
}
|
||||
|
||||
oldRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!newRegion.isSurroundingRegion(w))
|
||||
if (newRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if (wo == object)
|
||||
{
|
||||
@ -527,14 +526,15 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
newRegion.forEachSurroundingRegion(w ->
|
||||
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
|
||||
{
|
||||
if (!oldRegion.isSurroundingRegion(w))
|
||||
if (oldRegion.isSurroundingRegion(worldRegion))
|
||||
{
|
||||
for (WorldObject wo : w.getVisibleObjects().values())
|
||||
continue;
|
||||
}
|
||||
|
||||
for (WorldObject wo : worldRegion.getVisibleObjects().values())
|
||||
{
|
||||
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
|
||||
{
|
||||
@ -592,8 +592,6 @@ public class World
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)
|
||||
|
@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.model;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
@ -35,40 +34,13 @@ public class WorldRegion
|
||||
private WorldRegion[] _surroundingRegions;
|
||||
private final int _regionX;
|
||||
private final int _regionY;
|
||||
private boolean _active = false;
|
||||
private boolean _active = Config.GRIDS_ALWAYS_ON;
|
||||
private ScheduledFuture<?> _neighborsTask = null;
|
||||
|
||||
public WorldRegion(int regionX, int regionY)
|
||||
{
|
||||
_regionX = regionX;
|
||||
_regionY = regionY;
|
||||
|
||||
// Default a newly initialized region to inactive, unless always on is specified.
|
||||
_active = Config.GRIDS_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/** Task of AI notification */
|
||||
public class NeighborsTask implements Runnable
|
||||
{
|
||||
private final boolean _isActivating;
|
||||
|
||||
public NeighborsTask(boolean isActivating)
|
||||
{
|
||||
_isActivating = isActivating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
forEachSurroundingRegion(w ->
|
||||
{
|
||||
if (_isActivating || w.areNeighborsEmpty())
|
||||
{
|
||||
w.setActive(_isActivating);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void switchAI(boolean isOn)
|
||||
@ -80,11 +52,11 @@ public class WorldRegion
|
||||
|
||||
if (!isOn)
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
final Attackable mob = (Attackable) o;
|
||||
final Attackable mob = (Attackable) wo;
|
||||
|
||||
// Set target to null and cancel attack or cast.
|
||||
mob.setTarget(null);
|
||||
@ -107,25 +79,25 @@ public class WorldRegion
|
||||
|
||||
RandomAnimationTaskManager.getInstance().remove(mob);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().remove((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject o : _visibleObjects.values())
|
||||
for (WorldObject wo : _visibleObjects.values())
|
||||
{
|
||||
if (o.isAttackable())
|
||||
if (wo.isAttackable())
|
||||
{
|
||||
// Start HP/MP/CP regeneration task.
|
||||
((Attackable) o).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
((Attackable) wo).getStatus().startHpMpRegeneration();
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
else if (o instanceof Npc)
|
||||
else if (wo instanceof Npc)
|
||||
{
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) o);
|
||||
RandomAnimationTaskManager.getInstance().add((Npc) wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +110,14 @@ public class WorldRegion
|
||||
|
||||
public boolean areNeighborsEmpty()
|
||||
{
|
||||
return forEachSurroundingRegion(w -> !(w.isActive() && w.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable)));
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.isActive() && worldRegion.getVisibleObjects().values().stream().anyMatch(WorldObject::isPlayable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +155,13 @@ public class WorldRegion
|
||||
}
|
||||
|
||||
// Then, set a timer to activate the neighbors.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(true), 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
worldRegion.setActive(true);
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNON_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +181,16 @@ public class WorldRegion
|
||||
|
||||
// Start a timer to "suggest" a deactivate to self and neighbors.
|
||||
// Suggest means: first check if a neighbor has PlayerInstances in it. If not, deactivate.
|
||||
_neighborsTask = ThreadPool.schedule(new NeighborsTask(false), 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
_neighborsTask = ThreadPool.schedule(() ->
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (worldRegion.areNeighborsEmpty())
|
||||
{
|
||||
worldRegion.setActive(false);
|
||||
}
|
||||
}
|
||||
}, 1000 * Config.GRID_NEIGHBOR_TURNOFF_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +211,7 @@ public class WorldRegion
|
||||
if (object.isPlayable())
|
||||
{
|
||||
// If this is the first player to enter the region, activate self and neighbors.
|
||||
if (!_active && (!Config.GRIDS_ALWAYS_ON))
|
||||
if (!_active && !Config.GRIDS_ALWAYS_ON)
|
||||
{
|
||||
startActivation();
|
||||
}
|
||||
@ -255,18 +249,6 @@ public class WorldRegion
|
||||
return _visibleObjects;
|
||||
}
|
||||
|
||||
public boolean forEachSurroundingRegion(Predicate<WorldRegion> p)
|
||||
{
|
||||
for (WorldRegion worldRegion : _surroundingRegions)
|
||||
{
|
||||
if (!p.test(worldRegion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setSurroundingRegions(WorldRegion[] regions)
|
||||
{
|
||||
_surroundingRegions = regions;
|
||||
|
Loading…
Reference in New Issue
Block a user