/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.pepsoft.worldpainter.layers.trees; import java.io.Serializable; import java.util.Random; import static org.pepsoft.minecraft.Constants.*; import org.pepsoft.minecraft.Direction; import org.pepsoft.minecraft.Material; import static org.pepsoft.minecraft.Material.*; import org.pepsoft.worldpainter.Dimension; import org.pepsoft.worldpainter.exporting.Cursor; import org.pepsoft.worldpainter.exporting.MinecraftWorld; /** * * @author pepijn */ public abstract class TreeType implements Serializable { protected TreeType(Material trunkMaterial, Material leafMaterial) { this.trunkMaterial = trunkMaterial; this.leafMaterial = leafMaterial; } public abstract void renderTree(int blockInWorldX, int blockInWorldY, int height, int strength, MinecraftWorld minecraftWorld, Dimension dimension, Random random); protected void renderTrunk(int blockInWorldX, int blockInWorldY, int height, int size, MinecraftWorld minecraftWorld) { minecraftWorld.setMaterialAt(blockInWorldX, blockInWorldY, height, DIRT); for (int i = 1; i < size; i++) { minecraftWorld.setMaterialAt(blockInWorldX, blockInWorldY, height + i, trunkMaterial); } minecraftWorld.setMaterialAt(blockInWorldX, blockInWorldY, height + size, getCapMaterial()); } protected final Material getCapMaterial() { if ((trunkMaterial.blockType == BLK_WOOD) || (trunkMaterial.blockType == BLK_WOOD2)) { return Material.get(trunkMaterial.blockType, (trunkMaterial.data & 0x3) | 0xC); } else { return trunkMaterial; } } protected void maybePlaceLeaves(int x, int y, int h, int r, float distance, MinecraftWorld minecraftWorld, Random random) { if (minecraftWorld.getBlockTypeAt(x, y, h) == BLK_AIR) { if (((r > 0) ? random.nextInt(r) : 0) + 1.5f >= distance) { minecraftWorld.setMaterialAt(x, y, h, leafMaterial); } } } protected void renderVines(int x, int y, int z, int size, MinecraftWorld world, Random random) { renderVines(x, y, z, size, world, random, VINE_INCIDENCE, 3, 4); } protected void renderVines(int x, int y, int z, int size, MinecraftWorld world, Random random, int vineIncidence, int vineLengthBase, int vineLengthVariation) { int r = Math.max(1, Math.min(size / 2 + 1, 4)); int maxZ = world.getMaxHeight() - 1; for (int dz = 0; dz <= size + r; dz++) { if (z + dz > maxZ) { break; } for (int dx = -r; dx <= r; dx++) { for (int dy = -r; dy <= r; dy++) { if (random.nextInt(vineIncidence) == 0) { Cursor cursor = new Cursor(world, x + dx, y + dy, z + dz, Direction.NORTH); if (cursor.isFreeOrInsubstantial()) { int turns = random.nextInt(4); for (int i = 0; i < turns; i++) { cursor.turnRight(); } if (isTreeBlock(cursor.getBlockInFront())) { int vineLength = random.nextInt(vineLengthVariation) + vineLengthBase; for (int i = 0; i < vineLength; i++) { if (((z + dz - i) <= 0) || (! addVine(world, x + dx, y + dy, z + dz - i, cursor.getDirection()))) { break; } } } } } } } } } private boolean isTreeBlock(Material material) { if (material != null) { final int blockType = material.blockType; return blockType == BLK_WOOD || blockType == BLK_WOOD2 || blockType == BLK_LEAVES || blockType == BLK_LEAVES2; } else { return false; } } private boolean addVine(MinecraftWorld world, int x, int y, int z, Direction direction) { Material existingBlock = world.getMaterialAt(x, y, z); if ((existingBlock == null) || ((existingBlock != AIR) && (existingBlock.blockType != BLK_VINES))) { return false; } int data = existingBlock.data; switch (direction) { case NORTH: data |= 0x4; break; case EAST: data |= 0x8; break; case SOUTH: data |= 0x1; break; case WEST: data |= 0x2; break; } if (existingBlock == AIR) { world.setBlockTypeAt(x, y, z, BLK_VINES); } world.setDataAt(x, y, z, data); return true; } protected final Material trunkMaterial, leafMaterial; private static final int VINE_INCIDENCE = 5; private static final long serialVersionUID = 1L; }