NaturesAura/src/main/java/de/ellpeck/naturesaura/gen/WorldGenAncientTree.java

138 lines
5.7 KiB
Java
Raw Normal View History

2018-10-13 23:46:30 +02:00
package de.ellpeck.naturesaura.gen;
import de.ellpeck.naturesaura.blocks.ModBlocks;
2020-01-24 17:05:41 +01:00
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.LogBlock;
import net.minecraft.util.Direction.Axis;
2018-10-13 23:46:30 +02:00
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
2020-01-21 23:02:39 +01:00
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.world.gen.IWorldGenerationReader;
2019-10-20 22:30:49 +02:00
import net.minecraft.world.gen.feature.AbstractTreeFeature;
2020-01-24 17:05:41 +01:00
import net.minecraft.world.gen.feature.NoFeatureConfig;
2018-10-13 23:46:30 +02:00
import java.util.Random;
2020-01-21 23:02:39 +01:00
import java.util.Set;
2018-10-13 23:46:30 +02:00
2020-01-24 17:05:41 +01:00
public class WorldGenAncientTree extends AbstractTreeFeature<NoFeatureConfig> {
2018-10-13 23:46:30 +02:00
public WorldGenAncientTree(boolean notify) {
2020-01-24 17:05:41 +01:00
super(NoFeatureConfig::deserialize, notify);
2018-10-13 23:46:30 +02:00
}
@Override
2020-01-21 23:02:39 +01:00
protected boolean place(Set changedBlocks, IWorldGenerationReader world, Random rand, BlockPos pos, MutableBoundingBox box) {
2018-10-13 23:46:30 +02:00
int height = rand.nextInt(3) + 5;
BlockPos trunkTop = pos.up(height);
//Roots
int rootsAmount = rand.nextInt(4) + 5;
for (int i = 0; i < rootsAmount; i++) {
int length = rand.nextInt(3) + 3;
float angle = 2F * (float) Math.PI * (i / (float) rootsAmount);
float x = (float) Math.sin(angle) * length;
float z = (float) Math.cos(angle) * length;
BlockPos goal = pos.add(x, 0, z);
2020-01-24 17:05:41 +01:00
while (!world.hasBlockState(goal, state -> state.getMaterial().isReplaceable())) {
2018-10-13 23:46:30 +02:00
goal = goal.down();
if (goal.distanceSq(pos) >= 10 * 10)
break;
2018-10-13 23:46:30 +02:00
}
2020-01-24 17:05:41 +01:00
this.makeBranch(changedBlocks, world, pos.up(rand.nextInt(1)), goal, ModBlocks.ANCIENT_BARK.getDefaultState(), false);
2018-10-13 23:46:30 +02:00
}
//Trunk
for (int x = 0; x <= 1; x++) {
for (int z = 0; z <= 1; z++) {
for (int i = height - (x + z) * (rand.nextInt(2) + 2); i >= 0; i--) {
BlockPos goal = pos.add(x, i, z);
2020-01-24 17:05:41 +01:00
if (func_214587_a(world, goal)) {
this.setBlockState(world, goal, ModBlocks.ANCIENT_LOG.getDefaultState().with(LogBlock.AXIS, Axis.Y));
changedBlocks.add(goal);
2018-10-13 23:46:30 +02:00
}
}
}
}
2020-01-24 17:05:41 +01:00
this.makeLeaves(changedBlocks, world, trunkTop.up(rand.nextInt(2) - 1), ModBlocks.ANCIENT_LEAVES.getDefaultState(), rand.nextInt(2) + 3, rand);
2018-10-13 23:46:30 +02:00
//Branches
int branchAmount = rand.nextInt(3) + 4;
for (int i = 0; i < branchAmount; i++) {
int length = rand.nextInt(2) + 3;
float angle = 2F * (float) Math.PI * (i / (float) branchAmount);
float x = (float) Math.sin(angle) * length;
float z = (float) Math.cos(angle) * length;
BlockPos goal = trunkTop.add(x, rand.nextInt(3) + 1, z);
2020-01-24 17:05:41 +01:00
this.makeBranch(changedBlocks, world, trunkTop, goal, ModBlocks.ANCIENT_LOG.getDefaultState(), true);
this.makeLeaves(changedBlocks, world, goal, ModBlocks.ANCIENT_LEAVES.getDefaultState(), rand.nextInt(2) + 2, rand);
2018-10-13 23:46:30 +02:00
}
return true;
}
2020-01-24 17:05:41 +01:00
private void makeBranch(Set changedBlocks, IWorldGenerationReader world, BlockPos first, BlockPos second, BlockState state, boolean hasAxis) {
2018-10-13 23:46:30 +02:00
BlockPos pos = second.add(-first.getX(), -first.getY(), -first.getZ());
int length = this.getHighestCoord(pos);
float stepX = (float) pos.getX() / (float) length;
float stepY = (float) pos.getY() / (float) length;
float stepZ = (float) pos.getZ() / (float) length;
for (int i = 0; i <= length; i++) {
BlockPos goal = first.add((0.5F + i * stepX), (0.5F + i * stepY), (0.5F + i * stepZ));
2020-01-24 17:05:41 +01:00
if (func_214587_a(world, goal)) {
2018-10-13 23:46:30 +02:00
if (hasAxis) {
2020-01-24 17:05:41 +01:00
Axis axis = this.getLogAxis(first, goal);
this.setBlockState(world, goal, state.with(LogBlock.AXIS, axis));
2018-10-13 23:46:30 +02:00
} else {
2020-01-24 17:05:41 +01:00
this.setBlockState(world, goal, state);
2018-10-13 23:46:30 +02:00
}
2020-01-24 17:05:41 +01:00
changedBlocks.add(goal);
2018-10-13 23:46:30 +02:00
}
}
}
2020-01-24 17:05:41 +01:00
private void makeLeaves(Set changedBlocks, IWorldGenerationReader world, BlockPos pos, BlockState state, int radius, Random rand) {
2018-10-13 23:46:30 +02:00
for (int x = -radius; x <= radius; x++) {
for (int y = -radius; y <= radius; y++) {
for (int z = -radius; z <= radius; z++) {
BlockPos goal = pos.add(x, y, z);
if (pos.distanceSq(goal) <= radius * radius + rand.nextInt(3) - 1) {
2020-01-24 17:05:41 +01:00
if (isAirOrLeaves(world, goal)) {
if (world.hasBlockState(goal, st -> {
Block block = st.getBlock();
return !(block instanceof LogBlock) && block != Blocks.DIRT && block != Blocks.GRASS;
})) {
this.setBlockState(world, goal, state);
changedBlocks.add(goal);
}
2018-10-13 23:46:30 +02:00
}
}
}
}
}
}
private int getHighestCoord(BlockPos pos) {
return Math.max(MathHelper.abs(pos.getX()), Math.max(MathHelper.abs(pos.getY()), MathHelper.abs(pos.getZ())));
}
2020-01-24 17:05:41 +01:00
private Axis getLogAxis(BlockPos pos, BlockPos goal) {
Axis axis = Axis.Y;
2018-10-13 23:46:30 +02:00
int x = Math.abs(goal.getX() - pos.getX());
int y = Math.abs(goal.getZ() - pos.getZ());
int highest = Math.max(x, y);
if (highest > 0) {
if (x == highest) {
2020-01-24 17:05:41 +01:00
axis = Axis.X;
2018-10-13 23:46:30 +02:00
} else if (y == highest) {
2020-01-24 17:05:41 +01:00
axis = Axis.Z;
2018-10-13 23:46:30 +02:00
}
}
return axis;
}
2020-01-24 17:05:41 +01:00
}