Support for spawn banned territories.

This commit is contained in:
MobiusDevelopment
2022-08-30 21:31:12 +00:00
parent 50f15c4fb1
commit 0d34380d18
9 changed files with 429 additions and 24 deletions

View File

@@ -38,6 +38,26 @@
<xs:attribute type="xs:int" name="rad" use="optional" /> <xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="banned_territory" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="node" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:int" name="x" use="required" />
<xs:attribute type="xs:int" name="y" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="optional" />
<xs:attribute type="xs:short" name="minZ" use="required" />
<xs:attribute type="xs:short" name="maxZ" use="required" />
<xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="npc" minOccurs="1" maxOccurs="unbounded"> <xs:element name="npc" minOccurs="1" maxOccurs="unbounded">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>

View File

@@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader
private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final String OTHER_XML_FOLDER = "data/spawns/Others";
private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>(); private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>();
private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>(); private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>();
private int _spanwCount = 0; private int _spawnCount = 0;
@Override @Override
public void load() public void load()
@@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader
{ {
LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); LOGGER.info(getClass().getSimpleName() + ": Initializing spawns...");
parseDatapackDirectory("data/spawns", true); parseDatapackDirectory("data/spawns", true);
LOGGER.info(getClass().getSimpleName() + ": " + _spanwCount + " spawns have been initialized!"); LOGGER.info(getClass().getSimpleName() + ": " + _spawnCount + " spawns have been initialized!");
} }
} }
@@ -273,6 +273,106 @@ public class SpawnTable implements IXmlReader
ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm)); ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm));
} }
// Check for NPC banned spawn territories
else if (npctag.getNodeName().equalsIgnoreCase("banned_territory"))
{
if (!ZoneManager.getInstance().spawnTerritoryExists(territoryName))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: banned_territory " + territoryName + " must be set after normal territory.");
continue;
}
final int minZ = parseInteger(attrs, "minZ");
final int maxZ = parseInteger(attrs, "maxZ");
final String zoneShape = parseString(attrs, "shape", "NPoly");
final List<int[]> rs = new ArrayList<>();
int[][] coords;
ZoneForm zoneForm = null;
try
{
for (Node c = npctag.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("node".equalsIgnoreCase(c.getNodeName()))
{
attrs = c.getAttributes();
final int[] point = new int[2];
point[0] = parseInteger(attrs, "x");
point[1] = parseInteger(attrs, "y");
rs.add(point);
}
}
coords = rs.toArray(new int[rs.size()][2]);
rs.clear();
if ((coords == null) || (coords.length == 0))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: missing data for spawn banned_territory: " + territoryName + " XML file: " + f.getName());
continue;
}
// Create this zone. Parsing for cuboids is a bit different than for other polygons cuboids need exactly 2 points to be defined.
// Other polygons need at least 3 (one per vertex)
if (zoneShape.equalsIgnoreCase("Cuboid"))
{
if (coords.length == 2)
{
zoneForm = new ZoneCuboid(coords[0][0], coords[1][0], coords[0][1], coords[1][1], minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Missing cuboid vertex data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("NPoly"))
{
// nPoly needs to have at least 3 vertices
if (coords.length > 2)
{
final int[] aX = new int[coords.length];
final int[] aY = new int[coords.length];
for (int i = 0; i < coords.length; i++)
{
aX[i] = coords[i][0];
aY[i] = coords[i][1];
}
zoneForm = new ZoneNPoly(aX, aY, minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("Cylinder"))
{
// A Cylinder zone requires a center point at x,y and a radius
final int zoneRad = Integer.parseInt(attrs.getNamedItem("rad").getNodeValue());
if ((coords.length == 1) && (zoneRad > 0))
{
zoneForm = new ZoneCylinder(coords[0][0], coords[0][1], minZ, maxZ, zoneRad);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Unknown shape: \"" + zoneShape + "\" for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": SpawnTable: Failed to load banned_territory " + territoryName + " coordinates: " + e.getMessage(), e);
}
ZoneManager.getInstance().getSpawnTerritory(territoryName).setBannedTerritory(zoneForm);
}
// Check for NPC spawns // Check for NPC spawns
else if (npctag.getNodeName().equalsIgnoreCase("npc")) else if (npctag.getNodeName().equalsIgnoreCase("npc"))
{ {
@@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader
} }
spawnInfo.set("fileName", f.getPath()); spawnInfo.set("fileName", f.getPath());
_spanwCount += addSpawn(spawnInfo, map); _spawnCount += addSpawn(spawnInfo, map);
} }
} }
} }

View File

