Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
800
src/main/java/com/tiedup/remake/prison/PrisonerManager.java
Normal file
800
src/main/java/com/tiedup/remake/prison/PrisonerManager.java
Normal file
@@ -0,0 +1,800 @@
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user