diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 36a706c1..b35b9d0c 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -685,7 +685,7 @@ making it preferred for scoping ungenerated terrain, but it takes some compute r Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent the actual structure from forming. -If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or +If structure is specified, it will return `null` if a chunk is not eligible or invalid, `true` if the structure should appear, or a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece. @@ -702,7 +702,7 @@ the first case it returns a map of structures at a given position, keyed by stru the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure name, returns a map with two values, `'box'` for bounding box of the structure, and `'pieces'` for a list of components for that structure, with their name, direction and two sets of coordinates -indicating the bounding box of the structure piece. +indicating the bounding box of the structure piece. If structure is invalid, its data will be `null`. Requires a `Standard Structure` name (see above). diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index ee1ac0b5..c534b7b9 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -1128,7 +1128,17 @@ public class WorldAccess { Map ret = new HashMap<>(); for(StructureFeature str : StructureFeature.STRUCTURES.values()) { - StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize); + StructureStart start; + try + { + start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize); + } + catch (NullPointerException npe) + { + CarpetSettings.LOG.error("Failed to detect structure: "+str.getName()); + start = null; + } + if (start == null) continue; Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(str))); diff --git a/src/main/java/carpet/script/value/ValueConversions.java b/src/main/java/carpet/script/value/ValueConversions.java index 8ffd3c02..1108b1e2 100644 --- a/src/main/java/carpet/script/value/ValueConversions.java +++ b/src/main/java/carpet/script/value/ValueConversions.java @@ -299,23 +299,27 @@ public class ValueConversions public static Value of(StructureStart structure) { if (structure == null || structure == StructureStart.DEFAULT) return Value.NULL; - List pieces = new ArrayList<>(); - for (StructurePiece piece : structure.getChildren()) - { - BlockBox box = piece.getBoundingBox(); - pieces.add(ListValue.of( - new StringValue( NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))), - (piece.getFacing()== null)?Value.NULL: new StringValue(piece.getFacing().getName()), - ListValue.fromTriple(box.minX, box.minY, box.minZ), - ListValue.fromTriple(box.maxX, box.maxY, box.maxZ) - )); - } BlockBox boundingBox = structure.getBoundingBox(); + if (boundingBox.maxX < boundingBox.minX || boundingBox.maxY < boundingBox.minY || boundingBox.maxZ < boundingBox.minZ) return Value.NULL; Map ret = new HashMap<>(); ret.put(new StringValue("box"), ListValue.of( ListValue.fromTriple(boundingBox.minX, boundingBox.minY, boundingBox.minZ), ListValue.fromTriple(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ) )); + List pieces = new ArrayList<>(); + for (StructurePiece piece : structure.getChildren()) + { + BlockBox box = piece.getBoundingBox(); + if (box.maxX >= box.minX && box.maxY >= box.minY && box.maxZ >= box.minZ) + { + pieces.add(ListValue.of( + new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))), + (piece.getFacing() == null) ? Value.NULL : new StringValue(piece.getFacing().getName()), + ListValue.fromTriple(box.minX, box.minY, box.minZ), + ListValue.fromTriple(box.maxX, box.maxY, box.maxZ) + )); + } + } ret.put(new StringValue("pieces"), ListValue.wrap(pieces)); return MapValue.wrap(ret); }