Strip all Phase references, TODO/FUTURE roadmap notes, and internal planning comments from the codebase. Run Prettier for consistent formatting across all Java files.
155 lines
5.3 KiB
Java
155 lines
5.3 KiB
Java
package com.tiedup.remake.state.components;
|
|
|
|
import com.tiedup.remake.cells.CampOwnership;
|
|
import com.tiedup.remake.cells.CellRegistryV2;
|
|
import com.tiedup.remake.core.TiedUpMod;
|
|
import com.tiedup.remake.items.base.ItemBind;
|
|
import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
|
|
import com.tiedup.remake.v2.BodyRegionV2;
|
|
import java.util.UUID;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.Level;
|
|
|
|
/**
|
|
* Component responsible for player lifecycle management.
|
|
* Handles connection, death, respawn scenarios.
|
|
*
|
|
* Single Responsibility: Lifecycle events and registry coordination
|
|
* Complexity: HIGH (coordinates 4+ registries on death)
|
|
* Risk: HIGH (critical path, must maintain registry cleanup order)
|
|
*
|
|
* Registry Cleanup Order (on death):
|
|
* 1. CellRegistryV2 - remove from cells
|
|
* 2. PrisonerManager - release prisoner (via PrisonerService)
|
|
*/
|
|
public class PlayerLifecycle {
|
|
|
|
private final IPlayerBindStateHost host;
|
|
|
|
public PlayerLifecycle(IPlayerBindStateHost host) {
|
|
this.host = host;
|
|
}
|
|
|
|
// ========== Lifecycle Methods ==========
|
|
|
|
/**
|
|
* Resets the player instance upon reconnection or respawn.
|
|
*
|
|
* IMPORTANT: Handle transport restoration for pole binding.
|
|
* With proxy-based leash system, leashes are not persisted through disconnection.
|
|
* The leash proxy is ephemeral and will be recreated if needed.
|
|
*
|
|
* Leg Binding: Speed reduction based on hasLegsBound(), not isTiedUp().
|
|
*/
|
|
public void resetNewConnection(Player player) {
|
|
// Update player reference
|
|
host.setOnline(true);
|
|
|
|
host.setCaptor(null);
|
|
|
|
// Reset struggle animation state (prevent stuck animations)
|
|
host.setStrugglingClient(false);
|
|
|
|
// Leash proxy doesn't persist through disconnection
|
|
// If player was leashed, they are now freed
|
|
|
|
// H6 fix: V1 speed reduction re-application is no longer needed for players.
|
|
// MovementStyleManager (V2 tick-based system) re-resolves the active movement
|
|
// style on the first tick after login (clearMovementState() resets activeMovementStyle
|
|
// to null, triggering a fresh activation). The V1 RestraintEffectUtils call here would
|
|
// cause double stacking with the V2 MULTIPLY_BASE modifier.
|
|
}
|
|
|
|
/**
|
|
* Called when the kidnapped player dies.
|
|
* Comprehensive cleanup: unlock items, drop items, free captivity, cleanup registries.
|
|
*
|
|
* @param world The world/level where death occurred
|
|
* @return true if death was handled
|
|
*/
|
|
public boolean onDeathKidnapped(Level world) {
|
|
Player player = host.getPlayer();
|
|
|
|
// Mark player as offline
|
|
host.setOnline(false);
|
|
|
|
// Clean up all registries on death (server-side only)
|
|
if (world instanceof ServerLevel serverLevel) {
|
|
UUID playerId = player.getUUID();
|
|
cleanupRegistries(serverLevel, playerId);
|
|
}
|
|
|
|
TiedUpMod.LOGGER.debug(
|
|
"[PlayerLifecycle] {} died while kidnapped",
|
|
player.getName().getString()
|
|
);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Coordinates cleanup of all registries when player dies.
|
|
* Order matters: Cell → Camp → Ransom → Prisoner
|
|
*
|
|
* @param serverLevel The server level
|
|
* @param playerId The player's UUID
|
|
*/
|
|
private void cleanupRegistries(ServerLevel serverLevel, UUID playerId) {
|
|
String playerName = host.getPlayer().getName().getString();
|
|
|
|
// 1. Clean up CellRegistryV2 - remove from any cells
|
|
CellRegistryV2 cellRegistry = CellRegistryV2.get(serverLevel);
|
|
int cellsRemoved = cellRegistry.releasePrisonerFromAllCells(playerId);
|
|
if (cellsRemoved > 0) {
|
|
TiedUpMod.LOGGER.debug(
|
|
"[PlayerLifecycle] Removed {} from {} cells on death",
|
|
playerName,
|
|
cellsRemoved
|
|
);
|
|
}
|
|
|
|
// 2. Clean up prisoner state - release from imprisonment
|
|
com.tiedup.remake.prison.PrisonerManager manager =
|
|
com.tiedup.remake.prison.PrisonerManager.get(serverLevel);
|
|
com.tiedup.remake.prison.PrisonerState state = manager.getState(
|
|
playerId
|
|
);
|
|
|
|
// Release if imprisoned or working (player died)
|
|
if (
|
|
state == com.tiedup.remake.prison.PrisonerState.IMPRISONED ||
|
|
state == com.tiedup.remake.prison.PrisonerState.WORKING
|
|
) {
|
|
// Use centralized escape service for complete cleanup
|
|
com.tiedup.remake.prison.service.PrisonerService.get().escape(
|
|
serverLevel,
|
|
playerId,
|
|
"player_death"
|
|
);
|
|
}
|
|
}
|
|
|
|
// ========== Helper Methods ==========
|
|
|
|
/**
|
|
* Get the current bind ItemStack.
|
|
* Epic 5F: Migrated to V2EquipmentHelper.
|
|
*/
|
|
private ItemStack getCurrentBind() {
|
|
return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getInRegion(
|
|
host.getPlayer(),
|
|
com.tiedup.remake.v2.BodyRegionV2.ARMS
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check if player has legs bound.
|
|
*/
|
|
private boolean hasLegsBound(ItemStack bind) {
|
|
if (bind.isEmpty()) return false;
|
|
if (!(bind.getItem() instanceof ItemBind)) return false;
|
|
return ItemBind.hasLegsBound(bind);
|
|
}
|
|
}
|