add custom bush feature for scrub-type biomes
This commit is contained in:
parent
f46272b4e4
commit
bc89e7ebb9
2
Engine
2
Engine
@ -1 +1 @@
|
|||||||
Subproject commit 74305c79ee507602f7721478fbd5029bb5a9a51b
|
Subproject commit 78d4984ce66912d7844cffb8b7fa69dfc1630f24
|
@ -1 +1 @@
|
|||||||
Subproject commit 11ec92c8c103ddd1a30edcf0376f6270320e37d8
|
Subproject commit 95307b3315188255f7a57691500b8ec05a8b75e2
|
@ -31,6 +31,7 @@ import com.terraforged.config.ConfigManager;
|
|||||||
import com.terraforged.data.DataGen;
|
import com.terraforged.data.DataGen;
|
||||||
import com.terraforged.feature.context.ContextSelectorFeature;
|
import com.terraforged.feature.context.ContextSelectorFeature;
|
||||||
import com.terraforged.feature.decorator.poisson.PoissonAtSurface;
|
import com.terraforged.feature.decorator.poisson.PoissonAtSurface;
|
||||||
|
import com.terraforged.feature.feature.BushFeature;
|
||||||
import com.terraforged.feature.feature.DiskFeature;
|
import com.terraforged.feature.feature.DiskFeature;
|
||||||
import com.terraforged.feature.feature.FreezeLayer;
|
import com.terraforged.feature.feature.FreezeLayer;
|
||||||
import com.terraforged.fm.template.TemplateManager;
|
import com.terraforged.fm.template.TemplateManager;
|
||||||
@ -87,6 +88,7 @@ public class TerraForgedMod {
|
|||||||
TemplateManager.register(event);
|
TemplateManager.register(event);
|
||||||
event.getRegistry().register(DiskFeature.INSTANCE);
|
event.getRegistry().register(DiskFeature.INSTANCE);
|
||||||
event.getRegistry().register(FreezeLayer.INSTANCE);
|
event.getRegistry().register(FreezeLayer.INSTANCE);
|
||||||
|
event.getRegistry().register(BushFeature.INSTANCE);
|
||||||
event.getRegistry().register(ContextSelectorFeature.INSTANCE);
|
event.getRegistry().register(ContextSelectorFeature.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
139
src/main/java/com/terraforged/feature/feature/BushFeature.java
Normal file
139
src/main/java/com/terraforged/feature/feature/BushFeature.java
Normal 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)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.terraforged.feature.feature;
|
package com.terraforged.feature.feature;
|
||||||
|
|
||||||
|
import com.terraforged.fm.template.BlockUtils;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.SnowyDirtBlock;
|
import net.minecraft.block.SnowyDirtBlock;
|
||||||
@ -73,15 +74,17 @@ public class FreezeLayer extends Feature<NoFeatureConfig> {
|
|||||||
return false;
|
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())) {
|
if (BlockTags.LOGS.contains(above.getBlock()) || BlockTags.LEAVES.contains(above.getBlock())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSnow(world, top, below, stateUnder);
|
top.move(Direction.DOWN, 1);
|
||||||
|
if (setSnow(world, top, below, stateUnder)) {
|
||||||
if (above.getBlock() != Blocks.AIR) {
|
if (above.getBlock() != Blocks.AIR) {
|
||||||
world.setBlockState(top, Blocks.AIR.getDefaultState(), 2);
|
world.setBlockState(top, Blocks.AIR.getDefaultState(), 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSnow(world, top, below, stateUnder);
|
setSnow(world, top, below, stateUnder);
|
||||||
@ -90,11 +93,16 @@ public class FreezeLayer extends Feature<NoFeatureConfig> {
|
|||||||
return hasFrozen;
|
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);
|
world.setBlockState(pos1, Blocks.SNOW.getDefaultState(), 2);
|
||||||
|
|
||||||
if (below.has(SnowyDirtBlock.SNOWY)) {
|
if (below.has(SnowyDirtBlock.SNOWY)) {
|
||||||
world.setBlockState(pos2, below.with(SnowyDirtBlock.SNOWY, true), 2);
|
world.setBlockState(pos2, below.with(SnowyDirtBlock.SNOWY, true), 2);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user