add custom bush feature for scrub-type biomes

This commit is contained in:
dags- 2020-06-20 14:42:23 +01:00
parent f46272b4e4
commit bc89e7ebb9
8 changed files with 291 additions and 8 deletions

2
Engine

@ -1 +1 @@
Subproject commit 74305c79ee507602f7721478fbd5029bb5a9a51b
Subproject commit 78d4984ce66912d7844cffb8b7fa69dfc1630f24

@ -1 +1 @@
Subproject commit 11ec92c8c103ddd1a30edcf0376f6270320e37d8
Subproject commit 95307b3315188255f7a57691500b8ec05a8b75e2

View File

@ -31,6 +31,7 @@ import com.terraforged.config.ConfigManager;
import com.terraforged.data.DataGen;
import com.terraforged.feature.context.ContextSelectorFeature;
import com.terraforged.feature.decorator.poisson.PoissonAtSurface;
import com.terraforged.feature.feature.BushFeature;
import com.terraforged.feature.feature.DiskFeature;
import com.terraforged.feature.feature.FreezeLayer;
import com.terraforged.fm.template.TemplateManager;
@ -87,6 +88,7 @@ public class TerraForgedMod {
TemplateManager.register(event);
event.getRegistry().register(DiskFeature.INSTANCE);
event.getRegistry().register(FreezeLayer.INSTANCE);
event.getRegistry().register(BushFeature.INSTANCE);
event.getRegistry().register(ContextSelectorFeature.INSTANCE);
}

View File

@ -0,0 +1,139 @@
package com.terraforged.feature.feature;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps;
import com.terraforged.fm.template.BlockUtils;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.IWorld;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationSettings;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import java.util.Random;
public class BushFeature extends Feature<BushFeature.Config> {
public static final BushFeature INSTANCE = new BushFeature();
private static final Vec3i[] logs = {
new Vec3i(+1, 0, +1),
new Vec3i(+1, 0, -1),
new Vec3i(-1, 0, -1),
new Vec3i(-1, 0, +1),
new Vec3i(+2, 0, +1),
new Vec3i(+2, 0, -1),
new Vec3i(-2, 0, +1),
new Vec3i(-2, 0, -1),
new Vec3i(+1, 0, +2),
new Vec3i(+1, 0, -2),
new Vec3i(-1, 0, +2),
new Vec3i(-1, 0, -2),
};
private static final Vec3i[] leaves = {
new Vec3i(0, 0, 1),
new Vec3i(0, 0, -1),
new Vec3i(1, 0, 0),
new Vec3i(-1, 0, 0),
new Vec3i(0, 1, 0),
};
public BushFeature() {
super(BushFeature::deserialize);
setRegistryName("terraforged", "bush");
}
@Override
public boolean place(IWorld world, ChunkGenerator<? extends GenerationSettings> generator, Random rand, BlockPos pos, Config config) {
try (BlockPos.PooledMutable log = BlockPos.PooledMutable.retain(); BlockPos.PooledMutable leaf = BlockPos.PooledMutable.retain()) {
place(world, log.setPos(pos), leaf, rand, config);
for (float chance = rand.nextFloat(); chance < config.size_chance; chance += rand.nextFloat()) {
add(log, logs[rand.nextInt(logs.length)]);
if (!place(world, log, leaf, rand, config)) {
break;
}
}
}
return true;
}
private boolean place(IWorld world, BlockPos.Mutable center, BlockPos.Mutable pos, Random random, Config config) {
int y = world.getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, center.getX(), center.getZ());
center.setY(y);
world.setBlockState(center, config.trunk, 2);
for (Vec3i neighbour : leaves) {
if (neighbour.getY() == 0 && random.nextFloat() < config.airChance) {
continue;
}
pos.setPos(center);
add(pos, neighbour);
if (!BlockUtils.isSolid(world, pos)) {
world.setBlockState(pos, config.leaves, 2);
if (neighbour.getY() == 0 && random.nextFloat() < config.leafChance) {
pos.move(Direction.UP, 1);
world.setBlockState(pos, config.leaves, 2);
}
}
}
return true;
}
private static void add(BlockPos.Mutable pos, Vec3i add) {
pos.setPos(pos.getX() + add.getX(), pos.getY() + add.getY(), pos.getZ() + add.getZ());
}
public static Config deserialize(Dynamic<?> data) {
BlockState logs = BlockState.deserialize(data.get("trunk").get().get());
BlockState leaves = BlockState.deserialize(data.get("leaves").get().get());
float airChance = data.get("air_chance").asFloat(0.075F);
float leafChance = data.get("leaf_chance").asFloat(0.075F);
float sizeChance = data.get("size_chance").asFloat(0.75F);
return new Config(logs, leaves, airChance, leafChance, sizeChance);
}
public static class Config implements IFeatureConfig {
private final BlockState trunk;
private final BlockState leaves;
private final float airChance;
private final float leafChance;
private final float size_chance;
public Config(BlockState trunk, BlockState leaves, float airChance, float leafChance, float size_chance) {
this.trunk = trunk;
this.leaves = leaves;
this.airChance = airChance;
this.leafChance = leafChance;
this.size_chance = size_chance;
}
@Override
public <T> Dynamic<T> serialize(DynamicOps<T> ops) {
return new Dynamic<>(
ops,
ops.createMap(ImmutableMap.of(
ops.createString("trunk"), BlockState.serialize(ops, trunk).getValue(),
ops.createString("leaves"), BlockState.serialize(ops, leaves).getValue(),
ops.createString("air_chance"), ops.createFloat(airChance),
ops.createString("leaf_chance"), ops.createFloat(airChance),
ops.createString("size_chance"), ops.createFloat(size_chance)
))
);
}
}
}

