feat(settings): add native base control dialog
This commit is contained in:
@@ -20,13 +20,29 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.UnaryOperator;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import net.md_5.bungee.api.dialog.Dialog;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
final class BaseSettingsCommandTest {
|
||||
@Test
|
||||
void rejectsNonPlayerExecution() {
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
BaseSettingsCommand command = new BaseSettingsCommand(
|
||||
mock(BaseStateManager.class),
|
||||
new PluginSettingsProvider(PluginSettings.from(Map.of())),
|
||||
mock(BaseFlightController.class)
|
||||
);
|
||||
|
||||
command.onCommand(sender, null, "basesettings", new String[0]);
|
||||
|
||||
verify(sender).sendMessage("Only players have base progression.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void spawnableEnableIsIdempotentAfterUnlock() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
@@ -156,8 +172,8 @@ final class BaseSettingsCommandTest {
|
||||
|
||||
assertEquals(
|
||||
List.of(
|
||||
"status", "upgrade", "pocket", "visitors", "navigation", "flight", "border",
|
||||
"spawnable", "bossbar"
|
||||
"ui", "status", "upgrade", "pocket", "visitors", "navigation", "flight",
|
||||
"border", "spawnable", "bossbar"
|
||||
),
|
||||
command.onTabComplete(null, null, "basesettings", new String[] {""})
|
||||
);
|
||||
@@ -526,7 +542,7 @@ final class BaseSettingsCommandTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultAndStatusDisplayTheFullProgressReport() {
|
||||
void defaultAndUiOpenDialogWhileStatusDisplaysTheFullProgressReport() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(playerId);
|
||||
@@ -542,17 +558,19 @@ final class BaseSettingsCommandTest {
|
||||
);
|
||||
|
||||
command.onCommand(player, null, "basesettings", new String[0]);
|
||||
command.onCommand(player, null, "homesettings", new String[] {"ui"});
|
||||
command.onCommand(player, null, "basesettings", new String[] {"status"});
|
||||
|
||||
verify(player, times(2)).sendMessage(ChatColor.GOLD + "=== Base Progress ===");
|
||||
verify(player, times(2)).sendMessage(
|
||||
verify(player, times(2)).showDialog(any(Dialog.class));
|
||||
verify(player).sendMessage(ChatColor.GOLD + "=== Base Progress ===");
|
||||
verify(player).sendMessage(
|
||||
org.mockito.ArgumentMatchers.<String>argThat(message ->
|
||||
message.contains("Spawnable Overlay:")
|
||||
&& message.contains("0/250 placements")
|
||||
&& message.contains("locked")
|
||||
)
|
||||
);
|
||||
verify(player, times(2)).sendMessage(
|
||||
verify(player).sendMessage(
|
||||
org.mockito.ArgumentMatchers.<String>argThat(message ->
|
||||
message.contains("Settings: visitors=")
|
||||
&& message.contains("navigation=")
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import net.md_5.bungee.api.dialog.ConfirmationDialog;
|
||||
import net.md_5.bungee.api.dialog.Dialog;
|
||||
import net.md_5.bungee.api.dialog.DialogListDialog;
|
||||
import net.md_5.bungee.api.dialog.MultiActionDialog;
|
||||
import net.md_5.bungee.api.dialog.NoticeDialog;
|
||||
import net.md_5.bungee.api.dialog.action.Action;
|
||||
import net.md_5.bungee.api.dialog.action.ActionButton;
|
||||
import net.md_5.bungee.api.dialog.action.RunCommandAction;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class BaseSettingsDialogFactoryTest {
|
||||
@Test
|
||||
void createsControlsForEveryBaseSettingAndConfirmedPurchase() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState owner = PlayerState.newPlayer(playerId, "Builder")
|
||||
.withAdministrativeLevels(4, 2, 2, 1, 1, true, true, true)
|
||||
.withBase(
|
||||
new BaseLocation(UUID.randomUUID(), "world", 10, 64, 20, 10, 20),
|
||||
Instant.EPOCH
|
||||
)
|
||||
.withBorderEnabled(true)
|
||||
.withTotalBlocksPlaced(250)
|
||||
.withSpawnableOverlayEnabled(true);
|
||||
PocketBaseState pocket = new PocketBaseState(
|
||||
playerId,
|
||||
1,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
true,
|
||||
false,
|
||||
PocketBaseBiome.PLAINS
|
||||
);
|
||||
|
||||
Dialog dialog = new BaseSettingsDialogFactory(
|
||||
PluginSettings.from(Map.of())
|
||||
).create(owner, pocket);
|
||||
|
||||
DialogListDialog root = assertInstanceOf(DialogListDialog.class, dialog);
|
||||
assertTrue(root.getBase().body().get(0).toString().contains("Base 4/4"));
|
||||
List<String> commands = commands(root);
|
||||
assertTrue(commands.contains("/basesettings status"));
|
||||
assertTrue(commands.contains("/basesettings visitors blocked"));
|
||||
assertTrue(commands.contains("/basesettings navigation disable"));
|
||||
assertTrue(commands.contains("/basesettings flight disable"));
|
||||
assertTrue(commands.contains("/basesettings border disable"));
|
||||
assertTrue(commands.contains("/basesettings spawnable disable"));
|
||||
assertTrue(commands.contains("/basesettings bossbar disable"));
|
||||
assertTrue(commands.contains("/basesettings pocket upgrade"));
|
||||
assertTrue(commands.contains("/basesettings pocket mobs hostile disable"));
|
||||
assertTrue(commands.contains("/basesettings pocket mobs passive enable"));
|
||||
assertTrue(commands.contains("/basesettings pocket type nether crimson_forest"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void requiresConfirmationForBaseIvPurchase() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState owner = PlayerState.newPlayer(playerId, "Builder")
|
||||
.withAdministrativeLevels(3, 0, 0, 0, 0, false, false, false)
|
||||
.withBase(
|
||||
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
|
||||
Instant.EPOCH
|
||||
);
|
||||
|
||||
DialogListDialog root = assertInstanceOf(
|
||||
DialogListDialog.class,
|
||||
new BaseSettingsDialogFactory(PluginSettings.from(Map.of())).create(
|
||||
owner,
|
||||
PocketBaseState.locked(playerId)
|
||||
)
|
||||
);
|
||||
ConfirmationDialog upgrade = assertInstanceOf(
|
||||
ConfirmationDialog.class,
|
||||
root.dialogs().get(2)
|
||||
);
|
||||
|
||||
RunCommandAction action = assertInstanceOf(
|
||||
RunCommandAction.class,
|
||||
upgrade.yes().action()
|
||||
);
|
||||
assertTrue(action.template().equals("/basesettings upgrade"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void marksUnavailableControlsAsLocked() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState owner = PlayerState.newPlayer(playerId, "Newcomer");
|
||||
|
||||
DialogListDialog root = assertInstanceOf(
|
||||
DialogListDialog.class,
|
||||
new BaseSettingsDialogFactory(PluginSettings.from(Map.of())).create(
|
||||
owner,
|
||||
PocketBaseState.locked(playerId)
|
||||
)
|
||||
);
|
||||
MultiActionDialog controls = assertInstanceOf(
|
||||
MultiActionDialog.class,
|
||||
root.dialogs().get(0)
|
||||
);
|
||||
List<String> labels = controls.actions().stream()
|
||||
.map(ActionButton::label)
|
||||
.map(Object::toString)
|
||||
.toList();
|
||||
|
||||
assertTrue(labels.stream().anyMatch(label -> label.contains("Visitors: Locked")));
|
||||
assertTrue(labels.stream().anyMatch(label -> label.contains("Navigation: Locked")));
|
||||
assertTrue(labels.stream().anyMatch(label -> label.contains("Flight: Locked")));
|
||||
assertTrue(labels.stream().anyMatch(label -> label.contains("Border: Locked")));
|
||||
assertTrue(labels.stream().anyMatch(label -> label.contains("Spawnable Overlay: Locked")));
|
||||
}
|
||||
|
||||
private static List<String> commands(Dialog dialog) {
|
||||
List<String> commands = new ArrayList<>();
|
||||
collect(dialog, commands);
|
||||
return commands;
|
||||
}
|
||||
|
||||
private static void collect(Dialog dialog, List<String> commands) {
|
||||
if (dialog instanceof DialogListDialog list) {
|
||||
list.dialogs().forEach(child -> collect(child, commands));
|
||||
collect(list.exitAction(), commands);
|
||||
} else if (dialog instanceof MultiActionDialog actions) {
|
||||
actions.actions().forEach(button -> collect(button, commands));
|
||||
collect(actions.exitAction(), commands);
|
||||
} else if (dialog instanceof ConfirmationDialog confirmation) {
|
||||
collect(confirmation.yes(), commands);
|
||||
collect(confirmation.no(), commands);
|
||||
} else if (dialog instanceof NoticeDialog notice) {
|
||||
collect(notice.action(), commands);
|
||||
}
|
||||
}
|
||||
|
||||
private static void collect(ActionButton button, List<String> commands) {
|
||||
if (button == null) {
|
||||
return;
|
||||
}
|
||||
Action action = button.action();
|
||||
if (action instanceof RunCommandAction command) {
|
||||
commands.add(command.template());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user