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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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 javax.xml.parsers.DocumentBuilderFactory;
@ -33,7 +30,6 @@ import org.w3c.dom.Node;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.enums.FenceState;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldRegion;
import org.l2jmobius.gameserver.model.actor.instance.FenceInstance;
@ -47,7 +43,6 @@ public class FenceData
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()
@ -126,21 +121,12 @@ public class FenceData
private void addFence(FenceInstance fence)
{
final Location point = new Location(fence.getX(), fence.getY(), fence.getZ());
_fences.put(fence.getObjectId(), fence);
_regions.computeIfAbsent(World.getInstance().getRegion(point), key -> new ArrayList<>()).add(fence);
}
public void removeFence(FenceInstance fence)
{
_fences.remove(fence.getObjectId());
final Location point = new Location(fence.getX(), fence.getY(), fence.getZ());
final List<FenceInstance> fencesInRegion = _regions.get(World.getInstance().getRegion(point));
if (fencesInRegion != null)
{
fencesInRegion.remove(fence);
}
}
public Map<Integer, FenceInstance> getFences()
@ -155,12 +141,19 @@ public class FenceData
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz)
{
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;
}
final int xMin = fence.getXMin();
@ -169,40 +162,30 @@ public class FenceData
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;
};
return _regions.getOrDefault(World.getInstance().getRegion(new Location(x, y, z)), 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

@ -460,6 +460,11 @@ public abstract class WorldObject
return false;
}
public boolean isFence()
{
return false;
}
public boolean isBoat()
{
return false;

View File

@ -31,6 +31,7 @@ import org.l2jmobius.gameserver.data.sql.SpawnTable;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.DoorInstance;
import org.l2jmobius.gameserver.model.actor.instance.FenceInstance;
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
import org.l2jmobius.gameserver.model.spawn.Spawn;
import org.l2jmobius.gameserver.model.zone.ZoneManager;
@ -45,6 +46,7 @@ public class WorldRegion
private final UnboundArrayList<WorldObject> _visibleObjects = new UnboundArrayList<>();
private final List<DoorInstance> _doors = new ArrayList<>(1);
private final List<FenceInstance> _fences = new ArrayList<>(1);
private WorldRegion[] _surroundingRegions;
private final int _regionX;
private final int _regionY;
@ -241,7 +243,7 @@ public class WorldRegion
_active = value;
// turn the AI on or off to match the region's activation.
// Turn the AI on or off to match the region's activation.
switchAI(value);
}
@ -305,8 +307,7 @@ public class WorldRegion
/**
* Add the WorldObject in the WorldObjectHashSet(WorldObject) _visibleObjects containing WorldObject visible in this WorldRegion<br>
* If WorldObject is a PlayerInstance, Add the PlayerInstance in the WorldObjectHashSet(PlayerInstance) _allPlayable containing PlayerInstance of all player in game in this WorldRegion<br>
* Assert : object.getCurrentWorldRegion() == this
* If WorldObject is a PlayerInstance, Add the PlayerInstance in the WorldObjectHashSet(PlayerInstance) _allPlayable containing PlayerInstance of all player in game in this WorldRegion
* @param object
*/
public void addVisibleObject(WorldObject object)
@ -325,6 +326,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)
@ -334,9 +342,7 @@ public class WorldRegion
}
/**
* Remove the WorldObject from the WorldObjectHashSet(WorldObject) _visibleObjects in this WorldRegion<br>
* If WorldObject is a PlayerInstance, remove it from the WorldObjectHashSet(PlayerInstance) _allPlayable of this WorldRegion<br>
* Assert : object.getCurrentWorldRegion() == this || object.getCurrentWorldRegion() == null
* Remove the WorldObject from the WorldObjectHashSet(WorldObject) _visibleObjects in this WorldRegion. If WorldObject is a PlayerInstance, remove it from the WorldObjectHashSet(PlayerInstance) _allPlayable of this WorldRegion
* @param object
*/
public void removeVisibleObject(WorldObject object)
@ -357,7 +363,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);
}
}
@ -414,6 +427,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 String getName()
{
return "(" + _regionX + ", " + _regionY + ")";

View File

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

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 javax.xml.parsers.DocumentBuilderFactory;
@ -33,7 +30,6 @@ import org.w3c.dom.Node;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.enums.FenceState;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldRegion;
import org.l2jmobius.gameserver.model.actor.instance.FenceInstance;
@ -47,7 +43,6 @@ public class FenceData
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()
@ -126,21 +121,12 @@ public class FenceData
private void addFence(FenceInstance fence)
{
final Location point = new Location(fence.getX(), fence.getY(), fence.getZ());
_fences.put(fence.getObjectId(), fence);
_regions.computeIfAbsent(World.getInstance().getRegion(point), key -> new ArrayList<>()).add(fence);
}
public void removeFence(FenceInstance fence)
{
_fences.remove(fence.getObjectId());
final Location point = new Location(fence.getX(), fence.getY(), fence.getZ());
final List<FenceInstance> fencesInRegion = _regions.get(World.getInstance().getRegion(point));
if (fencesInRegion != null)
{
fencesInRegion.remove(fence);
}
}
public Map<Integer, FenceInstance> getFences()
@ -155,12 +141,19 @@ public class FenceData
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz)
{
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;
}
final int xMin = fence.getXMin();
@ -169,40 +162,30 @@ public class FenceData
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;
};
return _regions.getOrDefault(World.getInstance().getRegion(new Location(x, y, z)), 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

@ -460,6 +460,11 @@ public abstract class WorldObject
return false;
}
public boolean isFence()
{
return false;
}
public boolean isBoat()
{
return false;

View File

@ -31,6 +31,7 @@ import org.l2jmobius.gameserver.data.sql.SpawnTable;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.DoorInstance;
import org.l2jmobius.gameserver.model.actor.instance.FenceInstance;
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
import org.l2jmobius.gameserver.model.spawn.Spawn;
import org.l2jmobius.gameserver.model.zone.ZoneManager;
@ -45,6 +46,7 @@ public class WorldRegion
private final UnboundArrayList<WorldObject> _visibleObjects = new UnboundArrayList<>();
private final List<DoorInstance> _doors = new ArrayList<>(1);
private final List<FenceInstance> _fences = new ArrayList<>(1);
private WorldRegion[] _surroundingRegions;
private final int _regionX;
private final int _regionY;
@ -241,7 +243,7 @@ public class WorldRegion
_active = value;
// turn the AI on or off to match the region's activation.
// Turn the AI on or off to match the region's activation.
switchAI(value);
}
@ -305,8 +307,7 @@ public class WorldRegion
/**
* Add the WorldObject in the WorldObjectHashSet(WorldObject) _visibleObjects containing WorldObject visible in this WorldRegion<br>
* If WorldObject is a PlayerInstance, Add the PlayerInstance in the WorldObjectHashSet(PlayerInstance) _allPlayable containing PlayerInstance of all player in game in this WorldRegion<br>
* Assert : object.getCurrentWorldRegion() == this
* If WorldObject is a PlayerInstance, Add the PlayerInstance in the WorldObjectHashSet(PlayerInstance) _allPlayable containing PlayerInstance of all player in game in this WorldRegion
* @param object
*/
public void addVisibleObject(WorldObject object)
@ -325,6 +326,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)
@ -334,9 +342,7 @@ public class WorldRegion
}
/**
* Remove the WorldObject from the WorldObjectHashSet(WorldObject) _visibleObjects in this WorldRegion<br>
* If WorldObject is a PlayerInstance, remove it from the WorldObjectHashSet(PlayerInstance) _allPlayable of this WorldRegion<br>
* Assert : object.getCurrentWorldRegion() == this || object.getCurrentWorldRegion() == null
* Remove the WorldObject from the WorldObjectHashSet(WorldObject) _visibleObjects in this WorldRegion. If WorldObject is a PlayerInstance, remove it from the WorldObjectHashSet(PlayerInstance) _allPlayable of this WorldRegion
* @param object
*/
public void removeVisibleObject(WorldObject object)
@ -357,7 +363,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);
}
}
@ -414,6 +427,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 String getName()
{
return "(" + _regionX + ", " + _regionY + ")";

View File

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

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

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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

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;
@ -45,7 +42,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()
@ -104,18 +100,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()
@ -130,19 +119,26 @@ public class FenceData implements IXmlReader
public boolean checkIfFenceBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
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.
final int instanceId = (instance == null) ? 0 : instance.getId();
if (fence.getInstanceId() != instanceId)
{
return false;
continue;
}
final int xMin = fence.getXMin();
@ -151,34 +147,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) && (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)) && (z > (fence.getZ() - MAX_Z_DIFF)) && (z < (fence.getZ() + MAX_Z_DIFF)))
{
return true;
}
return false;
};
final WorldRegion region = World.getInstance().getRegion(x, y); // Should never be null.
return (region != null) && _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

@ -412,6 +412,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;
}
public void setTargetable(boolean targetable)
{
if (_isTargetable != targetable)

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