@@ -16,21 +16,18 @@
*/ */
package org.l2jmobius.gameserver.model.zone.type; package org.l2jmobius.gameserver.model.zone.type;
import java.util.List;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.zone.ZoneForm; import org.l2jmobius.gameserver.model.zone.ZoneForm;
/** /**
* Just dummy zone, needs only for geometry calculations * Just dummy zone, needs only for geometry calculations
* @author GKR * @author GKR, Mobius
*/ */
public class NpcSpawnTerritory public class NpcSpawnTerritory
{ {
private final String _name; private final String _name;
private final ZoneForm _territory; private final ZoneForm _territory;
@SuppressWarnings("unused") private ZoneForm _banned;
private List<ZoneForm> _bannedTerritories; // TODO: Implement it
public NpcSpawnTerritory(String name, ZoneForm territory) public NpcSpawnTerritory(String name, ZoneForm territory)
{ {
@@ -38,6 +35,11 @@ public class NpcSpawnTerritory
_territory = territory; _territory = territory;
} }
public void setBannedTerritory(ZoneForm banned)
{
_banned = banned;
}
public String getName() public String getName()
{ {
return _name; return _name;
@@ -45,6 +47,19 @@ public class NpcSpawnTerritory
public Location getRandomPoint() public Location getRandomPoint()
{ {
if (_banned != null)
{
int count = 0; // Prevent infinite loop from wrongly written data.
Location location;
while (count++ < 1000)
{
location = _territory.getRandomPoint();
if (!_banned.isInsideZone(location.getX(), location.getY(), location.getZ()))
{
return location;
}
}
}
return _territory.getRandomPoint(); return _territory.getRandomPoint();
} }

View File

@@ -38,6 +38,26 @@
<xs:attribute type="xs:int" name="rad" use="optional" /> <xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="banned_territory" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="node" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:int" name="x" use="required" />
<xs:attribute type="xs:int" name="y" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="optional" />
<xs:attribute type="xs:short" name="minZ" use="required" />
<xs:attribute type="xs:short" name="maxZ" use="required" />
<xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="npc" minOccurs="1" maxOccurs="unbounded"> <xs:element name="npc" minOccurs="1" maxOccurs="unbounded">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>

View File

@@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader
private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final String OTHER_XML_FOLDER = "data/spawns/Others";
private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>(); private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>();
private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>(); private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>();
private int _spanwCount = 0; private int _spawnCount = 0;
@Override @Override
public void load() public void load()
@@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader
{ {
LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); LOGGER.info(getClass().getSimpleName() + ": Initializing spawns...");
parseDatapackDirectory("data/spawns", true); parseDatapackDirectory("data/spawns", true);
LOGGER.info(getClass().getSimpleName() + ": " + _spanwCount + " spawns have been initialized!"); LOGGER.info(getClass().getSimpleName() + ": " + _spawnCount + " spawns have been initialized!");
} }
} }
@@ -273,6 +273,106 @@ public class SpawnTable implements IXmlReader
ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm)); ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm));
} }
// Check for NPC banned spawn territories
else if (npctag.getNodeName().equalsIgnoreCase("banned_territory"))
{
if (!ZoneManager.getInstance().spawnTerritoryExists(territoryName))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: banned_territory " + territoryName + " must be set after normal territory.");
continue;
}
final int minZ = parseInteger(attrs, "minZ");
final int maxZ = parseInteger(attrs, "maxZ");
final String zoneShape = parseString(attrs, "shape", "NPoly");
final List<int[]> rs = new ArrayList<>();
int[][] coords;
ZoneForm zoneForm = null;
try
{
for (Node c = npctag.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("node".equalsIgnoreCase(c.getNodeName()))
{
attrs = c.getAttributes();
final int[] point = new int[2];
point[0] = parseInteger(attrs, "x");
point[1] = parseInteger(attrs, "y");
rs.add(point);
}
}
coords = rs.toArray(new int[rs.size()][2]);
rs.clear();
if ((coords == null) || (coords.length == 0))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: missing data for spawn banned_territory: " + territoryName + " XML file: " + f.getName());
continue;
}
// Create this zone. Parsing for cuboids is a bit different than for other polygons cuboids need exactly 2 points to be defined.
// Other polygons need at least 3 (one per vertex)
if (zoneShape.equalsIgnoreCase("Cuboid"))
{
if (coords.length == 2)
{
zoneForm = new ZoneCuboid(coords[0][0], coords[1][0], coords[0][1], coords[1][1], minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Missing cuboid vertex data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("NPoly"))
{
// nPoly needs to have at least 3 vertices
if (coords.length > 2)
{
final int[] aX = new int[coords.length];
final int[] aY = new int[coords.length];
for (int i = 0; i < coords.length; i++)
{
aX[i] = coords[i][0];
aY[i] = coords[i][1];
}
zoneForm = new ZoneNPoly(aX, aY, minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("Cylinder"))
{
// A Cylinder zone requires a center point at x,y and a radius
final int zoneRad = Integer.parseInt(attrs.getNamedItem("rad").getNodeValue());
if ((coords.length == 1) && (zoneRad > 0))
{
zoneForm = new ZoneCylinder(coords[0][0], coords[0][1], minZ, maxZ, zoneRad);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Unknown shape: \"" + zoneShape + "\" for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": SpawnTable: Failed to load banned_territory " + territoryName + " coordinates: " + e.getMessage(), e);
}
ZoneManager.getInstance().getSpawnTerritory(territoryName).setBannedTerritory(zoneForm);
}
// Check for NPC spawns // Check for NPC spawns
else if (npctag.getNodeName().equalsIgnoreCase("npc")) else if (npctag.getNodeName().equalsIgnoreCase("npc"))
{ {
@@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader
} }
spawnInfo.set("fileName", f.getPath()); spawnInfo.set("fileName", f.getPath());
_spanwCount += addSpawn(spawnInfo, map); _spawnCount += addSpawn(spawnInfo, map);
} }
} }
} }

