feat(commands): show player stealth progress
Release / release (push) Successful in 2m29s
CI / build (push) Successful in 1m15s

This commit is contained in:
dmg
2026-08-15 00:03:09 -04:00
parent 91c9e7b9ad
commit 90851a0d87
7 changed files with 184 additions and 8 deletions
@@ -0,0 +1,69 @@
package games.dmg.spigotstealth;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.Test;
class StealthCommandTest {
@Test
void reportsLiveProgressTargetAndRemainingTimeWithoutMutatingState() {
UUID playerId = UUID.randomUUID();
AtomicLong nanos = new AtomicLong();
try (StealthStateManager manager = manager()) {
manager.update(state -> state.withPlayer(state.player(playerId).withAccumulatedMillis(Duration.ofHours(2).toMillis()))).join();
QualifyingInvisibilityService progression = new QualifyingInvisibilityService(
manager, Duration.ofHours(8), nanos::get, ignored -> { });
progression.begin(playerId, "Alex", Instant.EPOCH).join();
nanos.addAndGet(Duration.ofMinutes(5).toNanos());
Player player = player(playerId);
StealthCommand command = new StealthCommand(manager, progression, StealthSettings.from(Map.of()));
assertTrue(command.onCommand(player, mock(Command.class), "stealth", new String[] {"progress"}));
verify(player).sendMessage(contains("2h 5m / 8h"));
verify(player).sendMessage(contains("5h 55m remaining"));
org.junit.jupiter.api.Assertions.assertEquals(Duration.ofHours(2).toMillis(), manager.snapshot().player(playerId).accumulatedMillis());
}
}
@Test
void unlockedPlayerReceivesUsageGuidance() {
UUID playerId = UUID.randomUUID();
try (StealthStateManager manager = manager()) {
PlayerStealthState unlocked = new PlayerStealthState(playerId, "Alex", Duration.ofHours(8).toMillis(), true, false, false, null, Map.of());
manager.update(state -> state.withPlayer(unlocked)).join();
QualifyingInvisibilityService progression = new QualifyingInvisibilityService(
manager, Duration.ofHours(8), System::nanoTime, ignored -> { });
Player player = player(playerId);
StealthCommand command = new StealthCommand(manager, progression, StealthSettings.from(Map.of()));
command.onCommand(player, mock(Command.class), "stealth", new String[] {"progress"});
verify(player).sendMessage(contains("unlocked"));
verify(player).sendMessage(contains("log out while invisible"));
}
}
private static Player player(UUID playerId) {
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
return player;
}
private static StealthStateManager manager() {
StealthStateRepository repository = new StealthStateRepository() {
@Override public PersistentStealthState load() { return new PersistentStealthState(Map.of(), Map.of()); }
@Override public void save(PersistentStealthState state) { }
};
return new StealthStateManager(repository, new PersistentStealthState(Map.of(), Map.of()));
}
}
@@ -0,0 +1,15 @@
package games.dmg.spigotstealth;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;
import org.junit.jupiter.api.Test;
class StealthProgressFormatterTest {
@Test
void presentsConciseHumanReadableDurations() {
assertEquals("2h 5m 9s", StealthProgressFormatter.duration(Duration.ofHours(2).plusMinutes(5).plusSeconds(9).toMillis()));
assertEquals("45s", StealthProgressFormatter.duration(45_900L));
assertEquals("0s", StealthProgressFormatter.duration(0L));
}
}