use of com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment in project FastAsyncWorldEdit by IntellectualSites.
the class ExpressionMaskParser method parseFromInput.
@Override
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
if (!input.startsWith("=")) {
return null;
}
// FAWE start - richer parsing
if (input.charAt(1) == '[') {
int end = input.lastIndexOf(']');
if (end == -1) {
return null;
}
input = input.substring(2, end);
} else {
input = input.substring(1);
}
try {
// FAWE start - richer parsing
Expression exp = Expression.compile(input, "x", "y", "z");
// FAWE end
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(context.requireExtent(), Vector3.ONE, Vector3.ZERO);
exp.setEnvironment(env);
if (context.getActor() != null) {
SessionOwner owner = context.getActor();
IntSupplier timeout = () -> WorldEdit.getInstance().getSessionManager().get(owner).getTimeout();
return new ExpressionMask(exp, timeout);
}
return new ExpressionMask(exp);
} catch (ExpressionException e) {
throw new InputParseException(Caption.of("worldedit.error.parser.invalid-expression", TextComponent.of(e.getMessage())));
}
}
use of com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment in project FastAsyncWorldEdit by IntellectualSites.
the class ExpressionPatternParser method parseFromSimpleInput.
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
try {
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(context.requireExtent(), Vector3.ONE, Vector3.ZERO);
exp.setEnvironment(env);
return new ExpressionPattern(exp);
} catch (ExpressionException e) {
throw new InputParseException(Caption.of("worldedit.error.parser.invalid-expression", TextComponent.of(e.getMessage())));
}
}
use of com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment in project FastAsyncWorldEdit by IntellectualSites.
the class EditSession method makeBiomeShape.
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 {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
final EditSession editSession = this;
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero);
expression.setEnvironment(environment);
AtomicInteger timedOut = new AtomicInteger();
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
@Override
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) {
environment.setCurrentBlock(x, y, z);
double scaledX = (x - zero.getX()) / unit.getX();
double scaledY = (y - zero.getY()) / unit.getY();
double scaledZ = (z - zero.getZ()) / unit.getZ();
try {
if (expression.evaluate(new double[] { scaledX, scaledY, scaledZ }, timeout) <= 0) {
return null;
}
// TODO: Allow biome setting via a script variable (needs BiomeType<->int mapping)
return defaultBiomeType;
} catch (ExpressionTimeoutException e) {
timedOut.getAndIncrement();
return null;
} catch (Exception e) {
LOGGER.warn("Failed to create shape", e);
return null;
}
}
};
int changed = shape.generate(this, biomeType, hollow);
if (timedOut.get() > 0) {
throw new ExpressionTimeoutException(String.format("%d biomes changed. %d biomes took too long to evaluate (increase time with //timeout)", changed, timedOut.get()));
}
return changed;
}
use of com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment 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.regions.shape.WorldEditExpressionEnvironment 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