View File

@@ -16,21 +16,18 @@
*/ */
package org.l2jmobius.gameserver.model.zone.type; package org.l2jmobius.gameserver.model.zone.type;
import java.util.List;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.zone.ZoneForm; import org.l2jmobius.gameserver.model.zone.ZoneForm;
/** /**
* Just dummy zone, needs only for geometry calculations * Just dummy zone, needs only for geometry calculations
* @author GKR * @author GKR, Mobius
*/ */
public class NpcSpawnTerritory public class NpcSpawnTerritory
{ {
private final String _name; private final String _name;
private final ZoneForm _territory; private final ZoneForm _territory;
@SuppressWarnings("unused") private ZoneForm _banned;
private List<ZoneForm> _bannedTerritories; // TODO: Implement it
public NpcSpawnTerritory(String name, ZoneForm territory) public NpcSpawnTerritory(String name, ZoneForm territory)
{ {
@@ -38,6 +35,11 @@ public class NpcSpawnTerritory
_territory = territory; _territory = territory;
} }
public void setBannedTerritory(ZoneForm banned)
{
_banned = banned;
}
public String getName() public String getName()
{ {
return _name; return _name;
@@ -45,6 +47,19 @@ public class NpcSpawnTerritory
public Location getRandomPoint() public Location getRandomPoint()
{ {
if (_banned != null)
{
int count = 0; // Prevent infinite loop from wrongly written data.
Location location;
while (count++ < 1000)
{
location = _territory.getRandomPoint();
if (!_banned.isInsideZone(location.getX(), location.getY(), location.getZ()))
{
return location;
}
}
}
return _territory.getRandomPoint(); return _territory.getRandomPoint();
} }

View File

@@ -38,6 +38,26 @@
<xs:attribute type="xs:int" name="rad" use="optional" /> <xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="banned_territory" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="node" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:int" name="x" use="required" />
<xs:attribute type="xs:int" name="y" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="optional" />
<xs:attribute type="xs:short" name="minZ" use="required" />
<xs:attribute type="xs:short" name="maxZ" use="required" />
<xs:attribute type="xs:int" name="rad" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="npc" minOccurs="1" maxOccurs="unbounded"> <xs:element name="npc" minOccurs="1" maxOccurs="unbounded">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>

View File

@@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader
private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final String OTHER_XML_FOLDER = "data/spawns/Others";
private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>(); private static final Map<Integer, Set<Spawn>> _spawnTable = new ConcurrentHashMap<>();
private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>(); private static final Map<Integer, String> _spawnTemplates = new ConcurrentHashMap<>();
private int _spanwCount = 0; private int _spawnCount = 0;
@Override @Override
public void load() public void load()
@@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader
{ {
LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); LOGGER.info(getClass().getSimpleName() + ": Initializing spawns...");
parseDatapackDirectory("data/spawns", true); parseDatapackDirectory("data/spawns", true);
LOGGER.info(getClass().getSimpleName() + ": " + _spanwCount + " spawns have been initialized!"); LOGGER.info(getClass().getSimpleName() + ": " + _spawnCount + " spawns have been initialized!");
} }
} }
@@ -273,6 +273,106 @@ public class SpawnTable implements IXmlReader
ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm)); ZoneManager.getInstance().addSpawnTerritory(territoryName, new NpcSpawnTerritory(territoryName, zoneForm));
} }
// Check for NPC banned spawn territories
else if (npctag.getNodeName().equalsIgnoreCase("banned_territory"))
{
if (!ZoneManager.getInstance().spawnTerritoryExists(territoryName))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: banned_territory " + territoryName + " must be set after normal territory.");
continue;
}
final int minZ = parseInteger(attrs, "minZ");
final int maxZ = parseInteger(attrs, "maxZ");
final String zoneShape = parseString(attrs, "shape", "NPoly");
final List<int[]> rs = new ArrayList<>();
int[][] coords;
ZoneForm zoneForm = null;
try
{
for (Node c = npctag.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("node".equalsIgnoreCase(c.getNodeName()))
{
attrs = c.getAttributes();
final int[] point = new int[2];
point[0] = parseInteger(attrs, "x");
point[1] = parseInteger(attrs, "y");
rs.add(point);
}
}
coords = rs.toArray(new int[rs.size()][2]);
rs.clear();
if ((coords == null) || (coords.length == 0))
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: missing data for spawn banned_territory: " + territoryName + " XML file: " + f.getName());
continue;
}
// Create this zone. Parsing for cuboids is a bit different than for other polygons cuboids need exactly 2 points to be defined.
// Other polygons need at least 3 (one per vertex)
if (zoneShape.equalsIgnoreCase("Cuboid"))
{
if (coords.length == 2)
{
zoneForm = new ZoneCuboid(coords[0][0], coords[1][0], coords[0][1], coords[1][1], minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Missing cuboid vertex data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("NPoly"))
{
// nPoly needs to have at least 3 vertices
if (coords.length > 2)
{
final int[] aX = new int[coords.length];
final int[] aY = new int[coords.length];
for (int i = 0; i < coords.length; i++)
{
aX[i] = coords[i][0];
aY[i] = coords[i][1];
}
zoneForm = new ZoneNPoly(aX, aY, minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("Cylinder"))
{
// A Cylinder zone requires a center point at x,y and a radius
final int zoneRad = Integer.parseInt(attrs.getNamedItem("rad").getNodeValue());
if ((coords.length == 1) && (zoneRad > 0))
{
zoneForm = new ZoneCylinder(coords[0][0], coords[0][1], minZ, maxZ, zoneRad);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Bad data for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": SpawnTable: Unknown shape: \"" + zoneShape + "\" for banned_territory: " + territoryName + " in file: " + f.getName());
continue;
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": SpawnTable: Failed to load banned_territory " + territoryName + " coordinates: " + e.getMessage(), e);
}
ZoneManager.getInstance().getSpawnTerritory(territoryName).setBannedTerritory(zoneForm);
}
// Check for NPC spawns // Check for NPC spawns
else if (npctag.getNodeName().equalsIgnoreCase("npc")) else if (npctag.getNodeName().equalsIgnoreCase("npc"))
{ {
@@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader
} }
spawnInfo.set("fileName", f.getPath()); spawnInfo.set("fileName", f.getPath());
_spanwCount += addSpawn(spawnInfo, map); _spawnCount += addSpawn(spawnInfo, map);
} }
} }
} }

