2018-10-13 23:46:30 +02:00
|
|
|
package de.ellpeck.naturesaura.gen;
|
|
|
|
|
|
|
|
import de.ellpeck.naturesaura.blocks.ModBlocks;
|
|
|
|
import net.minecraft.block.Block;
|
2019-10-20 22:30:49 +02:00
|
|
|
import net.minecraft.block.LeavesBlock;
|
|
|
|
import net.minecraft.block.LogBlock;
|
2018-10-13 23:46:30 +02:00
|
|
|
import net.minecraft.block.BlockLog.EnumAxis;
|
|
|
|
import net.minecraft.block.material.Material;
|
2019-10-20 22:30:49 +02:00
|
|
|
import net.minecraft.block.BlockState;
|
|
|
|
import net.minecraft.block.Blocks;
|
2018-10-13 23:46:30 +02:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.util.math.MathHelper;
|
|
|
|
import net.minecraft.world.World;
|
2019-10-20 22:30:49 +02:00
|
|
|
import net.minecraft.world.gen.feature.AbstractTreeFeature;
|
2018-10-13 23:46:30 +02:00
|
|
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
2019-10-20 22:30:49 +02:00
|
|
|
public class WorldGenAncientTree extends AbstractTreeFeature {
|
2018-10-13 23:46:30 +02:00
|
|
|
|
|
|
|
public WorldGenAncientTree(boolean notify) {
|
|
|
|
super(notify);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean generate(World world, Random rand, BlockPos pos) {
|
|
|
|
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);
|
|
|
|
while (!world.getBlockState(goal).isFullBlock()) {
|
|
|
|
goal = goal.down();
|
2019-04-14 11:38:44 +02:00
|
|
|
if (goal.distanceSq(pos) >= 10 * 10)
|
|
|
|
break;
|
2018-10-13 23:46:30 +02:00
|
|
|
}
|
|
|
|
this.makeBranch(world, pos.up(rand.nextInt(1)), goal, ModBlocks.ANCIENT_BARK.getDefaultState(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//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);
|
|
|
|
if (this.isReplaceable(world, goal)) {
|
|
|
|
this.setBlockAndNotifyAdequately(world, goal,
|
2019-10-20 22:30:49 +02:00
|
|
|
ModBlocks.ANCIENT_LOG.getDefaultState().withProperty(LogBlock.LOG_AXIS, EnumAxis.Y));
|
2018-10-13 23:46:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.makeLeaves(world, trunkTop.up(rand.nextInt(2) - 1),
|
2019-10-20 22:30:49 +02:00
|
|
|
ModBlocks.ANCIENT_LEAVES.getDefaultState().withProperty(LeavesBlock.CHECK_DECAY, false), 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);
|
|
|
|
this.makeBranch(world, trunkTop, goal, ModBlocks.ANCIENT_LOG.getDefaultState(), true);
|
|
|
|
this.makeLeaves(world, goal,
|
2019-10-20 22:30:49 +02:00
|
|
|
ModBlocks.ANCIENT_LEAVES.getDefaultState().withProperty(LeavesBlock.CHECK_DECAY, false), rand.nextInt(2) + 2, rand);
|
2018-10-13 23:46:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean canGrowInto(Block blockType) {
|
|
|
|
if (super.canGrowInto(blockType)) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
Material material = blockType.getDefaultState().getMaterial();
|
|
|
|
return material == Material.VINE || material == Material.PLANTS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-20 22:30:49 +02:00
|
|
|
private void makeBranch(World 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));
|
|
|
|
if (this.isReplaceable(world, goal)) {
|
|
|
|
if (hasAxis) {
|
|
|
|
EnumAxis axis = this.getLogAxis(first, goal);
|
2019-10-20 22:30:49 +02:00
|
|
|
this.setBlockAndNotifyAdequately(world, goal, state.withProperty(LogBlock.LOG_AXIS, axis));
|
2018-10-13 23:46:30 +02:00
|
|
|
} else {
|
|
|
|
this.setBlockAndNotifyAdequately(world, goal, state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-20 22:30:49 +02:00
|
|
|
private void makeLeaves(World 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) {
|
2019-01-26 23:29:45 +01:00
|
|
|
if (this.isReplaceable(world, goal)) {
|
|
|
|
Block block = world.getBlockState(goal).getBlock();
|
2019-10-20 22:30:49 +02:00
|
|
|
if (!(block instanceof LogBlock) && block != Blocks.DIRT && block != Blocks.GRASS)
|
2019-01-26 23:29:45 +01:00
|
|
|
this.setBlockAndNotifyAdequately(world, goal, state);
|
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())));
|
|
|
|
}
|
|
|
|
|
|
|
|
private EnumAxis getLogAxis(BlockPos pos, BlockPos goal) {
|
|
|
|
EnumAxis axis = EnumAxis.Y;
|
|
|
|
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) {
|
|
|
|
axis = EnumAxis.X;
|
|
|
|
} else if (y == highest) {
|
|
|
|
axis = EnumAxis.Z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return axis;
|
|
|
|
}
|
|
|
|
}
|