diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java index 77c2eaf7c..dad7aa6f3 100644 --- a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java @@ -7,17 +7,18 @@ import com.dfsek.terra.api.config.ConfigFactory; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigType; import com.dfsek.terra.api.registry.OpenRegistry; +import com.dfsek.terra.api.structure.Structure; import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.world.Flora; -public class FloraConfigType implements ConfigType { - public static final TypeKey FLORA_TYPE_TOKEN = new TypeKey<>() { +public class FloraConfigType implements ConfigType { + public static final TypeKey FLORA_TYPE_TOKEN = new TypeKey<>() { }; private final FloraFactory factory = new FloraFactory(); @Override - public Supplier> registrySupplier(ConfigPack pack) { + public Supplier> registrySupplier(ConfigPack pack) { return pack.getRegistryFactory()::create; } @@ -27,12 +28,12 @@ public class FloraConfigType implements ConfigType { } @Override - public ConfigFactory getFactory() { + public ConfigFactory getFactory() { return factory; } @Override - public TypeKey getTypeKey() { + public TypeKey getTypeKey() { return FLORA_TYPE_TOKEN; } } diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java index 88b6ebcd9..318a569ff 100644 --- a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java @@ -3,14 +3,14 @@ package com.dfsek.terra.addons.flora; import com.dfsek.terra.addons.flora.flora.gen.TerraFlora; import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.config.ConfigFactory; -import com.dfsek.terra.api.world.Flora; +import com.dfsek.terra.api.structure.Structure; -public class FloraFactory implements ConfigFactory { +public class FloraFactory implements ConfigFactory { @Override public TerraFlora build(FloraTemplate config, TerraPlugin main) { - return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), - config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), - config.isSpawnBlacklist(), config.getIrrigableOffset(), main, config.getNoiseDistribution()); + return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), + config.getRotatable(), + config.getNoiseDistribution(), config.getID()); } } diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java index f58d64341..78b76ddda 100644 --- a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java @@ -19,23 +19,6 @@ public class FloraTemplate implements AbstractableTemplate { @Value("id") @Final private String id; - - @Value("spawnable") - private @Meta MaterialSet spawnable; - - @Value("spawn-blacklist") - @Default - private @Meta boolean spawnBlacklist = false; - - - @Value("replaceable") - @Default - private @Meta MaterialSet replaceable = MaterialSet.empty(); - - @Value("irrigable") - @Default - private @Meta MaterialSet irrigable; - @Value("rotatable") @Default private @Meta MaterialSet rotatable = MaterialSet.empty(); @@ -48,18 +31,6 @@ public class FloraTemplate implements AbstractableTemplate { @Default private @Meta boolean ceiling = false; - @Value("search") - @Default - private TerraFlora.@Meta Search search = TerraFlora.Search.UP; - - @Value("max-placements") - @Default - private @Meta int maxPlacements = -1; - - @Value("irrigable-offset") - @Default - private @Meta int irrigableOffset; - @Value("layers") private @Meta List<@Meta BlockLayer> layers; @@ -78,30 +49,6 @@ public class FloraTemplate implements AbstractableTemplate { return layers; } - public int getIrrigableOffset() { - return irrigableOffset; - } - - public TerraFlora.Search getSearch() { - return search; - } - - public int getMaxPlacements() { - return maxPlacements; - } - - public MaterialSet getReplaceable() { - return replaceable; - } - - public MaterialSet getSpawnable() { - return spawnable; - } - - public MaterialSet getIrrigable() { - return irrigable; - } - public String getID() { return id; } @@ -110,10 +57,6 @@ public class FloraTemplate implements AbstractableTemplate { return ceiling; } - public boolean isSpawnBlacklist() { - return spawnBlacklist; - } - public MaterialSet getRotatable() { return rotatable; } diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java index eb778728a..214181848 100644 --- a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java @@ -7,60 +7,40 @@ import java.util.EnumSet; import java.util.List; import java.util.Random; -import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.properties.base.Properties; import com.dfsek.terra.api.block.state.properties.enums.Direction; import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.buffer.Buffer; +import com.dfsek.terra.api.structure.rotation.Rotation; import com.dfsek.terra.api.util.collection.MaterialSet; import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.world.Chunk; -import com.dfsek.terra.api.world.Flora; import com.dfsek.terra.api.world.World; -public class TerraFlora implements Flora { +public class TerraFlora implements Structure { private final List> layers; private final boolean physics; private final boolean ceiling; - private final MaterialSet irrigable; - - private final MaterialSet spawnable; - private final MaterialSet replaceable; - private final MaterialSet testRotation; - private final int maxPlacements; - - private final Search search; - - private final boolean spawnBlacklist; - - private final int irrigableOffset; - - private final TerraPlugin main; - private final NoiseSampler distribution; - public TerraFlora(List layers, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, - MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, - int irrigableOffset, TerraPlugin main, NoiseSampler distribution) { + private final String id; + + public TerraFlora(List layers, boolean physics, boolean ceiling, + MaterialSet testRotation, + NoiseSampler distribution, String id) { this.physics = physics; this.testRotation = testRotation; - this.spawnBlacklist = spawnBlacklist; this.ceiling = ceiling; - this.irrigable = irrigable; - this.spawnable = spawnable; - this.replaceable = replaceable; - this.maxPlacements = maxPlacements; - this.search = search; - this.irrigableOffset = irrigableOffset; - this.main = main; this.distribution = distribution; - + this.id = id; + this.layers = new ArrayList<>(); layers.forEach(layer -> { for(int i = 0; i < layer.getLayers(); i++) { @@ -69,78 +49,12 @@ public class TerraFlora implements Flora { }); } - @Override - public boolean plant(Vector3 location, World world) { - boolean doRotation = testRotation.size() > 0; - int size = layers.size(); - int c = ceiling ? -1 : 1; - - EnumSet faces = doRotation ? getFaces(location.clone().add(0, c, 0), world) : EnumSet.noneOf(Direction.class); - if(doRotation && faces.size() == 0) return false; // Don't plant if no faces are valid. - - for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor - int lvl = (FastMath.abs(i)); - BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), - location.getZ(), world.getSeed()).clone(); - if(doRotation) { - Direction oneFace = new ArrayList<>(faces).get( - new Random(location.getBlockX() ^ location.getBlockZ()).nextInt(faces.size())); // Get random face. - - data.setIfPresent(Properties.DIRECTION, oneFace.opposite()) - .setIfPresent(Properties.NORTH, faces.contains(Direction.NORTH)) - .setIfPresent(Properties.SOUTH, faces.contains(Direction.SOUTH)) - .setIfPresent(Properties.EAST, faces.contains(Direction.EAST)) - .setIfPresent(Properties.WEST, faces.contains(Direction.WEST)); - } - world.setBlockData(location.clone().add(0, i + c, 0), data, physics); - } - return true; - } - - @Override - public List getValidSpawnsAt(Chunk chunk, int x, int z, Range range) { - int size = layers.size(); - Vector3 current = new Vector3(x, search.equals(Search.UP) ? range.getMin() : range.getMax(), z); - List blocks = new ArrayList<>(); - int cx = chunk.getX() << 4; - int cz = chunk.getZ() << 4; - for(int y : range) { - if(y > 255 || y < 0) continue; - current = current.add(0, search.equals(Search.UP) ? 1 : -1, 0); - if((spawnBlacklist != spawnable.contains( - chunk.getBlock(current.getBlockX(), current.getBlockY(), current.getBlockZ()).getBlockType())) && isIrrigated( - current.clone().add(cx, irrigableOffset, cz), chunk.getWorld()) && valid(size, current.clone().add(cx, 0, cz), - chunk.getWorld())) { - blocks.add(current.clone()); - if(maxPlacements > 0 && blocks.size() >= maxPlacements) break; - } - } - return blocks; - } - - private boolean valid(int size, Vector3 block, World world) { - for(int i = 0; i < size; i++) { // Down if ceiling, up if floor - if(block.getY() + 1 > 255 || block.getY() < 0) return false; - block.add(0, ceiling ? -1 : 1, 0); - if(!replaceable.contains(world.getBlockData(block).getBlockType())) return false; - } - return true; - } - private void test(EnumSet faces, Direction f, Vector3 b, World world) { if(testRotation.contains( world.getBlockData(b.getBlockX() + f.getModX(), b.getBlockY() + f.getModY(), b.getBlockZ() + f.getModZ()).getBlockType())) faces.add(f); } - private boolean isIrrigated(Vector3 b, World world) { - if(irrigable == null) return true; - return irrigable.contains(world.getBlockData(b.getBlockX() + 1, b.getBlockY(), b.getBlockZ()).getBlockType()) - || irrigable.contains(world.getBlockData(b.getBlockX() - 1, b.getBlockY(), b.getBlockZ()).getBlockType()) - || irrigable.contains(world.getBlockData(b.getBlockX(), b.getBlockY(), b.getBlockZ() + 1).getBlockType()) - || irrigable.contains(world.getBlockData(b.getBlockX(), b.getBlockY(), b.getBlockZ() - 1).getBlockType()); - } - private ProbabilityCollection getStateCollection(int layer) { return layers.get(FastMath.max(FastMath.min(layer, layers.size() - 1), 0)); } @@ -154,8 +68,46 @@ public class TerraFlora implements Flora { return faces; } - public enum Search { - UP, - DOWN + @Override + public String getID() { + return id; + } + + @Override + public boolean generate(Vector3 location, World world, Chunk chunk, Random random, Rotation rotation) { + return generate(location, world, random, rotation); + } + + @Override + public boolean generate(Buffer buffer, World world, Random random, Rotation rotation, int recursions) { + return generate(buffer.getOrigin(), world, random, rotation); + } + + @Override + public boolean generate(Vector3 location, World world, Random random, Rotation rotation) { + boolean doRotation = testRotation.size() > 0; + int size = layers.size(); + int c = ceiling ? -1 : 1; + + EnumSet faces = doRotation ? getFaces(location.clone().add(0, c, 0), world) : EnumSet.noneOf(Direction.class); + if(doRotation && faces.size() == 0) return false; // Don't plant if no faces are valid. + + for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor + int lvl = (FastMath.abs(i)); + BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), + location.getZ(), world.getSeed()).clone(); + if(doRotation) { + Direction oneFace = new ArrayList<>(faces).get( + new Random(location.getBlockX() ^ location.getBlockZ()).nextInt(faces.size())); // Get random face. + + data.setIfPresent(Properties.DIRECTION, oneFace.opposite()) + .setIfPresent(Properties.NORTH, faces.contains(Direction.NORTH)) + .setIfPresent(Properties.SOUTH, faces.contains(Direction.SOUTH)) + .setIfPresent(Properties.EAST, faces.contains(Direction.EAST)) + .setIfPresent(Properties.WEST, faces.contains(Direction.WEST)); + } + world.setBlockData(location.clone().add(0, i + c, 0), data, physics); + } + return true; } }