From 8dfe3539e028d0d1eb2d1dbfcb8b6aa8a1101fde Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:56:51 +0100 Subject: [PATCH 01/13] WIP: Post death command execution --- eternalcombat-plugin/build.gradle.kts | 7 ++-- .../implementation/CommandSettings.java | 32 ++++++++++++++++++ .../config/implementation/PluginConfig.java | 3 +- .../fight/death/DeathCommandController.java | 33 +++++++++++++++++++ .../fight/death/DeathCommandService.java | 22 +++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java diff --git a/eternalcombat-plugin/build.gradle.kts b/eternalcombat-plugin/build.gradle.kts index fb3a8d48..34a4760d 100644 --- a/eternalcombat-plugin/build.gradle.kts +++ b/eternalcombat-plugin/build.gradle.kts @@ -1,6 +1,6 @@ -import net.minecrell.pluginyml.bukkit.BukkitPluginDescription + import io.papermc.hangarpublishplugin.model.Platforms -import org.gradle.kotlin.dsl.shadowJar +import net.minecrell.pluginyml.bukkit.BukkitPluginDescription plugins { `eternalcombat-java` @@ -93,11 +93,12 @@ bukkit { tasks { runServer { - minecraftVersion("1.21.10") + minecraftVersion("1.21.11") downloadPlugins.modrinth("WorldEdit", Versions.WORLDEDIT) downloadPlugins.modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot") downloadPlugins.modrinth("WorldGuard", Versions.WORLDGUARD) downloadPlugins.modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit") + downloadPlugins.modrinth("EternalCore", "2.0.1-SNAPSHOT+12") } } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index d0819515..821fb219 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -23,4 +23,36 @@ public class CommandSettings extends OkaeriConfig { "tpa", "tpaccept" ); + + @Comment({ + "# List of commands that will be executed from console after player death.", + "# Use {dead} to represent the name of the player who died and {killer} for the killer's name (if applicable)." + }) + public List consolePostDeathCommands = List.of( + "broadcast {player} has died in combat!" + ); + + + @Comment({ + "# List of commands that will be executed from the dead player's perspective after death.", + "# Use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." + }) + public List deadPostDeathCommands = List.of( + "say You have died in combat!" + ); + + @Comment("# When this is set to true, the plugin will execute the commands above only after the dead player has respawned.") + public boolean executeAfterRespawn = true; + + + @Comment({ + "# List of commands that will be executed from the killer's perspective after killing a player.", + "# Use {player} to represent the name of the player who was killed and {killer} for the killer's name (if applicable)." + }) + public List killerPostDeathCommands = List.of( + "say You have killed {player} in combat!" + ); + + @Comment("# When this is set to true, the plugin will only execute the post-death commands if the players were tagged") + public boolean onlyExecuteIfTagged = true; } 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 bc29665f..4a328765 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 @@ -87,7 +87,8 @@ public class PluginConfig extends OkaeriConfig { @Comment({ " ", "# Settings related to commands during combat.", - "# Configure command restrictions and behaviors for players in combat." + "# Configure command restrictions and behaviors for players in combat.", + "# You can also execute which commands will be executed post-death and on logout of the player." }) public CommandSettings commands = new CommandSettings(); diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java new file mode 100644 index 00000000..0d4c658b --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -0,0 +1,33 @@ +package com.eternalcode.combat.fight.death; + +import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.event.FightUntagEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; + +import java.util.UUID; + +public class DeathCommandController implements Listener { + + private final DeathCommandService commandService; + private final PluginConfig config; + private final FightManager fightManager; + + public DeathCommandController(DeathCommandService commandService, PluginConfig config, FightManager fightManager) { + this.commandService = commandService; + this.config = config; + this.fightManager = fightManager; + } + + @EventHandler + void onPlayerUntag(FightUntagEvent event) { + UUID player = event.getPlayer(); + + if (this.config.commands.onlyExecuteIfTagged && ) + + } + +} diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java new file mode 100644 index 00000000..da502bc0 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java @@ -0,0 +1,22 @@ +package com.eternalcode.combat.fight.death; + +import org.bukkit.Server; +import org.bukkit.entity.Player; + +public class DeathCommandService { + + private final Server server; + + public DeathCommandService(Server server) { + this.server = server; + } + + void dispatchAsConsole(String command) { + this.server.dispatchCommand(this.server.getConsoleSender(), command); + } + + void dispatchAsPlayer(Player player, String command) { + this.server.dispatchCommand(player, command); + } + +} From e3331170536bb97b4fcb06659bb231d1fa25928a Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:37:53 +0100 Subject: [PATCH 02/13] Post death command execution --- buildSrc/src/main/kotlin/Versions.kt | 1 + eternalcombat-plugin/build.gradle.kts | 12 +- .../com/eternalcode/combat/CombatPlugin.java | 52 +++--- .../implementation/CommandSettings.java | 5 +- .../fight/death/DeathCommandController.java | 148 +++++++++++++++++- .../fight/death/DeathCommandService.java | 22 --- 6 files changed, 180 insertions(+), 60 deletions(-) delete mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 1a34654f..1ccdef15 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -32,6 +32,7 @@ object Versions { const val PACKETEVENTS = "2.11.1" const val WORLDGUARD = "7.0.15-beta-01" const val LUCKPERMS = "5.5.17" + const val ETERNALCORE = "2.0.1-SNAPSHOT+12" } diff --git a/eternalcombat-plugin/build.gradle.kts b/eternalcombat-plugin/build.gradle.kts index 34a4760d..ecefb955 100644 --- a/eternalcombat-plugin/build.gradle.kts +++ b/eternalcombat-plugin/build.gradle.kts @@ -94,11 +94,13 @@ bukkit { tasks { runServer { minecraftVersion("1.21.11") - downloadPlugins.modrinth("WorldEdit", Versions.WORLDEDIT) - downloadPlugins.modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot") - downloadPlugins.modrinth("WorldGuard", Versions.WORLDGUARD) - downloadPlugins.modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit") - downloadPlugins.modrinth("EternalCore", "2.0.1-SNAPSHOT+12") + downloadPlugins { + modrinth("WorldEdit", Versions.WORLDEDIT) + modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot") + modrinth("WorldGuard", Versions.WORLDGUARD) + modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit") + modrinth("EternalCore", Versions.ETERNALCORE) + } } } 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 4b492fc1..832da020 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -1,54 +1,55 @@ package com.eternalcode.combat; -import com.eternalcode.combat.border.BorderTriggerController; import com.eternalcode.combat.border.BorderService; import com.eternalcode.combat.border.BorderServiceImpl; +import com.eternalcode.combat.border.BorderTriggerController; import com.eternalcode.combat.border.animation.block.BorderBlockController; import com.eternalcode.combat.border.animation.particle.ParticleController; import com.eternalcode.combat.bridge.BridgeService; -import com.eternalcode.combat.crystalpvp.RespawnAnchorListener; +import com.eternalcode.combat.config.ConfigService; +import com.eternalcode.combat.config.implementation.PluginConfig; import com.eternalcode.combat.crystalpvp.EndCrystalListener; +import com.eternalcode.combat.crystalpvp.RespawnAnchorListener; +import com.eternalcode.combat.event.EventManager; +import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.FightManagerImpl; +import com.eternalcode.combat.fight.FightTagCommand; +import com.eternalcode.combat.fight.FightTask; +import com.eternalcode.combat.fight.controller.FightActionBlockerController; import com.eternalcode.combat.fight.controller.FightBypassAdminController; import com.eternalcode.combat.fight.controller.FightBypassCreativeController; import com.eternalcode.combat.fight.controller.FightBypassPermissionController; import com.eternalcode.combat.fight.controller.FightInventoryController; +import com.eternalcode.combat.fight.controller.FightMessageController; +import com.eternalcode.combat.fight.controller.FightTagController; +import com.eternalcode.combat.fight.controller.FightUnTagController; +import com.eternalcode.combat.fight.death.DeathCommandController; import com.eternalcode.combat.fight.death.DeathEffectController; -import com.eternalcode.combat.fight.drop.DropKeepInventoryService; -import com.eternalcode.combat.fight.FightManager; -import com.eternalcode.combat.fight.drop.DropService; -import com.eternalcode.combat.fight.effect.FightEffectService; -import com.eternalcode.combat.fight.firework.FireworkController; -import com.eternalcode.combat.fight.knockback.KnockbackService; -import com.eternalcode.combat.fight.tagout.FightTagOutService; -import com.eternalcode.combat.fight.pearl.FightPearlService; -import com.eternalcode.combat.handler.InvalidUsageHandlerImpl; -import com.eternalcode.combat.handler.MissingPermissionHandlerImpl; -import com.eternalcode.combat.config.ConfigService; -import com.eternalcode.combat.config.implementation.PluginConfig; import com.eternalcode.combat.fight.drop.DropController; +import com.eternalcode.combat.fight.drop.DropKeepInventoryService; import com.eternalcode.combat.fight.drop.DropKeepInventoryServiceImpl; +import com.eternalcode.combat.fight.drop.DropService; import com.eternalcode.combat.fight.drop.DropServiceImpl; import com.eternalcode.combat.fight.drop.impl.PercentDropModifier; import com.eternalcode.combat.fight.drop.impl.PlayersHealthDropModifier; -import com.eternalcode.combat.fight.FightTagCommand; -import com.eternalcode.combat.fight.controller.FightActionBlockerController; -import com.eternalcode.combat.fight.controller.FightMessageController; -import com.eternalcode.combat.fight.controller.FightTagController; -import com.eternalcode.combat.fight.controller.FightUnTagController; import com.eternalcode.combat.fight.effect.FightEffectController; -import com.eternalcode.combat.event.EventManager; -import com.eternalcode.combat.fight.FightManagerImpl; -import com.eternalcode.combat.fight.FightTask; +import com.eternalcode.combat.fight.effect.FightEffectService; import com.eternalcode.combat.fight.effect.FightEffectServiceImpl; +import com.eternalcode.combat.fight.firework.FireworkController; +import com.eternalcode.combat.fight.knockback.KnockbackRegionController; +import com.eternalcode.combat.fight.knockback.KnockbackService; import com.eternalcode.combat.fight.logout.LogoutController; import com.eternalcode.combat.fight.logout.LogoutService; import com.eternalcode.combat.fight.pearl.FightPearlController; +import com.eternalcode.combat.fight.pearl.FightPearlService; import com.eternalcode.combat.fight.pearl.FightPearlServiceImpl; +import com.eternalcode.combat.fight.tagout.FightTagOutCommand; import com.eternalcode.combat.fight.tagout.FightTagOutController; +import com.eternalcode.combat.fight.tagout.FightTagOutService; import com.eternalcode.combat.fight.tagout.FightTagOutServiceImpl; -import com.eternalcode.combat.fight.tagout.FightTagOutCommand; +import com.eternalcode.combat.handler.InvalidUsageHandlerImpl; +import com.eternalcode.combat.handler.MissingPermissionHandlerImpl; import com.eternalcode.combat.notification.NoticeService; -import com.eternalcode.combat.fight.knockback.KnockbackRegionController; import com.eternalcode.combat.region.RegionProvider; import com.eternalcode.combat.updater.UpdaterNotificationController; import com.eternalcode.combat.updater.UpdaterService; @@ -61,7 +62,6 @@ import dev.rollczi.litecommands.bukkit.LiteBukkitFactory; import dev.rollczi.litecommands.bukkit.LiteBukkitMessages; import dev.rollczi.litecommands.folia.FoliaExtension; -import java.time.Duration; import net.kyori.adventure.platform.AudienceProvider; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -73,6 +73,7 @@ import org.bukkit.plugin.java.JavaPlugin; import java.io.File; +import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -183,6 +184,7 @@ public void onEnable() { new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server), new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService), new DeathEffectController(pluginConfig), + new DeathCommandController(pluginConfig, this.fightManager, server), new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage), new KnockbackRegionController(noticeService, this.regionProvider, this.fightManager, knockbackService, server), new FightEffectController(pluginConfig.effect, this.fightEffectService, this.fightManager, server), diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index 821fb219..801d0e24 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -32,6 +32,8 @@ public class CommandSettings extends OkaeriConfig { "broadcast {player} has died in combat!" ); + @Comment("# When this is set to true, the plugin will execute the console commands only after the dead player has respawned.") + public boolean deferConsoleAfterRespawn = false; @Comment({ "# List of commands that will be executed from the dead player's perspective after death.", @@ -42,8 +44,7 @@ public class CommandSettings extends OkaeriConfig { ); @Comment("# When this is set to true, the plugin will execute the commands above only after the dead player has respawned.") - public boolean executeAfterRespawn = true; - + public boolean deferDeadAfterRespawn = true; @Comment({ "# List of commands that will be executed from the killer's perspective after killing a player.", diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index 0d4c658b..087e542d 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -2,32 +2,168 @@ import com.eternalcode.combat.config.implementation.PluginConfig; import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.FightTag; +import com.eternalcode.combat.fight.event.CauseOfUnTag; import com.eternalcode.combat.fight.event.FightUntagEvent; +import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class DeathCommandController implements Listener { - private final DeathCommandService commandService; private final PluginConfig config; private final FightManager fightManager; + private final Server server; - public DeathCommandController(DeathCommandService commandService, PluginConfig config, FightManager fightManager) { - this.commandService = commandService; + private final Map> pendingCommands = new ConcurrentHashMap<>(); + private final Set handledByUntag = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + public DeathCommandController(PluginConfig config, FightManager fightManager, Server server) { this.config = config; this.fightManager = fightManager; + this.server = server; } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) void onPlayerUntag(FightUntagEvent event) { - UUID player = event.getPlayer(); + UUID playerUUID = event.getPlayer(); + CauseOfUnTag cause = event.getCause(); + + if (cause != CauseOfUnTag.DEATH && cause != CauseOfUnTag.DEATH_BY_PLAYER && cause != CauseOfUnTag.LOGOUT) { + return; + } + + Player deadPlayer = this.server.getPlayer(playerUUID); + + if (deadPlayer == null) { + return; + } + + this.handledByUntag.add(playerUUID); + this.executeDeathCommands(deadPlayer); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + void onPlayerDeath(PlayerDeathEvent event) { + if (this.config.commands.onlyExecuteIfTagged) { + return; + } + + Player deadPlayer = event.getEntity(); + UUID playerUUID = deadPlayer.getUniqueId(); + + if (this.handledByUntag.remove(playerUUID)) { + return; + } + + this.executeDeathCommands(deadPlayer); + } + + @EventHandler(priority = EventPriority.MONITOR) + void onPlayerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + UUID playerUUID = player.getUniqueId(); + + this.handledByUntag.remove(playerUUID); + + List commands = this.pendingCommands.remove(playerUUID); + + if (commands == null) { + return; + } + + for (PendingCommand pending : commands) { + switch (pending.executor()) { + case CONSOLE -> this.server.dispatchCommand(this.server.getConsoleSender(), pending.command()); + case DEAD_PLAYER -> this.server.dispatchCommand(player, pending.command()); + } + } + } + + private void executeDeathCommands(Player deadPlayer) { + UUID playerUUID = deadPlayer.getUniqueId(); + String deadPlayerName = deadPlayer.getName(); + String killerName = this.resolveKillerName(playerUUID, deadPlayer); - if (this.config.commands.onlyExecuteIfTagged && ) + List deferred = new ArrayList<>(); + for (String command : this.config.commands.consolePostDeathCommands) { + String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); + if (this.config.commands.deferConsoleAfterRespawn) { + deferred.add(new PendingCommand(CommandSource.CONSOLE, resolved)); + } else { + this.server.dispatchCommand(this.server.getConsoleSender(), resolved); + } + } + + for (String command : this.config.commands.deadPostDeathCommands) { + String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); + if (this.config.commands.deferDeadAfterRespawn) { + deferred.add(new PendingCommand(CommandSource.DEAD_PLAYER, resolved)); + } else { + this.server.dispatchCommand(deadPlayer, resolved); + } + } + + Player killer = this.resolveKiller(playerUUID, deadPlayer); + + if (killer != null) { + for (String command : this.config.commands.killerPostDeathCommands) { + String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); + this.server.dispatchCommand(killer, resolved); + } + } + + if (!deferred.isEmpty()) { + this.pendingCommands.put(playerUUID, deferred); + } + } + + + private String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { + Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); + return killer != null ? killer.getName() : "Unknown"; + } + + private Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { + Player killer = deadPlayer.getKiller(); + + if (killer != null) { + return killer; + } + + FightTag tag = this.fightManager.getTag(deadPlayerUUID); + + if (tag != null && tag.getTagger() != null) { + return this.server.getPlayer(tag.getTagger()); + } + + return null; } + private String replacePlaceholders(String command, String playerName, String killerName) { + return command + .replace("{player}", playerName) + .replace("{killer}", killerName); + } + + private enum CommandSource { + CONSOLE, + DEAD_PLAYER + } + + private record PendingCommand(CommandSource executor, String command) { + } } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java deleted file mode 100644 index da502bc0..00000000 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.eternalcode.combat.fight.death; - -import org.bukkit.Server; -import org.bukkit.entity.Player; - -public class DeathCommandService { - - private final Server server; - - public DeathCommandService(Server server) { - this.server = server; - } - - void dispatchAsConsole(String command) { - this.server.dispatchCommand(this.server.getConsoleSender(), command); - } - - void dispatchAsPlayer(Player player, String command) { - this.server.dispatchCommand(player, command); - } - -} From 16f45ca98cc37b4815e1e91405d20138caee03ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:57:39 +0100 Subject: [PATCH 03/13] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../combat/config/implementation/CommandSettings.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index 801d0e24..7cea010e 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -26,8 +26,7 @@ public class CommandSettings extends OkaeriConfig { @Comment({ "# List of commands that will be executed from console after player death.", - "# Use {dead} to represent the name of the player who died and {killer} for the killer's name (if applicable)." - }) + "# Use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." public List consolePostDeathCommands = List.of( "broadcast {player} has died in combat!" ); From 13d9c094b592d6c5b2e5438a2d36f0c31a52ff4f Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:58:23 +0100 Subject: [PATCH 04/13] fix build --- .../combat/config/implementation/CommandSettings.java | 1 + 1 file changed, 1 insertion(+) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index 7cea010e..a97bea1e 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -27,6 +27,7 @@ public class CommandSettings extends OkaeriConfig { @Comment({ "# List of commands that will be executed from console after player death.", "# Use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." + }) public List consolePostDeathCommands = List.of( "broadcast {player} has died in combat!" ); From 911ef7bb100731e784be877122d25cc93f4ea4a3 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:01:08 +0100 Subject: [PATCH 05/13] adjust to gemini's suggestion --- .../combat/config/implementation/CommandSettings.java | 3 +++ .../eternalcode/combat/fight/death/DeathCommandController.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index a97bea1e..f4534b50 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -56,4 +56,7 @@ public class CommandSettings extends OkaeriConfig { @Comment("# When this is set to true, the plugin will only execute the post-death commands if the players were tagged") public boolean onlyExecuteIfTagged = true; + + @Comment("# The returned string when the killer is unknown") + public String unknownKillerPlaceholder = "Unknown"; } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index 087e542d..e9c2877b 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -134,7 +134,7 @@ private void executeDeathCommands(Player deadPlayer) { private String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); - return killer != null ? killer.getName() : "Unknown"; + return killer != null ? killer.getName() : this.config.commands.unknownKillerPlaceholder; } private Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { From ce87394d6d49760f0a4a73e4eec9f9605da2f122 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:11:47 +0100 Subject: [PATCH 06/13] Remove CauseOfTag.LOGOUT from the check --- .../eternalcode/combat/fight/death/DeathCommandController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index e9c2877b..98676b07 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -41,7 +41,7 @@ void onPlayerUntag(FightUntagEvent event) { UUID playerUUID = event.getPlayer(); CauseOfUnTag cause = event.getCause(); - if (cause != CauseOfUnTag.DEATH && cause != CauseOfUnTag.DEATH_BY_PLAYER && cause != CauseOfUnTag.LOGOUT) { + if (cause != CauseOfUnTag.DEATH && cause != CauseOfUnTag.DEATH_BY_PLAYER) { return; } From 356481e415ca77b8a976c7b5cdc8713dd8a3cc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 15 Mar 2026 17:57:35 +0100 Subject: [PATCH 07/13] Update eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com> --- .../eternalcode/combat/fight/death/DeathCommandController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index 98676b07..cf14ac66 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -109,7 +109,7 @@ private void executeDeathCommands(Player deadPlayer) { } for (String command : this.config.commands.deadPostDeathCommands) { - String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); + String commandReplaced = this.replacePlaceholders(command, deadPlayerName, killerName); if (this.config.commands.deferDeadAfterRespawn) { deferred.add(new PendingCommand(CommandSource.DEAD_PLAYER, resolved)); } else { From 2a99c851deefb47487767c965f20f8352d492d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 15 Mar 2026 17:57:58 +0100 Subject: [PATCH 08/13] Update eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com> --- .../combat/fight/death/DeathCommandController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index cf14ac66..a4d69b0c 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -133,8 +133,9 @@ private void executeDeathCommands(Player deadPlayer) { private String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { - Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); - return killer != null ? killer.getName() : this.config.commands.unknownKillerPlaceholder; +return Optional.ofNullable(this.resolveKiller(deadPlayerUUID, deadPlayer)) + .map(Player::getName) + .orElse(this.config.commands.unknownKillerPlaceholder); } private Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { From 320dd90a6f80f34f0d2648522d09a457776b97b7 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 15 Mar 2026 18:05:01 +0100 Subject: [PATCH 09/13] Adjust to Mike's suggestions. Simplify logic --- .../implementation/CommandSettings.java | 30 ++--- .../fight/death/DeathCommandController.java | 109 ++++++++---------- 2 files changed, 54 insertions(+), 85 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index f4534b50..856d1394 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -24,27 +24,18 @@ public class CommandSettings extends OkaeriConfig { "tpaccept" ); - @Comment({ - "# List of commands that will be executed from console after player death.", - "# Use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." - }) - public List consolePostDeathCommands = List.of( - "broadcast {player} has died in combat!" - ); + public PostDeathSettings onDeathInCombat = new PostDeathSettings(); - @Comment("# When this is set to true, the plugin will execute the console commands only after the dead player has respawned.") - public boolean deferConsoleAfterRespawn = false; + public PostDeathSettings onAnyDeath = new PostDeathSettings(); - @Comment({ - "# List of commands that will be executed from the dead player's perspective after death.", - "# Use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." - }) - public List deadPostDeathCommands = List.of( - "say You have died in combat!" - ); + public PostDeathSettings afterRespawn = new PostDeathSettings(); - @Comment("# When this is set to true, the plugin will execute the commands above only after the dead player has respawned.") - public boolean deferDeadAfterRespawn = true; + public PostDeathSettings onUntag = new PostDeathSettings(); + + public static class PostDeathSettings extends OkaeriConfig { + public List console = List.of(); + public List player = List.of(); + } @Comment({ "# List of commands that will be executed from the killer's perspective after killing a player.", @@ -54,9 +45,6 @@ public class CommandSettings extends OkaeriConfig { "say You have killed {player} in combat!" ); - @Comment("# When this is set to true, the plugin will only execute the post-death commands if the players were tagged") - public boolean onlyExecuteIfTagged = true; - @Comment("# The returned string when the killer is unknown") public String unknownKillerPlaceholder = "Unknown"; } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index 98676b07..d1eebaa7 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -1,5 +1,6 @@ package com.eternalcode.combat.fight.death; +import com.eternalcode.combat.config.implementation.CommandSettings; import com.eternalcode.combat.config.implementation.PluginConfig; import com.eternalcode.combat.fight.FightManager; import com.eternalcode.combat.fight.FightTag; @@ -13,9 +14,7 @@ import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerRespawnEvent; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -27,7 +26,7 @@ public class DeathCommandController implements Listener { private final FightManager fightManager; private final Server server; - private final Map> pendingCommands = new ConcurrentHashMap<>(); + private final Map killerNames = new ConcurrentHashMap<>(); private final Set handledByUntag = Collections.newSetFromMap(new ConcurrentHashMap<>()); public DeathCommandController(PluginConfig config, FightManager fightManager, Server server) { @@ -40,35 +39,39 @@ public DeathCommandController(PluginConfig config, FightManager fightManager, Se void onPlayerUntag(FightUntagEvent event) { UUID playerUUID = event.getPlayer(); CauseOfUnTag cause = event.getCause(); + Player player = this.server.getPlayer(playerUUID); - if (cause != CauseOfUnTag.DEATH && cause != CauseOfUnTag.DEATH_BY_PLAYER) { + if (player == null) { return; } - Player deadPlayer = this.server.getPlayer(playerUUID); - - if (deadPlayer == null) { + if (cause == CauseOfUnTag.DEATH || cause == CauseOfUnTag.DEATH_BY_PLAYER) { + String killerName = this.resolveKillerName(playerUUID, player); + this.handleDeathInCombat(player, killerName); + this.handledByUntag.add(playerUUID); + this.killerNames.put(playerUUID, killerName); return; } - - this.handledByUntag.add(playerUUID); - this.executeDeathCommands(deadPlayer); + this.handleUntag(player); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) void onPlayerDeath(PlayerDeathEvent event) { - if (this.config.commands.onlyExecuteIfTagged) { - return; - } + Player player = event.getEntity(); + UUID playerUUID = player.getUniqueId(); + String killerName = this.resolveKillerName(playerUUID, player); + + this.killerNames.putIfAbsent(playerUUID, killerName); - Player deadPlayer = event.getEntity(); - UUID playerUUID = deadPlayer.getUniqueId(); + this.handleAnyDeath(player, killerName); if (this.handledByUntag.remove(playerUUID)) { return; } - this.executeDeathCommands(deadPlayer); + if (this.fightManager.isInCombat(playerUUID)) { + this.handleDeathInCombat(player, killerName); + } } @EventHandler(priority = EventPriority.MONITOR) @@ -78,59 +81,45 @@ void onPlayerRespawn(PlayerRespawnEvent event) { this.handledByUntag.remove(playerUUID); - List commands = this.pendingCommands.remove(playerUUID); - - if (commands == null) { - return; + String killerName = this.killerNames.remove(playerUUID); + if (killerName == null) { + killerName = this.config.commands.unknownKillerPlaceholder; } - for (PendingCommand pending : commands) { - switch (pending.executor()) { - case CONSOLE -> this.server.dispatchCommand(this.server.getConsoleSender(), pending.command()); - case DEAD_PLAYER -> this.server.dispatchCommand(player, pending.command()); - } - } + this.dispatch(this.config.commands.afterRespawn, player, killerName); } - private void executeDeathCommands(Player deadPlayer) { - UUID playerUUID = deadPlayer.getUniqueId(); - String deadPlayerName = deadPlayer.getName(); - String killerName = this.resolveKillerName(playerUUID, deadPlayer); - - List deferred = new ArrayList<>(); - - for (String command : this.config.commands.consolePostDeathCommands) { - String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); - if (this.config.commands.deferConsoleAfterRespawn) { - deferred.add(new PendingCommand(CommandSource.CONSOLE, resolved)); - } else { - this.server.dispatchCommand(this.server.getConsoleSender(), resolved); - } - } - - for (String command : this.config.commands.deadPostDeathCommands) { - String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); - if (this.config.commands.deferDeadAfterRespawn) { - deferred.add(new PendingCommand(CommandSource.DEAD_PLAYER, resolved)); - } else { - this.server.dispatchCommand(deadPlayer, resolved); - } - } - - Player killer = this.resolveKiller(playerUUID, deadPlayer); + private void handleDeathInCombat(Player player, String killerName) { + this.dispatch(this.config.commands.onDeathInCombat, player, killerName); + Player killer = this.resolveKiller(player.getUniqueId(), player); if (killer != null) { for (String command : this.config.commands.killerPostDeathCommands) { - String resolved = this.replacePlaceholders(command, deadPlayerName, killerName); + String resolved = this.replacePlaceholders(command, player.getName(), killerName); this.server.dispatchCommand(killer, resolved); } } + } - if (!deferred.isEmpty()) { - this.pendingCommands.put(playerUUID, deferred); - } + private void handleAnyDeath(Player player, String killerName) { + this.dispatch(this.config.commands.onAnyDeath, player, killerName); } + private void handleUntag(Player player) { + this.dispatch(this.config.commands.onUntag, player, this.config.commands.unknownKillerPlaceholder); + } + + private void dispatch(CommandSettings.PostDeathSettings settings, Player player, String killerName) { + String playerName = player.getName(); + settings.console.forEach(command -> { + String resolved = this.replacePlaceholders(command, playerName, killerName); + this.server.dispatchCommand(this.server.getConsoleSender(), resolved); + }); + settings.player.forEach(command -> { + String resolved = this.replacePlaceholders(command, playerName, killerName); + this.server.dispatchCommand(player, resolved); + }); + } private String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); @@ -158,12 +147,4 @@ private String replacePlaceholders(String command, String playerName, String kil .replace("{player}", playerName) .replace("{killer}", killerName); } - - private enum CommandSource { - CONSOLE, - DEAD_PLAYER - } - - private record PendingCommand(CommandSource executor, String command) { - } } From 15b2267837b727f461811ce265e3c80fafa70f50 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 22 Mar 2026 08:56:19 +0100 Subject: [PATCH 10/13] fix build --- .../src/main/java/com/eternalcode/combat/CombatPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8dafcb17..20ad260e 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -24,7 +24,8 @@ import com.eternalcode.combat.fight.controller.FightTagController; import com.eternalcode.combat.fight.controller.FightUnTagController; import com.eternalcode.combat.fight.death.DeathCommandController; -import com.eternalcode.combat.fight.death.DeathEffectController; +import com.eternalcode.combat.fight.death.DeathFlareController; +import com.eternalcode.combat.fight.death.DeathLightningController; import com.eternalcode.combat.fight.drop.DropController; import com.eternalcode.combat.fight.drop.DropKeepInventoryService; import com.eternalcode.combat.fight.drop.DropKeepInventoryServiceImpl; @@ -183,7 +184,6 @@ public void onEnable() { new FightBypassCreativeController(server, pluginConfig), new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server), new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService), - new DeathEffectController(pluginConfig), new DeathCommandController(pluginConfig, this.fightManager, server), new DeathFlareController(pluginConfig, server, scheduler, this), new DeathLightningController(pluginConfig, server), From 115f8bbbebda371ec5d180df55f054c447ef69ed Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 22 Mar 2026 08:56:55 +0100 Subject: [PATCH 11/13] Change EternalCore version to latest stable --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 10e9ed35..15584b9d 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -34,7 +34,7 @@ object Versions { const val PACKETEVENTS = "2.11.1" const val WORLDGUARD = "7.0.15-beta-01" const val LUCKPERMS = "5.5.17" - const val ETERNALCORE = "2.0.1-SNAPSHOT+12" + const val ETERNALCORE = "2.0.0" } From a60635856e1348da8109f259f7c6cf7dc4258796 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 22 Mar 2026 09:01:16 +0100 Subject: [PATCH 12/13] Adjust to DMK's suggestion --- .../com/eternalcode/combat/CombatPlugin.java | 9 +- .../fight/death/DeathCommandController.java | 122 +----------------- .../fight/death/DeathCommandExecutor.java | 38 ++++++ .../fight/death/DeathCommandService.java | 84 ++++++++++++ .../combat/fight/death/KillerResolver.java | 44 +++++++ 5 files changed, 181 insertions(+), 116 deletions(-) create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java create mode 100644 eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.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 20ad260e..6adfe4bc 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -24,8 +24,11 @@ import com.eternalcode.combat.fight.controller.FightTagController; import com.eternalcode.combat.fight.controller.FightUnTagController; import com.eternalcode.combat.fight.death.DeathCommandController; +import com.eternalcode.combat.fight.death.DeathCommandExecutor; +import com.eternalcode.combat.fight.death.DeathCommandService; import com.eternalcode.combat.fight.death.DeathFlareController; import com.eternalcode.combat.fight.death.DeathLightningController; +import com.eternalcode.combat.fight.death.KillerResolver; import com.eternalcode.combat.fight.drop.DropController; import com.eternalcode.combat.fight.drop.DropKeepInventoryService; import com.eternalcode.combat.fight.drop.DropKeepInventoryServiceImpl; @@ -176,6 +179,10 @@ public void onEnable() { new PlayersHealthDropModifier(pluginConfig.drop, logoutService) ).forEach(this.dropService::registerModifier); + KillerResolver killerResolver = new KillerResolver(this.fightManager, server, pluginConfig); + DeathCommandExecutor deathCommandExecutor = new DeathCommandExecutor(server); + DeathCommandService deathCommandService = new DeathCommandService(pluginConfig, this.fightManager, killerResolver, deathCommandExecutor); + eventManager.subscribe( new FightTagController(this.fightManager, pluginConfig), new FightUnTagController(this.fightManager, pluginConfig, logoutService), @@ -184,7 +191,7 @@ public void onEnable() { new FightBypassCreativeController(server, pluginConfig), new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server), new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService), - new DeathCommandController(pluginConfig, this.fightManager, server), + new DeathCommandController(deathCommandService, server), new DeathFlareController(pluginConfig, server, scheduler, this), new DeathLightningController(pluginConfig, server), new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage), diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java index d1eebaa7..c7a42d4a 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandController.java @@ -1,10 +1,5 @@ package com.eternalcode.combat.fight.death; -import com.eternalcode.combat.config.implementation.CommandSettings; -import com.eternalcode.combat.config.implementation.PluginConfig; -import com.eternalcode.combat.fight.FightManager; -import com.eternalcode.combat.fight.FightTag; -import com.eternalcode.combat.fight.event.CauseOfUnTag; import com.eternalcode.combat.fight.event.FightUntagEvent; import org.bukkit.Server; import org.bukkit.entity.Player; @@ -14,137 +9,34 @@ import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerRespawnEvent; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - public class DeathCommandController implements Listener { - private final PluginConfig config; - private final FightManager fightManager; + private final DeathCommandService deathCommandService; private final Server server; - private final Map killerNames = new ConcurrentHashMap<>(); - private final Set handledByUntag = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - public DeathCommandController(PluginConfig config, FightManager fightManager, Server server) { - this.config = config; - this.fightManager = fightManager; + public DeathCommandController(DeathCommandService deathCommandService, Server server) { + this.deathCommandService = deathCommandService; this.server = server; } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) void onPlayerUntag(FightUntagEvent event) { - UUID playerUUID = event.getPlayer(); - CauseOfUnTag cause = event.getCause(); - Player player = this.server.getPlayer(playerUUID); + Player player = this.server.getPlayer(event.getPlayer()); if (player == null) { return; } - if (cause == CauseOfUnTag.DEATH || cause == CauseOfUnTag.DEATH_BY_PLAYER) { - String killerName = this.resolveKillerName(playerUUID, player); - this.handleDeathInCombat(player, killerName); - this.handledByUntag.add(playerUUID); - this.killerNames.put(playerUUID, killerName); - return; - } - this.handleUntag(player); + this.deathCommandService.handleUntag(player, event.getCause()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) void onPlayerDeath(PlayerDeathEvent event) { - Player player = event.getEntity(); - UUID playerUUID = player.getUniqueId(); - String killerName = this.resolveKillerName(playerUUID, player); - - this.killerNames.putIfAbsent(playerUUID, killerName); - - this.handleAnyDeath(player, killerName); - - if (this.handledByUntag.remove(playerUUID)) { - return; - } - - if (this.fightManager.isInCombat(playerUUID)) { - this.handleDeathInCombat(player, killerName); - } + this.deathCommandService.handleDeath(event.getEntity()); } @EventHandler(priority = EventPriority.MONITOR) void onPlayerRespawn(PlayerRespawnEvent event) { - Player player = event.getPlayer(); - UUID playerUUID = player.getUniqueId(); - - this.handledByUntag.remove(playerUUID); - - String killerName = this.killerNames.remove(playerUUID); - if (killerName == null) { - killerName = this.config.commands.unknownKillerPlaceholder; - } - - this.dispatch(this.config.commands.afterRespawn, player, killerName); - } - - private void handleDeathInCombat(Player player, String killerName) { - this.dispatch(this.config.commands.onDeathInCombat, player, killerName); - - Player killer = this.resolveKiller(player.getUniqueId(), player); - if (killer != null) { - for (String command : this.config.commands.killerPostDeathCommands) { - String resolved = this.replacePlaceholders(command, player.getName(), killerName); - this.server.dispatchCommand(killer, resolved); - } - } - } - - private void handleAnyDeath(Player player, String killerName) { - this.dispatch(this.config.commands.onAnyDeath, player, killerName); - } - - private void handleUntag(Player player) { - this.dispatch(this.config.commands.onUntag, player, this.config.commands.unknownKillerPlaceholder); - } - - private void dispatch(CommandSettings.PostDeathSettings settings, Player player, String killerName) { - String playerName = player.getName(); - settings.console.forEach(command -> { - String resolved = this.replacePlaceholders(command, playerName, killerName); - this.server.dispatchCommand(this.server.getConsoleSender(), resolved); - }); - settings.player.forEach(command -> { - String resolved = this.replacePlaceholders(command, playerName, killerName); - this.server.dispatchCommand(player, resolved); - }); - } - - private String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { - Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); - return killer != null ? killer.getName() : this.config.commands.unknownKillerPlaceholder; - } - - private Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { - Player killer = deadPlayer.getKiller(); - - if (killer != null) { - return killer; - } - - FightTag tag = this.fightManager.getTag(deadPlayerUUID); - - if (tag != null && tag.getTagger() != null) { - return this.server.getPlayer(tag.getTagger()); - } - - return null; - } - - private String replacePlaceholders(String command, String playerName, String killerName) { - return command - .replace("{player}", playerName) - .replace("{killer}", killerName); + this.deathCommandService.handleRespawn(event.getPlayer()); } } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java new file mode 100644 index 00000000..1660b536 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java @@ -0,0 +1,38 @@ +package com.eternalcode.combat.fight.death; + +import com.eternalcode.combat.config.implementation.CommandSettings; +import org.bukkit.Server; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public class DeathCommandExecutor { + + private final Server server; + + public DeathCommandExecutor(Server server) { + this.server = server; + } + + public void dispatch(CommandSettings.PostDeathSettings settings, Player player, String killerName) { + String playerName = player.getName(); + + this.dispatch(settings.console, this.server.getConsoleSender(), playerName, killerName); + this.dispatch(settings.player, player, playerName, killerName); + } + + public void dispatch(Collection commands, CommandSender sender, String playerName, String killerName) { + for (String command : commands) { + String resolved = this.replacePlaceholders(command, playerName, killerName); + this.server.dispatchCommand(sender, resolved); + } + } + + private String replacePlaceholders(String command, String playerName, String killerName) { + return command + .replace("{player}", playerName) + .replace("{killer}", killerName); + } +} + diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java new file mode 100644 index 00000000..b3b03158 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java @@ -0,0 +1,84 @@ +package com.eternalcode.combat.fight.death; + +import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.event.CauseOfUnTag; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class DeathCommandService { + + private final PluginConfig config; + private final FightManager fightManager; + private final KillerResolver killerResolver; + private final DeathCommandExecutor executor; + + private final Map killerNames = new ConcurrentHashMap<>(); + private final Set handledByUntag = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + public DeathCommandService(PluginConfig config, FightManager fightManager, KillerResolver killerResolver, DeathCommandExecutor executor) { + this.config = config; + this.fightManager = fightManager; + this.killerResolver = killerResolver; + this.executor = executor; + } + + public void handleUntag(Player player, CauseOfUnTag cause) { + UUID playerUUID = player.getUniqueId(); + + if (cause == CauseOfUnTag.DEATH || cause == CauseOfUnTag.DEATH_BY_PLAYER) { + String killerName = this.killerResolver.resolveKillerName(playerUUID, player); + this.handleDeathInCombat(player, killerName); + this.handledByUntag.add(playerUUID); + this.killerNames.put(playerUUID, killerName); + return; + } + + this.executor.dispatch(this.config.commands.onUntag, player, this.config.commands.unknownKillerPlaceholder); + } + + public void handleDeath(Player player) { + UUID playerUUID = player.getUniqueId(); + String killerName = this.killerResolver.resolveKillerName(playerUUID, player); + + this.killerNames.putIfAbsent(playerUUID, killerName); + + this.executor.dispatch(this.config.commands.onAnyDeath, player, killerName); + + if (this.handledByUntag.remove(playerUUID)) { + return; + } + + if (this.fightManager.isInCombat(playerUUID)) { + this.handleDeathInCombat(player, killerName); + } + } + + public void handleRespawn(Player player) { + UUID playerUUID = player.getUniqueId(); + + this.handledByUntag.remove(playerUUID); + + String killerName = this.killerNames.remove(playerUUID); + if (killerName == null) { + killerName = this.config.commands.unknownKillerPlaceholder; + } + + this.executor.dispatch(this.config.commands.afterRespawn, player, killerName); + } + + private void handleDeathInCombat(Player player, String killerName) { + this.executor.dispatch(this.config.commands.onDeathInCombat, player, killerName); + + Player killer = this.killerResolver.resolveKiller(player.getUniqueId(), player); + if (killer != null) { + this.executor.dispatch(this.config.commands.killerPostDeathCommands, killer, player.getName(), killerName); + } + } +} + diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java new file mode 100644 index 00000000..6c27f714 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java @@ -0,0 +1,44 @@ +package com.eternalcode.combat.fight.death; + +import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.FightTag; +import org.bukkit.Server; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class KillerResolver { + + private final FightManager fightManager; + private final Server server; + private final PluginConfig config; + + public KillerResolver(FightManager fightManager, Server server, PluginConfig config) { + this.fightManager = fightManager; + this.server = server; + this.config = config; + } + + public Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { + Player killer = deadPlayer.getKiller(); + + if (killer != null) { + return killer; + } + + FightTag tag = this.fightManager.getTag(deadPlayerUUID); + + if (tag != null && tag.getTagger() != null) { + return this.server.getPlayer(tag.getTagger()); + } + + return null; + } + + public String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { + Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); + return killer != null ? killer.getName() : this.config.commands.unknownKillerPlaceholder; + } +} + From dc0724b07d8e7d5e6571826bc263d8e4e1037841 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 22 Mar 2026 09:29:03 +0100 Subject: [PATCH 13/13] Move to DeathSettings --- .../implementation/CommandSettings.java | 24 ------------- .../fight/death/DeathCommandExecutor.java | 4 +-- .../fight/death/DeathCommandService.java | 12 +++---- .../combat/fight/death/DeathSettings.java | 35 +++++++++++++++++++ .../combat/fight/death/KillerResolver.java | 2 +- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java index 856d1394..d0819515 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/CommandSettings.java @@ -23,28 +23,4 @@ public class CommandSettings extends OkaeriConfig { "tpa", "tpaccept" ); - - public PostDeathSettings onDeathInCombat = new PostDeathSettings(); - - public PostDeathSettings onAnyDeath = new PostDeathSettings(); - - public PostDeathSettings afterRespawn = new PostDeathSettings(); - - public PostDeathSettings onUntag = new PostDeathSettings(); - - public static class PostDeathSettings extends OkaeriConfig { - public List console = List.of(); - public List player = List.of(); - } - - @Comment({ - "# List of commands that will be executed from the killer's perspective after killing a player.", - "# Use {player} to represent the name of the player who was killed and {killer} for the killer's name (if applicable)." - }) - public List killerPostDeathCommands = List.of( - "say You have killed {player} in combat!" - ); - - @Comment("# The returned string when the killer is unknown") - public String unknownKillerPlaceholder = "Unknown"; } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java index 1660b536..01838e5c 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandExecutor.java @@ -1,6 +1,5 @@ package com.eternalcode.combat.fight.death; -import com.eternalcode.combat.config.implementation.CommandSettings; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -15,7 +14,7 @@ public DeathCommandExecutor(Server server) { this.server = server; } - public void dispatch(CommandSettings.PostDeathSettings settings, Player player, String killerName) { + public void dispatch(DeathSettings.PostDeathCommandSettings.PostDeathCommands settings, Player player, String killerName) { String playerName = player.getName(); this.dispatch(settings.console, this.server.getConsoleSender(), playerName, killerName); @@ -35,4 +34,3 @@ private String replacePlaceholders(String command, String playerName, String kil .replace("{killer}", killerName); } } - diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java index b3b03158..48ad5f45 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathCommandService.java @@ -39,7 +39,7 @@ public void handleUntag(Player player, CauseOfUnTag cause) { return; } - this.executor.dispatch(this.config.commands.onUntag, player, this.config.commands.unknownKillerPlaceholder); + this.executor.dispatch(this.config.death.postDeathCommands.onUntag, player, this.config.death.postDeathCommands.unknownKillerPlaceholder); } public void handleDeath(Player player) { @@ -48,7 +48,7 @@ public void handleDeath(Player player) { this.killerNames.putIfAbsent(playerUUID, killerName); - this.executor.dispatch(this.config.commands.onAnyDeath, player, killerName); + this.executor.dispatch(this.config.death.postDeathCommands.onAnyDeath, player, killerName); if (this.handledByUntag.remove(playerUUID)) { return; @@ -66,18 +66,18 @@ public void handleRespawn(Player player) { String killerName = this.killerNames.remove(playerUUID); if (killerName == null) { - killerName = this.config.commands.unknownKillerPlaceholder; + killerName = this.config.death.postDeathCommands.unknownKillerPlaceholder; } - this.executor.dispatch(this.config.commands.afterRespawn, player, killerName); + this.executor.dispatch(this.config.death.postDeathCommands.afterRespawn, player, killerName); } private void handleDeathInCombat(Player player, String killerName) { - this.executor.dispatch(this.config.commands.onDeathInCombat, player, killerName); + this.executor.dispatch(this.config.death.postDeathCommands.onDeathInCombat, player, killerName); Player killer = this.killerResolver.resolveKiller(player.getUniqueId(), player); if (killer != null) { - this.executor.dispatch(this.config.commands.killerPostDeathCommands, killer, player.getName(), killerName); + this.executor.dispatch(this.config.death.postDeathCommands.killerPostDeathCommands, killer, player.getName(), killerName); } } } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathSettings.java index 8b4c8f1b..c8c48b1e 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/DeathSettings.java @@ -5,6 +5,8 @@ import eu.okaeri.configs.annotation.Comment; import org.bukkit.FireworkEffect; +import java.util.List; + public class DeathSettings extends OkaeriConfig { @Comment({ @@ -74,4 +76,37 @@ public static class FlareSettings extends OkaeriConfig { public int secondaryParticleCount = 3; } + + @Comment({ + "Commands that will be executed after a player's death.", + "You can use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)." + }) + public PostDeathCommandSettings postDeathCommands = new PostDeathCommandSettings(); + + public static class PostDeathCommandSettings extends OkaeriConfig { + + public PostDeathCommands onDeathInCombat = new PostDeathCommands(); + + public PostDeathCommands onAnyDeath = new PostDeathCommands(); + + public PostDeathCommands afterRespawn = new PostDeathCommands(); + + public PostDeathCommands onUntag = new PostDeathCommands(); + + public static class PostDeathCommands extends OkaeriConfig { + public List console = List.of(); + public List player = List.of(); + } + + @Comment({ + "# List of commands that will be executed from the killer's perspective after killing a player.", + "# Use {player} to represent the name of the player who was killed and {killer} for the killer's name (if applicable)." + }) + public List killerPostDeathCommands = List.of( + "say You have killed {player} in combat!" + ); + + @Comment("# The returned string when the killer is unknown") + public String unknownKillerPlaceholder = "Unknown"; + } } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java index 6c27f714..814f6449 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/death/KillerResolver.java @@ -38,7 +38,7 @@ public Player resolveKiller(UUID deadPlayerUUID, Player deadPlayer) { public String resolveKillerName(UUID deadPlayerUUID, Player deadPlayer) { Player killer = this.resolveKiller(deadPlayerUUID, deadPlayer); - return killer != null ? killer.getName() : this.config.commands.unknownKillerPlaceholder; + return killer != null ? killer.getName() : this.config.death.postDeathCommands.unknownKillerPlaceholder; } }