Add more listeners and events to listen to

This commit is contained in:
Len 2022-08-28 00:53:00 +02:00
parent 3be53703be
commit 8d17848b6b
8 changed files with 237 additions and 120 deletions

View File

@ -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();
}

View File

@ -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<PlayerShop> 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);

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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<Block> 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);
}
}

View File

@ -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;

View File

@ -148,8 +148,7 @@ public class PlayerShop {
void setSignLines(List<String> 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()),

View File

@ -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;