diff --git a/README.md b/README.md
index 9d507ca2..b0eed37e 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ fair, heart-pounding battles that keep players on their toes. Here’s a rundown
in action:
-- **Customize combat experience**
+- **Customize combat experience**
Add custom effects to players in combat or death. Everything should be configurable and user-friendly:
@@ -87,6 +87,8 @@ Control who can use EternalCombat’s powerful features with these permissions:
| `eternalcombat.status` | Check a player’s combat status with `/combatlog status `. |
| `eternalcombat.tag` | Start a fight between players using `/combatlog tag [player2]`. |
| `eternalcombat.untag` | Remove a player from combat with `/combatlog untag `. |
+| `eternalcombat.untagall` | Remove all players from combat with `/combatlog untagall`. |
+| `eternalcombat.stats` | View combat statistics with `/combatlog stats`. |
| `eternalcombat.reload` | Reload the plugin with `/combatlog reload`. |
| `eternalcombat.receiveupdates` | Receive notifications about new plugin versions on join. |
| `eternalcombat.bypass` | When exclude `excludeAdminsFromCombat` is set to `true` users with this permission will not be tagged |
diff --git a/eternalcombat-plugin/build.gradle.kts b/eternalcombat-plugin/build.gradle.kts
index 6edfab7f..3cbf3602 100644
--- a/eternalcombat-plugin/build.gradle.kts
+++ b/eternalcombat-plugin/build.gradle.kts
@@ -96,7 +96,7 @@ 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)
diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/MessagesSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/MessagesSettings.java
index d5f69e21..d7a8849a 100644
--- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/MessagesSettings.java
+++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/MessagesSettings.java
@@ -8,189 +8,189 @@
public class MessagesSettings extends OkaeriConfig {
@Comment({
- "# Customize messages related to admin commands and notifications.",
- "# These messages are displayed to server administrators."
+ "# Customize messages related to admin commands and notifications.",
+ "# These messages are displayed to server administrators."
})
public AdminMessages admin = new AdminMessages();
@Comment({
- " ",
- "# Configure the combat log notification displayed to players.",
- "# You can use the {TIME} variable to display the remaining combat time.",
- " ",
+ " ",
+ "# Configure the combat log notification displayed to players.",
+ "# You can use the {TIME} variable to display the remaining combat time.",
+ " ",
})
public Notice combatNotification = BukkitNotice.builder()
- .actionBar("Combat ends in: {TIME}")
- .build();
+ .actionBar("Combat ends in: {TIME}")
+ .build();
@Comment({
- "# Would you like to display milliseconds instead of seconds in combat notification "
+ "# Would you like to display milliseconds instead of seconds in combat notification "
})
public boolean withoutMillis = true;
@Comment({
- "# Message displayed when a player lacks permission to execute a command.",
- "# The {PERMISSION} placeholder is replaced with the required permission."
+ "# Message displayed when a player lacks permission to execute a command.",
+ "# The {PERMISSION} placeholder is replaced with the required permission."
})
public Notice noPermission = Notice.chat(
- "You don't have permission ({PERMISSION}) to perform this command!");
+ "You don't have permission ({PERMISSION}) to perform this command!");
@Comment({
- "# Message displayed when a specified player is not found.",
- "# This message is shown when a command targets a player who is not online or does not exist."
+ "# Message displayed when a specified player is not found.",
+ "# This message is shown when a command targets a player who is not online or does not exist."
})
- public Notice playerNotFound =
- Notice.chat("The specified player could not be found!");
+ public Notice playerNotFound = Notice
+ .chat("The specified player could not be found!");
@Comment({
- "# Message displayed when a player enters combat.",
- "# This message warns the player not to leave the server while in combat."
+ "# Message displayed when a player enters combat.",
+ "# This message warns the player not to leave the server while in combat."
})
public Notice playerTagged = Notice.chat(
- "⚠ You are in combat! Do not leave the server!");
+ "⚠ You are in combat! Do not leave the server!");
@Comment({
- "# Message displayed when a player leaves combat.",
- "# This message informs the player that they can safely leave the server."
+ "# Message displayed when a player leaves combat.",
+ "# This message informs the player that they can safely leave the server."
})
public Notice playerUntagged = Notice.chat(
- "✌ Combat ended! You can now safely leave!");
+ "✌ Combat ended! You can now safely leave!");
@Comment({
- "# Broadcast message displayed when a player logs out during combat.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Broadcast message displayed when a player logs out during combat.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
- public Notice playerLoggedOutDuringCombat =
- Notice.chat("⚠ {PLAYER} logged off during combat!");
+ public Notice playerLoggedOutDuringCombat = Notice
+ .chat("⚠ {PLAYER} logged off during combat!");
@Comment({
- "# Message displayed when a player attempts to use a disabled command during combat.",
- "# This message informs the player that the command is prohibited while in combat."
+ "# Message displayed when a player attempts to use a disabled command during combat.",
+ "# This message informs the player that the command is prohibited while in combat."
})
public Notice commandDisabledDuringCombat = Notice.chat(
- "⚠ Command blocked! Cannot use this during combat!");
+ "⚠ Command blocked! Cannot use this during combat!");
@Comment({
- "# Message displayed when a player uses a command with incorrect arguments.",
- "# The {USAGE} placeholder is replaced with the correct command syntax."
+ "# Message displayed when a player uses a command with incorrect arguments.",
+ "# The {USAGE} placeholder is replaced with the correct command syntax."
})
public Notice invalidCommandUsage = Notice.chat("Usage: {USAGE}");
@Comment({
- "# Message displayed when a player attempts to open their inventory during combat.",
- "# This message informs the player that inventory access is blocked while in combat."
+ "# Message displayed when a player attempts to open their inventory during combat.",
+ "# This message informs the player that inventory access is blocked while in combat."
})
public Notice inventoryBlockedDuringCombat = Notice.chat(
- "⚠ Inventory access is restricted during combat!");
+ "⚠ Inventory access is restricted during combat!");
@Comment({
- "# Message displayed when a player attempts to place a block during combat.",
- "# The {MODE} placeholder is replaced with the block placement mode (ABOVE/BELOW).",
- "# The {Y} placeholder is replaced with the Y coordinate set in the config."
+ "# Message displayed when a player attempts to place a block during combat.",
+ "# The {MODE} placeholder is replaced with the block placement mode (ABOVE/BELOW).",
+ "# The {Y} placeholder is replaced with the Y coordinate set in the config."
})
- public Notice blockPlacingBlockedDuringCombat =
- Notice.chat("⚠ Block placement {MODE} Y:{Y} is restricted!");
+ public Notice blockPlacingBlockedDuringCombat = Notice
+ .chat("⚠ Block placement {MODE} Y:{Y} is restricted!");
@Comment({
- "# Message sent to the player using fireworks when fireworks during elytra flight are disabled"
+ "# Message sent to the player using fireworks when fireworks during elytra flight are disabled"
})
- public Notice fireworksDisabled = Notice.actionbar("⚠ You can't use fireworks during combat ⚠");
-
+ public Notice fireworksDisabled = Notice
+ .actionbar("⚠ You can't use fireworks during combat ⚠");
+
@Comment({
- "# Message displayed when a player attempts to enter a restricted region during combat.",
- "# This message informs the player that they cannot enter the region while in combat."
+ "# Message displayed when a player attempts to enter a restricted region during combat.",
+ "# This message informs the player that they cannot enter the region while in combat."
})
public Notice cantEnterOnRegion = Notice.chat(
- "⚠ Restricted area! Cannot enter during combat!");
+ "⚠ Restricted area! Cannot enter during combat!");
public static class AdminMessages extends OkaeriConfig {
@Comment({
- "# Message displayed when the console attempts to use a player-only command.",
- "# This message informs the console that the command is not available for non-players."
+ "# Message displayed when the console attempts to use a player-only command.",
+ "# This message informs the console that the command is not available for non-players."
})
- public Notice onlyForPlayers =
- Notice.chat("❌ This command is player-only!");
+ public Notice onlyForPlayers = Notice.chat("❌ This command is player-only!");
@Comment({
- "# Message displayed to an admin when they tag a player.",
- "# The {PLAYER} placeholder is replaced with the tagged player's name."
+ "# Message displayed to an admin when they tag a player.",
+ "# The {PLAYER} placeholder is replaced with the tagged player's name."
})
- public Notice adminTagPlayer =
- Notice.chat("⚔ Tagged player: {PLAYER}");
+ public Notice adminTagPlayer = Notice
+ .chat("⚔ Tagged player: {PLAYER}");
@Comment({
- "# Message displayed when an admin tags multiple players.",
- "# The {FIRST_PLAYER} and {SECOND_PLAYER} placeholders are replaced with the players' names."
+ "# Message displayed when an admin tags multiple players.",
+ "# The {FIRST_PLAYER} and {SECOND_PLAYER} placeholders are replaced with the players' names."
})
public Notice adminTagMultiplePlayers = Notice.chat(
- "⚔ Tagged: {FIRST_PLAYER} and {SECOND_PLAYER}");
+ "⚔ Tagged: {FIRST_PLAYER} and {SECOND_PLAYER}");
@Comment({
- "# Message displayed to an admin when they remove a player from combat.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Message displayed to an admin when they remove a player from combat.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
public Notice adminUntagPlayer = Notice.chat(
- "✌ Removed {PLAYER} from combat");
+ "✌ Removed {PLAYER} from combat");
@Comment({
- "# Message displayed to an admin when they remove a player from combat.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Message displayed to an admin when they remove a player from combat.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
public Notice adminUntagAll = Notice.chat(
- "✌ Removed {COUNT} players from combat");
+ "✌ Removed {COUNT} players from combat");
@Comment({
- "# Message displayed when an admin attempts to untag a player who is not in combat.",
- "# This message informs the admin that the player is not currently in combat."
+ "# Message displayed when an admin attempts to untag a player who is not in combat.",
+ "# This message informs the admin that the player is not currently in combat."
})
- public Notice adminPlayerNotInCombat =
- Notice.chat("❌ {PLAYER} is not in combat!");
+ public Notice adminPlayerNotInCombat = Notice
+ .chat("❌ {PLAYER} is not in combat!");
@Comment({
- "# Message displayed when a player is in combat.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Message displayed when a player is in combat.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
- public Notice playerInCombat =
- Notice.chat("⚔ {PLAYER} is in combat!");
+ public Notice playerInCombat = Notice
+ .chat("⚔ {PLAYER} is in combat!");
@Comment({
- "# Message displayed when a player is not in combat.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Message displayed when a player is not in combat.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
- public Notice playerNotInCombat =
- Notice.chat("✌ {PLAYER} is safe");
+ public Notice playerNotInCombat = Notice
+ .chat("✌ {PLAYER} is safe");
@Comment({
- "# Message displayed when an admin attempts to tag themselves.",
- "# This message informs the admin that they cannot tag themselves."
+ "# Message displayed when an admin attempts to tag themselves.",
+ "# This message informs the admin that they cannot tag themselves."
})
public Notice adminCannotTagSelf = Notice.chat("❌ Cannot tag yourself!");
@Comment({
- "# Message displayed when an admin disables combat tagging for themselves.",
- "# The {TIME} placeholder is replaced with the remaining fight time."
+ "# Message displayed when an admin disables combat tagging for themselves.",
+ "# The {TIME} placeholder is replaced with the remaining fight time."
})
public Notice adminTagOutSelf = Notice.chat(
- "🛡 Self-protection active for {TIME}");
+ "🛡 Self-protection active for {TIME}");
@Comment({
- "# Message displayed when an admin disables combat tagging for another player.",
- "# The {PLAYER} placeholder is replaced with the player's name.",
- "# The {TIME} placeholder is replaced with the remaining fight time."
+ "# Message displayed when an admin disables combat tagging for another player.",
+ "# The {PLAYER} placeholder is replaced with the player's name.",
+ "# The {TIME} placeholder is replaced with the remaining fight time."
})
public Notice adminTagOut = Notice.chat(
- "🛡 Protected {PLAYER} for {TIME}");
+ "🛡 Protected {PLAYER} for {TIME}");
@Comment({
- "# Message displayed to a player when their combat tagging is disabled.",
- "# The {TIME} placeholder is replaced with the remaining fight time."
+ "# Message displayed to a player when their combat tagging is disabled.",
+ "# The {TIME} placeholder is replaced with the remaining fight time."
})
public Notice playerTagOut = Notice.chat(
- "🛡 Protection active for {TIME}");
+ "🛡 Protection active for {TIME}");
@Comment({
- "# Message displayed when an admin reenables combat tagging for a player.",
- "# The {PLAYER} placeholder is replaced with the player's name."
+ "# Message displayed when an admin reenables combat tagging for a player.",
+ "# The {PLAYER} placeholder is replaced with the player's name."
})
public Notice adminTagOutOff = Notice.chat(
"✌ Re-enabled tagging for {PLAYER}");
@@ -205,7 +205,14 @@ public static class AdminMessages extends OkaeriConfig {
"# Message displayed when an admin attempts to tag a player who has tag-out enabled.",
"# This message informs the admin that the player cannot be tagged at this time."
})
- public Notice adminTagOutCanceled =
- Notice.chat("❌ Player has tag-out protection!");
+ public Notice adminTagOutCanceled = Notice
+ .chat("❌ Player has tag-out protection!");
+
+ @Comment({
+ "# Message displayed when an admin checks combat statistics.",
+ "# The {COUNT} placeholder is replaced with the number of players currently in combat."
+ })
+ public Notice combatStats = Notice
+ .chat("⚔ Players in combat: {COUNT}");
}
}
diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTagCommand.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTagCommand.java
index 10cd2d3a..228f8288 100644
--- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTagCommand.java
+++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/FightTagCommand.java
@@ -16,10 +16,8 @@
import dev.rollczi.litecommands.annotations.priority.Priority;
import dev.rollczi.litecommands.annotations.priority.PriorityValue;
import java.time.Duration;
-import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
-
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -49,7 +47,6 @@ void status(@Context CommandSender sender, @Arg Player target) {
.placeholder("{PLAYER}", target.getName())
.viewer(sender)
.send();
-
}
@Execute(name = "tag")
@@ -74,7 +71,6 @@ void tag(@Context CommandSender sender, @Arg Player target) {
.placeholder("{PLAYER}", target.getName())
.viewer(sender)
.send();
-
}
@Execute(name = "tag")
@@ -122,7 +118,6 @@ void tagMultiple(@Context CommandSender sender, @Arg Player firstTarget, @Arg Pl
.placeholder("{SECOND_PLAYER}", secondTarget.getName())
.viewer(sender)
.send();
-
}
@Execute(name = "untag")
@@ -144,7 +139,6 @@ void untag(@Context CommandSender sender, @Arg Player target) {
return;
}
-
this.noticeService.create()
.notice(this.config.messagesSettings.admin.adminUntagPlayer)
.placeholder("{PLAYER}", target.getName())
@@ -169,13 +163,28 @@ void untagAll(@Context CommandSender sender) {
.send();
}
- private void tagoutReasonHandler(CommandSender sender, CancelTagReason cancelReason, MessagesSettings messagesSettings) {
+ @Execute(name = "stats")
+ @Permission("eternalcombat.stats")
+ void stats(@Context CommandSender sender) {
+ long activeCombatPlayers = this.fightManager.getFights().stream()
+ .filter(fightTag -> !fightTag.isExpired())
+ .count();
+
+ this.noticeService.create()
+ .notice(this.config.messagesSettings.admin.combatStats)
+ .placeholder("{COUNT}", String.valueOf(activeCombatPlayers))
+ .viewer(sender)
+ .send();
+ }
+
+ private void tagoutReasonHandler(
+ CommandSender sender, CancelTagReason cancelReason,
+ MessagesSettings messagesSettings) {
if (cancelReason == CancelTagReason.TAGOUT) {
this.noticeService.create()
.notice(messagesSettings.admin.adminTagOutCanceled)
.viewer(sender)
.send();
-
}
}
}