From 6ef6e3912835815e969feb445ca7b59973c3337a Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 17 Oct 2021 15:03:26 -0700 Subject: [PATCH] Initial commit --- common/addons/config-flora/README.md | 3 + common/addons/config-flora/build.gradle.kts | 2 + .../dfsek/terra/addons/flora/FloraAddon.java | 33 +++++ .../terra/addons/flora/FloraConfigType.java | 38 ++++++ .../terra/addons/flora/FloraFactory.java | 16 +++ .../terra/addons/flora/FloraTemplate.java | 63 ++++++++++ .../flora/config/BlockLayerTemplate.java | 23 ++++ .../addons/flora/flora/gen/BlockLayer.java | 23 ++++ .../addons/flora/flora/gen/TerraFlora.java | 113 ++++++++++++++++++ 9 files changed, 314 insertions(+) create mode 100644 common/addons/config-flora/README.md create mode 100644 common/addons/config-flora/build.gradle.kts create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java create mode 100644 common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java diff --git a/common/addons/config-flora/README.md b/common/addons/config-flora/README.md new file mode 100644 index 000000000..6ce6deaa8 --- /dev/null +++ b/common/addons/config-flora/README.md @@ -0,0 +1,3 @@ +# config-flora + +Registers the default configuration for Terra Flora, `FLORA`. \ No newline at end of file diff --git a/common/addons/config-flora/build.gradle.kts b/common/addons/config-flora/build.gradle.kts new file mode 100644 index 000000000..7d82dc72f --- /dev/null +++ b/common/addons/config-flora/build.gradle.kts @@ -0,0 +1,2 @@ +dependencies { +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java new file mode 100644 index 000000000..142924e7b --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.addons.flora; + +import com.dfsek.terra.addons.flora.config.BlockLayerTemplate; +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.TerraAddon; +import com.dfsek.terra.api.addon.annotations.Addon; +import com.dfsek.terra.api.addon.annotations.Author; +import com.dfsek.terra.api.addon.annotations.Version; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +@Addon("config-flora") +@Author("Terra") +@Version("0.1.0") +public class FloraAddon extends TerraAddon { + @Inject + private Platform platform; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPreLoadEvent.class) + .then(event -> { + event.getPack().registerConfigType(new FloraConfigType(), "FLORA", 2); + event.getPack().applyLoader(BlockLayer.class, BlockLayerTemplate::new); + }) + .failThrough(); + } +} 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 new file mode 100644 index 000000000..1d1a2934c --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.addons.flora; + +import java.util.function.Supplier; + +import com.dfsek.terra.api.Platform; +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; + + +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) { + return pack.getRegistryFactory()::create; + } + + @Override + public FloraTemplate getTemplate(ConfigPack pack, Platform platform) { + return new FloraTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + 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 new file mode 100644 index 000000000..ce24a3672 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.addons.flora; + +import com.dfsek.terra.addons.flora.flora.gen.TerraFlora; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.structure.Structure; + + +public class FloraFactory implements ConfigFactory { + @Override + public TerraFlora build(FloraTemplate config, Platform platform) { + 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 new file mode 100644 index 000000000..78b76ddda --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java @@ -0,0 +1,63 @@ +package com.dfsek.terra.addons.flora; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Final; +import com.dfsek.tectonic.annotations.Value; + +import java.util.List; + +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.addons.flora.flora.gen.TerraFlora; +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.MaterialSet; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class FloraTemplate implements AbstractableTemplate { + @Value("id") + @Final + private String id; + @Value("rotatable") + @Default + private @Meta MaterialSet rotatable = MaterialSet.empty(); + + @Value("physics") + @Default + private @Meta boolean doPhysics = false; + + @Value("ceiling") + @Default + private @Meta boolean ceiling = false; + + @Value("layers") + private @Meta List<@Meta BlockLayer> layers; + + @Value("layer-distribution") + private @Meta NoiseSampler noiseDistribution; + + public boolean doPhysics() { + return doPhysics; + } + + public NoiseSampler getNoiseDistribution() { + return noiseDistribution; + } + + public List getLayers() { + return layers; + } + + public String getID() { + return id; + } + + public boolean isCeiling() { + return ceiling; + } + + public MaterialSet getRotatable() { + return rotatable; + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java new file mode 100644 index 000000000..13673d93f --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.flora.config; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.loading.object.ObjectTemplate; + +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BlockLayerTemplate implements ObjectTemplate { + @Value("layers") + private @Meta int layers; + + @Value("materials") + private @Meta ProbabilityCollection data; + + @Override + public BlockLayer get() { + return new BlockLayer(layers, data); + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java new file mode 100644 index 000000000..75b16529a --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.flora.flora.gen; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BlockLayer { + private final int layers; + private final ProbabilityCollection blocks; + + public BlockLayer(int layers, ProbabilityCollection blocks) { + this.layers = layers; + this.blocks = blocks; + } + + public int getLayers() { + return layers; + } + + public ProbabilityCollection getBlocks() { + return blocks; + } +} 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 new file mode 100644 index 000000000..c9942f055 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java @@ -0,0 +1,113 @@ +package com.dfsek.terra.addons.flora.flora.gen; + +import net.jafama.FastMath; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +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.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.util.vector.Vector3; +import com.dfsek.terra.api.world.Chunk; +import com.dfsek.terra.api.world.World; + + +public class TerraFlora implements Structure { + private final List> layers; + private final boolean physics; + private final boolean ceiling; + + private final MaterialSet testRotation; + + private final 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.ceiling = ceiling; + this.distribution = distribution; + this.id = id; + + this.layers = new ArrayList<>(); + layers.forEach(layer -> { + for(int i = 0; i < layer.getLayers(); i++) { + this.layers.add(layer.getBlocks()); + } + }); + } + + 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 ProbabilityCollection getStateCollection(int layer) { + return layers.get(FastMath.max(FastMath.min(layer, layers.size() - 1), 0)); + } + + private EnumSet getFaces(Vector3 b, World world) { + EnumSet 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 + 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; + } +}