809 lines
24 KiB
Java
809 lines
24 KiB
Java
package com.tiedup.remake.prison;
|
|
|
|
import com.tiedup.remake.core.TiedUpMod;
|
|
import java.util.*;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.stream.Collectors;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.ListTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.level.saveddata.SavedData;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
/**
|
|
* Central manager for all prisoner data.
|
|
*
|
|
* Replaces:
|
|
* - CaptivityStateManager (state tracking)
|
|
* - Prisoner tracking in CellRegistry
|
|
* - Prisoner tracking in CampOwnership
|
|
*
|
|
* This is the SINGLE SOURCE OF TRUTH for prisoner state.
|
|
* All transitions must go through this class.
|
|
*/
|
|
public class PrisonerManager extends SavedData {
|
|
|
|
private static final String DATA_NAME = "tiedup_prisoner_manager";
|
|
|
|
// ==================== PRIMARY DATA ====================
|
|
|
|
/** Player UUID -> PrisonerRecord */
|
|
private final Map<UUID, PrisonerRecord> prisoners =
|
|
new ConcurrentHashMap<>();
|
|
|
|
/** Player UUID -> LaborRecord */
|
|
private final Map<UUID, LaborRecord> laborRecords =
|
|
new ConcurrentHashMap<>();
|
|
|
|
/** Player UUID -> RansomRecord */
|
|
private final Map<UUID, RansomRecord> ransomRecords =
|
|
new ConcurrentHashMap<>();
|
|
|
|
// ==================== INDEXES ====================
|
|
|
|
/** Camp UUID -> Set of prisoner UUIDs */
|
|
private final Map<UUID, Set<UUID>> prisonersByCamp =
|
|
new ConcurrentHashMap<>();
|
|
|
|
/** Cell UUID -> Set of prisoner UUIDs */
|
|
private final Map<UUID, Set<UUID>> prisonersByCell =
|
|
new ConcurrentHashMap<>();
|
|
|
|
// ==================== STATIC ACCESS ====================
|
|
|
|
public static PrisonerManager get(ServerLevel level) {
|
|
return level
|
|
.getDataStorage()
|
|
.computeIfAbsent(
|
|
PrisonerManager::load,
|
|
PrisonerManager::new,
|
|
DATA_NAME
|
|
);
|
|
}
|
|
|
|
public static PrisonerManager get(MinecraftServer server) {
|
|
return get(server.overworld());
|
|
}
|
|
|
|
@Nullable
|
|
public static PrisonerManager get(ServerPlayer player) {
|
|
if (player.getServer() == null) return null;
|
|
return get(player.getServer());
|
|
}
|
|
|
|
// ==================== RECORD ACCESS ====================
|
|
|
|
/**
|
|
* Mark this SavedData as dirty so it gets persisted on next save.
|
|
* Exposed for external callers that modify records directly (e.g., clearing stale guard refs).
|
|
*/
|
|
public void markDirty() {
|
|
setDirty();
|
|
}
|
|
|
|
/**
|
|
* Get or create the prisoner record for a player.
|
|
* Never returns null - creates a FREE record if none exists.
|
|
*/
|
|
public PrisonerRecord getRecord(UUID playerId) {
|
|
return prisoners.computeIfAbsent(playerId, id -> new PrisonerRecord());
|
|
}
|
|
|
|
/**
|
|
* Get the prisoner record if the player is a prisoner (non-FREE state).
|
|
* Returns null if player is FREE or has no record.
|
|
*/
|
|
@Nullable
|
|
public PrisonerRecord getPrisoner(UUID playerId) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
if (record == null || record.getState() == PrisonerState.FREE) {
|
|
return null;
|
|
}
|
|
return record;
|
|
}
|
|
|
|
/**
|
|
* Get or create the labor record for a player.
|
|
*/
|
|
public LaborRecord getLaborRecord(UUID playerId) {
|
|
return laborRecords.computeIfAbsent(playerId, id -> new LaborRecord());
|
|
}
|
|
|
|
/**
|
|
* Get labor record only if one exists. Does not create ghost entries.
|
|
*/
|
|
@Nullable
|
|
public LaborRecord getLaborRecordIfExists(UUID playerId) {
|
|
return laborRecords.get(playerId);
|
|
}
|
|
|
|
/**
|
|
* Set the labor record for a player.
|
|
*/
|
|
public void setLaborRecord(UUID playerId, LaborRecord record) {
|
|
laborRecords.put(playerId, record);
|
|
setDirty();
|
|
}
|
|
|
|
/**
|
|
* Get the ransom record for a player (may be null).
|
|
*/
|
|
@Nullable
|
|
public RansomRecord getRansomRecord(UUID playerId) {
|
|
return ransomRecords.get(playerId);
|
|
}
|
|
|
|
/**
|
|
* Set the ransom record for a player.
|
|
*/
|
|
public void setRansomRecord(UUID playerId, @Nullable RansomRecord record) {
|
|
if (record == null) {
|
|
ransomRecords.remove(playerId);
|
|
} else {
|
|
ransomRecords.put(playerId, record);
|
|
}
|
|
setDirty();
|
|
}
|
|
|
|
/**
|
|
* Create or get ransom record for a player.
|
|
*/
|
|
public RansomRecord getOrCreateRansomRecord(UUID playerId) {
|
|
return ransomRecords.computeIfAbsent(playerId, id ->
|
|
new RansomRecord()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check if a player has any prisoner data.
|
|
*/
|
|
public boolean hasRecord(UUID playerId) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
return record != null && record.getState() != PrisonerState.FREE;
|
|
}
|
|
|
|
// ==================== STATE QUERIES ====================
|
|
|
|
/**
|
|
* Get the current state for a player.
|
|
*/
|
|
public PrisonerState getState(UUID playerId) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
return record != null ? record.getState() : PrisonerState.FREE;
|
|
}
|
|
|
|
/**
|
|
* Check if player is captive (captured or imprisoned).
|
|
*/
|
|
public boolean isCaptive(UUID playerId) {
|
|
return getState(playerId).isCaptive();
|
|
}
|
|
|
|
/**
|
|
* Check if player is imprisoned (in cell or working).
|
|
*/
|
|
public boolean isImprisoned(UUID playerId) {
|
|
return getState(playerId).isImprisoned();
|
|
}
|
|
|
|
/**
|
|
* Check if player can be targeted by kidnappers.
|
|
*/
|
|
public boolean isTargetable(UUID playerId, long currentTime) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
if (record == null) return true;
|
|
return record.isTargetable(currentTime);
|
|
}
|
|
|
|
/**
|
|
* Check if player is protected from capture.
|
|
*/
|
|
public boolean isProtected(UUID playerId, long currentTime) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
if (record == null) return false;
|
|
return record.isProtected(currentTime);
|
|
}
|
|
|
|
// ==================== INDEX QUERIES ====================
|
|
|
|
/**
|
|
* Get all prisoners in a camp.
|
|
*/
|
|
public Set<UUID> getPrisonersInCamp(UUID campId) {
|
|
Set<UUID> prisoners = prisonersByCamp.get(campId);
|
|
return prisoners != null
|
|
? new HashSet<>(prisoners)
|
|
: Collections.emptySet();
|
|
}
|
|
|
|
/**
|
|
* Get all prisoners in a cell.
|
|
*/
|
|
public Set<UUID> getPrisonersInCell(UUID cellId) {
|
|
Set<UUID> prisoners = prisonersByCell.get(cellId);
|
|
return prisoners != null
|
|
? new HashSet<>(prisoners)
|
|
: Collections.emptySet();
|
|
}
|
|
|
|
/**
|
|
* Get prisoner count in a camp.
|
|
*/
|
|
public int getPrisonerCountInCamp(UUID campId) {
|
|
Set<UUID> prisoners = prisonersByCamp.get(campId);
|
|
return prisoners != null ? prisoners.size() : 0;
|
|
}
|
|
|
|
/**
|
|
* Get prisoner count in a cell.
|
|
*/
|
|
public int getPrisonerCountInCell(UUID cellId) {
|
|
Set<UUID> prisoners = prisonersByCell.get(cellId);
|
|
return prisoners != null ? prisoners.size() : 0;
|
|
}
|
|
|
|
/**
|
|
* Get all prisoner IDs (for iteration).
|
|
*/
|
|
public Set<UUID> getAllPrisonerIds() {
|
|
return prisoners
|
|
.keySet()
|
|
.stream()
|
|
.filter(id -> prisoners.get(id).getState() != PrisonerState.FREE)
|
|
.collect(Collectors.toSet());
|
|
}
|
|
|
|
/**
|
|
* Get all prisoners in a specific state.
|
|
*/
|
|
public Set<UUID> getPrisonersInState(PrisonerState state) {
|
|
return prisoners
|
|
.entrySet()
|
|
.stream()
|
|
.filter(e -> e.getValue().getState() == state)
|
|
.map(Map.Entry::getKey)
|
|
.collect(Collectors.toSet());
|
|
}
|
|
|
|
/**
|
|
* Get prisoners in camp with specific state.
|
|
*/
|
|
public Set<UUID> getPrisonersInCampWithState(
|
|
UUID campId,
|
|
PrisonerState state
|
|
) {
|
|
Set<UUID> campPrisoners = prisonersByCamp.get(campId);
|
|
if (campPrisoners == null) return Collections.emptySet();
|
|
|
|
return campPrisoners
|
|
.stream()
|
|
.filter(id -> {
|
|
PrisonerRecord record = prisoners.get(id);
|
|
return record != null && record.getState() == state;
|
|
})
|
|
.collect(Collectors.toSet());
|
|
}
|
|
|
|
// ==================== STATE TRANSITIONS ====================
|
|
|
|
/**
|
|
* Capture a free player.
|
|
*
|
|
* @param playerId Player to capture
|
|
* @param captorId UUID of the kidnapper
|
|
* @param currentTime Current game time
|
|
* @return true if capture was successful
|
|
*/
|
|
public boolean capture(UUID playerId, UUID captorId, long currentTime) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
|
|
if (
|
|
!PrisonerTransition.capture(record, captorId, currentTime, playerId)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Imprison a captured player in a camp cell.
|
|
*
|
|
* @param playerId Player to imprison
|
|
* @param campId Camp UUID
|
|
* @param cellId Cell UUID
|
|
* @param currentTime Current game time
|
|
* @return true if imprisonment was successful
|
|
*/
|
|
public boolean imprison(
|
|
UUID playerId,
|
|
UUID campId,
|
|
UUID cellId,
|
|
long currentTime
|
|
) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
|
|
if (
|
|
!PrisonerTransition.imprison(
|
|
record,
|
|
campId,
|
|
cellId,
|
|
currentTime,
|
|
playerId
|
|
)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
// Update indexes
|
|
addToIndex(prisonersByCamp, campId, playerId);
|
|
addToIndex(prisonersByCell, cellId, playerId);
|
|
|
|
// Initialize labor record
|
|
LaborRecord labor = getLaborRecord(playerId);
|
|
labor.setPhase(LaborRecord.WorkPhase.IDLE, currentTime);
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Extract prisoner from cell for labor.
|
|
*
|
|
* @param playerId Player to extract
|
|
* @param currentTime Current game time
|
|
* @return true if extraction was successful
|
|
*/
|
|
public boolean extract(UUID playerId, long currentTime) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
|
|
if (!PrisonerTransition.extract(record, currentTime, playerId)) {
|
|
return false;
|
|
}
|
|
|
|
// Remove from cell index (still in camp though)
|
|
UUID cellId = record.getCellId();
|
|
if (cellId != null) {
|
|
removeFromIndex(prisonersByCell, cellId, playerId);
|
|
}
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Return prisoner to cell after labor.
|
|
*
|
|
* @param playerId Player to return
|
|
* @param cellId Cell to return to (may be different from original)
|
|
* @param currentTime Current game time
|
|
* @return true if return was successful
|
|
*/
|
|
public boolean returnToCell(UUID playerId, UUID cellId, long currentTime) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
|
|
if (!PrisonerTransition.returnToCell(record, currentTime, playerId)) {
|
|
return false;
|
|
}
|
|
|
|
// Update cell assignment and index
|
|
record.setCellId(cellId);
|
|
addToIndex(prisonersByCell, cellId, playerId);
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Release a prisoner with grace period.
|
|
*
|
|
* @param playerId Player to release
|
|
* @param currentTime Current game time
|
|
* @param gracePeriodTicks Protection duration (default: 6000 = 5 min)
|
|
* @return true if release was successful
|
|
*/
|
|
public boolean release(
|
|
UUID playerId,
|
|
long currentTime,
|
|
long gracePeriodTicks
|
|
) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
UUID campId = record.getCampId();
|
|
UUID cellId = record.getCellId();
|
|
|
|
if (
|
|
!PrisonerTransition.release(
|
|
record,
|
|
currentTime,
|
|
gracePeriodTicks,
|
|
playerId
|
|
)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
// Remove from indexes
|
|
if (campId != null) {
|
|
removeFromIndex(prisonersByCamp, campId, playerId);
|
|
}
|
|
if (cellId != null) {
|
|
removeFromIndex(prisonersByCell, cellId, playerId);
|
|
}
|
|
|
|
// Clear labor and ransom records
|
|
laborRecords.remove(playerId);
|
|
ransomRecords.remove(playerId);
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Release a prisoner with default 5-minute grace period.
|
|
*
|
|
* @param playerId Player to release
|
|
* @param currentTime Current game time
|
|
* @return true if release was successful
|
|
*/
|
|
public boolean release(UUID playerId, long currentTime) {
|
|
return release(playerId, currentTime, 6000); // 5 minutes default
|
|
}
|
|
|
|
/**
|
|
* Transition prisoner from IMPRISONED to WORKING state.
|
|
* Used when extracting for labor.
|
|
*
|
|
* @param playerId Player to transition
|
|
* @param currentTime Current game time
|
|
* @return true if transition was successful
|
|
*/
|
|
public boolean transitionToWorking(UUID playerId, long currentTime) {
|
|
return extract(playerId, currentTime);
|
|
}
|
|
|
|
/**
|
|
* Mark a prisoner as escaped (goes directly to FREE).
|
|
*
|
|
* @param playerId Player who escaped
|
|
* @param currentTime Current game time
|
|
* @param reason Reason for escape (for logging)
|
|
* @return true if escape was processed
|
|
*/
|
|
public boolean escape(UUID playerId, long currentTime, String reason) {
|
|
PrisonerRecord record = getRecord(playerId);
|
|
UUID campId = record.getCampId();
|
|
UUID cellId = record.getCellId();
|
|
|
|
if (!PrisonerTransition.escape(record, currentTime, playerId, reason)) {
|
|
return false;
|
|
}
|
|
|
|
// Remove from indexes
|
|
if (campId != null) {
|
|
removeFromIndex(prisonersByCamp, campId, playerId);
|
|
}
|
|
if (cellId != null) {
|
|
removeFromIndex(prisonersByCell, cellId, playerId);
|
|
}
|
|
|
|
// Clear labor and ransom records
|
|
laborRecords.remove(playerId);
|
|
ransomRecords.remove(playerId);
|
|
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Expire protection (PROTECTED -> FREE).
|
|
*/
|
|
public boolean expireProtection(UUID playerId, long currentTime) {
|
|
PrisonerRecord record = prisoners.get(playerId);
|
|
if (record == null || record.getState() != PrisonerState.PROTECTED) {
|
|
return false;
|
|
}
|
|
|
|
PrisonerTransition.forceTransition(
|
|
record,
|
|
PrisonerState.FREE,
|
|
currentTime
|
|
);
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
// ==================== RANSOM MANAGEMENT ====================
|
|
|
|
/**
|
|
* Create a ransom for a prisoner.
|
|
*
|
|
* @param playerId Prisoner UUID
|
|
* @param totalDebt Total debt amount
|
|
* @param currentTime Current game time
|
|
*/
|
|
public void createRansom(UUID playerId, int totalDebt, long currentTime) {
|
|
RansomRecord ransom = getOrCreateRansomRecord(playerId);
|
|
ransom.setTotalDebt(totalDebt);
|
|
setDirty();
|
|
}
|
|
|
|
/**
|
|
* Add payment to a prisoner's ransom.
|
|
*
|
|
* @param playerId Prisoner UUID
|
|
* @param amount Payment amount
|
|
* @param contributorId Player who paid (null for labor)
|
|
* @return true if ransom is now fully paid
|
|
*/
|
|
public boolean addRansomPayment(
|
|
UUID playerId,
|
|
int amount,
|
|
@Nullable UUID contributorId
|
|
) {
|
|
RansomRecord ransom = ransomRecords.get(playerId);
|
|
if (ransom == null) return false;
|
|
|
|
boolean paid = ransom.addPayment(amount, contributorId);
|
|
setDirty();
|
|
return paid;
|
|
}
|
|
|
|
/**
|
|
* Increase prisoner's debt (punishment).
|
|
*/
|
|
public void increaseDebt(UUID playerId, int amount) {
|
|
RansomRecord ransom = ransomRecords.get(playerId);
|
|
if (ransom != null) {
|
|
ransom.increaseDebt(amount);
|
|
setDirty();
|
|
}
|
|
}
|
|
|
|
// ==================== LABOR MANAGEMENT ====================
|
|
|
|
/**
|
|
* Assign a task to a prisoner.
|
|
*/
|
|
public boolean assignTask(
|
|
UUID playerId,
|
|
com.tiedup.remake.labor.LaborTask task,
|
|
UUID maidId,
|
|
long currentTime
|
|
) {
|
|
LaborRecord labor = getLaborRecord(playerId);
|
|
if (!labor.canAssignTask()) {
|
|
return false;
|
|
}
|
|
|
|
labor.assignTask(task, maidId, currentTime);
|
|
setDirty();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get the current work phase for a prisoner.
|
|
*/
|
|
public LaborRecord.WorkPhase getWorkPhase(UUID playerId) {
|
|
LaborRecord labor = laborRecords.get(playerId);
|
|
return labor != null ? labor.getPhase() : LaborRecord.WorkPhase.IDLE;
|
|
}
|
|
|
|
// ==================== INDEX HELPERS ====================
|
|
|
|
private void addToIndex(Map<UUID, Set<UUID>> index, UUID key, UUID value) {
|
|
if (key == null) return;
|
|
index
|
|
.computeIfAbsent(key, k -> ConcurrentHashMap.newKeySet())
|
|
.add(value);
|
|
}
|
|
|
|
private void removeFromIndex(
|
|
Map<UUID, Set<UUID>> index,
|
|
UUID key,
|
|
UUID value
|
|
) {
|
|
if (key == null) return;
|
|
Set<UUID> set = index.get(key);
|
|
if (set != null) {
|
|
set.remove(value);
|
|
if (set.isEmpty()) {
|
|
index.remove(key);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ==================== CLEANUP ====================
|
|
|
|
/**
|
|
* Clean up stale records for offline players.
|
|
* Called periodically.
|
|
*/
|
|
public void cleanupOfflinePlayers(
|
|
MinecraftServer server,
|
|
long currentTime,
|
|
long offlineTimeoutTicks
|
|
) {
|
|
List<UUID> toCleanup = new ArrayList<>();
|
|
|
|
for (Map.Entry<UUID, PrisonerRecord> entry : prisoners.entrySet()) {
|
|
UUID playerId = entry.getKey();
|
|
PrisonerRecord record = entry.getValue();
|
|
|
|
// Skip FREE players
|
|
if (record.getState() == PrisonerState.FREE) {
|
|
continue;
|
|
}
|
|
|
|
// Check if player is online
|
|
ServerPlayer player = server.getPlayerList().getPlayer(playerId);
|
|
if (player != null) {
|
|
continue; // Online, skip
|
|
}
|
|
|
|
// Check timeout
|
|
long timeInState = record.getTimeInState(currentTime);
|
|
if (timeInState > offlineTimeoutTicks) {
|
|
toCleanup.add(playerId);
|
|
}
|
|
}
|
|
|
|
for (UUID playerId : toCleanup) {
|
|
TiedUpMod.LOGGER.info(
|
|
"[PrisonerManager] Cleaning up offline prisoner: {}",
|
|
playerId.toString().substring(0, 8)
|
|
);
|
|
escape(playerId, currentTime, "offline timeout");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Expire protection for players whose grace period ended.
|
|
*/
|
|
public void tickProtectionExpiry(long currentTime) {
|
|
List<UUID> toExpire = new ArrayList<>();
|
|
|
|
for (Map.Entry<UUID, PrisonerRecord> entry : prisoners.entrySet()) {
|
|
PrisonerRecord record = entry.getValue();
|
|
if (
|
|
record.getState() == PrisonerState.PROTECTED &&
|
|
currentTime >= record.getProtectionExpiry()
|
|
) {
|
|
toExpire.add(entry.getKey());
|
|
}
|
|
}
|
|
|
|
for (UUID playerId : toExpire) {
|
|
expireProtection(playerId, currentTime);
|
|
}
|
|
}
|
|
|
|
// ==================== PERSISTENCE ====================
|
|
|
|
@Override
|
|
public @NotNull CompoundTag save(@NotNull CompoundTag tag) {
|
|
// Save prisoners
|
|
ListTag prisonerList = new ListTag();
|
|
for (Map.Entry<UUID, PrisonerRecord> entry : prisoners.entrySet()) {
|
|
CompoundTag prisonerTag = new CompoundTag();
|
|
prisonerTag.putUUID("id", entry.getKey());
|
|
prisonerTag.put("record", entry.getValue().save());
|
|
prisonerList.add(prisonerTag);
|
|
}
|
|
tag.put("prisoners", prisonerList);
|
|
|
|
// Save labor records
|
|
ListTag laborList = new ListTag();
|
|
for (Map.Entry<UUID, LaborRecord> entry : laborRecords.entrySet()) {
|
|
CompoundTag laborTag = new CompoundTag();
|
|
laborTag.putUUID("id", entry.getKey());
|
|
laborTag.put("record", entry.getValue().save());
|
|
laborList.add(laborTag);
|
|
}
|
|
tag.put("laborRecords", laborList);
|
|
|
|
// Save ransom records
|
|
ListTag ransomList = new ListTag();
|
|
for (Map.Entry<UUID, RansomRecord> entry : ransomRecords.entrySet()) {
|
|
CompoundTag ransomTag = new CompoundTag();
|
|
ransomTag.putUUID("id", entry.getKey());
|
|
ransomTag.put("record", entry.getValue().save());
|
|
ransomList.add(ransomTag);
|
|
}
|
|
tag.put("ransomRecords", ransomList);
|
|
|
|
return tag;
|
|
}
|
|
|
|
public static PrisonerManager load(CompoundTag tag) {
|
|
PrisonerManager manager = new PrisonerManager();
|
|
|
|
// Load prisoners
|
|
if (tag.contains("prisoners")) {
|
|
ListTag prisonerList = tag.getList("prisoners", Tag.TAG_COMPOUND);
|
|
for (int i = 0; i < prisonerList.size(); i++) {
|
|
CompoundTag prisonerTag = prisonerList.getCompound(i);
|
|
UUID id = prisonerTag.getUUID("id");
|
|
PrisonerRecord record = PrisonerRecord.load(
|
|
prisonerTag.getCompound("record")
|
|
);
|
|
manager.prisoners.put(id, record);
|
|
|
|
// Rebuild indexes
|
|
if (record.getCampId() != null) {
|
|
manager.addToIndex(
|
|
manager.prisonersByCamp,
|
|
record.getCampId(),
|
|
id
|
|
);
|
|
}
|
|
if (record.getCellId() != null) {
|
|
manager.addToIndex(
|
|
manager.prisonersByCell,
|
|
record.getCellId(),
|
|
id
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Load labor records
|
|
if (tag.contains("laborRecords")) {
|
|
ListTag laborList = tag.getList("laborRecords", Tag.TAG_COMPOUND);
|
|
for (int i = 0; i < laborList.size(); i++) {
|
|
CompoundTag laborTag = laborList.getCompound(i);
|
|
UUID id = laborTag.getUUID("id");
|
|
LaborRecord record = LaborRecord.load(
|
|
laborTag.getCompound("record")
|
|
);
|
|
manager.laborRecords.put(id, record);
|
|
}
|
|
}
|
|
|
|
// Load ransom records
|
|
if (tag.contains("ransomRecords")) {
|
|
ListTag ransomList = tag.getList("ransomRecords", Tag.TAG_COMPOUND);
|
|
for (int i = 0; i < ransomList.size(); i++) {
|
|
CompoundTag ransomTag = ransomList.getCompound(i);
|
|
UUID id = ransomTag.getUUID("id");
|
|
RansomRecord record = RansomRecord.load(
|
|
ransomTag.getCompound("record")
|
|
);
|
|
manager.ransomRecords.put(id, record);
|
|
}
|
|
}
|
|
|
|
return manager;
|
|
}
|
|
|
|
// ==================== DEBUG ====================
|
|
|
|
public String toDebugString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append("PrisonerManager:\n");
|
|
sb.append(" Total records: ").append(prisoners.size()).append("\n");
|
|
sb
|
|
.append(" Active prisoners: ")
|
|
.append(getAllPrisonerIds().size())
|
|
.append("\n");
|
|
|
|
for (PrisonerState state : PrisonerState.values()) {
|
|
int count = getPrisonersInState(state).size();
|
|
if (count > 0) {
|
|
sb
|
|
.append(" - ")
|
|
.append(state)
|
|
.append(": ")
|
|
.append(count)
|
|
.append("\n");
|
|
}
|
|
}
|
|
|
|
return sb.toString();
|
|
}
|
|
}
|