package net.glowstone.generator.objects.trees;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Location;
import org.bukkit.Material;
import java.util.Random;
public class RedwoodTree extends GenericTree {
protected int maxRadius;
protected int leavesHeight;
public RedwoodTree(Random random, Location location, BlockStateDelegate delegate) {
super(random, location, delegate);
setOverridables(
Material.AIR,
Material.LEAVES
);
setHeight(random.nextInt(4) + 6);
setLeavesHeight(random.nextInt(2) + 1);
setMaxRadius(random.nextInt(2) + 2);
setTypes(1, 1);
}
protected final void setMaxRadius(int maxRadius) {
this.maxRadius = maxRadius;
}
protected final void setLeavesHeight(int leavesHeight) {
this.leavesHeight = leavesHeight;
}
@Override
public boolean canPlace() {
for (int y = loc.getBlockY(); y <= loc.getBlockY() + 1 + height; y++) {
// Space requirement
int radius; // default radius if above first block
if (y - loc.getBlockY() < leavesHeight) {
radius = 0; // radius is 0 for trunk below leaves
} else {
radius = maxRadius;
}
// check for block collision on horizontal slices
for (int x = loc.getBlockX() - radius; x <= loc.getBlockX() + radius; x++) {
for (int z = loc.getBlockZ() - radius; z <= loc.getBlockZ() + radius; z++) {
if (y >= 0 && y < 256) {
// we can overlap some blocks around
final Material type = delegate.getBlockState(loc.getWorld(), x, y, z).getType();
if (!overridables.contains(type)) {
return false;
}
} else { // height out of range
return false;
}
}
}
}
return true;
}
@Override
public boolean generate() {
if (!canHeightFit() || !canPlaceOn() || !canPlace()) {
return false;
}
// generate the leaves
int radius = random.nextInt(2);
int peakRadius = 1;
int minRadius = 0;
for (int y = loc.getBlockY() + height; y >= loc.getBlockY() + leavesHeight; y--) {
// leaves are built from top to bottom
for (int x = loc.getBlockX() - radius; x <= loc.getBlockX() + radius; x++) {
for (int z = loc.getBlockZ() - radius; z <= loc.getBlockZ() + radius; z++) {
if ((Math.abs(x - loc.getBlockX()) != radius || Math.abs(z - loc.getBlockZ()) != radius || radius <= 0) &&
delegate.getBlockState(loc.getWorld(), x, y, z).getType() == Material.AIR) {
delegate.setTypeAndRawData(loc.getWorld(), x, y, z, Material.LEAVES, leavesType);
}
}
}
if (radius >= peakRadius) {
radius = minRadius;
minRadius = 1; // after the peak radius is reached once, the min radius increases
peakRadius++; // the peak radius increases each time it's reached
if (peakRadius > maxRadius) {
peakRadius = maxRadius;
}
} else {
radius++;
}
}
// generate the trunk
for (int y = 0; y < height - random.nextInt(3); y++) {
final Material type = delegate.getBlockState(loc.getWorld(), loc.getBlockX(), loc.getBlockY() + y, loc.getBlockZ()).getType();
if (overridables.contains(type)) {
delegate.setTypeAndRawData(loc.getWorld(), loc.getBlockX(), loc.getBlockY() + y, loc.getBlockZ(), Material.LOG, logType);
}
}
// block below trunk is always dirt
delegate.setTypeAndRawData(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ(), Material.DIRT, 0);
return true;
}
}