feat(tamer): limit custody to one mob
Release / release (push) Successful in 2m42s
CI / build (push) Successful in 1m11s

This commit is contained in:
dmg
2026-08-21 21:47:42 -04:00
parent 34f32cd32d
commit 80810b3ba1
11 changed files with 182 additions and 8 deletions
@@ -2,7 +2,8 @@ package games.dmg.spigottyrant;
import org.bukkit.entity.Player;
@FunctionalInterface
public interface CapturedMobCustodyRelease {
PlayerState releaseAll(Player player, PlayerState state);
PlayerState releaseExcess(Player player, PlayerState state, int custodyLimit);
}
@@ -16,6 +16,11 @@ public final class CapturedMobService {
if (player.tyrantClass() != TyrantClass.TAMER) {
throw new IllegalStateException("only a Tamer can capture mobs");
}
if (!player.capturedMobs().isEmpty()) {
throw new IllegalStateException(
"release the currently captured mob before capturing another"
);
}
if ("ENDER_DRAGON".equalsIgnoreCase(entityType)) {
throw new IllegalArgumentException("Ender Dragons cannot be captured");
}
@@ -13,13 +13,27 @@ public final class DefaultCapturedMobCustodyRelease implements CapturedMobCustod
@Override
public PlayerState releaseAll(Player player, PlayerState state) {
return releaseExcess(player, state, 0);
}
@Override
public PlayerState releaseExcess(
Player player,
PlayerState state,
int custodyLimit
) {
if (custodyLimit < 0) {
throw new IllegalArgumentException("custodyLimit must not be negative");
}
List<CapturedMob> retained = new ArrayList<>();
for (CapturedMob mob : state.capturedMobs()) {
if (!spawner.spawn(player, mob)) {
List<CapturedMob> custody = state.capturedMobs();
for (int index = 0; index < custody.size(); index++) {
CapturedMob mob = custody.get(index);
if (index < custodyLimit || !spawner.spawn(player, mob)) {
retained.add(mob);
}
}
if (retained.size() == state.capturedMobs().size()) {
if (retained.equals(custody)) {
return state;
}
return new PlayerState(
@@ -37,14 +37,18 @@ public final class FormerTamerReleaseTask implements Runnable {
Map<UUID, Player> online = server.getOnlinePlayers().stream()
.collect(Collectors.toMap(Player::getUniqueId, player -> player));
for (PlayerState state : stateManager.players().values()) {
if (state.tyrantClass() == TyrantClass.TAMER || state.capturedMobs().isEmpty()) {
if (state.capturedMobs().isEmpty()
|| state.tyrantClass() == TyrantClass.TAMER
&& state.capturedMobs().size() == 1) {
continue;
}
Player player = online.get(state.playerId());
if (player == null || player.isDead()) {
continue;
}
PlayerState released = release.releaseAll(player, state);
PlayerState released = state.tyrantClass() == TyrantClass.TAMER
? release.releaseExcess(player, state, 1)
: release.releaseAll(player, state);
if (released.equals(state)) {
continue;
}
@@ -63,6 +63,11 @@ public final class TamerListener implements Listener {
return;
}
PlayerState state = stateManager.player(player.getUniqueId(), player.getName());
if (!state.capturedMobs().isEmpty()) {
player.sendMessage(ChatColor.RED
+ "Release the currently captured mob before capturing another.");
return;
}
Entity target = event.getRightClicked();
if (!canCapture(state, target)) {
player.sendMessage(ChatColor.RED + "That mob cannot be captured.");