From 35e19d0eedd50c2a06d01c0ff8158ccac867117b Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Mon, 17 Aug 2026 21:24:24 +0200 Subject: [PATCH 1/2] Keep combat tag active below void height to prevent evasion --- .../eternalcode/combat/fight/event/CauseOfTag.java | 5 +++++ .../config/implementation/CombatSettings.java | 13 +++++++++++++ .../com/eternalcode/combat/fight/FightTask.java | 10 ++++++++++ 3 files changed, 28 insertions(+) diff --git a/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/event/CauseOfTag.java b/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/event/CauseOfTag.java index 9cbc001e..8250cda4 100644 --- a/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/event/CauseOfTag.java +++ b/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/event/CauseOfTag.java @@ -34,6 +34,11 @@ public enum CauseOfTag { ENDER_PEARL, + /** + * The player's combat tag was kept active because they were below the void combat height. + */ + VOID, + /** * A custom cause, typically defined by external plugins or systems, applied the combat tag. */ diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CombatSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CombatSettings.java index 8378dae9..557615a7 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CombatSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CombatSettings.java @@ -90,6 +90,19 @@ public class CombatSettings extends OkaeriConfig { }) public EventPriority quitPunishmentEventPriority = EventPriority.NORMAL; + @Comment({ + "# Keep a player's combat tag continuously active while they are below 'voidCombatHeight'.", + "# This prevents players from evading combat by falling into the void (e.g. in the End).", + "# Set to 'true' to keep resetting the combat timer to its full duration while below that height." + }) + public boolean keepCombatActiveInVoid = false; + + @Comment({ + "# The Y height below which the combat timer is kept active (see 'keepCombatActiveInVoid').", + "# Default: 0, matching the void threshold in worlds such as the End." + }) + public double voidCombatHeight = 0; + @Comment({ "# List of kick reasons where players will NOT be punished for combat logging.", "# If this list is empty, players are ALWAYS punished when kicked during combat.", diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java index 9f78f18b..9120d046 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java @@ -1,7 +1,9 @@ package com.eternalcode.combat.fight; import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.event.CauseOfTag; import com.eternalcode.combat.fight.event.CauseOfUnTag; +import com.eternalcode.combat.fight.event.FightTagEvent; import com.eternalcode.combat.notification.NoticeService; import com.eternalcode.combat.util.DurationUtil; import java.util.Optional; @@ -36,6 +38,14 @@ public void run() { UUID playerUniqueId = player.getUniqueId(); + if (this.config.combat.keepCombatActiveInVoid && player.getLocation().getY() < this.config.combat.voidCombatHeight) { + FightTagEvent tagEvent = this.fightManager.tag(playerUniqueId, this.config.settings.combatTimerDuration, CauseOfTag.VOID, fightTag.getTagger()); + + if (!tagEvent.isCancelled()) { + fightTag = this.fightManager.getTag(playerUniqueId); + } + } + if (fightTag.isExpired()) { this.fightManager.untag(playerUniqueId, CauseOfUnTag.TIME_EXPIRED); return; From bc11f4627510a32712ee15f25985e13350fedd73 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Mon, 17 Aug 2026 21:32:18 +0200 Subject: [PATCH 2/2] Respect ignored worlds for void combat --- .../com/eternalcode/combat/fight/FightTask.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java index 9120d046..95a62679 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTask.java @@ -38,7 +38,14 @@ public void run() { UUID playerUniqueId = player.getUniqueId(); - if (this.config.combat.keepCombatActiveInVoid && player.getLocation().getY() < this.config.combat.voidCombatHeight) { + if (fightTag.isExpired()) { + this.fightManager.untag(playerUniqueId, CauseOfUnTag.TIME_EXPIRED); + return; + } + + if (this.config.combat.keepCombatActiveInVoid + && player.getLocation().getY() < this.config.combat.voidCombatHeight + && !this.config.settings.ignoredWorlds.contains(player.getWorld().getName())) { FightTagEvent tagEvent = this.fightManager.tag(playerUniqueId, this.config.settings.combatTimerDuration, CauseOfTag.VOID, fightTag.getTagger()); if (!tagEvent.isCancelled()) { @@ -46,11 +53,6 @@ public void run() { } } - if (fightTag.isExpired()) { - this.fightManager.untag(playerUniqueId, CauseOfUnTag.TIME_EXPIRED); - return; - } - Duration remaining = fightTag.getRemainingDuration(); String opponent = Optional.ofNullable(fightTag.getTagger())