feat(progression): reward unique boss kills
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package games.dmg.triggerspawn;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
final class ProgressionReminder {
|
||||
private ProgressionReminder() {
|
||||
}
|
||||
|
||||
static Optional<String> create(Set<BossType> defeated, PluginSettings settings) {
|
||||
if (defeated.size() >= BossType.values().length) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String remaining = Arrays.stream(BossType.values())
|
||||
.filter(boss -> !defeated.contains(boss))
|
||||
.map(BossType::displayName)
|
||||
.collect(Collectors.joining(", "));
|
||||
Duration nextTier = switch (defeated.size()) {
|
||||
case 0 -> settings.oneKillCooldown();
|
||||
case 1 -> settings.twoKillCooldown();
|
||||
default -> settings.threeKillCooldown();
|
||||
};
|
||||
return Optional.of(ChatColor.GOLD + "Progression reminder: " + ChatColor.YELLOW
|
||||
+ "defeat " + remaining + " to permanently reduce your boss cooldown; "
|
||||
+ "the next tier is " + DurationFormatter.format(nextTier) + ".");
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ final class SpawnCommand implements CommandExecutor, Listener {
|
||||
private final Plugin plugin;
|
||||
private final SpawnStateManager stateManager;
|
||||
private final AccessService access;
|
||||
private final PluginSettings settings;
|
||||
private final SpawnAreaService spawnAreas;
|
||||
private final SafeSpawnFinder safeSpawnFinder;
|
||||
private final Clock clock;
|
||||
@@ -36,12 +37,14 @@ final class SpawnCommand implements CommandExecutor, Listener {
|
||||
Plugin plugin,
|
||||
SpawnStateManager stateManager,
|
||||
AccessService access,
|
||||
PluginSettings settings,
|
||||
SpawnAreaService spawnAreas,
|
||||
SafeSpawnFinder safeSpawnFinder,
|
||||
Clock clock) {
|
||||
this.plugin = plugin;
|
||||
this.stateManager = stateManager;
|
||||
this.access = access;
|
||||
this.settings = settings;
|
||||
this.spawnAreas = spawnAreas;
|
||||
this.safeSpawnFinder = safeSpawnFinder;
|
||||
this.clock = clock;
|
||||
@@ -140,10 +143,8 @@ final class SpawnCommand implements CommandExecutor, Listener {
|
||||
recordSuccessfulUse(player);
|
||||
player.sendTitle(ChatColor.GREEN + "Welcome to spawn", "", 5, 30, 10);
|
||||
PlayerState completed = stateManager.player(player.getUniqueId(), player.getName());
|
||||
if (completed.defeatedBosses().size() < BossType.values().length) {
|
||||
player.sendMessage(ChatColor.GOLD
|
||||
+ "Defeat each remaining boss to permanently reduce your /spawn cooldown.");
|
||||
}
|
||||
ProgressionReminder.create(completed.defeatedBosses(), settings)
|
||||
.ifPresent(player::sendMessage);
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED
|
||||
+ "The spawn teleport failed. Your cooldown was not used.");
|
||||
|
||||
@@ -37,6 +37,7 @@ public final class TriggerSpawnPlugin extends JavaPlugin {
|
||||
this,
|
||||
stateManager,
|
||||
access,
|
||||
settings,
|
||||
new SpawnAreaService(stateManager),
|
||||
new SafeSpawnFinder(),
|
||||
Clock.systemUTC());
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package games.dmg.triggerspawn;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ProgressionReminderTest {
|
||||
@Test
|
||||
void identifiesRemainingBossesAndNextPermanentTier() {
|
||||
PluginSettings settings = PluginSettings.from(new MemoryConfiguration());
|
||||
|
||||
String reminder = ProgressionReminder.create(Set.of(BossType.WARDEN), settings).orElseThrow();
|
||||
|
||||
assertTrue(reminder.contains("Dragon"));
|
||||
assertTrue(reminder.contains("Wither"));
|
||||
assertTrue(reminder.contains("4h"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void completedProgressionNeedsNoReminder() {
|
||||
PluginSettings settings = PluginSettings.from(new MemoryConfiguration());
|
||||
assertTrue(ProgressionReminder.create(Set.of(BossType.values()), settings).isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,18 @@ final class ProgressionServiceTest {
|
||||
assertEquals(Duration.ofHours(4), second.applicableCooldown());
|
||||
assertEquals(2, second.defeatedBosses().size());
|
||||
assertTrue(manager.snapshot().players().get(playerId).lastSpawnUse().isEmpty());
|
||||
|
||||
Instant laterUse = Instant.parse("2026-08-08T12:00:00Z");
|
||||
PlayerState current = manager.snapshot().players().get(playerId);
|
||||
manager.putPlayer(new PlayerState(
|
||||
current.playerId(),
|
||||
current.latestName(),
|
||||
current.defeatedBosses(),
|
||||
current.grantedCooldown(),
|
||||
false,
|
||||
Optional.of(laterUse)));
|
||||
progression.creditKill(identity, BossType.WARDEN);
|
||||
assertEquals(laterUse, manager.snapshot().players().get(playerId).lastSpawnUse().orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -43,6 +43,7 @@ final class SpawnCommandTest {
|
||||
mock(Plugin.class),
|
||||
manager,
|
||||
access,
|
||||
settings,
|
||||
new SpawnAreaService(manager),
|
||||
new SafeSpawnFinder(),
|
||||
Clock.fixed(Instant.parse("2026-08-08T11:00:00Z"), ZoneOffset.UTC));
|
||||
|
||||
Reference in New Issue
Block a user