mirror of
https://github.com/songoda/UltimateTimber.git
synced 2024-11-29 05:16:29 +01:00
Tree detector, file formatting, this., new settings, other changes
This commit is contained in:
parent
94ffdcc5f5
commit
8026babcdf
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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<Block> 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
|
||||
|
@ -35,13 +35,18 @@ public class CurrentAdapter implements VersionAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyToolDurability(TreeBlockSet<Block> 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Block> 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Block> treeBlocks;
|
||||
protected final DetectedTree detectedTree;
|
||||
|
||||
public TreeEvent(Player player, TreeBlockSet<Block> 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<Block> getTreeBlocks() {
|
||||
return this.treeBlocks;
|
||||
public DetectedTree getDetectedTree() {
|
||||
return this.detectedTree;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Block> treeBlocks) {
|
||||
super(player, treeBlocks);
|
||||
public TreeFallEvent(Player player, DetectedTree detectedTree) {
|
||||
super(player, detectedTree);
|
||||
}
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
@ -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<Block> treeBlocks) {
|
||||
super(player, treeBlocks);
|
||||
public TreeFellEvent(Player player, DetectedTree detectedTree) {
|
||||
super(player, detectedTree);
|
||||
}
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
@ -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");
|
||||
|
@ -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<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] args) {
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if (args.length == 0 || args.length > 1)
|
||||
if (args.length < 1)
|
||||
return completions;
|
||||
|
||||
Set<String> possibleCompletions = new HashSet<>();
|
||||
|
@ -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<String> getStringList() {
|
||||
this.loadValue();
|
||||
return (List<String>)value;
|
||||
return (List<String>)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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ public class HookManager extends Manager {
|
||||
|
||||
public HookManager(UltimateTimber ultimateTimber) {
|
||||
super(ultimateTimber);
|
||||
this.hooks = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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<Location> 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());
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
||||
|
@ -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() + ""));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<Block> detectedTreeBlocks = new TreeBlockSet<>(initialTreeBlock);
|
||||
Set<TreeDefinition> possibleTreeDefinitions = treeDefinitionManager.getTreeDefinitionsForLog(initialBlock);
|
||||
Set<TreeDefinition> possibleTreeDefinitions = this.treeDefinitionManager.getTreeDefinitionsForLog(initialBlock);
|
||||
|
||||
if (possibleTreeDefinitions.isEmpty())
|
||||
return null;
|
||||
|
||||
// Detect tree trunk
|
||||
Set<Block> 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<TreeDefinition> treeDefinitions, TreeBlockSet<Block> 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<TreeDefinition> 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<TreeDefinition> treeDefinitions, Block block) {
|
||||
VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter();
|
||||
for (TreeDefinition treeDefinition : treeDefinitions)
|
||||
for (IBlockData leafBlockData : treeDefinition.getLeafBlockData())
|
||||
if (leafBlockData.isSimilar(block))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Material> 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<Material> 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<Material> getValidWoodMaterials() {
|
||||
return VALID_LOG_MATERIALS;
|
||||
}
|
||||
|
||||
private static final Set<Vector> VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS;
|
||||
|
||||
private HashSet<Block> 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<Block> 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<Block> 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<Block> branchBlocks = new HashSet<Block>(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<Block> getTreeBlocks() {
|
||||
return this.treeBlocks;
|
||||
}
|
||||
|
||||
}
|
@ -159,6 +159,7 @@ public class TreeBlockSet<BlockType> implements Collection {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray(Object[] a) {
|
||||
Set<ITreeBlock<BlockType>> treeBlocks = new HashSet<>();
|
||||
for (Object o : a)
|
||||
|
@ -58,7 +58,7 @@ public class TreeLoot {
|
||||
* @return The command that this tree loot can run
|
||||
*/
|
||||
public String getCommand() {
|
||||
return command;
|
||||
return this.command;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -692,4 +692,4 @@ public class Metrics {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,4 @@ public class NMSUtil {
|
||||
return Integer.valueOf(NMSVersion.substring(NMSVersion.length() - 2).replace(".", ""));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -24,4 +24,4 @@ permissions:
|
||||
default: op
|
||||
ultimatetimber.reload:
|
||||
description: Reloads the configuration file
|
||||
default: op
|
||||
default: op
|
||||
|
Loading…
Reference in New Issue
Block a user