use of com.sk89q.worldedit.internal.expression.LocalSlot.Variable in project FastAsyncWorldEdit by IntellectualSites.
the class EditSession method makeShape.
/**
* Generate a shape for the given expression.
*
* @param region the region to generate the shape in
* @param zero the coordinate origin for x/y/z variables
* @param unit the scale of the 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, final Vector3 zero, final Vector3 unit, 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();
final Variable typeVariable = expression.getSlots().getVariable("type").orElseThrow(IllegalStateException::new);
final Variable dataVariable = expression.getSlots().getVariable("data").orElseThrow(IllegalStateException::new);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
final int[] timedOut = { 0 };
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 scaled = current.subtract(zero).divide(unit);
try {
int[] legacy = LegacyMapper.getInstance().getLegacyFromBlock(defaultMaterial.toImmutableState());
int typeVar = 0;
int dataVar = 0;
if (legacy != null) {
typeVar = legacy[0];
if (legacy.length > 1) {
dataVar = legacy[1];
}
}
if (expression.evaluate(new double[] { scaled.getX(), scaled.getY(), scaled.getZ(), typeVar, dataVar }, timeout) <= 0) {
return null;
}
int newType = (int) typeVariable.getValue();
int newData = (int) dataVariable.getValue();
if (newType != typeVar || newData != dataVar) {
BlockState state = LegacyMapper.getInstance().getBlockFromLegacy(newType, newData);
return state == null ? defaultMaterial : state.toBaseBlock();
} else {
return defaultMaterial;
}
} catch (ExpressionTimeoutException e) {
timedOut[0] = timedOut[0] + 1;
return null;
} catch (Exception e) {
LOGGER.warn("Failed to create shape", e);
return null;
}
}
};
int changed = shape.generate(this, pattern, hollow);
if (timedOut[0] > 0) {
throw new ExpressionTimeoutException(String.format("%d blocks changed. %d blocks took too long to evaluate (increase with //timeout).", changed, timedOut[0]));
}
return changed;
}
use of com.sk89q.worldedit.internal.expression.LocalSlot.Variable in project FastAsyncWorldEdit by IntellectualSites.
the class EditSession method deformRegion.
/**
* Internal version of {@link EditSession#deformRegion(Region, Vector3, Vector3, String, int)}.
*
* <p>
* The Expression class is subject to change. Expressions should be provided via the string overload.
* </p>
*/
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, 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").orElseThrow(IllegalStateException::new);
final Variable z = expression.getSlots().getVariable("z").orElseThrow(IllegalStateException::new);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
// FAWE start
final Vector3 zero2 = zero.add(0.5, 0.5, 0.5);
RegionVisitor visitor = new RegionVisitor(region, position -> {
try {
// offset, scale
final Vector3 scaled = position.toVector3().subtract(zero).divide(unit);
// transform
expression.evaluate(new double[] { scaled.getX(), scaled.getY(), scaled.getZ() }, timeout);
int xv = (int) (x.getValue() * unit.getX() + zero2.getX());
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
BlockState get;
if (yv >= minY && yv <= maxY) {
get = getBlock(xv, yv, zv);
} else {
get = BlockTypes.AIR.getDefaultState();
}
// read block from world
return setBlock(position, get);
} catch (EvaluationException e) {
throw new RuntimeException(e);
}
}, this);
Operations.completeBlindly(visitor);
changes += visitor.getAffected();
return changes;
// FAWE end
}
Aggregations