View File

@@ -16,21 +16,18 @@
*/ */
package org.l2jmobius.gameserver.model.zone.type; package org.l2jmobius.gameserver.model.zone.type;
import java.util.List;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.zone.ZoneForm; import org.l2jmobius.gameserver.model.zone.ZoneForm;
/** /**
* Just dummy zone, needs only for geometry calculations * Just dummy zone, needs only for geometry calculations
* @author GKR * @author GKR, Mobius
*/ */
public class NpcSpawnTerritory public class NpcSpawnTerritory
{ {
private final String _name; private final String _name;
private final ZoneForm _territory; private final ZoneForm _territory;
@SuppressWarnings("unused") private ZoneForm _banned;
private List<ZoneForm> _bannedTerritories; // TODO: Implement it
public NpcSpawnTerritory(String name, ZoneForm territory) public NpcSpawnTerritory(String name, ZoneForm territory)
{ {
@@ -38,6 +35,11 @@ public class NpcSpawnTerritory
_territory = territory; _territory = territory;
} }
public void setBannedTerritory(ZoneForm banned)
{
_banned = banned;
}
public String getName() public String getName()
{ {
return _name; return _name;
@@ -45,6 +47,19 @@ public class NpcSpawnTerritory
public Location getRandomPoint() public Location getRandomPoint()
{ {
if (_banned != null)
{
int count = 0; // Prevent infinite loop from wrongly written data.
Location location;
while (count++ < 1000)
{
location = _territory.getRandomPoint();
if (!_banned.isInsideZone(location.getX(), location.getY(), location.getZ()))
{
return location;
}
}
}
return _territory.getRandomPoint(); return _territory.getRandomPoint();
} }