2019-03-26 21:35:17 +01:00
|
|
|
package com.songoda.ultimatetimber.manager;
|
|
|
|
|
2021-04-05 16:07:03 +02:00
|
|
|
import com.songoda.core.compatibility.CompatibleMaterial;
|
2021-06-16 01:03:30 +02:00
|
|
|
import com.songoda.core.compatibility.ServerVersion;
|
2019-03-28 01:56:39 +01:00
|
|
|
import com.songoda.ultimatetimber.UltimateTimber;
|
2019-04-01 12:22:08 +02:00
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimation;
|
2019-04-17 10:11:58 +02:00
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimationCrumble;
|
2019-04-01 12:22:08 +02:00
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimationDisintegrate;
|
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimationFancy;
|
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimationNone;
|
2019-04-28 04:17:40 +02:00
|
|
|
import com.songoda.ultimatetimber.animation.TreeAnimationType;
|
2019-03-29 23:52:17 +01:00
|
|
|
import com.songoda.ultimatetimber.tree.DetectedTree;
|
2019-04-01 12:22:08 +02:00
|
|
|
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
2019-03-29 23:52:17 +01:00
|
|
|
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
2020-10-30 21:00:23 +01:00
|
|
|
import com.songoda.ultimatetimber.utils.ParticleUtils;
|
|
|
|
import com.songoda.ultimatetimber.utils.SoundUtils;
|
2019-03-28 01:56:39 +01:00
|
|
|
import org.bukkit.Bukkit;
|
2019-04-01 12:22:08 +02:00
|
|
|
import org.bukkit.block.Block;
|
|
|
|
import org.bukkit.entity.Entity;
|
|
|
|
import org.bukkit.entity.EntityType;
|
|
|
|
import org.bukkit.entity.FallingBlock;
|
|
|
|
import org.bukkit.entity.LivingEntity;
|
2019-03-29 23:52:17 +01:00
|
|
|
import org.bukkit.entity.Player;
|
2019-03-28 01:56:39 +01:00
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.EventPriority;
|
|
|
|
import org.bukkit.event.Listener;
|
|
|
|
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
|
|
|
|
2019-03-30 07:46:13 +01:00
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Set;
|
|
|
|
|
2019-04-01 12:22:08 +02:00
|
|
|
public class TreeAnimationManager extends Manager implements Listener, Runnable {
|
|
|
|
private final Set<TreeAnimation> activeAnimations;
|
2021-02-20 00:29:12 +01:00
|
|
|
private final int taskId;
|
2019-03-30 07:46:13 +01:00
|
|
|
|
2023-06-29 14:31:22 +02:00
|
|
|
public TreeAnimationManager(UltimateTimber plugin) {
|
|
|
|
super(plugin);
|
2019-03-30 07:46:13 +01:00
|
|
|
this.activeAnimations = new HashSet<>();
|
2019-04-01 12:22:08 +02:00
|
|
|
this.taskId = -1;
|
2023-06-29 14:31:22 +02:00
|
|
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
2020-01-27 14:16:29 +01:00
|
|
|
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0, 1L);
|
2019-03-28 01:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void reload() {
|
2019-03-30 07:46:13 +01:00
|
|
|
this.activeAnimations.clear();
|
2019-03-28 01:56:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void disable() {
|
2019-03-30 07:46:13 +01:00
|
|
|
this.activeAnimations.clear();
|
2019-04-01 12:22:08 +02:00
|
|
|
Bukkit.getScheduler().cancelTask(this.taskId);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
|
|
|
Set<ITreeBlock<FallingBlock>> groundedBlocks = new HashSet<>();
|
|
|
|
for (ITreeBlock<FallingBlock> fallingTreeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
|
|
|
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
2023-06-29 14:31:22 +02:00
|
|
|
if (fallingBlock.isDead() || ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) && fallingBlock.isOnGround()) {
|
2019-04-01 12:22:08 +02:00
|
|
|
groundedBlocks.add(fallingTreeBlock);
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (ITreeBlock<FallingBlock> fallingBlock : groundedBlocks) {
|
|
|
|
this.runFallingBlockImpact(treeAnimation, fallingBlock);
|
2023-06-29 14:31:22 +02:00
|
|
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17)) {
|
2021-06-16 01:03:30 +02:00
|
|
|
fallingBlock.getBlock().remove();
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
treeAnimation.getFallingTreeBlocks().remove(fallingBlock);
|
|
|
|
}
|
|
|
|
}
|
2019-03-28 01:56:39 +01:00
|
|
|
}
|
|
|
|
|
2019-03-29 23:52:17 +01:00
|
|
|
/**
|
|
|
|
* Plays an animation for toppling a tree
|
|
|
|
*
|
|
|
|
* @param detectedTree The DetectedTree
|
2020-10-30 21:00:23 +01:00
|
|
|
* @param player The Player who toppled the tree
|
2019-03-29 23:52:17 +01:00
|
|
|
*/
|
|
|
|
public void runAnimation(DetectedTree detectedTree, Player player) {
|
2019-04-28 04:17:40 +02:00
|
|
|
switch (TreeAnimationType.fromString(ConfigurationManager.Setting.TREE_ANIMATION_TYPE.getString())) {
|
|
|
|
case FANCY:
|
2019-03-30 07:46:13 +01:00
|
|
|
this.registerTreeAnimation(new TreeAnimationFancy(detectedTree, player));
|
|
|
|
break;
|
2019-04-28 04:17:40 +02:00
|
|
|
case DISINTEGRATE:
|
2019-03-30 07:46:13 +01:00
|
|
|
this.registerTreeAnimation(new TreeAnimationDisintegrate(detectedTree, player));
|
|
|
|
break;
|
2019-04-28 04:17:40 +02:00
|
|
|
case CRUMBLE:
|
2019-04-17 10:11:58 +02:00
|
|
|
this.registerTreeAnimation(new TreeAnimationCrumble(detectedTree, player));
|
|
|
|
break;
|
2019-04-28 04:17:40 +02:00
|
|
|
case NONE:
|
2019-03-30 07:46:13 +01:00
|
|
|
this.registerTreeAnimation(new TreeAnimationNone(detectedTree, player));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-01 12:22:08 +02:00
|
|
|
/**
|
|
|
|
* Checks if the given block is in an animation
|
|
|
|
*
|
|
|
|
* @param block The block to check
|
|
|
|
*/
|
|
|
|
public boolean isBlockInAnimation(Block block) {
|
2023-06-29 14:31:22 +02:00
|
|
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
|
|
|
for (ITreeBlock<Block> treeBlock : treeAnimation.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks()) {
|
|
|
|
if (treeBlock.getBlock().equals(block)) {
|
2019-04-01 12:22:08 +02:00
|
|
|
return true;
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the given falling block is in an animation
|
|
|
|
*
|
|
|
|
* @param fallingBlock The falling block to check
|
|
|
|
*/
|
|
|
|
public boolean isBlockInAnimation(FallingBlock fallingBlock) {
|
2023-06-29 14:31:22 +02:00
|
|
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
|
|
|
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
|
|
|
if (treeBlock.getBlock().equals(fallingBlock)) {
|
2019-04-01 12:22:08 +02:00
|
|
|
return true;
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a TreeAnimation that a given falling block is in
|
|
|
|
*
|
|
|
|
* @return A TreeAnimation
|
|
|
|
*/
|
|
|
|
private TreeAnimation getAnimationForBlock(FallingBlock fallingBlock) {
|
2023-06-29 14:31:22 +02:00
|
|
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
|
|
|
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
|
|
|
if (treeBlock.getBlock().equals(fallingBlock)) {
|
2019-04-01 12:22:08 +02:00
|
|
|
return treeAnimation;
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-03-30 07:46:13 +01:00
|
|
|
/**
|
|
|
|
* Registers and runs a tree animation
|
|
|
|
*/
|
|
|
|
private void registerTreeAnimation(TreeAnimation treeAnimation) {
|
|
|
|
this.activeAnimations.add(treeAnimation);
|
|
|
|
treeAnimation.playAnimation(() -> this.activeAnimations.remove(treeAnimation));
|
2019-03-29 23:52:17 +01:00
|
|
|
}
|
|
|
|
|
2019-04-01 12:22:08 +02:00
|
|
|
/**
|
|
|
|
* Reacts to a falling block hitting the ground
|
|
|
|
*
|
|
|
|
* @param treeAnimation The tree animation for the falling block
|
2020-10-30 21:00:23 +01:00
|
|
|
* @param treeBlock The tree block to impact
|
2019-04-01 12:22:08 +02:00
|
|
|
*/
|
|
|
|
public void runFallingBlockImpact(TreeAnimation treeAnimation, ITreeBlock<FallingBlock> treeBlock) {
|
2020-01-27 14:16:29 +01:00
|
|
|
TreeDefinitionManager treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
2019-04-01 12:22:08 +02:00
|
|
|
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
|
|
|
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
|
|
|
TreeDefinition treeDefinition = treeAnimation.getDetectedTree().getTreeDefinition();
|
|
|
|
|
2023-06-29 14:31:22 +02:00
|
|
|
if (useCustomParticles) {
|
2020-10-30 21:00:23 +01:00
|
|
|
ParticleUtils.playLandingParticles(treeBlock);
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
|
|
|
if (useCustomSound) {
|
2020-10-30 21:00:23 +01:00
|
|
|
SoundUtils.playLandingSound(treeBlock);
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
|
2021-04-05 16:07:03 +02:00
|
|
|
Block block = treeBlock.getLocation().subtract(0, 1, 0).getBlock();
|
|
|
|
if (ConfigurationManager.Setting.FRAGILE_BLOCKS.getStringList().contains(block.getType().toString())) {
|
|
|
|
block.getWorld().dropItemNaturally(block.getLocation(), CompatibleMaterial.getMaterial(block).getItem());
|
|
|
|
block.breakNaturally();
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:01:34 +02:00
|
|
|
treeDefinitionManager.dropTreeLoot(treeDefinition, treeBlock, treeAnimation.getPlayer(), treeAnimation.hasSilkTouch(), false);
|
2020-01-27 14:16:29 +01:00
|
|
|
this.plugin.getSaplingManager().replantSaplingWithChance(treeDefinition, treeBlock);
|
2019-04-01 12:22:08 +02:00
|
|
|
treeAnimation.getFallingTreeBlocks().remove(treeBlock);
|
|
|
|
}
|
|
|
|
|
2019-03-28 01:56:39 +01:00
|
|
|
@EventHandler(priority = EventPriority.HIGH)
|
|
|
|
public void onFallingBlockLand(EntityChangeBlockEvent event) {
|
2023-06-29 14:31:22 +02:00
|
|
|
if (event.getEntityType() != EntityType.FALLING_BLOCK) {
|
2019-04-01 12:22:08 +02:00
|
|
|
return;
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
|
2019-05-01 12:01:34 +02:00
|
|
|
FallingBlock fallingBlock = (FallingBlock) event.getEntity();
|
2023-06-29 14:31:22 +02:00
|
|
|
if (!this.isBlockInAnimation(fallingBlock)) {
|
2019-04-01 12:22:08 +02:00
|
|
|
return;
|
2023-06-29 14:31:22 +02:00
|
|
|
}
|
2019-04-01 12:22:08 +02:00
|
|
|
|
|
|
|
if (ConfigurationManager.Setting.FALLING_BLOCKS_DEAL_DAMAGE.getBoolean()) {
|
|
|
|
int damage = ConfigurationManager.Setting.FALLING_BLOCK_DAMAGE.getInt();
|
|
|
|
for (Entity entity : fallingBlock.getNearbyEntities(0.5, 0.5, 0.5)) {
|
2023-06-29 14:31:22 +02:00
|
|
|
if (!(entity instanceof LivingEntity)) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-30 21:00:23 +01:00
|
|
|
((LivingEntity) entity).damage(damage, fallingBlock);
|
2019-04-01 12:22:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConfigurationManager.Setting.SCATTER_TREE_BLOCKS_ON_GROUND.getBoolean()) {
|
|
|
|
TreeAnimation treeAnimation = this.getAnimationForBlock(fallingBlock);
|
|
|
|
if (treeAnimation != null) {
|
|
|
|
treeAnimation.removeFallingBlock(fallingBlock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2019-03-28 01:56:39 +01:00
|
|
|
|
2019-04-01 12:22:08 +02:00
|
|
|
event.setCancelled(true);
|
2019-03-28 01:56:39 +01:00
|
|
|
}
|
2019-03-26 21:35:17 +01:00
|
|
|
}
|