From 4703f2b20088e36ea612c707c709b9b9698bd549 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Sun, 13 Mar 2022 07:47:56 +1100 Subject: [PATCH] SPIGOT-6895: Trees grown with applyBoneMeal() don't fire the StructureGrowthEvent By: DerFrZocker --- .../bukkit/craftbukkit/block/CraftBlock.java | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java index fbdf997c8c..34d99e5455 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -1,9 +1,11 @@ package org.bukkit.craftbukkit.block; import com.google.common.base.Preconditions; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import net.minecraft.core.BlockPosition; import net.minecraft.core.EnumDirection; @@ -21,6 +23,7 @@ import net.minecraft.world.level.GeneratorAccess; import net.minecraft.world.level.RayTrace; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.BlockRedstoneWire; +import net.minecraft.world.level.block.BlockSapling; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.phys.AxisAlignedBB; @@ -29,11 +32,13 @@ import net.minecraft.world.phys.MovingObjectPositionBlock; import net.minecraft.world.phys.Vec3D; import net.minecraft.world.phys.shapes.VoxelShape; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Registry; +import org.bukkit.TreeType; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.Block; @@ -53,6 +58,8 @@ import org.bukkit.craftbukkit.util.CraftRayTraceResult; import org.bukkit.craftbukkit.util.CraftVoxelShape; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockFertilizeEvent; +import org.bukkit.event.world.StructureGrowEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.Plugin; @@ -483,9 +490,39 @@ public class CraftBlock implements Block { @Override public boolean applyBoneMeal(BlockFace face) { EnumDirection direction = blockFaceToNotch(face); - ItemActionContext context = new ItemActionContext(getCraftWorld().getHandle(), null, EnumHand.MAIN_HAND, Items.BONE_MEAL.getDefaultInstance(), new MovingObjectPositionBlock(Vec3D.ZERO, direction, getPosition(), false)); + BlockFertilizeEvent event = null; + WorldServer world = getCraftWorld().getHandle(); + ItemActionContext context = new ItemActionContext(world, null, EnumHand.MAIN_HAND, Items.BONE_MEAL.getDefaultInstance(), new MovingObjectPositionBlock(Vec3D.ZERO, direction, getPosition(), false)); - return ItemBoneMeal.applyBonemeal(context) == EnumInteractionResult.SUCCESS; + // SPIGOT-6895: Call StructureGrowEvent and BlockFertilizeEvent + world.captureTreeGeneration = true; + EnumInteractionResult result = ItemBoneMeal.applyBonemeal(context); + world.captureTreeGeneration = false; + + if (world.capturedBlockStates.size() > 0) { + TreeType treeType = BlockSapling.treeType; + BlockSapling.treeType = null; + List blocks = new ArrayList<>(world.capturedBlockStates.values()); + world.capturedBlockStates.clear(); + StructureGrowEvent structureEvent = null; + + if (treeType != null) { + structureEvent = new StructureGrowEvent(getLocation(), treeType, true, null, blocks); + Bukkit.getPluginManager().callEvent(structureEvent); + } + + event = new BlockFertilizeEvent(CraftBlock.at(world, getPosition()), null, blocks); + event.setCancelled(structureEvent != null && structureEvent.isCancelled()); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + for (BlockState blockstate : blocks) { + blockstate.update(true); + } + } + } + + return result == EnumInteractionResult.SUCCESS && (event == null || !event.isCancelled()); } @Override