feat(tamer): limit custody to one mob
This commit is contained in:
@@ -28,6 +28,21 @@ final class CapturedMobServiceTest {
|
||||
assertEquals(java.util.List.of(), released.capturedMobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
void tamerMustReleaseHeldMobBeforeCapturingAnother() {
|
||||
PlayerState holding = service.capture(
|
||||
tamer(), UUID.randomUUID(), "COW", "cow-snapshot"
|
||||
);
|
||||
|
||||
IllegalStateException exception = assertThrows(IllegalStateException.class, () ->
|
||||
service.capture(holding, UUID.randomUUID(), "SHEEP", "sheep-snapshot")
|
||||
);
|
||||
|
||||
assertEquals("release the currently captured mob before capturing another",
|
||||
exception.getMessage());
|
||||
assertEquals(1, holding.capturedMobs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void enderDragonCanNeverBeCapturedAndMissingReleaseDoesNotMutate() {
|
||||
assertThrows(IllegalArgumentException.class, () -> service.capture(
|
||||
|
||||
@@ -12,6 +12,28 @@ import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class DefaultCapturedMobCustodyReleaseTest {
|
||||
@Test
|
||||
void legacyExcessReleaseRetainsOneAndAnyFailedExtra() {
|
||||
UUID playerId = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||
CapturedMob retained = mob("COW");
|
||||
CapturedMob releasedExtra = mob("SHEEP");
|
||||
CapturedMob deferredExtra = mob("PIG");
|
||||
PlayerState state = new PlayerState(
|
||||
playerId, "Tamer", Optional.empty(), Optional.empty(), TyrantClass.TAMER,
|
||||
Optional.empty(), Map.of(), java.util.Set.of(),
|
||||
List.of(retained, releasedExtra, deferredExtra)
|
||||
);
|
||||
CapturedMobSpawner spawner = mock(CapturedMobSpawner.class);
|
||||
Player player = mock(Player.class);
|
||||
when(spawner.spawn(player, releasedExtra)).thenReturn(true);
|
||||
when(spawner.spawn(player, deferredExtra)).thenReturn(false);
|
||||
DefaultCapturedMobCustodyRelease service = new DefaultCapturedMobCustodyRelease(spawner);
|
||||
|
||||
PlayerState result = service.releaseExcess(player, state, 1);
|
||||
|
||||
assertEquals(List.of(retained, deferredExtra), result.capturedMobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
void removesOnlyCustodyThatSpawnedSuccessfully() {
|
||||
UUID playerId = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||
|
||||
@@ -31,6 +31,28 @@ final class FormerTamerReleaseTaskTest {
|
||||
verify(release, never()).releaseAll(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void safelyReleasesLegacyCustodyAboveOneForActiveTamer() {
|
||||
UUID tamerId = UUID.fromString("44444444-4444-4444-4444-444444444444");
|
||||
PlayerState once = withMob(withClass(
|
||||
PlayerState.newPlayer(tamerId, "Tamer"), TyrantClass.TAMER
|
||||
));
|
||||
PlayerState legacy = withMob(once);
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.players()).thenReturn(Map.of(tamerId, legacy));
|
||||
Player tamer = mock(Player.class);
|
||||
when(tamer.getUniqueId()).thenReturn(tamerId);
|
||||
Server server = mock(Server.class);
|
||||
doReturn(Set.of(tamer)).when(server).getOnlinePlayers();
|
||||
CapturedMobCustodyRelease release = mock(CapturedMobCustodyRelease.class);
|
||||
when(release.releaseExcess(tamer, legacy, 1)).thenReturn(legacy);
|
||||
|
||||
new FormerTamerReleaseTask(manager, server, release).run();
|
||||
|
||||
verify(release).releaseExcess(tamer, legacy, 1);
|
||||
verify(release, never()).releaseAll(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void releasesCustodyOnlyAfterPlayerLosesTamerClass() {
|
||||
UUID formerId = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||
@@ -61,10 +83,12 @@ final class FormerTamerReleaseTaskTest {
|
||||
CapturedMob mob = new CapturedMob("COW", Map.of(
|
||||
"capture-id", UUID.randomUUID().toString(), "snapshot", "snapshot"
|
||||
));
|
||||
java.util.List<CapturedMob> custody = new java.util.ArrayList<>(player.capturedMobs());
|
||||
custody.add(mob);
|
||||
return new PlayerState(
|
||||
player.playerId(), player.latestName(), player.lastLogin(), player.optedOutUntil(),
|
||||
player.tyrantClass(), player.followerOf(), player.cooldownEnds(),
|
||||
player.readyAbilityItems(), java.util.List.of(mob)
|
||||
player.readyAbilityItems(), custody
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
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.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class TamerListenerTest {
|
||||
@Test
|
||||
void heldMobRejectsAnotherCaptureBeforeTargetOrInventoryChanges() {
|
||||
UUID playerId = UUID.fromString("33333333-3333-3333-3333-333333333333");
|
||||
CapturedMob heldMob = new CapturedMob("COW", Map.of(
|
||||
"capture-id", UUID.randomUUID().toString(), "snapshot", "cow"
|
||||
));
|
||||
PlayerState state = new PlayerState(
|
||||
playerId, "Tamer", Optional.empty(), Optional.empty(), TyrantClass.TAMER,
|
||||
Optional.empty(), Map.of(), Set.of(Ability.TAMER_CAPTURE),
|
||||
java.util.List.of(heldMob)
|
||||
);
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(playerId);
|
||||
when(player.getName()).thenReturn("Tamer");
|
||||
PlayerInventory inventory = mock(PlayerInventory.class);
|
||||
when(player.getInventory()).thenReturn(inventory);
|
||||
ItemStack lead = mock(ItemStack.class);
|
||||
when(inventory.getItem(org.bukkit.inventory.EquipmentSlot.HAND)).thenReturn(lead);
|
||||
Entity target = mock(Entity.class);
|
||||
PlayerInteractEntityEvent event = mock(PlayerInteractEntityEvent.class);
|
||||
when(event.getPlayer()).thenReturn(player);
|
||||
when(event.getHand()).thenReturn(org.bukkit.inventory.EquipmentSlot.HAND);
|
||||
when(event.getRightClicked()).thenReturn(target);
|
||||
AbilityItemService abilityItems = mock(AbilityItemService.class);
|
||||
when(abilityItems.ability(lead)).thenReturn(Optional.of(Ability.TAMER_CAPTURE));
|
||||
when(abilityItems.owner(lead)).thenReturn(Optional.of(playerId));
|
||||
TyrantStateManager manager = mock(TyrantStateManager.class);
|
||||
when(manager.player(playerId, "Tamer")).thenReturn(state);
|
||||
CapturedMobItemService capturedItems = mock(CapturedMobItemService.class);
|
||||
TamerListener listener = new TamerListener(
|
||||
manager, abilityItems, capturedItems, new CapturedMobService(),
|
||||
PluginSettings.from(Map.of()), mock(Server.class)
|
||||
);
|
||||
|
||||
listener.onCapture(event);
|
||||
|
||||
verify(player).sendMessage(org.mockito.ArgumentMatchers.contains(
|
||||
"Release the currently captured mob"
|
||||
));
|
||||
verify(target, never()).createSnapshot();
|
||||
verify(capturedItems, never()).create(
|
||||
org.mockito.ArgumentMatchers.any(), org.mockito.ArgumentMatchers.any(),
|
||||
org.mockito.ArgumentMatchers.anyString()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user