fix(arena): keep vigilante victory private
This commit is contained in:
@@ -6,6 +6,12 @@ description: Chronological record of material decisions affecting the Spigot Tyr
|
|||||||
|
|
||||||
# Spigot Tyrant Design Log
|
# Spigot Tyrant Design Log
|
||||||
|
|
||||||
|
## 2026-09-04 — Vigilante arena victory kept private
|
||||||
|
|
||||||
|
- Removed the server-wide Vigilante arena victory announcement that exposed the new Vigilante's identity.
|
||||||
|
- The winning Vigilante now receives a private confirmation, while the publicly identifiable Tyrant victory announcement remains unchanged.
|
||||||
|
- Verified private Vigilante and public Tyrant messaging, 121 automated tests, compiler warnings, and packaging with `./gradlew clean check jar`.
|
||||||
|
|
||||||
## 2026-09-04 — Arena winners safely extracted
|
## 2026-09-04 — Arena winners safely extracted
|
||||||
|
|
||||||
- Corrected shared-role arena completion so a successful Tyrant or Vigilante challenger is moved safely outside immediately after assignment and barrier removal.
|
- Corrected shared-role arena completion so a successful Tyrant or Vigilante challenger is moved safely outside immediately after assignment and barrier removal.
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ As an **opted-in participant**, I want a visible one-player boss challenge for a
|
|||||||
- [x] Block placement and breaking are denied inside the arena during an active fight so players cannot build over or modify the boundary.
|
- [x] Block placement and breaking are denied inside the arena during an active fight so players cannot build over or modify the boundary.
|
||||||
- [x] Killing the boss assigns the challenger as Vigilante, removes the boss and barriers, and restores the passive particle boundary.
|
- [x] Killing the boss assigns the challenger as Vigilante, removes the boss and barriers, and restores the passive particle boundary.
|
||||||
- [x] After winning, the new Vigilante is moved safely outside the arena before normal arena enforcement resumes.
|
- [x] After winning, the new Vigilante is moved safely outside the arena before normal arena enforcement resumes.
|
||||||
|
- [x] The Vigilante winner receives a private confirmation, and no server-wide victory message names or reveals the new Vigilante.
|
||||||
- [x] Pausing, resetting, restarting, reloading, and repeated or concurrent events cannot duplicate the boss, barriers, challenger, or Vigilante assignment.
|
- [x] Pausing, resetting, restarting, reloading, and repeated or concurrent events cannot duplicate the boss, barriers, challenger, or Vigilante assignment.
|
||||||
- [x] If the arena is not configured when a challenge should open, the Vigilante remains vacant and administrators receive a clear warning.
|
- [x] If the arena is not configured when a challenge should open, the Vigilante remains vacant and administrators receive a clear warning.
|
||||||
|
|
||||||
|
|||||||
@@ -416,6 +416,13 @@ public final class RoleArenaController implements Listener, Runnable {
|
|||||||
barrier.clear();
|
barrier.clear();
|
||||||
Player winner = server.getPlayer(playerId);
|
Player winner = server.getPlayer(playerId);
|
||||||
moveWinnerOutside(winner);
|
moveWinnerOutside(winner);
|
||||||
|
if (role == ArenaRole.VIGILANTE) {
|
||||||
|
if (winner != null) {
|
||||||
|
winner.sendMessage(ChatColor.YELLOW
|
||||||
|
+ "You defeated the arena boss and became the Vigilante!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
String name = Optional.ofNullable(winner)
|
String name = Optional.ofNullable(winner)
|
||||||
.map(Player::getName).orElse(playerId.toString());
|
.map(Player::getName).orElse(playerId.toString());
|
||||||
String message = ChatColor.YELLOW + name + " defeated the arena boss and is the "
|
String message = ChatColor.YELLOW + name + " defeated the arena boss and is the "
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
final class RoleArenaControllerTest {
|
final class RoleArenaControllerTest {
|
||||||
private static final UUID TYRANT = UUID.fromString("11111111-1111-1111-1111-111111111111");
|
private static final UUID TYRANT = UUID.fromString("11111111-1111-1111-1111-111111111111");
|
||||||
private static final UUID PLAYER = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
private static final UUID PLAYER = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||||
|
private static final UUID OTHER = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void boundaryColorsIdentifyTheOpenRole() {
|
void boundaryColorsIdentifyTheOpenRole() {
|
||||||
@@ -133,13 +134,15 @@ final class RoleArenaControllerTest {
|
|||||||
when(player.getUniqueId()).thenReturn(PLAYER);
|
when(player.getUniqueId()).thenReturn(PLAYER);
|
||||||
when(player.getName()).thenReturn("Player");
|
when(player.getName()).thenReturn("Player");
|
||||||
when(player.getLocation()).thenReturn(new Location(world, arena.x(), arena.y(), arena.z()));
|
when(player.getLocation()).thenReturn(new Location(world, arena.x(), arena.y(), arena.z()));
|
||||||
|
Player other = mock(Player.class);
|
||||||
|
when(other.getUniqueId()).thenReturn(OTHER);
|
||||||
PlayerState playerState = PlayerState.newPlayer(PLAYER, "Player");
|
PlayerState playerState = PlayerState.newPlayer(PLAYER, "Player");
|
||||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||||
when(manager.snapshot()).thenReturn(new PersistentState(game, Map.of(PLAYER, playerState)));
|
when(manager.snapshot()).thenReturn(new PersistentState(game, Map.of(PLAYER, playerState)));
|
||||||
Server server = mock(Server.class);
|
Server server = mock(Server.class);
|
||||||
when(server.getPlayer(PLAYER)).thenReturn(player);
|
when(server.getPlayer(PLAYER)).thenReturn(player);
|
||||||
when(server.getWorld("world")).thenReturn(world);
|
when(server.getWorld("world")).thenReturn(world);
|
||||||
doReturn(Set.of(player)).when(server).getOnlinePlayers();
|
doReturn(Set.of(player, other)).when(server).getOnlinePlayers();
|
||||||
ArenaLocationStore locations = mock(ArenaLocationStore.class);
|
ArenaLocationStore locations = mock(ArenaLocationStore.class);
|
||||||
when(locations.location()).thenReturn(Optional.of(arena));
|
when(locations.location()).thenReturn(Optional.of(arena));
|
||||||
RoleArenaController controller = new RoleArenaController(
|
RoleArenaController controller = new RoleArenaController(
|
||||||
@@ -153,6 +156,14 @@ final class RoleArenaControllerTest {
|
|||||||
!ArenaGeometry.contains(arena, 10.0, "world",
|
!ArenaGeometry.contains(arena, 10.0, "world",
|
||||||
destination.getX(), destination.getY(), destination.getZ())
|
destination.getX(), destination.getY(), destination.getZ())
|
||||||
), eq(org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.PLUGIN));
|
), eq(org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.PLUGIN));
|
||||||
|
if (role == ArenaRole.VIGILANTE) {
|
||||||
|
verify(player).sendMessage(contains(
|
||||||
|
"You defeated the arena boss and became the Vigilante"
|
||||||
|
));
|
||||||
|
verify(other, never()).sendMessage(contains("Vigilante"));
|
||||||
|
} else {
|
||||||
|
verify(other).sendMessage(contains("Player defeated the arena boss"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlayerJoinEvent mockJoin(Player player) {
|
private static PlayerJoinEvent mockJoin(Player player) {
|
||||||
|
|||||||
Reference in New Issue
Block a user