diff --git a/plugins/realisticbiomes-paper/src/main/java/com/untamedears/realisticbiomes/growth/TreeGrower.java b/plugins/realisticbiomes-paper/src/main/java/com/untamedears/realisticbiomes/growth/TreeGrower.java index 3793a635e..8112153c6 100644 --- a/plugins/realisticbiomes-paper/src/main/java/com/untamedears/realisticbiomes/growth/TreeGrower.java +++ b/plugins/realisticbiomes-paper/src/main/java/com/untamedears/realisticbiomes/growth/TreeGrower.java @@ -1,28 +1,17 @@ package com.untamedears.realisticbiomes.growth; -import com.untamedears.realisticbiomes.PlantManager; -import com.untamedears.realisticbiomes.RealisticBiomes; import com.untamedears.realisticbiomes.model.Plant; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.TreeType; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.type.Sapling; +import java.util.Random; public class TreeGrower extends AgeableGrower { - - private static boolean adjacentSaplingCheck(Material mat, Block northwest) { - for (Block block : new Block[]{northwest, northwest.getRelative(1, 0, 0), northwest.getRelative(0, 0, 1), - northwest.getRelative(1, 0, 1)}) { - if (block == null) { - return false; - } - if (block.getType() != mat) { - return false; - } - } - return true; - } + private final Random random = new Random(); private static boolean canBeBig(Material mat) { switch (mat) { @@ -45,73 +34,40 @@ private static boolean canBeBig(Material mat) { } /** - * Checks whether the block is part of a valid 2x2 grid + * checks whether this sapling is the NW sapling of a valid 2x2 sapling setup * - * @param block Block to check for - * @param mat Sapling material - * @return True if the block is part of a 2x2 sapling grid and could grow large, - * false otherwise + * @param mat the material the saplings must share + * @param northwest the sapling to check for + * @return true iff this is a valid 2x2 setup */ - private static boolean canGrowBig(Block block, Material mat) { - return adjacentSaplingCheck(mat, block.getRelative(-1, 0, -1)) - || adjacentSaplingCheck(mat, block.getRelative(0, 0, -1)) - || adjacentSaplingCheck(mat, block.getRelative(-1, 0, 0)) || adjacentSaplingCheck(mat, block); + private static boolean adjacentSaplingCheck(Material mat, Block northwest) { + for (int i = 0; i < 4; i++) { + Block block = northwest.getRelative(i % 2, 0, i / 2); + if (block.getType() != mat) { + return false; + } + } + + return true; } /** - * Checks whether the block is part of a 2x2 grid and returns the north west block + * Checks whether the block is part of a 2x2 grid and returns the north west block. + * The block is tested as the northwest, northeast, southwest, and southeast sapling, + * in that order. * * @param block to check for * @param mat Sapling material * @return North west block; null if the block is not part of a 2x2 sapling grid */ - private static Block findNWSapling(Block block, Material mat) { - Block northwest = null; - for (Block nwCandidate : new Block[]{block, block.getRelative(1, 0, 1), block.getRelative(0, 0, 1), - block.getRelative(1, 0, 0)}) { + private static Block find2x2NWSapling(Block block, Material mat) { + for (int i = 0; i < 4; i++) { + Block nwCandidate = block.getRelative(-(i % 2), 0, -(i / 2)); if (adjacentSaplingCheck(mat, nwCandidate)) { - northwest = nwCandidate; - break; + return nwCandidate; } } - if (northwest == null) { - return null; - } - return northwest; - } - - private static void removeSapling(Block block) { - PlantManager manager = RealisticBiomes.getInstance().getPlantManager(); - Plant plant = manager.getPlant(block); - if (plant == null) { - return; - } - manager.deletePlant(plant); - block.setType(Material.AIR); - } - - /** - * Remove a 2x2 saplings grid if the block is part of one - * - * @param block to check for - * @param mat Sapling material - */ - private static void clearBigTreeSaplings(Block block, Material mat) { - Block northwest = null; - Block northeast, southwest, southeast; - northwest = findNWSapling(block, mat); - if (northwest == null) { - return; - } - - northeast = northwest.getRelative(BlockFace.EAST); - southwest = northwest.getRelative(BlockFace.SOUTH); - southeast = northeast.getRelative(BlockFace.SOUTH); - - removeSapling(northwest); - removeSapling(northeast); - removeSapling(southeast); - removeSapling(southwest); + return null; } private static TreeType remapSaplingToTree(Material mat, boolean big) { @@ -157,6 +113,49 @@ public int getStage(Plant plant) { return 0; } + /** + * Set the saplings of the tree to a given material + * + * @param northwest northwestern sapling of the base + * @param isBig whether to set a 2x2 or 1x1 shape + * @param mat the material to change to + */ + public void setSaplings(Block northwest, boolean isBig, Material mat) { + northwest.setType(mat); + + if (!isBig) { + return; + } + + Block northeast, southwest, southeast; + northeast = northwest.getRelative(BlockFace.EAST); + southwest = northwest.getRelative(BlockFace.SOUTH); + southeast = northeast.getRelative(BlockFace.SOUTH); + + northeast.setType(mat); + southwest.setType(mat); + southeast.setType(mat); + } + + /** + * Attempts to grow a tree at the provided position. + * It will do 10 grow attempts. + * + * @param location The position to grow the tree at. NW sapling for 2x2 trees. + * @param type The type of tree to grow at the position. + * @return True if the tree grew successfully + */ + public boolean tryGrowTree(Location location, TreeType type) { + World world = location.getWorld(); + for (int i = 0; i < 10; i++) { + if (world.generateTree(location, random, type)) { + return true; + } + } + + return false; + } + @Override public boolean setStage(Plant plant, int stage) { if (stage < 1) { @@ -170,20 +169,22 @@ public boolean setStage(Plant plant, int stage) { Material mat = block.getType(); boolean canBeBig = canBeBig(mat); if (canBeBig) { - canBeBig = canGrowBig(block, mat); + Block found = find2x2NWSapling(block, mat); + canBeBig = found != null; + + if (canBeBig) { + block = found; + } } + TreeType type = remapSaplingToTree(mat, canBeBig); if (type == null) { return true; } - if (canBeBig) { - clearBigTreeSaplings(block, mat); - } else { - block.setType(Material.AIR); - } - if (!block.getLocation().getWorld().generateTree(block.getLocation(), type)) { - //failed, so restore sapling, TODO restore 2x2 - block.setType(mat); + + setSaplings(block, canBeBig, Material.AIR); + if (!tryGrowTree(block.getLocation(), type)) { + setSaplings(block, canBeBig, mat); } return true; }