feat(spawning): add spawnable block overlay
This commit is contained in:
@@ -11,6 +11,19 @@ final class AdminProgressCounterTest {
|
||||
new PluginSettingsProvider(PluginSettings.from(Map.of()))
|
||||
);
|
||||
|
||||
@Test
|
||||
void settingTotalPlacementCounterUnlocksSpawnableOverlay() {
|
||||
PlayerState player = PlayerState.newPlayer(UUID.randomUUID(), "Alex");
|
||||
|
||||
PlayerState updated = service.setProgress(
|
||||
player,
|
||||
ProgressCounter.TOTAL_PLACEMENTS,
|
||||
250
|
||||
);
|
||||
|
||||
assertEquals(250, updated.totalBlocksPlaced());
|
||||
}
|
||||
|
||||
@Test
|
||||
void settingPlacementCounterEvaluatesBaseAndWarmupTiers() {
|
||||
PlayerState player = PlayerState.newPlayer(UUID.randomUUID(), "Alex");
|
||||
|
||||
@@ -53,6 +53,24 @@ final class AdminProgressionServiceTest {
|
||||
assertFalse(updated.borderEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void completeResetClearsSpawnableOverlayProgressAndPreference() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState player = PlayerState.newPlayer(playerId, "Alex")
|
||||
.withAdministrativeLevels(1, 0, 0, 0, 0, false, false, false)
|
||||
.withBase(
|
||||
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
|
||||
Instant.EPOCH
|
||||
)
|
||||
.withTotalBlocksPlaced(250)
|
||||
.withSpawnableOverlayEnabled(true);
|
||||
|
||||
PlayerState updated = service.resetPath(player, ProgressionPath.BASE);
|
||||
|
||||
assertEquals(0, updated.totalBlocksPlaced());
|
||||
assertFalse(updated.spawnableOverlayEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnknownLevel() {
|
||||
PlayerState player = PlayerState.newPlayer(UUID.randomUUID(), "Alex");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
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;
|
||||
@@ -9,10 +10,13 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
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.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -22,6 +26,46 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
final class BaseAdminCommandTest {
|
||||
@Test
|
||||
void adminCanEnableUnlockedSpawnableOverlayForPlayer() {
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
when(sender.hasPermission("spigotbase.admin")).thenReturn(true);
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState target = 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);
|
||||
AtomicReference<PlayerState> updated = new AtomicReference<>();
|
||||
BaseStateManager stateManager = mock(BaseStateManager.class);
|
||||
when(stateManager.findByName("Builder")).thenReturn(Optional.of(target));
|
||||
when(stateManager.update(any(), anyString(), any())).thenAnswer(invocation -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
UnaryOperator<PlayerState> operation = invocation.getArgument(2);
|
||||
PlayerState result = operation.apply(target);
|
||||
updated.set(result);
|
||||
return result;
|
||||
});
|
||||
BaseAdminCommand command = new BaseAdminCommand(
|
||||
mock(JavaPlugin.class),
|
||||
stateManager,
|
||||
new AdminProgressionService(
|
||||
new PluginSettingsProvider(PluginSettings.from(Map.of()))
|
||||
),
|
||||
new PluginSettingsProvider(PluginSettings.from(Map.of()))
|
||||
);
|
||||
|
||||
try (MockedStatic<Bukkit> bukkit = mockStatic(Bukkit.class)) {
|
||||
bukkit.when(() -> Bukkit.getPlayerExact("Builder")).thenReturn(null);
|
||||
command.onCommand(sender, null, "baseadmin",
|
||||
new String[] {"setsetting", "Builder", "spawnable", "enable"});
|
||||
}
|
||||
|
||||
assertTrue(updated.get().spawnableOverlayEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidPathShowsFriendlyUsage() {
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
@@ -92,10 +136,23 @@ final class BaseAdminCommandTest {
|
||||
new String[] {"setlevel", "Builder", ""})
|
||||
);
|
||||
assertEquals(
|
||||
List.of("grass_dirt", "stone", "deepslate", "obsidian", "placements", "base_breaks"),
|
||||
List.of(
|
||||
"grass_dirt", "stone", "deepslate", "obsidian", "placements",
|
||||
"total_placements", "base_breaks"
|
||||
),
|
||||
command.onTabComplete(sender, null, "baseadmin",
|
||||
new String[] {"setprogress", "Builder", ""})
|
||||
);
|
||||
assertEquals(
|
||||
List.of("spawnable"),
|
||||
command.onTabComplete(sender, null, "baseadmin",
|
||||
new String[] {"setsetting", "Builder", ""})
|
||||
);
|
||||
assertEquals(
|
||||
List.of("enable"),
|
||||
command.onTabComplete(sender, null, "baseadmin",
|
||||
new String[] {"setsetting", "Builder", "spawnable", "e"})
|
||||
);
|
||||
assertEquals(
|
||||
List.of("personal", "visitor", "all"),
|
||||
command.onTabComplete(sender, null, "baseadmin",
|
||||
@@ -108,6 +165,42 @@ final class BaseAdminCommandTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminCanChangeSpawnableOverlayUnlockThreshold() {
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
when(sender.hasPermission("spigotbase.admin")).thenReturn(true);
|
||||
JavaPlugin plugin = mock(JavaPlugin.class);
|
||||
FileConfiguration configuration = mock(FileConfiguration.class);
|
||||
when(plugin.getConfig()).thenReturn(configuration);
|
||||
when(configuration.get("spawnable-overlay-unlock-placements")).thenReturn(250);
|
||||
when(configuration.getValues(false)).thenReturn(Map.of(
|
||||
"spawnable-overlay-unlock-placements", 250
|
||||
));
|
||||
PluginSettingsProvider settings = new PluginSettingsProvider(
|
||||
PluginSettings.from(Map.of())
|
||||
);
|
||||
BaseAdminCommand command = new BaseAdminCommand(
|
||||
plugin,
|
||||
mock(BaseStateManager.class),
|
||||
mock(AdminProgressionService.class),
|
||||
settings
|
||||
);
|
||||
|
||||
try (MockedStatic<PluginSettingsValidator> validator =
|
||||
mockStatic(PluginSettingsValidator.class)) {
|
||||
validator.when(() -> PluginSettingsValidator.validateMaterials(
|
||||
any(PluginSettings.class)
|
||||
)).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
command.onCommand(sender, null, "baseadmin", new String[] {
|
||||
"config", "spawnable-overlay-unlock-placements", "500"
|
||||
});
|
||||
}
|
||||
|
||||
verify(configuration).set("spawnable-overlay-unlock-placements", 500L);
|
||||
verify(plugin).saveConfig();
|
||||
assertEquals(500, settings.current().spawnableOverlayUnlockPlacements());
|
||||
}
|
||||
|
||||
@Test
|
||||
void autocompletesNumericConfigurationKeys() {
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
@@ -169,7 +262,10 @@ final class BaseAdminCommandTest {
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
List.of("status", "setlevel", "setprogress", "clearcooldown", "reset", "config"),
|
||||
List.of(
|
||||
"status", "setlevel", "setprogress", "setsetting", "clearcooldown", "reset",
|
||||
"config"
|
||||
),
|
||||
command.onTabComplete(sender, null, "baseadmin", new String[] {""})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.UnaryOperator;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class BaseProgressListenerTest {
|
||||
@Test
|
||||
void survivalPlacementOutsideBaseCountsTowardOverlayUnlock() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerState current = PlayerState.newPlayer(playerId, "Builder");
|
||||
AtomicReference<PlayerState> updated = new AtomicReference<>();
|
||||
BaseStateManager stateManager = mock(BaseStateManager.class);
|
||||
when(stateManager.player(playerId, "Builder")).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;
|
||||
});
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(playerId);
|
||||
when(player.getName()).thenReturn("Builder");
|
||||
when(player.getGameMode()).thenReturn(GameMode.SURVIVAL);
|
||||
World world = mock(World.class);
|
||||
when(world.getUID()).thenReturn(UUID.randomUUID());
|
||||
Block block = mock(Block.class);
|
||||
when(block.getWorld()).thenReturn(world);
|
||||
BlockPlaceEvent event = mock(BlockPlaceEvent.class);
|
||||
when(event.getPlayer()).thenReturn(player);
|
||||
when(event.getBlockPlaced()).thenReturn(block);
|
||||
PluginSettingsProvider settings = new PluginSettingsProvider(
|
||||
PluginSettings.from(Map.of())
|
||||
);
|
||||
BaseProgressListener listener = new BaseProgressListener(
|
||||
mock(Plugin.class),
|
||||
stateManager,
|
||||
mock(BaseProgressionService.class),
|
||||
mock(SecondaryProgressionService.class),
|
||||
mock(TeleportProgressionService.class),
|
||||
new SpawnableOverlayProgressionService(settings),
|
||||
new BaseBoundsService(settings),
|
||||
settings
|
||||
);
|
||||
|
||||
listener.onBlockPlace(event);
|
||||
|
||||
assertEquals(1, updated.get().totalBlocksPlaced());
|
||||
assertEquals(0, updated.get().blocksPlacedInBase());
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,22 @@ import org.bukkit.inventory.PlayerInventory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class BaseSettingsCommandTest {
|
||||
@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();
|
||||
@@ -73,7 +89,7 @@ final class BaseSettingsCommandTest {
|
||||
List.of("allowed"),
|
||||
command.onTabComplete(null, null, "basesettings", new String[] {"visitors", "a"})
|
||||
);
|
||||
for (String setting : List.of("navigation", "flight", "border", "bossbar")) {
|
||||
for (String setting : List.of("navigation", "flight", "border", "spawnable", "bossbar")) {
|
||||
assertEquals(
|
||||
List.of("disable"),
|
||||
command.onTabComplete(null, null, "basesettings", new String[] {setting, "d"})
|
||||
@@ -90,7 +106,10 @@ final class BaseSettingsCommandTest {
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
List.of("status", "upgrade", "visitors", "navigation", "flight", "border", "bossbar"),
|
||||
List.of(
|
||||
"status", "upgrade", "visitors", "navigation", "flight", "border",
|
||||
"spawnable", "bossbar"
|
||||
),
|
||||
command.onTabComplete(null, null, "basesettings", new String[] {""})
|
||||
);
|
||||
}
|
||||
@@ -204,12 +223,20 @@ final class BaseSettingsCommandTest {
|
||||
command.onCommand(player, null, "basesettings", new String[] {"status"});
|
||||
|
||||
verify(player, times(2)).sendMessage(ChatColor.GOLD + "=== Base Progress ===");
|
||||
verify(player, times(2)).sendMessage(
|
||||
org.mockito.ArgumentMatchers.<String>argThat(message ->
|
||||
message.contains("Spawnable Overlay:")
|
||||
&& message.contains("0/250 placements")
|
||||
&& message.contains("locked")
|
||||
)
|
||||
);
|
||||
verify(player, times(2)).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=")
|
||||
)
|
||||
);
|
||||
|
||||
@@ -11,6 +11,23 @@ import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class PlayerStateTest {
|
||||
@Test
|
||||
void spawnableOverlayProgressAndPreferenceCanBeUpdated() {
|
||||
PlayerState player = PlayerState.newPlayer(UUID.randomUUID(), "Alex")
|
||||
.withAdministrativeLevels(1, 0, 0, 0, 0, false, false, false)
|
||||
.withBase(
|
||||
new BaseLocation(UUID.randomUUID(), "world", 0, 64, 0, 0, 0),
|
||||
Instant.EPOCH
|
||||
);
|
||||
|
||||
PlayerState updated = player
|
||||
.withTotalBlocksPlaced(250)
|
||||
.withSpawnableOverlayEnabled(true);
|
||||
|
||||
assertTrue(updated.spawnableOverlayEnabled());
|
||||
assertTrue(updated.totalBlocksPlaced() == 250);
|
||||
}
|
||||
|
||||
@Test
|
||||
void borderVisualizationIsDisabledByDefaultAndCanBeEnabled() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
|
||||
@@ -18,6 +18,7 @@ final class PluginSettingsTest {
|
||||
assertEquals(86_400L, settings.relocationCooldownSeconds());
|
||||
assertEquals(5, settings.flightWarningBuffer());
|
||||
assertEquals(200, settings.teleportUnlockPlacements());
|
||||
assertEquals(250, settings.spawnableOverlayUnlockPlacements());
|
||||
assertEquals(10_800L, settings.initialTeleportCooldownSeconds());
|
||||
assertEquals(128, settings.visitorUnlockDiamondCost());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
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.when;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.type.Slab;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class SpawnableBlockPolicyTest {
|
||||
@Test
|
||||
void acceptsDarkSolidSurfaceWithTwoPassableBlocksAbove() {
|
||||
Block surface = mock(Block.class);
|
||||
Block above = mock(Block.class);
|
||||
Block secondAbove = mock(Block.class);
|
||||
Slab slab = mock(Slab.class);
|
||||
when(slab.getType()).thenReturn(Slab.Type.TOP);
|
||||
when(surface.getBlockData()).thenReturn(slab);
|
||||
when(surface.getRelative(BlockFace.UP)).thenReturn(above);
|
||||
when(above.getRelative(BlockFace.UP)).thenReturn(secondAbove);
|
||||
when(above.isPassable()).thenReturn(true);
|
||||
when(secondAbove.isPassable()).thenReturn(true);
|
||||
when(above.getLightFromBlocks()).thenReturn((byte) 0);
|
||||
when(above.getLightFromSky()).thenReturn((byte) 0);
|
||||
|
||||
assertTrue(SpawnableBlockPolicy.isCandidate(surface));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsBlockLitSurface() {
|
||||
Block surface = mock(Block.class);
|
||||
Block above = mock(Block.class);
|
||||
Block secondAbove = mock(Block.class);
|
||||
Slab slab = mock(Slab.class);
|
||||
when(slab.getType()).thenReturn(Slab.Type.TOP);
|
||||
when(surface.getBlockData()).thenReturn(slab);
|
||||
when(surface.getRelative(BlockFace.UP)).thenReturn(above);
|
||||
when(above.getRelative(BlockFace.UP)).thenReturn(secondAbove);
|
||||
when(above.isPassable()).thenReturn(true);
|
||||
when(secondAbove.isPassable()).thenReturn(true);
|
||||
when(above.getLightFromBlocks()).thenReturn((byte) 1);
|
||||
|
||||
assertFalse(SpawnableBlockPolicy.isCandidate(surface));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.type.Slab;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class SpawnableOverlayControllerTest {
|
||||
@Test
|
||||
void ownerReceivesBoundedRedParticlesForNearbyCandidates() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
UUID worldId = UUID.randomUUID();
|
||||
PlayerState state = PlayerState.newPlayer(playerId, "Builder")
|
||||
.withAdministrativeLevels(1, 0, 0, 0, 0, false, false, false)
|
||||
.withBase(new BaseLocation(worldId, "world", 0, 64, 0, 0, 0), Instant.EPOCH)
|
||||
.withTotalBlocksPlaced(250)
|
||||
.withSpawnableOverlayEnabled(true);
|
||||
|
||||
Block surface = mock(Block.class);
|
||||
Block above = mock(Block.class);
|
||||
Block secondAbove = mock(Block.class);
|
||||
Slab slab = mock(Slab.class);
|
||||
when(slab.getType()).thenReturn(Slab.Type.TOP);
|
||||
when(surface.getBlockData()).thenReturn(slab);
|
||||
when(surface.getRelative(BlockFace.UP)).thenReturn(above);
|
||||
when(above.getRelative(BlockFace.UP)).thenReturn(secondAbove);
|
||||
when(above.isPassable()).thenReturn(true);
|
||||
when(secondAbove.isPassable()).thenReturn(true);
|
||||
when(above.getLightFromBlocks()).thenReturn((byte) 0);
|
||||
when(above.getLightFromSky()).thenReturn((byte) 0);
|
||||
|
||||
World world = mock(World.class);
|
||||
when(world.getUID()).thenReturn(worldId);
|
||||
when(world.getMinHeight()).thenReturn(-64);
|
||||
when(world.getMaxHeight()).thenReturn(320);
|
||||
when(world.getBlockAt(anyInt(), anyInt(), anyInt()))
|
||||
.thenReturn(surface);
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(playerId);
|
||||
when(player.getName()).thenReturn("Builder");
|
||||
when(player.getWorld()).thenReturn(world);
|
||||
when(player.getLocation()).thenReturn(new Location(world, 0.5, 65.0, 0.5));
|
||||
Server server = mock(Server.class);
|
||||
doReturn(java.util.List.of(player)).when(server).getOnlinePlayers();
|
||||
BaseStateManager stateManager = mock(BaseStateManager.class);
|
||||
when(stateManager.player(playerId, "Builder")).thenReturn(state);
|
||||
PluginSettingsProvider settings = new PluginSettingsProvider(
|
||||
PluginSettings.from(Map.of())
|
||||
);
|
||||
|
||||
SpawnableOverlayController controller = new SpawnableOverlayController(
|
||||
server,
|
||||
stateManager,
|
||||
new BaseBoundsService(settings),
|
||||
settings
|
||||
);
|
||||
controller.run();
|
||||
controller.run();
|
||||
controller.run();
|
||||
|
||||
verify(player, atLeastOnce()).spawnParticle(
|
||||
eq(Particle.DUST),
|
||||
any(Location.class),
|
||||
eq(1),
|
||||
any(Particle.DustOptions.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package games.dmg.spigotbase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class SpawnableOverlayProgressionServiceTest {
|
||||
@Test
|
||||
void twoHundredFiftiethPlacementUnlocksOverlay() {
|
||||
PlayerState player = PlayerState.newPlayer(UUID.randomUUID(), "Builder")
|
||||
.withTotalBlocksPlaced(249);
|
||||
SpawnableOverlayProgressionService service = new SpawnableOverlayProgressionService(
|
||||
new PluginSettingsProvider(PluginSettings.from(Map.of()))
|
||||
);
|
||||
|
||||
SpawnableOverlayProgressionUpdate update = service.recordPlacement(player);
|
||||
|
||||
assertEquals(250, update.player().totalBlocksPlaced());
|
||||
assertTrue(update.unlocked());
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ final class YamlBaseStateRepositoryTest {
|
||||
Optional.of(Instant.ofEpochMilli(1_750_000_000_000L)),
|
||||
Optional.of(Instant.ofEpochMilli(1_750_000_100_000L)),
|
||||
Map.of(ownerId, Instant.ofEpochMilli(1_750_001_000_000L)),
|
||||
true,
|
||||
2_500,
|
||||
true
|
||||
);
|
||||
PersistentState expected = new PersistentState(Map.of(playerId, player));
|
||||
@@ -40,6 +42,26 @@ final class YamlBaseStateRepositoryTest {
|
||||
assertEquals(expected, repository.load());
|
||||
}
|
||||
|
||||
@Test
|
||||
void olderStateUsesKnownInBasePlacementsAsTotalPlacementMinimum() throws Exception {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
Path stateFile = temporaryDirectory.resolve("state.yml");
|
||||
Files.writeString(stateFile, """
|
||||
players:
|
||||
%s:
|
||||
name: Alex
|
||||
blocks-placed-in-base: 225
|
||||
""".formatted(playerId));
|
||||
|
||||
PlayerState player = new YamlBaseStateRepository(stateFile)
|
||||
.load()
|
||||
.players()
|
||||
.get(playerId);
|
||||
|
||||
assertEquals(225, player.totalBlocksPlaced());
|
||||
assertFalse(player.spawnableOverlayEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void olderStateWithoutBorderPreferenceDefaultsToDisabled() throws Exception {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
|
||||
Reference in New Issue
Block a user