mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-19 19:25:48 +00:00
Deny placement when deletion is queued (#3911)
Co-authored-by: Daniel Walsh <walshydev@gmail.com> Co-authored-by: J3fftw <44972470+J3fftw1@users.noreply.github.com>
This commit is contained in:
parent
1aeb0e8f65
commit
0589b21af3
@ -90,20 +90,34 @@ public class BlockListener implements Listener {
|
|||||||
Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.PLACE_BLOCK);
|
Slimefun.getProtectionManager().logAction(e.getPlayer(), e.getBlock(), Interaction.PLACE_BLOCK);
|
||||||
}
|
}
|
||||||
if (sfItem != null && !(sfItem instanceof NotPlaceable)) {
|
if (sfItem != null && !(sfItem instanceof NotPlaceable)) {
|
||||||
if (!sfItem.canUse(e.getPlayer(), true)) {
|
Player player = e.getPlayer();
|
||||||
|
|
||||||
|
if (!sfItem.canUse(player, true)) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
} else {
|
} else {
|
||||||
SlimefunBlockPlaceEvent placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, e.getBlock(), sfItem);
|
Block block = e.getBlockPlaced();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resolves an issue when placing a block in a location currently in the deletion queue
|
||||||
|
* TODO This can be safely removed if/when the deletion no longer has a delay associated with it.
|
||||||
|
*/
|
||||||
|
if (Slimefun.getTickerTask().isDeletedSoon(block.getLocation())) {
|
||||||
|
Slimefun.getLocalization().sendMessage(player, "messages.await-deletion");
|
||||||
|
e.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlimefunBlockPlaceEvent placeEvent = new SlimefunBlockPlaceEvent(player, item, block, sfItem);
|
||||||
Bukkit.getPluginManager().callEvent(placeEvent);
|
Bukkit.getPluginManager().callEvent(placeEvent);
|
||||||
|
|
||||||
if (placeEvent.isCancelled()) {
|
if (placeEvent.isCancelled()) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
} else {
|
} else {
|
||||||
if (Slimefun.getBlockDataService().isTileEntity(e.getBlock().getType())) {
|
if (Slimefun.getBlockDataService().isTileEntity(block.getType())) {
|
||||||
Slimefun.getBlockDataService().setBlockData(e.getBlock(), sfItem.getId());
|
Slimefun.getBlockDataService().setBlockData(block, sfItem.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockStorage.addBlockInfo(e.getBlock(), "id", sfItem.getId(), true);
|
BlockStorage.addBlockInfo(block, "id", sfItem.getId(), true);
|
||||||
sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e));
|
sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,7 @@ messages:
|
|||||||
bee-suit-slow-fall: '&eYour Bee Wings will help you to get back to the ground safe and slow'
|
bee-suit-slow-fall: '&eYour Bee Wings will help you to get back to the ground safe and slow'
|
||||||
deprecated-item: '&4This item has been deprecated and will be removed from Slimefun soon.'
|
deprecated-item: '&4This item has been deprecated and will be removed from Slimefun soon.'
|
||||||
researching-is-disabled: '&cResearching has been disabled on this server. Everything is unlocked by default!'
|
researching-is-disabled: '&cResearching has been disabled on this server. Everything is unlocked by default!'
|
||||||
|
await-deletion: '&cYou cannot place a Slimefun block so soon after breaking one. Try again shortly.'
|
||||||
|
|
||||||
multi-tool:
|
multi-tool:
|
||||||
mode-change: '&b%device% mode changed to: &9%mode%'
|
mode-change: '&b%device% mode changed to: &9%mode%'
|
||||||
|
@ -58,7 +58,7 @@ class TestSlimefunBlockBreakEvent {
|
|||||||
Player player = new PlayerMock(server, "SomePlayer");
|
Player player = new PlayerMock(server, "SomePlayer");
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt()));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
||||||
@ -75,7 +75,7 @@ class TestSlimefunBlockBreakEvent {
|
|||||||
player.getInventory().setItemInMainHand(itemStack);
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt()));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
||||||
@ -106,7 +106,7 @@ class TestSlimefunBlockBreakEvent {
|
|||||||
player.getInventory().setItemInMainHand(itemStack);
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt()));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
||||||
@ -119,4 +119,24 @@ class TestSlimefunBlockBreakEvent {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Test that breaking a Slimefun block gets queued for deletion")
|
||||||
|
void testBlockBreaksGetQueuedForDeletion() {
|
||||||
|
Player player = new PlayerMock(server, "SomePlayer");
|
||||||
|
ItemStack itemStack = new ItemStack(Material.IRON_PICKAXE);
|
||||||
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
|
World world = server.addSimpleWorld("my_world");
|
||||||
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, TestUtilities.randomInt(), 100, TestUtilities.randomInt()));
|
||||||
|
|
||||||
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
|
BlockStorage.addBlockInfo(block, "id", "FOOD_COMPOSTER");
|
||||||
|
|
||||||
|
BlockBreakEvent blockBreakEvent = new BlockBreakEvent(block, player);
|
||||||
|
server.getPluginManager().callEvent(blockBreakEvent);
|
||||||
|
server.getPluginManager().assertEventFired(SlimefunBlockBreakEvent.class, e -> true);
|
||||||
|
|
||||||
|
Assertions.assertTrue(Slimefun.getTickerTask().isDeletedSoon(block.getLocation()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import org.bukkit.block.Block;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -61,9 +62,10 @@ public class TestSlimefunBlockPlaceEvent {
|
|||||||
player.getInventory().setItemInMainHand(itemStack);
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
int x = TestUtilities.randomInt();
|
||||||
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1));
|
int z = TestUtilities.randomInt();
|
||||||
BlockStorage.clearBlockInfo(block);
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z));
|
||||||
|
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
|
|
||||||
@ -83,9 +85,10 @@ public class TestSlimefunBlockPlaceEvent {
|
|||||||
player.getInventory().setItemInMainHand(itemStack);
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
int x = TestUtilities.randomInt();
|
||||||
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1));
|
int z = TestUtilities.randomInt();
|
||||||
BlockStorage.clearBlockInfo(block);
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z));
|
||||||
|
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
|
|
||||||
@ -119,9 +122,10 @@ public class TestSlimefunBlockPlaceEvent {
|
|||||||
player.getInventory().setItemInMainHand(itemStack);
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
World world = server.addSimpleWorld("my_world");
|
World world = server.addSimpleWorld("my_world");
|
||||||
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, 1, 1, 1));
|
int x = TestUtilities.randomInt();
|
||||||
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, 1, 0, 1));
|
int z = TestUtilities.randomInt();
|
||||||
BlockStorage.clearBlockInfo(block);
|
Block block = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z));
|
||||||
|
Block blockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z));
|
||||||
|
|
||||||
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
|
|
||||||
@ -136,4 +140,48 @@ public class TestSlimefunBlockPlaceEvent {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Test that you cannot place before a SlimefunBlock is fully cleared")
|
||||||
|
void testBlockPlacementBeforeFullDeletion() {
|
||||||
|
Player player = new PlayerMock(server, "SomePlayer");
|
||||||
|
ItemStack itemStack = slimefunItem.getItem();
|
||||||
|
player.getInventory().setItemInMainHand(itemStack);
|
||||||
|
|
||||||
|
// Place first block
|
||||||
|
World world = server.addSimpleWorld("my_world");
|
||||||
|
int x = TestUtilities.randomInt();
|
||||||
|
int z = TestUtilities.randomInt();
|
||||||
|
Block firstBlock = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z));
|
||||||
|
Block firstBlockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z));
|
||||||
|
|
||||||
|
Slimefun.getRegistry().getWorlds().put("my_world", new BlockStorage(world));
|
||||||
|
|
||||||
|
BlockPlaceEvent firstBlockPlaceEvent = new BlockPlaceEvent(
|
||||||
|
firstBlock, firstBlock.getState(), firstBlockAgainst, itemStack, player, true, EquipmentSlot.HAND
|
||||||
|
);
|
||||||
|
|
||||||
|
server.getPluginManager().callEvent(firstBlockPlaceEvent);
|
||||||
|
server.getPluginManager().assertEventFired(SlimefunBlockPlaceEvent.class, e -> {
|
||||||
|
Assertions.assertFalse(e.isCancelled());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Break block
|
||||||
|
server.getPluginManager().callEvent(new BlockBreakEvent(firstBlock, player));
|
||||||
|
server.getPluginManager().assertEventFired(SlimefunBlockBreakEvent.class, e -> true);
|
||||||
|
|
||||||
|
// Assert that the block is not fully deleted
|
||||||
|
Assertions.assertTrue(Slimefun.getTickerTask().isDeletedSoon(firstBlock.getLocation()));
|
||||||
|
|
||||||
|
// Place second block in the same location
|
||||||
|
Block secondBlock = new BlockMock(Material.GREEN_TERRACOTTA, new Location(world, x, 0, z));
|
||||||
|
Block secondBlockAgainst = new BlockMock(Material.GRASS, new Location(world, x, 1, z));
|
||||||
|
|
||||||
|
BlockPlaceEvent secondBlockPlaceEvent = new BlockPlaceEvent(
|
||||||
|
secondBlock, secondBlock.getState(), secondBlockAgainst, itemStack, player, true, EquipmentSlot.HAND
|
||||||
|
);
|
||||||
|
server.getPluginManager().callEvent(secondBlockPlaceEvent);
|
||||||
|
Assertions.assertTrue(secondBlockPlaceEvent.isCancelled());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.test;
|
|||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
@ -30,6 +31,8 @@ import io.github.thebusybiscuit.slimefun4.test.mocks.MockSlimefunItem;
|
|||||||
|
|
||||||
public final class TestUtilities {
|
public final class TestUtilities {
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
private TestUtilities() {}
|
private TestUtilities() {}
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
@ -76,4 +79,14 @@ public final class TestUtilities {
|
|||||||
latch.await(2, TimeUnit.SECONDS);
|
latch.await(2, TimeUnit.SECONDS);
|
||||||
return ref.get();
|
return ref.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
public static @Nonnull int randomInt() {
|
||||||
|
return random.nextInt(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
public static @Nonnull int randomInt(int upperBound) {
|
||||||
|
return random.nextInt(upperBound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user