From 0d34380d18ff0e89f9dfc4f8106506a9bee8f73f Mon Sep 17 00:00:00 2001 From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com> Date: Tue, 30 Aug 2022 21:31:12 +0000 Subject: [PATCH] Support for spawn banned territories. --- .../dist/game/data/xsd/spawns.xsd | 20 ++++ .../l2jmobius/gameserver/data/SpawnTable.java | 106 +++++++++++++++++- .../model/zone/type/NpcSpawnTerritory.java | 25 ++++- .../dist/game/data/xsd/spawns.xsd | 20 ++++ .../l2jmobius/gameserver/data/SpawnTable.java | 106 +++++++++++++++++- .../model/zone/type/NpcSpawnTerritory.java | 25 ++++- .../dist/game/data/xsd/spawns.xsd | 20 ++++ .../l2jmobius/gameserver/data/SpawnTable.java | 106 +++++++++++++++++- .../model/zone/type/NpcSpawnTerritory.java | 25 ++++- 9 files changed, 429 insertions(+), 24 deletions(-) diff --git a/L2J_Mobius_CT_0_Interlude/dist/game/data/xsd/spawns.xsd b/L2J_Mobius_CT_0_Interlude/dist/game/data/xsd/spawns.xsd index bfe4e88cf3..090ad395e9 100644 --- a/L2J_Mobius_CT_0_Interlude/dist/game/data/xsd/spawns.xsd +++ b/L2J_Mobius_CT_0_Interlude/dist/game/data/xsd/spawns.xsd @@ -38,6 +38,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/data/SpawnTable.java b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/data/SpawnTable.java index 3549709790..6111f40695 100644 --- a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/data/SpawnTable.java +++ b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/data/SpawnTable.java @@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final Map> _spawnTable = new ConcurrentHashMap<>(); private static final Map _spawnTemplates = new ConcurrentHashMap<>(); - private int _spanwCount = 0; + private int _spawnCount = 0; @Override public void load() @@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader { LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); 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)); } + // 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 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 else if (npctag.getNodeName().equalsIgnoreCase("npc")) { @@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader } spawnInfo.set("fileName", f.getPath()); - _spanwCount += addSpawn(spawnInfo, map); + _spawnCount += addSpawn(spawnInfo, map); } } } diff --git a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java index 42df5cadd2..2daf57a9ed 100644 --- a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java +++ b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java @@ -16,21 +16,18 @@ */ package org.l2jmobius.gameserver.model.zone.type; -import java.util.List; - import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.zone.ZoneForm; /** * Just dummy zone, needs only for geometry calculations - * @author GKR + * @author GKR, Mobius */ public class NpcSpawnTerritory { private final String _name; private final ZoneForm _territory; - @SuppressWarnings("unused") - private List _bannedTerritories; // TODO: Implement it + private ZoneForm _banned; public NpcSpawnTerritory(String name, ZoneForm territory) { @@ -38,6 +35,11 @@ public class NpcSpawnTerritory _territory = territory; } + public void setBannedTerritory(ZoneForm banned) + { + _banned = banned; + } + public String getName() { return _name; @@ -45,6 +47,19 @@ public class NpcSpawnTerritory 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(); } diff --git a/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/xsd/spawns.xsd b/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/xsd/spawns.xsd index bfe4e88cf3..090ad395e9 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/xsd/spawns.xsd +++ b/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/xsd/spawns.xsd @@ -38,6 +38,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/data/SpawnTable.java b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/data/SpawnTable.java index 3549709790..6111f40695 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/data/SpawnTable.java +++ b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/data/SpawnTable.java @@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final Map> _spawnTable = new ConcurrentHashMap<>(); private static final Map _spawnTemplates = new ConcurrentHashMap<>(); - private int _spanwCount = 0; + private int _spawnCount = 0; @Override public void load() @@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader { LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); 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)); } + // 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 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 else if (npctag.getNodeName().equalsIgnoreCase("npc")) { @@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader } spawnInfo.set("fileName", f.getPath()); - _spanwCount += addSpawn(spawnInfo, map); + _spawnCount += addSpawn(spawnInfo, map); } } } diff --git a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java index 42df5cadd2..2daf57a9ed 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java +++ b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java @@ -16,21 +16,18 @@ */ package org.l2jmobius.gameserver.model.zone.type; -import java.util.List; - import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.zone.ZoneForm; /** * Just dummy zone, needs only for geometry calculations - * @author GKR + * @author GKR, Mobius */ public class NpcSpawnTerritory { private final String _name; private final ZoneForm _territory; - @SuppressWarnings("unused") - private List _bannedTerritories; // TODO: Implement it + private ZoneForm _banned; public NpcSpawnTerritory(String name, ZoneForm territory) { @@ -38,6 +35,11 @@ public class NpcSpawnTerritory _territory = territory; } + public void setBannedTerritory(ZoneForm banned) + { + _banned = banned; + } + public String getName() { return _name; @@ -45,6 +47,19 @@ public class NpcSpawnTerritory 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(); } diff --git a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/xsd/spawns.xsd b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/xsd/spawns.xsd index bfe4e88cf3..090ad395e9 100644 --- a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/xsd/spawns.xsd +++ b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/xsd/spawns.xsd @@ -38,6 +38,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/data/SpawnTable.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/data/SpawnTable.java index 3549709790..6111f40695 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/data/SpawnTable.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/data/SpawnTable.java @@ -63,7 +63,7 @@ public class SpawnTable implements IXmlReader private static final String OTHER_XML_FOLDER = "data/spawns/Others"; private static final Map> _spawnTable = new ConcurrentHashMap<>(); private static final Map _spawnTemplates = new ConcurrentHashMap<>(); - private int _spanwCount = 0; + private int _spawnCount = 0; @Override public void load() @@ -73,7 +73,7 @@ public class SpawnTable implements IXmlReader { LOGGER.info(getClass().getSimpleName() + ": Initializing spawns..."); 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)); } + // 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 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 else if (npctag.getNodeName().equalsIgnoreCase("npc")) { @@ -351,7 +451,7 @@ public class SpawnTable implements IXmlReader } spawnInfo.set("fileName", f.getPath()); - _spanwCount += addSpawn(spawnInfo, map); + _spawnCount += addSpawn(spawnInfo, map); } } } diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java index 42df5cadd2..2daf57a9ed 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/zone/type/NpcSpawnTerritory.java @@ -16,21 +16,18 @@ */ package org.l2jmobius.gameserver.model.zone.type; -import java.util.List; - import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.zone.ZoneForm; /** * Just dummy zone, needs only for geometry calculations - * @author GKR + * @author GKR, Mobius */ public class NpcSpawnTerritory { private final String _name; private final ZoneForm _territory; - @SuppressWarnings("unused") - private List _bannedTerritories; // TODO: Implement it + private ZoneForm _banned; public NpcSpawnTerritory(String name, ZoneForm territory) { @@ -38,6 +35,11 @@ public class NpcSpawnTerritory _territory = territory; } + public void setBannedTerritory(ZoneForm banned) + { + _banned = banned; + } + public String getName() { return _name; @@ -45,6 +47,19 @@ public class NpcSpawnTerritory 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(); }