implement StateFunction

This commit is contained in:
dfsek
2021-01-05 01:04:15 -07:00
parent aec1d671fa
commit a38eba2916
14 changed files with 306 additions and 32 deletions

View File

@@ -16,4 +16,8 @@ public interface BlockState extends Handle {
BlockData getBlockData();
boolean update(boolean applyPhysics);
default void applyState(String state) {
// Do nothing by default.
}
}

View File

@@ -0,0 +1,38 @@
package com.dfsek.terra.api.platform.block.state;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import org.jetbrains.annotations.NotNull;
public interface MobSpawner extends BlockState {
EntityType getSpawnedType();
void setSpawnedType(@NotNull EntityType creatureType);
int getDelay();
void setDelay(int delay);
int getMinSpawnDelay();
void setMinSpawnDelay(int delay);
int getMaxSpawnDelay();
void setMaxSpawnDelay(int delay);
int getSpawnCount();
void setSpawnCount(int spawnCount);
int getMaxNearbyEntities();
void setMaxNearbyEntities(int maxNearbyEntities);
int getRequiredPlayerRange();
void setRequiredPlayerRange(int requiredPlayerRange);
int getSpawnRange();
void setSpawnRange(int spawnRange);
}

View File

@@ -0,0 +1,94 @@
package com.dfsek.terra.api.platform.block.state;
import java.util.HashMap;
import java.util.Map;
public class SerialState {
protected final Map<String, Property<?>> properties = new HashMap<>();
public SerialState() {
}
public static Map<String, String> parse(String props) {
String[] sep = props.split(",");
Map<String, String> map = new HashMap<>();
for(String item : sep) {
map.put(item.substring(0, item.indexOf('=')), item.substring(item.indexOf('=') + 1));
}
return map;
}
private void checkExists(String prop) {
if(!properties.containsKey(prop)) throw new IllegalArgumentException("No such property \"" + prop + "\"");
}
private void checkType(Class<?> clazz, Object o, String id) {
if(!clazz.isInstance(o))
throw new IllegalArgumentException("Invalid data for property " + id + ": " + o);
}
public void setProperty(String id, Object value) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(prop.getValueClass(), value, id);
prop.setValue(value);
}
public int getInteger(String id) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(Integer.class, prop.getValue(), id);
return (Integer) prop.getValue();
}
public String getString(String id) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(String.class, prop.getValue(), id);
return (String) prop.getValue();
}
public long getLong(String id) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(Long.class, prop.getValue(), id);
return (Long) prop.getValue();
}
public boolean getBoolean(String id) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(Boolean.class, prop.getValue(), id);
return (Boolean) prop.getValue();
}
@SuppressWarnings("unchecked")
public <T> T get(String id, Class<T> clazz) {
checkExists(id);
Property<?> prop = properties.get(id);
checkType(clazz, prop.getValue(), id);
return (T) prop.getValue();
}
protected static class Property<T> {
private final Class<T> clazz;
private Object value;
public Property(Class<T> clazz) {
this.clazz = clazz;
}
public Class<T> getValueClass() {
return clazz;
}
@SuppressWarnings("unchecked")
public T getValue() {
return (T) value;
}
public void setValue(Object value) {
this.value = value;
}
}
}

View File

@@ -0,0 +1,11 @@
package com.dfsek.terra.api.platform.block.state;
import org.jetbrains.annotations.NotNull;
public interface Sign extends BlockState {
@NotNull String[] getLines();
@NotNull String getLine(int index) throws IndexOutOfBoundsException;
void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
}

View File

@@ -18,6 +18,7 @@ import com.dfsek.terra.api.structures.script.builders.MarkFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.PullFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.RandomFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.RecursionsFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder;
@@ -63,6 +64,7 @@ public class StructureScript {
.registerFunction("entity", new EntityFunctionBuilder(main))
.registerFunction("getBiome", new BiomeFunctionBuilder(main))
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
.registerFunction("state", new StateFunctionBuilder(main))
.registerFunction("print", new UnaryStringFunctionBuilder(string -> Debug.info("[" + tempID + "] " + string)))
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue())))
.registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))

View File

@@ -0,0 +1,44 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
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.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.StateFunction;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List;
public class StateFunctionBuilder implements FunctionBuilder<StateFunction> {
private final TerraPlugin main;
public StateFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public StateFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
return new StateFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {
case 0:
case 1:
case 2:
return Returnable.ReturnType.NUMBER;
case 3:
return Returnable.ReturnType.STRING;
default:
return null;
}
}
}

