convert TerraFlora to structure

This commit is contained in:
dfsek 2021-09-19 00:17:28 -07:00
parent 1968bdf88d
commit c4415c6fd2
4 changed files with 63 additions and 167 deletions

View File

@ -7,17 +7,18 @@ import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType; import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.OpenRegistry; 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.util.reflection.TypeKey;
import com.dfsek.terra.api.world.Flora; import com.dfsek.terra.api.world.Flora;
public class FloraConfigType implements ConfigType<FloraTemplate, Flora> { public class FloraConfigType implements ConfigType<FloraTemplate, Structure> {
public static final TypeKey<Flora> FLORA_TYPE_TOKEN = new TypeKey<>() { public static final TypeKey<Structure> FLORA_TYPE_TOKEN = new TypeKey<>() {
}; };
private final FloraFactory factory = new FloraFactory(); private final FloraFactory factory = new FloraFactory();
@Override @Override
public Supplier<OpenRegistry<Flora>> registrySupplier(ConfigPack pack) { public Supplier<OpenRegistry<Structure>> registrySupplier(ConfigPack pack) {
return pack.getRegistryFactory()::create; return pack.getRegistryFactory()::create;
} }
@ -27,12 +28,12 @@ public class FloraConfigType implements ConfigType<FloraTemplate, Flora> {
} }
@Override @Override
public ConfigFactory<FloraTemplate, Flora> getFactory() { public ConfigFactory<FloraTemplate, Structure> getFactory() {
return factory; return factory;
} }
@Override @Override
public TypeKey<Flora> getTypeKey() { public TypeKey<Structure> getTypeKey() {
return FLORA_TYPE_TOKEN; return FLORA_TYPE_TOKEN;
} }
} }

View File

@ -3,14 +3,14 @@ package com.dfsek.terra.addons.flora;
import com.dfsek.terra.addons.flora.flora.gen.TerraFlora; import com.dfsek.terra.addons.flora.flora.gen.TerraFlora;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory; 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<FloraTemplate, Flora> { public class FloraFactory implements ConfigFactory<FloraTemplate, Structure> {
@Override @Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) { public TerraFlora build(FloraTemplate config, TerraPlugin main) {
return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(),
config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), config.getRotatable(),
config.isSpawnBlacklist(), config.getIrrigableOffset(), main, config.getNoiseDistribution()); config.getNoiseDistribution(), config.getID());
} }
} }

View File

@ -19,23 +19,6 @@ public class FloraTemplate implements AbstractableTemplate {
@Value("id") @Value("id")
@Final @Final
private String id; 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") @Value("rotatable")
@Default @Default
private @Meta MaterialSet rotatable = MaterialSet.empty(); private @Meta MaterialSet rotatable = MaterialSet.empty();
@ -48,18 +31,6 @@ public class FloraTemplate implements AbstractableTemplate {
@Default @Default
private @Meta boolean ceiling = false; 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") @Value("layers")
private @Meta List<@Meta BlockLayer> layers; private @Meta List<@Meta BlockLayer> layers;
@ -78,30 +49,6 @@ public class FloraTemplate implements AbstractableTemplate {
return layers; 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() { public String getID() {
return id; return id;
} }
@ -110,10 +57,6 @@ public class FloraTemplate implements AbstractableTemplate {
return ceiling; return ceiling;
} }
public boolean isSpawnBlacklist() {
return spawnBlacklist;
}
public MaterialSet getRotatable() { public MaterialSet getRotatable() {
return rotatable; return rotatable;
} }

View File

@ -7,59 +7,39 @@ import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Random; 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.BlockState;
import com.dfsek.terra.api.block.state.properties.base.Properties; 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.block.state.properties.enums.Direction;
import com.dfsek.terra.api.noise.NoiseSampler; 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.MaterialSet;
import com.dfsek.terra.api.util.collection.ProbabilityCollection; import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk; import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.Flora;
import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.World;
public class TerraFlora implements Flora { public class TerraFlora implements Structure {
private final List<ProbabilityCollection<BlockState>> layers; private final List<ProbabilityCollection<BlockState>> layers;
private final boolean physics; private final boolean physics;
private final boolean ceiling; private final boolean ceiling;
private final MaterialSet irrigable;
private final MaterialSet spawnable;
private final MaterialSet replaceable;
private final MaterialSet testRotation; 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; private final NoiseSampler distribution;
public TerraFlora(List<BlockLayer> layers, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, private final String id;
MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist,
int irrigableOffset, TerraPlugin main, NoiseSampler distribution) { public TerraFlora(List<BlockLayer> layers, boolean physics, boolean ceiling,
MaterialSet testRotation,
NoiseSampler distribution, String id) {
this.physics = physics; this.physics = physics;
this.testRotation = testRotation; this.testRotation = testRotation;
this.spawnBlacklist = spawnBlacklist;
this.ceiling = ceiling; 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.distribution = distribution;
this.id = id;
this.layers = new ArrayList<>(); this.layers = new ArrayList<>();
layers.forEach(layer -> { layers.forEach(layer -> {
@ -69,8 +49,42 @@ public class TerraFlora implements Flora {
}); });
} }
private void test(EnumSet<Direction> 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 ProbabilityCollection<BlockState> getStateCollection(int layer) {
return layers.get(FastMath.max(FastMath.min(layer, layers.size() - 1), 0));
}
private EnumSet<Direction> getFaces(Vector3 b, World world) {
EnumSet<Direction> faces = EnumSet.noneOf(Direction.class);
test(faces, Direction.NORTH, b, world);
test(faces, Direction.SOUTH, b, world);
test(faces, Direction.EAST, b, world);
test(faces, Direction.WEST, b, world);
return faces;
}
@Override @Override
public boolean plant(Vector3 location, World world) { 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; boolean doRotation = testRotation.size() > 0;
int size = layers.size(); int size = layers.size();
int c = ceiling ? -1 : 1; int c = ceiling ? -1 : 1;
@ -96,66 +110,4 @@ public class TerraFlora implements Flora {
} }
return true; return true;
} }
@Override
public List<Vector3> 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<Vector3> 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<Direction> 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<BlockState> getStateCollection(int layer) {
return layers.get(FastMath.max(FastMath.min(layer, layers.size() - 1), 0));
}
private EnumSet<Direction> getFaces(Vector3 b, World world) {
EnumSet<Direction> faces = EnumSet.noneOf(Direction.class);
test(faces, Direction.NORTH, b, world);
test(faces, Direction.SOUTH, b, world);
test(faces, Direction.EAST, b, world);
test(faces, Direction.WEST, b, world);
return faces;
}
public enum Search {
UP,
DOWN
}
} }