From 6fc9735da93d7a35a4abead99f48d9fc605ccb04 Mon Sep 17 00:00:00 2001 From: LemADEC Date: Mon, 26 Jun 2017 00:37:45 +0200 Subject: [PATCH] Improved XML validation - XML schema has a proper namespace now - line number in parsing error messages - celestial object borders are validated too - celestial object validation only crash after reporting all issues --- .../config/CelestialObjectManager.java | 89 +++++++++-- .../warpdrive/config/WarpDriveConfig.java | 13 +- src/main/resources/config/WarpDrive.xsd | 144 +++++++++--------- .../config/celestialObjects-default.xml | 10 +- .../resources/config/dimensions-default.xml | 4 +- src/main/resources/config/filler-default.xml | 4 +- .../resources/config/filler-netherores.xml | 4 +- .../config/filler-undergroundbiomes.xml | 4 +- src/main/resources/config/loot-default.xml | 4 +- .../resources/config/structures-default.xml | 6 +- .../config/structures-netherores.xml | 4 +- src/main/resources/config/structures-ship.xml | 4 +- 12 files changed, 179 insertions(+), 111 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/config/CelestialObjectManager.java b/src/main/java/cr0s/warpdrive/config/CelestialObjectManager.java index f2913268..ceb4d016 100644 --- a/src/main/java/cr0s/warpdrive/config/CelestialObjectManager.java +++ b/src/main/java/cr0s/warpdrive/config/CelestialObjectManager.java @@ -61,8 +61,51 @@ public class CelestialObjectManager extends XmlFileManager { } // check overlapping regions + int countErrors = 0; for (CelestialObject celestialObject1 : celestialObjects) { celestialObject1.lateUpdate(); + + // validate coordinates + if (!celestialObject1.isVirtual) { + if (celestialObject1.parentDimensionId != celestialObject1.dimensionId) {// not hyperspace + final CelestialObject celestialObjectParent = get(celestialObject1.parentGroup, celestialObject1.parentName); + if (celestialObjectParent == null) { + countErrors++; + WarpDrive.logger.error(String.format("Validation error #%d\nCelestial object %s refers to unknown parent %s:%s", + countErrors, + celestialObject1.getFullName(), + celestialObject1.parentGroup, celestialObject1.parentName )); + } else if ( celestialObject1.parentCenterX - celestialObject1.borderRadiusX < celestialObjectParent.dimensionCenterX - celestialObjectParent.borderRadiusX + || celestialObject1.parentCenterZ - celestialObject1.borderRadiusZ < celestialObjectParent.dimensionCenterZ - celestialObjectParent.borderRadiusZ + || celestialObject1.parentCenterX + celestialObject1.borderRadiusX > celestialObjectParent.dimensionCenterX + celestialObjectParent.borderRadiusX + || celestialObject1.parentCenterZ + celestialObject1.borderRadiusZ > celestialObjectParent.dimensionCenterZ + celestialObjectParent.borderRadiusZ) { + countErrors++; + WarpDrive.logger.error(String.format("Validation error #%d\nCelestial object %s is outside its parent border.\n%s\n%s\n%s's area in parent %s is outside %s's border %s", + countErrors, + celestialObject1.getFullName(), + celestialObject1, + celestialObjectParent, + celestialObject1.getFullName(), + celestialObject1.getAreaInParent(), + celestialObjectParent.getFullName(), + celestialObjectParent.getWorldBorderArea() )); + } + } + if ( celestialObject1.dimensionCenterX - celestialObject1.borderRadiusX < -30000000 + || celestialObject1.dimensionCenterZ - celestialObject1.borderRadiusZ < -30000000 + || celestialObject1.dimensionCenterX + celestialObject1.borderRadiusX >= 30000000 + || celestialObject1.dimensionCenterZ + celestialObject1.borderRadiusZ >= 30000000 ) { + countErrors++; + WarpDrive.logger.error(String.format("Validation error #%d\nCelestial object %s is outside the game border +/-30000000.\n%s\n%s border is %s", + countErrors, + celestialObject1.getFullName(), + celestialObject1, + celestialObject1.getFullName(), + celestialObject1.getWorldBorderArea() )); + } + } + + // validate against other celestial objects for (CelestialObject celestialObject2 : celestialObjects) { if (celestialObject1 == celestialObject2) { continue; @@ -72,29 +115,45 @@ public class CelestialObjectManager extends XmlFileManager { final AxisAlignedBB areaInParent1 = celestialObject1.getAreaInParent(); final AxisAlignedBB areaInParent2 = celestialObject2.getAreaInParent(); if (areaInParent1.intersectsWith(areaInParent2)) { - WarpDrive.logger.error("Overlapping parent areas detected " + celestialObject1.parentDimensionId); - WarpDrive.logger.error("Celestial object 1 is " + celestialObject1 + " with area " + areaInParent1); - WarpDrive.logger.error("Celestial object 2 is " + celestialObject2 + " with area " + areaInParent2); - throw new RuntimeException(String.format( - "Invalid celestial objects definition:\n %s\nand\n %s\nare overlapping each others. Update your configuration to fix it.", - celestialObject1.toString(), celestialObject2.toString())); + countErrors++; + WarpDrive.logger.error(String.format("Validation error #%d\nOverlapping parent areas detected in dimension %d between %s and %s\nArea1 %s from %s\nArea2 %s from %s", + countErrors, + celestialObject1.parentDimensionId, + celestialObject1.getFullName(), + celestialObject2.getFullName(), + areaInParent1, + celestialObject1, + areaInParent2, + celestialObject2 )); } } // are they in the same dimension? if (!celestialObject1.isVirtual && !celestialObject2.isVirtual && celestialObject1.dimensionId == celestialObject2.dimensionId) { - final AxisAlignedBB areaToReachParent1 = celestialObject1.getAreaToReachParent(); - final AxisAlignedBB areaToReachParent2 = celestialObject2.getAreaToReachParent(); - if (areaToReachParent1.intersectsWith(areaToReachParent2)) { - WarpDrive.logger.error("Overlapping areas detected in dimension " + celestialObject1.dimensionId); - WarpDrive.logger.error("Celestial object 1 is " + celestialObject1 + " with area " + areaToReachParent1); - WarpDrive.logger.error("Celestial object 2 is " + celestialObject2 + " with area " + areaToReachParent2); - throw new RuntimeException(String.format( - "Invalid celestial objects definition:\n %s\nand\n %s\nare overlapping each others. Update your configuration to fix it.", - celestialObject1.toString(), celestialObject2.toString())); + final AxisAlignedBB worldBorderArea1 = celestialObject1.getWorldBorderArea(); + final AxisAlignedBB worldBorderArea2 = celestialObject2.getWorldBorderArea(); + if (worldBorderArea1.intersectsWith(worldBorderArea2)) { + countErrors++; + WarpDrive.logger.error(String.format("Validation error #%d\nOverlapping areas detected in dimension %d between %s and %s\nArea1 %s from %s\nArea2 %s from %s", + countErrors, + celestialObject1.dimensionId, + celestialObject1.getFullName(), + celestialObject2.getFullName(), + worldBorderArea1, + celestialObject1, + worldBorderArea2, + celestialObject2 )); } } } } + if (countErrors == 1) { + throw new RuntimeException("Invalid celestial objects definition: update your configuration to fix this validation error, see logs for details."); + } else if (countErrors > 0) { + throw new RuntimeException(String.format( + "Invalid celestial objects definition: update your configuration to fix those %d validation errors, see logs for details.", + countErrors)); + } + // We're not checking invalid dimension id, so they can be pre-allocated (see MystCraft) } diff --git a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java index 9b6d9228..35f0b93b 100644 --- a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java +++ b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java @@ -1012,19 +1012,26 @@ public class WarpDriveConfig { ErrorHandler xmlErrorHandler = new ErrorHandler() { @Override public void warning(SAXParseException exception) throws SAXException { - WarpDrive.logger.warn("XML warning: " + exception.getLocalizedMessage()); + WarpDrive.logger.warn(String.format("XML warning at line %d: %s", + exception.getLineNumber(), + exception.getLocalizedMessage() )); // exception.printStackTrace(); } @Override public void fatalError(SAXParseException exception) throws SAXException { - WarpDrive.logger.warn("XML fatal error: " + exception.getLocalizedMessage()); + WarpDrive.logger.warn(String.format("XML fatal error at line %d: %s", + exception.getLineNumber(), + exception.getLocalizedMessage() )); // exception.printStackTrace(); } @Override public void error(SAXParseException exception) throws SAXException { - WarpDrive.logger.warn("XML error: " + exception.getLocalizedMessage()); + WarpDrive.logger.warn(String.format("XML error at line %d: %s", + exception.getLineNumber(), + exception.getLocalizedMessage() )); + // exception.printStackTrace(); } }; diff --git a/src/main/resources/config/WarpDrive.xsd b/src/main/resources/config/WarpDrive.xsd index 1cf7b10e..1108357c 100644 --- a/src/main/resources/config/WarpDrive.xsd +++ b/src/main/resources/config/WarpDrive.xsd @@ -2,17 +2,18 @@ - + - - - - - - + + + + + + @@ -21,11 +22,11 @@ - + - - - + + + @@ -34,13 +35,13 @@ - + - + @@ -49,12 +50,13 @@ - + - - - - + + + + + @@ -63,10 +65,10 @@ - + - - + + @@ -76,21 +78,21 @@ - + - - - + + + - + - - + + @@ -99,7 +101,7 @@ - + @@ -110,7 +112,7 @@ - + @@ -120,11 +122,11 @@ - + - - - + + + @@ -133,7 +135,7 @@ - + @@ -144,7 +146,7 @@ - + @@ -152,12 +154,12 @@ - - + + - + @@ -167,21 +169,21 @@ - + - - + + - + - - + + @@ -190,16 +192,16 @@ - + Defines the actual game world characteristics. - - - + + + @@ -222,18 +224,18 @@ - - - + + + - + - + @@ -244,19 +246,19 @@ - + - + - + Vanilla block positions is limited to +/- 30000 km. @@ -269,14 +271,14 @@ - + - - - - - - + + + + + + @@ -288,12 +290,12 @@ - - - - - - + + + + + + diff --git a/src/main/resources/config/celestialObjects-default.xml b/src/main/resources/config/celestialObjects-default.xml index 2bf535d5..119d4198 100644 --- a/src/main/resources/config/celestialObjects-default.xml +++ b/src/main/resources/config/celestialObjects-default.xml @@ -1,8 +1,8 @@  + xsi:schemaLocation="http://warpdrive.lemadec.org WarpDrive.xsd"> - + -
+
diff --git a/src/main/resources/config/dimensions-default.xml b/src/main/resources/config/dimensions-default.xml index 371b1f5c..7ed27888 100644 --- a/src/main/resources/config/dimensions-default.xml +++ b/src/main/resources/config/dimensions-default.xml @@ -1,8 +1,8 @@  + xsi:schemaLocation="http://warpdrive.lemadec.org WarpDrive.xsd"> diff --git a/src/main/resources/config/filler-default.xml b/src/main/resources/config/filler-default.xml index c9b892af..1733d579 100644 --- a/src/main/resources/config/filler-default.xml +++ b/src/main/resources/config/filler-default.xml @@ -1,8 +1,8 @@  + xsi:schemaLocation="http://warpdrive.lemadec.org WarpDrive.xsd"> diff --git a/src/main/resources/config/filler-netherores.xml b/src/main/resources/config/filler-netherores.xml index 56edc4f8..d3727200 100644 --- a/src/main/resources/config/filler-netherores.xml +++ b/src/main/resources/config/filler-netherores.xml @@ -1,8 +1,8 @@  @@ -169,7 +169,7 @@ - + diff --git a/src/main/resources/config/structures-netherores.xml b/src/main/resources/config/structures-netherores.xml index aa59d4ed..1fb1aee8 100644 --- a/src/main/resources/config/structures-netherores.xml +++ b/src/main/resources/config/structures-netherores.xml @@ -1,9 +1,9 @@