package com.jaquadro.minecraft.gardentrees.world.gen; import com.jaquadro.minecraft.gardencore.api.WoodRegistry; import com.jaquadro.minecraft.gardencore.block.BlockGarden; import com.jaquadro.minecraft.gardentrees.block.tile.TileEntityWoodProxy; import com.jaquadro.minecraft.gardentrees.core.ModBlocks; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.world.World; import net.minecraft.world.gen.feature.WorldGenAbstractTree; import java.util.Random; public abstract class WorldGenOrnamentalTree extends WorldGenAbstractTree { private final Block wood; private final Block leaves; private final int metaWood; private final int metaLeaves; protected enum LayerType { LEAF, TRUNK, CORE; } protected final static String PAT_1X1 = "T"; protected final static String PAT_3X3 = "XXX" + "XTX" + "XXX"; protected final static String PAT_3X3PLUS = " X " + "XTX" + " X "; protected final static String PAT_3X3IPLUS = "X X" + " T " + "X X"; protected final static String PAT_3X3UNBAL = "0X " + "XTX" + " X "; protected final static String PAT_3X3OPT = " 0 " + "1X2" + " 3 "; protected final static String PAT_5X5 = "XXXXX" + "XXXXX" + "XXTXX" + "XXXXX" + "XXXXX"; protected final static String PAT_5X5PLUS = " X " + " XXX " + "XXTXX" + " XXX " + " X "; protected final static String PAT_5X5PLUS2 = " XXX " + "XXXXX" + "XXTXX" + "XXXXX" + " XXX "; protected final static String PAT_5X5PLUS2N = " X X " + "XXXXX" + " XTX " + "XXXXX" + " X X "; protected final static String PAT_5X5PLUS2T = " XXX " + "XXTXX" + "XTTTX" + "XXTXX" + " XXX "; protected final static String PAT_5X5UNBAL = " 00 " + "0XXX " + "0XTX " + " XXX " + " "; protected static String transform (String pattern, LayerType type) { return transform(pattern, type, 0); } protected static String transform (String pattern, LayerType type, int option) { int groups = countOptionGroups(pattern); for (int i = 0; i < groups; i++) { if (((option >> i) & 1) == 0) pattern = pattern.replace((char)('0' + i), ' '); else pattern = pattern.replace((char)('0' + i), 'X'); } if (type == LayerType.LEAF) pattern = pattern.replace('T', 'X'); else if (type == LayerType.TRUNK) pattern = pattern.replace('X', 'T'); boolean flipH = ((option >>> 30) & 1) == 1; boolean flipV = ((option >>> 31) & 1) == 1; if (flipH && flipV) pattern = new StringBuilder(pattern).reverse().toString(); else if (flipH) { int dim = getPatternDim(pattern); StringBuilder sb = new StringBuilder(pattern); for (int y = 0; y < dim; y++) { int base = y * dim; for (int x = 0; x < dim; x++) sb.setCharAt(base + x, pattern.charAt(base + dim - x - 1)); } pattern = sb.toString(); } else if (flipV) { int dim = getPatternDim(pattern); StringBuilder sb = new StringBuilder(pattern); for (int y = 0; y < dim; y++) { int base = y * dim; int base2 = (dim - y - 1) * dim; for (int x = 0; x < dim; x++) sb.setCharAt(base + x, pattern.charAt(base2 + x)); } pattern = sb.toString(); } return pattern; } private static int countOptionGroups (String pattern) { char high = '0' - 1; for (int i = 0, n = pattern.length(); i < n; i++) { char c = pattern.charAt(i); if (c >= '0' && c <= '9' && c > high) high = c; } return high - '0' + 1; } public WorldGenOrnamentalTree (boolean blockNotify, Block wood, int metaWood, Block leaves, int metaLeaves) { super(blockNotify); /*if (wood != ModBlocks.thinLog) { metaWood = TileEntityWoodProxy.composeMetadata(wood, metaWood); wood = ModBlocks.thinLog; }*/ this.wood = wood; this.leaves = leaves; this.metaWood = metaWood; this.metaLeaves = metaLeaves; } @Override public boolean generate (World world, Random rand, int x, int y, int z) { int height = getNeighborAirCount(world, x, y - 1, z) >= 6 ? 5 : 6; int trunkHeight = height - 4; prepare(world, rand, x, y, z, trunkHeight); if (!canGenerate(world, x, y, z, height)) return false; generateCanopy(world, x, y, z, trunkHeight); generateTrunk(world, x, y, z, trunkHeight); return true; } private int getNeighborAirCount (World world, int x, int y, int z) { int count = 0; count += world.isAirBlock(x - 1, y, z - 1) ? 1 : 0; count += world.isAirBlock(x - 1, y, z) ? 1 : 0; count += world.isAirBlock(x - 1, y, z + 1) ? 1 : 0; count += world.isAirBlock(x, y, z - 1) ? 1 : 0; count += world.isAirBlock(x, y, z + 1) ? 1 : 0; count += world.isAirBlock(x + 1, y, z - 1) ? 1 : 0; count += world.isAirBlock(x + 1, y, z) ? 1 : 0; count += world.isAirBlock(x + 1, y, z + 1) ? 1 : 0; return count; } private boolean canGenerate (World world, int x, int y, int z, int height) { int trunkHeight = height - 4; if (y + height > 256) return false; return canGenerateTrunk(world, x, y, z, trunkHeight) && canGenerateCanopy(world, x, y, z, trunkHeight); } protected void prepare (World world, Random rand, int x, int y, int z, int trunkHeight) { } protected boolean canGenerateTrunk (World world, int x, int y, int z, int trunkHeight) { for (int iy = y; iy < y + trunkHeight; iy++) { if (!isReplaceable(world, x, iy, z)) return false; } return true; } protected abstract boolean canGenerateCanopy (World world, int x, int y, int z, int trunkHeight); protected void generateTrunk (World world, int x, int y, int z, int trunkHeight) { for (int iy = y; iy < y + trunkHeight + 1; iy++) generateBlock(world, x, iy, z, wood, metaWood); } protected abstract void generateCanopy (World world, int x, int y, int z, int trunkHeight); private static int getPatternDim (String pattern) { return (int)Math.floor(Math.sqrt(pattern.length())); } protected boolean canGeneratePattern (World world, int x, int y, int z, String pattern) { int dim = getPatternDim(pattern) / 2; for (int ix = x - dim; ix <= x + dim; ix++) { for (int iz = z - dim; iz <= z + dim; iz++) { int index = (iz - z + dim) * (dim * 2 + 1) + (ix - x + dim); if ((pattern.charAt(index) == 'X' || pattern.charAt(index) == 'T') && !isReplaceable(world, ix, y, iz)) return false; } } return true; } protected void generatePattern (World world, int x, int y, int z, String pattern) { int dim = getPatternDim(pattern) / 2; for (int ix = x - dim; ix <= x + dim; ix++) { for (int iz = z - dim; iz <= z + dim; iz++) { int index = (iz - z + dim) * (dim * 2 + 1) + (ix - x + dim); if (pattern.charAt(index) == 'X') generateBlock(world, ix, y, iz); else if (pattern.charAt(index) == 'T') generateTrunk(world, ix, y, iz); } } } private void generateBlock (World world, int x, int y, int z) { Block block = world.getBlock(x, y, z); if (block.isAir(world, x, y, z) || block.isLeaves(world, x, y, z)) setBlockAndNotifyAdequately(world, x, y, z, leaves, metaLeaves); } private void generateTrunk (World world, int x, int y, int z) { generateBlock(world, x, y, z, wood, metaWood); } private void generateBlock (World world, int x, int y, int z, Block block, int meta) { Block existingBlock = world.getBlock(x, y, z); if (existingBlock.isAir(world, x, y, z) || existingBlock.isLeaves(world, x, y, z)) { if (block == Blocks.log) setBlockAndNotifyAdequately(world, x, y, z, ModBlocks.thinLog, meta % 4); else if (block == Blocks.log2) setBlockAndNotifyAdequately(world, x, y, z, ModBlocks.thinLog, meta % 4 + 4); else if (WoodRegistry.instance().contains(block, meta)) { setBlockAndNotifyAdequately(world, x, y, z, block, 0); TileEntityWoodProxy te = new TileEntityWoodProxy(); te.setProtoBlock(block, meta); setBlockAndNotifyAdequately(world, x, y, z, ModBlocks.thinLog, 0); world.setTileEntity(x, y, z, te); } else setBlockAndNotifyAdequately(world, x, y, z, block, meta); } } @Override protected boolean isReplaceable (World world, int x, int y, int z) { Block block = world.getBlock(x, y, z); return super.isReplaceable(world, x, y, z); } }