feat(vigilante): add follower control panel
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class DefaultVigilanteControlPanelTest {
|
||||
@Test
|
||||
void activeVigilanteOpensAuthoritativeOverview() {
|
||||
UUID tyrantId = UUID.fromString("11111111-1111-1111-1111-111111111111");
|
||||
UUID vigilanteId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
GameState game = game(tyrantId, vigilanteId);
|
||||
PlayerState vigilanteState = PlayerState.newPlayer(vigilanteId, "Vigilante");
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.game()).thenReturn(game);
|
||||
when(manager.players()).thenReturn(Map.of(vigilanteId, vigilanteState));
|
||||
Player vigilante = mock(Player.class);
|
||||
when(vigilante.getUniqueId()).thenReturn(vigilanteId);
|
||||
VigilanteControlPanelRenderer renderer = mock(VigilanteControlPanelRenderer.class);
|
||||
FollowerPresenceProvider presence = mock(FollowerPresenceProvider.class);
|
||||
when(presence.inspect(any(), any())).thenReturn(Map.of());
|
||||
DefaultVigilanteControlPanel panel = new DefaultVigilanteControlPanel(
|
||||
manager, new FollowerService(), renderer, presence, 5, 4
|
||||
);
|
||||
|
||||
panel.open(vigilante);
|
||||
|
||||
verify(renderer).openOverview(org.mockito.ArgumentMatchers.eq(vigilante), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonVigilanteCannotRenderControlPanel() {
|
||||
UUID tyrantId = UUID.fromString("11111111-1111-1111-1111-111111111111");
|
||||
UUID vigilanteId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
Player other = mock(Player.class);
|
||||
when(other.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.game()).thenReturn(game(tyrantId, vigilanteId));
|
||||
VigilanteControlPanelRenderer renderer = mock(VigilanteControlPanelRenderer.class);
|
||||
DefaultVigilanteControlPanel panel = new DefaultVigilanteControlPanel(
|
||||
manager, new FollowerService(), renderer, mock(FollowerPresenceProvider.class), 5, 4
|
||||
);
|
||||
|
||||
panel.open(other);
|
||||
|
||||
verify(renderer, never()).openOverview(any(), any());
|
||||
verify(other).sendMessage(org.mockito.ArgumentMatchers.contains("active Vigilante"));
|
||||
}
|
||||
|
||||
private static GameState game(UUID tyrantId, UUID vigilanteId) {
|
||||
return new GameState(
|
||||
GameLifecycle.RUNNING, Optional.of(tyrantId), Optional.of(vigilanteId),
|
||||
Optional.empty(), Optional.empty(), Optional.empty(), Duration.ZERO,
|
||||
0, 0, Set.of()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
@@ -34,6 +35,32 @@ final class FollowerServiceTest {
|
||||
assertEquals(TyrantClass.FIXER, accepted.players().get(FOLLOWER).tyrantClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
void repeatedInvitationIsRejectedAndPendingInvitationCanBeInspected() {
|
||||
GameState game = game();
|
||||
PlayerState target = PlayerState.newPlayer(FOLLOWER, "Follower");
|
||||
Map<UUID, PlayerState> players = Map.of(FOLLOWER, target);
|
||||
|
||||
FollowerResult first = service.invite(game, players, VIGILANTE, FOLLOWER);
|
||||
FollowerResult repeated = service.invite(game, players, VIGILANTE, FOLLOWER);
|
||||
|
||||
assertEquals(FollowerStatus.INVITED, first.status());
|
||||
assertEquals(FollowerStatus.ALREADY_INVITED, repeated.status());
|
||||
assertTrue(service.invitedPlayerIds(VIGILANTE).contains(FOLLOWER));
|
||||
}
|
||||
|
||||
@Test
|
||||
void existingFollowerCannotReceiveAnotherInvitation() {
|
||||
GameState game = game();
|
||||
PlayerState follower = withFollower(PlayerState.newPlayer(FOLLOWER, "Follower"));
|
||||
|
||||
FollowerResult result = service.invite(
|
||||
game, Map.of(FOLLOWER, follower), VIGILANTE, FOLLOWER
|
||||
);
|
||||
|
||||
assertEquals(FollowerStatus.INELIGIBLE, result.status());
|
||||
}
|
||||
|
||||
@Test
|
||||
void vigilanteCanDismissAndFollowerCanLeave() {
|
||||
GameState game = game();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class VigilanteCommandTest {
|
||||
@Test
|
||||
void playerCanOpenControlPanelWithNoArgumentsOrMenuSubcommand() {
|
||||
UUID playerId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(playerId);
|
||||
VigilanteControlPanel controlPanel = mock(VigilanteControlPanel.class);
|
||||
VigilanteCommand command = new VigilanteCommand(
|
||||
mock(TyrantStateManager.class),
|
||||
new FollowerService(),
|
||||
mock(OnlinePlayerDirectory.class),
|
||||
controlPanel
|
||||
);
|
||||
|
||||
command.onCommand(player, mock(Command.class), "vigilante", new String[0]);
|
||||
command.onCommand(player, mock(Command.class), "vigilante", new String[] {"menu"});
|
||||
|
||||
verify(controlPanel, times(2)).open(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
final class VigilanteControlPanelJoinListenerTest {
|
||||
@Test
|
||||
void opensPanelOneHundredTicksAfterActiveVigilanteJoins() {
|
||||
UUID vigilanteId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.game()).thenReturn(game(GameLifecycle.RUNNING, vigilanteId));
|
||||
Player vigilante = player(vigilanteId);
|
||||
PlayerJoinEvent event = mock(PlayerJoinEvent.class);
|
||||
when(event.getPlayer()).thenReturn(vigilante);
|
||||
DelayedTaskScheduler scheduler = mock(DelayedTaskScheduler.class);
|
||||
VigilanteControlPanel panel = mock(VigilanteControlPanel.class);
|
||||
VigilanteControlPanelJoinListener listener = new VigilanteControlPanelJoinListener(
|
||||
manager, panel, scheduler
|
||||
);
|
||||
|
||||
listener.onJoin(event);
|
||||
|
||||
ArgumentCaptor<Runnable> task = ArgumentCaptor.forClass(Runnable.class);
|
||||
verify(scheduler).schedule(task.capture(), org.mockito.ArgumentMatchers.eq(100L));
|
||||
task.getValue().run();
|
||||
verify(panel).open(vigilante);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotOpenAfterPauseOrWhenAlreadyOpenedManually() {
|
||||
UUID vigilanteId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
Player vigilante = player(vigilanteId);
|
||||
PlayerJoinEvent event = mock(PlayerJoinEvent.class);
|
||||
when(event.getPlayer()).thenReturn(vigilante);
|
||||
DelayedTaskScheduler scheduler = mock(DelayedTaskScheduler.class);
|
||||
VigilanteControlPanel panel = mock(VigilanteControlPanel.class);
|
||||
when(panel.openedThisSession(vigilanteId)).thenReturn(true);
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.game()).thenReturn(game(GameLifecycle.PAUSED, vigilanteId));
|
||||
VigilanteControlPanelJoinListener listener = new VigilanteControlPanelJoinListener(
|
||||
manager, panel, scheduler
|
||||
);
|
||||
|
||||
listener.onJoin(event);
|
||||
ArgumentCaptor<Runnable> task = ArgumentCaptor.forClass(Runnable.class);
|
||||
verify(scheduler).schedule(task.capture(), org.mockito.ArgumentMatchers.eq(100L));
|
||||
task.getValue().run();
|
||||
|
||||
verify(panel, never()).open(vigilante);
|
||||
}
|
||||
|
||||
private static Player player(UUID id) {
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(id);
|
||||
when(player.isOnline()).thenReturn(true);
|
||||
return player;
|
||||
}
|
||||
|
||||
private static GameState game(GameLifecycle lifecycle, UUID vigilanteId) {
|
||||
return new GameState(
|
||||
lifecycle,
|
||||
Optional.of(UUID.fromString("11111111-1111-1111-1111-111111111111")),
|
||||
Optional.of(vigilanteId), Optional.empty(), Optional.empty(),
|
||||
lifecycle == GameLifecycle.PAUSED
|
||||
? Optional.of(java.time.Instant.EPOCH) : Optional.empty(),
|
||||
Duration.ZERO, 0, 0, Set.of()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class VigilanteControlPanelModelTest {
|
||||
@Test
|
||||
void overviewReportsFollowersInvitationsAndCappedNearbyPower() {
|
||||
UUID tyrantId = UUID.fromString("11111111-1111-1111-1111-111111111111");
|
||||
UUID vigilanteId = UUID.fromString("22222222-2222-2222-2222-222222222222");
|
||||
UUID nearbyId = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||
UUID offlineId = UUID.fromString("44444444-4444-4444-4444-444444444444");
|
||||
UUID invitedId = UUID.fromString("55555555-5555-5555-5555-555555555555");
|
||||
GameState game = new GameState(
|
||||
GameLifecycle.RUNNING, Optional.of(tyrantId), Optional.of(vigilanteId),
|
||||
Optional.empty(), Optional.empty(), Optional.empty(), Duration.ZERO,
|
||||
0, 0, Set.of()
|
||||
);
|
||||
PlayerState nearby = follower(nearbyId, "Nearby", vigilanteId);
|
||||
PlayerState offline = follower(offlineId, "Offline", vigilanteId);
|
||||
PlayerState invited = PlayerState.newPlayer(invitedId, "Invited");
|
||||
|
||||
VigilanteControlPanelModel model = VigilanteControlPanelModel.create(
|
||||
game,
|
||||
Map.of(nearbyId, nearby, offlineId, offline, invitedId, invited),
|
||||
Set.of(invitedId),
|
||||
Map.of(
|
||||
nearbyId, new FollowerPresence(true, true, true, true),
|
||||
offlineId, new FollowerPresence(false, false, false, false)
|
||||
),
|
||||
5,
|
||||
4
|
||||
);
|
||||
|
||||
assertEquals(2, model.followers().size());
|
||||
assertEquals(Set.of("Invited"), model.pendingInvitations());
|
||||
assertEquals(1, model.nearbyEligibleFollowers());
|
||||
assertEquals(1, model.strengthLevel());
|
||||
assertEquals(1, model.resistanceLevel());
|
||||
assertEquals(5, model.strengthCap());
|
||||
assertEquals(4, model.resistanceCap());
|
||||
}
|
||||
|
||||
private static PlayerState follower(UUID id, String name, UUID vigilanteId) {
|
||||
PlayerState player = PlayerState.newPlayer(id, name);
|
||||
return new PlayerState(
|
||||
player.playerId(), player.latestName(), player.lastLogin(), player.optedOutUntil(),
|
||||
player.tyrantClass(), Optional.of(vigilanteId), player.cooldownEnds(),
|
||||
player.readyAbilityItems(), player.capturedMobs()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user