feat(board): add shared physical quest boards
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package games.dmg.spigotquestboard;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class BoardRegistryTest {
|
||||
private static final RegisteredBoard BOARD = new RegisteredBoard(
|
||||
new BoardId(UUID.fromString("00000000-0000-0000-0000-000000000001"), 1, 64, 2),
|
||||
"world"
|
||||
);
|
||||
|
||||
@Test
|
||||
void registersAndPersistsBeforePublishingBoard() throws IOException {
|
||||
RecordingRepository repository = new RecordingRepository(BoardState.empty());
|
||||
BoardRegistry registry = new BoardRegistry(repository);
|
||||
|
||||
assertEquals(BoardRegistrationResult.CREATED, registry.register(BOARD));
|
||||
assertTrue(registry.contains(BOARD.id()));
|
||||
assertEquals(Set.of(BOARD), repository.saved.boards());
|
||||
}
|
||||
|
||||
@Test
|
||||
void duplicateDoesNotWrite() throws IOException {
|
||||
RecordingRepository repository = new RecordingRepository(new BoardState(Set.of(BOARD)));
|
||||
BoardRegistry registry = new BoardRegistry(repository);
|
||||
|
||||
assertEquals(BoardRegistrationResult.ALREADY_REGISTERED, registry.register(BOARD));
|
||||
assertEquals(0, repository.saveCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void failedPersistenceDoesNotPublishBoard() throws Exception {
|
||||
BoardRepository repository = new BoardRepository() {
|
||||
@Override public BoardState load() { return BoardState.empty(); }
|
||||
@Override public void save(BoardState state) throws IOException {
|
||||
throw new IOException("disk failed");
|
||||
}
|
||||
};
|
||||
BoardRegistry registry = new BoardRegistry(repository);
|
||||
|
||||
assertThrows(IOException.class, () -> registry.register(BOARD));
|
||||
assertFalse(registry.contains(BOARD.id()));
|
||||
}
|
||||
|
||||
private static final class RecordingRepository implements BoardRepository {
|
||||
private final BoardState initial;
|
||||
private BoardState saved;
|
||||
private int saveCount;
|
||||
|
||||
private RecordingRepository(BoardState initial) {
|
||||
this.initial = initial;
|
||||
}
|
||||
|
||||
@Override public BoardState load() { return initial; }
|
||||
@Override public void save(BoardState state) {
|
||||
saved = state;
|
||||
saveCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package games.dmg.spigotquestboard;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
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.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class QuestAdminCommandTest {
|
||||
@Test
|
||||
void unauthorizedSenderCannotCreateBoard() throws Exception {
|
||||
MemoryBoardRepository repository = new MemoryBoardRepository();
|
||||
QuestAdminCommand executor = new QuestAdminCommand(new BoardRegistry(repository));
|
||||
Player player = mock(Player.class);
|
||||
when(player.hasPermission("spigotquestboard.admin")).thenReturn(false);
|
||||
|
||||
assertTrue(executor.onCommand(player, mock(Command.class), "questadmin", new String[] {"createboard"}));
|
||||
|
||||
verify(player, never()).getTargetBlockExact(5);
|
||||
assertTrue(repository.state.boards().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void registersTargetedPhysicalBlock() throws Exception {
|
||||
MemoryBoardRepository repository = new MemoryBoardRepository();
|
||||
QuestAdminCommand executor = new QuestAdminCommand(new BoardRegistry(repository));
|
||||
Player player = mock(Player.class);
|
||||
Block block = mock(Block.class);
|
||||
World world = mock(World.class);
|
||||
UUID worldId = UUID.randomUUID();
|
||||
when(player.hasPermission("spigotquestboard.admin")).thenReturn(true);
|
||||
when(player.getTargetBlockExact(5)).thenReturn(block);
|
||||
when(block.getWorld()).thenReturn(world);
|
||||
when(world.getUID()).thenReturn(worldId);
|
||||
when(world.getName()).thenReturn("world");
|
||||
when(block.getX()).thenReturn(10);
|
||||
when(block.getY()).thenReturn(65);
|
||||
when(block.getZ()).thenReturn(-4);
|
||||
|
||||
assertTrue(executor.onCommand(player, mock(Command.class), "questadmin", new String[] {"createboard"}));
|
||||
|
||||
assertTrue(repository.state.boards().contains(new RegisteredBoard(
|
||||
new BoardId(worldId, 10, 65, -4), "world"
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleAndMissingTargetDoNotChangeState() throws Exception {
|
||||
MemoryBoardRepository repository = new MemoryBoardRepository();
|
||||
QuestAdminCommand executor = new QuestAdminCommand(new BoardRegistry(repository));
|
||||
CommandSender console = mock(CommandSender.class);
|
||||
when(console.hasPermission("spigotquestboard.admin")).thenReturn(true);
|
||||
assertTrue(executor.onCommand(console, mock(Command.class), "questadmin", new String[] {"createboard"}));
|
||||
|
||||
Player player = mock(Player.class);
|
||||
when(player.hasPermission("spigotquestboard.admin")).thenReturn(true);
|
||||
when(player.getTargetBlockExact(5)).thenReturn(null);
|
||||
assertTrue(executor.onCommand(player, mock(Command.class), "questadmin", new String[] {"createboard"}));
|
||||
|
||||
assertTrue(repository.state.boards().isEmpty());
|
||||
}
|
||||
|
||||
private static final class MemoryBoardRepository implements BoardRepository {
|
||||
private BoardState state = new BoardState(Set.of());
|
||||
@Override public BoardState load() { return state; }
|
||||
@Override public void save(BoardState state) { this.state = state; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package games.dmg.spigotquestboard;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
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.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class QuestBoardInteractionListenerTest {
|
||||
@Test
|
||||
void registeredBoardsOpenTheSameGlobalInterface() throws Exception {
|
||||
UUID worldId = UUID.randomUUID();
|
||||
RegisteredBoard first = new RegisteredBoard(new BoardId(worldId, 1, 64, 1), "world");
|
||||
RegisteredBoard second = new RegisteredBoard(new BoardId(worldId, 2, 64, 2), "world");
|
||||
BoardRepository repository = new FixedRepository(new BoardState(Set.of(first, second)));
|
||||
BoardRegistry registry = new BoardRegistry(repository);
|
||||
CountingUi ui = new CountingUi();
|
||||
QuestBoardInteractionListener listener = new QuestBoardInteractionListener(registry, ui);
|
||||
Player player = mock(Player.class);
|
||||
|
||||
PlayerInteractEvent firstEvent = eventFor(first, player);
|
||||
PlayerInteractEvent secondEvent = eventFor(second, player);
|
||||
listener.onPlayerInteract(firstEvent);
|
||||
listener.onPlayerInteract(secondEvent);
|
||||
|
||||
verify(firstEvent).setCancelled(true);
|
||||
verify(secondEvent).setCancelled(true);
|
||||
assertEquals(2, ui.opens);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unregisteredAndOffHandInteractionsPassThrough() throws Exception {
|
||||
BoardRegistry registry = new BoardRegistry(new FixedRepository(BoardState.empty()));
|
||||
CountingUi ui = new CountingUi();
|
||||
QuestBoardInteractionListener listener = new QuestBoardInteractionListener(registry, ui);
|
||||
PlayerInteractEvent event = eventFor(
|
||||
new RegisteredBoard(new BoardId(UUID.randomUUID(), 1, 64, 1), "world"),
|
||||
mock(Player.class)
|
||||
);
|
||||
listener.onPlayerInteract(event);
|
||||
verify(event, never()).setCancelled(true);
|
||||
|
||||
when(event.getHand()).thenReturn(EquipmentSlot.OFF_HAND);
|
||||
listener.onPlayerInteract(event);
|
||||
assertEquals(0, ui.opens);
|
||||
}
|
||||
|
||||
private static PlayerInteractEvent eventFor(RegisteredBoard board, Player player) {
|
||||
PlayerInteractEvent event = mock(PlayerInteractEvent.class);
|
||||
Block block = mock(Block.class);
|
||||
World world = mock(World.class);
|
||||
when(event.getAction()).thenReturn(Action.RIGHT_CLICK_BLOCK);
|
||||
when(event.getHand()).thenReturn(EquipmentSlot.HAND);
|
||||
when(event.getClickedBlock()).thenReturn(block);
|
||||
when(event.getPlayer()).thenReturn(player);
|
||||
when(block.getWorld()).thenReturn(world);
|
||||
when(world.getUID()).thenReturn(board.id().worldId());
|
||||
when(world.getName()).thenReturn(board.worldName());
|
||||
when(block.getX()).thenReturn(board.id().x());
|
||||
when(block.getY()).thenReturn(board.id().y());
|
||||
when(block.getZ()).thenReturn(board.id().z());
|
||||
return event;
|
||||
}
|
||||
|
||||
private static final class FixedRepository implements BoardRepository {
|
||||
private final BoardState state;
|
||||
private FixedRepository(BoardState state) { this.state = state; }
|
||||
@Override public BoardState load() { return state; }
|
||||
@Override public void save(BoardState state) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private static final class CountingUi implements QuestBoardUi {
|
||||
private int opens;
|
||||
@Override public void open(Player player) { opens++; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package games.dmg.spigotquestboard;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
final class YamlBoardRepositoryTest {
|
||||
@TempDir Path temporaryDirectory;
|
||||
|
||||
@Test
|
||||
void missingFileLoadsEmptyState() throws Exception {
|
||||
YamlBoardRepository repository = new YamlBoardRepository(
|
||||
temporaryDirectory.resolve("boards.yml")
|
||||
);
|
||||
|
||||
assertTrue(repository.load().boards().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void roundTripsWorldIdentityAndCoordinates() throws Exception {
|
||||
Path path = temporaryDirectory.resolve("boards.yml");
|
||||
YamlBoardRepository repository = new YamlBoardRepository(path);
|
||||
BoardState expected = new BoardState(Set.of(
|
||||
new RegisteredBoard(
|
||||
new BoardId(UUID.fromString("00000000-0000-0000-0000-000000000001"), 4, 70, -8),
|
||||
"survival"
|
||||
),
|
||||
new RegisteredBoard(
|
||||
new BoardId(UUID.fromString("00000000-0000-0000-0000-000000000002"), 4, 70, -8),
|
||||
"resource"
|
||||
)
|
||||
));
|
||||
|
||||
repository.save(expected);
|
||||
|
||||
assertEquals(expected, repository.load());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user