Does it build?

This commit is contained in:
Esophose 2019-03-30 00:46:13 -06:00
parent d8bd19a08a
commit 5d83a2bd27
34 changed files with 587 additions and 1161 deletions

6
.gitignore vendored
View File

@ -1,9 +1,7 @@
.idea/
UltimateTimber\.iml
*.iml
target/
.settings/
bin/
.classpath
.project
src/main/main\.iml
.project

View File

@ -6,14 +6,12 @@
<parent>
<groupId>com.songoda.ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<artifactId>UltimateTimber-Parent</artifactId>
<version>maven-version-number</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>UltimateTimber-CurrentAdapter</artifactId>
<packaging>jar</packaging>
<version>maven-version-number</version>
<dependencies>
<!--Spigot API-->
@ -45,4 +43,9 @@
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>${project.artifactId}</finalName>
</build>
</project>

View File

@ -4,13 +4,22 @@ import com.songoda.ultimatetimber.adapter.IBlockData;
import com.songoda.ultimatetimber.adapter.VersionAdapter;
import com.songoda.ultimatetimber.adapter.VersionAdapterType;
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlock;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlockSet;
import com.songoda.ultimatetimber.utils.Methods;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Collection;
import java.util.HashSet;
public class CurrentAdapter implements VersionAdapter {
@ -21,27 +30,52 @@ public class CurrentAdapter implements VersionAdapter {
@Override
public IBlockData parseBlockDataFromString(String blockDataString) {
return null;
return new CurrentBlockData(Material.matchMaterial(blockDataString));
}
@Override
public ItemStack parseItemStackFromString(String itemStackString) {
return null;
return new ItemStack(Material.matchMaterial(itemStackString));
}
@Override
public Collection<ItemStack> getBlockDrops(TreeBlock treeBlock) {
return null;
public Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock) {
if (treeBlock.getBlock() instanceof Block) {
Block block = (Block)treeBlock.getBlock();
return block.getDrops(); // TODO: Do this properly
}
return new HashSet<>();
}
@Override
public void applyToolDurability(ItemStack tool, int damage) {
public void applyToolDurability(Player player, int damage) {
ItemStack tool = this.getItemInHand(player);
if (!tool.hasItemMeta() || !(tool.getItemMeta() instanceof Damageable))
return;
int unbreakingLevel = tool.getEnchantmentLevel(Enchantment.DURABILITY);
Damageable damageable = (Damageable)tool.getItemMeta();
int actualDamage = 0;
for (int i = 0; i < damage; i++)
if (Methods.checkUnbreakingChance(unbreakingLevel))
actualDamage++;
damageable.setDamage(damageable.getDamage() + actualDamage);
tool.setItemMeta((ItemMeta) damageable);
}
@Override
public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) {
return false;
if (!tool.hasItemMeta() || !(tool.getItemMeta() instanceof Damageable))
return false;
Damageable damageable = (Damageable)tool.getItemMeta();
int durabilityRemaining = tool.getType().getMaxDurability() - damageable.getDamage();
return durabilityRemaining > requiredAmount;
}
@Override
@ -49,6 +83,11 @@ public class CurrentAdapter implements VersionAdapter {
return player.getInventory().getItemInMainHand();
}
@Override
public void removeItemInHand(Player player) {
player.getInventory().setItemInMainHand(null);
}
@Override
public void playFallingParticles(TreeBlockSet<Block> treeBlocks) {
@ -61,12 +100,14 @@ public class CurrentAdapter implements VersionAdapter {
@Override
public void playFallingSound(TreeBlockSet<Block> treeBlocks) {
Location location = treeBlocks.getInitialLogBlock().getLocation();
location.getWorld().playSound(location, Sound.BLOCK_CHEST_OPEN, 3F, 0.1F);
}
@Override
public void playLandingSound(FallingTreeBlock treeBlock) {
Location location = treeBlock.getLocation();
location.getWorld().playSound(location, Sound.BLOCK_WOOD_FALL, 3F, 0.1F);
}
}

View File

@ -6,14 +6,12 @@
<parent>
<groupId>com.songoda.ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<artifactId>UltimateTimber-Parent</artifactId>
<version>maven-version-number</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>UltimateTimber-LegacyAdapter</artifactId>
<packaging>jar</packaging>
<version>maven-version-number</version>
<dependencies>
<!--Spigot API-->
@ -45,4 +43,9 @@
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>${project.artifactId}</finalName>
</build>
</project>

View File

@ -4,8 +4,11 @@ import com.songoda.ultimatetimber.adapter.IBlockData;
import com.songoda.ultimatetimber.adapter.VersionAdapter;
import com.songoda.ultimatetimber.adapter.VersionAdapterType;
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlock;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlockSet;
import com.songoda.ultimatetimber.utils.NMSUtil;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -31,12 +34,12 @@ public class LegacyAdapter implements VersionAdapter {
}
@Override
public Collection<ItemStack> getBlockDrops(TreeBlock treeBlock) {
public Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock) {
return null;
}
@Override
public void applyToolDurability(ItemStack tool, int damage) {
public void applyToolDurability(Player player, int damage) {
}
@ -50,6 +53,11 @@ public class LegacyAdapter implements VersionAdapter {
return player.getItemInHand();
}
@Override
public void removeItemInHand(Player player) {
player.setItemInHand(null);
}
@Override
public void playFallingParticles(TreeBlockSet<Block> treeBlocks) {
@ -62,12 +70,22 @@ public class LegacyAdapter implements VersionAdapter {
@Override
public void playFallingSound(TreeBlockSet<Block> treeBlocks) {
Location location = treeBlocks.getInitialLogBlock().getLocation();
if (NMSUtil.getVersionNumber() > 8) {
location.getWorld().playSound(location, Sound.BLOCK_CHEST_OPEN, 3F, 0.1F);
} else {
location.getWorld().playSound(location, Sound.valueOf("CHEST_OPEN"), 3F, 0.1F);
}
}
@Override
public void playLandingSound(FallingTreeBlock treeBlock) {
Location location = treeBlock.getLocation();
if (NMSUtil.getVersionNumber() > 8) {
location.getWorld().playSound(location, Sound.BLOCK_WOOD_FALL, 3F, 0.1F);
} else {
location.getWorld().playSound(location, Sound.valueOf("DIG_WOOD"), 3F, 0.1F);
}
}
}

View File

@ -6,14 +6,12 @@
<parent>
<groupId>com.songoda.ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<artifactId>UltimateTimber-Parent</artifactId>
<version>maven-version-number</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>UltimateTimber-Core</artifactId>
<packaging>jar</packaging>
<version>maven-version-number</version>
<dependencies>
<!--Spigot API-->
@ -24,4 +22,9 @@
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>${project.artifactId}</finalName>
</build>
</project>

View File

@ -1,7 +1,7 @@
package com.songoda.ultimatetimber.adapter;
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlock;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlockSet;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -40,15 +40,15 @@ public interface VersionAdapter {
* @param treeBlock The tree block
* @return A Set of ItemStacks that should be dropped
*/
Collection<ItemStack> getBlockDrops(TreeBlock treeBlock);
Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock);
/**
* Applies damage to a tool
*
* @param tool The tool to apply damage to
* @param player The Player who's tool to apply damage to
* @param damage The amount of damage to apply
*/
void applyToolDurability(ItemStack tool, int damage);
void applyToolDurability(Player player, int damage);
/**
* Checks if a given tool has enough durability remaining
@ -67,6 +67,13 @@ public interface VersionAdapter {
*/
ItemStack getItemInHand(Player player);
/**
* Removes the item in the player's main hand
*
* @param player The Player to remove the item from
*/
void removeItemInHand(Player player);
/**
* Plays particles to indicate a tree has started falling
*/

View File

@ -2,14 +2,31 @@ package com.songoda.ultimatetimber.utils;
import org.bukkit.ChatColor;
import java.util.Random;
public class Methods {
private static Random random = new Random();
/**
* Formats a given string replacing colors
*
* @param text The string
* @return The formatted string
*/
public static String formatText(String text) {
if (text == null || text.equals(""))
return "";
return formatText(text, false);
}
/**
* Formats a given string replacing colors and optionally capitalizing the first word
*
* @param text The string
* @param cap If the first word should be capitalized
* @return The formatted string
*/
private static String formatText(String text, boolean cap) {
if (text == null || text.equals(""))
return "";
@ -18,4 +35,14 @@ public class Methods {
return ChatColor.translateAlternateColorCodes('&', text);
}
/**
* Check if durbility should be applied based on the unbreaking enchantment
*
* @param level The level of the unbreaking enchantment
* @return True if durability should be applied, otherwise false
*/
public static boolean checkUnbreakingChance(int level) {
return ((double) 1 / (level + 1)) > random.nextDouble();
}
}

View File

@ -12,7 +12,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot:1.13.2" level="project" />
<orderEntry type="module" module-name="UltimateTimber-Core" />
<orderEntry type="module" module-name="Current" />
<orderEntry type="module" module-name="Legacy" />
<orderEntry type="module" module-name="UltimateTimber-CurrentAdapter" />
<orderEntry type="module" module-name="UltimateTimber-LegacyAdapter" />
</component>
</module>

View File

@ -6,14 +6,12 @@
<parent>
<groupId>com.songoda.ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<artifactId>UltimateTimber-Parent</artifactId>
<version>maven-version-number</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>UltimateTimber-Plugin</artifactId>
<packaging>jar</packaging>
<version>maven-version-number</version>
<dependencies>
<!--Spigot API-->
@ -47,29 +45,22 @@
</dependencies>
<build>
<finalName>${parent.artifactId}-${project.version}</finalName>
<defaultGoal>clean install</defaultGoal>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>

View File

@ -1,29 +1,44 @@
package com.songoda.ultimatetimber.animation;
import com.songoda.ultimatetimber.UltimateTimber;
import com.songoda.ultimatetimber.manager.ConfigurationManager;
import com.songoda.ultimatetimber.manager.SaplingManager;
import com.songoda.ultimatetimber.tree.DetectedTree;
import com.songoda.ultimatetimber.tree.TreeBlockSet;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
public abstract class TreeAnimation {
protected final TreeAnimationType treeAnimationType;
protected final TreeBlockSet<Block> treeBlocks;
protected final TreeDefinition treeDefinition;
protected final DetectedTree detectedTree;
protected final Player player;
TreeAnimation(TreeAnimationType treeAnimationType, TreeBlockSet<Block> treeBlocks, TreeDefinition treeDefinition) {
TreeAnimation(TreeAnimationType treeAnimationType, DetectedTree detectedTree, Player player) {
this.treeAnimationType = treeAnimationType;
this.treeBlocks = treeBlocks;
this.treeDefinition = treeDefinition;
this.detectedTree = detectedTree;
this.player = player;
}
/**
* Plays this tree topple animation
*
* @param detectedTree The DetectedTree
* @param player The Player who toppled the tree
* @param whenFinished The runnable to run when the animation is done
*/
abstract void playAnimation(DetectedTree detectedTree, Player player);
public abstract void playAnimation(Runnable whenFinished);
/**
* Replaces a given block with a new one
*
* @param treeDefinition The tree definition for the replacement
* @param block The block to replace
*/
protected void replaceBlock(TreeDefinition treeDefinition, Block block) {
block.setType(Material.AIR);
UltimateTimber.getInstance().getSaplingManager().replantSapling(treeDefinition, block.getLocation());
}
}

View File

@ -8,12 +8,12 @@ import org.bukkit.entity.Player;
public class TreeAnimationChaos extends TreeAnimation {
public TreeAnimationChaos(TreeBlockSet<Block> treeBlocks, TreeDefinition treeDefinition) {
super(TreeAnimationType.CHAOS, treeBlocks, treeDefinition);
public TreeAnimationChaos(DetectedTree detectedTree, Player player) {
super(TreeAnimationType.CHAOS, detectedTree, player);
}
@Override
public void playAnimation(DetectedTree detectedTree, Player player) {
public void playAnimation(Runnable whenFinished) {
}

View File

@ -8,12 +8,12 @@ import org.bukkit.entity.Player;
public class TreeAnimationDisintegrate extends TreeAnimation {
public TreeAnimationDisintegrate(TreeBlockSet<Block> treeBlocks, TreeDefinition treeDefinition) {
super(TreeAnimationType.DISINTIGRATE, treeBlocks, treeDefinition);
public TreeAnimationDisintegrate(DetectedTree detectedTree, Player player) {
super(TreeAnimationType.DISINTIGRATE, detectedTree, player);
}
@Override
public void playAnimation(DetectedTree detectedTree, Player player) {
public void playAnimation(Runnable whenFinished) {
}

View File

@ -8,12 +8,12 @@ import org.bukkit.entity.Player;
public class TreeAnimationFancy extends TreeAnimation {
public TreeAnimationFancy(TreeBlockSet<Block> treeBlocks, TreeDefinition treeDefinition) {
super(TreeAnimationType.FANCY, treeBlocks, treeDefinition);
public TreeAnimationFancy(DetectedTree detectedTree, Player player) {
super(TreeAnimationType.FANCY, detectedTree, player);
}
@Override
public void playAnimation(DetectedTree detectedTree, Player player) {
public void playAnimation(Runnable whenFinished) {
}

View File

@ -1,6 +1,7 @@
package com.songoda.ultimatetimber.animation;
import com.songoda.ultimatetimber.tree.DetectedTree;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeBlockSet;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.block.Block;
@ -8,13 +9,15 @@ import org.bukkit.entity.Player;
public class TreeAnimationNone extends TreeAnimation {
public TreeAnimationNone(TreeBlockSet<Block> treeBlocks, TreeDefinition treeDefinition) {
super(TreeAnimationType.NONE, treeBlocks, treeDefinition);
public TreeAnimationNone(DetectedTree detectedTree, Player player) {
super(TreeAnimationType.NONE, detectedTree, player);
}
@Override
public void playAnimation(DetectedTree detectedTree, Player player) {
public void playAnimation(Runnable whenFinished) {
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
}
}
}

View File

@ -1,7 +1,7 @@
package com.songoda.ultimatetimber.manager;
import com.songoda.ultimatetimber.UltimateTimber;
import utils.Methods;
import com.songoda.ultimatetimber.utils.Methods;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;

View File

@ -33,6 +33,7 @@ public class ConfigurationManager extends Manager {
USE_CUSTOM_SOUNDS,
USE_CUSTOM_PARTICLES,
BONUS_LOOT_MULTIPLIER,
TREE_ANIMATION_TYPE,
SCATTER_TREE_BLOCKS_ON_GROUND,
MIX_ALL_TREE_TYPES;

View File

@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import java.util.HashSet;
import java.util.Random;
@ -44,7 +45,7 @@ public class SaplingManager extends Manager {
if (!ConfigurationManager.Setting.REPLANT_SAPLINGS.getBoolean())
return;
this.internalReplant(treeDefinition, location);
Bukkit.getScheduler().scheduleSyncDelayedTask(this.ultimateTimber, () -> this.internalReplant(treeDefinition, location), 1L);
}
/**
@ -62,7 +63,7 @@ public class SaplingManager extends Manager {
if (this.random.nextDouble() > chance / 100)
return;
this.internalReplant(treeDefinition, location);
Bukkit.getScheduler().scheduleSyncDelayedTask(this.ultimateTimber, () -> this.internalReplant(treeDefinition, location), 1L);
}
/**
@ -76,6 +77,18 @@ public class SaplingManager extends Manager {
if (!block.getType().equals(Material.AIR))
return;
Block blockBelow = block.getRelative(BlockFace.DOWN);
boolean isValidSoil = false;
for (IBlockData soilBlockData : treeDefinition.getPlantableSoilBlockData()) {
if (soilBlockData.isSimilar(blockBelow)) {
isValidSoil = true;
break;
}
}
if (!isValidSoil)
return;
IBlockData saplingBlockData = treeDefinition.getSaplingBlockData();
saplingBlockData.setBlock(location.getBlock());

View File

@ -1,6 +1,7 @@
package com.songoda.ultimatetimber.manager;
import com.songoda.ultimatetimber.UltimateTimber;
import com.songoda.ultimatetimber.animation.*;
import com.songoda.ultimatetimber.tree.DetectedTree;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.Bukkit;
@ -10,21 +11,27 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import java.util.HashSet;
import java.util.Set;
public class TreeAnimationManager extends Manager implements Listener {
private Set<TreeAnimation> activeAnimations;
public TreeAnimationManager(UltimateTimber ultimateTimber) {
super(ultimateTimber);
this.activeAnimations = new HashSet<>();
Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
}
@Override
public void reload() {
this.activeAnimations.clear();
}
@Override
public void disable() {
this.activeAnimations.clear();
}
/**
@ -34,7 +41,28 @@ public class TreeAnimationManager extends Manager implements Listener {
* @param player The Player who toppled the tree
*/
public void runAnimation(DetectedTree detectedTree, Player player) {
TreeDefinition treeDefinition = detectedTree.getTreeDefinition();
switch (ConfigurationManager.Setting.TREE_ANIMATION_TYPE.getString()) {
case "FANCY":
this.registerTreeAnimation(new TreeAnimationFancy(detectedTree, player));
break;
case "DISINTEGRATE":
this.registerTreeAnimation(new TreeAnimationDisintegrate(detectedTree, player));
break;
case "CHAOS":
this.registerTreeAnimation(new TreeAnimationChaos(detectedTree, player));
break;
case "NONE":
this.registerTreeAnimation(new TreeAnimationNone(detectedTree, player));
break;
}
}
/**
* Registers and runs a tree animation
*/
private void registerTreeAnimation(TreeAnimation treeAnimation) {
this.activeAnimations.add(treeAnimation);
treeAnimation.playAnimation(() -> this.activeAnimations.remove(treeAnimation));
}
@EventHandler(priority = EventPriority.HIGH)

View File

@ -207,8 +207,9 @@ public class TreeDefinitionManager extends Manager {
* @param treeBlock The TreeBlock to drop for
* @param player The Player to drop for
*/
@SuppressWarnings("unchecked")
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player) {
VersionAdapter versionAdapter = this.ultimateTimber.getVersionAdapter();
boolean addToInventory = ConfigurationManager.Setting.ADD_ITEMS_TO_INVENTORY.getBoolean();
ItemStack itemInHand = this.ultimateTimber.getVersionAdapter().getItemInHand(player);
boolean hasSilkTouch = itemInHand != null && itemInHand.hasItemMeta() && itemInHand.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);
@ -223,13 +224,13 @@ public class TreeDefinitionManager extends Manager {
toTry.addAll(treeDefinition.getLogLoot());
toTry.addAll(this.globalLogLoot);
if (treeDefinition.shouldDropOriginalLog() || hasSilkTouch)
lootedItems.addAll(treeBlock.getDrops());
lootedItems.addAll(versionAdapter.getBlockDrops(treeBlock));
break;
case LEAF:
toTry.addAll(treeDefinition.getLeafLoot());
toTry.addAll(this.globalLeafLoot);
if (treeDefinition.shouldDropOriginalLeaf() || hasSilkTouch)
lootedItems.addAll(treeBlock.getDrops());
lootedItems.addAll(versionAdapter.getBlockDrops(treeBlock));
break;
}

View File

@ -89,7 +89,7 @@ public class TreeFallManager extends Manager implements Listener {
event.setCancelled(true);
if (!player.getGameMode().equals(GameMode.CREATIVE)) {
versionAdapter.applyToolDurability(tool, toolDamage);
versionAdapter.applyToolDurability(player, toolDamage);
hookManager.applyHooks(player, detectedTree.getDetectedTreeBlocks());
}

View File

@ -1,85 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.HashSet;
import java.util.Random;
public class AxeDurability {
private static Random random = new Random();
/**
* Applies damage to the axe the player is holding based on logs they broke
*
* @param blocks The blocks that are part of the tree
* @param player The player
*/
public static void adjustAxeDamage(HashSet<Block> blocks, Player player) {
if (player.getGameMode().equals(GameMode.CREATIVE))
return;
ItemStack item = player.getInventory().getItemInMainHand();
Material itemType = item.getType();
if (!(itemType.equals(Material.DIAMOND_AXE) ||
itemType.equals(Material.GOLDEN_AXE) ||
itemType.equals(Material.IRON_AXE) ||
itemType.equals(Material.STONE_AXE) ||
itemType.equals(Material.WOODEN_AXE))) return;
int unbreakingLevel = item.getEnchantmentLevel(Enchantment.DURABILITY);
ItemMeta itemMeta = item.getItemMeta();
Damageable damageableMeta = (Damageable) itemMeta;
for (Block block : blocks) {
Material material = WoodToLogConverter.convert(block.getType());
if (isMaterialDurable(material) && checkUnbreakingChance(unbreakingLevel))
damageableMeta.setDamage(damageableMeta.getDamage() + 1);
}
item.setItemMeta((ItemMeta) damageableMeta);
if (damageableMeta.getDamage() >= item.getType().getMaxDurability())
player.getInventory().setItemInMainHand(new ItemStack(Material.AIR));
}
/**
* Checks is a material should apply durability
*
* @param material The material to check
* @return If durability should be applied
*/
private static boolean isMaterialDurable(Material material) {
return material.equals(Material.ACACIA_LOG) ||
material.equals(Material.BIRCH_LOG) ||
material.equals(Material.DARK_OAK_LOG) ||
material.equals(Material.JUNGLE_LOG) ||
material.equals(Material.OAK_LOG) ||
material.equals(Material.SPRUCE_LOG) ||
material.equals(Material.STRIPPED_ACACIA_LOG) ||
material.equals(Material.STRIPPED_BIRCH_LOG) ||
material.equals(Material.STRIPPED_DARK_OAK_LOG) ||
material.equals(Material.STRIPPED_JUNGLE_LOG) ||
material.equals(Material.STRIPPED_OAK_LOG) ||
material.equals(Material.STRIPPED_SPRUCE_LOG);
}
/**
* Check if durbility should be applied based on the unbreaking enchantment
*
* @param level The level of the unbreaking enchantment
* @return True if durability should be applied, otherwise false
*/
private static boolean checkUnbreakingChance(int level) {
return ((double) 1 / (level + 1)) > random.nextDouble();
}
}

View File

@ -1,68 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class CustomLoot {
/*
This is a very simple config parser for items
Each item is a new line in a list
Each line includes the keywords "Material:" and "Chance:" seperated by a ","
The chance is a percentage
It throws specific errors on startup when an invalid configuration is detected
*/
private static HashMap<ItemStack, Double> itemMap = new HashMap<>();
static void doCustomItemDrop(Location location) {
for (ItemStack itemStack : itemMap.keySet())
if ((ThreadLocalRandom.current().nextDouble()) < itemMap.get(itemStack) / 100)
location.getWorld().dropItem(location, itemStack);
}
public static void initializeCustomItems() {
itemMap.clear();
FileConfiguration fileConfiguration = UltimateTimber.getInstance().getConfig();
List<String> arrayList = fileConfiguration.getStringList(DefaultConfig.CUSTOM_LOOT_LIST);
for (String string : arrayList) {
Material material = null;
double chance = 0;
String materialString = string.split(",")[0].replace("Material:", "");
try {
material = Material.valueOf(materialString);
} catch (Exception ex) {
Bukkit.getLogger().warning("[UltimateTimber] Warning: " + materialString + " is not a valid material name.");
}
String chanceString = string.split(",")[1].replace("Chance:", "");
try {
chance = Double.parseDouble(chanceString);
} catch (Exception ex) {
Bukkit.getLogger().warning("[UltimateTimber] Warning: " + chanceString + " is not a valid chance.");
}
if (material == null || chance == 0) continue;
ItemStack itemStack = new ItemStack(material);
itemMap.put(itemStack, chance);
}
}
}

View File

@ -1,77 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.Configuration;
import java.util.Collections;
public class DefaultConfig {
/*
Storing these values in final strings makes it so you can change the keys or refactor their names later on without
ever having to alter any code directly.
Also they are easier to refer to using an IDE.
*/
public static final String MAX_BRANCH_BLOCKS = "Max amount of logs that can be broken with one chop";
public static final String LEAVES_FOR_TREE = "The number of leaves required to detect a valid tree";
public static final String ONLY_BREAK_LOGS_UPWARDS = "Only break logs above the block broken";
public static final String ALLOW_MIXED_TREE_TYPES = "Allow mixed log/leaf to be considered as one tree";
public static final String ENTIRE_TREE_BASE = "Entire tree base must be broken for the tree to fall";
public static final String AXES_ONLY = "Only topple down trees cut down using axes";
public static final String TIMEOUT_BREAK = "Five second time out before you can break saplings";
public static final String SNEAK_ONLY = "Only topple down trees cut down while sneaking";
public static final String ACCURATE_AXE_DURABILITY = "Lower durability proportionately to the amount of blocks toppled down";
public static final String CREATIVE_DISALLOWED = "Players in creative mode can't topple down trees";
public static final String PERMISSIONS_ONLY = "Only allow players with the permission node to topple down trees";
public static final String VALID_WORLDS = "Valid worlds.";
public static final String DAMAGE_PLAYERS = "Damage players when trees fall on them";
public static final String DELETE_BROKEN_LOG = "Delete the log that initiated the tree fall";
public static final String REPLANT_SAPLING = "Replant sapling when tree is cut down";
public static final String REPLANT_FROM_LEAVES = "Fallen leaves have a chance to plant saplings";
public static final String CUSTOM_AUDIO = "Use custom sounds for trees falling";
public static final String SHOW_ANIMATION = "Show tree fall animation";
public static final String SCATTER_FALLEN_BLOCKS = "Scatter fallen tree blocks on the ground when animated";
public static final String CUSTOM_LOOT_LIST = "Custom loot";
public static final String CUSTOM_LOOT_ITEM = "Material:GOLDEN_APPLE,Chance:1";
public static void initialize() {
UltimateTimber plugin = UltimateTimber.getInstance();
Configuration configuration = plugin.getConfig();
configuration.addDefault(MAX_BRANCH_BLOCKS, 120);
configuration.addDefault(LEAVES_FOR_TREE, 5);
configuration.addDefault(ONLY_BREAK_LOGS_UPWARDS, true);
configuration.addDefault(ALLOW_MIXED_TREE_TYPES, false);
configuration.addDefault(ENTIRE_TREE_BASE, false);
configuration.addDefault(AXES_ONLY, true);
configuration.addDefault(TIMEOUT_BREAK, true);
configuration.addDefault(SNEAK_ONLY, false);
configuration.addDefault(ACCURATE_AXE_DURABILITY, true);
configuration.addDefault(CREATIVE_DISALLOWED, true);
configuration.addDefault(PERMISSIONS_ONLY, true);
configuration.addDefault(DAMAGE_PLAYERS, true);
configuration.addDefault(DELETE_BROKEN_LOG, false);
configuration.addDefault(REPLANT_SAPLING, true);
configuration.addDefault(REPLANT_FROM_LEAVES, true);
configuration.addDefault(CUSTOM_AUDIO, true);
configuration.addDefault(SHOW_ANIMATION, true);
configuration.addDefault(SCATTER_FALLEN_BLOCKS, false);
/*
Add all worlds that exist in the world at startup
*/
for (World world : Bukkit.getServer().getWorlds())
configuration.addDefault(VALID_WORLDS + world.getName(), true);
configuration.addDefault(CUSTOM_LOOT_LIST, Collections.singletonList(CUSTOM_LOOT_ITEM));
configuration.options().copyDefaults(true);
plugin.saveConfig();
plugin.saveDefaultConfig();
}
}

View File

@ -1,51 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.block.BlockBreakEvent;
class EventFilter {
/*
Incorporate all checks that would disqualify this event from happening
Mostly config settings, also permissions
*/
static boolean eventIsValid(BlockBreakEvent event) {
UltimateTimber plugin = UltimateTimber.getInstance();
/*
General catchers
*/
if (event.isCancelled()
|| !plugin.isWorldValid(event.getPlayer().getWorld())
|| !TreeChecker.getValidWoodMaterials().contains(event.getBlock().getType())) return false;
FileConfiguration fileConfiguration = UltimateTimber.getInstance().getConfig();
/*
Config-based catchers
*/
if (fileConfiguration.getBoolean(DefaultConfig.CREATIVE_DISALLOWED) &&
event.getPlayer().getGameMode().equals(GameMode.CREATIVE))
return false;
if (fileConfiguration.getBoolean(DefaultConfig.AXES_ONLY) &&
!(event.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.DIAMOND_AXE) ||
event.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.GOLDEN_AXE) ||
event.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.IRON_AXE) ||
event.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.STONE_AXE) ||
event.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.WOODEN_AXE)))
return false;
if (fileConfiguration.getBoolean(DefaultConfig.SNEAK_ONLY) &&
!event.getPlayer().isSneaking())
return false;
return !fileConfiguration.getBoolean(DefaultConfig.PERMISSIONS_ONLY) ||
event.getPlayer().hasPermission("ultimatetimber.chop");
}
}

View File

@ -1,20 +1,20 @@
package com.songoda.ultimatetimber.old_code;
import org.bukkit.block.Block;
import java.util.HashSet;
class NoAnimationTreeDestroyer {
/*
Only ever triggers when people have tree falling animations off in the config
*/
static void destroyTree(HashSet<Block> blocks, boolean hasBonusLoot, boolean hasSilkTouch) {
// Drop loot and plant a new sapling
for (Block block : blocks) {
TreeLoot.dropTreeLoot(block.getBlockData(), block.getLocation().clone().add(0.5, 0.5, 0.5), hasBonusLoot, hasSilkTouch);
TreeReplant.replaceOriginalBlock(block);
}
}
}
//package com.songoda.ultimatetimber.old_code;
//
//import org.bukkit.block.Block;
//
//import java.util.HashSet;
//
//class NoAnimationTreeDestroyer {
//
// /*
// Only ever triggers when people have tree falling animations off in the config
// */
// static void destroyTree(HashSet<Block> blocks, boolean hasBonusLoot, boolean hasSilkTouch) {
// // Drop loot and plant a new sapling
// for (Block block : blocks) {
// TreeLoot.dropTreeLoot(block.getBlockData(), block.getLocation().clone().add(0.5, 0.5, 0.5), hasBonusLoot, hasSilkTouch);
// TreeReplant.replaceOriginalBlock(block);
// }
// }
//
//}

View File

@ -1,21 +1,21 @@
package com.songoda.ultimatetimber.old_code;
import org.bukkit.entity.Entity;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.LivingEntity;
class TreeEntityDamage {
static void runDamage(FallingBlock fallingBlock) {
for (Entity entity : fallingBlock.getNearbyEntities(0.5, 0.5, 0.5)) {
if (!(entity instanceof LivingEntity)) continue;
((LivingEntity) entity).damage(1);
}
}
}
//package com.songoda.ultimatetimber.old_code;
//
//import org.bukkit.entity.Entity;
//import org.bukkit.entity.FallingBlock;
//import org.bukkit.entity.LivingEntity;
//
//class TreeEntityDamage {
//
// static void runDamage(FallingBlock fallingBlock) {
//
// for (Entity entity : fallingBlock.getNearbyEntities(0.5, 0.5, 0.5)) {
//
// if (!(entity instanceof LivingEntity)) continue;
//
// ((LivingEntity) entity).damage(1);
//
// }
//
// }
//
//}

View File

@ -1,298 +1,298 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class TreeFallAnimation implements Listener, Runnable {
/*
Register all instances of falling trees.
*/
private static ArrayList<TreeFallAnimation> treeFallAnimationInstances = new ArrayList<>();
private static Random random = new Random();
/*
This field gets updated based on player permissions, doubles loot from trees
*/
private boolean hasBonusLoot;
/*
If a player's tool has the silk touch enchantment, it changes the loot table
*/
private boolean hasSilkTouch;
/*
This field stores every falling block in this instance of the animation
This list is also used to identify if a falling block is a part of an animation
*/
private ArrayList<FallingBlock> fallingBlocks = new ArrayList<>();
/*
The ID of the task that manages the falling block detection
*/
private int fallingBlockTaskId;
private boolean hasBonusLoot() {
return this.hasBonusLoot;
}
private void setHasBonusLoot(boolean bool) {
this.hasBonusLoot = bool;
}
private boolean hasSilkTouch() {
return this.hasSilkTouch;
}
private void setHasSilkTouch(boolean bool) {
this.hasSilkTouch = bool;
}
private boolean isFallingTreeBlock(FallingBlock fallingBlock) {
return this.fallingBlocks.contains(fallingBlock);
}
private void registerFallingBlock(FallingBlock fallingBlock) {
this.fallingBlocks.add(fallingBlock);
}
private void unregisterFallingBlock(FallingBlock fallingBlock) {
this.fallingBlocks.remove(fallingBlock);
}
private ArrayList<FallingBlock> getAllFallingBlocks() {
return this.fallingBlocks;
}
private boolean isInTreeFallInstance(FallingBlock fallingBlock) {
for (TreeFallAnimation treeFallAnimation : treeFallAnimationInstances)
if (treeFallAnimation.isFallingTreeBlock(fallingBlock))
return true;
return false;
}
private TreeFallAnimation getTreeFallAnimation(FallingBlock fallingBlock) {
for (TreeFallAnimation treeFallAnimation : treeFallAnimationInstances)
if (treeFallAnimation.isFallingTreeBlock(fallingBlock))
return treeFallAnimation;
return null;
}
private void registerTreeFallInstance() {
treeFallAnimationInstances.add(this);
}
private void unregisterTreeFallAnimation() {
if (this.fallingBlocks.isEmpty()) {
treeFallAnimationInstances.remove(this);
Bukkit.getScheduler().cancelTask(this.fallingBlockTaskId);
}
}
/*
This is used to detect after the falling tree blocks have hit the ground
Using the event was too unreliable since multiple entities could hit the ground at the same time
*/
@Override
public void run() {
Set<FallingBlock> groundedBlocks = new HashSet<>();
for (FallingBlock fallingBlock : this.fallingBlocks)
if (fallingBlock.isDead())
groundedBlocks.add(fallingBlock);
for (FallingBlock fallingBlock : groundedBlocks)
runFallingBlockImpact(fallingBlock);
}
/*
This animation has multiple phases.
Initially, the tree will start slowly toppling over.
After a short while, it goes over the tipping point and the fall accelerates.
*/
void startAnimation(Block originalBlock, HashSet<Block> blocks, Player player) {
/*
This vector makes sure that the entire tree falls in the same direction from the same reference point
*/
Vector velocityVector = originalBlock.getLocation().clone().subtract(player.getLocation().clone()).toVector().normalize().setY(0);
registerTreeFallInstance();
setHasBonusLoot(player.hasPermission("ultimatetimber.bonusloot"));
/*
Register private properties
*/
if (player.getInventory().getItemInMainHand().getType().equals(Material.DIAMOND_AXE) ||
player.getInventory().getItemInMainHand().getType().equals(Material.GOLDEN_AXE) ||
player.getInventory().getItemInMainHand().getType().equals(Material.IRON_AXE) ||
player.getInventory().getItemInMainHand().getType().equals(Material.STONE_AXE) ||
player.getInventory().getItemInMainHand().getType().equals(Material.WOODEN_AXE))
if (player.getInventory().getItemInMainHand().getEnchantments().containsKey(Enchantment.SILK_TOUCH))
setHasSilkTouch(true);
else
setHasSilkTouch(false);
else
setHasSilkTouch(false);
for (Block block : blocks) {
/*
Dropping air causes some issues
*/
if (block.getType().equals(Material.AIR)) continue;
FallingBlock fallingBlock = block.getWorld().spawnFallingBlock(block.getLocation().clone().add(0.5, 0, 0.5), block.getBlockData());
fallingBlock.setDropItem(false);
registerFallingBlock(fallingBlock);
/*
Remove original block
*/
TreeReplant.replaceOriginalBlock(block);
/*
Set tipping over effect
The horizontal velocity going away from the player increases as the Y moves away from the player
*/
double multiplier = (block.getLocation().getY() - player.getLocation().getY()) * 0.1;
startPhaseOneAnimation(fallingBlock, velocityVector, multiplier);
}
/*
Kick off a task for detecting when the falling blocks have hit the ground
*/
this.fallingBlockTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(UltimateTimber.getInstance(), this, 0, 1);
}
/*
Phase one of the animation, the tree starts slowly tipping over
*/
private void startPhaseOneAnimation(FallingBlock fallingBlock, Vector velocityVector, double multiplier) {
/*
Vertical offset so top of the tree sways faster than the base
*/
fallingBlock.setVelocity(velocityVector.clone().multiply(multiplier));
/*
No gravity helps with the initial surrounding block detection (somehow) and with the initial trunk rigidity aspect
required for the effect to look convincing
*/
fallingBlock.setGravity(false);
fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(0.2));
new BukkitRunnable() {
@Override
public void run() {
fallingBlock.setGravity(true);
/*
Phase 2 has to be launched from here as to not override effects
*/
runPhaseTwoAnimation(fallingBlock);
}
}.runTaskLater(UltimateTimber.getInstance(), 20);
}
/*
Phase two of the animation, the tree picks up speed until it is on the ground
For safety's sake, it disintegrates after a 4 seconds
*/
private void runPhaseTwoAnimation(FallingBlock fallingBlock) {
UltimateTimber plugin = UltimateTimber.getInstance();
new BukkitRunnable() {
int counter = 0;
@Override
public void run() {
if (!fallingBlock.isValid()) {
cancel();
return;
}
/*
Safeguard to prevent errors that come from glitchy Minecraft behavior
*/
if (counter > 20 * 3) {
runFallingBlockImpact(fallingBlock);
cancel();
}
if (counter < 10)
fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(1.3));
counter++;
}
}.runTaskTimer(plugin, 0, 1);
}
/*
Catch tree blocks falling down and prevent them from interacting with the ground
*/
@EventHandler
public void blockDrop(EntityChangeBlockEvent event) {
if (!(event.getEntity() instanceof FallingBlock)) return;
FallingBlock fallingBlock = (FallingBlock) event.getEntity();
if (!isInTreeFallInstance(fallingBlock)) return;
if (UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.SCATTER_FALLEN_BLOCKS)) {
boolean isLeaf = fallingBlock.getBlockData().getMaterial().name().endsWith("LEAVES");
if (!isLeaf || (isLeaf && random.nextDouble() > 0.5)) { // Only let about half the leafs turn back into blocks
getTreeFallAnimation(fallingBlock).unregisterFallingBlock(fallingBlock);
return;
}
}
event.setCancelled(true);
}
private void runFallingBlockImpact(FallingBlock fallingBlock) {
TreeFallAnimation treeFallAnimation = getTreeFallAnimation(fallingBlock);
treeFallAnimation.unregisterFallingBlock(fallingBlock);
if (treeFallAnimation.getAllFallingBlocks().isEmpty())
unregisterTreeFallAnimation();
FileConfiguration fileConfiguration = UltimateTimber.getInstance().getConfig();
/*
Run block fall aftermath
*/
TreeLoot.dropTreeLoot(fallingBlock.getBlockData(), fallingBlock.getLocation(), treeFallAnimation.hasBonusLoot(), treeFallAnimation.hasSilkTouch());
if (UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.REPLANT_FROM_LEAVES))
TreeReplant.leafFallReplant(fallingBlock);
if (fileConfiguration.getBoolean(DefaultConfig.DAMAGE_PLAYERS))
TreeEntityDamage.runDamage(fallingBlock);
if (fileConfiguration.getBoolean(DefaultConfig.CUSTOM_AUDIO))
TreeSounds.fallNoise(fallingBlock);
fallingBlock.getLocation().getWorld().spawnParticle(Particle.SMOKE_LARGE, fallingBlock.getLocation(), 3, 0.2, 0.2, 0.2, 0.05);
/*
Make sure the falling block gets culled
*/
fallingBlock.remove();
}
}
//package com.songoda.ultimatetimber.old_code;
//
//import com.songoda.ultimatetimber.UltimateTimber;
//import org.bukkit.Bukkit;
//import org.bukkit.Material;
//import org.bukkit.Particle;
//import org.bukkit.block.Block;
//import org.bukkit.configuration.file.FileConfiguration;
//import org.bukkit.enchantments.Enchantment;
//import org.bukkit.entity.FallingBlock;
//import org.bukkit.entity.Player;
//import org.bukkit.event.EventHandler;
//import org.bukkit.event.Listener;
//import org.bukkit.event.entity.EntityChangeBlockEvent;
//import org.bukkit.scheduler.BukkitRunnable;
//import org.bukkit.util.Vector;
//
//import java.util.ArrayList;
//import java.util.HashSet;
//import java.util.Random;
//import java.util.Set;
//
//public class TreeFallAnimation implements Listener, Runnable {
//
// /*
// Register all instances of falling trees.
// */
// private static ArrayList<TreeFallAnimation> treeFallAnimationInstances = new ArrayList<>();
// private static Random random = new Random();
// /*
// This field gets updated based on player permissions, doubles loot from trees
// */
// private boolean hasBonusLoot;
// /*
// If a player's tool has the silk touch enchantment, it changes the loot table
// */
// private boolean hasSilkTouch;
// /*
// This field stores every falling block in this instance of the animation
// This list is also used to identify if a falling block is a part of an animation
// */
// private ArrayList<FallingBlock> fallingBlocks = new ArrayList<>();
//
// /*
// The ID of the task that manages the falling block detection
// */
// private int fallingBlockTaskId;
//
// private boolean hasBonusLoot() {
// return this.hasBonusLoot;
// }
//
// private void setHasBonusLoot(boolean bool) {
// this.hasBonusLoot = bool;
// }
//
// private boolean hasSilkTouch() {
// return this.hasSilkTouch;
// }
//
// private void setHasSilkTouch(boolean bool) {
// this.hasSilkTouch = bool;
// }
//
// private boolean isFallingTreeBlock(FallingBlock fallingBlock) {
// return this.fallingBlocks.contains(fallingBlock);
// }
//
// private void registerFallingBlock(FallingBlock fallingBlock) {
// this.fallingBlocks.add(fallingBlock);
// }
//
// private void unregisterFallingBlock(FallingBlock fallingBlock) {
// this.fallingBlocks.remove(fallingBlock);
// }
//
// private ArrayList<FallingBlock> getAllFallingBlocks() {
// return this.fallingBlocks;
// }
//
// private boolean isInTreeFallInstance(FallingBlock fallingBlock) {
// for (TreeFallAnimation treeFallAnimation : treeFallAnimationInstances)
// if (treeFallAnimation.isFallingTreeBlock(fallingBlock))
// return true;
// return false;
// }
//
// private TreeFallAnimation getTreeFallAnimation(FallingBlock fallingBlock) {
// for (TreeFallAnimation treeFallAnimation : treeFallAnimationInstances)
// if (treeFallAnimation.isFallingTreeBlock(fallingBlock))
// return treeFallAnimation;
// return null;
// }
//
// private void registerTreeFallInstance() {
// treeFallAnimationInstances.add(this);
// }
//
// private void unregisterTreeFallAnimation() {
// if (this.fallingBlocks.isEmpty()) {
// treeFallAnimationInstances.remove(this);
// Bukkit.getScheduler().cancelTask(this.fallingBlockTaskId);
// }
// }
//
// /*
// This is used to detect after the falling tree blocks have hit the ground
// Using the event was too unreliable since multiple entities could hit the ground at the same time
// */
// @Override
// public void run() {
// Set<FallingBlock> groundedBlocks = new HashSet<>();
// for (FallingBlock fallingBlock : this.fallingBlocks)
// if (fallingBlock.isDead())
// groundedBlocks.add(fallingBlock);
// for (FallingBlock fallingBlock : groundedBlocks)
// runFallingBlockImpact(fallingBlock);
// }
//
// /*
// This animation has multiple phases.
// Initially, the tree will start slowly toppling over.
// After a short while, it goes over the tipping point and the fall accelerates.
// */
// void startAnimation(Block originalBlock, HashSet<Block> blocks, Player player) {
// /*
// This vector makes sure that the entire tree falls in the same direction from the same reference point
// */
// Vector velocityVector = originalBlock.getLocation().clone().subtract(player.getLocation().clone()).toVector().normalize().setY(0);
//
// registerTreeFallInstance();
// setHasBonusLoot(player.hasPermission("ultimatetimber.bonusloot"));
//
// /*
// Register private properties
// */
// if (player.getInventory().getItemInMainHand().getType().equals(Material.DIAMOND_AXE) ||
// player.getInventory().getItemInMainHand().getType().equals(Material.GOLDEN_AXE) ||
// player.getInventory().getItemInMainHand().getType().equals(Material.IRON_AXE) ||
// player.getInventory().getItemInMainHand().getType().equals(Material.STONE_AXE) ||
// player.getInventory().getItemInMainHand().getType().equals(Material.WOODEN_AXE))
// if (player.getInventory().getItemInMainHand().getEnchantments().containsKey(Enchantment.SILK_TOUCH))
// setHasSilkTouch(true);
// else
// setHasSilkTouch(false);
// else
// setHasSilkTouch(false);
//
// for (Block block : blocks) {
//
// /*
// Dropping air causes some issues
// */
// if (block.getType().equals(Material.AIR)) continue;
//
// FallingBlock fallingBlock = block.getWorld().spawnFallingBlock(block.getLocation().clone().add(0.5, 0, 0.5), block.getBlockData());
// fallingBlock.setDropItem(false);
// registerFallingBlock(fallingBlock);
//
// /*
// Remove original block
// */
// TreeReplant.replaceOriginalBlock(block);
//
// /*
// Set tipping over effect
// The horizontal velocity going away from the player increases as the Y moves away from the player
// */
// double multiplier = (block.getLocation().getY() - player.getLocation().getY()) * 0.1;
//
// startPhaseOneAnimation(fallingBlock, velocityVector, multiplier);
//
// }
//
// /*
// Kick off a task for detecting when the falling blocks have hit the ground
// */
// this.fallingBlockTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(UltimateTimber.getInstance(), this, 0, 1);
//
// }
//
// /*
// Phase one of the animation, the tree starts slowly tipping over
// */
// private void startPhaseOneAnimation(FallingBlock fallingBlock, Vector velocityVector, double multiplier) {
//
// /*
// Vertical offset so top of the tree sways faster than the base
// */
// fallingBlock.setVelocity(velocityVector.clone().multiply(multiplier));
// /*
// No gravity helps with the initial surrounding block detection (somehow) and with the initial trunk rigidity aspect
// required for the effect to look convincing
// */
// fallingBlock.setGravity(false);
//
// fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(0.2));
//
// new BukkitRunnable() {
// @Override
// public void run() {
//
// fallingBlock.setGravity(true);
//
// /*
// Phase 2 has to be launched from here as to not override effects
// */
// runPhaseTwoAnimation(fallingBlock);
//
// }
// }.runTaskLater(UltimateTimber.getInstance(), 20);
//
// }
//
// /*
// Phase two of the animation, the tree picks up speed until it is on the ground
// For safety's sake, it disintegrates after a 4 seconds
// */
// private void runPhaseTwoAnimation(FallingBlock fallingBlock) {
// UltimateTimber plugin = UltimateTimber.getInstance();
// new BukkitRunnable() {
// int counter = 0;
//
// @Override
// public void run() {
//
// if (!fallingBlock.isValid()) {
// cancel();
// return;
// }
//
// /*
// Safeguard to prevent errors that come from glitchy Minecraft behavior
// */
// if (counter > 20 * 3) {
// runFallingBlockImpact(fallingBlock);
// cancel();
// }
//
// if (counter < 10)
// fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(1.3));
//
// counter++;
// }
// }.runTaskTimer(plugin, 0, 1);
//
// }
//
// /*
// Catch tree blocks falling down and prevent them from interacting with the ground
// */
// @EventHandler
// public void blockDrop(EntityChangeBlockEvent event) {
// if (!(event.getEntity() instanceof FallingBlock)) return;
// FallingBlock fallingBlock = (FallingBlock) event.getEntity();
// if (!isInTreeFallInstance(fallingBlock)) return;
//
// if (UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.SCATTER_FALLEN_BLOCKS)) {
// boolean isLeaf = fallingBlock.getBlockData().getMaterial().name().endsWith("LEAVES");
// if (!isLeaf || (isLeaf && random.nextDouble() > 0.5)) { // Only let about half the leafs turn back into blocks
// getTreeFallAnimation(fallingBlock).unregisterFallingBlock(fallingBlock);
// return;
// }
// }
//
// event.setCancelled(true);
// }
//
// private void runFallingBlockImpact(FallingBlock fallingBlock) {
//
// TreeFallAnimation treeFallAnimation = getTreeFallAnimation(fallingBlock);
// treeFallAnimation.unregisterFallingBlock(fallingBlock);
// if (treeFallAnimation.getAllFallingBlocks().isEmpty())
// unregisterTreeFallAnimation();
//
// FileConfiguration fileConfiguration = UltimateTimber.getInstance().getConfig();
//
// /*
// Run block fall aftermath
// */
// TreeLoot.dropTreeLoot(fallingBlock.getBlockData(), fallingBlock.getLocation(), treeFallAnimation.hasBonusLoot(), treeFallAnimation.hasSilkTouch());
// if (UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.REPLANT_FROM_LEAVES))
// TreeReplant.leafFallReplant(fallingBlock);
// if (fileConfiguration.getBoolean(DefaultConfig.DAMAGE_PLAYERS))
// TreeEntityDamage.runDamage(fallingBlock);
// if (fileConfiguration.getBoolean(DefaultConfig.CUSTOM_AUDIO))
// TreeSounds.fallNoise(fallingBlock);
//
// fallingBlock.getLocation().getWorld().spawnParticle(Particle.SMOKE_LARGE, fallingBlock.getLocation(), 3, 0.2, 0.2, 0.2, 0.05);
//
// /*
// Make sure the falling block gets culled
// */
// fallingBlock.remove();
//
// }
//
//}

View File

@ -1,86 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import com.songoda.ultimatetimber.events.TreeFallEvent;
import com.songoda.ultimatetimber.events.TreeFellEvent;
import com.songoda.ultimatetimber.manager.HookManager;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import java.util.HashSet;
public class TreeFallListener implements Listener {
/*
This is the starting point for the whole effect
It's been broken up instead of chained in order to make step-by-step debugging easier
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onTreeBreak(BlockBreakEvent event) {
FileConfiguration config = UltimateTimber.getInstance().getConfig();
Block block = event.getBlock();
if (block != null && block.getType().name().contains("SAPLING") &&
config.getBoolean(DefaultConfig.TIMEOUT_BREAK) && TreeReplant.isTimeout(block))
event.setCancelled(true);
if (!EventFilter.eventIsValid(event)) return;
if (config.getBoolean(DefaultConfig.SNEAK_ONLY) && !event.getPlayer().isSneaking()) return;
if (!UltimateTimber.getInstance().isChopping(event.getPlayer())) return;
TreeChecker treeChecker = new TreeChecker();
HashSet<Block> blocks = treeChecker.parseTree(block);
/*
Previous list will be null if no valid tree is found
*/
if (blocks == null)
return;
//Call event that tree will fall
TreeFallEvent treeFallEvent = new TreeFallEvent(event.getPlayer(), treeChecker, block);
Bukkit.getPluginManager().callEvent(treeFallEvent);
if (treeFallEvent.isCancelled()) return;
/*
Everything beyond this point assumes that the tree was valid
*/
// Do not let any items drop, it will be handled later
event.setDropItems(false);
// Remove log if it's enabled
if (config.getBoolean(DefaultConfig.DELETE_BROKEN_LOG))
TreeReplant.replaceOriginalBlock(block);
// Apply hooks
HookManager.getInstance().applyHooks(event.getPlayer(), blocks);
if (config.getBoolean(DefaultConfig.ACCURATE_AXE_DURABILITY))
AxeDurability.adjustAxeDamage(blocks, event.getPlayer());
if (config.getBoolean(DefaultConfig.CUSTOM_AUDIO))
TreeSounds.tipOverNoise(block.getLocation());
if (config.getBoolean(DefaultConfig.SHOW_ANIMATION)) {
TreeFallAnimation treeFallAnimation = new TreeFallAnimation();
treeFallAnimation.startAnimation(block, blocks, event.getPlayer());
} else {
NoAnimationTreeDestroyer.destroyTree(blocks, event.getPlayer().hasPermission("ultimatetimber.bonusloot"),
event.getPlayer().getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH));
}
//Call event that a tree has fell
TreeFellEvent treeFellEvent = new TreeFellEvent(event.getPlayer(), treeChecker, block);
Bukkit.getPluginManager().callEvent(treeFellEvent);
}
}

View File

@ -1,85 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import utils.LeafToSaplingConverter;
import utils.WoodToLogConverter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.Random;
class TreeLoot {
static Random random = new Random();
static void dropTreeLoot(BlockData blockData, Location location, boolean hasBonusLoot, boolean hasSilkTouch) {
World world = location.getWorld();
Material originalMaterial = blockData.getMaterial();
Material material = LeafToSaplingConverter.convertLeaves(originalMaterial);
if (originalMaterial.equals(Material.AIR) || originalMaterial.equals(Material.CAVE_AIR) || originalMaterial.equals(Material.VOID_AIR))
return;
if (hasSilkTouch) { // No bonus loot for silk touch
world.dropItem(location, new ItemStack(WoodToLogConverter.convert(originalMaterial), 1));
return;
}
switch (material) {
case VINE:
case MUSHROOM_STEM:
break;
case BROWN_MUSHROOM_BLOCK:
case RED_MUSHROOM_BLOCK:
boolean isRed = material.equals(Material.RED_MUSHROOM_BLOCK);
int numToDrop = Math.max(0, random.nextInt(10) - 7); // 80% chance to drop nothing, 10% chance for 1, 10% chance for 2
if (numToDrop != 0)
world.dropItem(location, new ItemStack(isRed ? Material.RED_MUSHROOM : Material.BROWN_MUSHROOM, numToDrop));
break;
case ACACIA_SAPLING:
case BIRCH_SAPLING:
case SPRUCE_SAPLING:
boolean dropChance = random.nextInt(20) == 0; // 1/20 chance to drop sapling
if (dropChance)
world.dropItem(location, new ItemStack(material, 1));
if (hasBonusLoot)
CustomLoot.doCustomItemDrop(location);
break;
case JUNGLE_SAPLING:
boolean jungleDropChance = random.nextInt(40) == 0; // 1/40 chance to drop sapling
if (jungleDropChance)
world.dropItem(location, new ItemStack(material, 1));
if (hasBonusLoot)
CustomLoot.doCustomItemDrop(location);
break;
case DARK_OAK_SAPLING:
case OAK_SAPLING:
boolean oakDropChance = random.nextInt(20) == 0; // 1/20 chance to drop sapling
if (oakDropChance)
world.dropItem(location, new ItemStack(material, 1));
boolean appleDropChance = random.nextInt(200) == 0; // 1/200 chance to drop apple
if (appleDropChance)
world.dropItem(location, new ItemStack(Material.APPLE, 1));
if (hasBonusLoot)
CustomLoot.doCustomItemDrop(location);
break;
default:
Material dropMaterial = WoodToLogConverter.convert(material);
world.dropItem(location, new ItemStack(dropMaterial, 1));
break;
}
}
}

View File

@ -1,141 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import com.songoda.ultimatetimber.UltimateTimber;
import utils.WoodToLogConverter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.FallingBlock;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
class TreeReplant {
private static List<Location> timeout = new ArrayList<>();
static void replaceOriginalBlock(Block block) {
boolean isTimeout = UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.TIMEOUT_BREAK);
Material material = WoodToLogConverter.convert(block.getType());
if (!UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.REPLANT_SAPLING)) {
block.setType(Material.AIR);
return;
}
Block below = block.getRelative(BlockFace.DOWN);
Material belowType = below.getType();
if (belowType.equals(Material.AIR) && UltimateTimber.getInstance().getConfig().getBoolean(DefaultConfig.ENTIRE_TREE_BASE)) {
if (isValidGround(below.getRelative(BlockFace.DOWN).getType())) {
if (isTimeout) {
timeout.add(below.getLocation());
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> timeout.remove(below.getLocation()), 20 * 5);
}
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> performReplacement(below, material), 1);
}
}
if (!isValidGround(belowType)) {
block.setType(Material.AIR);
return;
}
if (isTimeout) {
timeout.add(block.getLocation());
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> timeout.remove(block.getLocation()), 20 * 5);
}
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () -> performReplacement(block, material), 1);
}
static void performReplacement(Block block, Material material) {
switch (material) {
case ACACIA_LOG:
case STRIPPED_ACACIA_LOG:
block.setType(Material.ACACIA_SAPLING);
return;
case BIRCH_LOG:
case STRIPPED_BIRCH_LOG:
block.setType(Material.BIRCH_SAPLING);
return;
case DARK_OAK_LOG:
case STRIPPED_DARK_OAK_LOG:
block.setType(Material.DARK_OAK_SAPLING);
return;
case JUNGLE_LOG:
case STRIPPED_JUNGLE_LOG:
block.setType(Material.JUNGLE_SAPLING);
return;
case OAK_LOG:
case STRIPPED_OAK_LOG:
block.setType(Material.OAK_SAPLING);
return;
case SPRUCE_LOG:
case STRIPPED_SPRUCE_LOG:
block.setType(Material.SPRUCE_SAPLING);
return;
case BROWN_MUSHROOM_BLOCK:
block.setType(Material.BROWN_MUSHROOM);
return;
case RED_MUSHROOM_BLOCK:
block.setType(Material.RED_MUSHROOM);
return;
default:
block.setType(Material.AIR);
}
}
static void leafFallReplant(FallingBlock fallingBlock) {
Material material;
switch (fallingBlock.getBlockData().getMaterial()) {
case ACACIA_LEAVES:
material = Material.ACACIA_SAPLING;
break;
case BIRCH_LEAVES:
material = Material.BIRCH_SAPLING;
break;
case DARK_OAK_LEAVES:
material = Material.DARK_OAK_SAPLING;
break;
case JUNGLE_LEAVES:
material = Material.JUNGLE_SAPLING;
break;
case OAK_LEAVES:
material = Material.OAK_SAPLING;
break;
case SPRUCE_LEAVES:
material = Material.SPRUCE_SAPLING;
break;
default:
material = null;
}
if (material == null) return;
if (ThreadLocalRandom.current().nextDouble() > 0.01) return;
Block block = fallingBlock.getLocation().clone().subtract(new Vector(0, 1, 0)).getBlock();
if (isValidGround(block.getType())) {
Block blockAbove = block.getLocation().clone().add(new Vector(0, 1, 0)).getBlock();
if (blockAbove.getType().equals(Material.AIR))
fallingBlock.getLocation().getBlock().setType(material);
}
}
static boolean isTimeout(Block block) {
return timeout.contains(block.getLocation());
}
private static boolean isValidGround(Material material) {
return material.equals(Material.DIRT) || material.equals(Material.COARSE_DIRT) || material.equals(Material.PODZOL) || material.equals(Material.GRASS_BLOCK);
}
}

View File

@ -1,35 +0,0 @@
package com.songoda.ultimatetimber.old_code;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.FallingBlock;
class TreeSounds {
static void tipOverNoise(Location location) {
if (Bukkit.getServer().getClass().getPackage().toString().contains("8")) {
location.getWorld().playSound(location, Sound.valueOf("CHEST_OPEN"), 3f, 0.1f);
} else {
location.getWorld().playSound(location, Sound.BLOCK_CHEST_OPEN, 3F, 0.1F);
}
}
static void fallNoise(FallingBlock fallingBlock) {
if (Bukkit.getServer().getClass().getPackage().toString().contains("8")) {
fallingBlock.getWorld().playSound(fallingBlock.getLocation(), Sound.valueOf("ANVIL_LAND"), 3F, 0.1F);
return;
}
if (fallingBlock.getTicksLived() < 20)
fallingBlock.getWorld().playSound(fallingBlock.getLocation(), Sound.BLOCK_ANVIL_FALL, 3F, 0.1F);
else
fallingBlock.getWorld().playSound(fallingBlock.getLocation(), Sound.BLOCK_WOOD_FALL, 3F, 0.1F);
}
}

View File

@ -1,94 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<version>maven-version-number</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>UltimateTimber-${project.version}</finalName>
<defaultGoal>clean resources:resources package</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${project.build.directory}/classes/plugin.yml</file>
<replacements>
<replacement>
<token>maven-version-number</token>
<value>${project.version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>songoda-repo</id>
<url>http://repo.songoda.com/artifactory/private</url>
</repository>
</repositories>
<dependencies>
<!--Spigot API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Bukkit API-->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.13-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--mcMMO-->
<dependency>
<groupId>com.gmail.nossr50</groupId>
<artifactId>mcmmo</artifactId>
<version>1.5.09</version>
<scope>provided</scope>
</dependency>
<!--Jobs Reborn-->
<dependency>
<groupId>com.gamingmesh</groupId>
<artifactId>jobs</artifactId>
<version>4.6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

38
pom.xml
View File

@ -5,40 +5,36 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.songoda.ultimatetimber</groupId>
<artifactId>UltimateTimber</artifactId>
<artifactId>UltimateTimber-Parent</artifactId>
<packaging>pom</packaging>
<version>maven-version-number</version>
<modules>
<module>UltimateTimber/Core</module>
<module>UltimateTimber-Adapter/Current</module>
<module>UltimateTimber-Adapter/Legacy</module>
<module>UltimateTimber/Core</module>
<module>UltimateTimber/Plugin</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>songoda-repo</id>
<url>http://repo.songoda.com/artifactory/private</url>
</repository>
</repositories>
<build>
<defaultGoal>clean install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>