2019-03-26 21:35:17 +01:00
|
|
|
package com.songoda.ultimatetimber.manager;
|
|
|
|
|
2020-11-07 20:38:58 +01:00
|
|
|
import com.google.common.base.Strings;
|
2020-10-30 21:00:23 +01:00
|
|
|
import com.songoda.core.compatibility.CompatibleMaterial;
|
2020-11-07 20:38:58 +01:00
|
|
|
import com.songoda.core.compatibility.ServerVersion;
|
2020-08-29 00:54:47 +02:00
|
|
|
import com.songoda.core.hooks.McMMOHook;
|
2022-03-18 21:10:57 +01:00
|
|
|
import com.songoda.core.third_party.de.tr7zw.nbtapi.NBTItem;
|
2020-11-07 20:38:58 +01:00
|
|
|
import com.songoda.core.utils.TextUtils;
|
2019-03-26 21:35:17 +01:00
|
|
|
import com.songoda.ultimatetimber.UltimateTimber;
|
2019-03-28 09:30:33 +01:00
|
|
|
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
|
|
|
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
2019-03-26 21:35:17 +01:00
|
|
|
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
2019-03-28 09:30:33 +01:00
|
|
|
import com.songoda.ultimatetimber.tree.TreeLoot;
|
2020-10-30 21:00:23 +01:00
|
|
|
import com.songoda.ultimatetimber.utils.BlockUtils;
|
2019-03-28 09:30:33 +01:00
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.Location;
|
2020-11-07 20:38:58 +01:00
|
|
|
import org.bukkit.NamespacedKey;
|
2019-03-28 21:34:17 +01:00
|
|
|
import org.bukkit.block.Block;
|
2019-03-28 09:30:33 +01:00
|
|
|
import org.bukkit.configuration.ConfigurationSection;
|
|
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
2020-11-07 20:38:58 +01:00
|
|
|
import org.bukkit.enchantments.Enchantment;
|
2019-03-28 09:30:33 +01:00
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.inventory.ItemStack;
|
2020-11-07 20:38:58 +01:00
|
|
|
import org.bukkit.inventory.meta.ItemMeta;
|
2019-03-26 21:35:17 +01:00
|
|
|
|
2022-03-18 21:09:52 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Random;
|
|
|
|
import java.util.Set;
|
2020-11-07 20:38:58 +01:00
|
|
|
import java.util.stream.Collectors;
|
2019-03-26 21:35:17 +01:00
|
|
|
|
2019-03-28 01:56:39 +01:00
|
|
|
public class TreeDefinitionManager extends Manager {
|
2019-03-26 21:35:17 +01:00
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
private final Random random;
|
2020-10-30 21:00:23 +01:00
|
|
|
private final Set<TreeDefinition> treeDefinitions;
|
|
|
|
private final Set<CompatibleMaterial> globalPlantableSoil;
|
|
|
|
private final Set<TreeLoot> globalLogLoot, globalLeafLoot, globalEntireTreeLoot;
|
|
|
|
private final Set<ItemStack> globalRequiredTools;
|
2019-03-26 21:35:17 +01:00
|
|
|
|
2020-11-07 20:38:58 +01:00
|
|
|
private boolean globalAxeRequired;
|
|
|
|
private ItemStack requiredAxe;
|
|
|
|
private String requiredAxeKey;
|
|
|
|
|
2019-03-26 21:35:17 +01:00
|
|
|
public TreeDefinitionManager(UltimateTimber ultimateTimber) {
|
2019-03-28 01:56:39 +01:00
|
|
|
super(ultimateTimber);
|
2019-03-28 09:30:33 +01:00
|
|
|
this.random = new Random();
|
2019-03-26 21:35:17 +01:00
|
|
|
this.treeDefinitions = new HashSet<>();
|
2019-03-30 10:34:27 +01:00
|
|
|
this.globalPlantableSoil = new HashSet<>();
|
2019-03-28 09:30:33 +01:00
|
|
|
this.globalLogLoot = new HashSet<>();
|
|
|
|
this.globalLeafLoot = new HashSet<>();
|
2019-05-01 12:01:34 +02:00
|
|
|
this.globalEntireTreeLoot = new HashSet<>();
|
2019-03-28 09:30:33 +01:00
|
|
|
this.globalRequiredTools = new HashSet<>();
|
2019-03-26 21:35:17 +01:00
|
|
|
}
|
|
|
|
|
2019-03-28 01:56:39 +01:00
|
|
|
@Override
|
|
|
|
public void reload() {
|
|
|
|
this.treeDefinitions.clear();
|
2019-03-30 10:34:27 +01:00
|
|
|
this.globalPlantableSoil.clear();
|
2019-03-28 09:30:33 +01:00
|
|
|
this.globalLogLoot.clear();
|
|
|
|
this.globalLeafLoot.clear();
|
2019-05-01 12:01:34 +02:00
|
|
|
this.globalEntireTreeLoot.clear();
|
2019-03-28 09:30:33 +01:00
|
|
|
this.globalRequiredTools.clear();
|
2019-03-26 21:35:17 +01:00
|
|
|
|
2020-01-27 14:16:29 +01:00
|
|
|
ConfigurationManager configurationManager = this.plugin.getConfigurationManager();
|
2019-03-28 09:30:33 +01:00
|
|
|
YamlConfiguration config = configurationManager.getConfig();
|
|
|
|
|
|
|
|
// Load tree settings
|
|
|
|
ConfigurationSection treeSection = config.getConfigurationSection("trees");
|
2020-06-29 02:18:23 +02:00
|
|
|
top:
|
2019-03-28 09:30:33 +01:00
|
|
|
for (String key : treeSection.getKeys(false)) {
|
|
|
|
ConfigurationSection tree = treeSection.getConfigurationSection(key);
|
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
Set<CompatibleMaterial> logMaterials = new HashSet<>();
|
|
|
|
Set<CompatibleMaterial> leafMaterials = new HashSet<>();
|
|
|
|
CompatibleMaterial saplingMaterial;
|
|
|
|
Set<CompatibleMaterial> plantableSoilMaterial = new HashSet<>();
|
2019-05-03 02:33:26 +02:00
|
|
|
double maxLogDistanceFromTrunk;
|
2019-03-28 09:30:33 +01:00
|
|
|
int maxLeafDistanceFromLog;
|
2019-03-28 18:38:37 +01:00
|
|
|
boolean detectLeavesDiagonally;
|
2019-03-28 09:30:33 +01:00
|
|
|
boolean dropOriginalLog;
|
|
|
|
boolean dropOriginalLeaf;
|
|
|
|
Set<TreeLoot> logLoot = new HashSet<>();
|
|
|
|
Set<TreeLoot> leafLoot = new HashSet<>();
|
2019-05-01 09:33:21 +02:00
|
|
|
Set<TreeLoot> entireTreeLoot = new HashSet<>();
|
2019-03-28 09:30:33 +01:00
|
|
|
Set<ItemStack> requiredTools = new HashSet<>();
|
2020-11-07 20:38:58 +01:00
|
|
|
boolean requiredAxe;
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
for (String materialString : tree.getStringList("logs")) {
|
|
|
|
CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
|
|
|
|
if (material == null || material.getMaterial() == null) continue top;
|
|
|
|
logMaterials.add(material);
|
2020-06-29 02:18:23 +02:00
|
|
|
}
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
for (String materialString : tree.getStringList("leaves")) {
|
|
|
|
CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
|
|
|
|
if (material == null || material.getMaterial() == null) continue top;
|
|
|
|
leafMaterials.add(material);
|
2020-06-29 02:18:23 +02:00
|
|
|
}
|
2019-03-28 21:34:17 +01:00
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
saplingMaterial = CompatibleMaterial.getMaterial(tree.getString("sapling"));
|
2019-03-28 21:34:17 +01:00
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
for (String materialString : tree.getStringList("plantable-soil")) {
|
|
|
|
CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
|
|
|
|
if (material == null || material.getMaterial() == null) continue top;
|
|
|
|
plantableSoilMaterial.add(material);
|
|
|
|
}
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2019-05-03 02:33:26 +02:00
|
|
|
maxLogDistanceFromTrunk = tree.getDouble("max-log-distance-from-trunk");
|
2019-03-28 09:30:33 +01:00
|
|
|
maxLeafDistanceFromLog = tree.getInt("max-leaf-distance-from-log");
|
2019-03-28 18:38:37 +01:00
|
|
|
detectLeavesDiagonally = tree.getBoolean("search-for-leaves-diagonally");
|
2019-03-28 09:30:33 +01:00
|
|
|
dropOriginalLog = tree.getBoolean("drop-original-log");
|
|
|
|
dropOriginalLeaf = tree.getBoolean("drop-original-leaf");
|
|
|
|
|
|
|
|
ConfigurationSection logLootSection = tree.getConfigurationSection("log-loot");
|
2019-03-30 10:34:27 +01:00
|
|
|
if (logLootSection != null)
|
|
|
|
for (String lootKey : logLootSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
logLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logLootSection.getConfigurationSection(lootKey)));
|
2019-03-28 09:30:33 +01:00
|
|
|
|
|
|
|
ConfigurationSection leafLootSection = tree.getConfigurationSection("leaf-loot");
|
2019-03-30 10:34:27 +01:00
|
|
|
if (leafLootSection != null)
|
|
|
|
for (String lootKey : leafLootSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
leafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey)));
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2019-05-01 09:33:21 +02:00
|
|
|
ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot");
|
|
|
|
if (entireTreeLootSection != null)
|
|
|
|
for (String lootKey : entireTreeLootSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
entireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey)));
|
2019-05-01 09:33:21 +02:00
|
|
|
|
2020-06-29 02:18:23 +02:00
|
|
|
for (String itemStackString : tree.getStringList("required-tools")) {
|
2020-10-30 21:00:23 +01:00
|
|
|
CompatibleMaterial material = CompatibleMaterial.getMaterial(itemStackString);
|
|
|
|
if (material == null) continue top;
|
|
|
|
requiredTools.add(material.getItem());
|
2020-06-29 02:18:23 +02:00
|
|
|
}
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2020-11-07 20:38:58 +01:00
|
|
|
requiredAxe = tree.getBoolean("required-axe", false);
|
|
|
|
|
2020-10-30 21:00:23 +01:00
|
|
|
this.treeDefinitions.add(new TreeDefinition(key, logMaterials, leafMaterials, saplingMaterial, plantableSoilMaterial, maxLogDistanceFromTrunk,
|
2020-11-07 20:38:58 +01:00
|
|
|
maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, entireTreeLoot, requiredTools, requiredAxe));
|
2019-03-28 09:30:33 +01:00
|
|
|
}
|
|
|
|
|
2019-03-30 10:34:27 +01:00
|
|
|
// Load global plantable soil
|
2020-10-30 21:00:23 +01:00
|
|
|
for (String material : config.getStringList("global-plantable-soil"))
|
|
|
|
this.globalPlantableSoil.add(CompatibleMaterial.getMaterial(material));
|
2019-03-30 10:34:27 +01:00
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
// Load global log drops
|
|
|
|
ConfigurationSection logSection = config.getConfigurationSection("global-log-loot");
|
2019-03-30 10:34:27 +01:00
|
|
|
if (logSection != null)
|
|
|
|
for (String lootKey : logSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
this.globalLogLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logSection.getConfigurationSection(lootKey)));
|
2019-03-28 09:30:33 +01:00
|
|
|
|
|
|
|
// Load global leaf drops
|
|
|
|
ConfigurationSection leafSection = config.getConfigurationSection("global-leaf-loot");
|
2019-03-30 10:34:27 +01:00
|
|
|
if (leafSection != null)
|
|
|
|
for (String lootKey : leafSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
this.globalLeafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafSection.getConfigurationSection(lootKey)));
|
2019-03-28 09:30:33 +01:00
|
|
|
|
2019-05-01 12:01:34 +02:00
|
|
|
// Load global entire tree drops
|
2019-05-05 04:09:20 +02:00
|
|
|
ConfigurationSection entireTreeSection = config.getConfigurationSection("global-entire-tree-loot");
|
2019-05-01 12:01:34 +02:00
|
|
|
if (entireTreeSection != null)
|
|
|
|
for (String lootKey : entireTreeSection.getKeys(false))
|
2020-10-30 21:00:23 +01:00
|
|
|
this.globalEntireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, entireTreeSection.getConfigurationSection(lootKey)));
|
2019-05-01 12:01:34 +02:00
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
// Load global tools
|
2020-06-29 02:18:23 +02:00
|
|
|
for (String itemStackString : config.getStringList("global-required-tools")) {
|
2020-10-30 21:00:23 +01:00
|
|
|
ItemStack tool = CompatibleMaterial.getMaterial(itemStackString).getItem();
|
2020-06-29 02:18:23 +02:00
|
|
|
if (tool == null) continue;
|
|
|
|
this.globalRequiredTools.add(tool);
|
|
|
|
}
|
2020-11-07 20:38:58 +01:00
|
|
|
|
|
|
|
this.globalAxeRequired = config.getBoolean("global-required-axe", false);
|
|
|
|
|
|
|
|
// Load required axe
|
|
|
|
if (config.contains("required-axe"))
|
|
|
|
loadAxe(config);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadAxe(YamlConfiguration config) {
|
|
|
|
|
|
|
|
// Reset the axe loaded, but load the NBT anyway in case someone wanted to use another plugin to give it.
|
|
|
|
this.requiredAxeKey = config.getString("required-axe.nbt");
|
|
|
|
this.requiredAxe = null;
|
|
|
|
|
|
|
|
String typeString = config.getString("required-axe.type");
|
|
|
|
|
|
|
|
if (Strings.isNullOrEmpty(typeString)) {
|
|
|
|
plugin.getLogger().warning("Required-axe has to have a material set.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CompatibleMaterial material = CompatibleMaterial.getMaterial(typeString);
|
|
|
|
|
|
|
|
if (material == null) {
|
|
|
|
plugin.getLogger().warning("Material " + typeString + " is invalid.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack item = material.getItem();
|
|
|
|
|
|
|
|
// Add display name and lore
|
|
|
|
String displayName = TextUtils.formatText(config.getString("required-axe.name"));
|
|
|
|
List<String> lore = config.getStringList("required-axe.lore").stream()
|
|
|
|
.map(TextUtils::formatText)
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
ItemMeta meta = item.getItemMeta();
|
|
|
|
meta.setDisplayName(displayName);
|
|
|
|
meta.setLore(lore);
|
|
|
|
|
|
|
|
// Enchants
|
|
|
|
for (String enchantString : config.getStringList("required-axe.enchants")) {
|
|
|
|
String[] arr = enchantString.split(":");
|
|
|
|
int level = arr.length > 1 ? Math.max(1, parseInt(arr[1])) : 1;
|
|
|
|
|
|
|
|
// Enchantment#getKey is not present on versions below 1.13
|
|
|
|
Enchantment enchantment;
|
|
|
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
|
|
|
NamespacedKey key = NamespacedKey.minecraft(arr[0].trim().toLowerCase());
|
|
|
|
enchantment = Enchantment.getByKey(key);
|
|
|
|
|
|
|
|
// Try to fall back to #getByName() if someone uses the old names.
|
|
|
|
if (enchantment == null)
|
|
|
|
enchantment = Enchantment.getByName(arr[0].trim());
|
|
|
|
} else
|
|
|
|
enchantment = Enchantment.getByName(arr[0].trim());
|
|
|
|
|
|
|
|
if (enchantment == null) {
|
|
|
|
plugin.getLogger().warning("Enchantment " + arr[0].trim() + " is invalid.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta.addEnchant(enchantment, level, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
item.setItemMeta(meta);
|
2020-11-20 01:53:41 +01:00
|
|
|
|
|
|
|
// Apply NBT
|
2022-03-18 21:10:57 +01:00
|
|
|
NBTItem nbtItem = new NBTItem(item);
|
|
|
|
nbtItem.setBoolean(requiredAxeKey, true);
|
|
|
|
item = nbtItem.getItem();
|
2020-11-20 01:53:41 +01:00
|
|
|
|
2020-11-07 20:38:58 +01:00
|
|
|
this.requiredAxe = item;
|
|
|
|
}
|
|
|
|
|
|
|
|
private int parseInt(String str) {
|
|
|
|
try {
|
|
|
|
return Integer.parseInt(str.trim());
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ItemStack getRequiredAxe() {
|
|
|
|
return this.requiredAxe;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isGlobalAxeRequired() {
|
|
|
|
return globalAxeRequired;
|
2019-03-28 01:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void disable() {
|
|
|
|
this.treeDefinitions.clear();
|
2019-03-26 21:35:17 +01:00
|
|
|
}
|
|
|
|
|
2019-03-28 18:38:37 +01:00
|
|
|
/**
|
2019-03-28 21:34:17 +01:00
|
|
|
* Gets a Set of possible TreeDefinitions that match the given Block
|
2019-03-28 18:38:37 +01:00
|
|
|
*
|
2019-03-28 21:34:17 +01:00
|
|
|
* @param block The Block to check
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-28 21:34:17 +01:00
|
|
|
* @return A Set of TreeDefinitions for the given Block
|
2019-03-28 18:38:37 +01:00
|
|
|
*/
|
2019-03-28 21:34:17 +01:00
|
|
|
public Set<TreeDefinition> getTreeDefinitionsForLog(Block block) {
|
|
|
|
return this.narrowTreeDefinition(this.treeDefinitions, block, TreeBlockType.LOG);
|
2019-03-28 18:38:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-03-28 21:34:17 +01:00
|
|
|
* Narrows a Set of TreeDefinitions down to ones matching the given Block and TreeBlockType
|
2019-03-28 18:38:37 +01:00
|
|
|
*
|
|
|
|
* @param possibleTreeDefinitions The possible TreeDefinitions
|
2020-06-29 02:18:23 +02:00
|
|
|
* @param block The Block to narrow to
|
|
|
|
* @param treeBlockType The TreeBlockType of the given Block
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-28 18:38:37 +01:00
|
|
|
* @return A Set of TreeDefinitions narrowed down
|
|
|
|
*/
|
2019-03-28 21:34:17 +01:00
|
|
|
public Set<TreeDefinition> narrowTreeDefinition(Set<TreeDefinition> possibleTreeDefinitions, Block block, TreeBlockType treeBlockType) {
|
2019-03-28 18:38:37 +01:00
|
|
|
Set<TreeDefinition> matchingTreeDefinitions = new HashSet<>();
|
|
|
|
switch (treeBlockType) {
|
|
|
|
case LOG:
|
2019-03-28 21:34:17 +01:00
|
|
|
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
2020-10-30 21:00:23 +01:00
|
|
|
for (CompatibleMaterial material : treeDefinition.getLogMaterial()) {
|
|
|
|
if (material.equals(CompatibleMaterial.getMaterial(block))) {
|
2019-03-28 18:38:37 +01:00
|
|
|
matchingTreeDefinitions.add(treeDefinition);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LEAF:
|
2019-03-28 21:34:17 +01:00
|
|
|
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
2020-10-30 21:00:23 +01:00
|
|
|
for (CompatibleMaterial material : treeDefinition.getLeafMaterial()) {
|
|
|
|
if (material.equals(CompatibleMaterial.getMaterial(block))) {
|
2019-03-28 18:38:37 +01:00
|
|
|
matchingTreeDefinitions.add(treeDefinition);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return matchingTreeDefinitions;
|
|
|
|
}
|
|
|
|
|
2019-03-28 21:34:17 +01:00
|
|
|
/**
|
|
|
|
* Checks if a given tool is valid for any tree definitions, also takes into account global tools
|
|
|
|
*
|
|
|
|
* @param tool The tool to check
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-28 21:34:17 +01:00
|
|
|
* @return True if the tool is allowed for toppling any trees
|
|
|
|
*/
|
|
|
|
public boolean isToolValidForAnyTreeDefinition(ItemStack tool) {
|
2019-03-29 23:52:17 +01:00
|
|
|
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
|
|
|
|
return true;
|
2020-11-07 20:38:58 +01:00
|
|
|
|
|
|
|
for (TreeDefinition treeDefinition : this.treeDefinitions) {
|
|
|
|
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
|
2022-03-18 21:10:57 +01:00
|
|
|
if (new NBTItem(tool).hasKey(requiredAxeKey))
|
2020-11-07 20:38:58 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 21:34:17 +01:00
|
|
|
for (TreeDefinition treeDefinition : this.treeDefinitions)
|
|
|
|
for (ItemStack requiredTool : treeDefinition.getRequiredTools())
|
2019-03-30 10:34:27 +01:00
|
|
|
if (requiredTool.getType().equals(tool.getType()))
|
2019-03-28 21:34:17 +01:00
|
|
|
return true;
|
2020-11-07 20:38:58 +01:00
|
|
|
|
2019-03-28 21:34:17 +01:00
|
|
|
for (ItemStack requiredTool : this.globalRequiredTools)
|
2019-03-30 10:34:27 +01:00
|
|
|
if (requiredTool.getType().equals(tool.getType()))
|
2019-03-28 21:34:17 +01:00
|
|
|
return true;
|
2020-11-07 20:38:58 +01:00
|
|
|
|
2019-03-28 21:34:17 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
/**
|
|
|
|
* Checks if a given tool is valid for a given tree definition, also takes into account global tools
|
|
|
|
*
|
|
|
|
* @param treeDefinition The TreeDefinition to use
|
2020-06-29 02:18:23 +02:00
|
|
|
* @param tool The tool to check
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-28 09:30:33 +01:00
|
|
|
* @return True if the tool is allowed for toppling the given TreeDefinition
|
|
|
|
*/
|
|
|
|
public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) {
|
2020-11-07 20:38:58 +01:00
|
|
|
|
2019-03-29 23:52:17 +01:00
|
|
|
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
|
|
|
|
return true;
|
2020-11-07 20:38:58 +01:00
|
|
|
|
|
|
|
// If the tree definition requires the custom axe, don't allow any other checks to pass.
|
|
|
|
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
|
2022-03-18 21:10:57 +01:00
|
|
|
return new NBTItem(tool).hasKey(requiredAxeKey);
|
2020-11-07 20:38:58 +01:00
|
|
|
}
|
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
for (ItemStack requiredTool : treeDefinition.getRequiredTools())
|
2019-03-30 10:34:27 +01:00
|
|
|
if (requiredTool.getType().equals(tool.getType()))
|
2019-03-28 09:30:33 +01:00
|
|
|
return true;
|
2020-11-07 20:38:58 +01:00
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
for (ItemStack requiredTool : this.globalRequiredTools)
|
2019-03-30 10:34:27 +01:00
|
|
|
if (requiredTool.getType().equals(tool.getType()))
|
2019-03-28 09:30:33 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-05-01 09:33:21 +02:00
|
|
|
* Tries to spawn loot for a given TreeBlock with the given TreeDefinition for a given Player
|
2019-03-28 09:30:33 +01:00
|
|
|
*
|
2020-06-29 02:18:23 +02:00
|
|
|
* @param treeDefinition The TreeDefinition to use
|
|
|
|
* @param treeBlock The TreeBlock to drop for
|
|
|
|
* @param player The Player to drop for
|
2019-05-01 09:33:21 +02:00
|
|
|
* @param isForEntireTree If the loot is for the entire tree
|
2019-03-28 09:30:33 +01:00
|
|
|
*/
|
2019-05-01 09:33:21 +02:00
|
|
|
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player, boolean hasSilkTouch, boolean isForEntireTree) {
|
2019-03-28 09:30:33 +01:00
|
|
|
boolean addToInventory = ConfigurationManager.Setting.ADD_ITEMS_TO_INVENTORY.getBoolean();
|
|
|
|
boolean hasBonusChance = player.hasPermission("ultimatetimber.bonusloot");
|
2019-04-29 02:58:38 +02:00
|
|
|
List<ItemStack> lootedItems = new ArrayList<>();
|
|
|
|
List<String> lootedCommands = new ArrayList<>();
|
2019-03-28 09:30:33 +01:00
|
|
|
|
|
|
|
// Get the loot that we should try to drop
|
2019-04-29 02:58:38 +02:00
|
|
|
List<TreeLoot> toTry = new ArrayList<>();
|
2019-05-01 09:33:21 +02:00
|
|
|
if (isForEntireTree) {
|
|
|
|
toTry.addAll(treeDefinition.getEntireTreeLoot());
|
2019-05-01 12:01:34 +02:00
|
|
|
toTry.addAll(this.globalEntireTreeLoot);
|
2019-03-31 21:48:03 +02:00
|
|
|
} else {
|
2019-05-01 12:01:34 +02:00
|
|
|
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH.getBoolean() && hasSilkTouch) {
|
2020-12-23 16:35:02 +01:00
|
|
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
2022-03-18 21:09:52 +01:00
|
|
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player))
|
2020-10-30 21:00:23 +01:00
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
2019-05-01 09:33:21 +02:00
|
|
|
} else {
|
|
|
|
switch (treeBlock.getTreeBlockType()) {
|
|
|
|
case LOG:
|
|
|
|
toTry.addAll(treeDefinition.getLogLoot());
|
|
|
|
toTry.addAll(this.globalLogLoot);
|
|
|
|
if (treeDefinition.shouldDropOriginalLog()) {
|
2020-12-23 16:35:02 +01:00
|
|
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
2022-03-18 21:09:52 +01:00
|
|
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player))
|
2020-10-30 21:00:23 +01:00
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
2019-05-01 09:33:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LEAF:
|
|
|
|
toTry.addAll(treeDefinition.getLeafLoot());
|
|
|
|
toTry.addAll(this.globalLeafLoot);
|
|
|
|
if (treeDefinition.shouldDropOriginalLeaf()) {
|
2020-12-23 16:35:02 +01:00
|
|
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
2022-03-18 21:09:52 +01:00
|
|
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player))
|
2020-10-30 21:00:23 +01:00
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
|
|
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
2019-05-01 09:33:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-03-31 21:48:03 +02:00
|
|
|
}
|
2019-03-28 09:30:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Roll the dice
|
2019-03-29 23:52:17 +01:00
|
|
|
double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble();
|
2019-03-28 09:30:33 +01:00
|
|
|
for (TreeLoot treeLoot : toTry) {
|
2020-10-30 21:00:23 +01:00
|
|
|
if (treeLoot == null) continue;
|
2019-03-30 10:34:27 +01:00
|
|
|
double chance = hasBonusChance ? treeLoot.getChance() * bonusLootMultiplier : treeLoot.getChance();
|
2019-03-29 23:52:17 +01:00
|
|
|
if (this.random.nextDouble() > chance / 100)
|
2019-03-28 09:30:33 +01:00
|
|
|
continue;
|
2019-04-28 04:04:45 +02:00
|
|
|
|
|
|
|
if (treeLoot.hasItem()) {
|
2020-12-23 16:35:02 +01:00
|
|
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
2022-03-18 21:09:52 +01:00
|
|
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player))
|
2019-04-28 04:04:45 +02:00
|
|
|
lootedItems.add(treeLoot.getItem());
|
2019-03-28 09:30:33 +01:00
|
|
|
lootedItems.add(treeLoot.getItem());
|
2019-04-28 04:04:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (treeLoot.hasCommand()) {
|
2020-12-23 16:35:02 +01:00
|
|
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
2022-03-18 21:09:52 +01:00
|
|
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player))
|
2019-04-28 04:04:45 +02:00
|
|
|
lootedCommands.add(treeLoot.getCommand());
|
2019-03-28 09:30:33 +01:00
|
|
|
lootedCommands.add(treeLoot.getCommand());
|
2019-04-28 04:04:45 +02:00
|
|
|
}
|
2019-03-28 09:30:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add to inventory or drop on ground
|
2019-04-15 22:33:31 +02:00
|
|
|
if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) {
|
2019-04-29 02:58:38 +02:00
|
|
|
List<ItemStack> extraItems = new ArrayList<>();
|
2019-03-28 09:30:33 +01:00
|
|
|
for (ItemStack lootedItem : lootedItems)
|
2019-03-31 09:50:42 +02:00
|
|
|
extraItems.addAll(player.getInventory().addItem(lootedItem).values());
|
2019-04-12 03:19:10 +02:00
|
|
|
Location location = player.getLocation().clone().subtract(0.5, 0, 0.5);
|
2019-03-31 09:50:42 +02:00
|
|
|
for (ItemStack extraItem : extraItems)
|
|
|
|
location.getWorld().dropItemNaturally(location, extraItem);
|
2019-03-28 09:30:33 +01:00
|
|
|
} else {
|
|
|
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
|
|
for (ItemStack lootedItem : lootedItems)
|
|
|
|
location.getWorld().dropItemNaturally(location, lootedItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run looted commands
|
|
|
|
for (String lootedCommand : lootedCommands)
|
2019-03-29 23:52:17 +01:00
|
|
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
|
2019-04-05 08:05:43 +02:00
|
|
|
lootedCommand.replace("%player%", player.getName())
|
2020-06-29 02:18:23 +02:00
|
|
|
.replace("%type%", treeDefinition.getKey())
|
|
|
|
.replace("%xPos%", treeBlock.getLocation().getBlockX() + "")
|
|
|
|
.replace("%yPos%", treeBlock.getLocation().getBlockY() + "")
|
|
|
|
.replace("%zPos%", treeBlock.getLocation().getBlockZ() + ""));
|
2019-03-28 09:30:33 +01:00
|
|
|
}
|
|
|
|
|
2019-03-30 10:34:27 +01:00
|
|
|
/**
|
|
|
|
* Gets all possible plantable soil blocks for the given tree definition
|
|
|
|
*
|
|
|
|
* @param treeDefinition The TreeDefinition
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-30 10:34:27 +01:00
|
|
|
* @return A Set of IBlockData of plantable soil
|
|
|
|
*/
|
2020-10-30 21:00:23 +01:00
|
|
|
public Set<CompatibleMaterial> getPlantableSoilMaterial(TreeDefinition treeDefinition) {
|
|
|
|
Set<CompatibleMaterial> plantableSoilBlockData = new HashSet<>();
|
|
|
|
plantableSoilBlockData.addAll(treeDefinition.getPlantableSoilMaterial());
|
2019-03-30 10:34:27 +01:00
|
|
|
plantableSoilBlockData.addAll(this.globalPlantableSoil);
|
|
|
|
return plantableSoilBlockData;
|
|
|
|
}
|
|
|
|
|
2019-03-28 09:30:33 +01:00
|
|
|
/**
|
|
|
|
* Gets a TreeLoot entry from a ConfigurationSection
|
|
|
|
*
|
2020-06-29 02:18:23 +02:00
|
|
|
* @param treeBlockType The TreeBlockType to use
|
2019-03-28 09:30:33 +01:00
|
|
|
* @param configurationSection The ConfigurationSection
|
2022-03-18 21:09:52 +01:00
|
|
|
*
|
2019-03-28 09:30:33 +01:00
|
|
|
* @return A TreeLoot entry from the section
|
|
|
|
*/
|
2020-10-30 21:00:23 +01:00
|
|
|
private TreeLoot getTreeLootEntry(TreeBlockType treeBlockType, ConfigurationSection configurationSection) {
|
2019-03-30 10:34:27 +01:00
|
|
|
String material = configurationSection.getString("material");
|
2020-10-30 21:00:23 +01:00
|
|
|
CompatibleMaterial compatibleMaterial = material == null ? null : CompatibleMaterial.getMaterial(material);
|
|
|
|
|
|
|
|
ItemStack item = compatibleMaterial == null ? null : compatibleMaterial.getItem();
|
2019-03-28 09:30:33 +01:00
|
|
|
String command = configurationSection.getString("command");
|
|
|
|
double chance = configurationSection.getDouble("chance");
|
|
|
|
return new TreeLoot(treeBlockType, item, command, chance);
|
|
|
|
}
|
2019-03-26 21:35:17 +01:00
|
|
|
}
|