From 8d17848b6bd826def5d58b28cc3deb7e341d4ddc Mon Sep 17 00:00:00 2001 From: Len <40720638+destro174@users.noreply.github.com> Date: Sun, 28 Aug 2022 00:53:00 +0200 Subject: [PATCH] Add more listeners and events to listen to --- .../com/alttd/playershops/PlayerShops.java | 3 - .../playershops/handler/ShopHandler.java | 26 ++- .../playershops/listener/BlockListener.java | 92 ---------- .../playershops/listener/PlayerListener.java | 69 ++++++-- .../playershops/listener/ShopListener.java | 159 +++++++++++++++++- .../listener/TransactionListener.java | 3 + .../alttd/playershops/shop/PlayerShop.java | 3 +- .../com/alttd/playershops/utils/ShopUtil.java | 2 +- 8 files changed, 237 insertions(+), 120 deletions(-) delete mode 100644 src/main/java/com/alttd/playershops/listener/BlockListener.java diff --git a/src/main/java/com/alttd/playershops/PlayerShops.java b/src/main/java/com/alttd/playershops/PlayerShops.java index 3b1363b..f571cef 100644 --- a/src/main/java/com/alttd/playershops/PlayerShops.java +++ b/src/main/java/com/alttd/playershops/PlayerShops.java @@ -30,7 +30,6 @@ public class PlayerShops extends JavaPlugin { private DatabaseHelper databaseHelper; private ShopListener shopListener; private PlayerListener playerListener; - private BlockListener blockListener; private TransactionListener transactionListener; private InventoryListener inventoryListener; @@ -91,7 +90,6 @@ public class PlayerShops extends JavaPlugin { private void registerListeners() { shopListener = new ShopListener(this); playerListener = new PlayerListener(this); - blockListener = new BlockListener(this); transactionListener = new TransactionListener(this); inventoryListener = new InventoryListener(this); } @@ -99,7 +97,6 @@ public class PlayerShops extends JavaPlugin { private void unRegisterListeners() { shopListener.unregister(); playerListener.unregister(); - blockListener.unregister(); transactionListener.unregister(); inventoryListener.unregister(); } diff --git a/src/main/java/com/alttd/playershops/handler/ShopHandler.java b/src/main/java/com/alttd/playershops/handler/ShopHandler.java index 682cb96..db2b7c1 100644 --- a/src/main/java/com/alttd/playershops/handler/ShopHandler.java +++ b/src/main/java/com/alttd/playershops/handler/ShopHandler.java @@ -12,7 +12,10 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.DoubleChest; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; import java.sql.ResultSet; import java.sql.SQLException; @@ -95,10 +98,12 @@ public class ShopHandler { } public boolean isShopMaterial(Block block) { - if (Tag.SHULKER_BOXES.isTagged(block.getType())) { - return true; - } - return shopMaterials.contains(block.getType()); +// if (Tag.SHULKER_BOXES.isTagged(block.getType())) { +// return true; +// } +// return shopMaterials.contains(block.getType()); + // TODO make a cache of this somehow? + return block.getState() instanceof InventoryHolder inventoryHolder && !(inventoryHolder.getInventory().getHolder() instanceof DoubleChest); } public List getShops(UUID uuid) { @@ -116,6 +121,19 @@ public class ShopHandler { return shopSignLocation.get(newLocation); } + public PlayerShop getShopsNear(Block block) { + BlockFace[] faces = {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}; + for (BlockFace face : faces) { + if (this.isShopMaterial(block.getRelative(face))) { + Block shopChest = block.getRelative(face); + PlayerShop shop = getShop(shopChest.getLocation()); + if (shop != null) + return shop; + } + } + return null; + } + public void addShop(PlayerShop shop) { shopLocation.put(shop.getShopLocation(), shop); shopSignLocation.put(shop.getSignLocation(), shop); diff --git a/src/main/java/com/alttd/playershops/listener/BlockListener.java b/src/main/java/com/alttd/playershops/listener/BlockListener.java deleted file mode 100644 index d149c86..0000000 --- a/src/main/java/com/alttd/playershops/listener/BlockListener.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.alttd.playershops.listener; - -import com.alttd.playershops.PlayerShops; -import com.alttd.playershops.config.Config; -import com.alttd.playershops.config.MessageConfig; -import com.alttd.playershops.handler.ShopHandler; -import com.alttd.playershops.shop.PlayerShop; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import org.bukkit.Tag; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.Sign; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.type.WallSign; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.SignChangeEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.permissions.PermissionAttachmentInfo; - -import java.util.UUID; - -public class BlockListener extends EventListener { - - private final PlayerShops plugin; - ShopHandler shopHandler; - - public BlockListener(PlayerShops plugin) { - this.plugin = plugin; - this.register(this.plugin); - shopHandler = plugin.getShopHandler(); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onInventoryHolderBlockBreak(BlockBreakEvent event) { - if(!this.isRegistered) - return; - Block block = event.getBlock(); - - if (!(block.getState() instanceof InventoryHolder inventoryHolder)) - return; - - PlayerShop shop = shopHandler.getShop(block.getLocation()); - if (shop == null) - return; - - if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) { - event.setCancelled(true); - return; - } - - shopHandler.removeShop(shop); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onSignBlockBreak(BlockBreakEvent event) { - if(!this.isRegistered) - return; - // this is going to be heavy, add a cache shopsignlocation <-> Shop? - Block block = event.getBlock(); - - if (!(block.getState() instanceof Sign)) - return; - - BlockFace facing; - BlockData data = block.getState().getBlockData(); - if (data instanceof WallSign) { - facing = ((Directional) data).getFacing(); - } else { - facing = ((Rotatable) data).getRotation(); - } - - Block relativeBlock = block.getRelative(facing.getOppositeFace()); - PlayerShop shop = shopHandler.getShop(relativeBlock.getLocation()); - if (shop == null) - return; - - if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) { - event.setCancelled(true); - return; - } - - shopHandler.removeShop(shop); - } -} diff --git a/src/main/java/com/alttd/playershops/listener/PlayerListener.java b/src/main/java/com/alttd/playershops/listener/PlayerListener.java index 5a5db7a..2bad04a 100644 --- a/src/main/java/com/alttd/playershops/listener/PlayerListener.java +++ b/src/main/java/com/alttd/playershops/listener/PlayerListener.java @@ -9,8 +9,11 @@ import com.alttd.playershops.utils.EconomyUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.Chest; import org.bukkit.block.Sign; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; @@ -19,12 +22,19 @@ import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.inventory.EquipmentSlot; import org.bukkit.permissions.PermissionAttachmentInfo; import java.util.UUID; +/** + * Dedicated class to listen to player events + */ public class PlayerListener extends EventListener { private final PlayerShops plugin; @@ -64,21 +74,6 @@ public class PlayerListener extends EventListener { shopHandler.addPlayerLimit(player.getUniqueId(), buildPermissionNumber); } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onSignChange(SignChangeEvent event) { - if(!this.isRegistered) - return; - - Block block = event.getBlock(); - - if (!(block.getState() instanceof Sign)) return; - - PlayerShop shop = shopHandler.getShop(block.getLocation()); - if(shop == null) return; - - if(shop.isInitialized()) event.setCancelled(true); - } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onShopCreation(SignChangeEvent event) { if(!this.isRegistered) @@ -146,4 +141,48 @@ public class PlayerListener extends EventListener { } } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onDoubleChestPlace(BlockPlaceEvent event) { + if(!this.isRegistered) + return; + + Block block = event.getBlock(); + if (!(block.getState() instanceof Chest)) + return; + + PlayerShop playerShop = shopHandler.getShopsNear(block); + if (playerShop == null) + return; + + // As net.minecraft.world.level.block.state.properties.ChestType + // is not exposed in the api this is the shit we need to do to ensure these chests do not connect. + BlockData blockData = block.getState().getBlockData(); + Material material = blockData.getMaterial(); + BlockData newBlockData = material.createBlockData(); + BlockFace facing = ((Directional) blockData).getFacing(); + ((Directional) newBlockData).setFacing(facing); + block.getLocation().getBlock().setBlockData(newBlockData, true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onShopBlockInteraction(PlayerInteractEvent event) { + if(!this.isRegistered) + return; + + Block block = event.getClickedBlock(); + if (block == null) + return; + + PlayerShop playerShop = shopHandler.getShop(block.getLocation()); + if (playerShop == null) + return; + + // todo add bypass permission to open shop containers? + Player player = event.getPlayer(); + if (player.getUniqueId().equals(playerShop.getOwnerUUID())) + return; + + event.setCancelled(true); + // We could send some info here eg remaining inventory, item details + } } diff --git a/src/main/java/com/alttd/playershops/listener/ShopListener.java b/src/main/java/com/alttd/playershops/listener/ShopListener.java index 524d0ef..ae3d766 100644 --- a/src/main/java/com/alttd/playershops/listener/ShopListener.java +++ b/src/main/java/com/alttd/playershops/listener/ShopListener.java @@ -5,12 +5,31 @@ import com.alttd.playershops.handler.ShopHandler; import com.alttd.playershops.shop.PlayerShop; import org.bukkit.Location; import org.bukkit.Tag; +import org.bukkit.TreeType; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.type.WallSign; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.inventory.InventoryHolder; import java.util.Iterator; +/** + * Dedicated class to listen to events related to shops. + * + */ public class ShopListener extends EventListener { private final PlayerShops plugin; @@ -22,12 +41,12 @@ public class ShopListener extends EventListener { shopHandler = plugin.getShopHandler(); } - @EventHandler(ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onEntityExplosion(EntityExplodeEvent event) { if(!this.isRegistered) return; - // This might be heavy when tnt is chained, would it be better to expand the unbreakable block api in galaxy and use that? - // No need for slow bukkit events eating up cpu and memory + + // This might be heavy when tnt is chained Iterator blockIterator = event.blockList().iterator(); PlayerShop shop = null; while (blockIterator.hasNext()) { @@ -45,4 +64,138 @@ public class ShopListener extends EventListener { } } } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPhysics(BlockPhysicsEvent event) { + if(!this.isRegistered) + return; + + Block block = event.getBlock(); + if (!Tag.WALL_SIGNS.isTagged(block.getType())) return; + + + if (shopHandler.getShopBySignLocation(block.getLocation()) != null) + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInventoryHolderBlockBreak(BlockBreakEvent event) { + if(!this.isRegistered) + return; + + Block block = event.getBlock(); + + if (!(block.getState() instanceof InventoryHolder)) + return; + + PlayerShop shop = shopHandler.getShop(block.getLocation()); + if (shop == null) + return; + + // Shop sign must be broken in order to remove the shop? + event.setCancelled(true); + } + + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onSignBlockBreak(BlockBreakEvent event) { + if(!this.isRegistered) + return; + // this is going to be heavy, add a cache shopsignlocation <-> Shop? + Block block = event.getBlock(); + + if (!(block.getState() instanceof Sign)) + return; + + BlockFace facing; + BlockData data = block.getState().getBlockData(); + if (data instanceof WallSign) { + facing = ((Directional) data).getFacing(); + } else { + facing = ((Rotatable) data).getRotation(); + } + + Block relativeBlock = block.getRelative(facing.getOppositeFace()); + PlayerShop shop = shopHandler.getShop(relativeBlock.getLocation()); + if (shop == null) + return; + + if (!shopHandler.canPlayerBreakShop(event.getPlayer(), shop)) { + event.setCancelled(true); + return; + } + + shopHandler.removeShop(shop); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketEmptyAtSign(PlayerBucketEmptyEvent event) { + if (!this.isRegistered) + return; + + Block block = event.getBlock(); + if (!Tag.WALL_SIGNS.isTagged(block.getType())) + return; + + PlayerShop playerShop = shopHandler.getShopBySignLocation(block.getLocation()); + if (playerShop != null) + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketEmptyOnBlock(PlayerBucketEmptyEvent event) { + if (!this.isRegistered) + return; + + Block block = event.getBlock(); + + PlayerShop playerShop = shopHandler.getShop(block.getLocation()); + if (playerShop != null) + event.setCancelled(true); + } + + // mushrooms can replace blocks anywhere in the world w/o a check, this needs to be fixed in Galaxy or upstreams but is a pita + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onTreeGrow(StructureGrowEvent event) { + if (!this.isRegistered) + return; + + // as mushrooms only grow from bonemeal we can cut off early + if (!event.isFromBonemeal()) + return; + + // Only continue with mushrooms + TreeType treeType = event.getSpecies(); + if (treeType != TreeType.RED_MUSHROOM && treeType != TreeType.BROWN_MUSHROOM) + return; + + // we can either cancel the event or remove the blocks from the event. + // as canceling would mean we get back here on the next attempt I opt to remove the blocks + for (int i = 0; i < event.getBlocks().size(); i++) { + BlockState block = event.getBlocks().get(i); + PlayerShop playerShop; + if (block instanceof Sign sign) { // does not work? + playerShop = shopHandler.getShopBySignLocation(sign.getLocation()); + System.out.println(block.getBlock()); + } else { + playerShop = shopHandler.getShop(block.getLocation()); + } + if (playerShop != null) { + event.getBlocks().remove(i--); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onSignChange(SignChangeEvent event) { + if(!this.isRegistered) + return; + + if (!(event.getBlock().getState() instanceof Sign sign)) return; + + PlayerShop shop = shopHandler.getShopBySignLocation(sign.getLocation()); + if(shop == null) return; + + event.setCancelled(true); + } } diff --git a/src/main/java/com/alttd/playershops/listener/TransactionListener.java b/src/main/java/com/alttd/playershops/listener/TransactionListener.java index 40e88a2..83dc043 100644 --- a/src/main/java/com/alttd/playershops/listener/TransactionListener.java +++ b/src/main/java/com/alttd/playershops/listener/TransactionListener.java @@ -77,6 +77,9 @@ public class TransactionListener extends EventListener { } if (ShopUtil.canManageShop(player, playerShop)) { + if (player.isSneaking()) + return; + ShopManagementGui gui = new ShopManagementGui(player.getUniqueId(), playerShop); gui.open(); return; diff --git a/src/main/java/com/alttd/playershops/shop/PlayerShop.java b/src/main/java/com/alttd/playershops/shop/PlayerShop.java index ed2e30d..6e4e0f1 100644 --- a/src/main/java/com/alttd/playershops/shop/PlayerShop.java +++ b/src/main/java/com/alttd/playershops/shop/PlayerShop.java @@ -148,8 +148,7 @@ public class PlayerShop { void setSignLines(List signLines) { new BukkitRunnable() { public void run() { - - Sign signBlock = (Sign) signLocation.getBlock().getState(); + if (!(signLocation.getBlock().getState() instanceof Sign signBlock)) return; MiniMessage miniMessage = MiniMessage.miniMessage(); TagResolver tagResolver = TagResolver.resolver( Placeholder.unparsed("ownername", getOwnerName()), diff --git a/src/main/java/com/alttd/playershops/utils/ShopUtil.java b/src/main/java/com/alttd/playershops/utils/ShopUtil.java index 6a57a92..5ccb5ae 100644 --- a/src/main/java/com/alttd/playershops/utils/ShopUtil.java +++ b/src/main/java/com/alttd/playershops/utils/ShopUtil.java @@ -174,7 +174,7 @@ public class ShopUtil { if (m.equals(Material.TNT)) { return "TNT"; } - String orig = m.toString().toLowerCase(); + String orig = m.name().toLowerCase(); String[] splits = orig.split("_"); StringBuilder sb = new StringBuilder(orig.length()); int pos = 0;