View File

@@ -0,0 +1,49 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
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.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedStateManipulator;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
public class StateFunction implements Function<Void> {
private final Returnable<String> data;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
public StateFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) {
this.position = position;
this.main = main;
this.data = data;
this.x = x;
this.y = y;
this.z = z;
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}

View File

@@ -0,0 +1,26 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.state.BlockState;
public class BufferedStateManipulator implements BufferedItem {
private final TerraPlugin main;
private final String data;
public BufferedStateManipulator(TerraPlugin main, String state) {
this.main = main;
this.data = state;
}
@Override
public void paste(Location origin) {
BlockState state = origin.getBlock().getState();
try {
state.applyState(data);
state.update(false);
} catch(ClassCastException e) {
main.getLogger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage());
}
}
}

View File

@@ -1,27 +0,0 @@
package com.dfsek.terra.api.structures.structure.buffer.items.state;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem;
@SuppressWarnings("unchecked")
public abstract class BufferedStateManipulator<T extends BlockState> implements BufferedItem {
private final TerraPlugin main;
protected BufferedStateManipulator(TerraPlugin main) {
this.main = main;
}
@Override
public void paste(Location origin) {
BlockState state = origin.getBlock().getState();
try {
apply((T) state);
} catch(ClassCastException e) {
main.getLogger().warning("Could not find expected BlockState at " + origin + "; found " + origin.getBlock().getBlockData().getAsString());
}
}
public abstract void apply(T state);
}

View File

@@ -22,13 +22,11 @@ public class TerraTree implements Tree {
@Override
public synchronized boolean plant(Location location, Random random) {
structure.get(random).execute(location.clone().add(0, yOffset, 0), random, Rotation.fromDegrees(90 * random.nextInt(4)));
return true;
return structure.get(random).execute(location.clone().add(0, yOffset, 0), random, Rotation.fromDegrees(90 * random.nextInt(4)));
}
@Override
public MaterialSet getSpawnable() {
return spawnable;
}
}

View File

@@ -55,8 +55,7 @@ public class EventListener implements Listener {
TreeRegistry registry = c.getTreeRegistry();
Tree tree = registry.get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies()));
Debug.info("Overrode tree type: " + e.getSpecies());
org.bukkit.Location location = e.getLocation().subtract(0, 1, 0);
org.bukkit.Location location = e.getLocation();
if(!tree.plant(new Location(bukkit, location.getX(), location.getY(), location.getZ()), new FastRandom())) block.setBlockData(data);
}
}

View File

@@ -6,6 +6,7 @@ import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.bukkit.world.block.BukkitBlock;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData;
import org.bukkit.block.Container;
import org.bukkit.block.Sign;
public class BukkitBlockState implements BlockState {
private final org.bukkit.block.BlockState delegate;
@@ -16,6 +17,7 @@ public class BukkitBlockState implements BlockState {
public static BukkitBlockState newInstance(org.bukkit.block.BlockState block) {
if(block instanceof Container) return new BukkitContainer((Container) block);
if(block instanceof Sign) return new BukkitSign((Sign) block);
return new BukkitBlockState(block);
}

View File

@@ -5,6 +5,7 @@ import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.bukkit.world.inventory.BukkitInventory;
public class BukkitContainer extends BukkitBlockState implements Container {
protected BukkitContainer(org.bukkit.block.Container block) {
super(block);
}
@@ -13,4 +14,5 @@ public class BukkitContainer extends BukkitBlockState implements Container {
public Inventory getInventory() {
return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory());
}
}

View File

@@ -0,0 +1,32 @@
package com.dfsek.terra.bukkit.world.block.state;
import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.block.state.Sign;
import org.jetbrains.annotations.NotNull;
public class BukkitSign extends BukkitBlockState implements Sign {
protected BukkitSign(org.bukkit.block.Sign block) {
super(block);
}
@Override
public @NotNull String[] getLines() {
return ((org.bukkit.block.Sign) getHandle()).getLines();
}
@Override
public @NotNull String getLine(int index) throws IndexOutOfBoundsException {
return ((org.bukkit.block.Sign) getHandle()).getLine(index);
}
@Override
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
((org.bukkit.block.Sign) getHandle()).setLine(index, line);
}
@Override
public void applyState(String state) {
SerialState.parse(state).forEach((k, v) -> setLine(Integer.parseInt(k), v));
}
}