From 57f8c9e4525e7f99649f75ad99cd0a2f752a28c5 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Mon, 15 Jun 2026 22:44:44 +0200 Subject: [PATCH 1/2] Add combat sign editing blocker --- .../com/eternalcode/combat/CombatPlugin.java | 2 + .../config/implementation/PluginConfig.java | 7 +++ .../implementation/SignEditingSettings.java | 13 ++++ .../fight/blocker/SignEditingBlocker.java | 63 +++++++++++++++++++ .../SignEditingSettingsTest.java | 15 +++++ .../fight/blocker/SignEditingBlockerTest.java | 34 ++++++++++ 6 files changed, 134 insertions(+) create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/SignEditingSettings.java create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java create mode 100644 eternalcombat-plugin/test/com/eternalcode/combat/config/implementation/SignEditingSettingsTest.java create mode 100644 eternalcombat-plugin/test/com/eternalcode/combat/fight/blocker/SignEditingBlockerTest.java diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java index d491fba0..b1f38b99 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -36,6 +36,7 @@ import com.eternalcode.combat.fight.drop.impl.PercentDropModifier; import com.eternalcode.combat.fight.drop.impl.PlayersHealthDropModifier; import com.eternalcode.combat.fight.blocker.PlaceBlockBlocker; +import com.eternalcode.combat.fight.blocker.SignEditingBlocker; import com.eternalcode.combat.fight.effect.FightEffectController; import com.eternalcode.combat.fight.effect.FightEffectService; import com.eternalcode.combat.fight.effect.FightEffectServiceImpl; @@ -204,6 +205,7 @@ public void onEnable() { new RespawnAnchorListener(this, this.fightManager, pluginConfig), new FireworkController(this.fightManager, pluginConfig, noticeService), new InventoryContainersBlocker(this.fightManager, pluginConfig, noticeService), + new SignEditingBlocker(this.fightManager, pluginConfig), new CommandsBlocker(this.fightManager, noticeService, pluginConfig), new ElytraBlocker(this.fightManager, pluginConfig), new ElytraEquipBlocker(this.fightManager, noticeService, pluginConfig, server), diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java index 6534cf0f..28ac1448 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java @@ -127,6 +127,13 @@ public class PluginConfig extends OkaeriConfig { }) public InventorySettings inventory = new InventorySettings(); + @Comment({ + " ", + "# Settings related to sign editing during combat.", + "# Created for sign traps where opening the sign editor can block ender pearl throws." + }) + public SignEditingSettings signEditing = new SignEditingSettings(); + @Comment({ " ", "# Settings related to placeholders used in the plugin.", diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/SignEditingSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/SignEditingSettings.java new file mode 100644 index 00000000..d826babf --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/SignEditingSettings.java @@ -0,0 +1,13 @@ +package com.eternalcode.combat.config.implementation; + +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.annotation.Comment; + +public class SignEditingSettings extends OkaeriConfig { + + @Comment({ + "# Prevent players from editing signs during combat.", + "# Disabled by default; created for sign traps where sign editing blocks ender pearl throws." + }) + public boolean disableSignEditingDuringCombat = false; +} diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java new file mode 100644 index 00000000..ea7f4d5f --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java @@ -0,0 +1,63 @@ +package com.eternalcode.combat.fight.blocker; + +import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; +import java.util.UUID; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Event.Result; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class SignEditingBlocker implements Listener { + + private final FightManager fightManager; + private final PluginConfig config; + + public SignEditingBlocker(FightManager fightManager, PluginConfig config) { + this.fightManager = fightManager; + this.config = config; + } + + @EventHandler + void onInteract(PlayerInteractEvent event) { + if (!this.config.signEditing.disableSignEditingDuringCombat) { + return; + } + + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + + Block clickedBlock = event.getClickedBlock(); + if (clickedBlock == null || !isSign(clickedBlock.getType())) { + return; + } + + Player player = event.getPlayer(); + UUID uniqueId = player.getUniqueId(); + + if (!this.fightManager.isInCombat(uniqueId)) { + return; + } + + event.setUseInteractedBlock(Result.DENY); + + ItemStack item = event.getItem(); + if (item != null && isEnderPearl(item.getType())) { + event.setUseItemInHand(Result.ALLOW); + } + } + + static boolean isSign(Material material) { + return material.name().endsWith("_SIGN"); + } + + static boolean isEnderPearl(Material material) { + return material == Material.ENDER_PEARL; + } +} diff --git a/eternalcombat-plugin/test/com/eternalcode/combat/config/implementation/SignEditingSettingsTest.java b/eternalcombat-plugin/test/com/eternalcode/combat/config/implementation/SignEditingSettingsTest.java new file mode 100644 index 00000000..6ed31815 --- /dev/null +++ b/eternalcombat-plugin/test/com/eternalcode/combat/config/implementation/SignEditingSettingsTest.java @@ -0,0 +1,15 @@ +package com.eternalcode.combat.config.implementation; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; + +class SignEditingSettingsTest { + + @Test + void shouldDisableSignEditingBlockerByDefault() { + SignEditingSettings signEditingSettings = new SignEditingSettings(); + + assertFalse(signEditingSettings.disableSignEditingDuringCombat); + } +} diff --git a/eternalcombat-plugin/test/com/eternalcode/combat/fight/blocker/SignEditingBlockerTest.java b/eternalcombat-plugin/test/com/eternalcode/combat/fight/blocker/SignEditingBlockerTest.java new file mode 100644 index 00000000..ffac4826 --- /dev/null +++ b/eternalcombat-plugin/test/com/eternalcode/combat/fight/blocker/SignEditingBlockerTest.java @@ -0,0 +1,34 @@ +package com.eternalcode.combat.fight.blocker; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.bukkit.Material; +import org.junit.jupiter.api.Test; + +class SignEditingBlockerTest { + + @Test + void shouldRecognizeStandingSignMaterials() { + assertTrue(SignEditingBlocker.isSign(Material.OAK_SIGN)); + assertTrue(SignEditingBlocker.isSign(Material.CRIMSON_SIGN)); + } + + @Test + void shouldRecognizeWallSignMaterials() { + assertTrue(SignEditingBlocker.isSign(Material.OAK_WALL_SIGN)); + assertTrue(SignEditingBlocker.isSign(Material.WARPED_WALL_SIGN)); + } + + @Test + void shouldIgnoreNonSignMaterials() { + assertFalse(SignEditingBlocker.isSign(Material.CHEST)); + assertFalse(SignEditingBlocker.isSign(Material.ENDER_PEARL)); + } + + @Test + void shouldRecognizeEnderPearlMaterial() { + assertTrue(SignEditingBlocker.isEnderPearl(Material.ENDER_PEARL)); + assertFalse(SignEditingBlocker.isEnderPearl(Material.OAK_SIGN)); + } +} From 2848ce06a5406d7c0fb3889a2dceaa9fad00a673 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Mon, 17 Aug 2026 20:54:08 +0200 Subject: [PATCH 2/2] Fix. --- .../eternalcode/combat/fight/blocker/SignEditingBlocker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java index ea7f4d5f..2d7b9102 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/blocker/SignEditingBlocker.java @@ -23,7 +23,7 @@ public SignEditingBlocker(FightManager fightManager, PluginConfig config) { this.config = config; } - @EventHandler + @EventHandler(ignoreCancelled = true) void onInteract(PlayerInteractEvent event) { if (!this.config.signEditing.disableSignEditingDuringCombat) { return; @@ -48,7 +48,7 @@ void onInteract(PlayerInteractEvent event) { event.setUseInteractedBlock(Result.DENY); ItemStack item = event.getItem(); - if (item != null && isEnderPearl(item.getType())) { + if (item != null && isEnderPearl(item.getType()) && event.useItemInHand() != Result.DENY) { event.setUseItemInHand(Result.ALLOW); } }