blob: 7cf4d3ffbc196c068de9c03ecd26ef0f72afc8b6 [file] [log] [blame] [raw]
package net.glowstone.generator.objects.trees;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.DirtType;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.material.Dirt;
import java.util.Random;
public class DarkOakTree extends GenericTree {
public DarkOakTree(Random random, Location location, BlockStateDelegate delegate) {
super(random, location, delegate);
setOverridables(
Material.AIR,
Material.LEAVES,
Material.LEAVES_2,
Material.GRASS,
Material.DIRT,
Material.LOG,
Material.LOG_2,
Material.SAPLING,
Material.VINE
);
setHeight(random.nextInt(2) + random.nextInt(3) + 6);
}
@Override
public boolean canPlaceOn() {
final BlockState state = delegate.getBlockState(loc.getBlock().getRelative(BlockFace.DOWN).getLocation());
return state.getType() == Material.GRASS || state.getType() == Material.DIRT;
}
@Override
public boolean generate() {
if (!canHeightFit() || !canPlaceOn() || !canPlace()) {
return false;
}
float d = (float) (random.nextFloat() * Math.PI * 2.0F); // random direction
int dx = ((int) (Math.cos(d) + 1.5F)) - 1;
int dz = ((int) (Math.sin(d) + 1.5F)) - 1;
if (Math.abs(dx) > 0 && Math.abs(dz) > 0) { // reduce possible directions to NSEW
if (random.nextBoolean()) {
dx = 0;
} else {
dz = 0;
}
}
int twistHeight = height - random.nextInt(4);
int twistCount = random.nextInt(3);
int centerX = loc.getBlockX(), centerZ = loc.getBlockZ();
int trunkTopY = 0;
// generates the trunk
for (int y = 0; y < height; y++) {
// trunk twists
if (twistCount > 0 && y >= twistHeight) {
centerX += dx;
centerZ += dz;
twistCount--;
}
final Material material = delegate.getBlockState(loc.getWorld(), centerX, loc.getBlockY() + y, centerZ).getType();
if (material == Material.AIR || material == Material.LEAVES) {
trunkTopY = loc.getBlockY() + y;
// SELF, SOUTH, EAST, SOUTH EAST
delegate.setTypeAndRawData(loc.getWorld(), centerX, loc.getBlockY() + y, centerZ, Material.LOG_2, 1);
delegate.setTypeAndRawData(loc.getWorld(), centerX, loc.getBlockY() + y, centerZ + 1, Material.LOG_2, 1);
delegate.setTypeAndRawData(loc.getWorld(), centerX + 1, loc.getBlockY() + y, centerZ, Material.LOG_2, 1);
delegate.setTypeAndRawData(loc.getWorld(), centerX + 1, loc.getBlockY() + y, centerZ + 1, Material.LOG_2, 1);
}
}
// generates leaves
for (int x = -2; x <= 0; x++) {
for (int z = -2; z <= 0; z++) {
if ((x != -1 || z != -2) && (x > -2 || z > -1)) {
setLeaves(centerX + x, trunkTopY + 1, centerZ + z);
setLeaves(1 + centerX - x, trunkTopY + 1, centerZ + z);
setLeaves(centerX + x, trunkTopY + 1, 1 + centerZ - z);
setLeaves(1 + centerX - x, trunkTopY + 1, 1 + centerZ - z);
}
setLeaves(centerX + x, trunkTopY - 1, centerZ + z);
setLeaves(1 + centerX - x, trunkTopY - 1, centerZ + z);
setLeaves(centerX + x, trunkTopY - 1, 1 + centerZ - z);
setLeaves(1 + centerX - x, trunkTopY - 1, 1 + centerZ - z);
}
}
// finish leaves below the canopy
for (int x = -3; x <= 4; x++) {
for (int z = -3; z <= 4; z++) {
if (Math.abs(x) < 3 || Math.abs(z) < 3) {
setLeaves(centerX + x, trunkTopY, centerZ + z);
}
}
}
// generates some trunk excrescences
for (int x = -1; x <= 2; x++) {
for (int z = -1; z <= 2; z++) {
if ((x == -1 || z == -1 || x == 2 || z == 2) && random.nextInt(3) == 0) {
for (int y = 0; y < random.nextInt(3) + 2; y++) {
final Material material = delegate.getBlockState(loc.getWorld(), loc.getBlockX() + x, trunkTopY - y - 1, loc.getBlockZ() + z).getType();
if (material == Material.AIR || material == Material.LEAVES) {
delegate.setTypeAndRawData(loc.getWorld(), loc.getBlockX() + x, trunkTopY - y - 1, loc.getBlockZ() + z, Material.LOG_2, 1);
}
}
// leaves below the canopy
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
setLeaves(centerX + x + i, trunkTopY, centerZ + z + j);
}
}
for (int i = -2; i <= 2; i++) {
for (int j = -2; j <= 2; j++) {
if ((Math.abs(i) < 2) || (Math.abs(j) < 2)) {
setLeaves(centerX + x + i, trunkTopY - 1, centerZ + z + j);
}
}
}
}
}
}
// 50% chance to have a 4 leaves cap on the center of the canopy
if (random.nextInt(2) == 0) {
setLeaves(centerX, trunkTopY + 2, centerZ);
setLeaves(centerX + 1, trunkTopY + 2, centerZ);
setLeaves(centerX + 1, trunkTopY + 2, centerZ + 1);
setLeaves(centerX, trunkTopY + 2, centerZ + 1);
}
// block below trunk is always dirt (SELF, SOUTH, EAST, SOUTH EAST)
final Dirt dirt = new Dirt(DirtType.NORMAL);
delegate.setTypeAndData(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ(), Material.DIRT, dirt);
delegate.setTypeAndData(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ() + 1, Material.DIRT, dirt);
delegate.setTypeAndData(loc.getWorld(), loc.getBlockX() + 1, loc.getBlockY() - 1, loc.getBlockZ(), Material.DIRT, dirt);
delegate.setTypeAndData(loc.getWorld(), loc.getBlockX() + 1, loc.getBlockY() - 1, loc.getBlockZ() + 1, Material.DIRT, dirt);
return true;
}
private void setLeaves(int x, int y, int z) {
if (delegate.getBlockState(loc.getWorld(), x, y, z).getType() == Material.AIR) {
delegate.setTypeAndRawData(loc.getWorld(), x, y, z, Material.LEAVES_2, 1);
}
}
}