diff --git a/docs/scarpet/api/BlockIterations.md b/docs/scarpet/api/BlockIterations.md index 4f2085ff..6aebfbc8 100644 --- a/docs/scarpet/api/BlockIterations.md +++ b/docs/scarpet/api/BlockIterations.md @@ -2,11 +2,15 @@ These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. -### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)` +### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)`, `scan(center, range, lower_range?, expr)` -Evaluates expression over area of blocks defined by its center (`cx, cy, cz`), expanded in all directions -by `dx, dy, dz` blocks, or optionally in negative with `d` coords, and `p` coords in positive values. `expr` -receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. +Evaluates expression over area of blocks defined by its center `center = (cx, cy, cz)`, expanded in all directions +by `range = (dx, dy, dz)` blocks, or optionally in negative with `range` coords, and `upper_range` coords in +positive values. +`center` can be defined either as a three coordinates, list of three coords, or block value. +`range` and `lower_range` can have the same representations, just if its a block, it computes the distance to the center +as range instead of taking the values as is. +`expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. Returns number of successful evaluations of `expr` (with `true` boolean result) unless called in void context, which would cause the expression not be evaluated for their boolean value. diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 3169d1b3..624c8c98 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -21,7 +21,6 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; -import carpet.script.utils.CarpetArgParser; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.FunctionValue; @@ -108,6 +107,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.EulerAngle; import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; import net.minecraft.util.registry.Registry; import net.minecraft.world.poi.PointOfInterest; import net.minecraft.world.poi.PointOfInterestStorage; @@ -1946,30 +1946,58 @@ public class CarpetExpression { this.expr.addLazyFunction("scan", -1, (c, t, lv) -> { - int lvsise = lv.size(); - if (lvsise != 7 && lvsise != 10) - throw new InternalExpressionException("'scan' takes 2, or 3 triples of coords, and the expression"); - int cx = (int) NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - int cy = (int) NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); - int cz = (int) NumericValue.asNumber(lv.get(2).evalValue(c)).getLong(); - int xrange = (int) NumericValue.asNumber(lv.get(3).evalValue(c)).getLong(); - int yrange = (int) NumericValue.asNumber(lv.get(4).evalValue(c)).getLong(); - int zrange = (int) NumericValue.asNumber(lv.get(5).evalValue(c)).getLong(); - int xprange = xrange; - int yprange = yrange; - int zprange = zrange; - LazyValue expr; - if (lvsise == 7) + CarpetContext cc = (CarpetContext)c; + BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); + Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + BlockPos center = centerLocator.block.getPos(); + Vec3i range; + + if (rangeLocator.fromBlock) { - expr = lv.get(6); + range = new Vec3i( + abs(rangeLocator.vec.x - center.getX()), + abs(rangeLocator.vec.y - center.getY()), + abs(rangeLocator.vec.z - center.getZ()) + ); + //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") } else { - xprange = (int) NumericValue.asNumber(lv.get(6).evalValue(c)).getLong(); - yprange = (int) NumericValue.asNumber(lv.get(7).evalValue(c)).getLong(); - zprange = (int) NumericValue.asNumber(lv.get(8).evalValue(c)).getLong(); - expr = lv.get(9); + range = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } + Vec3i upperRange = range; + if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression + { + rangeLocator = Vector3Argument.findIn(cc, lv, rangeLocator.offset); + if (rangeLocator.fromBlock) + { + upperRange = new Vec3i( + abs(rangeLocator.vec.x - center.getX()), + abs(rangeLocator.vec.y - center.getY()), + abs(rangeLocator.vec.z - center.getZ()) + ); + //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") + } + else + { + upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); + } + } + if (lv.size() != rangeLocator.offset+1) + { + throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset); + } + LazyValue expr = lv.get(rangeLocator.offset); + + int cx = center.getX(); + int cy = center.getY(); + int cz = center.getZ(); + int xrange = range.getX(); + int yrange = range.getY(); + int zrange = range.getZ(); + int xprange = upperRange.getX(); + int yprange = upperRange.getY(); + int zprange = upperRange.getZ(); //saving outer scope LazyValue _x = c.getVariable("_x"); diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java index 0e492f64..59c0d96c 100644 --- a/src/main/java/carpet/script/argument/BlockArgument.java +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -77,7 +77,7 @@ public class BlockArgument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + throw handleError(optional, acceptString); } } @@ -127,7 +127,18 @@ public class BlockArgument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + throw handleError(optional, acceptString); } } + + private static InternalExpressionException handleError(boolean optional, boolean acceptString) + { + String message = "Block-type argument should be defined either by three coordinates (a triple or by three arguments), or a block value"; + if (acceptString) + message+=", or a string with block description"; + if (optional) + message+=", or null"; + return new InternalExpressionException(message); + } + } diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index b39b56bf..e581b6d3 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -88,7 +88,7 @@ public class Vector3Argument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); + throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); } } } diff --git a/src/main/java/carpet/script/utils/CarpetArgParser.java b/src/main/java/carpet/script/utils/CarpetArgParser.java deleted file mode 100644 index 7fff1c5b..00000000 --- a/src/main/java/carpet/script/utils/CarpetArgParser.java +++ /dev/null @@ -1,6 +0,0 @@ -package carpet.script.utils; - - -public class CarpetArgParser -{ -}