diff --git a/src/main/kotlin/listener/ClickListener.kt b/src/main/kotlin/listener/ClickListener.kt index 9e27fec..9912eb0 100644 --- a/src/main/kotlin/listener/ClickListener.kt +++ b/src/main/kotlin/listener/ClickListener.kt @@ -3,7 +3,9 @@ package top.e404.boom.listener import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.block.Action +import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.hanging.HangingBreakByEntityEvent import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerInteractEvent import top.e404.boom.PL @@ -27,6 +29,77 @@ object ClickListener : EListener(PL) { if (!blockRegex.matches(block.type.name) || !itemRegex.matches(item) ) continue + if (player.hasPermission("boom.bypass.block")) { + plugin.debug { + Lang[ + "click.pass", + "player" to player.name, + "item" to item, + "target" to block.type.name, + "world" to player.world.name, + "x" to block.x, + "y" to block.y, + "z" to block.z, + ] + } + return + } + isCancelled = true + plugin.debug { + Lang[ + "click.prevent", + "player" to player.name, + "item" to item, + "target" to block.type.name, + "world" to player.world.name, + "x" to block.x, + "y" to block.y, + "z" to block.z, + ] + } + return + } + plugin.debug { + Lang[ + "click.pass", + "player" to player.name, + "item" to item, + "target" to block.type.name, + "world" to player.world.name, + "x" to block.x, + "y" to block.y, + "z" to block.z, + ] + } + } + + @EventHandler + fun BlockBreakEvent.onEvent() { + val block = block + val cfg = Config.getEachOrGlobal(player.world.name) { preventClickBlock } ?: return + val item = player.inventory.itemInMainHand.type.name + for ((itemRegex, blockRegex, type) in cfg) { + // 忽略交互检测 + if (type == Config.ClickType.RIGHT) continue + // 物品或方块不匹配 + if (!blockRegex.matches(block.type.name) + || !itemRegex.matches(item) + ) continue + if (player.hasPermission("boom.bypass.block")) { + plugin.debug { + Lang[ + "click.pass", + "player" to player.name, + "item" to item, + "target" to block.type.name, + "world" to player.world.name, + "x" to block.x, + "y" to block.y, + "z" to block.z, + ] + } + return + } isCancelled = true plugin.debug { Lang[ @@ -68,6 +141,22 @@ object ClickListener : EListener(PL) { if (!entityRegex.matches(entity) || !itemRegex.matches(item) ) continue + if (player.hasPermission("boom.bypass.entity")) { + plugin.debug { + val l = rightClicked.location + Lang[ + "click.pass", + "player" to player.name, + "item" to item, + "target" to entity, + "world" to player.world.name, + "x" to l.blockX, + "y" to l.blockY, + "z" to l.blockZ, + ] + } + return + } isCancelled = true plugin.debug { val l = rightClicked.location @@ -99,6 +188,67 @@ object ClickListener : EListener(PL) { } } + @EventHandler + fun HangingBreakByEntityEvent.onEvent() { + val remover = remover + if (remover !is Player) return + val entity = entity + val cfg = Config.getEachOrGlobal(remover.world.name) { preventClickEntity } ?: return + val item = remover.inventory.itemInMainHand.type.name + for ((itemRegex, entityRegex, type) in cfg) { + // 忽略交互检测 + if (type == Config.ClickType.RIGHT) continue + // 物品或实体不匹配 + if (!entityRegex.matches(entity.type.name) + || !itemRegex.matches(item) + ) continue + if (remover.hasPermission("boom.bypass.entity")) { + plugin.debug { + val l = entity.location + Lang[ + "click.pass", + "player" to remover.name, + "item" to item, + "target" to entity.type.name, + "world" to remover.world.name, + "x" to l.x, + "y" to l.y, + "z" to l.z, + ] + } + return + } + isCancelled = true + plugin.debug { + val l = entity.location + Lang[ + "click.prevent", + "player" to remover.name, + "item" to item, + "target" to entity.type.name, + "world" to remover.world.name, + "x" to l.x, + "y" to l.y, + "z" to l.z, + ] + } + return + } + plugin.debug { + val l = entity.location + Lang[ + "click.pass", + "player" to remover.name, + "item" to item, + "target" to entity.type.name, + "world" to remover.world.name, + "x" to l.x, + "y" to l.y, + "z" to l.z, + ] + } + } + @EventHandler fun EntityDamageByEntityEvent.onEvent() { val damager = damager @@ -112,6 +262,22 @@ object ClickListener : EListener(PL) { if (!entityRegex.matches(entityType.name) || !itemRegex.matches(item) ) continue + if (damager.hasPermission("boom.bypass.entity")) { + plugin.debug { + val l = entity.location + Lang[ + "click.pass", + "player" to damager.name, + "item" to item, + "target" to entity.type.name, + "world" to damager.world.name, + "x" to l.x, + "y" to l.y, + "z" to l.z, + ] + } + return + } isCancelled = true plugin.debug { val l = entity.location diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bde5047..b0b000b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -202,6 +202,11 @@ global: # 阻止玩家使用物品点击方块 # 空手时item为AIR + # 可用物品|方块类型: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html + + # 匹配正则示例(方块): "IRON_ORE|DIAMOND_ORE" + # 反向匹配正则示例(方块)(除了其中写到的其他都匹配): "(?!(IRON_ORE|DIAMOND_ORE)$).+" + # 匹配全部示例(匹配所有): ".*" prevent_click_block: # 以下这条配置的效果是阻止玩家使用刷怪蛋点击刷怪笼 # - # 玩家点击方块时的物品类型匹配正则 @@ -214,6 +219,13 @@ global: # 阻止玩家使用物品点击实体 # 空手时item为AIR + # 展示框等也算是实体 + # 可用实体类型: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html + # 可用物品类型: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html + + # 匹配正则示例(实体): "SPIDER|ZOMBIE" + # 反向匹配正则示例(实体)(除了其中写到的其他都匹配): "(?!(SPIDER|ZOMBIE)$).+" + # 匹配全部示例(匹配所有): ".*" prevent_click_entity: # 以下这条配置的效果是阻止玩家使用胡萝卜点击猪 # - # 玩家点击方块时的物品类型匹配正则 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cf06801..ac043d4 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -34,4 +34,12 @@ permissions: boom.stick: default: op - description: 允许使用盔甲架调试棒 \ No newline at end of file + description: 允许使用盔甲架调试棒 + boom.bypass.*: + default: false + + children: + boom.bypass.block: + default: false + boom.bypass.entity: + default: false