From 62e94d16ec10017417bf399da26cbc7a5bd346f8 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Wed, 8 Mar 2023 01:03:43 +0100
Subject: [PATCH 01/11] 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 92284f25bd..f32e80c218 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
@@ -495,7 +495,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;
@@ -504,7 +504,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 be558a4a8d0c6c64ea1a6926963acd2d0df37f11 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Wed, 8 Mar 2023 04:59:45 +0100
Subject: [PATCH 02/11] 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 a97f205479d4cb6ca8481be946e76b7f2fee4773 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Thu, 18 Jul 2024 08:04:08 +0200
Subject: [PATCH 03/11] 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 49b6895f495fdfae4db19cb2b4b6f088d1b5984c Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 14:35:16 +0200
Subject: [PATCH 04/11] 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 9f4fae4ea7c208c22785ca4dd57f4af1db571dca Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 14:41:53 +0200
Subject: [PATCH 05/11] 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 17e28bca866b73d976f63aafc309574e522ed050 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sat, 13 Jul 2024 21:00:50 +0200
Subject: [PATCH 06/11] 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 f32e80c218..d1b8efa0d1 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
@@ -47,13 +47,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;
@@ -498,41 +499,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 cb59fab8f9820f448f1c21232544e95ab1099c4d Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 00:36:53 +0200
Subject: [PATCH 07/11] 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 d1b8efa0d1..c24c4cb1de 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;
@@ -501,9 +502,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 2e0ecdb02be70ecaa0911aca1901409276783d7e Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 09:14:00 +0200
Subject: [PATCH 08/11] 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 c24c4cb1de..3469a765f0 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.block.BlockReplace;
@@ -50,6 +51,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;
@@ -499,13 +501,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) {
From 08252ee0264b11cb3f4d0a26046255a85b54d6c8 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 22:53:10 +0200
Subject: [PATCH 09/11] //brush deform: Use ScaleAndTranslateTransform in
everything using WorldEditExpressionEnvironment
---
.../worldedit/function/factory/Deform.java | 36 +++----------------
.../internal/util/TransformUtil.java | 24 +++++++++++++
2 files changed, 28 insertions(+), 32 deletions(-)
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 6ae469b4c1..ff05b2966f 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
@@ -32,9 +32,8 @@
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
+import com.sk89q.worldedit.internal.util.TransformUtil;
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;
@@ -123,37 +122,10 @@ public String toString() {
public Operation createFromContext(final EditContext context) {
Region region = firstNonNull(context.getRegion(), this.region);
+ final Vector3 min = region.getMinimumPoint().toVector3();
+ final Vector3 max = region.getMaximumPoint().toVector3();
- final Transform transform;
- switch (mode) {
- case UNIT_CUBE:
- final Vector3 min = region.getMinimumPoint().toVector3();
- final Vector3 max = region.getMaximumPoint().toVector3();
- final Vector3 zero = max.add(min).multiply(0.5);
- Vector3 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);
- }
-
- transform = new ScaleAndTranslateTransform(zero, unit);
- break;
-
- case RAW_COORD:
- transform = new Identity();
- break;
-
- case OFFSET:
- default:
- transform = new ScaleAndTranslateTransform(offset, Vector3.ONE);
- break;
- }
+ final Transform transform = TransformUtil.createTransformForExpressionCommand(mode, min, max, offset);
LocalSession session = context.getSession();
return new DeformOperation(context.getDestination(), region, transform, expression,
session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout());
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 9c3851c20d..33da69d6a2 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
@@ -22,6 +22,7 @@
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.extension.platform.Actor;
+import com.sk89q.worldedit.function.factory.Deform;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
@@ -94,4 +95,27 @@ public static Transform createTransformForExpressionCommand(boolean useRawCoords
}
return new ScaleAndTranslateTransform(center, scale);
}
+
+ /**
+ * Creates a {@link Transform} for the //deform command with clipboard support.
+ *
+ * @param mode The coordinate mode to use
+ * @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(Deform.Mode mode, Vector3 min, Vector3 max, Vector3 placement) {
+ switch (mode) {
+ case UNIT_CUBE:
+ return createTransformForExpressionCommand(false, false, false, min, max, placement);
+
+ case RAW_COORD:
+ return createTransformForExpressionCommand(true, false, false, min, max, placement);
+
+ case OFFSET:
+ default:
+ return createTransformForExpressionCommand(false, true, false, min, max, placement);
+ }
+ }
}
From 556152300cac7d94e6397eb32a6f5c15c9b87626 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Sun, 14 Jul 2024 23:02:05 +0200
Subject: [PATCH 10/11] //brush deform: Add inputExtent parameter and separate
in/outputTransform for deformRegion
---
.../com/sk89q/worldedit/function/factory/Deform.java | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
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 ff05b2966f..984d3514dd 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
@@ -25,6 +25,7 @@
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
+import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
@@ -127,23 +128,26 @@ public Operation createFromContext(final EditContext context) {
final Transform transform = TransformUtil.createTransformForExpressionCommand(mode, min, max, offset);
LocalSession session = context.getSession();
+ EditSession editSession = (EditSession) context.getDestination();
return new DeformOperation(context.getDestination(), region, transform, expression,
- session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout());
+ session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout(), editSession.getWorld(), transform);
}
private record DeformOperation(
Extent destination,
Region region,
- Transform transform,
+ Transform targetTransform,
Expression expression,
- int timeout
+ int timeout,
+ InputExtent sourceExtent,
+ Transform sourceTransform
) implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
try {
// TODO: Move deformation code
final EditSession editSession = (EditSession) destination;
- editSession.deformRegion(region, transform, expression, timeout, editSession.getWorld(), transform);
+ editSession.deformRegion(region, targetTransform, expression, timeout, sourceExtent, sourceTransform);
return null;
} catch (ExpressionException e) {
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
From adbee4e7567c44844fd09239db886ee5845f0e62 Mon Sep 17 00:00:00 2001
From: TomyLobo
Date: Wed, 17 Jul 2024 08:03:17 +0200
Subject: [PATCH 11/11] Add clipboard to //brush deform
---
.../com/sk89q/worldedit/LocalSession.java | 10 +++++
.../worldedit/command/BrushCommands.java | 5 ++-
.../worldedit/function/factory/Deform.java | 37 +++++++++++++++++--
3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java
index 7eb1a73837..b89da133c7 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java
@@ -69,6 +69,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
@@ -451,6 +452,15 @@ public ClipboardHolder getClipboard() throws EmptyClipboardException {
return clipboard;
}
+ /**
+ * Gets the clipboard.
+ *
+ * @return clipboard
+ */
+ public Optional getClipboardOptional() {
+ return Optional.ofNullable(clipboard);
+ }
+
/**
* Sets the clipboard.
*
diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
index 120ba27db8..f2155b3e96 100644
--- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
+++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
@@ -506,7 +506,9 @@ public void deform(Player player, LocalSession localSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement position as the origin")
- boolean usePlacement) throws WorldEditException {
+ boolean usePlacement,
+ @Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
+ boolean useClipboard) throws WorldEditException {
Deform deform = new Deform(expression);
if (useRawCoords) {
deform.setMode(Deform.Mode.RAW_COORD);
@@ -514,6 +516,7 @@ public void deform(Player player, LocalSession localSession,
deform.setMode(Deform.Mode.OFFSET);
deform.setOffset(localSession.getPlacementPosition(player).toVector3());
}
+ deform.setUseClipboard(useClipboard);
setOperationBasedBrush(player, localSession, radius,
deform, shape, "worldedit.brush.deform");
}
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 984d3514dd..6136a969b2 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
@@ -27,6 +27,7 @@
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.NullExtent;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.operation.Operation;
@@ -38,11 +39,14 @@
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
+import java.util.Optional;
+
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull;
@@ -53,6 +57,7 @@ public class Deform implements Contextual {
private final Expression expression;
private Mode mode;
private Vector3 offset = Vector3.ZERO;
+ private boolean useClipboard;
public Deform(String expression) {
this(new NullExtent(), new NullRegion(), expression);
@@ -114,6 +119,14 @@ public void setOffset(Vector3 offset) {
this.offset = offset;
}
+ public boolean useClipboard() {
+ return useClipboard;
+ }
+
+ public void setUseClipboard(boolean useClipboard) {
+ this.useClipboard = useClipboard;
+ }
+
@Override
public String toString() {
return "deformation of " + expression.getSource();
@@ -126,11 +139,29 @@ public Operation createFromContext(final EditContext context) {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();
- final Transform transform = TransformUtil.createTransformForExpressionCommand(mode, min, max, offset);
LocalSession session = context.getSession();
EditSession editSession = (EditSession) context.getDestination();
- return new DeformOperation(context.getDestination(), region, transform, expression,
- session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout(), editSession.getWorld(), transform);
+ final Optional clipboardOptional = Optional.ofNullable(session)
+ .flatMap(LocalSession::getClipboardOptional)
+ .map(ClipboardHolder::getClipboard);
+
+ final Transform targetTransform = TransformUtil.createTransformForExpressionCommand(mode, min, max, offset);
+ final InputExtent sourceExtent;
+ final Transform sourceTransform;
+ if (useClipboard && clipboardOptional.isPresent()) {
+ final Clipboard clipboard = clipboardOptional.get();
+ final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
+ final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();
+
+ sourceExtent = clipboard;
+ sourceTransform = TransformUtil.createTransformForExpressionCommand(mode, clipboardMin, clipboardMax, offset);
+ } else {
+ sourceExtent = editSession.getWorld();
+ sourceTransform = targetTransform;
+ }
+
+ return new DeformOperation(context.getDestination(), region, targetTransform, expression,
+ session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout(), sourceExtent, sourceTransform);
}
private record DeformOperation(