mirror of
https://github.com/songoda/UltimateTimber.git
synced 2025-01-08 08:47:51 +01:00
Tree detection
This commit is contained in:
parent
671236f57d
commit
9329cc1fb6
@ -29,7 +29,6 @@ public class UltimateTimber extends JavaPlugin {
|
||||
private CommandManager commandManager;
|
||||
private ConfigurationManager configurationManager;
|
||||
private HookManager hookManager;
|
||||
private MessageManager messageManager;
|
||||
private TreeAnimationManager treeAnimationManager;
|
||||
private TreeDefinitionManager treeDefinitionManager;
|
||||
private TreeDetectionManager treeDetectionManager;
|
||||
@ -50,15 +49,15 @@ public class UltimateTimber extends JavaPlugin {
|
||||
this.managers = new HashSet<>();
|
||||
this.choppingManager = this.registerManager(ChoppingManager.class);
|
||||
this.commandManager = this.registerManager(CommandManager.class);
|
||||
this.configurationManager = this.registerManager(ConfigurationManager.class);
|
||||
this.configurationManager = new ConfigurationManager(this);
|
||||
this.hookManager = this.registerManager(HookManager.class);
|
||||
this.messageManager = this.registerManager(MessageManager.class);
|
||||
this.treeAnimationManager = this.registerManager(TreeAnimationManager.class);
|
||||
this.treeDefinitionManager = this.registerManager(TreeDefinitionManager.class);
|
||||
this.treeDetectionManager = this.registerManager(TreeDetectionManager.class);
|
||||
this.treeFallManager = this.registerManager(TreeFallManager.class);
|
||||
|
||||
this.setupVersionAdapter();
|
||||
this.reload();
|
||||
|
||||
new Metrics(this);
|
||||
|
||||
@ -80,6 +79,7 @@ public class UltimateTimber extends JavaPlugin {
|
||||
* Reloads the plugin's settings
|
||||
*/
|
||||
public void reload() {
|
||||
this.configurationManager.reload();
|
||||
this.managers.forEach(Manager::reload);
|
||||
}
|
||||
|
||||
@ -87,6 +87,7 @@ public class UltimateTimber extends JavaPlugin {
|
||||
* Disables most of the plugin
|
||||
*/
|
||||
public void disable() {
|
||||
this.configurationManager.disable();
|
||||
this.managers.forEach(Manager::disable);
|
||||
}
|
||||
|
||||
@ -112,9 +113,9 @@ public class UltimateTimber extends JavaPlugin {
|
||||
try {
|
||||
T newManager = managerClass.getConstructor(UltimateTimber.class).newInstance(this);
|
||||
this.managers.add(newManager);
|
||||
newManager.reload();
|
||||
return newManager;
|
||||
} catch (Exception ignored) {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -164,15 +165,6 @@ public class UltimateTimber extends JavaPlugin {
|
||||
return hookManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration manager
|
||||
*
|
||||
* @return The ConfigurationManager instance
|
||||
*/
|
||||
public MessageManager getMessageManager() {
|
||||
return messageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tree animation manager
|
||||
*
|
||||
|
@ -9,10 +9,16 @@ import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public interface VersionAdapter {
|
||||
|
||||
/**
|
||||
* Gets the version adapter type
|
||||
*
|
||||
* @return The VersionAdapterType
|
||||
*/
|
||||
VersionAdapterType getVersionAdapterType();
|
||||
|
||||
/**
|
||||
@ -34,11 +40,19 @@ public interface VersionAdapter {
|
||||
/**
|
||||
* Get the items that a tree block should drop when it breaks
|
||||
*
|
||||
* @param treeBlock The tree block broken
|
||||
* @param treeDefinition The tree definition to get the drops for
|
||||
* @param treeBlock The tree block
|
||||
* @return A Set of ItemStacks that should be dropped
|
||||
*/
|
||||
Set<ItemStack> getTreeBlockDrops(TreeBlock treeBlock, TreeDefinition treeDefinition);
|
||||
Collection<ItemStack> getBlockDrops(TreeBlock treeBlock);
|
||||
|
||||
/**
|
||||
* Checks if two block states are similar
|
||||
*
|
||||
* @param blockState1 The first BlockState
|
||||
* @param blockState2 The second BlockState
|
||||
* @return True if the BlockStates are similar, otherwise false
|
||||
*/
|
||||
boolean areBlockStatesSimilar(BlockState blockState1, BlockState blockState2);
|
||||
|
||||
/**
|
||||
* Applies damage to a tool
|
||||
|
@ -5,13 +5,12 @@ import com.songoda.ultimatetimber.adapter.VersionAdapterType;
|
||||
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
|
||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
|
||||
public class CurrentAdapter implements VersionAdapter {
|
||||
|
||||
@ -31,10 +30,15 @@ public class CurrentAdapter implements VersionAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ItemStack> getTreeBlockDrops(TreeBlock treeBlock, TreeDefinition treeDefinition) {
|
||||
public Collection<ItemStack> getBlockDrops(TreeBlock treeBlock) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areBlockStatesSimilar(BlockState blockState1, BlockState blockState2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyToolDurability(TreeBlockSet<Block> treeBlocks, ItemStack tool) {
|
||||
|
||||
|
@ -5,13 +5,12 @@ import com.songoda.ultimatetimber.adapter.VersionAdapterType;
|
||||
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
|
||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
|
||||
public class LegacyAdapter implements VersionAdapter {
|
||||
|
||||
@ -31,10 +30,15 @@ public class LegacyAdapter implements VersionAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ItemStack> getTreeBlockDrops(TreeBlock treeBlock, TreeDefinition treeDefinition) {
|
||||
public Collection<ItemStack> getBlockDrops(TreeBlock treeBlock) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areBlockStatesSimilar(BlockState blockState1, BlockState blockState2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyToolDurability(TreeBlockSet<Block> treeBlocks, ItemStack tool) {
|
||||
|
||||
|
@ -20,7 +20,7 @@ public abstract class TreeEvent extends PlayerEvent {
|
||||
/**
|
||||
* Get the tree blocks
|
||||
*
|
||||
* @return tree checker for the tree
|
||||
* @return The blocks that are part of the tree
|
||||
*/
|
||||
public TreeBlockSet<Block> getTreeBlocks() {
|
||||
return this.treeBlocks;
|
||||
|
@ -6,6 +6,7 @@ import com.songoda.ultimatetimber.hooks.McMMOHook;
|
||||
import com.songoda.ultimatetimber.hooks.TimberHook;
|
||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
@ -56,7 +57,7 @@ public class HookManager extends Manager {
|
||||
* @param player The player to apply the hook for
|
||||
* @param treeBlocks The blocks of the tree that were broken
|
||||
*/
|
||||
public void applyHooks(Player player, TreeBlockSet treeBlocks) {
|
||||
public void applyHooks(Player player, TreeBlockSet<Block> treeBlocks) {
|
||||
Set<TimberHook> invalidHooks = new HashSet<>();
|
||||
for (TimberHook hook : this.hooks) {
|
||||
try {
|
||||
|
@ -1,33 +0,0 @@
|
||||
package com.songoda.ultimatetimber.manager;
|
||||
|
||||
import com.songoda.ultimatetimber.UltimateTimber;
|
||||
|
||||
public class MessageManager extends Manager {
|
||||
|
||||
public enum MessageType {
|
||||
TOGGLE_ON,
|
||||
TOGGLE_OFF,
|
||||
RELOAD
|
||||
}
|
||||
|
||||
private final String prefix = "&8[&6UltimateTimber&8]";
|
||||
|
||||
public MessageManager(UltimateTimber ultimateTimber) {
|
||||
super(ultimateTimber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,6 @@ import com.songoda.ultimatetimber.tree.TreeDefinition;
|
||||
import com.songoda.ultimatetimber.tree.TreeLoot;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@ -56,6 +55,7 @@ public class TreeDefinitionManager extends Manager {
|
||||
Set<BlockState> leafBlockStates = new HashSet<>();
|
||||
BlockState saplingBlockState;
|
||||
int maxLeafDistanceFromLog;
|
||||
boolean detectLeavesDiagonally;
|
||||
boolean dropOriginalLog;
|
||||
boolean dropOriginalLeaf;
|
||||
Set<TreeLoot> logLoot = new HashSet<>();
|
||||
@ -70,6 +70,7 @@ public class TreeDefinitionManager extends Manager {
|
||||
|
||||
saplingBlockState = versionAdapter.parseBlockStateFromString(tree.getString("sapling"));
|
||||
maxLeafDistanceFromLog = tree.getInt("max-leaf-distance-from-log");
|
||||
detectLeavesDiagonally = tree.getBoolean("search-for-leaves-diagonally");
|
||||
dropOriginalLog = tree.getBoolean("drop-original-log");
|
||||
dropOriginalLeaf = tree.getBoolean("drop-original-leaf");
|
||||
|
||||
@ -84,7 +85,7 @@ public class TreeDefinitionManager extends Manager {
|
||||
for (String itemStackString : tree.getStringList("required-tools"))
|
||||
requiredTools.add(versionAdapter.parseItemStackFromString(itemStackString));
|
||||
|
||||
this.treeDefinitions.add(new TreeDefinition(key, logBlockStates, leafBlockStates, saplingBlockState, maxLeafDistanceFromLog, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, requiredTools));
|
||||
this.treeDefinitions.add(new TreeDefinition(key, logBlockStates, leafBlockStates, saplingBlockState, maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, requiredTools));
|
||||
}
|
||||
|
||||
// Load global log drops
|
||||
@ -107,6 +108,54 @@ public class TreeDefinitionManager extends Manager {
|
||||
this.treeDefinitions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Set of possible TreeDefinitions that match the given BlockState
|
||||
*
|
||||
* @param blockState The BlockState to check
|
||||
* @return A Set of TreeDefinitions for the given BlockState
|
||||
*/
|
||||
public Set<TreeDefinition> getTreeDefinitionsForLog(BlockState blockState) {
|
||||
return this.narrowTreeDefinition(this.treeDefinitions, blockState, TreeBlockType.LOG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Narrows a Set of TreeDefinitions down to ones matching the given BlockState and TreeBlockType
|
||||
*
|
||||
* @param possibleTreeDefinitions The possible TreeDefinitions
|
||||
* @param blockState The BlockState to narrow to
|
||||
* @param treeBlockType The TreeBlockType of the given BlockState
|
||||
* @return A Set of TreeDefinitions narrowed down
|
||||
*/
|
||||
public Set<TreeDefinition> narrowTreeDefinition(Set<TreeDefinition> possibleTreeDefinitions, BlockState blockState, TreeBlockType treeBlockType) {
|
||||
VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter();
|
||||
|
||||
Set<TreeDefinition> matchingTreeDefinitions = new HashSet<>();
|
||||
switch (treeBlockType) {
|
||||
case LOG:
|
||||
for (TreeDefinition treeDefinition : this.treeDefinitions) {
|
||||
for (BlockState logBlockState : treeDefinition.getLogBlockStates()) {
|
||||
if (versionAdapter.areBlockStatesSimilar(logBlockState, blockState)) {
|
||||
matchingTreeDefinitions.add(treeDefinition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LEAF:
|
||||
for (TreeDefinition treeDefinition : this.treeDefinitions) {
|
||||
for (BlockState leafBlockState : treeDefinition.getLeafBlockStates()) {
|
||||
if (versionAdapter.areBlockStatesSimilar(leafBlockState, blockState)) {
|
||||
matchingTreeDefinitions.add(treeDefinition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return matchingTreeDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given tool is valid for a given tree definition, also takes into account global tools
|
||||
*
|
||||
|
@ -1,18 +1,65 @@
|
||||
package com.songoda.ultimatetimber.manager;
|
||||
|
||||
import com.songoda.ultimatetimber.UltimateTimber;
|
||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
||||
import com.songoda.ultimatetimber.tree.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TreeDetectionManager extends Manager {
|
||||
|
||||
private UltimateTimber ultimateTimber;
|
||||
private final Set<Vector> VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS;
|
||||
|
||||
private TreeDefinitionManager treeDefinitionManager;
|
||||
private int maxBranchBlocksAllowed;
|
||||
private int numLeavesRequiredForTree;
|
||||
private boolean allowMixedTreeTypes;
|
||||
private boolean onlyBreakLogsUpwards;
|
||||
private boolean destroyBaseLog;
|
||||
private boolean entireTreeBase;
|
||||
|
||||
public TreeDetectionManager(UltimateTimber ultimateTimber) {
|
||||
super(ultimateTimber);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -20,4 +67,154 @@ public class TreeDetectionManager extends Manager {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects a tree given an initial starting block
|
||||
*
|
||||
* @param initialBlock The starting Block of the detection
|
||||
* @return A DetectedTree if one was found, otherwise null
|
||||
*/
|
||||
public DetectedTree detectTree(Block initialBlock) {
|
||||
TreeBlock initialTreeBlock = new TreeBlock(initialBlock, TreeBlockType.LOG);
|
||||
TreeBlockSet<Block> detectedTreeBlocks = new TreeBlockSet<>(initialTreeBlock);
|
||||
Set<TreeDefinition> possibleTreeDefinitions = treeDefinitionManager.getTreeDefinitionsForLog(initialBlock.getState());
|
||||
|
||||
// Detect tree trunk
|
||||
Set<Block> trunkBlocks = new HashSet<>();
|
||||
trunkBlocks.add(initialBlock);
|
||||
Block targetBlock = initialBlock;
|
||||
while (this.isValidLogType(possibleTreeDefinitions, (targetBlock = targetBlock.getRelative(BlockFace.UP)))) {
|
||||
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LOG);
|
||||
detectedTreeBlocks.add(treeBlock);
|
||||
trunkBlocks.add(initialBlock);
|
||||
possibleTreeDefinitions.retainAll(this.treeDefinitionManager.narrowTreeDefinition(possibleTreeDefinitions, targetBlock.getState(), TreeBlockType.LOG));
|
||||
}
|
||||
|
||||
// Tree must be at least 2 blocks tall
|
||||
if (detectedTreeBlocks.size() < 2)
|
||||
return null;
|
||||
|
||||
// Detect branches off the main trunk
|
||||
for (Block trunkBlock : trunkBlocks)
|
||||
this.recursiveBranchSearch(possibleTreeDefinitions, detectedTreeBlocks, trunkBlock, initialBlock.getY());
|
||||
|
||||
// Detect leaves off the trunk/branches
|
||||
Set<ITreeBlock<Block>> branchBlocks = new HashSet<>(detectedTreeBlocks.getLogBlocks());
|
||||
for (ITreeBlock<Block> branchBlock : branchBlocks)
|
||||
this.recursiveLeafSearch(possibleTreeDefinitions, detectedTreeBlocks, branchBlock.getBlock(), 1);
|
||||
|
||||
// Trees need at least a certain number of leaves
|
||||
if (detectedTreeBlocks.getLeafBlocks().size() < this.numLeavesRequiredForTree)
|
||||
return null;
|
||||
|
||||
// TODO: Soil detection
|
||||
|
||||
// Delete the starting block if applicable
|
||||
if (this.destroyBaseLog)
|
||||
detectedTreeBlocks.remove(initialTreeBlock);
|
||||
|
||||
// Use the first tree definition in the set
|
||||
return new DetectedTree(possibleTreeDefinitions.iterator().next(), detectedTreeBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively searches for branches off a given block
|
||||
*
|
||||
* @param treeDefinitions The possible tree definitions
|
||||
* @param treeBlocks The detected tree blocks
|
||||
* @param block The next block to check for a branch
|
||||
* @param startingBlockY The Y coordinate of the initial block
|
||||
*/
|
||||
private void recursiveBranchSearch(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block, int startingBlockY) {
|
||||
if (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());
|
||||
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LOG);
|
||||
if (this.isValidLogType(treeDefinitions, targetBlock) && !treeBlocks.contains(treeBlock)) {
|
||||
treeBlocks.add(treeBlock);
|
||||
treeDefinitions.retainAll(this.treeDefinitionManager.narrowTreeDefinition(treeDefinitions, block.getState(), TreeBlockType.LOG));
|
||||
if (!this.onlyBreakLogsUpwards || targetBlock.getLocation().getBlockY() > startingBlockY)
|
||||
this.recursiveBranchSearch(treeDefinitions, treeBlocks, targetBlock, startingBlockY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively searches for leaves that are next to this tree
|
||||
*
|
||||
* @param treeDefinitions The possible tree definitions
|
||||
* @param treeBlocks The detected tree blocks
|
||||
* @param block The next block to check for a leaf
|
||||
* @param distanceFromLog The distance this leaf is from a log
|
||||
*/
|
||||
private void recursiveLeafSearch(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block, int distanceFromLog) {
|
||||
int maxDistanceFromLog = treeDefinitions.stream().max(Comparator.comparingInt(TreeDefinition::getMaxLeafDistanceFromLog)).get().getMaxLeafDistanceFromLog();
|
||||
boolean detectLeavesDiagonally = treeDefinitions.stream().anyMatch(TreeDefinition::shouldDetectLeavesDiagonally);
|
||||
|
||||
if (distanceFromLog > maxDistanceFromLog)
|
||||
return;
|
||||
|
||||
for (Vector offset : !detectLeavesDiagonally ? VALID_LEAF_OFFSETS : 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)) {
|
||||
if (!treeBlocks.contains(treeBlock) && !this.doesLeafBorderInvalidLog(treeDefinitions, treeBlocks, targetBlock)) {
|
||||
treeBlocks.add(treeBlock);
|
||||
treeDefinitions.retainAll(this.treeDefinitionManager.narrowTreeDefinition(treeDefinitions, block.getState(), TreeBlockType.LEAF));
|
||||
}
|
||||
this.recursiveLeafSearch(treeDefinitions, treeBlocks, targetBlock, distanceFromLog + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a leaf is bordering a log that isn't part of this tree
|
||||
*
|
||||
* @param treeDefinitions The possible tree definitions
|
||||
* @param treeBlocks The detected tree blocks
|
||||
* @param block The block to check
|
||||
* @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) {
|
||||
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
||||
if (this.isValidLogType(treeDefinitions, targetBlock) && !treeBlocks.contains(new TreeBlock(targetBlock, TreeBlockType.LOG)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given block is valid for the given TreeDefinitions
|
||||
*
|
||||
* @param treeDefinitions The Set of TreeDefinitions to compare against
|
||||
* @param block The Block to check
|
||||
* @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 (BlockState logBlockState : treeDefinition.getLogBlockStates())
|
||||
if (versionAdapter.areBlockStatesSimilar(logBlockState, block.getState()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given block is valid for the given TreeDefinitions
|
||||
*
|
||||
* @param treeDefinitions The Set of TreeDefinitions to compare against
|
||||
* @param block The Block to check
|
||||
* @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 (BlockState leafBlockState : treeDefinition.getLeafBlockStates())
|
||||
if (versionAdapter.areBlockStatesSimilar(leafBlockState, block.getState()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.songoda.ultimatetimber.tree;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class DetectedTree {
|
||||
|
||||
private TreeDefinition treeDefinition;
|
||||
private TreeBlockSet<Block> detectedTreeBlocks;
|
||||
|
||||
public DetectedTree(TreeDefinition treeDefinition, TreeBlockSet<Block> detectedTreeBlocks) {
|
||||
this.treeDefinition = treeDefinition;
|
||||
this.detectedTreeBlocks = detectedTreeBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TreeDefinition of this detected tree
|
||||
*
|
||||
* @return The TreeDefinition of this detected tree
|
||||
*/
|
||||
public TreeDefinition getTreeDefinition() {
|
||||
return this.treeDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blocks that were detected as part of this tree
|
||||
*
|
||||
* @return A TreeBlockSet of detected Blocks
|
||||
*/
|
||||
public TreeBlockSet<Block> getDetectedTreeBlocks() {
|
||||
return this.detectedTreeBlocks;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.songoda.ultimatetimber.tree;
|
||||
|
||||
import com.songoda.ultimatetimber.UltimateTimber;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -15,7 +16,7 @@ public class FallingTreeBlock implements ITreeBlock<FallingBlock> {
|
||||
public FallingTreeBlock(TreeBlock originalTreeBlock, FallingBlock fallingBlock, TreeBlockType treeBlockType) {
|
||||
this.fallingBlock = fallingBlock;
|
||||
this.treeBlockType = treeBlockType;
|
||||
this.drops = originalTreeBlock.getDrops();
|
||||
this.drops = UltimateTimber.getInstance().getVersionAdapter().getBlockDrops(originalTreeBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.songoda.ultimatetimber.tree;
|
||||
|
||||
import com.songoda.ultimatetimber.UltimateTimber;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class TreeBlock implements ITreeBlock<Block> {
|
||||
|
||||
@ -29,7 +29,7 @@ public class TreeBlock implements ITreeBlock<Block> {
|
||||
|
||||
@Override
|
||||
public Collection<ItemStack> getDrops() {
|
||||
return this.block.getDrops();
|
||||
return UltimateTimber.getInstance().getVersionAdapter().getBlockDrops(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -12,18 +12,20 @@ public class TreeDefinition {
|
||||
private final Set<BlockState> logBlockStates, leafBlockStates;
|
||||
private final BlockState saplingBlockState;
|
||||
private final int maxLeafDistanceFromLog;
|
||||
private final boolean detectLeavesDiagonally;
|
||||
private final boolean dropOriginalLog, dropOriginalLeaf;
|
||||
private final Set<TreeLoot> logLoot, leafLoot;
|
||||
private final Set<ItemStack> requiredTools;
|
||||
|
||||
public TreeDefinition(String key, Set<BlockState> logBlocks, Set<BlockState> leafBlocks, BlockState saplingBlockState,
|
||||
int maxLeafDistanceFromLog, boolean dropOriginalLog, boolean dropOriginalLeaf,
|
||||
int maxLeafDistanceFromLog, boolean detectLeavesDiagonally, boolean dropOriginalLog, boolean dropOriginalLeaf,
|
||||
Set<TreeLoot> logLoot, Set<TreeLoot> leafLoot, Set<ItemStack> requiredTools) {
|
||||
this.key = key;
|
||||
this.logBlockStates = logBlocks;
|
||||
this.leafBlockStates = leafBlocks;
|
||||
this.saplingBlockState = saplingBlockState;
|
||||
this.maxLeafDistanceFromLog = maxLeafDistanceFromLog;
|
||||
this.detectLeavesDiagonally = detectLeavesDiagonally;
|
||||
this.dropOriginalLog = dropOriginalLog;
|
||||
this.dropOriginalLeaf = dropOriginalLeaf;
|
||||
this.logLoot = logLoot;
|
||||
@ -76,6 +78,15 @@ public class TreeDefinition {
|
||||
return this.maxLeafDistanceFromLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if tree detection should check for leaves diagonally
|
||||
*
|
||||
* @return True if leaves should be searched for diagonally, otherwise false
|
||||
*/
|
||||
public boolean shouldDetectLeavesDiagonally() {
|
||||
return this.detectLeavesDiagonally;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the logs of this tree should drop their original block
|
||||
*
|
||||
|
@ -125,6 +125,7 @@ trees:
|
||||
- OAK_LEAVES
|
||||
sapling: OAK_SAPLING
|
||||
max-leaf-distance-from-log: 6
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -146,6 +147,7 @@ trees:
|
||||
- SPRUCE_LEAVES
|
||||
sapling: SPRUCE_SAPLING
|
||||
max-leaf-distance-from-log: 6
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -164,6 +166,7 @@ trees:
|
||||
- SPRUCE_BIRCH
|
||||
sapling: BIRCH_SAPLING
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -182,6 +185,7 @@ trees:
|
||||
- SPRUCE_LEAVES
|
||||
sapling: SPRUCE_SAPLING
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -200,6 +204,7 @@ trees:
|
||||
- ACACIA_LEAVES
|
||||
sapling: ACACIA_SAPLING
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -218,6 +223,7 @@ trees:
|
||||
- DARK_OAK_LEAVES
|
||||
sapling: DARK_OAK_SAPLING
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -236,6 +242,7 @@ trees:
|
||||
- BROWN_MUSHROOM_BLOCK
|
||||
sapling: BROWN_MUSHROOM
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: false
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -251,6 +258,7 @@ trees:
|
||||
- RED_MUSHROOM_BLOCK
|
||||
sapling: RED_MUSHROOM
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: true
|
||||
drop-original-log: false
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
|
@ -128,6 +128,7 @@ trees:
|
||||
- LEAVES:12
|
||||
sapling: SAPLING:0
|
||||
max-leaf-distance-from-log: 6
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -152,6 +153,7 @@ trees:
|
||||
- LEAVES:13
|
||||
sapling: SAPLING:1
|
||||
max-leaf-distance-from-log: 6
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -173,6 +175,7 @@ trees:
|
||||
- LEAVES:14
|
||||
sapling: SAPLING:2
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -194,6 +197,7 @@ trees:
|
||||
- LEAVES:15
|
||||
sapling: SAPLING:3
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -215,6 +219,7 @@ trees:
|
||||
- LEAVES_2:12
|
||||
sapling: SAPLING:4
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -236,6 +241,7 @@ trees:
|
||||
- LEAVES:13
|
||||
sapling: SAPLING:5
|
||||
max-leaf-distance-from-log: 5
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: true
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -265,6 +271,7 @@ trees:
|
||||
- HUGE_MUSHROOM_1:14
|
||||
sapling: BROWN_MUSHROOM
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: false
|
||||
drop-original-log: false
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
@ -291,6 +298,7 @@ trees:
|
||||
- HUGE_MUSHROOM_2:14
|
||||
sapling: RED_MUSHROOM
|
||||
max-leaf-distance-from-log: 4
|
||||
search-for-leaves-diagonally: true
|
||||
drop-original-log: false
|
||||
drop-original-leaf: false
|
||||
log-loot: []
|
||||
|
Loading…
Reference in New Issue
Block a user