Hook tree loot double drops fix, placed block detection

This commit is contained in:
Esophose 2019-04-28 18:58:38 -06:00
parent a5b8fab267
commit 4b35f0ee4e
9 changed files with 193 additions and 21 deletions

View File

@ -8,6 +8,7 @@ import com.songoda.ultimatetimber.manager.CommandManager;
import com.songoda.ultimatetimber.manager.ConfigurationManager;
import com.songoda.ultimatetimber.manager.HookManager;
import com.songoda.ultimatetimber.manager.Manager;
import com.songoda.ultimatetimber.manager.PlacedBlockManager;
import com.songoda.ultimatetimber.manager.SaplingManager;
import com.songoda.ultimatetimber.manager.TreeAnimationManager;
import com.songoda.ultimatetimber.manager.TreeDefinitionManager;
@ -40,6 +41,7 @@ public class UltimateTimber extends JavaPlugin {
private CommandManager commandManager;
private ConfigurationManager configurationManager;
private HookManager hookManager;
private PlacedBlockManager placedBlockManager;
private SaplingManager saplingManager;
private TreeAnimationManager treeAnimationManager;
private TreeDefinitionManager treeDefinitionManager;
@ -63,6 +65,7 @@ public class UltimateTimber extends JavaPlugin {
this.commandManager = this.registerManager(CommandManager.class);
this.configurationManager = new ConfigurationManager(this);
this.hookManager = this.registerManager(HookManager.class);
this.placedBlockManager = this.registerManager(PlacedBlockManager.class);
this.saplingManager = this.registerManager(SaplingManager.class);
this.treeAnimationManager = this.registerManager(TreeAnimationManager.class);
this.treeDefinitionManager = this.registerManager(TreeDefinitionManager.class);
@ -187,6 +190,15 @@ public class UltimateTimber extends JavaPlugin {
return this.hookManager;
}
/**
* Gets the placed block manager
*
* @return The PlacedBlockManager instance
*/
public PlacedBlockManager getPlacedBlockManager() {
return this.placedBlockManager;
}
/**
* Gets the sapling manager
*

View File

@ -9,8 +9,10 @@ import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlock;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.block.Block;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collections;
@ -60,6 +62,11 @@ public class TreeAnimationDisintegrate extends TreeAnimation {
}
}
for (ITreeBlock<FallingBlock> fallingTreeBlock : TreeAnimationDisintegrate.this.fallingTreeBlocks.getAllTreeBlocks()) {
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
fallingBlock.setVelocity(fallingBlock.getVelocity().clone().subtract(new Vector(0, 0.05, 0)));
}
if (!toDestroy.isEmpty()) {
ITreeBlock<Block> first = toDestroy.get(0);
if (useCustomSound)

View File

@ -36,12 +36,13 @@ public class ConfigurationManager extends Manager {
USE_CUSTOM_SOUNDS(SettingType.BOOLEAN),
USE_CUSTOM_PARTICLES(SettingType.BOOLEAN),
BONUS_LOOT_MULTIPLIER(SettingType.DOUBLE),
IGNORE_PLACED_BLOCKS(SettingType.BOOLEAN),
IGNORE_PLACED_BLOCKS_MEMORY_SIZE(SettingType.INT),
HOOKS_APPLY_EXPERIENCE(SettingType.BOOLEAN),
HOOKS_APPLY_EXTRA_DROPS(SettingType.BOOLEAN),
HOOKS_REQUIRE_ABILITY_ACTIVE(SettingType.BOOLEAN),
TREE_ANIMATION_TYPE(SettingType.STRING),
SCATTER_TREE_BLOCKS_ON_GROUND(SettingType.BOOLEAN),
MIX_ALL_TREE_TYPES(SettingType.BOOLEAN);
SCATTER_TREE_BLOCKS_ON_GROUND(SettingType.BOOLEAN);
private SettingType settingType;
private Object value = null;

View File

@ -0,0 +1,124 @@
package com.songoda.ultimatetimber.manager;
import com.songoda.ultimatetimber.UltimateTimber;
import com.songoda.ultimatetimber.adapter.IBlockData;
import com.songoda.ultimatetimber.events.TreeFellEvent;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlockType;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.world.StructureGrowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class PlacedBlockManager extends Manager implements Listener {
private List<Location> placedBlocks;
private boolean ignorePlacedBlocks;
private int maxPlacedBlockMemorySize;
public PlacedBlockManager(UltimateTimber ultimateTimber) {
super(ultimateTimber);
this.placedBlocks = new ArrayList<>();
this.ignorePlacedBlocks = true;
this.maxPlacedBlockMemorySize = 10000;
Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
}
@Override
public void reload() {
this.placedBlocks.clear();
this.ignorePlacedBlocks = ConfigurationManager.Setting.IGNORE_PLACED_BLOCKS.getBoolean();
this.maxPlacedBlockMemorySize = ConfigurationManager.Setting.IGNORE_PLACED_BLOCKS_MEMORY_SIZE.getInt();
}
@Override
public void disable() {
this.placedBlocks.clear();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlaced(BlockPlaceEvent event) {
if (!this.ignorePlacedBlocks)
return;
this.internalProtect(event.getBlock(), true);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
if (!this.ignorePlacedBlocks)
return;
this.internalProtect(event.getBlock(), false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onLeafDecay(LeavesDecayEvent event) {
if (!this.ignorePlacedBlocks)
return;
this.internalProtect(event.getBlock(), false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onStructureGrow(StructureGrowEvent event) {
if (!this.ignorePlacedBlocks)
return;
for (BlockState blockState : event.getBlocks())
this.internalProtect(blockState.getBlock(), false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onTreeFell(TreeFellEvent event) {
if (!this.ignorePlacedBlocks)
return;
for (ITreeBlock<Block> treeBlock : event.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks())
this.internalProtect(treeBlock.getBlock(), false);
}
/**
* Handles when a block is placed/broken
*/
private void internalProtect(Block block, boolean isPlaced) {
if (isPlaced) {
if (this.isBlockPlaced(block))
return;
this.placedBlocks.add(block.getLocation());
if (this.placedBlocks.size() > this.maxPlacedBlockMemorySize)
this.placedBlocks.remove(0);
} else {
this.placedBlocks.remove(block.getLocation());
}
}
/**
* Gets if a block is placed
*
* @param block The Block to check
* @return True if the block is placed, otherwise false
*/
public boolean isBlockPlaced(Block block) {
return this.placedBlocks.contains(block.getLocation());
}
}

View File

@ -15,7 +15,9 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
@ -221,11 +223,11 @@ public class TreeDefinitionManager extends Manager {
boolean addToInventory = ConfigurationManager.Setting.ADD_ITEMS_TO_INVENTORY.getBoolean();
boolean hasBonusChance = player.hasPermission("ultimatetimber.bonusloot");
Set<ItemStack> lootedItems = new HashSet<>();
Set<String> lootedCommands = new HashSet<>();
List<ItemStack> lootedItems = new ArrayList<>();
List<String> lootedCommands = new ArrayList<>();
// Get the loot that we should try to drop
Set<TreeLoot> toTry = new HashSet<>();
List<TreeLoot> toTry = new ArrayList<>();
if (hasSilkTouch) {
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
} else {
@ -233,14 +235,20 @@ public class TreeDefinitionManager extends Manager {
case LOG:
toTry.addAll(treeDefinition.getLogLoot());
toTry.addAll(this.globalLogLoot);
if (treeDefinition.shouldDropOriginalLog())
if (treeDefinition.shouldDropOriginalLog()) {
if (hookManager.shouldApplyDoubleDropsHooks(player))
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
}
break;
case LEAF:
toTry.addAll(treeDefinition.getLeafLoot());
toTry.addAll(this.globalLeafLoot);
if (treeDefinition.shouldDropOriginalLeaf())
if (treeDefinition.shouldDropOriginalLeaf()) {
if (hookManager.shouldApplyDoubleDropsHooks(player))
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
}
break;
}
}
@ -267,7 +275,7 @@ public class TreeDefinitionManager extends Manager {
// Add to inventory or drop on ground
if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) {
Set<ItemStack> extraItems = new HashSet<>();
List<ItemStack> extraItems = new ArrayList<>();
for (ItemStack lootedItem : lootedItems)
extraItems.addAll(player.getInventory().addItem(lootedItem).values());
Location location = player.getLocation().clone().subtract(0.5, 0, 0.5);

View File

@ -24,6 +24,7 @@ public class TreeDetectionManager extends Manager {
private final Set<Vector> VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS;
private TreeDefinitionManager treeDefinitionManager;
private PlacedBlockManager placedBlockManager;
private int maxLogBlocksAllowed, numLeavesRequiredForTree;
private boolean onlyBreakLogsUpwards, entireTreeBase, destroyLeaves;
@ -57,6 +58,7 @@ public class TreeDetectionManager extends Manager {
@Override
public void reload() {
this.treeDefinitionManager = this.ultimateTimber.getTreeDefinitionManager();
this.placedBlockManager = this.ultimateTimber.getPlacedBlockManager();
this.maxLogBlocksAllowed = ConfigurationManager.Setting.MAX_LOGS_PER_CHOP.getInt();
this.numLeavesRequiredForTree = ConfigurationManager.Setting.LEAVES_REQUIRED_FOR_TREE.getInt();
this.onlyBreakLogsUpwards = ConfigurationManager.Setting.ONLY_DETECT_LOGS_UPWARDS.getBoolean();
@ -224,6 +226,9 @@ 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) {
if (this.placedBlockManager.isBlockPlaced(block))
return false;
for (TreeDefinition treeDefinition : treeDefinitions)
for (IBlockData logBlockData : treeDefinition.getLogBlockData())
if (logBlockData.isSimilar(block))
@ -239,6 +244,9 @@ 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) {
if (this.placedBlockManager.isBlockPlaced(block))
return false;
for (TreeDefinition treeDefinition : treeDefinitions)
for (IBlockData leafBlockData : treeDefinition.getLeafBlockData())
if (leafBlockData.isSimilar(block))

View File

@ -71,8 +71,10 @@ public class TreeFallManager extends Manager implements Listener {
if (!choppingManager.isChopping(player))
isValid = false;
if (treeAnimationManager.isBlockInAnimation(block))
if (treeAnimationManager.isBlockInAnimation(block)) {
isValid = false;
event.setCancelled(true);
}
if (!treeDefinitionManager.isToolValidForAnyTreeDefinition(tool))
isValid = false;

View File

@ -116,6 +116,17 @@ use-custom-particles: true
# Default: 2
bonus-loot-multiplier: 2
# If placed blocks should be ignored for toppling trees
# Note: This only keeps track of blocks placed during the current server load
# If your server restarts, the placed tree blocks could be toppled again
# Default: true
ignore-placed-blocks: true
# The maximum number of blocks to keep track of in memory at once
# Use a lower number if this starts to take up too much memory
# Default: 10000
ignore-placed-blocks-memory-size: 10000
# Applies experience when using Jobs/mcMMO
# Only does something if Jobs or mcMMO is installed
# Default: true
@ -140,12 +151,6 @@ tree-animation-type: FANCY
# Default: false
scatter-tree-blocks-on-ground: false
# Mix all the tree types below and consider all of them as a single tree type
# Useful for EpicWorldGenerator and similar plugins that make custom trees
# Warning: Custom loot can get messy with this enabled
# Default: false
mix-all-tree-types: false
# Tree configuration
# Allows for extreme fine-tuning of tree detection and what are considered trees
# Multiple log and leaf types are allowed, only one sapling type is allowed

View File

@ -117,6 +117,17 @@ use-custom-particles: true
# Default: 2
bonus-loot-multiplier: 2
# If placed blocks should be ignored for toppling trees
# Note: This only keeps track of blocks placed during the current server load
# If your server restarts, the placed tree blocks could be toppled again
# Default: true
ignore-placed-blocks: true
# The maximum number of blocks to keep track of in memory at once
# Use a lower number if this starts to take up too much memory
# Default: 10000
ignore-placed-blocks-memory-size: 10000
# Applies experience when using Jobs/mcMMO
# Only does something if Jobs or mcMMO is installed
# Default: true
@ -141,12 +152,6 @@ tree-animation-type: FANCY
# Default: false
scatter-tree-blocks-on-ground: false
# Mix all the tree types below and consider all of them as a single tree type
# Useful for EpicWorldGenerator and similar plugins that make custom trees
# Warning: Custom loot can get messy with this enabled
# Default: false
mix-all-tree-types: false
# Tree configuration
# Allows for extreme fine-tuning of tree detection and what are considered trees
# Multiple log and leaf types are allowed, only one sapling type is allowed