Files
purpur-base/src/test/java/games/dmg/spigotbase/BaseSettingsCommandTest.java
T
dmg e0b1a25c5e
Release / release (push) Successful in 2m50s
CI / build (push) Successful in 1m15s
feat(pocket-base): share flight through gold portals
2026-08-29 00:20:40 -04:00

674 lines
28 KiB
Java

package games.dmg.spigotbase;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
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.kyori.adventure.dialog.DialogLike;
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();
PlayerState current = PlayerState.newPlayer(playerId, "Builder")
.withAdministrativeLevels(1, 0, 0, 0, 0, false, false, false)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
)
.withTotalBlocksPlaced(250);
CommandResult result = execute(current, "spawnable", "enable");
assertTrue(result.updated().spawnableOverlayEnabled());
}
@Test
void borderEnableIsIdempotent() {
UUID playerId = UUID.randomUUID();
PlayerState current = PlayerState.newPlayer(playerId, "Builder")
.withAdministrativeLevels(1, 0, 0, 0, 0, false, false, false)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
);
CommandResult result = execute(current, "border", "enable");
assertTrue(result.updated().borderEnabled());
}
@Test
void invalidArgumentsShowUsage() {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class)
);
command.onCommand(player, null, "basesettings", new String[] {"unknown"});
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("Usage: /basesettings")
));
}
@Test
void autocompletesValuesForEachSetting() {
BaseSettingsCommand command = new BaseSettingsCommand(
mock(BaseStateManager.class),
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class)
);
assertEquals(
List.of("allowed"),
command.onTabComplete(null, null, "basesettings", new String[] {"visitors", "a"})
);
assertEquals(
List.of("upgrade"),
command.onTabComplete(null, null, "basesettings", new String[] {"pocket", "u"})
);
assertEquals(
List.of("flight"),
command.onTabComplete(null, null, "basesettings", new String[] {"pocket", "f"})
);
assertEquals(
List.of("disable"),
command.onTabComplete(
null, null, "basesettings", new String[] {"pocket", "flight", "d"}
)
);
assertEquals(
List.of("mobs"),
command.onTabComplete(null, null, "basesettings", new String[] {"pocket", "m"})
);
assertEquals(
List.of("type"),
command.onTabComplete(null, null, "basesettings", new String[] {"pocket", "t"})
);
assertEquals(
List.of("nether"),
command.onTabComplete(
null, null, "basesettings", new String[] {"pocket", "type", "n"}
)
);
assertEquals(
List.of("crimson_forest"),
command.onTabComplete(
null,
null,
"basesettings",
new String[] {"pocket", "type", "nether", "c"}
)
);
assertEquals(
List.of("hostile"),
command.onTabComplete(
null, null, "basesettings", new String[] {"pocket", "mobs", "h"}
)
);
assertEquals(
List.of("passive"),
command.onTabComplete(
null, null, "basesettings", new String[] {"pocket", "mobs", "p"}
)
);
assertEquals(
List.of("enable"),
command.onTabComplete(
null, null, "basesettings",
new String[] {"pocket", "mobs", "hostile", "e"}
)
);
for (String setting : List.of("navigation", "flight", "border", "spawnable", "bossbar")) {
assertEquals(
List.of("disable"),
command.onTabComplete(null, null, "basesettings", new String[] {setting, "d"})
);
}
}
@Test
void autocompletesSettingNames() {
BaseSettingsCommand command = new BaseSettingsCommand(
mock(BaseStateManager.class),
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class)
);
assertEquals(
List.of(
"ui", "status", "upgrade", "pocket", "visitors", "navigation", "flight",
"border", "spawnable", "bossbar"
),
command.onTabComplete(null, null, "basesettings", new String[] {""})
);
}
@Test
void upgradePurchasesBaseIv() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Host");
PlayerInventory inventory = mock(PlayerInventory.class);
ItemStack firstStack = item(Material.DIAMOND, 64);
ItemStack secondStack = item(Material.DIAMOND, 64);
when(player.getInventory()).thenReturn(inventory);
when(inventory.getStorageContents()).thenReturn(new ItemStack[] {
firstStack,
secondStack
});
PlayerState current = PlayerState.newPlayer(playerId, "Host")
.withAdministrativeLevels(3, 0, 0, 0, 0, false, false, false)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
);
AtomicReference<PlayerState> updated = new AtomicReference<>();
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Host")).thenReturn(current);
when(stateManager.updateAndSave(any(), anyString(), any())).thenAnswer(invocation -> {
@SuppressWarnings("unchecked")
UnaryOperator<PlayerState> operation = invocation.getArgument(2);
PlayerState result = operation.apply(current);
updated.set(result);
return result;
});
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class)
);
command.onCommand(player, null, "basesettings", new String[] {"upgrade"});
assertEquals(4, updated.get().baseLevel());
assertTrue(updated.get().visitorsEnabled());
}
@Test
void pocketUpgradePurchasesFirstLevelAfterBaseIv() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
PlayerInventory inventory = mock(PlayerInventory.class);
ItemStack currency = item(Material.DIAMOND_BLOCK, 64);
when(player.getInventory()).thenReturn(inventory);
when(inventory.getStorageContents()).thenReturn(new ItemStack[] {currency});
PlayerState owner = PlayerState.newPlayer(playerId, "Builder")
.withAdministrativeLevels(4, 0, 0, 0, 0, false, false, true)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
);
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder")).thenReturn(owner);
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(PocketBaseState.locked(playerId));
when(pocketBases.upgrade(playerId)).thenReturn(
new PocketBaseState(playerId, 1, java.util.Optional.empty())
);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {"pocket", "upgrade"});
verify(pocketBases).upgrade(playerId);
verify(inventory).setStorageContents(any(ItemStack[].class));
}
@Test
void pocketOwnerCanPurchaseBiomeChangeWithConfiguredCurrency() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
PlayerInventory inventory = mock(PlayerInventory.class);
ItemStack currency = item(Material.NETHERITE_BLOCK, 16);
when(player.getInventory()).thenReturn(inventory);
when(inventory.getStorageContents()).thenReturn(new ItemStack[] {currency});
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
PocketBaseState current = new PocketBaseState(playerId, 1, java.util.Optional.empty());
when(pocketBases.state(playerId)).thenReturn(current);
when(pocketBases.setBiome(playerId, PocketBaseBiome.CRIMSON_FOREST))
.thenReturn(current.withBiome(PocketBaseBiome.CRIMSON_FOREST));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {
"pocket", "type", "nether", "crimson_forest"
});
verify(pocketBases).setBiome(playerId, PocketBaseBiome.CRIMSON_FOREST);
verify(inventory).setStorageContents(any(ItemStack[].class));
}
@Test
void selectingCurrentPocketBiomeDoesNotCharge() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
PlayerInventory inventory = mock(PlayerInventory.class);
when(player.getInventory()).thenReturn(inventory);
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(
new PocketBaseState(playerId, 1, java.util.Optional.empty())
);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {
"pocket", "type", "void", "the_void"
});
verify(pocketBases, never()).setBiome(
org.mockito.ArgumentMatchers.eq(playerId),
org.mockito.ArgumentMatchers.any(PocketBaseBiome.class)
);
verify(inventory, never()).setStorageContents(any(ItemStack[].class));
}
@Test
void pocketOwnerCanEnableHostileMobSpawningWithoutChangingPassive() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
PocketBaseState current = new PocketBaseState(
playerId, 1, java.util.Optional.empty(), java.util.Optional.empty(),
false, true, PocketBaseBiome.THE_VOID
);
when(pocketBases.state(playerId)).thenReturn(current);
when(pocketBases.setHostileMobSpawning(playerId, true)).thenReturn(
current.withHostileMobSpawningEnabled(true)
);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {
"pocket", "mobs", "hostile", "enable"
});
verify(pocketBases).setHostileMobSpawning(playerId, true);
verify(pocketBases, never()).setPassiveMobSpawning(playerId, true);
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("hostile mob spawning") && message.contains("enabled")
));
}
@Test
void failedPocketMobSpawningChangeReportsOnlyFailure() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(
new PocketBaseState(playerId, 1, java.util.Optional.empty())
);
when(pocketBases.setPassiveMobSpawning(playerId, true))
.thenThrow(new IOException("save failed"));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {
"pocket", "mobs", "passive", "enable"
});
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("could not be changed")
));
verify(player, never()).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("is now")
));
}
@Test
void lockedPlayerCannotEnablePocketMobSpawning() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(PocketBaseState.locked(playerId));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {
"pocket", "mobs", "hostile", "enable"
});
verify(pocketBases, never()).setHostileMobSpawning(playerId, true);
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("Pocket Base I") && message.contains("locked")
));
}
@Test
void failedPocketUpgradeRestoresPayment() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
PlayerInventory inventory = mock(PlayerInventory.class);
ItemStack currency = item(Material.DIAMOND_BLOCK, 64);
when(player.getInventory()).thenReturn(inventory);
when(inventory.getStorageContents()).thenReturn(new ItemStack[] {currency});
PlayerState owner = PlayerState.newPlayer(playerId, "Builder")
.withAdministrativeLevels(4, 0, 0, 0, 0, false, false, true)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
);
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder")).thenReturn(owner);
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(PocketBaseState.locked(playerId));
when(pocketBases.upgrade(playerId)).thenThrow(new IOException("save failed"));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {"pocket", "upgrade"});
ArgumentCaptor<ItemStack[]> contents = ArgumentCaptor.forClass(ItemStack[].class);
verify(inventory, times(2)).setStorageContents(contents.capture());
ItemStack[] restored = contents.getAllValues().get(1);
assertEquals(Material.DIAMOND_BLOCK, restored[0].getType());
assertEquals(64, restored[0].getAmount());
}
@Test
void ownerCanDisableAutomaticPocketBaseFlight() throws Exception {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder")).thenReturn(
PlayerState.newPlayer(playerId, "Builder")
);
PocketBaseState enabled = new PocketBaseState(playerId, 1, Optional.empty())
.withFlightUnlocked();
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(enabled);
when(pocketBases.setFlightEnabled(playerId, false)).thenReturn(
enabled.withFlightEnabled(false)
);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(
player, null, "basesettings",
new String[] {"pocket", "flight", "disable"}
);
verify(pocketBases).setFlightEnabled(playerId, false);
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("automatic flight") && message.contains("disabled")
));
}
@Test
void statusDisplaysPocketMobSpawningPreferences() {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
PocketBaseManager pocketBases = mock(PocketBaseManager.class);
when(pocketBases.state(playerId)).thenReturn(
new PocketBaseState(
playerId, 1, java.util.Optional.empty(), java.util.Optional.empty(),
true, false, PocketBaseBiome.THE_VOID
)
);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
pocketBases
);
command.onCommand(player, null, "basesettings", new String[] {"status"});
verify(player).sendMessage(org.mockito.ArgumentMatchers.<String>argThat(
message -> message.contains("Pocket Base 1")
&& message.contains("type=void/the_void")
&& message.contains("hostile spawning=enabled")
&& message.contains("passive spawning=disabled")
&& message.contains("flight=complete a raid to unlock")
));
}
@Test
void bossbarEnableIsIdempotent() {
UUID playerId = UUID.randomUUID();
PlayerState current = PlayerState.newPlayer(playerId, "Miner");
CommandResult result = execute(current, "bossbar", "enable");
assertTrue(result.updated().bossBarEnabled());
}
@Test
void flightDisableIsIdempotentAndRemovesGrantedFlight() {
UUID playerId = UUID.randomUUID();
PlayerState current = PlayerState.newPlayer(playerId, "Pilot")
.withAdministrativeLevels(1, 0, 1, 0, 0, false, true, false);
CommandResult result = execute(current, "flight", "disable");
assertFalse(result.updated().flightEnabled());
verify(result.flightController()).removeGrantedFlight(any(Player.class));
}
@Test
void navigationDisableIsIdempotent() {
UUID playerId = UUID.randomUUID();
PlayerState current = PlayerState.newPlayer(playerId, "Explorer")
.withAdministrativeLevels(2, 0, 0, 0, 0, true, false, false)
.withBase(
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
Instant.EPOCH
);
CommandResult result = execute(current, "navigation", "disable");
assertFalse(result.updated().navigationEnabled());
}
@Test
void visitorsAllowedIsIdempotent() {
UUID playerId = UUID.randomUUID();
PlayerState current = PlayerState.newPlayer(playerId, "Host")
.withAdministrativeLevels(4, 0, 0, 0, 0, false, false, true);
CommandResult result = execute(current, "visitors", "allowed");
assertTrue(result.updated().visitorsEnabled());
}
@Test
void defaultAndUiOpenDialogWhileStatusDisplaysTheFullProgressReport() {
UUID playerId = UUID.randomUUID();
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerId);
when(player.getName()).thenReturn("Builder");
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(playerId, "Builder"))
.thenReturn(PlayerState.newPlayer(playerId, "Builder"));
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
mock(BaseFlightController.class),
null,
(owner, pocket) -> null
);
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)).showDialog((DialogLike) null);
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).sendMessage(
org.mockito.ArgumentMatchers.<String>argThat(message ->
message.contains("Settings: visitors=")
&& message.contains("navigation=")
&& message.contains("flight=")
&& message.contains("border=")
&& message.contains("spawnable=")
&& message.contains("bossbar=")
)
);
}
private static ItemStack item(Material material, int amount) {
ItemStack item = mock(ItemStack.class);
ItemStack copy = mock(ItemStack.class);
when(item.getType()).thenReturn(material);
when(item.getAmount()).thenReturn(amount);
when(item.clone()).thenReturn(copy);
when(copy.getType()).thenReturn(material);
when(copy.getAmount()).thenReturn(amount);
when(copy.clone()).thenReturn(copy);
return item;
}
private static CommandResult execute(PlayerState current, String... arguments) {
Player player = mock(Player.class);
when(player.getUniqueId()).thenReturn(current.playerId());
when(player.getName()).thenReturn(current.latestName());
AtomicReference<PlayerState> updated = new AtomicReference<>();
BaseStateManager stateManager = mock(BaseStateManager.class);
when(stateManager.player(current.playerId(), current.latestName())).thenReturn(current);
when(stateManager.update(any(), anyString(), any())).thenAnswer(invocation -> {
@SuppressWarnings("unchecked")
UnaryOperator<PlayerState> operation = invocation.getArgument(2);
PlayerState result = operation.apply(current);
updated.set(result);
return result;
});
BaseFlightController flightController = mock(BaseFlightController.class);
BaseSettingsCommand command = new BaseSettingsCommand(
stateManager,
new PluginSettingsProvider(PluginSettings.from(Map.of())),
flightController
);
command.onCommand(player, null, "basesettings", arguments);
return new CommandResult(updated.get(), flightController);
}
private record CommandResult(PlayerState updated, BaseFlightController flightController) {
}
}