feat(commands): report aura progress
This commit is contained in:
@@ -17,3 +17,4 @@ description: Chronological record of material changes to the Spigot Creeper Fear
|
|||||||
- Completed US-002 with per-tier rank advancement, online aura state, creeper block protection, rank damage multipliers, and rank VI cancellation.
|
- Completed US-002 with per-tier rank advancement, online aura state, creeper block protection, rank damage multipliers, and rank VI cancellation.
|
||||||
- Completed US-003 with temporary configurable boss bars, current-tier progress presentation, full-screen rank-up titles, and maximum-rank hiding.
|
- Completed US-003 with temporary configurable boss bars, current-tier progress presentation, full-screen rank-up titles, and maximum-rank hiding.
|
||||||
- Extended US-001 so a self-destructing creeper awards deduplicated progress and normal feedback to every player its explosion hits.
|
- Extended US-001 so a self-destructing creeper awards deduplicated progress and normal feedback to every player its explosion hits.
|
||||||
|
- Completed US-004 with an asynchronous self-service progress command, ordinary-player permission, completion output, and command metadata.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
type: User Story
|
type: User Story
|
||||||
title: "US-004: Check personal progress"
|
title: "US-004: Check personal progress"
|
||||||
description: Let players request their current Creeper Aura rank and tier progress through a command.
|
description: Let players request their current Creeper Aura rank and tier progress through a command.
|
||||||
status: backlog
|
status: done
|
||||||
---
|
---
|
||||||
|
|
||||||
# US-004: Check personal progress
|
# US-004: Check personal progress
|
||||||
@@ -11,12 +11,12 @@ As a **player**, I want a command that reports my Creeper Aura progress so that
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] `/creeperaura progress` reports the player's current locked or ranked state and current-tier progress.
|
- [x] `/creeperaura progress` reports the player's current locked or ranked state and current-tier progress.
|
||||||
- [ ] Before rank VI, the response reports the next rank requirement and the number of additional kills needed.
|
- [x] Before rank VI, the response reports the next rank requirement and the number of additional kills needed.
|
||||||
- [ ] At rank VI, the response clearly reports that progression is complete.
|
- [x] At rank VI, the response clearly reports that progression is complete.
|
||||||
- [ ] The self-service command is available to ordinary players without administrative permission.
|
- [x] The self-service command is available to ordinary players without administrative permission.
|
||||||
- [ ] Console use, invalid arguments, and unavailable player data produce clear responses.
|
- [x] Console use, invalid arguments, and unavailable player data produce clear responses.
|
||||||
- [ ] Command usage is included in plugin help and command metadata.
|
- [x] Command usage is included in plugin help and command metadata.
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package games.dmg.creeperfear;
|
|||||||
|
|
||||||
import games.dmg.creeperfear.aura.AuraRules;
|
import games.dmg.creeperfear.aura.AuraRules;
|
||||||
import games.dmg.creeperfear.aura.CreeperAuraListener;
|
import games.dmg.creeperfear.aura.CreeperAuraListener;
|
||||||
|
import games.dmg.creeperfear.command.CreeperAuraCommand;
|
||||||
|
import games.dmg.creeperfear.command.ProgressMessages;
|
||||||
import games.dmg.creeperfear.feedback.ProgressDisplay;
|
import games.dmg.creeperfear.feedback.ProgressDisplay;
|
||||||
import games.dmg.creeperfear.feedback.ProgressFeedback;
|
import games.dmg.creeperfear.feedback.ProgressFeedback;
|
||||||
import games.dmg.creeperfear.listener.CreeperDeathListener;
|
import games.dmg.creeperfear.listener.CreeperDeathListener;
|
||||||
@@ -10,6 +12,7 @@ import games.dmg.creeperfear.listener.PlayerSessionListener;
|
|||||||
import games.dmg.creeperfear.progress.ProgressService;
|
import games.dmg.creeperfear.progress.ProgressService;
|
||||||
import games.dmg.creeperfear.progress.SqliteProgressRepository;
|
import games.dmg.creeperfear.progress.SqliteProgressRepository;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
@@ -34,6 +37,8 @@ public final class CreeperFearPlugin extends JavaPlugin {
|
|||||||
new PlayerSessionListener(progressService, getLogger()), this);
|
new PlayerSessionListener(progressService, getLogger()), this);
|
||||||
getServer().getPluginManager().registerEvents(
|
getServer().getPluginManager().registerEvents(
|
||||||
new CreeperAuraListener(progressService, auraRules), this);
|
new CreeperAuraListener(progressService, auraRules), this);
|
||||||
|
Objects.requireNonNull(getCommand("creeperaura"), "creeperaura command")
|
||||||
|
.setExecutor(new CreeperAuraCommand(this, progressService, new ProgressMessages(auraRules)));
|
||||||
getServer().getOnlinePlayers().forEach(player -> progressService.loadOnline(player.getUniqueId())
|
getServer().getOnlinePlayers().forEach(player -> progressService.loadOnline(player.getUniqueId())
|
||||||
.exceptionally(failure -> {
|
.exceptionally(failure -> {
|
||||||
getLogger().log(Level.SEVERE,
|
getLogger().log(Level.SEVERE,
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package games.dmg.creeperfear.command;
|
||||||
|
|
||||||
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
|
import games.dmg.creeperfear.progress.PlayerProgress;
|
||||||
|
import games.dmg.creeperfear.progress.ProgressService;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public final class CreeperAuraCommand implements CommandExecutor {
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
private final ProgressService progressService;
|
||||||
|
private final ProgressMessages messages;
|
||||||
|
|
||||||
|
public CreeperAuraCommand(JavaPlugin plugin, ProgressService progressService, ProgressMessages messages) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.progressService = progressService;
|
||||||
|
this.messages = messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
if (args.length != 1 || !args[0].equalsIgnoreCase("progress")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(sender instanceof Player player)) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "This form of the command can only be used by a player.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressService.find(player.getUniqueId()).whenComplete((stored, failure) ->
|
||||||
|
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||||
|
if (failure != null) {
|
||||||
|
plugin.getLogger().log(Level.SEVERE,
|
||||||
|
"Could not read Creeper Aura progress for " + player.getUniqueId(), failure);
|
||||||
|
sender.sendMessage(ChatColor.RED + "Creeper Aura progress is temporarily unavailable.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PlayerProgress progress = stored.orElseGet(() -> new PlayerProgress(
|
||||||
|
player.getUniqueId(), player.getName(), AuraRank.LOCKED, 0));
|
||||||
|
sender.sendMessage(ChatColor.GREEN + messages.describe(progress));
|
||||||
|
}));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package games.dmg.creeperfear.command;
|
||||||
|
|
||||||
|
import games.dmg.creeperfear.aura.AuraRules;
|
||||||
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
|
import games.dmg.creeperfear.progress.PlayerProgress;
|
||||||
|
|
||||||
|
public final class ProgressMessages {
|
||||||
|
private final AuraRules rules;
|
||||||
|
|
||||||
|
public ProgressMessages(AuraRules rules) {
|
||||||
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String describe(PlayerProgress progress) {
|
||||||
|
if (progress.rank().isMaximum()) {
|
||||||
|
return "Creeper Aura VI — maximum rank reached; progression complete.";
|
||||||
|
}
|
||||||
|
int requirement = rules.requirementForCurrentRank(progress.rank());
|
||||||
|
int remaining = Math.max(0, requirement - progress.tierKills());
|
||||||
|
String rank = progress.rank() == AuraRank.LOCKED ? "Locked" : progress.rank().name();
|
||||||
|
return "Creeper Aura " + rank + " — " + progress.tierKills() + "/" + requirement
|
||||||
|
+ " current-tier kills; " + remaining + " remaining.";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,3 +4,12 @@ main: games.dmg.creeperfear.CreeperFearPlugin
|
|||||||
api-version: '26.2'
|
api-version: '26.2'
|
||||||
author: dmg.games
|
author: dmg.games
|
||||||
description: Unlock Creeper Aura ranks by defeating creepers.
|
description: Unlock Creeper Aura ranks by defeating creepers.
|
||||||
|
commands:
|
||||||
|
creeperaura:
|
||||||
|
description: Check and administer Creeper Aura progression.
|
||||||
|
usage: /<command> progress
|
||||||
|
permission: creeperfear.progress
|
||||||
|
permissions:
|
||||||
|
creeperfear.progress:
|
||||||
|
description: Check personal Creeper Aura progression.
|
||||||
|
default: true
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package games.dmg.creeperfear.command;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import games.dmg.creeperfear.aura.AuraRules;
|
||||||
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
|
import games.dmg.creeperfear.progress.PlayerProgress;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ProgressMessagesTest {
|
||||||
|
private final ProgressMessages messages = new ProgressMessages(AuraRules.defaults());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reportsCurrentTierAndRemainingKills() {
|
||||||
|
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.II, 40);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"Creeper Aura II — 40/100 current-tier kills; 60 remaining.",
|
||||||
|
messages.describe(progress));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reportsCompletedProgressAtRankSix() {
|
||||||
|
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.VI, 0);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"Creeper Aura VI — maximum rank reached; progression complete.",
|
||||||
|
messages.describe(progress));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user