From 7bceafe55810181dfc86c1fa9ab19f81594f807a Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Wed, 8 Mar 2023 01:03:43 +0100
Subject: [PATCH 1/8] Rename offset arguments on //deform, //generate and
//generatebiome to offsetPlacement
---
.../com/sk89q/worldedit/command/GenerationCommands.java | 8 ++++----
.../java/com/sk89q/worldedit/command/RegionCommands.java | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
index 1c7bb86655..bf5076848c 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
@@ -370,7 +370,7 @@ public int generate(Actor actor, LocalSession session, EditSession editSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
- boolean offset,
+ boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
@@ -380,7 +380,7 @@ public int generate(Actor actor, LocalSession session, EditSession editSession,
if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
- } else if (offset) {
+ } else if (offsetPlacement) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
@@ -439,7 +439,7 @@ public int generateBiome(Actor actor, LocalSession session, EditSession editSess
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
- boolean offset,
+ boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
final Vector3 zero;
@@ -448,7 +448,7 @@ public int generateBiome(Actor actor, LocalSession session, EditSession editSess
if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
- } else if (offset) {
+ } else if (offsetPlacement) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 8fefaab6a6..62207daa16 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -498,7 +498,7 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
- boolean offset,
+ boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
final Vector3 zero;
@@ -507,7 +507,7 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
- } else if (offset) {
+ } else if (offsetPlacement) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
From 35eae8b438c757742dccd084060e5b197f52454e Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Wed, 8 Mar 2023 04:59:45 +0100
Subject: [PATCH 2/8] More accurate comments
---
.../src/main/java/com/sk89q/worldedit/EditSession.java | 5 +++--
.../regions/shape/WorldEditExpressionEnvironment.java | 1 -
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
index b442163190..631c0ddb49 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -2437,12 +2437,13 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
final Vector3 targetPosition = targetBlockPosition.toVector3();
environment.setCurrentBlock(targetPosition);
- // offset, scale
+ // transform from target coordinates
final Vector3 scaled = targetPosition.subtract(zero).divide(unit);
- // transform
+ // deform
expression.evaluate(new double[]{ scaled.x(), scaled.y(), scaled.z() }, timeout);
+ // transform to source coordinates, round-nearest
final BlockVector3 sourcePosition = environment.toWorld(x.value(), y.value(), z.value());
// read block from world
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
index 56763d3bc2..da1825259d 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
@@ -39,7 +39,6 @@ public WorldEditExpressionEnvironment(Extent extent, Vector3 unit, Vector3 zero)
}
public BlockVector3 toWorld(double x, double y, double z) {
- // unscale, unoffset, round-nearest
return Vector3.at(x, y, z).multiply(unit).add(zero2).toBlockPoint();
}
From 87f43fef6e68c8400e417a7dd586bce8d6e7443c Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Thu, 18 Jul 2024 08:04:08 +0200
Subject: [PATCH 3/8] Give some variables more appropriate names
---
.../java/com/sk89q/worldedit/EditSession.java | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
index 631c0ddb49..9e418ffb47 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -2327,7 +2327,7 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
final Vector3 current = Vector3.at(x, y, z);
environment.setCurrentBlock(current);
- final Vector3 scaled = current.subtract(zero).divide(unit);
+ final Vector3 inputPosition = current.subtract(zero).divide(unit);
try {
int[] legacy = LegacyMapper.getInstance().getLegacyFromBlock(defaultMaterial.toImmutableState());
@@ -2339,7 +2339,7 @@ protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial)
dataVar = legacy[1];
}
}
- if (expression.evaluate(new double[]{ scaled.x(), scaled.y(), scaled.z(), typeVar, dataVar}, timeout) <= 0) {
+ if (expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z(), typeVar, dataVar}, timeout) <= 0) {
return null;
}
int newType = (int) typeVariable.value();
@@ -2438,10 +2438,10 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
environment.setCurrentBlock(targetPosition);
// transform from target coordinates
- final Vector3 scaled = targetPosition.subtract(zero).divide(unit);
+ final Vector3 inputPosition = targetPosition.subtract(zero).divide(unit);
// deform
- expression.evaluate(new double[]{ scaled.x(), scaled.y(), scaled.z() }, timeout);
+ expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout);
// transform to source coordinates, round-nearest
final BlockVector3 sourcePosition = environment.toWorld(x.value(), y.value(), z.value());
@@ -2455,11 +2455,11 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
int affected = 0;
for (Map.Entry entry : queue) {
- BlockVector3 position = entry.getKey();
+ BlockVector3 targetPosition = entry.getKey();
BaseBlock material = entry.getValue();
- // set at new position
- if (setBlock(position, material)) {
+ // set at new targetPosition
+ if (setBlock(targetPosition, material)) {
++affected;
}
}
@@ -2773,10 +2773,10 @@ public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) {
final Vector3 current = Vector3.at(x, y, z);
environment.setCurrentBlock(current);
- final Vector3 scaled = current.subtract(zero).divide(unit);
+ final Vector3 inputPosition = current.subtract(zero).divide(unit);
try {
- if (expression.evaluate(new double[]{ scaled.x(), scaled.y(), scaled.z() }, timeout) <= 0) {
+ if (expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout) <= 0) {
return null;
}
From 5caeb4c775388f8ab5ce2201a0a9490833bb1343 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 14:35:16 +0200
Subject: [PATCH 4/8] Add ScaleAndTranslateTransform class
---
.../transform/ScaleAndTranslateTransform.java | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/ScaleAndTranslateTransform.java
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/ScaleAndTranslateTransform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/ScaleAndTranslateTransform.java
new file mode 100644
index 0000000000..93630a8688
--- /dev/null
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/transform/ScaleAndTranslateTransform.java
@@ -0,0 +1,68 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.math.transform;
+
+import com.sk89q.worldedit.math.Vector3;
+
+/**
+ * A more light-weight {@link Transform} than {@link AffineTransform}, supporting only translation and scaling.
+ */
+public record ScaleAndTranslateTransform(Vector3 offset, Vector3 scale) implements Transform {
+
+ @Override
+ public boolean isIdentity() {
+ return offset.equals(Vector3.ZERO) && scale.equals(Vector3.ONE);
+ }
+
+ @Override
+ public Vector3 apply(Vector3 input) {
+ return input.multiply(scale).add(offset);
+ }
+
+ @Override
+ public Transform inverse() {
+ return new Transform() {
+ @Override
+ public boolean isIdentity() {
+ return ScaleAndTranslateTransform.this.isIdentity();
+ }
+
+ @Override
+ public Vector3 apply(Vector3 input) {
+ return input.subtract(offset).divide(scale);
+ }
+
+ @Override
+ public Transform inverse() {
+ return ScaleAndTranslateTransform.this;
+ }
+
+ @Override
+ public Transform combine(Transform other) {
+ return new CombinedTransform(this, other);
+ }
+ };
+ }
+
+ @Override
+ public Transform combine(Transform other) {
+ return new CombinedTransform(this, other);
+ }
+}
From ab4399fbc6e3a8b83a41b6cf04fa12b8843330c6 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 14:41:53 +0200
Subject: [PATCH 5/8] Use ScaleAndTranslateTransform in
WorldEditExpressionEnvironment
---
.../shape/WorldEditExpressionEnvironment.java | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
index da1825259d..a27dd863a5 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
@@ -23,23 +23,28 @@
import com.sk89q.worldedit.internal.expression.ExpressionEnvironment;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
+import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
+import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.registry.LegacyMapper;
public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
- private final Vector3 unit;
- private final Vector3 zero2;
+ private final Transform transform;
private Vector3 current = Vector3.ZERO;
private final Extent extent;
+ @Deprecated
public WorldEditExpressionEnvironment(Extent extent, Vector3 unit, Vector3 zero) {
+ this(extent, new ScaleAndTranslateTransform(zero, unit));
+ }
+
+ public WorldEditExpressionEnvironment(Extent extent, Transform transform) {
this.extent = extent;
- this.unit = unit;
- this.zero2 = zero.add(0.5, 0.5, 0.5);
+ this.transform = transform;
}
public BlockVector3 toWorld(double x, double y, double z) {
- return Vector3.at(x, y, z).multiply(unit).add(zero2).toBlockPoint();
+ return transform.apply(Vector3.at(x, y, z)).add(0.5, 0.5, 0.5).toBlockPoint();
}
public Vector3 toWorldRel(double x, double y, double z) {
From ac082fa2be134c4f237c347d1cc47d34f050ea86 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 21:00:50 +0200
Subject: [PATCH 6/8] Use ScaleAndTranslateTransform in everything using
WorldEditExpressionEnvironment
---
.../java/com/sk89q/worldedit/EditSession.java | 102 ++++++++++++++++--
.../worldedit/command/GenerationCommands.java | 74 ++-----------
.../worldedit/command/RegionCommands.java | 37 +------
.../parser/mask/ExpressionMaskParser.java | 4 +-
.../worldedit/function/factory/Deform.java | 30 +++---
.../internal/util/TransformUtil.java | 82 ++++++++++++++
6 files changed, 202 insertions(+), 127 deletions(-)
create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
index 9e418ffb47..06c4f2a050 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -94,6 +94,8 @@
import com.sk89q.worldedit.math.interpolation.Node;
import com.sk89q.worldedit.math.noise.RandomNoise;
import com.sk89q.worldedit.math.transform.AffineTransform;
+import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
+import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.EllipsoidRegion;
@@ -2267,6 +2269,7 @@ public List> getBlockDistribution(Region region, boolean s
* @throws ExpressionException if there is a problem with the expression
* @throws MaxChangedBlocksException if the maximum block change limit is exceeded
*/
+ @Deprecated
public int makeShape(final Region region, final Vector3 zero, final Vector3 unit,
final Pattern pattern, final String expressionString, final boolean hollow)
throws ExpressionException, MaxChangedBlocksException {
@@ -2287,12 +2290,32 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
* @throws ExpressionException if there is a problem with the expression
* @throws MaxChangedBlocksException if the maximum block change limit is exceeded
*/
+ @Deprecated
public int makeShape(final Region region, final Vector3 zero, final Vector3 unit,
final Pattern pattern, final String expressionString, final boolean hollow, final int timeout)
throws ExpressionException, MaxChangedBlocksException {
+ return makeShape(region, new ScaleAndTranslateTransform(zero, unit), pattern, expressionString, hollow, timeout);
+ }
+
+ /**
+ * Generate a shape for the given expression.
+ *
+ * @param region the region to generate the shape in
+ * @param transform the transformation for x/y/z variables
+ * @param pattern the default material to make the shape from
+ * @param expressionString the expression defining the shape
+ * @param hollow whether the shape should be hollow
+ * @param timeout the time, in milliseconds, to wait for each expression evaluation before halting it. -1 to disable
+ * @return number of blocks changed
+ * @throws ExpressionException if there is a problem with the expression
+ * @throws MaxChangedBlocksException if the maximum block change limit is exceeded
+ */
+ public int makeShape(final Region region,
+ Transform transform, final Pattern pattern, final String expressionString, final boolean hollow, final int timeout)
+ throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize();
- return makeShape(region, zero, unit, pattern, expression, hollow, timeout);
+ return makeShape(region, transform, pattern, expression, hollow, timeout);
}
/**
@@ -2302,9 +2325,23 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
* The Expression class is subject to change. Expressions should be provided via the string overload.
*
*/
+ @Deprecated
public int makeShape(final Region region, final Vector3 zero, final Vector3 unit,
final Pattern pattern, final Expression expression, final boolean hollow, final int timeout)
throws ExpressionException, MaxChangedBlocksException {
+ return makeShape(region, new ScaleAndTranslateTransform(zero, unit), pattern, expression, hollow, timeout);
+ }
+
+ /**
+ * Internal version of {@link EditSession#makeShape(Region, Vector3, Vector3, Pattern, String, boolean, int)}.
+ *
+ *
+ * The Expression class is subject to change. Expressions should be provided via the string overload.
+ *
+ */
+ public int makeShape(final Region region, Transform transform,
+ final Pattern pattern, final Expression expression, final boolean hollow, final int timeout)
+ throws ExpressionException, MaxChangedBlocksException {
expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
@@ -2318,16 +2355,17 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
final Variable dataVariable = expression.getSlots().getVariable("data")
.orElseThrow(IllegalStateException::new);
- final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
+ final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, transform);
expression.setEnvironment(environment);
final int[] timedOut = {0};
+ final Transform transformInverse = transform.inverse();
final ArbitraryShape shape = new ArbitraryShape(region) {
@Override
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
final Vector3 current = Vector3.at(x, y, z);
environment.setCurrentBlock(current);
- final Vector3 inputPosition = current.subtract(zero).divide(unit);
+ final Vector3 inputPosition = transformInverse.apply(current);
try {
int[] legacy = LegacyMapper.getInstance().getLegacyFromBlock(defaultMaterial.toImmutableState());
@@ -2384,9 +2422,10 @@ protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial)
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
+ @Deprecated
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString)
throws ExpressionException, MaxChangedBlocksException {
- return deformRegion(region, zero, unit, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout);
+ return deformRegion(region, new ScaleAndTranslateTransform(zero, unit), expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout);
}
/**
@@ -2405,11 +2444,31 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
+ @Deprecated
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
+ final Transform transform = new ScaleAndTranslateTransform(zero, unit);
+ return deformRegion(region, transform, expressionString, timeout);
+ }
+
+ /**
+ * Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
+ * to an expression, and then sets the block to the block given by the resulting values of the variables, if they
+ * have changed.
+ *
+ * @param region the region to deform
+ * @param transform the coordinate system
+ * @param expressionString the expression to evaluate for each block
+ * @param timeout maximum time for the expression to evaluate for each block. -1 for unlimited.
+ * @return number of blocks changed
+ * @throws ExpressionException thrown on invalid expression input
+ * @throws MaxChangedBlocksException thrown if too many blocks are changed
+ */
+ public int deformRegion(final Region region, final Transform transform, final String expressionString,
+ final int timeout) throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
- return deformRegion(region, zero, unit, expression, timeout);
+ return deformRegion(region, transform, expression, timeout);
}
/**
@@ -2419,8 +2478,21 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* The Expression class is subject to change. Expressions should be provided via the string overload.
*
*/
+ @Deprecated
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final Expression expression,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
+ return deformRegion(region, new ScaleAndTranslateTransform(zero, unit), expression, timeout);
+ }
+
+ /**
+ * Internal version of {@link EditSession#deformRegion(Region, Vector3, Vector3, String, int)}.
+ *
+ *
+ * The Expression class is subject to change. Expressions should be provided via the string overload.
+ *
+ */
+ public int deformRegion(final Region region, final Transform transform, final Expression expression,
+ final int timeout) throws ExpressionException, MaxChangedBlocksException {
final Variable x = expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
final Variable y = expression.getSlots().getVariable("y")
@@ -2428,23 +2500,25 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
final Variable z = expression.getSlots().getVariable("z")
.orElseThrow(IllegalStateException::new);
- final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
+ final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, transform);
expression.setEnvironment(environment);
final DoubleArrayList queue = new DoubleArrayList<>(false);
+ final Transform transformInverse = transform.inverse();
for (BlockVector3 targetBlockPosition : region) {
final Vector3 targetPosition = targetBlockPosition.toVector3();
environment.setCurrentBlock(targetPosition);
// transform from target coordinates
- final Vector3 inputPosition = targetPosition.subtract(zero).divide(unit);
+ final Vector3 inputPosition = transformInverse.apply(targetPosition);
// deform
expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout);
+ final Vector3 outputPosition = Vector3.at(x.value(), y.value(), z.value());
// transform to source coordinates, round-nearest
- final BlockVector3 sourcePosition = environment.toWorld(x.value(), y.value(), z.value());
+ final BlockVector3 sourcePosition = transform.apply(outputPosition).add(0.5, 0.5, 0.5).toBlockPoint();
// read block from world
final BaseBlock material = world.getFullBlock(sourcePosition);
@@ -2752,28 +2826,36 @@ private void recurseHollow(Region region, BlockVector3 origin, Set
}
}
+ @Deprecated
public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
final String expressionString, final boolean hollow) throws ExpressionException {
return makeBiomeShape(region, zero, unit, biomeType, expressionString, hollow, WorldEdit.getInstance().getConfiguration().calculationTimeout);
}
+ @Deprecated
public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
final String expressionString, final boolean hollow, final int timeout) throws ExpressionException {
+ return makeBiomeShape(region, new ScaleAndTranslateTransform(zero, unit), biomeType, expressionString, hollow, timeout);
+ }
+
+ public int makeBiomeShape(final Region region, Transform transform, final BiomeType biomeType,
+ final String expressionString, final boolean hollow, final int timeout) throws ExpressionException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
final EditSession editSession = this;
- final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero);
+ final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, transform);
expression.setEnvironment(environment);
AtomicInteger timedOut = new AtomicInteger();
+ final Transform transformInverse = transform.inverse();
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
@Override
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) {
final Vector3 current = Vector3.at(x, y, z);
environment.setCurrentBlock(current);
- final Vector3 inputPosition = current.subtract(zero).divide(unit);
+ final Vector3 inputPosition = transformInverse.apply(current);
try {
if (expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout) <= 0) {
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
index bf5076848c..7cd222f742 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
@@ -32,8 +32,9 @@
import com.sk89q.worldedit.internal.annotation.Radii;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
+import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.BlockVector3;
-import com.sk89q.worldedit.math.Vector3;
+import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
@@ -373,42 +374,10 @@ public int generate(Actor actor, LocalSession session, EditSession editSession,
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
-
- final Vector3 zero;
- Vector3 unit;
-
- if (useRawCoords) {
- zero = Vector3.ZERO;
- unit = Vector3.ONE;
- } else if (offsetPlacement) {
- zero = session.getPlacementPosition(actor).toVector3();
- unit = Vector3.ONE;
- } else if (offsetCenter) {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = Vector3.ONE;
- } else {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = max.subtract(zero);
-
- if (unit.x() == 0) {
- unit = unit.withX(1.0);
- }
- if (unit.y() == 0) {
- unit = unit.withY(1.0);
- }
- if (unit.z() == 0) {
- unit = unit.withZ(1.0);
- }
- }
+ final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
try {
- final int affected = editSession.makeShape(region, zero, unit, pattern, String.join(" ", expression), hollow, session.getTimeout());
+ final int affected = editSession.makeShape(region, transform, pattern, String.join(" ", expression), hollow, session.getTimeout());
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
@@ -442,41 +411,10 @@ public int generateBiome(Actor actor, LocalSession session, EditSession editSess
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
- final Vector3 zero;
- Vector3 unit;
-
- if (useRawCoords) {
- zero = Vector3.ZERO;
- unit = Vector3.ONE;
- } else if (offsetPlacement) {
- zero = session.getPlacementPosition(actor).toVector3();
- unit = Vector3.ONE;
- } else if (offsetCenter) {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = Vector3.ONE;
- } else {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = max.subtract(zero);
-
- if (unit.x() == 0) {
- unit = unit.withX(1.0);
- }
- if (unit.y() == 0) {
- unit = unit.withY(1.0);
- }
- if (unit.z() == 0) {
- unit = unit.withZ(1.0);
- }
- }
+ final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
try {
- final int affected = editSession.makeBiomeShape(region, zero, unit, target, String.join(" ", expression), hollow, session.getTimeout());
+ final int affected = editSession.makeBiomeShape(region, transform, target, String.join(" ", expression), hollow, session.getTimeout());
actor.printInfo(TranslatableComponent.of("worldedit.generatebiome.changed", TextComponent.of(affected)));
return affected;
} catch (ExpressionException e) {
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 62207daa16..8a7c418f5e 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -49,13 +49,14 @@
import com.sk89q.worldedit.internal.annotation.Offset;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
+import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.BlockVector3;
-import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.math.convolution.SnowHeightMap;
import com.sk89q.worldedit.math.noise.RandomNoise;
+import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
@@ -501,41 +502,11 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
- final Vector3 zero;
- Vector3 unit;
-
- if (useRawCoords) {
- zero = Vector3.ZERO;
- unit = Vector3.ONE;
- } else if (offsetPlacement) {
- zero = session.getPlacementPosition(actor).toVector3();
- unit = Vector3.ONE;
- } else if (offsetCenter) {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = Vector3.ONE;
- } else {
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).divide(2);
- unit = max.subtract(zero);
- if (unit.x() == 0) {
- unit = unit.withX(1.0);
- }
- if (unit.y() == 0) {
- unit = unit.withY(1.0);
- }
- if (unit.z() == 0) {
- unit = unit.withZ(1.0);
- }
- }
+ final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
try {
- final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout());
+ final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout());
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java
index c58af7d566..09f684cf2e 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java
@@ -27,7 +27,7 @@
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.registry.InputParser;
-import com.sk89q.worldedit.math.Vector3;
+import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.SessionOwner;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
@@ -58,7 +58,7 @@ public Mask parseFromInput(String input, ParserContext context) throws InputPars
try {
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
- context.requireExtent(), Vector3.ONE, Vector3.ZERO);
+ context.requireExtent(), new Identity());
exp.setEnvironment(env);
if (context.getActor() != null) {
SessionOwner owner = context.getActor();
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
index 017e8b3a3e..5103770fdd 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
@@ -33,6 +33,9 @@
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.Vector3;
+import com.sk89q.worldedit.math.transform.Identity;
+import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
+import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.formatting.text.Component;
@@ -118,18 +121,16 @@ public String toString() {
@Override
public Operation createFromContext(final EditContext context) {
- final Vector3 zero;
- Vector3 unit;
Region region = firstNonNull(context.getRegion(), this.region);
+ final Transform transform;
switch (mode) {
case UNIT_CUBE:
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();
-
- zero = max.add(min).multiply(0.5);
- unit = max.subtract(zero);
+ final Vector3 zero = max.add(min).multiply(0.5);
+ Vector3 unit = max.subtract(zero);
if (unit.x() == 0) {
unit = unit.withX(1.0);
@@ -140,27 +141,28 @@ public Operation createFromContext(final EditContext context) {
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}
+
+ transform = new ScaleAndTranslateTransform(zero, unit);
break;
+
case RAW_COORD:
- zero = Vector3.ZERO;
- unit = Vector3.ONE;
+ transform = new Identity();
break;
+
case OFFSET:
default:
- zero = offset;
- unit = Vector3.ONE;
+ transform = new ScaleAndTranslateTransform(offset, Vector3.ONE);
+ break;
}
-
LocalSession session = context.getSession();
- return new DeformOperation(context.getDestination(), region, zero, unit, expression,
+ return new DeformOperation(context.getDestination(), region, transform, expression,
session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout());
}
private record DeformOperation(
Extent destination,
Region region,
- Vector3 zero,
- Vector3 unit,
+ Transform transform,
Expression expression,
int timeout
) implements Operation {
@@ -168,7 +170,7 @@ private record DeformOperation(
public Operation resume(RunContext run) throws WorldEditException {
try {
// TODO: Move deformation code
- ((EditSession) destination).deformRegion(region, zero, unit, expression, timeout);
+ ((EditSession) destination).deformRegion(region, transform, expression, timeout);
return null;
} catch (ExpressionException e) {
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
new file mode 100644
index 0000000000..b5efce5a94
--- /dev/null
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
@@ -0,0 +1,82 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.internal.util;
+
+import com.sk89q.worldedit.IncompleteRegionException;
+import com.sk89q.worldedit.LocalSession;
+import com.sk89q.worldedit.extension.platform.Actor;
+import com.sk89q.worldedit.math.Vector3;
+import com.sk89q.worldedit.math.transform.Identity;
+import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
+import com.sk89q.worldedit.math.transform.Transform;
+import com.sk89q.worldedit.regions.Region;
+
+/**
+ * Various internal utility methods related to {@link Transform}s.
+ */
+public final class TransformUtil {
+
+ private TransformUtil() {
+ }
+
+ /**
+ * Creates a {@link Transform} for various expression commands.
+ *
+ * @param actor Actor that ran the command
+ * @param session Session that the command was run in
+ * @param region Selection that the command was run in
+ * @param useRawCoords Use the game's coordinate origin
+ * @param offsetPlacement Use the placement's coordinate origin
+ * @param offsetCenter Use the selection's center as origin
+ * @return A transform from the expression coordinate system to the raw coordinate system
+ */
+ public static Transform createTransformForExpressionCommand(Actor actor, LocalSession session, Region region, boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter) throws IncompleteRegionException {
+ if (useRawCoords) {
+ return new Identity();
+ }
+
+ if (offsetPlacement) {
+ final Vector3 placement = session.getPlacementPosition(actor).toVector3();
+
+ return new ScaleAndTranslateTransform(placement, Vector3.ONE);
+ }
+
+ final Vector3 min = region.getMinimumPoint().toVector3();
+ final Vector3 max = region.getMaximumPoint().toVector3();
+ final Vector3 center = max.add(min).multiply(0.5);
+
+ if (offsetCenter) {
+ return new ScaleAndTranslateTransform(center, Vector3.ONE);
+ }
+
+ Vector3 scale = max.subtract(center);
+
+ if (scale.x() == 0) {
+ scale = scale.withX(1.0);
+ }
+ if (scale.y() == 0) {
+ scale = scale.withY(1.0);
+ }
+ if (scale.z() == 0) {
+ scale = scale.withZ(1.0);
+ }
+ return new ScaleAndTranslateTransform(center, scale);
+ }
+}
From 83e66b2fcf84dc0123919c74676e38e13248d53e Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 00:36:53 +0200
Subject: [PATCH 7/8] Add inputExtent parameter and separate in/outputTransform
for deformRegion
---
.../java/com/sk89q/worldedit/EditSession.java | 47 ++++++++++++++-----
.../worldedit/command/RegionCommands.java | 4 +-
.../worldedit/function/factory/Deform.java | 3 +-
3 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
index 06c4f2a050..ddceae30d7 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -28,6 +28,7 @@
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
+import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.extent.TracingExtent;
@@ -2451,6 +2452,28 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
return deformRegion(region, transform, expressionString, timeout);
}
+ /**
+ * Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
+ * to an expression, and then sets the block to the block given by the resulting values of the variables, if they
+ * have changed.
+ *
+ * @param region the region to deform
+ * @param targetTransform the target coordinate system
+ * @param expressionString the expression to evaluate for each block
+ * @param timeout maximum time for the expression to evaluate for each block. -1 for unlimited.
+ * @param sourceExtent the InputExtent to fetch blocks from, for instance a World or a Clipboard
+ * @param sourceTransform the source coordinate system
+ * @return number of blocks changed
+ * @throws ExpressionException thrown on invalid expression input
+ * @throws MaxChangedBlocksException thrown if too many blocks are changed
+ */
+ public int deformRegion(final Region region, final Transform targetTransform, final String expressionString,
+ final int timeout, InputExtent sourceExtent, Transform sourceTransform) throws ExpressionException, MaxChangedBlocksException {
+ final Expression expression = Expression.compile(expressionString, "x", "y", "z");
+ expression.optimize();
+ return deformRegion(region, targetTransform, expression, timeout, sourceExtent, sourceTransform);
+ }
+
/**
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
@@ -2464,11 +2487,10 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
+ @Deprecated
public int deformRegion(final Region region, final Transform transform, final String expressionString,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
- final Expression expression = Expression.compile(expressionString, "x", "y", "z");
- expression.optimize();
- return deformRegion(region, transform, expression, timeout);
+ return deformRegion(region, transform, expressionString, timeout, world, transform);
}
/**
@@ -2481,7 +2503,8 @@ public int deformRegion(final Region region, final Transform transform, final St
@Deprecated
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final Expression expression,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
- return deformRegion(region, new ScaleAndTranslateTransform(zero, unit), expression, timeout);
+ final Transform transform = new ScaleAndTranslateTransform(zero, unit);
+ return deformRegion(region, transform, expression, timeout, world, transform);
}
/**
@@ -2491,8 +2514,8 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* The Expression class is subject to change. Expressions should be provided via the string overload.
*
*/
- public int deformRegion(final Region region, final Transform transform, final Expression expression,
- final int timeout) throws ExpressionException, MaxChangedBlocksException {
+ public int deformRegion(final Region region, final Transform targetTransform, final Expression expression,
+ final int timeout, InputExtent sourceExtent, final Transform sourceTransform) throws ExpressionException, MaxChangedBlocksException {
final Variable x = expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
final Variable y = expression.getSlots().getVariable("y")
@@ -2500,28 +2523,28 @@ public int deformRegion(final Region region, final Transform transform, final Ex
final Variable z = expression.getSlots().getVariable("z")
.orElseThrow(IllegalStateException::new);
- final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, transform);
+ final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, targetTransform);
expression.setEnvironment(environment);
final DoubleArrayList queue = new DoubleArrayList<>(false);
- final Transform transformInverse = transform.inverse();
+ final Transform targetTransformInverse = targetTransform.inverse();
for (BlockVector3 targetBlockPosition : region) {
final Vector3 targetPosition = targetBlockPosition.toVector3();
environment.setCurrentBlock(targetPosition);
// transform from target coordinates
- final Vector3 inputPosition = transformInverse.apply(targetPosition);
+ final Vector3 inputPosition = targetTransformInverse.apply(targetPosition);
// deform
expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout);
final Vector3 outputPosition = Vector3.at(x.value(), y.value(), z.value());
// transform to source coordinates, round-nearest
- final BlockVector3 sourcePosition = transform.apply(outputPosition).add(0.5, 0.5, 0.5).toBlockPoint();
+ final BlockVector3 sourcePosition = sourceTransform.apply(outputPosition).add(0.5, 0.5, 0.5).toBlockPoint();
- // read block from world
- final BaseBlock material = world.getFullBlock(sourcePosition);
+ // read block from source extent (e.g. world/clipboard)
+ final BaseBlock material = sourceExtent.getFullBlock(sourcePosition);
// queue operation
queue.put(targetBlockPosition, material);
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 8a7c418f5e..872e0ec9f1 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -31,6 +31,7 @@
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
+import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
@@ -504,9 +505,10 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
boolean offsetCenter) throws WorldEditException {
final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
+ final InputExtent inputExtent = editSession.getWorld();
try {
- final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout());
+ final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout(), inputExtent, transform);
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
index 5103770fdd..6ae469b4c1 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java
@@ -170,7 +170,8 @@ private record DeformOperation(
public Operation resume(RunContext run) throws WorldEditException {
try {
// TODO: Move deformation code
- ((EditSession) destination).deformRegion(region, transform, expression, timeout);
+ final EditSession editSession = (EditSession) destination;
+ editSession.deformRegion(region, transform, expression, timeout, editSession.getWorld(), transform);
return null;
} catch (ExpressionException e) {
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
From cc32178907070f52a494ddde9b05b85ec945115a Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 09:14:00 +0200
Subject: [PATCH 8/8] Add clipboard support to //deform
---
.../worldedit/command/RegionCommands.java | 25 ++++++++++++++++---
.../internal/util/TransformUtil.java | 23 ++++++++++++++---
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 872e0ec9f1..ff5b0b1548 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -33,6 +33,7 @@
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
@@ -52,6 +53,7 @@
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
@@ -502,13 +504,28 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
- boolean offsetCenter) throws WorldEditException {
+ boolean offsetCenter,
+ @Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
+ boolean useClipboard) throws WorldEditException {
+ final Transform targetTransform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
- final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
- final InputExtent inputExtent = editSession.getWorld();
+ final InputExtent sourceExtent;
+ final Transform sourceTransform;
+ if (useClipboard) {
+ final Clipboard clipboard = session.getClipboard().getClipboard();
+ sourceExtent = clipboard;
+
+ final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
+ final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();
+
+ sourceTransform = TransformUtil.createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, clipboardMin, clipboardMax, clipboardMin);
+ } else {
+ sourceExtent = editSession.getWorld();
+ sourceTransform = targetTransform;
+ }
try {
- final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout(), inputExtent, transform);
+ final int affected = editSession.deformRegion(region, targetTransform, String.join(" ", expression), session.getTimeout(), sourceExtent, sourceTransform);
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
index b5efce5a94..9c3851c20d 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/TransformUtil.java
@@ -48,18 +48,33 @@ private TransformUtil() {
* @return A transform from the expression coordinate system to the raw coordinate system
*/
public static Transform createTransformForExpressionCommand(Actor actor, LocalSession session, Region region, boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter) throws IncompleteRegionException {
+ final Vector3 placement = session.getPlacementPosition(actor).toVector3();
+ final Vector3 min = region.getMinimumPoint().toVector3();
+ final Vector3 max = region.getMaximumPoint().toVector3();
+
+ return createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, min, max, placement);
+ }
+
+ /**
+ * Creates a {@link Transform} for the //deform command with clipboard support.
+ *
+ * @param useRawCoords Use the game's coordinate origin
+ * @param offsetPlacement Use the placement's coordinate origin
+ * @param offsetCenter Use the selection's center as origin
+ * @param min Minimum of the selection/clipboard
+ * @param max Maximum of the selection/clipboard
+ * @param placement Placement position
+ * @return A transform from the expression coordinate system to the world/clipboard coordinate system
+ */
+ public static Transform createTransformForExpressionCommand(boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter, Vector3 min, Vector3 max, Vector3 placement) {
if (useRawCoords) {
return new Identity();
}
if (offsetPlacement) {
- final Vector3 placement = session.getPlacementPosition(actor).toVector3();
-
return new ScaleAndTranslateTransform(placement, Vector3.ONE);
}
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
final Vector3 center = max.add(min).multiply(0.5);
if (offsetCenter) {