Added query{,Abs,Rel}(x,y,z,typevar,datavar) to the expression parser.

This commit is contained in:
TomyLobo 2013-09-21 14:35:57 +02:00
parent eba1114b39
commit 8badb09399
5 changed files with 155 additions and 8 deletions

View File

@ -2808,10 +2808,15 @@ public class EditSession {
final RValue typeVariable = expression.getVariable("type", false); final RValue typeVariable = expression.getVariable("type", false);
final RValue dataVariable = expression.getVariable("data", false); final RValue dataVariable = expression.getVariable("data", false);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
final ArbitraryShape shape = new ArbitraryShape(region) { final ArbitraryShape shape = new ArbitraryShape(region) {
@Override @Override
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) { protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
final Vector scaled = new Vector(x, y, z).subtract(zero).divide(unit); final Vector current = new Vector(x, y, z);
environment.setCurrentBlock(current);
final Vector scaled = current.subtract(zero).divide(unit);
try { try {
if (expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getType(), defaultMaterial.getData()) <= 0) { if (expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getType(), defaultMaterial.getData()) <= 0) {
@ -2837,7 +2842,8 @@ public class EditSession {
final RValue y = expression.getVariable("y", false); final RValue y = expression.getVariable("y", false);
final RValue z = expression.getVariable("z", false); final RValue z = expression.getVariable("z", false);
Vector zero2 = zero.add(0.5, 0.5, 0.5); final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
final DoubleArrayList<BlockVector, BaseBlock> queue = new DoubleArrayList<BlockVector, BaseBlock>(false); final DoubleArrayList<BlockVector, BaseBlock> queue = new DoubleArrayList<BlockVector, BaseBlock>(false);
@ -2848,13 +2854,11 @@ public class EditSession {
// transform // transform
expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ()); expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ());
final Vector sourceScaled = new Vector(x.getValue(), y.getValue(), z.getValue()); final BlockVector sourcePosition = environment.toWorld(scaled.getX(), scaled.getY(), scaled.getZ());
// unscale, unoffset, round-nearest
final BlockVector sourcePosition = sourceScaled.multiply(unit).add(zero2).toBlockPoint();
// read block from world // read block from world
BaseBlock material = new BaseBlock(world.getBlockType(sourcePosition), world.getBlockData(sourcePosition)); // TODO: use getBlock here once the reflection is out of the way
final BaseBlock material = new BaseBlock(world.getBlockType(sourcePosition), world.getBlockData(sourcePosition));
// queue operation // queue operation
queue.put(position, material); queue.put(position, material);

View File

@ -0,0 +1,59 @@
package com.sk89q.worldedit;
import com.sk89q.worldedit.expression.runtime.ExpressionEnvironment;
class WorldEditExpressionEnvironment implements ExpressionEnvironment {
private final Vector unit;
private final Vector zero2;
private Vector current = new Vector();
private EditSession editSession;
public WorldEditExpressionEnvironment(EditSession editSession, Vector unit, Vector zero) {
this.editSession = editSession;
this.unit = unit;
this.zero2 = zero.add(0.5, 0.5, 0.5);
}
public BlockVector toWorld(double x, double y, double z) {
// unscale, unoffset, round-nearest
return new Vector(x, y, z).multiply(unit).add(zero2).toBlockPoint();
}
public Vector toWorldRel(double x, double y, double z) {
return current.add(x, y, z);
}
@Override
public int getBlockType(double x, double y, double z) {
return editSession.getBlockType(toWorld(x, y, z));
}
@Override
public int getBlockData(double x, double y, double z) {
return editSession.getBlockData(toWorld(x, y, z));
}
@Override
public int getBlockTypeAbs(double x, double y, double z) {
return editSession.getBlockType(new Vector(x, y, z));
}
@Override
public int getBlockDataAbs(double x, double y, double z) {
return editSession.getBlockData(new Vector(x, y, z));
}
@Override
public int getBlockTypeRel(double x, double y, double z) {
return editSession.getBlockType(toWorldRel(x, y, z));
}
@Override
public int getBlockDataRel(double x, double y, double z) {
return editSession.getBlockData(toWorldRel(x, y, z));
}
public void setCurrentBlock(Vector current) {
this.current = current;
}
}

View File

@ -24,9 +24,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Stack; import java.util.Stack;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.expression.lexer.Lexer; import com.sk89q.worldedit.expression.lexer.Lexer;
import com.sk89q.worldedit.expression.lexer.tokens.Token; import com.sk89q.worldedit.expression.lexer.tokens.Token;
import com.sk89q.worldedit.expression.parser.Parser; import com.sk89q.worldedit.expression.parser.Parser;
import com.sk89q.worldedit.expression.runtime.ExpressionEnvironment;
import com.sk89q.worldedit.expression.runtime.Constant; import com.sk89q.worldedit.expression.runtime.Constant;
import com.sk89q.worldedit.expression.runtime.EvaluationException; import com.sk89q.worldedit.expression.runtime.EvaluationException;
import com.sk89q.worldedit.expression.runtime.Functions; import com.sk89q.worldedit.expression.runtime.Functions;
@ -43,7 +46,7 @@ import com.sk89q.worldedit.expression.runtime.Variable;
* Arithmetic: +, -, *, /, % (modulo), ^ (power), - (unary), --, ++ (prefix only) * Arithmetic: +, -, *, /, % (modulo), ^ (power), - (unary), --, ++ (prefix only)
* Comparison: <=, >=, >, <, ==, !=, ~= (near) * Comparison: <=, >=, >, <, ==, !=, ~= (near)
* *
* Supported functions: abs, acos, asin, atan, atan2, cbrt, ceil, cos, cosh, exp, floor, ln, log, log10, max, max, min, min, rint, round, sin, sinh, sqrt, tan, tanh * Supported functions: abs, acos, asin, atan, atan2, cbrt, ceil, cos, cosh, exp, floor, ln, log, log10, max, max, min, min, rint, round, sin, sinh, sqrt, tan, tanh and more. (See the Functions class or the wiki)
* *
* Constants: e, pi * Constants: e, pi
* *
@ -65,6 +68,7 @@ public class Expression {
private final String[] variableNames; private final String[] variableNames;
private RValue root; private RValue root;
private final Functions functions = new Functions(); private final Functions functions = new Functions();
private ExpressionEnvironment environment;
public static Expression compile(String expression, String... variableNames) throws ExpressionException { public static Expression compile(String expression, String... variableNames) throws ExpressionException {
return new Expression(expression, variableNames); return new Expression(expression, variableNames);
@ -157,4 +161,12 @@ public class Expression {
public Functions getFunctions() { public Functions getFunctions() {
return functions; return functions;
} }
public ExpressionEnvironment getEnvironment() {
return environment;
}
public void setEnvironment(ExpressionEnvironment environment) {
this.environment = environment;
}
} }

View File

@ -0,0 +1,16 @@
package com.sk89q.worldedit.expression.runtime;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
/**
* Represents a way to access blocks in a world. Has to accept non-rounded coordinates.
*/
public interface ExpressionEnvironment {
int getBlockType(double x, double y, double z);
int getBlockData(double x, double y, double z);
int getBlockTypeAbs(double x, double y, double z);
int getBlockDataAbs(double x, double y, double z);
int getBlockTypeRel(double x, double y, double z);
int getBlockDataRel(double x, double y, double z);
}

View File

@ -375,4 +375,60 @@ public final class Functions {
public static double randint(RValue max) throws EvaluationException { public static double randint(RValue max) throws EvaluationException {
return random.nextInt((int) Math.floor(max.getValue())); return random.nextInt((int) Math.floor(max.getValue()));
} }
private static double queryInternal(LValue type, LValue data, double typeId, double dataValue) throws EvaluationException {
// Compare to input values and determine return value
final double ret = typeId == type.getValue() && typeId == type.getValue() ? 1.0 : 0.0;
type.assign(typeId);
data.assign(dataValue);
return ret;
}
@Dynamic
public static double query(RValue x, RValue y, RValue z, LValue type, LValue data) throws EvaluationException {
final double xp = x.getValue();
final double yp = y.getValue();
final double zp = z.getValue();
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
// Read values from world
final double typeId = environment.getBlockType(xp, yp, zp);
final double dataValue = environment.getBlockData(xp, yp, zp);
return queryInternal(type, data, typeId, dataValue);
}
@Dynamic
public static double queryAbs(RValue x, RValue y, RValue z, LValue type, LValue data) throws EvaluationException {
final double xp = x.getValue();
final double yp = y.getValue();
final double zp = z.getValue();
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
// Read values from world
final double typeId = environment.getBlockTypeAbs(xp, yp, zp);
final double dataValue = environment.getBlockDataAbs(xp, yp, zp);
return queryInternal(type, data, typeId, dataValue);
}
@Dynamic
public static double queryRel(RValue x, RValue y, RValue z, LValue type, LValue data) throws EvaluationException {
final double xp = x.getValue();
final double yp = y.getValue();
final double zp = z.getValue();
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
// Read values from world
final double typeId = environment.getBlockTypeRel(xp, yp, zp);
final double dataValue = environment.getBlockDataRel(xp, yp, zp);
return queryInternal(type, data, typeId, dataValue);
}
} }