Store fence objects in regions.

This commit is contained in:
MobiusDevelopment
2021-03-14 22:03:28 +00:00
parent 031006131b
commit a8c77b8795
92 changed files with 1570 additions and 652 deletions

View File

@@ -17,12 +17,9 @@
package org.l2jmobius.gameserver.data.xml;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.logging.Logger;
import org.w3c.dom.Document;
@@ -44,7 +41,6 @@ public class FenceData implements IXmlReader
private static final int MAX_Z_DIFF = 100;
private final Map<WorldRegion, List<FenceInstance>> _regions = new ConcurrentHashMap<>();
private final Map<Integer, FenceInstance> _fences = new ConcurrentHashMap<>();
protected FenceData()
@@ -103,18 +99,11 @@ public class FenceData implements IXmlReader
private void addFence(FenceInstance fence)
{
_fences.put(fence.getObjectId(), fence);
_regions.computeIfAbsent(World.getInstance().getRegion(fence), key -> new ArrayList<>()).add(fence);
}
public void removeFence(FenceInstance fence)
{
_fences.remove(fence.getObjectId());
final List<FenceInstance> fencesInRegion = _regions.get(World.getInstance().getRegion(fence));
if (fencesInRegion != null)
{
fencesInRegion.remove(fence);
}
}
public Map<Integer, FenceInstance> getFences()
@@ -129,18 +118,25 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, int instanceId)
{
final Predicate<FenceInstance> filter = fence ->
final WorldRegion region = World.getInstance().getRegion(x, y);
final List<FenceInstance> fences = region != null ? region.getFences() : null;
if ((fences == null) || fences.isEmpty())
{
return false;
}
for (FenceInstance fence : fences)
{
// Check if fence is geodata enabled.
if (!fence.getState().isGeodataEnabled())
{
return false;
continue;
}
// Check if fence is within the instance we search for.
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@@ -149,41 +145,30 @@ public class FenceData implements IXmlReader
final int yMax = fence.getYMax();
if ((x < xMin) && (tx < xMin))
{
return false;
continue;
}
if ((x > xMax) && (tx > xMax))
{
return false;
continue;
}
if ((y < yMin) && (ty < yMin))
{
return false;
continue;
}
if ((y > yMax) && (ty > yMax))
{
return false;
continue;
}
if ((x > xMin) && (tx > xMin) && (x < xMax) && (tx < xMax))
if ((x > xMin) && (tx > xMin) && (x < xMax) && (tx < xMax) && (y > yMin) && (ty > yMin) && (y < yMax) && (ty < yMax))
{
if ((y > yMin) && (ty > yMin) && (y < yMax) && (ty < yMax))
{
return false;
}
continue;
}
if (crossLinePart(xMin, yMin, xMax, yMin, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMax, yMin, xMax, yMax, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMax, yMax, xMin, yMax, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMin, yMax, xMin, yMin, x, y, tx, ty, xMin, yMin, xMax, yMax))
if ((crossLinePart(xMin, yMin, xMax, yMin, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMax, yMin, xMax, yMax, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMax, yMax, xMin, yMax, x, y, tx, ty, xMin, yMin, xMax, yMax) || crossLinePart(xMin, yMax, xMin, yMin, x, y, tx, ty, xMin, yMin, xMax, yMax)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
if ((z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return region == null ? false : _regions.getOrDefault(region, Collections.emptyList()).stream().anyMatch(filter);
}
return false;
}
private boolean crossLinePart(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double xMin, double yMin, double xMax, double yMax)

View File

@@ -415,6 +415,15 @@ public abstract class WorldObject extends ListenersContainer implements IIdentif
return false;
}
/**
* Verifies if this object is a fence.
* @return {@code true} if object is Fence, {@code false} otherwise
*/
public boolean isFence()
{
return false;
}
/**
* @return {@code true} if object Can be targeted
*/

View File

@@ -25,6 +25,7 @@ import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.DoorInstance;
import org.l2jmobius.gameserver.model.actor.instance.FenceInstance;
import org.l2jmobius.gameserver.taskmanager.RandomAnimationTaskManager;
import org.l2jmobius.gameserver.util.UnboundArrayList;
@@ -34,6 +35,8 @@ public class WorldRegion
private final UnboundArrayList<WorldObject> _visibleObjects = new UnboundArrayList<>();
/** List containing doors in this world region. */
private final List<DoorInstance> _doors = new ArrayList<>(1);
/** List containing fences in this world region. */
private final List<FenceInstance> _fences = new ArrayList<>(1);
/** Array containing nearby regions forming this world region's effective area. */
private WorldRegion[] _surroundingRegions;
private final int _regionX;
@@ -241,6 +244,13 @@ public class WorldRegion
_surroundingRegions[i].addDoor((DoorInstance) object);
}
}
else if (object.isFence())
{
for (int i = 0; i < _surroundingRegions.length; i++)
{
_surroundingRegions[i].addFence((FenceInstance) object);
}
}
// If this is the first player to enter the region, activate self and neighbors.
if (object.isPlayable() && !_active && !Config.GRIDS_ALWAYS_ON)
@@ -271,7 +281,14 @@ public class WorldRegion
{
for (int i = 0; i < _surroundingRegions.length; i++)
{
removeDoor((DoorInstance) object);
_surroundingRegions[i].removeDoor((DoorInstance) object);
}
}
else if (object.isFence())
{
for (int i = 0; i < _surroundingRegions.length; i++)
{
_surroundingRegions[i].removeFence((FenceInstance) object);
}
}
@@ -304,6 +321,24 @@ public class WorldRegion
return _doors;
}
public synchronized void addFence(FenceInstance fence)
{
if (!_fences.contains(fence))
{
_fences.add(fence);
}
}
private synchronized void removeFence(FenceInstance fence)
{
_fences.remove(fence);
}
public List<FenceInstance> getFences()
{
return _fences;
}
public void setSurroundingRegions(WorldRegion[] regions)
{
_surroundingRegions = regions;

View File

@@ -160,4 +160,10 @@ public class FenceInstance extends WorldObject
{
return _yMax;
}
@Override
public boolean isFence()
{
return true;
}
}