WorldRegion class simplifications.

This commit is contained in:
MobiusDevelopment
2019-08-19 22:37:36 +00:00
parent d2e926851d
commit 9233a76402
56 changed files with 2763 additions and 4798 deletions

View File

@ -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;

View File

@ -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,67 +403,63 @@ 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
for (WorldRegion worldRegion : oldRegion.getSurroundingRegions())
{
oldRegion.removeVisibleObject(object);
// Go through all surrounding WorldRegion Creatures
oldRegion.forEachSurroundingRegion(w ->
for (WorldObject wo : worldRegion.getVisibleObjects().values())
{
for (WorldObject wo : w.getVisibleObjects().values())
if (wo == object)
{
if (wo == object)
continue;
}
if (object.isCreature())
{
final Creature objectCreature = (Creature) object;
final CreatureAI ai = objectCreature.getAI();
if (ai != null)
{
continue;
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, wo);
}
if (object.isCreature())
if (objectCreature.getTarget() == wo)
{
final Creature objectCreature = (Creature) object;
final CreatureAI ai = objectCreature.getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, wo);
}
if (objectCreature.getTarget() == wo)
{
objectCreature.setTarget(null);
}
if (object.isPlayer())
{
object.sendPacket(new DeleteObject(wo));
}
objectCreature.setTarget(null);
}
if (wo.isCreature())
if (object.isPlayer())
{
final Creature woCreature = (Creature) wo;
final CreatureAI ai = woCreature.getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
}
if (woCreature.getTarget() == object)
{
woCreature.setTarget(null);
}
if (wo.isPlayer())
{
wo.sendPacket(new DeleteObject(object));
}
object.sendPacket(new DeleteObject(wo));
}
}
return true;
});
if (wo.isCreature())
{
final Creature woCreature = (Creature) wo;
final CreatureAI ai = woCreature.getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
}
if (woCreature.getTarget() == object)
{
woCreature.setTarget(null);
}
if (wo.isPlayer())
{
wo.sendPacket(new DeleteObject(object));
}
}
}
}
}
@ -475,125 +471,127 @@ 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)
{
if (wo == object)
continue;
}
if (object.isCreature())
{
final Creature objectCreature = (Creature) object;
final CreatureAI ai = objectCreature.getAI();
if (ai != null)
{
continue;
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, wo);
}
if (object.isCreature())
if (objectCreature.getTarget() == wo)
{
final Creature objectCreature = (Creature) object;
final CreatureAI ai = objectCreature.getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, wo);
}
if (objectCreature.getTarget() == wo)
{
objectCreature.setTarget(null);
}
if (object.isPlayer())
{
object.sendPacket(new DeleteObject(wo));
}
objectCreature.setTarget(null);
}
if (object.isPlayer())
{
object.sendPacket(new DeleteObject(wo));
}
}
if (wo.isCreature())
{
final Creature woCreature = (Creature) wo;
final CreatureAI ai = woCreature.getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
}
if (woCreature.getTarget() == object)
{
woCreature.setTarget(null);
}
if (wo.isPlayer())
{
wo.sendPacket(new DeleteObject(object));
}
}
}
}
for (WorldRegion worldRegion : newRegion.getSurroundingRegions())
{
if (oldRegion.isSurroundingRegion(worldRegion))
{
continue;
}
for (WorldObject wo : worldRegion.getVisibleObjects().values())
{
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
{
continue;
}
if (object.isPlayer() && wo.isVisibleFor((PlayerInstance) object))
{
wo.sendInfo((PlayerInstance) object);
if (wo.isCreature())
{
final Creature woCreature = (Creature) wo;
final CreatureAI ai = woCreature.getAI();
final CreatureAI ai = ((Creature) wo).getAI();
if (ai != null)
{
ai.notifyEvent(CtrlEvent.EVT_FORGET_OBJECT, object);
}
if (woCreature.getTarget() == object)
{
woCreature.setTarget(null);
}
if (wo.isPlayer())
{
wo.sendPacket(new DeleteObject(object));
ai.describeStateToPlayer((PlayerInstance) object);
if (wo.isMonster())
{
if (ai.getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
ai.setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
}
}
}
}
}
return true;
});
newRegion.forEachSurroundingRegion(w ->
{
if (!oldRegion.isSurroundingRegion(w))
{
for (WorldObject wo : w.getVisibleObjects().values())
if (wo.isPlayer() && object.isVisibleFor((PlayerInstance) wo))
{
if ((wo == object) || (wo.getInstanceWorld() != object.getInstanceWorld()))
object.sendInfo((PlayerInstance) wo);
if (object.isCreature())
{
continue;
}
if (object.isPlayer() && wo.isVisibleFor((PlayerInstance) object))
{
wo.sendInfo((PlayerInstance) object);
if (wo.isCreature())
final CreatureAI ai = ((Creature) object).getAI();
if (ai != null)
{
final CreatureAI ai = ((Creature) wo).getAI();
if (ai != null)
ai.describeStateToPlayer((PlayerInstance) wo);
if (object.isMonster())
{
ai.describeStateToPlayer((PlayerInstance) object);
if (wo.isMonster())
if (ai.getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
if (ai.getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
ai.setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
ai.setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
}
}
}
if (wo.isPlayer() && object.isVisibleFor((PlayerInstance) wo))
{
object.sendInfo((PlayerInstance) wo);
if (object.isCreature())
{
final CreatureAI ai = ((Creature) object).getAI();
if (ai != null)
{
ai.describeStateToPlayer((PlayerInstance) wo);
if (object.isMonster())
{
if (ai.getIntention() == CtrlIntention.AI_INTENTION_IDLE)
{
ai.setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
}
}
}
}
if (wo.isNpc() && object.isCreature())
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcCreatureSee((Npc) wo, (Creature) object, object.isSummon()), (Npc) wo);
}
if (object.isNpc() && wo.isCreature())
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcCreatureSee((Npc) object, (Creature) wo, wo.isSummon()), (Npc) object);
}
}
if (wo.isNpc() && object.isCreature())
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcCreatureSee((Npc) wo, (Creature) object, object.isSummon()), (Npc) wo);
}
if (object.isNpc() && wo.isCreature())
{
EventDispatcher.getInstance().notifyEventAsync(new OnNpcCreatureSee((Npc) object, (Creature) wo, wo.isSummon()), (Npc) object);
}
}
return true;
});
}
}
public <T extends WorldObject> List<T> getVisibleObjects(WorldObject object, Class<T> clazz)

View File

@ -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;