From f9cac11d7a580f50572661661f02048f777309e9 Mon Sep 17 00:00:00 2001 From: Esophose Date: Sun, 17 Feb 2019 01:37:31 -0700 Subject: [PATCH] Add config setting to require entire tree base to be broken --- .../configurations/DefaultConfig.java | 2 ++ .../treefall/AxeDurability.java | 4 +++ .../ultimatetimber/treefall/TreeChecker.java | 17 +++++++++++++ .../ultimatetimber/treefall/TreeReplant.java | 25 +++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/songoda/ultimatetimber/configurations/DefaultConfig.java b/src/main/java/com/songoda/ultimatetimber/configurations/DefaultConfig.java index b2f7d83..efed38a 100644 --- a/src/main/java/com/songoda/ultimatetimber/configurations/DefaultConfig.java +++ b/src/main/java/com/songoda/ultimatetimber/configurations/DefaultConfig.java @@ -18,6 +18,7 @@ public class DefaultConfig { public static final String LEAVES_FOR_TREE = "The number of leaves required to detect a valid tree"; public static final String ONLY_BREAK_LOGS_UPWARDS = "Only break logs above the block broken"; public static final String ALLOW_MIXED_TREE_TYPES = "Allow mixed log/leaf to be considered as one tree"; + public static final String ENTIRE_TREE_BASE = "Entire tree base must be broken for the tree to fall"; public static final String AXES_ONLY = "Only topple down trees cut down using axes"; public static final String TIMEOUT_BREAK = "Five second time out before you can break saplings"; public static final String SNEAK_ONLY = "Only topple down trees cut down while sneaking"; @@ -44,6 +45,7 @@ public class DefaultConfig { configuration.addDefault(LEAVES_FOR_TREE, 5); configuration.addDefault(ONLY_BREAK_LOGS_UPWARDS, true); configuration.addDefault(ALLOW_MIXED_TREE_TYPES, false); + configuration.addDefault(ENTIRE_TREE_BASE, false); configuration.addDefault(AXES_ONLY, true); configuration.addDefault(TIMEOUT_BREAK, true); configuration.addDefault(SNEAK_ONLY, false); diff --git a/src/main/java/com/songoda/ultimatetimber/treefall/AxeDurability.java b/src/main/java/com/songoda/ultimatetimber/treefall/AxeDurability.java index c7616f4..1eadcef 100644 --- a/src/main/java/com/songoda/ultimatetimber/treefall/AxeDurability.java +++ b/src/main/java/com/songoda/ultimatetimber/treefall/AxeDurability.java @@ -3,6 +3,7 @@ package com.songoda.ultimatetimber.treefall; import java.util.HashSet; import java.util.Random; +import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; @@ -24,6 +25,9 @@ public class AxeDurability { * @param player The player */ public static void adjustAxeDamage(HashSet blocks, Player player) { + if (player.getGameMode().equals(GameMode.CREATIVE)) + return; + ItemStack item = player.getInventory().getItemInMainHand(); Material itemType = item.getType(); diff --git a/src/main/java/com/songoda/ultimatetimber/treefall/TreeChecker.java b/src/main/java/com/songoda/ultimatetimber/treefall/TreeChecker.java index 9544f6f..6eb0503 100644 --- a/src/main/java/com/songoda/ultimatetimber/treefall/TreeChecker.java +++ b/src/main/java/com/songoda/ultimatetimber/treefall/TreeChecker.java @@ -81,6 +81,7 @@ public class TreeChecker { private boolean allowMixedTreeTypes; private boolean onlyBreakLogsUpwards; private boolean destroyBaseLog; + private boolean entireTreeBase; private boolean isMushroom = false; static { @@ -131,6 +132,7 @@ public class TreeChecker { this.numLeavesRequiredForTree = config.getInt(DefaultConfig.LEAVES_FOR_TREE); this.onlyBreakLogsUpwards = config.getBoolean(DefaultConfig.ONLY_BREAK_LOGS_UPWARDS); this.destroyBaseLog = config.getBoolean(DefaultConfig.DELETE_BROKEN_LOG); + this.entireTreeBase = config.getBoolean(DefaultConfig.ENTIRE_TREE_BASE); // Detect tree trunk Set trunkBlocks = new HashSet<>(); @@ -161,6 +163,21 @@ public class TreeChecker { if (!this.isMushroom && this.treeBlocks.stream().filter(x -> this.isValidLeafType(x.getType())).count() < this.numLeavesRequiredForTree) return null; + // All logs must not have a plantable surface below them (if enabled) + if (this.entireTreeBase) { + boolean isTreeGrounded = this.treeBlocks.stream().anyMatch(x -> { + Material typeBelow = x.getRelative(BlockFace.DOWN).getType(); + return (typeBelow.equals(Material.DIRT) || + typeBelow.equals(Material.COARSE_DIRT) || + typeBelow.equals(Material.PODZOL) || + typeBelow.equals(Material.GRASS_BLOCK)) && + !x.equals(block) && + isValidLogType(x.getType()); + }); + if (isTreeGrounded) + return null; + } + // Delete the starting block if applicable if (this.destroyBaseLog) this.treeBlocks.remove(block); diff --git a/src/main/java/com/songoda/ultimatetimber/treefall/TreeReplant.java b/src/main/java/com/songoda/ultimatetimber/treefall/TreeReplant.java index 9bf7a5a..5b4ea34 100644 --- a/src/main/java/com/songoda/ultimatetimber/treefall/TreeReplant.java +++ b/src/main/java/com/songoda/ultimatetimber/treefall/TreeReplant.java @@ -8,6 +8,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.entity.FallingBlock; import org.bukkit.util.Vector; @@ -21,14 +22,26 @@ class TreeReplant { static void replaceOriginalBlock(Block block) { boolean isTimeout = UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.TIMEOUT_BREAK); + Material material = WoodToLogConverter.convert(block.getType()); if (!UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.REPLANT_SAPLING)) { block.setType(Material.AIR); return; } - Material belowBlockType = block.getLocation().clone().subtract(new Vector(0, 1, 0)).getBlock().getType(); - if (!belowBlockType.equals(Material.DIRT) && !belowBlockType.equals(Material.COARSE_DIRT) && !belowBlockType.equals(Material.PODZOL) && !belowBlockType.equals(Material.GRASS_BLOCK)) { + Block below = block.getRelative(BlockFace.DOWN); + Material belowType = below.getType(); + if (belowType.equals(Material.AIR) && UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.ENTIRE_TREE_BASE)) { + if (isValidGround(below.getRelative(BlockFace.DOWN).getType())) { + if (isTimeout) { + timeout.add(below.getLocation()); + Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> timeout.remove(below.getLocation()), 20 * 5); + } + Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> performReplacement(below, material), 1); + } + } + + if (!isValidGround(belowType)) { block.setType(Material.AIR); return; } @@ -38,7 +51,6 @@ class TreeReplant { Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> timeout.remove(block.getLocation()), 20 * 5); } - Material material = WoodToLogConverter.convert(block.getType()); Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> performReplacement(block, material), 1); } @@ -112,11 +124,10 @@ class TreeReplant { Block block = fallingBlock.getLocation().clone().subtract(new Vector(0, 1, 0)).getBlock(); - if (block.getType().equals(Material.DIRT) || block.getType().equals(Material.COARSE_DIRT) || block.getType().equals(Material.PODZOL) || block.getType().equals(Material.GRASS_BLOCK)) { + if (isValidGround(block.getType())) { Block blockAbove = block.getLocation().clone().add(new Vector(0, 1, 0)).getBlock(); if (blockAbove.getType().equals(Material.AIR)) fallingBlock.getLocation().getBlock().setType(material); - } } @@ -124,5 +135,9 @@ class TreeReplant { static boolean isTimeout(Block block) { return timeout.contains(block.getLocation()); } + + private static boolean isValidGround(Material material) { + return material.equals(Material.DIRT) || material.equals(Material.COARSE_DIRT) || material.equals(Material.PODZOL) || material.equals(Material.GRASS_BLOCK); + } }