Support for spawn banned territories.
This commit is contained in:
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user