Merge pull request #96 from PolyhedralDev/ver/5.1.0

Address several issues
This commit is contained in:
dfsek authored and GitHub committed 2021-03-17 10:53:32 -07:00
commit 2e8cd54ac2
38 files changed
+211 -732

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash import com.dfsek.terra.getGitHash
val versionObj = Version("5", "0", "0", true) val versionObj = Version("5", "1", "0", true)
allprojects { allprojects {
version = versionObj version = versionObj
@@ -6,4 +6,6 @@ public interface BlockType extends Handle {
BlockData getDefaultData(); BlockData getDefaultData();
boolean isSolid(); boolean isSolid();
boolean isWater();
} }
@@ -1,4 +1,4 @@
package com.dfsek.terra.api.world.tree; package com.dfsek.terra.api.platform.world;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
@@ -21,6 +21,7 @@ import com.dfsek.terra.api.structures.script.builders.RecursionsFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.SetMarkFunctionBuilder; import com.dfsek.terra.api.structures.script.builders.SetMarkFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder; 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.StructureFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryBooleanFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder; import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder; import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder; import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder;
@@ -58,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())
@@ -71,6 +73,7 @@ public class StructureScript {
.registerFunction("getBiome", new BiomeFunctionBuilder(main)) .registerFunction("getBiome", new BiomeFunctionBuilder(main))
.registerFunction("getBlock", new CheckBlockFunctionBuilder()) .registerFunction("getBlock", new CheckBlockFunctionBuilder())
.registerFunction("state", new StateFunctionBuilder(main)) .registerFunction("state", new StateFunctionBuilder(main))
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER)) .registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER))
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER)) .registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER))
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER)) .registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER))
@@ -146,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);
@@ -11,6 +11,7 @@ public class TerraImplementationArguments implements ImplementationArguments {
private final Rotation rotation; private final Rotation rotation;
private final Random random; private final Random random;
private final int recursions; private final int recursions;
private boolean waterlog = false;
public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, int recursions) { public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, int recursions) {
this.buffer = buffer; this.buffer = buffer;
@@ -34,4 +35,12 @@ public class TerraImplementationArguments implements ImplementationArguments {
public Rotation getRotation() { public Rotation getRotation() {
return rotation; return rotation;
} }
public boolean isWaterlog() {
return waterlog;
}
public void setWaterlog(boolean waterlog) {
this.waterlog = waterlog;
}
} }
@@ -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);
} }
@@ -0,0 +1,55 @@
package com.dfsek.terra.api.structures.script.builders;
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.functions.FunctionBuilder;
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.List;
import java.util.Map;
import java.util.function.BiConsumer;
public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Void>> {
private final BiConsumer<Boolean, TerraImplementationArguments> function;
public UnaryBooleanFunctionBuilder(BiConsumer<Boolean, TerraImplementationArguments> function) {
this.function = function;
}
@Override
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
return new Function<Void>() {
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
@SuppressWarnings("unchecked")
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
function.accept(((Returnable<Boolean>) argumentList.get(0)).apply(implementationArguments, variableMap), (TerraImplementationArguments) implementationArguments);
return null;
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.BOOLEAN;
return null;
}
}
@@ -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;
}
}
@@ -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), 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;
}
} }
@@ -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;
}
}
@@ -4,23 +4,30 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.data.Waterlogged;
public class BufferedBlock implements BufferedItem { public class BufferedBlock implements BufferedItem {
private final BlockData data; private final BlockData data;
private final boolean overwrite; private final boolean overwrite;
private final TerraPlugin main; private final TerraPlugin main;
private final boolean waterlog;
public BufferedBlock(BlockData data, boolean overwrite, TerraPlugin main) { public BufferedBlock(BlockData data, boolean overwrite, TerraPlugin main, boolean waterlog) {
this.data = data; this.data = data;
this.overwrite = overwrite; this.overwrite = overwrite;
this.main = main; this.main = main;
this.waterlog = waterlog;
} }
@Override @Override
public void paste(Location origin) { public void paste(Location origin) {
Block block = origin.getBlock(); Block block = origin.getBlock();
try { try {
if(overwrite || block.isEmpty()) block.setBlockData(data, false); if(overwrite || block.isEmpty()) {
if(waterlog && data instanceof Waterlogged && block.getBlockData().getBlockType().isWater())
((Waterlogged) data).setWaterlogged(true);
block.setBlockData(data, false);
}
} catch(RuntimeException e) { } catch(RuntimeException e) {
main.logger().severe("Failed to place block at location " + origin + ": " + e.getMessage()); main.logger().severe("Failed to place block at location " + origin + ": " + e.getMessage());
main.getDebugLogger().stack(e); main.getDebugLogger().stack(e);
@@ -1,32 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.entity.Entity;
import java.util.function.Consumer;
public class EntitySpawnHolder {
private final Location l;
private final Class<? extends Entity> e;
private final Consumer<Entity> c;
public EntitySpawnHolder(Location l, Class<? extends Entity> e, Consumer<Entity> c) {
this.l = l;
this.e = e;
this.c = c;
}
@SuppressWarnings("rawtypes")
public Class getEntity() {
return e;
}
public Consumer<Entity> getConsumer() {
return c;
}
public Location getLocation() {
return l;
}
}
@@ -1,48 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.util.collections.MaterialSet;
import java.util.Random;
import java.util.function.Consumer;
public abstract class FractalTree {
protected final TerraPlugin main;
public abstract MaterialSet getSpawnable();
/**
* Instantiates a TreeGrower at an origin location.
*/
public FractalTree(TerraPlugin plugin) {
this.main = plugin;
}
/**
* Sets a block in the tree's storage map to a material.
*
* @param l - The location to set.
* @param m - The material to which it will be set.
*/
public void setBlock(Location l, BlockData m) {
l.getBlock().setBlockData(m, false);
}
public TerraPlugin getMain() {
return main;
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
public abstract void grow(Location origin, Random random);
public void spawnEntity(Location spawn, EntityType type, Consumer<Entity> consumer) {
consumer.accept(spawn.getWorld().spawnEntity(spawn, type));
}
}
@@ -1,68 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import java.util.Random;
public class TreeGeometry {
private final FractalTree tree;
public TreeGeometry(FractalTree tree) {
this.tree = tree;
}
public static Vector3 getPerpendicular(Vector3 v) {
return v.getZ() < v.getX() ? new Vector3(v.getY(), -v.getX(), 0) : new Vector3(0, -v.getZ(), v.getY());
}
public FractalTree getTree() {
return tree;
}
public void generateSphere(Location l, BlockData m, int radius, boolean overwrite, Random r) {
generateSphere(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, overwrite, r);
}
public void generateCylinder(Location l, BlockData m, int radius, int height, boolean overwrite, Random r) {
generateCylinder(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, height, overwrite, r);
}
public void generateSphere(Location l, ProbabilityCollection<BlockData> m, int radius, boolean overwrite, Random r) {
for(int x = -radius; x <= radius; x++) {
for(int y = -radius; y <= radius; y++) {
for(int z = -radius; z <= radius; z++) {
Vector3 position = l.toVector().clone().add(new Vector3(x, y, z));
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
}
}
}
}
public void generateSponge(Location l, ProbabilityCollection<BlockData> m, int radius, boolean overwrite, int sponginess, Random r) {
for(int x = -radius; x <= radius; x++) {
for(int y = -radius; y <= radius; y++) {
for(int z = -radius; z <= radius; z++) {
Vector3 position = l.toVector().clone().add(new Vector3(x, y, z));
if(r.nextInt(100) < sponginess && l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
}
}
}
}
public void generateCylinder(Location l, ProbabilityCollection<BlockData> m, int radius, int height, boolean overwrite, Random r) {
for(int x = -radius; x <= radius; x++) {
for(int y = 0; y <= height; y++) {
for(int z = -radius; z <= radius; z++) {
Vector3 position = l.toVector().clone().add(new Vector3(x, 0, z));
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
}
}
}
}
}
@@ -1,35 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import java.util.Random;
public class Cactus extends FractalTree {
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:sand"),
main.getWorldHandle().createBlockData("minecraft:red_sand"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public Cactus(TerraPlugin main) {
super(main);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
BlockData cactus = getMain().getWorldHandle().createBlockData("minecraft:cactus");
int h = random.nextInt(4) + 1;
for(int i = 0; i < h; i++) setBlock(origin.clone().add(0, i, 0), cactus);
}
}
@@ -1,57 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.TreeGeometry;
import java.util.Random;
public class IceSpike extends FractalTree {
private final TreeGeometry geo;
private final ProbabilityCollection<BlockData> ice;
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:stone"),
main.getWorldHandle().createBlockData("minecraft:gravel"),
main.getWorldHandle().createBlockData("minecraft:snow_block"),
main.getWorldHandle().createBlockData("minecraft:grass_block"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public IceSpike(TerraPlugin main) {
super(main);
geo = new TreeGeometry(this);
WorldHandle handle = main.getWorldHandle();
ice = new ProbabilityCollection<BlockData>().add(handle.createBlockData("minecraft:packed_ice"), 95).add(handle.createBlockData("minecraft:blue_ice"), 5);
}
private double getOffset(Random r) {
return (r.nextDouble() - 0.5D);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
Vector3 direction = new Vector3(getOffset(random), 0, getOffset(random));
Location l1 = origin.clone();
int h = random.nextInt(16) + 8;
for(int i = 0; i < h; i++) {
geo.generateSponge(l1.clone().add(0, i, 0).add(direction.clone().multiply(i)), ice, (int) ((1 - ((double) i / h)) * 2 + 1), true, 80, random);
}
for(int i = 0; i < h / 3; i++) {
setBlock(l1.clone().add(0, h + i, 0).add(direction.clone().multiply(h + i)), ice.get(random));
}
}
}
@@ -1,66 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.TreeGeometry;
import net.jafama.FastMath;
import java.util.Random;
public class OakTree extends FractalTree {
private final TreeGeometry geo;
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:podzol"),
main.getWorldHandle().createBlockData("minecraft:grass_block"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public OakTree(TerraPlugin main) {
super(main);
geo = new TreeGeometry(this);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(4) + 6, random.nextInt(5) - 2), 2, 0, random);
}
private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) {
BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:oak_wood");
BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:oak_leaves");
if(recursions > 1) {
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false, r);
if(recursions > 2) return;
}
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
int d = (int) diff.length();
for(int i = 0; i < d; i++) {
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, FastMath.max((int) d1, 0), true, r);
}
double runningAngle = (double) 45 / (recursions + 1);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
}
private int getNoise(Random r) {
return r.nextInt(60) - 30;
}
}
@@ -1,56 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import java.util.Random;
public class ShatteredPillar extends FractalTree {
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public ShatteredPillar(TerraPlugin main) {
super(main);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
* @param origin
* @param random
*/
@Override
public void grow(Location origin, Random random) {
BlockData obsidian = getMain().getWorldHandle().createBlockData("minecraft:obsidian");
int h = random.nextInt(5) + 8;
int max = h;
for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 0), obsidian);
h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1));
int[] crystalLoc = new int[] {0, 0};
if(h > max) {
max = h;
crystalLoc = new int[] {1, 0};
}
for(int i = -h; i < h; i++) setBlock(origin.clone().add(1, i, 0), obsidian);
h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1));
if(h > max) {
max = h;
crystalLoc = new int[] {0, 1};
}
for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 1), obsidian);
h = h + (random.nextBoolean() ? random.nextInt(3) + 1 : -(random.nextInt(3) + 1));
if(h > max) {
max = h;
crystalLoc = new int[] {1, 1};
}
for(int i = -h; i < h; i++) setBlock(origin.clone().add(1, i, 1), obsidian);
}
}
@@ -1,75 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.TreeGeometry;
import net.jafama.FastMath;
import java.util.Random;
public class ShatteredTree extends FractalTree {
private final TreeGeometry geo;
private final ProbabilityCollection<BlockData> bark;
private final ProbabilityCollection<BlockData> leaves;
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public ShatteredTree(TerraPlugin main) {
super(main);
geo = new TreeGeometry(this);
WorldHandle handle = main.getWorldHandle();
bark = new ProbabilityCollection<BlockData>()
.add(handle.createBlockData("minecraft:obsidian"), 1)
.add(handle.createBlockData("minecraft:black_concrete"), 1);
leaves = new ProbabilityCollection<BlockData>()
.add(handle.createBlockData("minecraft:purple_stained_glass"), 1)
.add(handle.createBlockData("minecraft:magenta_stained_glass"), 1);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(4) + 6, random.nextInt(5) - 2), 1, 0, random);
}
private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) {
if(recursions > 2) {
geo.generateSphere(l1, leaves, 1 + r.nextInt(2), false, r);
return;
}
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
int d = (int) diff.length();
for(int i = 0; i < d; i++) {
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true, r);
}
double runningAngle = (double) 45 / (recursions + 1);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
}
private int getNoise(Random r) {
return r.nextInt(90) - 45;
}
}
@@ -1,36 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import java.util.Random;
public class SmallShatteredPillar extends FractalTree {
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public SmallShatteredPillar(TerraPlugin main) {
super(main);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
* @param origin
* @param random
*/
@Override
public void grow(Location origin, Random random) {
int h = random.nextInt(5) + 5;
BlockData obsidian = getMain().getWorldHandle().createBlockData("minecraft:obsidian");
for(int i = -h; i < h; i++) setBlock(origin.clone().add(0, i, 0), obsidian);
}
}
@@ -1,75 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.TreeGeometry;
import net.jafama.FastMath;
import java.util.Random;
public class SmallShatteredTree extends FractalTree {
private final TreeGeometry geo;
private final ProbabilityCollection<BlockData> bark;
private final ProbabilityCollection<BlockData> leaves;
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:end_stone"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public SmallShatteredTree(TerraPlugin main) {
super(main);
geo = new TreeGeometry(this);
WorldHandle handle = main.getWorldHandle();
bark = new ProbabilityCollection<BlockData>()
.add(handle.createBlockData("minecraft:obsidian"), 1)
.add(handle.createBlockData("minecraft:black_concrete"), 1);
leaves = new ProbabilityCollection<BlockData>()
.add(handle.createBlockData("minecraft:purple_stained_glass"), 1)
.add(handle.createBlockData("minecraft:magenta_stained_glass"), 1);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
growBranch(origin.clone(), new Vector3(random.nextInt(5) - 2, random.nextInt(3) + 4, random.nextInt(5) - 2), 1.5, 0, random);
}
private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) {
if(recursions > 2) {
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false, r);
return;
}
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
int d = (int) diff.length();
for(int i = 0; i < d; i++) {
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true, r);
}
double runningAngle = (double) 45 / (recursions + 1);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundZ(FastMath.toRadians(-runningAngle + getNoise(r))).rotateAroundX(FastMath.toRadians(getNoise(r))),
d1 - 1, recursions + 1, r);
}
private int getNoise(Random r) {
return r.nextInt(90) - 45;
}
}
@@ -1,53 +0,0 @@
package com.dfsek.terra.api.world.tree.fractal.trees;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.TreeGeometry;
import net.jafama.FastMath;
import java.util.Random;
public class SpruceTree extends FractalTree {
private final TreeGeometry geo;
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:podzol"),
main.getWorldHandle().createBlockData("minecraft:grass_block"));
}
/**
* Instantiates a TreeGrower at an origin location.
*/
public SpruceTree(TerraPlugin main) {
super(main);
geo = new TreeGeometry(this);
}
/**
* Grows the tree in memory. Intended to be invoked from an async thread.
*/
@Override
public void grow(Location origin, Random random) {
growTrunk(origin.clone(), new Vector3(0, 16 + random.nextInt(5), 0), random);
}
private void growTrunk(Location l1, Vector3 diff, Random r) {
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
int d = (int) diff.length();
int rad = 7;
BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:spruce_wood");
BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:spruce_leave");
for(int i = 0; i < d; i++) {
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, (int) ((i > d * 0.65) ? 0.5 : 1.5), true, r);
if(i > 3)
geo.generateCylinder(l1.clone().add(diff.clone().multiply((double) i / d)), leaves, (int) (((6 - (i % 4))) * (1.25 - ((double) i / d))), 1, false, r);
}
setBlock(l1.clone().add(diff), leaves);
setBlock(l1.clone().add(diff).add(0, 1, 0), leaves);
}
}
@@ -1,7 +1,7 @@
package com.dfsek.terra.config.factories; package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.config.templates.TreeTemplate; import com.dfsek.terra.config.templates.TreeTemplate;
import com.dfsek.terra.world.population.items.tree.TerraTree; import com.dfsek.terra.world.population.items.tree.TerraTree;
@@ -1,11 +1,11 @@
package com.dfsek.terra.config.loaders; package com.dfsek.terra.config.loaders;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
@@ -5,9 +5,9 @@ import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader; import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.config.loaders.Types; import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.world.population.items.tree.TreeLayer; import com.dfsek.terra.world.population.items.tree.TreeLayer;
@@ -12,6 +12,7 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structures.loot.LootTable; import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
@@ -20,7 +21,6 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.dummy.DummyWorld; import com.dfsek.terra.config.dummy.DummyWorld;
@@ -120,7 +120,7 @@ public class ConfigPack implements LoaderRegistrar {
long l = System.nanoTime(); long l = System.nanoTime();
floraRegistry = new FloraRegistry(main); floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main); paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main); treeRegistry = new TreeRegistry();
register(abstractConfigLoader); register(abstractConfigLoader);
register(selfLoader); register(selfLoader);
@@ -156,7 +156,7 @@ public class ConfigPack implements LoaderRegistrar {
long l = System.nanoTime(); long l = System.nanoTime();
floraRegistry = new FloraRegistry(main); floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main); paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main); treeRegistry = new TreeRegistry();
register(abstractConfigLoader); register(abstractConfigLoader);
register(selfLoader); register(selfLoader);
@@ -1,19 +1,15 @@
package com.dfsek.terra.config.pack; package com.dfsek.terra.config.pack;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.registry.LockedRegistry; import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.structures.loot.LootTable; import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.registry.OpenRegistry;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
@@ -22,7 +18,6 @@ import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore; import com.dfsek.terra.world.population.items.ores.Ore;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
public class WorldConfig { public class WorldConfig {
private final LockedRegistry<StructureScript> scriptRegistry; private final LockedRegistry<StructureScript> scriptRegistry;
@@ -1,77 +1,11 @@
package com.dfsek.terra.registry.config; package com.dfsek.terra.registry.config;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.api.world.tree.fractal.FractalTree;
import com.dfsek.terra.api.world.tree.fractal.trees.Cactus;
import com.dfsek.terra.api.world.tree.fractal.trees.IceSpike;
import com.dfsek.terra.api.world.tree.fractal.trees.OakTree;
import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredPillar;
import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredTree;
import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredPillar;
import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredTree;
import com.dfsek.terra.api.world.tree.fractal.trees.SpruceTree;
import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.registry.OpenRegistry;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Random;
public class TreeRegistry extends OpenRegistry<Tree> { public class TreeRegistry extends OpenRegistry<Tree> {
private final TerraPlugin main;
public TreeRegistry(TerraPlugin main) {
this.main = main;
tryAdd("CACTUS", Cactus.class);
tryAdd("GIANT_OAK", OakTree.class);
tryAdd("GIANT_SPRUCE", SpruceTree.class);
tryAdd("LARGE_SHATTERED_PILLAR", ShatteredPillar.class);
tryAdd("SHATTERED_LARGE", ShatteredTree.class);
tryAdd("SHATTERED_SMALL", SmallShatteredTree.class);
tryAdd("SMALL_SHATTERED_PILLAR", SmallShatteredPillar.class);
tryAdd("ICE_SPIKE", IceSpike.class);
}
private void tryAdd(String id, Class<? extends FractalTree> value) {
try {
add(id, new FractalTreeHolder(value));
} catch(Exception e) {
main.logger().warning("Unable to load tree " + id + ": " + e.getMessage());
}
}
@Override @Override
public boolean add(String identifier, Tree value) { public boolean add(String identifier, Tree value) {
return super.add(identifier, value); return super.add(identifier, value);
} }
private final class FractalTreeHolder implements Tree {
private final FractalTree tree;
private FractalTreeHolder(Class<? extends FractalTree> clazz) throws NoSuchMethodException {
Constructor<? extends FractalTree> constructor = clazz.getConstructor(TerraPlugin.class);
try {
tree = constructor.newInstance(main);
} catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
throw new IllegalArgumentException("Unable to load tree: " + clazz);
}
}
@Override
public boolean plant(Location l, Random r) {
if(!getSpawnable().contains(l.getBlock().getType())) return false;
if(!l.getBlock().getRelative(BlockFace.UP).isEmpty()) return false;
tree.grow(l.add(0, 1, 0), r);
return true;
}
@Override
public MaterialSet getSpawnable() {
return tree.getSpawnable();
}
}
} }
@@ -1,11 +1,11 @@
package com.dfsek.terra.world.population.items.tree; package com.dfsek.terra.world.population.items.tree;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.tree.Tree;
import java.util.Random; import java.util.Random;
@@ -6,9 +6,9 @@ import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.world.PopulationUtil; import com.dfsek.terra.api.util.world.PopulationUtil;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.world.population.items.PlaceableLayer; import com.dfsek.terra.world.population.items.PlaceableLayer;
public class TreeLayer extends PlaceableLayer<Tree> { public class TreeLayer extends PlaceableLayer<Tree> {
@@ -2,13 +2,12 @@ package com.dfsek.terra.bukkit.listeners;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.transform.MapTransform; import com.dfsek.terra.api.transform.MapTransform;
import com.dfsek.terra.api.transform.Transformer; import com.dfsek.terra.api.transform.Transformer;
import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig; import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
import org.bukkit.Material; import org.bukkit.Material;
@@ -3,8 +3,8 @@ package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.Tree;
import org.bukkit.TreeType; import org.bukkit.TreeType;
import java.util.Random; import java.util.Random;
@@ -29,6 +29,11 @@ public class BukkitBlockTypeAndItem implements BlockType, Item {
return delegate.isSolid(); return delegate.isSolid();
} }
@Override
public boolean isWater() {
return delegate == Material.WATER;
}
@Override @Override
public ItemStack newItemStack(int amount) { public ItemStack newItemStack(int amount) {
return BukkitAdapter.adapt(new org.bukkit.inventory.ItemStack(delegate, amount)); return BukkitAdapter.adapt(new org.bukkit.inventory.ItemStack(delegate, amount));
@@ -20,6 +20,7 @@ import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry; import com.dfsek.terra.api.registry.LockedRegistry;
@@ -27,7 +28,6 @@ import com.dfsek.terra.api.transform.NotNullValidator;
import com.dfsek.terra.api.transform.Transformer; import com.dfsek.terra.api.transform.Transformer;
import com.dfsek.terra.api.util.logging.DebugLogger; import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger; import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig; import com.dfsek.terra.config.PluginConfig;
@@ -1,8 +1,8 @@
package com.dfsek.terra.fabric.world; package com.dfsek.terra.fabric.world;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator; import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
@@ -4,6 +4,7 @@ import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
public class FabricBlockType implements BlockType { public class FabricBlockType implements BlockType {
private final Block delegate; private final Block delegate;
@@ -27,6 +28,11 @@ public class FabricBlockType implements BlockType {
return delegate.getDefaultState().isOpaque(); return delegate.getDefaultState().isOpaque();
} }
@Override
public boolean isWater() {
return delegate == Blocks.WATER;
}
@Override @Override
public int hashCode() { public int hashCode() {
return delegate.hashCode(); return delegate.hashCode();
@@ -97,4 +97,9 @@ public class Data implements BlockData, BlockType {
public boolean isSolid() { public boolean isSolid() {
return false; return false;
} }
@Override
public boolean isWater() {
return false;
}
} }
@@ -1,8 +1,8 @@
package com.dfsek.terra.platform; package com.dfsek.terra.platform;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.tree.Tree;
import java.util.Random; import java.util.Random;