Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix not dropping sensitive blocks once and for all #4200

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
Expand All @@ -29,17 +27,14 @@
import org.bukkit.inventory.meta.ItemMeta;

import io.github.bakedlibs.dough.protection.Interaction;
import io.github.thebusybiscuit.slimefun4.api.events.ExplosiveToolBreakBlocksEvent;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;

import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
Expand Down Expand Up @@ -171,23 +166,9 @@ public void onBlockBreak(BlockBreakEvent e) {
}

if (!e.isCancelled()) {
// Checks for Slimefun sensitive blocks above, using Slimefun Tags
// TODO: merge this with the vanilla sensitive block check (when 1.18- is dropped)
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock(), item);

callBlockHandler(e, item, drops, sfItem);

dropItems(e, drops);

// Checks for vanilla sensitive blocks everywhere
// checkForSensitiveBlocks(e.getBlock(), 0, e.isDropItems());
}
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onExplosiveToolBlockBreak(ExplosiveToolBreakBlocksEvent e) {
for (Block block : e.getAdditionalBlocks()) {
checkForSensitiveBlockAbove(e.getPlayer(), block, e.getItemInHand());
}
}

Expand Down Expand Up @@ -250,6 +231,9 @@ private void dropItems(BlockBreakEvent e, List<ItemStack> drops) {
// Disable normal block drops
e.setDropItems(false);

// Fix #3182 - Drop the sensitive blocks that require supporting block but don't drop the supporting block
e.getBlock().setType(Material.AIR, true);

for (ItemStack drop : drops) {
// Prevent null or air from being dropped
if (drop != null && drop.getType() != Material.AIR) {
Expand All @@ -262,107 +246,6 @@ private void dropItems(BlockBreakEvent e, List<ItemStack> drops) {
}
}

/**
* This method checks for a sensitive {@link Block}.
* Sensitive {@link Block Blocks} are pressure plates or saplings, which should be broken
* when the block beneath is broken as well.
*
* @param player
* The {@link Player} who broke this {@link Block}
* @param block
* The {@link Block} that was broken
* @param item
* The {@link ItemStack} that was used to break the {@link Block}
*/
@ParametersAreNonnullByDefault
private void checkForSensitiveBlockAbove(Player player, Block block, ItemStack item) {
Block blockAbove = block.getRelative(BlockFace.UP);

if (SlimefunTag.SENSITIVE_MATERIALS.isTagged(blockAbove.getType())) {
SlimefunItem sfItem = BlockStorage.check(blockAbove);

if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
/*
* We create a dummy here to pass onto the BlockBreakHandler.
* This will set the correct block context.
*/
BlockBreakEvent dummyEvent = new BlockBreakEvent(blockAbove, player);
List<ItemStack> drops = new ArrayList<>(sfItem.getDrops(player));

sfItem.callItemHandler(BlockBreakHandler.class, handler -> handler.onPlayerBreak(dummyEvent, item, drops));
blockAbove.setType(Material.AIR);

if (!dummyEvent.isCancelled() && dummyEvent.isDropItems()) {
for (ItemStack drop : drops) {
if (drop != null && !drop.getType().isAir()) {
blockAbove.getWorld().dropItemNaturally(blockAbove.getLocation(), drop);
}
}
}

// Fixes #2944 - Don't forget to clear the Block Data
BlockStorage.clearBlockInfo(blockAbove);
}
}
}

/**
* This method checks recursively for any sensitive blocks
* that are no longer supported due to this block breaking
*
* @param block
* The {@link Block} in question
* @param count
* The amount of times this has been recursively called
*/
// Disabled for now due to #4069 - Servers crashing due to this check
// There is additionally a second bug with `getMaxChainedNeighborUpdates` not existing in 1.17
@ParametersAreNonnullByDefault
private void checkForSensitiveBlocks(Block block, int count, boolean isDropItems) {
if (count >= Bukkit.getServer().getMaxChainedNeighborUpdates()) {
return;
}

BlockState state = block.getState();
// We set the block to air to make use of BlockData#isSupported.
block.setType(Material.AIR, false);
for (BlockFace face : CARDINAL_BLOCKFACES) {
if (!isSupported(block.getRelative(face).getBlockData(), block.getRelative(face))) {
Block relative = block.getRelative(face);
if (!isDropItems) {
for (ItemStack drop : relative.getDrops()) {
block.getWorld().dropItemNaturally(relative.getLocation(), drop);
}
}
checkForSensitiveBlocks(relative, ++count, isDropItems);
}
}
// Set the BlockData back: this makes it so containers and spawners drop correctly. This is a hacky fix.
block.setBlockData(state.getBlockData(), false);
state.update(true, false);
}

/**
* This method checks if the {@link BlockData} would be
* supported at the given {@link Block}.
*
* @param blockData
* The {@link BlockData} to check
* @param block
* The {@link Block} the {@link BlockData} would be at
* @return
* Whether the {@link BlockData} would be supported at the given {@link Block}
*/
@ParametersAreNonnullByDefault
private boolean isSupported(BlockData blockData, Block block) {
if (Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) {
return blockData.isSupported(block);
} else {
// TODO: Make 1.16-1.18 version. BlockData::isSupported is 1.19+.
return true;
}
}

private int getBonusDropsWithFortune(@Nullable ItemStack item, @Nonnull Block b) {
int amount = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import javax.annotation.Nonnull;

import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
Expand All @@ -12,6 +14,7 @@
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPistonEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
Expand Down Expand Up @@ -112,4 +115,34 @@ public void onBucketUse(PlayerBucketEmptyEvent e) {
e.setCancelled(true);
}
}

@EventHandler
public void onBlockUpdate(BlockPhysicsEvent event) {
if (!Slimefun.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_19)) {
// Method BlockData::isSupported is 1.19+
return;
}

Block block = event.getBlock();

// Listen for collapsing sensitive blocks
if (!block.getBlockData().isSupported(event.getBlock())) {
SlimefunItem sfItem = BlockStorage.check(block);

if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {
// Drop items from surrounding sensitive blocks but don't drop from supporting block
event.setCancelled(true);
block.setType(Material.AIR, true);

for (ItemStack drop : sfItem.getDrops()) {
if (drop != null && !drop.getType().isAir()) {
block.getWorld().dropItemNaturally(block.getLocation(), drop);
}
}

// Fixes #2944 - Don't forget to clear the Block Data
BlockStorage.clearBlockInfo(block);
EpicPlayerA10 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
EpicPlayerA10 marked this conversation as resolved.
Show resolved Hide resolved
}
Loading