diff --git a/CHANGELOG.md b/CHANGELOG.md index b5821b674..ad9af9284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ * Crafting a Rag now yields two items * Small performance improvements for Slimefun guides * Small performance improvements for Cargo networks +* Small performance improvements for Miner Androids #### Fixes * Fixed Programmable Androids rotating in the wrong direction @@ -68,6 +69,7 @@ * Fixed #2207 * Fixed ChestTerminal timings showing up as cargo nodes * Fixed timings reports never arriving sometimes +* Fixed #2138 ## Release Candidate 15 (01 Aug 2020) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index 2553ba4d8..f475995fe 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -6,6 +6,7 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; @@ -39,24 +40,28 @@ public abstract class MinerAndroid extends ProgrammableAndroid { protected void dig(Block b, BlockMenu menu, Block block) { Collection drops = block.getDrops(effectivePickaxe); - if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) { + if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) { + OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); - AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); - Bukkit.getPluginManager().callEvent(event); + if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) { + AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); + Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } + if (event.isCancelled()) { + return; + } - // We only want to break non-Slimefun blocks - String blockId = BlockStorage.checkID(block); - if (blockId == null) { - for (ItemStack drop : drops) { - if (menu.fits(drop, getOutputSlots())) { - menu.pushItem(drop, getOutputSlots()); - block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); - block.setType(Material.AIR); + // We only want to break non-Slimefun blocks + String blockId = BlockStorage.checkID(block); + if (blockId == null) { + for (ItemStack drop : drops) { + if (menu.fits(drop, getOutputSlots())) { + menu.pushItem(drop, getOutputSlots()); + } } + + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); + block.setType(Material.AIR); } } } @@ -66,30 +71,34 @@ public abstract class MinerAndroid extends ProgrammableAndroid { protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) { Collection drops = block.getDrops(effectivePickaxe); - if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) { + if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) { + OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); - AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); - Bukkit.getPluginManager().callEvent(event); + if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) { + AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); + Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - - // We only want to break non-Slimefun blocks - SlimefunItem blockId = BlockStorage.check(block); - if (blockId == null) { - for (ItemStack drop : drops) { - if (menu.fits(drop, getOutputSlots())) { - menu.pushItem(drop, getOutputSlots()); - block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); - - block.setType(Material.AIR); - move(b, face, block); - - b.setType(Material.AIR); - BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation()); - } + if (event.isCancelled()) { + return; } + + // We only want to break non-Slimefun blocks + SlimefunItem blockId = BlockStorage.check(block); + if (blockId == null) { + for (ItemStack drop : drops) { + if (menu.fits(drop, getOutputSlots())) { + menu.pushItem(drop, getOutputSlots()); + } + } + + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); + + block.setType(Material.AIR); + move(b, face, block); + } + } + else { + move(b, face, block); } } else { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java index d478f9b59..225af96dd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/blocks/BlockPlacer.java @@ -1,26 +1,33 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.blocks; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Effect; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Nameable; +import org.bukkit.OfflinePlayer; import org.bukkit.block.Block; -import org.bukkit.block.BlockState; import org.bukkit.block.Dispenser; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections; +import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; -import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import io.papermc.lib.PaperLib; +import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.Objects.Category; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; @@ -39,7 +46,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; * @see BlockPlacerPlaceEvent * */ -public class BlockPlacer extends SimpleSlimefunItem { +public class BlockPlacer extends SlimefunItem { private final ItemSetting> blacklist = new ItemSetting<>("unplaceable-blocks", MaterialCollections.getAllUnbreakableBlocks().stream().map(Material::name).collect(Collectors.toList())); @@ -47,11 +54,28 @@ public class BlockPlacer extends SimpleSlimefunItem { super(category, item, recipeType, recipe); addItemSetting(blacklist); + addItemHandler(onPlace(), onBlockDispense()); } - @Override - public BlockDispenseHandler getItemHandler() { + private BlockPlaceHandler onPlace() { + return new BlockPlaceHandler(false) { + + @Override + public void onPlayerPlace(BlockPlaceEvent e) { + Player p = e.getPlayer(); + Block b = e.getBlock(); + + BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString()); + } + }; + } + + private BlockDispenseHandler onBlockDispense() { return (e, dispenser, facedBlock, machine) -> { + if (!hasPermission(dispenser, facedBlock)) { + return; + } + if (isShulkerBox(e.getItem().getType())) { // Since vanilla Dispensers can already place Shulker boxes, we // simply fallback to the vanilla behaviour. @@ -76,6 +100,31 @@ public class BlockPlacer extends SimpleSlimefunItem { }; } + /** + * This checks whether the {@link Player} who placed down this {@link BlockPlacer} has + * building permissions at that {@link Location}. + * + * @param dispenser + * The {@link Dispenser} who represents our {@link BlockPlacer} + * @param target + * The {@link Block} where it should be placed + * + * @return Whether this action is permitted or not + */ + private boolean hasPermission(Dispenser dispenser, Block target) { + String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner"); + + if (owner == null) { + // If no owner was set, then we will fallback to the previous behaviour: + // Allowing block placers to bypass protection, newly placed Block placers + // will respect protection plugins. + return true; + } + + OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner)); + return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK); + } + private boolean isShulkerBox(Material type) { return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX"); } @@ -139,14 +188,17 @@ public class BlockPlacer extends SimpleSlimefunItem { ItemMeta meta = item.getItemMeta(); if (meta.hasDisplayName()) { - BlockState blockState = facedBlock.getState(); + BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false); - if ((blockState instanceof Nameable)) { - ((Nameable) blockState).setCustomName(meta.getDisplayName()); + if ((blockState.getState() instanceof Nameable)) { + Nameable nameable = ((Nameable) blockState.getState()); + nameable.setCustomName(meta.getDisplayName()); + + if (blockState.isSnapshot()) { + // Update block state after changing name + blockState.getState().update(true, false); + } } - - // Update block state after changing name - blockState.update(); } }