View File

@ -1,5 +1,6 @@
package com.terraforged.feature.feature;
import com.terraforged.fm.template.BlockUtils;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.SnowyDirtBlock;
@ -73,16 +74,18 @@ public class FreezeLayer extends Feature<NoFeatureConfig> {
return false;
}
BlockState above = world.getBlockState(top.up());
top.move(Direction.UP, 1);
BlockState above = world.getBlockState(top);
if (BlockTags.LOGS.contains(above.getBlock()) || BlockTags.LEAVES.contains(above.getBlock())) {
return false;
}
setSnow(world, top, below, stateUnder);
top.move(Direction.DOWN, 1);
if (setSnow(world, top, below, stateUnder)) {
if (above.getBlock() != Blocks.AIR) {
world.setBlockState(top, Blocks.AIR.getDefaultState(), 2);
}
}
} else {
setSnow(world, top, below, stateUnder);
}
@ -90,11 +93,16 @@ public class FreezeLayer extends Feature<NoFeatureConfig> {
return hasFrozen;
}
private void setSnow(IWorld world, BlockPos pos1, BlockPos pos2, BlockState below) {
private boolean setSnow(IWorld world, BlockPos pos1, BlockPos pos2, BlockState below) {
if (BlockUtils.isSolid(world, pos1)) {
return false;
}
world.setBlockState(pos1, Blocks.SNOW.getDefaultState(), 2);
if (below.has(SnowyDirtBlock.SNOWY)) {
world.setBlockState(pos2, below.with(SnowyDirtBlock.SNOWY, true), 2);
}
return true;
}
}

View File

@ -0,0 +1,44 @@
{
"biomes": [
"terraforged:cold_steppe"
],
"match": [
[
"minecraft:grass"
]
],
"before": {
"name": "minecraft:decorated",
"config": {
"feature": {
"name": "terraforged:bush",
"config": {
"trunk": {
"Name": "minecraft:spruce_log",
"Properties": {
"axis": "y"
}
},
"leaves": {
"Name": "minecraft:spruce_leaves",
"Properties": {
"distance": "7",
"persistent": "false"
}
},
"air_chance": 0.05,
"leaf_chance": 0.075,
"size_chance": 0.6
}
},
"decorator": {
"name": "minecraft:count_extra_heightmap",
"config": {
"count": 0,
"extra_chance": 0.2,
"extra_count": 1
}
}
}
}
}

View File

@ -0,0 +1,46 @@
{
"biomes": [
"terraforged:steppe",
"terraforged:savanna_scrub",
"terraforged:shattered_savanna_scrub"
],
"match": [
[
"minecraft:grass"
]
],
"before": {
"name": "minecraft:decorated",
"config": {
"feature": {
"name": "terraforged:bush",
"config": {
"trunk": {
"Name": "minecraft:acacia_log",
"Properties": {
"axis": "y"
}
},
"leaves": {
"Name": "minecraft:acacia_leaves",
"Properties": {
"distance": "7",
"persistent": "false"
}
},
"air_chance": 0.06,
"leaf_chance": 0.08,
"size_chance": 0.7
}
},
"decorator": {
"name": "minecraft:count_extra_heightmap",
"config": {
"count": 0,
"extra_chance": 0.12,
"extra_count": 1
}
}
}
}
}

View File

@ -0,0 +1,44 @@
{
"biomes": [
"terraforged:taiga_scrub"
],
"match": [
[
"minecraft:grass"
]
],
"before": {
"name": "minecraft:decorated",
"config": {
"feature": {
"name": "terraforged:bush",
"config": {
"trunk": {
"Name": "minecraft:spruce_log",
"Properties": {
"axis": "y"
}
},
"leaves": {
"Name": "minecraft:spruce_leaves",
"Properties": {
"distance": "7",
"persistent": "false"
}
},
"air_chance": 0.05,
"leaf_chance": 0.075,
"size_chance": 0.6
}
},
"decorator": {
"name": "minecraft:count_extra_heightmap",
"config": {
"count": 0,
"extra_chance": 0.1,
"extra_count": 1
}
}
}
}
}