Entire tree loot, topple cooldown, sneaking change

This commit is contained in:
Esophose 2019-05-01 01:33:21 -06:00
parent 90ba6bbf02
commit 7d716fe62b
10 changed files with 213 additions and 41 deletions

View File

@ -106,7 +106,7 @@ public class LegacyAdapter implements VersionAdapter {
@Override
public void applyToolDurability(Player player, int damage) {
ItemStack tool = this.getItemInHand(player);
if (tool.getType().getMaxDurability() <= 1)
if (tool.getType().getMaxDurability() < 1)
return;
int unbreakingLevel = tool.getEnchantmentLevel(Enchantment.DURABILITY);

View File

@ -0,0 +1,20 @@
package com.songoda.ultimatetimber.misc;
public enum OnlyToppleWhile {
SNEAKING,
NOT_SNEAKING,
ALWAYS;
/**
* Gets an OnlyToppleWhile from a given string
*
* @param string The string
* @return The TreeAnimationType, returns FANCY if the string is an invalid type
*/
public static OnlyToppleWhile fromString(String string) {
for (OnlyToppleWhile value : values())
if (value.name().equalsIgnoreCase(string))
return value;
return OnlyToppleWhile.ALWAYS;
}
}

View File

@ -14,13 +14,13 @@ public class TreeDefinition {
private final int maxLeafDistanceFromLog;
private final boolean detectLeavesDiagonally;
private final boolean dropOriginalLog, dropOriginalLeaf;
private final Set<TreeLoot> logLoot, leafLoot;
private final Set<TreeLoot> logLoot, leafLoot, entireTreeLoot;
private final Set<ItemStack> requiredTools;
public TreeDefinition(String key, Set<IBlockData> logBlockData, Set<IBlockData> leafBlockData, IBlockData saplingBlockData,
Set<IBlockData> plantableSoilBlockData, int maxLeafDistanceFromLog, boolean detectLeavesDiagonally,
boolean dropOriginalLog, boolean dropOriginalLeaf, Set<TreeLoot> logLoot,
Set<TreeLoot> leafLoot, Set<ItemStack> requiredTools) {
boolean dropOriginalLog, boolean dropOriginalLeaf, Set<TreeLoot> logLoot, Set<TreeLoot> leafLoot,
Set<TreeLoot> entireTreeLoot, Set<ItemStack> requiredTools) {
this.key = key;
this.logBlockData = logBlockData;
this.leafBlockData = leafBlockData;
@ -32,6 +32,7 @@ public class TreeDefinition {
this.dropOriginalLeaf = dropOriginalLeaf;
this.logLoot = logLoot;
this.leafLoot = leafLoot;
this.entireTreeLoot = entireTreeLoot;
this.requiredTools = requiredTools;
}
@ -134,6 +135,15 @@ public class TreeDefinition {
return Collections.unmodifiableSet(this.leafLoot);
}
/**
* Gets the loot for this TreeDefinition
*
* @return A Set of TreeLoot
*/
public Set<TreeLoot> getEntireTreeLoot() {
return Collections.unmodifiableSet(this.entireTreeLoot);
}
/**
* Gets the tools that can be used to activate this tree topple
*

View File

@ -1,29 +1,39 @@
package com.songoda.ultimatetimber.manager;
import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class ChoppingManager extends Manager {
private Set<UUID> disabledPlayers;
private Map<UUID, Boolean> cooldownedPlayers;
private boolean useCooldown;
private int cooldownAmount;
public ChoppingManager(UltimateTimber ultimateTimber) {
super(ultimateTimber);
this.disabledPlayers = new HashSet<>();
this.cooldownedPlayers = new HashMap<>();
}
@Override
public void reload() {
this.useCooldown = ConfigurationManager.Setting.PLAYER_TREE_TOPPLE_COOLDOWN.getBoolean();
this.cooldownAmount = ConfigurationManager.Setting.PLAYER_TREE_TOPPLE_COOLDOWN_LENGTH.getInt();
}
@Override
public void disable() {
this.disabledPlayers.clear();
this.cooldownedPlayers.clear();
}
/**
@ -52,4 +62,34 @@ public class ChoppingManager extends Manager {
return !this.disabledPlayers.contains(player.getUniqueId());
}
/**
* Sets a player into cooldown
*
* @param player The player to cooldown
*/
public void cooldownPlayer(Player player) {
if (!this.useCooldown || player.hasPermission("ultimatetimber.bypasscooldown"))
return;
this.cooldownedPlayers.put(player.getUniqueId(), false);
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () ->
this.cooldownedPlayers.remove(player.getUniqueId()), this.cooldownAmount * 20L);
}
/**
* Checks if a player is in cooldown
*
* @param player The player to check
* @return True if the player can topple trees, otherwise false
*/
public boolean isInCooldown(Player player) {
boolean cooldowned = !this.useCooldown && this.cooldownedPlayers.containsKey(player.getUniqueId());
if (this.cooldownedPlayers.containsKey(player.getUniqueId()) && !this.cooldownedPlayers.get(player.getUniqueId())) {
player.sendMessage(UltimateTimber.getInstance().getPrefix() + ChatColor.YELLOW + "You are on cooldown and cannot topple trees right now.");
this.cooldownedPlayers.replace(player.getUniqueId(), true);
}
return cooldowned;
}
}

View File

@ -22,9 +22,11 @@ public class ConfigurationManager extends Manager {
BREAK_ENTIRE_TREE_BASE(SettingType.BOOLEAN),
DESTROY_INITIATED_BLOCK(SettingType.BOOLEAN),
ONLY_DETECT_LOGS_UPWARDS(SettingType.BOOLEAN),
ONLY_TOPPLE_WHILE_SNEAKING(SettingType.BOOLEAN),
ONLY_TOPPLE_WHILE(SettingType.STRING),
ALLOW_CREATIVE_MODE(SettingType.BOOLEAN),
REQUIRE_CHOP_PERMISSION(SettingType.BOOLEAN),
PLAYER_TREE_TOPPLE_COOLDOWN(SettingType.BOOLEAN),
PLAYER_TREE_TOPPLE_COOLDOWN_LENGTH(SettingType.INT),
IGNORE_REQUIRED_TOOLS(SettingType.BOOLEAN),
REPLANT_SAPLINGS(SettingType.BOOLEAN),
REPLANT_SAPLINGS_COOLDOWN(SettingType.INT),

View File

@ -66,6 +66,7 @@ public class TreeDefinitionManager extends Manager {
boolean dropOriginalLeaf;
Set<TreeLoot> logLoot = new HashSet<>();
Set<TreeLoot> leafLoot = new HashSet<>();
Set<TreeLoot> entireTreeLoot = new HashSet<>();
Set<ItemStack> requiredTools = new HashSet<>();
for (String blockDataString : tree.getStringList("logs"))
@ -94,10 +95,16 @@ public class TreeDefinitionManager extends Manager {
for (String lootKey : leafLootSection.getKeys(false))
leafLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey)));
ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot");
if (entireTreeLootSection != null)
for (String lootKey : entireTreeLootSection.getKeys(false))
entireTreeLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey)));
for (String itemStackString : tree.getStringList("required-tools"))
requiredTools.add(versionAdapter.parseItemStackFromString(itemStackString));
this.treeDefinitions.add(new TreeDefinition(key, logBlockData, leafBlockData, saplingBlockData, plantableSoilBlockData, maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, requiredTools));
this.treeDefinitions.add(new TreeDefinition(key, logBlockData, leafBlockData, saplingBlockData, plantableSoilBlockData,
maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, entireTreeLoot, requiredTools));
}
// Load global plantable soil
@ -211,13 +218,14 @@ public class TreeDefinitionManager extends Manager {
}
/**
* Tries to spawn loot for a given TreeBlock with the given TreeDefinition for a given player
* Tries to spawn loot for a given TreeBlock with the given TreeDefinition for a given Player
*
* @param treeDefinition The TreeDefinition to use
* @param treeBlock The TreeBlock to drop for
* @param player The Player to drop for
* @param isForEntireTree If the loot is for the entire tree
*/
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player, boolean hasSilkTouch) {
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player, boolean hasSilkTouch, boolean isForEntireTree) {
VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter();
HookManager hookManager = this.ultimateTimber.getHookManager();
@ -228,28 +236,32 @@ public class TreeDefinitionManager extends Manager {
// Get the loot that we should try to drop
List<TreeLoot> toTry = new ArrayList<>();
if (hasSilkTouch) {
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
if (isForEntireTree) {
toTry.addAll(treeDefinition.getEntireTreeLoot());
} else {
switch (treeBlock.getTreeBlockType()) {
case LOG:
toTry.addAll(treeDefinition.getLogLoot());
toTry.addAll(this.globalLogLoot);
if (treeDefinition.shouldDropOriginalLog()) {
if (hookManager.shouldApplyDoubleDropsHooks(player))
if (hasSilkTouch) {
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
} else {
switch (treeBlock.getTreeBlockType()) {
case LOG:
toTry.addAll(treeDefinition.getLogLoot());
toTry.addAll(this.globalLogLoot);
if (treeDefinition.shouldDropOriginalLog()) {
if (hookManager.shouldApplyDoubleDropsHooks(player))
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
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 (hookManager.shouldApplyDoubleDropsHooks(player))
}
break;
case LEAF:
toTry.addAll(treeDefinition.getLeafLoot());
toTry.addAll(this.globalLeafLoot);
if (treeDefinition.shouldDropOriginalLeaf()) {
if (hookManager.shouldApplyDoubleDropsHooks(player))
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
}
break;
}
break;
}
}
}

View File

@ -4,6 +4,7 @@ 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.misc.OnlyToppleWhile;
import com.songoda.ultimatetimber.tree.DetectedTree;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@ -62,7 +63,7 @@ public class TreeFallManager extends Manager implements Listener {
if (!ConfigurationManager.Setting.ALLOW_CREATIVE_MODE.getBoolean() && player.getGameMode().equals(GameMode.CREATIVE))
isValid = false;
if (ConfigurationManager.Setting.ONLY_TOPPLE_WHILE_SNEAKING.getBoolean() && !player.isSneaking())
if (!this.checkToppleWhile(player))
isValid = false;
if (ConfigurationManager.Setting.REQUIRE_CHOP_PERMISSION.getBoolean() && !player.hasPermission("ultimatetimber.chop"))
@ -71,6 +72,9 @@ public class TreeFallManager extends Manager implements Listener {
if (!choppingManager.isChopping(player))
isValid = false;
if (choppingManager.isInCooldown(player))
isValid = false;
if (treeAnimationManager.isBlockInAnimation(block)) {
isValid = false;
event.setCancelled(true);
@ -114,6 +118,8 @@ public class TreeFallManager extends Manager implements Listener {
// Valid tree and meets all conditions past this point
event.setCancelled(true);
choppingManager.cooldownPlayer(player);
// Destroy initiated block if enabled
if (ConfigurationManager.Setting.DESTROY_INITIATED_BLOCK.getBoolean()) {
detectedTree.getDetectedTreeBlocks().getInitialLogBlock().getBlock().setType(Material.AIR);
@ -125,10 +131,28 @@ public class TreeFallManager extends Manager implements Listener {
hookManager.applyExperienceHooks(player, detectedTree.getDetectedTreeBlocks());
treeAnimationManager.runAnimation(detectedTree, player);
treeDefinitionManager.dropTreeLoot(detectedTree.getTreeDefinition(), detectedTree.getDetectedTreeBlocks().getInitialLogBlock(), player, false, true);
// Trigger fell event
TreeFellEvent treeFellEvent = new TreeFellEvent(player, detectedTree);
Bukkit.getPluginManager().callEvent(treeFellEvent);
}
/**
* Checks if a player is doing a certain action required to topple a tree
*
* @param player The player to check
* @return True if the check passes, otherwise false
*/
private boolean checkToppleWhile(Player player) {
switch (OnlyToppleWhile.fromString(ConfigurationManager.Setting.ONLY_TOPPLE_WHILE.getString())) {
case SNEAKING:
return player.isSneaking();
case NOT_SNEAKING:
return !player.isSneaking();
default:
return true;
}
}
}

View File

@ -49,17 +49,27 @@ destroy-initiated-block: false
# Default: true
only-detect-logs-upwards: true
# Only topple over trees while the player is sneaking
# Default: false
only-topple-while-sneaking: false
# Only topple trees while the player is doing something
# Valid values: SNEAKING, NOT_SNEAKING, ALWAYS
# Default: ALWAYS
only-topple-while: ALWAYS
# Allow toppling trees in creative mode
# Default: true
allow-creative-mode: true
# Require the player to have the permission 'ultimatetimber.chop' to topple trees
# Default: true
require-chop-permission: true
# Default: false
require-chop-permission: false
# If a player should only be allowed to chop one tree per cooldown length
# Default: false
player-tree-topple-cooldown: false
# The amount of seconds a player has to wait before they can chop a tree again
# Does nothing if player-tree-topple-cooldown is false
# Default: 5
player-tree-topple-cooldown-length: 5
# Allow players to topple trees regardless of what they are holding in their hand
# Default: false
@ -178,6 +188,7 @@ trees:
1:
material: APPLE
chance: 0.5
entire-tree-loot: []
required-tools: []
spruce:
logs:
@ -198,6 +209,7 @@ trees:
0:
material: SPRUCE_SAPLING
chance: 5
entire-tree-loot: []
required-tools: []
birch:
logs:
@ -218,6 +230,7 @@ trees:
0:
material: BIRCH_SAPLING
chance: 5
entire-tree-loot: []
required-tools: []
jungle:
logs:
@ -238,6 +251,7 @@ trees:
0:
material: JUNGLE_SAPLING
chance: 2.5
entire-tree-loot: []
required-tools: []
acacia:
logs:
@ -258,6 +272,7 @@ trees:
0:
material: ACACIA_SAPLING
chance: 5
entire-tree-loot: []
required-tools: []
dark_oak:
logs:
@ -281,6 +296,7 @@ trees:
1:
material: APPLE
chance: 0.5
entire-tree-loot: []
required-tools: []
brown_mushroom:
logs:
@ -299,6 +315,7 @@ trees:
0:
material: BROWN_MUSHROOM
chance: 25
entire-tree-loot: []
required-tools: []
red_mushroom:
logs:
@ -317,6 +334,7 @@ trees:
0:
material: RED_MUSHROOM
chance: 25
entire-tree-loot: []
required-tools: []
# All soil types that the tree type's saplings can be planted on
@ -331,6 +349,7 @@ global-plantable-soil:
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# The default examples here are to show what you can do with custom loot
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-log-loot:
0:
material: DIAMOND
@ -347,10 +366,21 @@ global-log-loot:
# The loot applies to each leaf broken in the tree
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-leaf-loot:
0:
material: GOLDEN_APPLE
chance: 0.5
chance: 0.1
# Custom entire tree loot that is available for all tree types
# The loot will be dropped only one time for the entire tree
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-entire-tree-loot:
0:
material: DIAMOND
chance: 0
# Tools that must be used to topple over a tree
# Applies to all tree types

View File

@ -50,17 +50,27 @@ destroy-initiated-block: false
# Default: true
only-detect-logs-upwards: true
# Only topple over trees while the player is sneaking
# Default: false
only-topple-while-sneaking: false
# Only topple trees while the player is doing something
# Valid values: SNEAKING, NOT_SNEAKING, ALWAYS
# Default: ALWAYS
only-topple-while: ALWAYS
# Allow toppling trees in creative mode
# Default: true
allow-creative-mode: true
# Require the player to have the permission 'ultimatetimber.chop' to topple trees
# Default: true
require-chop-permission: true
# Default: false
require-chop-permission: false
# If a player should only be allowed to chop one tree per cooldown length
# Default: false
player-tree-topple-cooldown: false
# The amount of seconds a player has to wait before they can chop a tree again
# Does nothing if player-tree-topple-cooldown is false
# Default: 5
player-tree-topple-cooldown-length: 5
# Allow players to topple trees regardless of what they are holding in their hand
# Default: false
@ -176,6 +186,7 @@ trees:
1:
material: APPLE
chance: 0.5
entire-tree-loot: []
required-tools: []
spruce:
logs:
@ -193,6 +204,7 @@ trees:
0:
material: SAPLING:1
chance: 5
entire-tree-loot: []
required-tools: []
birch:
logs:
@ -210,6 +222,7 @@ trees:
0:
material: SAPLING:2
chance: 5
entire-tree-loot: []
required-tools: []
jungle:
logs:
@ -227,6 +240,7 @@ trees:
0:
material: SAPLING:3
chance: 2.5
entire-tree-loot: []
required-tools: []
acacia:
logs:
@ -244,6 +258,7 @@ trees:
0:
material: SAPLING:4
chance: 5
entire-tree-loot: []
required-tools: []
dark_oak:
logs:
@ -264,6 +279,7 @@ trees:
1:
material: APPLE
chance: 0.5
entire-tree-loot: []
required-tools: []
brown_mushroom:
logs:
@ -282,6 +298,7 @@ trees:
0:
material: BROWN_MUSHROOM
chance: 25
entire-tree-loot: []
required-tools: []
red_mushroom:
logs:
@ -300,6 +317,7 @@ trees:
0:
material: RED_MUSHROOM
chance: 25
entire-tree-loot: []
required-tools: []
# All soil types that the tree type's saplings can be planted on
@ -314,6 +332,7 @@ global-plantable-soil:
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# The default examples here are to show what you can do with custom loot
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-log-loot:
0:
material: DIAMOND
@ -330,11 +349,22 @@ global-log-loot:
# The loot applies to each leaf broken in the tree
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-leaf-loot:
0:
material: GOLDEN_APPLE
chance: 0.5
# Custom entire tree loot that is available for all tree types
# The loot will be dropped only one time for the entire tree
# To add more, increment the number by 1
# The chance is out of 100 and can contain decimals
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
global-entire-tree-loot:
0:
material: DIAMOND
chance: 0
# Tools that must be used to topple over a tree
# Applies to all tree types
global-required-tools:

View File

@ -1,6 +1,6 @@
name: UltimateTimber
version: @version@
author: Songoda
authors: [Songoda, Esophose]
main: com.songoda.ultimatetimber.UltimateTimber
api-version: 1.13
softdepend: [mcMMO, Jobs]
@ -16,6 +16,7 @@ permissions:
ultimatetimber.chop: true
ultimatetimber.bonusloot: true
ultimatetimber.reload: true
ultimatetimber.bypasscooldown: true
ultimatetimber.chop:
description: Allows players to trigger the trees toppling down effect
default: op
@ -25,3 +26,6 @@ permissions:
ultimatetimber.reload:
description: Reloads the configuration file
default: op
ultimatetimber.bypasscooldown:
description: Allows a player to bypass the tree topple cooldown
default: op