diff --git a/src/main/java/com/songoda/ultimatetimber/UltimateTimber.java b/src/main/java/com/songoda/ultimatetimber/UltimateTimber.java index 0d165d4..2f91346 100644 --- a/src/main/java/com/songoda/ultimatetimber/UltimateTimber.java +++ b/src/main/java/com/songoda/ultimatetimber/UltimateTimber.java @@ -31,6 +31,7 @@ public class UltimateTimber extends JavaPlugin { private CommandManager commandManager; private ConfigurationManager configurationManager; private HookManager hookManager; + private SaplingManager saplingManager; private TreeAnimationManager treeAnimationManager; private TreeDefinitionManager treeDefinitionManager; private TreeDetectionManager treeDetectionManager; @@ -44,15 +45,16 @@ public class UltimateTimber extends JavaPlugin { public void onEnable() { INSTANCE = this; - console.sendMessage(Methods.formatText("&a=============================")); - console.sendMessage(Methods.formatText("&7" + this.getDescription().getName() + " " + this.getDescription().getVersion() + " by &5Songoda <3&7!")); - console.sendMessage(Methods.formatText("&7Action: &aEnabling&7...")); + this.console.sendMessage(Methods.formatText("&a=============================")); + this.console.sendMessage(Methods.formatText("&7" + this.getDescription().getName() + " " + this.getDescription().getVersion() + " by &5Songoda <3&7!")); + this.console.sendMessage(Methods.formatText("&7Action: &aEnabling&7...")); this.managers = new HashSet<>(); this.choppingManager = this.registerManager(ChoppingManager.class); this.commandManager = this.registerManager(CommandManager.class); this.configurationManager = new ConfigurationManager(this); this.hookManager = this.registerManager(HookManager.class); + this.saplingManager = this.registerManager(SaplingManager.class); this.treeAnimationManager = this.registerManager(TreeAnimationManager.class); this.treeDefinitionManager = this.registerManager(TreeDefinitionManager.class); this.treeDetectionManager = this.registerManager(TreeDetectionManager.class); @@ -62,19 +64,19 @@ public class UltimateTimber extends JavaPlugin { this.reload(); new Metrics(this); - - console.sendMessage(Methods.formatText("&a=============================")); + + this.console.sendMessage(Methods.formatText("&a=============================")); } @Override public void onDisable() { - console.sendMessage(Methods.formatText("&a=============================")); - console.sendMessage(Methods.formatText("&7" + this.getDescription().getName() + " " + this.getDescription().getVersion() + " by &5Songoda <3&7!")); - console.sendMessage(Methods.formatText("&7Action: &cDisabling&7...")); + this.console.sendMessage(Methods.formatText("&a=============================")); + this.console.sendMessage(Methods.formatText("&7" + this.getDescription().getName() + " " + this.getDescription().getVersion() + " by &5Songoda <3&7!")); + this.console.sendMessage(Methods.formatText("&7Action: &cDisabling&7...")); this.disable(); - - console.sendMessage(Methods.formatText("&a=============================")); + + this.console.sendMessage(Methods.formatText("&a=============================")); } /** @@ -164,7 +166,7 @@ public class UltimateTimber extends JavaPlugin { * @return The ConfigurationManager instance */ public ConfigurationManager getConfigurationManager() { - return configurationManager; + return this.configurationManager; } /** @@ -173,7 +175,16 @@ public class UltimateTimber extends JavaPlugin { * @return The HookManager instance */ public HookManager getHookManager() { - return hookManager; + return this.hookManager; + } + + /** + * Gets the sapling manager + * + * @return The SaplingManager instance + */ + public SaplingManager getSaplingManager() { + return this.saplingManager; } /** @@ -182,7 +193,7 @@ public class UltimateTimber extends JavaPlugin { * @return The TreeAnimationManager instance */ public TreeAnimationManager getTreeAnimationManager() { - return treeAnimationManager; + return this.treeAnimationManager; } /** @@ -191,7 +202,7 @@ public class UltimateTimber extends JavaPlugin { * @return The TreeDefinitionManager instance */ public TreeDefinitionManager getTreeDefinitionManager() { - return treeDefinitionManager; + return this.treeDefinitionManager; } /** @@ -200,7 +211,7 @@ public class UltimateTimber extends JavaPlugin { * @return The TreeDetectionManager instance */ public TreeDetectionManager getTreeDetectionManager() { - return treeDetectionManager; + return this.treeDetectionManager; } /** @@ -209,7 +220,7 @@ public class UltimateTimber extends JavaPlugin { * @return The TreeFallManager instance */ public TreeFallManager getTreeFallManager() { - return treeFallManager; + return this.treeFallManager; } } diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/IBlockData.java b/src/main/java/com/songoda/ultimatetimber/adapter/IBlockData.java index 58e33ee..3670237 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/IBlockData.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/IBlockData.java @@ -33,4 +33,11 @@ public interface IBlockData { */ boolean isSimilar(Block block); + /** + * Sets a given Block to use this IBlockData + * + * @param block The Block to set + */ + void setBlock(Block block); + } diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/VersionAdapter.java b/src/main/java/com/songoda/ultimatetimber/adapter/VersionAdapter.java index afe3410..34ee3f6 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/VersionAdapter.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/VersionAdapter.java @@ -5,6 +5,7 @@ import com.songoda.ultimatetimber.tree.TreeBlock; import com.songoda.ultimatetimber.tree.TreeBlockSet; import org.bukkit.block.Block; import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import java.util.Collection; @@ -45,10 +46,19 @@ public interface VersionAdapter { /** * Applies damage to a tool * - * @param treeBlocks The Set of tree blocks that are being broken * @param tool The tool to apply damage to + * @param damage The amount of damage to apply */ - void applyToolDurability(TreeBlockSet treeBlocks, ItemStack tool); + void applyToolDurability(ItemStack tool, int damage); + + /** + * Checks if a given tool has enough durability remaining + * + * @param tool The tool to check + * @param requiredAmount The amount of durability required + * @return True if enough durability is remaining to not break the tool, otherwise false + */ + boolean hasEnoughDurability(ItemStack tool, int requiredAmount); /** * Gets the item in the player's main hand diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentAdapter.java b/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentAdapter.java index cb150d1..d6b256f 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentAdapter.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentAdapter.java @@ -35,13 +35,18 @@ public class CurrentAdapter implements VersionAdapter { } @Override - public void applyToolDurability(TreeBlockSet treeBlocks, ItemStack tool) { + public void applyToolDurability(ItemStack tool, int damage) { } + @Override + public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) { + return false; + } + @Override public ItemStack getItemInHand(Player player) { - return null; + return player.getInventory().getItemInMainHand(); } @Override diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentBlockData.java b/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentBlockData.java index 825c962..24738bc 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentBlockData.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/current/CurrentBlockData.java @@ -32,4 +32,9 @@ public class CurrentBlockData implements IBlockData { return this.material.equals(block.getType()); } + @Override + public void setBlock(Block block) { + block.setType(this.material); + } + } diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyAdapter.java b/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyAdapter.java index 51cffd9..ebe8544 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyAdapter.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyAdapter.java @@ -12,6 +12,7 @@ import org.bukkit.inventory.ItemStack; import java.util.Collection; +@SuppressWarnings("deprecation") public class LegacyAdapter implements VersionAdapter { @Override @@ -35,13 +36,18 @@ public class LegacyAdapter implements VersionAdapter { } @Override - public void applyToolDurability(TreeBlockSet treeBlocks, ItemStack tool) { + public void applyToolDurability(ItemStack tool, int damage) { } + @Override + public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) { + return false; + } + @Override public ItemStack getItemInHand(Player player) { - return null; + return player.getItemInHand(); } @Override diff --git a/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyBlockData.java b/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyBlockData.java index 1d51e8d..2057e4d 100644 --- a/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyBlockData.java +++ b/src/main/java/com/songoda/ultimatetimber/adapter/legacy/LegacyBlockData.java @@ -37,4 +37,11 @@ public class LegacyBlockData implements IBlockData { return this.material.equals(blockMaterial) && this.data == blockData; } + @Override + public void setBlock(Block block) { + block.setType(this.material); + // TODO: Break into maven modules so this can use a 1.12.2 jar for compiling instead + // block.setData(this.data); + } + } diff --git a/src/main/java/com/songoda/ultimatetimber/events/TreeEvent.java b/src/main/java/com/songoda/ultimatetimber/events/TreeEvent.java index 09a47e8..434d91e 100644 --- a/src/main/java/com/songoda/ultimatetimber/events/TreeEvent.java +++ b/src/main/java/com/songoda/ultimatetimber/events/TreeEvent.java @@ -1,7 +1,6 @@ package com.songoda.ultimatetimber.events; -import com.songoda.ultimatetimber.tree.TreeBlockSet; -import org.bukkit.block.Block; +import com.songoda.ultimatetimber.tree.DetectedTree; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerEvent; @@ -10,11 +9,11 @@ import org.bukkit.event.player.PlayerEvent; */ public abstract class TreeEvent extends PlayerEvent { - protected final TreeBlockSet treeBlocks; + protected final DetectedTree detectedTree; - public TreeEvent(Player player, TreeBlockSet treeBlocks) { + public TreeEvent(Player player, DetectedTree detectedTree) { super(player); - this.treeBlocks = treeBlocks; + this.detectedTree = detectedTree; } /** @@ -22,8 +21,8 @@ public abstract class TreeEvent extends PlayerEvent { * * @return The blocks that are part of the tree */ - public TreeBlockSet getTreeBlocks() { - return this.treeBlocks; + public DetectedTree getDetectedTree() { + return this.detectedTree; } } diff --git a/src/main/java/com/songoda/ultimatetimber/events/TreeFallEvent.java b/src/main/java/com/songoda/ultimatetimber/events/TreeFallEvent.java index 9e7d9d5..57b44b0 100644 --- a/src/main/java/com/songoda/ultimatetimber/events/TreeFallEvent.java +++ b/src/main/java/com/songoda/ultimatetimber/events/TreeFallEvent.java @@ -1,7 +1,6 @@ package com.songoda.ultimatetimber.events; -import com.songoda.ultimatetimber.tree.TreeBlockSet; -import org.bukkit.block.Block; +import com.songoda.ultimatetimber.tree.DetectedTree; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; @@ -13,8 +12,8 @@ public class TreeFallEvent extends TreeEvent implements Cancellable { private boolean cancelled = false; - public TreeFallEvent(Player player, TreeBlockSet treeBlocks) { - super(player, treeBlocks); + public TreeFallEvent(Player player, DetectedTree detectedTree) { + super(player, detectedTree); } private static final HandlerList handlers = new HandlerList(); diff --git a/src/main/java/com/songoda/ultimatetimber/events/TreeFellEvent.java b/src/main/java/com/songoda/ultimatetimber/events/TreeFellEvent.java index 7abdf39..8eda83f 100644 --- a/src/main/java/com/songoda/ultimatetimber/events/TreeFellEvent.java +++ b/src/main/java/com/songoda/ultimatetimber/events/TreeFellEvent.java @@ -1,7 +1,6 @@ package com.songoda.ultimatetimber.events; -import com.songoda.ultimatetimber.tree.TreeBlockSet; -import org.bukkit.block.Block; +import com.songoda.ultimatetimber.tree.DetectedTree; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; @@ -10,8 +9,8 @@ import org.bukkit.event.HandlerList; */ public class TreeFellEvent extends TreeEvent { - public TreeFellEvent(Player player, TreeBlockSet treeBlocks) { - super(player, treeBlocks); + public TreeFellEvent(Player player, DetectedTree detectedTree) { + super(player, detectedTree); } private static final HandlerList handlers = new HandlerList(); diff --git a/src/main/java/com/songoda/ultimatetimber/hooks/McMMOHook.java b/src/main/java/com/songoda/ultimatetimber/hooks/McMMOHook.java index a65a976..7aae868 100644 --- a/src/main/java/com/songoda/ultimatetimber/hooks/McMMOHook.java +++ b/src/main/java/com/songoda/ultimatetimber/hooks/McMMOHook.java @@ -22,21 +22,21 @@ public class McMMOHook implements TimberHook { for (Object enumValue : primarySkillTypeClass.getEnumConstants()) { Enum primarySkillTypeEnum = (Enum) enumValue; if (primarySkillTypeEnum.name().equals("WOODCUTTING")) { - woodcuttingEnum = primarySkillTypeEnum; + this.woodcuttingEnum = primarySkillTypeEnum; break; } } - getXpMethod = ExperienceConfig.class.getMethod("getXp", woodcuttingEnum.getClass(), Material.class); + this.getXpMethod = ExperienceConfig.class.getMethod("getXp", this.woodcuttingEnum.getClass(), Material.class); } catch (Exception ex) { Class skillTypeClass = Class.forName("com.gmail.nossr50.datatypes.skills.SkillType"); for (Object enumValue : skillTypeClass.getEnumConstants()) { Enum skillTypeEnum = (Enum) enumValue; if (skillTypeEnum.name().equals("WOODCUTTING")) { - woodcuttingEnum = skillTypeEnum; + this.woodcuttingEnum = skillTypeEnum; break; } } - getXpMethod = ExperienceConfig.class.getMethod("getXp", woodcuttingEnum.getClass(), Material.class); + this.getXpMethod = ExperienceConfig.class.getMethod("getXp", this.woodcuttingEnum.getClass(), Material.class); } } @@ -50,7 +50,7 @@ public class McMMOHook implements TimberHook { Block block = treeBlock.getBlock(); Material material = block.getType(); if (!material.name().endsWith("LOG")) continue; - xp += (int) getXpMethod.invoke(ExperienceConfig.getInstance(), woodcuttingEnum, material); + xp += (int) this.getXpMethod.invoke(ExperienceConfig.getInstance(), this.woodcuttingEnum, material); } ExperienceAPI.addXP(player, "woodcutting", xp, "pve"); diff --git a/src/main/java/com/songoda/ultimatetimber/manager/CommandManager.java b/src/main/java/com/songoda/ultimatetimber/manager/CommandManager.java index e96a67c..560d2da 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/CommandManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/CommandManager.java @@ -35,7 +35,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) { if (args.length > 0) { if (args[0].equalsIgnoreCase("reload")) { - if (commandSender instanceof Player && !permCheck((Player) commandSender, "ultimatetimber.reload")) + if (commandSender instanceof Player && !this.permCheck((Player) commandSender, "ultimatetimber.reload")) return true; UltimateTimber.getInstance().reload(); @@ -47,7 +47,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl return true; } - if (!permCheck((Player) commandSender, "ultimatetimber.toggle")) + if (!this.permCheck((Player) commandSender, "ultimatetimber.toggle")) return true; if (UltimateTimber.getInstance().getChoppingManager().togglePlayer((Player)commandSender)) { @@ -81,7 +81,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl public List onTabComplete(CommandSender commandSender, Command command, String s, String[] args) { List completions = new ArrayList<>(); - if (args.length == 0 || args.length > 1) + if (args.length < 1) return completions; Set possibleCompletions = new HashSet<>(); diff --git a/src/main/java/com/songoda/ultimatetimber/manager/ConfigurationManager.java b/src/main/java/com/songoda/ultimatetimber/manager/ConfigurationManager.java index 8cff42d..616a950 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/ConfigurationManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/ConfigurationManager.java @@ -10,10 +10,12 @@ import java.util.List; public class ConfigurationManager extends Manager { public enum Setting { + SERVER_TYPE, DISABLED_WORLDS, MAX_LOGS_PER_CHOP, LEAVES_REQUIRED_FOR_TREE, REALISTIC_TOOL_DAMAGE, + PROTECT_TOOL, BREAK_ENTIRE_TREE_BASE, DESTROY_INITIATED_BLOCK, ONLY_DETECT_LOGS_UPWARDS, @@ -29,6 +31,8 @@ public class ConfigurationManager extends Manager { FALLING_BLOCK_DAMAGE, ADD_ITEMS_TO_INVENTORY, USE_CUSTOM_SOUNDS, + USE_CUSTOM_PARTICLES, + BONUS_LOOT_MULTIPLIER, SCATTER_TREE_BLOCKS_ON_GROUND, MIX_ALL_TREE_TYPES; @@ -41,7 +45,7 @@ public class ConfigurationManager extends Manager { */ public boolean getBoolean() { this.loadValue(); - return (boolean)value; + return (boolean)this.value; } /** @@ -51,7 +55,27 @@ public class ConfigurationManager extends Manager { */ public int getInt() { this.loadValue(); - return (int)value; + return (int)this.value; + } + + /** + * Gets the setting as a double + * + * @return The setting a double + */ + public double getDouble() { + this.loadValue(); + return (double)this.value; + } + + /** + * Gets the setting as a String + * + * @return The setting a String + */ + public String getString() { + this.loadValue(); + return (String)this.value; } /** @@ -62,7 +86,7 @@ public class ConfigurationManager extends Manager { @SuppressWarnings("unchecked") public List getStringList() { this.loadValue(); - return (List)value; + return (List)this.value; } /** @@ -77,7 +101,7 @@ public class ConfigurationManager extends Manager { */ private void loadValue() { if (this.value == null) - value = UltimateTimber.getInstance().getConfigurationManager().getConfig().get(this.getNameAsKey()); + this.value = UltimateTimber.getInstance().getConfigurationManager().getConfig().get(this.getNameAsKey()); } /** @@ -98,21 +122,21 @@ public class ConfigurationManager extends Manager { @Override public void reload() { - File configFile = new File(ultimateTimber.getDataFolder() + "/config.yml"); + File configFile = new File(this.ultimateTimber.getDataFolder() + "/config.yml"); // If an old config still exists, rename it so it doesn't interfere - if (configFile.exists() && ultimateTimber.getConfig().get("server-type") == null) { - File renameConfigTo = new File(ultimateTimber.getDataFolder() + "/config-old.yml"); + if (configFile.exists() && this.ultimateTimber.getConfig().get("server-type") == null) { + File renameConfigTo = new File(this.ultimateTimber.getDataFolder() + "/config-old.yml"); configFile.renameTo(renameConfigTo); - configFile = new File(ultimateTimber.getDataFolder() + "/config.yml"); + configFile = new File(this.ultimateTimber.getDataFolder() + "/config.yml"); } // Create the new config if it doesn't exist if (!configFile.exists()) { - boolean isCurrentConfig = ultimateTimber.getVersionAdapter().getVersionAdapterType() == VersionAdapterType.CURRENT; + boolean isCurrentConfig = this.ultimateTimber.getVersionAdapter().getVersionAdapterType() == VersionAdapterType.CURRENT; String newConfigName = "config-" + (isCurrentConfig ? "current" : "legacy") + ".yml"; - File newConfigFile = new File(ultimateTimber.getDataFolder() + "/" + newConfigName); - ultimateTimber.saveResource(newConfigName, false); + File newConfigFile = new File(this.ultimateTimber.getDataFolder() + "/" + newConfigName); + this.ultimateTimber.saveResource(newConfigName, false); newConfigFile.renameTo(configFile); } @@ -137,4 +161,4 @@ public class ConfigurationManager extends Manager { return this.configuration; } -} \ No newline at end of file +} diff --git a/src/main/java/com/songoda/ultimatetimber/manager/HookManager.java b/src/main/java/com/songoda/ultimatetimber/manager/HookManager.java index f4617be..6707afa 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/HookManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/HookManager.java @@ -18,6 +18,7 @@ public class HookManager extends Manager { public HookManager(UltimateTimber ultimateTimber) { super(ultimateTimber); + this.hooks = new HashSet<>(); } @Override diff --git a/src/main/java/com/songoda/ultimatetimber/manager/SaplingManager.java b/src/main/java/com/songoda/ultimatetimber/manager/SaplingManager.java new file mode 100644 index 0000000..ef151d2 --- /dev/null +++ b/src/main/java/com/songoda/ultimatetimber/manager/SaplingManager.java @@ -0,0 +1,99 @@ +package com.songoda.ultimatetimber.manager; + +import com.songoda.ultimatetimber.UltimateTimber; +import com.songoda.ultimatetimber.adapter.IBlockData; +import com.songoda.ultimatetimber.tree.TreeDefinition; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; + +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +public class SaplingManager extends Manager { + + private Random random; + private Set protectedSaplings; + + public SaplingManager(UltimateTimber ultimateTimber) { + super(ultimateTimber); + this.random = new Random(); + this.protectedSaplings = new HashSet<>(); + } + + @Override + public void reload() { + + } + + @Override + public void disable() { + + } + + /** + * Replants a sapling given a TreeDefinition and Location + * Takes into account config settings + * + * @param treeDefinition The TreeDefinition of the sapling + * @param location The Location to plant the sapling + */ + public void replantSapling(TreeDefinition treeDefinition, Location location) { + if (!ConfigurationManager.Setting.REPLANT_SAPLINGS.getBoolean()) + return; + + this.internalReplant(treeDefinition, location); + } + + /** + * Randomly replants a sapling given a TreeDefinition and Location + * Takes into account config settings + * + * @param treeDefinition The TreeDefinition of the sapling + * @param location The Location to plant the sapling + */ + public void replantSaplingWithChance(TreeDefinition treeDefinition, Location location) { + if (!ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS.getBoolean()) + return; + + double chance = ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS_CHANCE.getDouble(); + if (this.random.nextDouble() > chance / 100) + return; + + this.internalReplant(treeDefinition, location); + } + + /** + * Replants a sapling given a TreeDefinition and Location + * + * @param treeDefinition The TreeDefinition of the sapling + * @param location The Location to plant the sapling + */ + private void internalReplant(TreeDefinition treeDefinition, Location location) { + Block block = location.getBlock(); + if (!block.getType().equals(Material.AIR)) + return; + + IBlockData saplingBlockData = treeDefinition.getSaplingBlockData(); + saplingBlockData.setBlock(location.getBlock()); + + int cooldown = ConfigurationManager.Setting.REPLANT_SAPLINGS_COOLDOWN.getInt(); + if (cooldown != 0) { + this.protectedSaplings.add(location); + Bukkit.getScheduler().scheduleSyncDelayedTask(this.ultimateTimber, () -> this.protectedSaplings.remove(location), cooldown * 20L); + } + } + + /** + * Gets if a sapling is protected + * + * @param block The Block to check + * @return True if the sapling is protected, otherwise false + */ + public boolean isSaplingProtected(Block block) { + return this.protectedSaplings.contains(block.getLocation()); + } + +} diff --git a/src/main/java/com/songoda/ultimatetimber/manager/TreeAnimationManager.java b/src/main/java/com/songoda/ultimatetimber/manager/TreeAnimationManager.java index 5046ce0..3cc9e45 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/TreeAnimationManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/TreeAnimationManager.java @@ -1,7 +1,10 @@ package com.songoda.ultimatetimber.manager; import com.songoda.ultimatetimber.UltimateTimber; +import com.songoda.ultimatetimber.tree.DetectedTree; +import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -24,6 +27,16 @@ public class TreeAnimationManager extends Manager implements Listener { } + /** + * Plays an animation for toppling a tree + * + * @param detectedTree The DetectedTree + * @param player The Player who toppled the tree + */ + public void runAnimation(DetectedTree detectedTree, Player player) { + TreeDefinition treeDefinition = detectedTree.getTreeDefinition(); + } + @EventHandler(priority = EventPriority.HIGH) public void onFallingBlockLand(EntityChangeBlockEvent event) { diff --git a/src/main/java/com/songoda/ultimatetimber/manager/TreeDefinitionManager.java b/src/main/java/com/songoda/ultimatetimber/manager/TreeDefinitionManager.java index ba5c2c6..d2b46de 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/TreeDefinitionManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/TreeDefinitionManager.java @@ -169,6 +169,8 @@ public class TreeDefinitionManager extends Manager { * @return True if the tool is allowed for toppling any trees */ public boolean isToolValidForAnyTreeDefinition(ItemStack tool) { + if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) + return true; for (TreeDefinition treeDefinition : this.treeDefinitions) for (ItemStack requiredTool : treeDefinition.getRequiredTools()) if (requiredTool.isSimilar(tool)) @@ -187,6 +189,8 @@ public class TreeDefinitionManager extends Manager { * @return True if the tool is allowed for toppling the given TreeDefinition */ public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) { + if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) + return true; for (ItemStack requiredTool : treeDefinition.getRequiredTools()) if (requiredTool.isSimilar(tool)) return true; @@ -230,9 +234,10 @@ public class TreeDefinitionManager extends Manager { } // Roll the dice + double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble(); for (TreeLoot treeLoot : toTry) { double chance = hasBonusChance ? treeLoot.getChance() * 2 : treeLoot.getChance(); - if (this.random.nextDouble() > chance) + if (this.random.nextDouble() > chance / 100) continue; if (treeLoot.hasItem()) lootedItems.add(treeLoot.getItem()); @@ -252,7 +257,12 @@ public class TreeDefinitionManager extends Manager { // Run looted commands for (String lootedCommand : lootedCommands) - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), lootedCommand.replace("%player", player.getName()).replace("%type", treeDefinition.getKey())); + Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), + lootedCommand.replace("%player", player.getName()) + .replace("%type", treeDefinition.getKey()) + .replace("%xPos", treeBlock.getLocation().getBlockX() + "") + .replace("%yPos", treeBlock.getLocation().getBlockY() + "") + .replace("%zPos", treeBlock.getLocation().getBlockZ() + "")); } /** diff --git a/src/main/java/com/songoda/ultimatetimber/manager/TreeDetectionManager.java b/src/main/java/com/songoda/ultimatetimber/manager/TreeDetectionManager.java index a56bd18..e8927c8 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/TreeDetectionManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/TreeDetectionManager.java @@ -2,7 +2,6 @@ package com.songoda.ultimatetimber.manager; import com.songoda.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.adapter.IBlockData; -import com.songoda.ultimatetimber.adapter.VersionAdapter; import com.songoda.ultimatetimber.tree.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -19,7 +18,6 @@ public class TreeDetectionManager extends Manager { private TreeDefinitionManager treeDefinitionManager; private int maxBranchBlocksAllowed; private int numLeavesRequiredForTree; - private boolean allowMixedTreeTypes; private boolean onlyBreakLogsUpwards; private boolean destroyBaseLog; private boolean entireTreeBase; @@ -27,27 +25,27 @@ public class TreeDetectionManager extends Manager { public TreeDetectionManager(UltimateTimber ultimateTimber) { super(ultimateTimber); - VALID_BRANCH_OFFSETS = new HashSet<>(); - VALID_TRUNK_OFFSETS = new HashSet<>(); - VALID_LEAF_OFFSETS = new HashSet<>(); + this.VALID_BRANCH_OFFSETS = new HashSet<>(); + this.VALID_TRUNK_OFFSETS = new HashSet<>(); + this.VALID_LEAF_OFFSETS = new HashSet<>(); // 3x2x3 centered around log, excluding -y axis for (int x = -1; x <= 1; x++) for (int y = 0; y <= 1; y++) for (int z = -1; z <= 1; z++) - VALID_BRANCH_OFFSETS.add(new Vector(x, y, z)); + this.VALID_BRANCH_OFFSETS.add(new Vector(x, y, z)); // 3x3x3 centered around log for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++) for (int z = -1; z <= 1; z++) - VALID_TRUNK_OFFSETS.add(new Vector(x, y, z)); + this.VALID_TRUNK_OFFSETS.add(new Vector(x, y, z)); // Adjacent blocks to log for (int i = -1; i <= 1; i += 2) { - VALID_LEAF_OFFSETS.add(new Vector(i, 0, 0)); - VALID_LEAF_OFFSETS.add(new Vector(0, i, 0)); - VALID_LEAF_OFFSETS.add(new Vector(0, 0, i)); + this.VALID_LEAF_OFFSETS.add(new Vector(i, 0, 0)); + this.VALID_LEAF_OFFSETS.add(new Vector(0, i, 0)); + this.VALID_LEAF_OFFSETS.add(new Vector(0, 0, i)); } } @@ -56,7 +54,6 @@ public class TreeDetectionManager extends Manager { this.treeDefinitionManager = this.ultimateTimber.getTreeDefinitionManager(); this.maxBranchBlocksAllowed = ConfigurationManager.Setting.MAX_LOGS_PER_CHOP.getInt(); this.numLeavesRequiredForTree = ConfigurationManager.Setting.LEAVES_REQUIRED_FOR_TREE.getInt(); - this.allowMixedTreeTypes = ConfigurationManager.Setting.MIX_ALL_TREE_TYPES.getBoolean(); this.onlyBreakLogsUpwards = ConfigurationManager.Setting.ONLY_DETECT_LOGS_UPWARDS.getBoolean(); this.destroyBaseLog = ConfigurationManager.Setting.DESTROY_INITIATED_BLOCK.getBoolean(); this.entireTreeBase = ConfigurationManager.Setting.BREAK_ENTIRE_TREE_BASE.getBoolean(); @@ -76,7 +73,10 @@ public class TreeDetectionManager extends Manager { public DetectedTree detectTree(Block initialBlock) { TreeBlock initialTreeBlock = new TreeBlock(initialBlock, TreeBlockType.LOG); TreeBlockSet detectedTreeBlocks = new TreeBlockSet<>(initialTreeBlock); - Set possibleTreeDefinitions = treeDefinitionManager.getTreeDefinitionsForLog(initialBlock); + Set possibleTreeDefinitions = this.treeDefinitionManager.getTreeDefinitionsForLog(initialBlock); + + if (possibleTreeDefinitions.isEmpty()) + return null; // Detect tree trunk Set trunkBlocks = new HashSet<>(); @@ -151,7 +151,7 @@ public class TreeDetectionManager extends Manager { if (treeBlocks.size() > this.maxBranchBlocksAllowed) return; - for (Vector offset : this.onlyBreakLogsUpwards ? VALID_BRANCH_OFFSETS : VALID_TRUNK_OFFSETS) { + for (Vector offset : this.onlyBreakLogsUpwards ? this.VALID_BRANCH_OFFSETS : this.VALID_TRUNK_OFFSETS) { Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LOG); if (this.isValidLogType(treeDefinitions, targetBlock) && !treeBlocks.contains(treeBlock)) { @@ -178,7 +178,7 @@ public class TreeDetectionManager extends Manager { if (distanceFromLog > maxDistanceFromLog) return; - for (Vector offset : !detectLeavesDiagonally ? VALID_LEAF_OFFSETS : VALID_TRUNK_OFFSETS) { + for (Vector offset : !detectLeavesDiagonally ? this.VALID_LEAF_OFFSETS : this.VALID_TRUNK_OFFSETS) { Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LEAF); if (this.isValidLeafType(treeDefinitions, targetBlock)) { @@ -200,7 +200,7 @@ public class TreeDetectionManager extends Manager { * @return True if the leaf borders an invalid log, otherwise false */ private boolean doesLeafBorderInvalidLog(Set treeDefinitions, TreeBlockSet treeBlocks, Block block) { - for (Vector offset : VALID_TRUNK_OFFSETS) { + for (Vector offset : this.VALID_TRUNK_OFFSETS) { Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); if (this.isValidLogType(treeDefinitions, targetBlock) && !treeBlocks.contains(new TreeBlock(targetBlock, TreeBlockType.LOG))) return true; @@ -216,7 +216,6 @@ public class TreeDetectionManager extends Manager { * @return True if the block is a valid log type, otherwise false */ private boolean isValidLogType(Set treeDefinitions, Block block) { - VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter(); for (TreeDefinition treeDefinition : treeDefinitions) for (IBlockData logBlockData : treeDefinition.getLogBlockData()) if (logBlockData.isSimilar(block)) @@ -232,7 +231,6 @@ public class TreeDetectionManager extends Manager { * @return True if the block is a valid log type, otherwise false */ private boolean isValidLeafType(Set treeDefinitions, Block block) { - VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter(); for (TreeDefinition treeDefinition : treeDefinitions) for (IBlockData leafBlockData : treeDefinition.getLeafBlockData()) if (leafBlockData.isSimilar(block)) diff --git a/src/main/java/com/songoda/ultimatetimber/manager/TreeFallManager.java b/src/main/java/com/songoda/ultimatetimber/manager/TreeFallManager.java index 6d16207..94aa956 100644 --- a/src/main/java/com/songoda/ultimatetimber/manager/TreeFallManager.java +++ b/src/main/java/com/songoda/ultimatetimber/manager/TreeFallManager.java @@ -1,11 +1,19 @@ package com.songoda.ultimatetimber.manager; import com.songoda.ultimatetimber.UltimateTimber; +import com.songoda.ultimatetimber.adapter.VersionAdapter; +import com.songoda.ultimatetimber.events.TreeFallEvent; +import com.songoda.ultimatetimber.events.TreeFellEvent; +import com.songoda.ultimatetimber.tree.DetectedTree; import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.inventory.ItemStack; public class TreeFallManager extends Manager implements Listener { @@ -26,7 +34,70 @@ public class TreeFallManager extends Manager implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent event) { + TreeDefinitionManager treeDefinitionManager = this.ultimateTimber.getTreeDefinitionManager(); + TreeDetectionManager treeDetectionManager = this.ultimateTimber.getTreeDetectionManager(); + TreeAnimationManager treeAnimationManager = this.ultimateTimber.getTreeAnimationManager(); + ChoppingManager choppingManager = this.ultimateTimber.getChoppingManager(); + SaplingManager saplingManager = this.ultimateTimber.getSaplingManager(); + VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter(); + HookManager hookManager = this.ultimateTimber.getHookManager(); + Player player = event.getPlayer(); + Block block = event.getBlock(); + ItemStack tool = versionAdapter.getItemInHand(player); + + // Protect saplings + if (saplingManager.isSaplingProtected(block)) { + event.setCancelled(true); + return; + } + + // Condition checks + if (ConfigurationManager.Setting.DISABLED_WORLDS.getStringList().contains(player.getWorld().getName())) + return; + + if (!ConfigurationManager.Setting.ALLOW_CREATIVE_MODE.getBoolean() && player.getGameMode().equals(GameMode.CREATIVE)) + return; + + if (ConfigurationManager.Setting.ONLY_TOPPLE_WHILE_SNEAKING.getBoolean() && !player.isSneaking()) + return; + + if (ConfigurationManager.Setting.REQUIRE_CHOP_PERMISSION.getBoolean() && !player.hasPermission("ultimatetimber.chop")) + return; + + if (!choppingManager.isChopping(player)) + return; + + if (!treeDefinitionManager.isToolValidForAnyTreeDefinition(tool)) + return; + + DetectedTree detectedTree = treeDetectionManager.detectTree(block); + if (detectedTree == null) + return; + + int toolDamage = ConfigurationManager.Setting.REALISTIC_TOOL_DAMAGE.getBoolean() ? detectedTree.getDetectedTreeBlocks().getLogBlocks().size() : 1; + if (ConfigurationManager.Setting.PROTECT_TOOL.getBoolean() && !versionAdapter.hasEnoughDurability(tool, toolDamage)) + return; + + // Trigger fall event + TreeFallEvent treeFallEvent = new TreeFallEvent(player, detectedTree); + Bukkit.getPluginManager().callEvent(treeFallEvent); + if (treeFallEvent.isCancelled()) + return; + + // Valid tree and meets all conditions past this point + event.setCancelled(true); + + if (!player.getGameMode().equals(GameMode.CREATIVE)) { + versionAdapter.applyToolDurability(tool, toolDamage); + hookManager.applyHooks(player, detectedTree.getDetectedTreeBlocks()); + } + + treeAnimationManager.runAnimation(detectedTree, player); + + // Trigger fell event + TreeFellEvent treeFellEvent = new TreeFellEvent(player, detectedTree); + Bukkit.getPluginManager().callEvent(treeFellEvent); } } diff --git a/src/main/java/com/songoda/ultimatetimber/old_code/TreeChecker.java b/src/main/java/com/songoda/ultimatetimber/old_code/TreeChecker.java deleted file mode 100644 index 3195aee..0000000 --- a/src/main/java/com/songoda/ultimatetimber/old_code/TreeChecker.java +++ /dev/null @@ -1,303 +0,0 @@ -package com.songoda.ultimatetimber.old_code; - -import com.songoda.ultimatetimber.UltimateTimber; -import com.songoda.ultimatetimber.utils.LogToLeafConverter; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.util.Vector; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; - -public class TreeChecker { - - /* - Used to check if a piece of wood is a part of the tree - */ - private final static Set VALID_LOG_MATERIALS = new HashSet<>(Arrays.asList( - Material.ACACIA_LOG, - Material.ACACIA_WOOD, - Material.STRIPPED_ACACIA_LOG, - Material.STRIPPED_ACACIA_WOOD, - Material.BIRCH_LOG, - Material.BIRCH_WOOD, - Material.STRIPPED_BIRCH_LOG, - Material.STRIPPED_BIRCH_WOOD, - Material.DARK_OAK_LOG, - Material.DARK_OAK_WOOD, - Material.STRIPPED_DARK_OAK_LOG, - Material.STRIPPED_DARK_OAK_WOOD, - Material.JUNGLE_LOG, - Material.JUNGLE_WOOD, - Material.STRIPPED_JUNGLE_LOG, - Material.STRIPPED_JUNGLE_WOOD, - Material.OAK_LOG, - Material.OAK_WOOD, - Material.STRIPPED_OAK_LOG, - Material.STRIPPED_OAK_WOOD, - Material.SPRUCE_LOG, - Material.SPRUCE_WOOD, - Material.STRIPPED_SPRUCE_LOG, - Material.STRIPPED_SPRUCE_WOOD, - Material.MUSHROOM_STEM - )); - - /* - Used to check if a leaf is a part of the tree - */ - private final static Set VALID_LEAF_MATERIALS = new HashSet<>(Arrays.asList( - Material.ACACIA_LEAVES, - Material.BIRCH_LEAVES, - Material.DARK_OAK_LEAVES, - Material.JUNGLE_LEAVES, - Material.OAK_LEAVES, - Material.SPRUCE_LEAVES, - Material.BROWN_MUSHROOM_BLOCK, - Material.RED_MUSHROOM_BLOCK - )); - - /** - * Gets a Set of all valid wood materials - * - * @return A Set of all valid wood materials - */ - public static Set getValidWoodMaterials() { - return VALID_LOG_MATERIALS; - } - - private static final Set VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS; - - private HashSet treeBlocks; - private int maxDistanceFromLog; - private Material logType, leafType; - private int startingBlockY; - private int maxBranchBlocksAllowed; - private int numLeavesRequiredForTree; - private boolean allowMixedTreeTypes; - private boolean onlyBreakLogsUpwards; - private boolean destroyBaseLog; - private boolean entireTreeBase; - private boolean isMushroom = false; - - static { - VALID_BRANCH_OFFSETS = new HashSet<>(); - VALID_TRUNK_OFFSETS = new HashSet<>(); - VALID_LEAF_OFFSETS = new HashSet<>(); - - // 3x2x3 centered around log, excluding -y axis - for (int x = -1; x <= 1; x++) - for (int y = 0; y <= 1; y++) - for (int z = -1; z <= 1; z++) - VALID_BRANCH_OFFSETS.add(new Vector(x, y, z)); - - // 3x3x3 centered around log - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) - for (int z = -1; z <= 1; z++) - VALID_TRUNK_OFFSETS.add(new Vector(x, y, z)); - - // Adjacent blocks to log - for (int i = -1; i <= 1; i += 2) { - VALID_LEAF_OFFSETS.add(new Vector(i, 0, 0)); - VALID_LEAF_OFFSETS.add(new Vector(0, i, 0)); - VALID_LEAF_OFFSETS.add(new Vector(0, 0, i)); - } - } - - /** - * Parses a block for a potential tree - * - * @param block The based block of the potential tree - * @return A HashSet of all blocks in the tree, or null if no tree was found - */ - protected HashSet parseTree(Block block) { - this.treeBlocks = new HashSet<>(); - this.treeBlocks.add(block); - - // Set tree information - this.logType = block.getType(); - this.leafType = LogToLeafConverter.convert(this.logType); - this.startingBlockY = block.getLocation().getBlockY(); - this.isMushroom = this.logType.equals(Material.MUSHROOM_STEM); - - // Load settings for algorithm - FileConfiguration config = UltimateTimber.getInstance().getConfig(); - this.allowMixedTreeTypes = config.getBoolean(DefaultConfig.ALLOW_MIXED_TREE_TYPES); - this.maxBranchBlocksAllowed = config.getInt(DefaultConfig.MAX_BRANCH_BLOCKS); - 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<>(); - trunkBlocks.add(block); - Block targetBlock = block; - while (this.isValidLogType((targetBlock = targetBlock.getRelative(BlockFace.UP)).getType())) { - this.treeBlocks.add(targetBlock); - trunkBlocks.add(targetBlock); - } - - // Tree must be at least 2 blocks tall - if (this.treeBlocks.size() < 2) - return null; - - // Detect branches off the main trunk - for (Block trunkBlock : trunkBlocks) - this.recursiveBranchSearch(trunkBlock); - - // Make it so trees only break as many leaves as they have to - this.maxDistanceFromLog = this.getMaxLeafDistanceFromLog(); - - // Detect leaves off the trunk/branches - Set branchBlocks = new HashSet(this.treeBlocks); - for (Block branchBlock : branchBlocks) - this.recursiveLeafSearch(branchBlock, 1); - - // Trees need at least 5 leaves - if (!this.isMushroom && this.treeBlocks.stream().filter(x -> this.isValidLeafType(x.getType())).count() < this.numLeavesRequiredForTree) - return null; - - // The lowest logs of the tree must not have a plantable surface below them - if (this.entireTreeBase) { - int lowestY = this.treeBlocks.stream().min(Comparator.comparingInt(Block::getY)).get().getY(); - boolean isTreeGrounded = this.treeBlocks.stream().filter(x -> x.getY() == lowestY).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) || - isValidLogType(typeBelow)) && - !x.equals(block) && - isValidLogType(x.getType()); - }); - if (isTreeGrounded) - return null; - } - - // Delete the starting block if applicable - if (this.destroyBaseLog) - this.treeBlocks.remove(block); - - return this.treeBlocks; - } - - /** - * Recursively searches for branches off a given block - * - * @param block The next block to check for a branch - */ - private void recursiveBranchSearch(Block block) { - if (this.treeBlocks.size() > this.maxBranchBlocksAllowed) - return; - - for (Vector offset : this.onlyBreakLogsUpwards ? VALID_BRANCH_OFFSETS : VALID_TRUNK_OFFSETS) { - Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); - if (this.isValidLogType(targetBlock.getType()) && !this.treeBlocks.contains(targetBlock)) { - this.treeBlocks.add(targetBlock); - if (!this.onlyBreakLogsUpwards || targetBlock.getLocation().getBlockY() > this.startingBlockY) - this.recursiveBranchSearch(targetBlock); - } - } - } - - /** - * Recursively searches for leaves that are next to this tree - * - * @param block The next block to check for a leaf - * @param distanceFromLog The distance this leaf is from a log - */ - private void recursiveLeafSearch(Block block, int distanceFromLog) { - if (distanceFromLog > this.maxDistanceFromLog) - return; - - for (Vector offset : !this.isMushroom ? VALID_LEAF_OFFSETS : VALID_TRUNK_OFFSETS) { - Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); - if (this.isValidLeafType(targetBlock.getType())) { - if (!this.treeBlocks.contains(targetBlock) && !doesLeafBorderInvalidLog(targetBlock)) - this.treeBlocks.add(targetBlock); - this.recursiveLeafSearch(targetBlock, distanceFromLog + 1); - } - } - } - - /** - * Checks if a leaf is bordering a log that isn't part of this tree - * - * @param block The block to check - * @return If the leaf borders an invalid log - */ - private boolean doesLeafBorderInvalidLog(Block block) { - for (Vector offset : VALID_TRUNK_OFFSETS) { - Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ()); - if (this.isValidLogType(targetBlock.getType()) && !this.treeBlocks.contains(targetBlock)) - return true; - } - return false; - } - - private boolean isValidLogType(Material material) { - if (this.allowMixedTreeTypes) - return VALID_LOG_MATERIALS.contains(material); - return material.equals(this.logType); - } - - private boolean isValidLeafType(Material material) { - if (this.allowMixedTreeTypes) - return VALID_LEAF_MATERIALS.contains(material); - return material.equals(this.leafType); - } - - /** - * Gets the max distance away from a log based on how many logs there are and the leaf type - * - * @return The max distance away a leaf can be from a log - */ - private int getMaxLeafDistanceFromLog() { - int numLogs = this.treeBlocks.size(); - - switch (this.leafType) { - - case ACACIA_LEAVES: - return 5; - - case BIRCH_LEAVES: - return 4; - - case DARK_OAK_LEAVES: - return 5; - - case JUNGLE_LEAVES: - if (numLogs > 15) - return 5; - return 4; - - case OAK_LEAVES: - if (numLogs > 15) - return 6; - if (numLogs > 6) - return 5; - return 4; - - case SPRUCE_LEAVES: - if (numLogs > 15) - return 6; - return 5; - - case MUSHROOM_STEM: - return 4; - - default: - return -1; - } - } - - public HashSet getTreeBlocks() { - return this.treeBlocks; - } - -} diff --git a/src/main/java/com/songoda/ultimatetimber/tree/TreeBlockSet.java b/src/main/java/com/songoda/ultimatetimber/tree/TreeBlockSet.java index d71403b..c9a3720 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/TreeBlockSet.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/TreeBlockSet.java @@ -159,6 +159,7 @@ public class TreeBlockSet implements Collection { } @Override + @SuppressWarnings("unchecked") public Object[] toArray(Object[] a) { Set> treeBlocks = new HashSet<>(); for (Object o : a) diff --git a/src/main/java/com/songoda/ultimatetimber/tree/TreeLoot.java b/src/main/java/com/songoda/ultimatetimber/tree/TreeLoot.java index de8818c..9e84dbf 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/TreeLoot.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/TreeLoot.java @@ -58,7 +58,7 @@ public class TreeLoot { * @return The command that this tree loot can run */ public String getCommand() { - return command; + return this.command; } /** diff --git a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimation.java b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimation.java index ccbb836..371a31f 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimation.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimation.java @@ -1,8 +1,10 @@ package com.songoda.ultimatetimber.tree.animation; +import com.songoda.ultimatetimber.tree.DetectedTree; import com.songoda.ultimatetimber.tree.TreeBlockSet; import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public abstract class TreeAnimation { @@ -16,6 +18,12 @@ public abstract class TreeAnimation { this.treeDefinition = treeDefinition; } - abstract void playAnimation(); + /** + * Plays this tree topple animation + * + * @param detectedTree The DetectedTree + * @param player The Player who toppled the tree + */ + abstract void playAnimation(DetectedTree detectedTree, Player player); } diff --git a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationChaos.java b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationChaos.java index 98ff982..bd34e01 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationChaos.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationChaos.java @@ -1,8 +1,10 @@ package com.songoda.ultimatetimber.tree.animation; +import com.songoda.ultimatetimber.tree.DetectedTree; import com.songoda.ultimatetimber.tree.TreeBlockSet; import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public class TreeAnimationChaos extends TreeAnimation { @@ -11,7 +13,7 @@ public class TreeAnimationChaos extends TreeAnimation { } @Override - public void playAnimation() { + public void playAnimation(DetectedTree detectedTree, Player player) { } diff --git a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationDisintegrate.java b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationDisintegrate.java index 0821883..550fafd 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationDisintegrate.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationDisintegrate.java @@ -1,8 +1,10 @@ package com.songoda.ultimatetimber.tree.animation; +import com.songoda.ultimatetimber.tree.DetectedTree; import com.songoda.ultimatetimber.tree.TreeBlockSet; import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public class TreeAnimationDisintegrate extends TreeAnimation { @@ -11,7 +13,7 @@ public class TreeAnimationDisintegrate extends TreeAnimation { } @Override - public void playAnimation() { + public void playAnimation(DetectedTree detectedTree, Player player) { } diff --git a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationFancy.java b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationFancy.java index 3b85a0b..5c6e6cc 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationFancy.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationFancy.java @@ -1,8 +1,10 @@ package com.songoda.ultimatetimber.tree.animation; +import com.songoda.ultimatetimber.tree.DetectedTree; import com.songoda.ultimatetimber.tree.TreeBlockSet; import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public class TreeAnimationFancy extends TreeAnimation { @@ -11,7 +13,7 @@ public class TreeAnimationFancy extends TreeAnimation { } @Override - public void playAnimation() { + public void playAnimation(DetectedTree detectedTree, Player player) { } diff --git a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationNone.java b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationNone.java index 4d0fd0c..2f6629e 100644 --- a/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationNone.java +++ b/src/main/java/com/songoda/ultimatetimber/tree/animation/TreeAnimationNone.java @@ -1,8 +1,10 @@ package com.songoda.ultimatetimber.tree.animation; +import com.songoda.ultimatetimber.tree.DetectedTree; import com.songoda.ultimatetimber.tree.TreeBlockSet; import com.songoda.ultimatetimber.tree.TreeDefinition; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public class TreeAnimationNone extends TreeAnimation { @@ -11,7 +13,7 @@ public class TreeAnimationNone extends TreeAnimation { } @Override - public void playAnimation() { + public void playAnimation(DetectedTree detectedTree, Player player) { } diff --git a/src/main/java/com/songoda/ultimatetimber/utils/Metrics.java b/src/main/java/com/songoda/ultimatetimber/utils/Metrics.java index fe7c518..6ddcae1 100644 --- a/src/main/java/com/songoda/ultimatetimber/utils/Metrics.java +++ b/src/main/java/com/songoda/ultimatetimber/utils/Metrics.java @@ -692,4 +692,4 @@ public class Metrics { } } -} \ No newline at end of file +} diff --git a/src/main/java/com/songoda/ultimatetimber/utils/NMSUtil.java b/src/main/java/com/songoda/ultimatetimber/utils/NMSUtil.java index 68f6d1a..c89f4e0 100644 --- a/src/main/java/com/songoda/ultimatetimber/utils/NMSUtil.java +++ b/src/main/java/com/songoda/ultimatetimber/utils/NMSUtil.java @@ -19,4 +19,4 @@ public class NMSUtil { return Integer.valueOf(NMSVersion.substring(NMSVersion.length() - 2).replace(".", "")); } -} \ No newline at end of file +} diff --git a/src/main/resources/config-current.yml b/src/main/resources/config-current.yml index 58c01da..e618cbc 100644 --- a/src/main/resources/config-current.yml +++ b/src/main/resources/config-current.yml @@ -24,9 +24,15 @@ max-logs-per-chop: 120 leaves-required-for-tree: 5 # Apply realistic damage to the tools based on the number of logs chopped +# If false, only one durability will be removed from the tool # Default: true realistic-tool-damage: true +# Protect the tool used to chop down the tree from breaking +# Prevents the tree from being toppled if the tool would break +# Default: false +protect-tool: false + # Require the entire base of the tree to be broken before it topples # Default: false break-entire-tree-base: false @@ -62,8 +68,8 @@ replant-saplings: true # How many seconds to prevent players from breaking replanted saplings # Set to 0 to disable # Does nothing if replant-saplings is false -# Default: 5 -replant-saplings-cooldown: 5 +# Default: 3 +replant-saplings-cooldown: 3 # Give fallen leaf blocks a chance to replant saplings when they hit the ground # Default: true @@ -71,6 +77,7 @@ falling-blocks-replant-saplings: true # The percent chance that fallen leaves have of planting a sapling # Does nothing if falling-blocks-replant-saplings is false +# The chance is out of 100 and may contain decimals # Default: 1 falling-blocks-replant-saplings-chance: 1 @@ -95,6 +102,12 @@ use-custom-sounds: true # Default: true use-custom-particles: true +# The bonus loot multiplier when a player has the permission ultimatetimber.bonusloot +# Multiplies the chance of tree drops by this value +# Decimal values are allowed +# Default: 2 +bonus-loot-multiplier: 2 + # The type of animation to use for tree toppling # Types: FANCY, DISINTEGRATE, CHAOS, NONE tree-animation-type: FANCY @@ -283,6 +296,7 @@ global-plantable-soil: - GRASS_BLOCK - DIRT - COARSE_DIRT + - PODZOL # Custom loot that is available for all tree types # The loot applies to each log broken in the tree @@ -298,7 +312,7 @@ global-log-loot: chance: 0 2: material: GOLDEN_APPLE - command: 'broadcast %player found a golden apple in a %type tree!' + command: 'broadcast %player found a golden apple in a %type tree at %xPos %yPos %zPos!' chance: 0 # Custom loot that is available for all tree types diff --git a/src/main/resources/config-legacy.yml b/src/main/resources/config-legacy.yml index c5d9972..a253806 100644 --- a/src/main/resources/config-legacy.yml +++ b/src/main/resources/config-legacy.yml @@ -25,9 +25,15 @@ max-logs-per-chop: 120 leaves-required-for-tree: 5 # Apply realistic damage to the tools based on the number of logs chopped +# If false, only one durability will be removed from the tool # Default: true realistic-tool-damage: true +# Protect the tool used to chop down the tree from breaking +# Prevents the tree from being toppled if the tool would break +# Default: false +protect-tool: false + # Require the entire base of the tree to be broken before it topples # Default: false break-entire-tree-base: false @@ -63,8 +69,8 @@ replant-saplings: true # How many seconds to prevent players from breaking replanted saplings # Set to 0 to disable # Does nothing if replant-saplings is false -# Default: 5 -replant-saplings-cooldown: 5 +# Default: 3 +replant-saplings-cooldown: 3 # Give fallen leaf blocks a chance to replant saplings when they hit the ground # Default: true @@ -72,6 +78,7 @@ falling-blocks-replant-saplings: true # The percent chance that fallen leaves have of planting a sapling # Does nothing if falling-blocks-replant-saplings is false +# The chance is out of 100 and may contain decimals # Default: 1 falling-blocks-replant-saplings-chance: 1 @@ -96,6 +103,12 @@ use-custom-sounds: true # Default: true use-custom-particles: true +# The bonus loot multiplier when a player has the permission ultimatetimber.bonusloot +# Multiplies the chance of tree drops by this value +# Decimal values are allowed +# Default: 2 +bonus-loot-multiplier: 2 + # The type of animation to use for tree toppling # Types: FANCY, DISINTEGRATE, CHAOS, NONE tree-animation-type: FANCY @@ -323,6 +336,7 @@ global-plantable-soil: - GRASS - DIRT:0 - DIRT:1 + - DIRT:2 # Custom loot that is available for all tree types # The loot applies to each log broken in the tree @@ -338,7 +352,7 @@ global-log-loot: chance: 0 2: material: GOLDEN_APPLE - command: 'broadcast %player found a golden apple in a %type tree!' + command: 'broadcast %player found a golden apple in a %type tree at %xPos %yPos %zPos!' chance: 0 # Custom loot that is available for all tree types diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f42111c..bd05a36 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -24,4 +24,4 @@ permissions: default: op ultimatetimber.reload: description: Reloads the configuration file - default: op \ No newline at end of file + default: op