implement DynamicBlockFunction

This commit is contained in:
dfsek 2021-03-16 21:20:02 -07:00
parent 5028582198
commit cda2d4688c
5 changed files with 101 additions and 40 deletions

View File

@ -59,7 +59,8 @@ public class StructureScript {
functionRegistry.forEach(parser::registerFunction); // Register registry functions. functionRegistry.forEach(parser::registerFunction); // Register registry functions.
parser.registerFunction("block", new BlockFunctionBuilder(main)) parser.registerFunction("block", new BlockFunctionBuilder(main, false))
.registerFunction("dynamicBlock", new BlockFunctionBuilder(main, true))
.registerFunction("check", new CheckFunctionBuilder(main)) .registerFunction("check", new CheckFunctionBuilder(main))
.registerFunction("structure", new StructureFunctionBuilder(registry, main)) .registerFunction("structure", new StructureFunctionBuilder(registry, main))
.registerFunction("randomInt", new RandomFunctionBuilder()) .registerFunction("randomInt", new RandomFunctionBuilder())
@ -148,7 +149,7 @@ public class StructureScript {
private boolean applyBlock(TerraImplementationArguments arguments) { private boolean applyBlock(TerraImplementationArguments arguments) {
try { try {
return !block.apply(arguments).getLevel().equals(Block.ReturnLevel.FAIL); return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL;
} catch(RuntimeException e) { } catch(RuntimeException e) {
main.logger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); main.logger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage());
main.getDebugLogger().stack(e); main.getDebugLogger().stack(e);

View File

@ -5,24 +5,30 @@ import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.AbstractBlockFunction;
import com.dfsek.terra.api.structures.script.functions.BlockFunction; import com.dfsek.terra.api.structures.script.functions.BlockFunction;
import com.dfsek.terra.api.structures.script.functions.DynamicBlockFunction;
import com.dfsek.terra.api.structures.tokenizer.Position; import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List; import java.util.List;
public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> { public class BlockFunctionBuilder implements FunctionBuilder<AbstractBlockFunction> {
private final TerraPlugin main; private final TerraPlugin main;
private final boolean dynamic;
public BlockFunctionBuilder(TerraPlugin main) { public BlockFunctionBuilder(TerraPlugin main, boolean dynamic) {
this.main = main; this.main = main;
this.dynamic = dynamic;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public BlockFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException { public AbstractBlockFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
if(argumentList.size() < 4) throw new ParseException("Expected data", position); if(argumentList.size() < 4) throw new ParseException("Expected data", position);
Returnable<Boolean> booleanReturnable = new BooleanConstant(true, position); Returnable<Boolean> booleanReturnable = new BooleanConstant(true, position);
if(argumentList.size() == 5) booleanReturnable = (Returnable<Boolean>) argumentList.get(4); if(argumentList.size() == 5) booleanReturnable = (Returnable<Boolean>) argumentList.get(4);
if(dynamic)
return new DynamicBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position);
return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position); return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position);
} }

View File

@ -0,0 +1,54 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public abstract class AbstractBlockFunction implements Function<Void> {
protected final Returnable<Number> x, y, z;
protected final Returnable<String> blockData;
protected final TerraPlugin main;
private final Returnable<Boolean> overwrite;
private final Position position;
protected AbstractBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
this.x = x;
this.y = y;
this.z = z;
this.blockData = blockData;
this.overwrite = overwrite;
this.main = main;
this.position = position;
}
void setBlock(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap, TerraImplementationArguments arguments, BlockData rot) {
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}

View File

@ -1,67 +1,36 @@
package com.dfsek.terra.api.structures.script.functions; package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable; import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments; import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock;
import com.dfsek.terra.api.structures.tokenizer.Position; import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map; import java.util.Map;
public class BlockFunction implements Function<Void> { public class BlockFunction extends AbstractBlockFunction {
private final BlockData data; private final BlockData data;
private final Returnable<Number> x, y, z;
private final Position position;
private final Returnable<Boolean> overwrite;
private final TerraPlugin main;
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Returnable<Boolean> overwrite, TerraPlugin main, Position position) throws ParseException { public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Returnable<Boolean> overwrite, TerraPlugin main, Position position) throws ParseException {
this.position = position; super(x, y, z, data, overwrite, main, position);
this.main = main;
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
try { try {
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant()); this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
} catch(IllegalArgumentException e) { } catch(IllegalArgumentException e) {
throw new ParseException("Could not parse block data", data.getPosition(), e); throw new ParseException("Could not parse block data", data.getPosition(), e);
} }
this.x = x;
this.y = y;
this.z = z;
this.overwrite = overwrite;
} }
@Override @Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) { public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
BlockData rot = data.clone(); BlockData rot = data.clone();
setBlock(implementationArguments, variableMap, arguments, rot);
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null; return null;
} }
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
} }

View File

@ -0,0 +1,31 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.HashMap;
import java.util.Map;
public class DynamicBlockFunction extends AbstractBlockFunction {
private final Map<String, BlockData> data = new HashMap<>();
private final Position position;
public DynamicBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
super(x, y, z, data, overwrite, main, position);
this.position = position;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
BlockData rot = data.computeIfAbsent(blockData.apply(implementationArguments, variableMap), main.getWorldHandle()::createBlockData).clone();
setBlock(implementationArguments, variableMap, arguments, rot);
return null;
}
}