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:
427
src/main/java/com/tiedup/remake/state/PlayerCaptorManager.java
Normal file
427
src/main/java/com/tiedup/remake/state/PlayerCaptorManager.java
Normal file
@@ -0,0 +1,427 @@
|
||||
package com.tiedup.remake.state;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.items.base.ItemCollar;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
// C6-V2: IRestrainable → IBondageState (narrowed API)
|
||||
|
||||
/**
|
||||
* Phase 8: Master-Captive Relationships
|
||||
* Phase 17: Renamed from PlayerKidnapperManager, terminology slave → captive
|
||||
*
|
||||
* Manages capture relationships for player captors.
|
||||
*
|
||||
* Terminology (Phase 17):
|
||||
* - "Captive" = Entity attached by leash (active physical control)
|
||||
* - "Slave" = Entity wearing a collar owned by someone (passive ownership via CollarRegistry)
|
||||
*
|
||||
* Features:
|
||||
* - Supports multiple captives simultaneously
|
||||
* - Allows captive transfer between captors
|
||||
* - Tracks captive list persistently
|
||||
* - Handles cleanup on captive logout/escape
|
||||
*
|
||||
* Thread Safety:
|
||||
* - Uses CopyOnWriteArrayList to avoid ConcurrentModificationException
|
||||
* - Safe for iteration during modification
|
||||
*
|
||||
* Design:
|
||||
* - Each PlayerBindState has one PlayerCaptorManager
|
||||
* - Manager tracks all captives owned by that player
|
||||
* - Implements ICaptor interface for polymorphic usage
|
||||
*
|
||||
* @see ICaptor
|
||||
* @see PlayerBindState
|
||||
*/
|
||||
public class PlayerCaptorManager implements ICaptor {
|
||||
|
||||
/**
|
||||
* The player who owns this manager (the captor).
|
||||
*/
|
||||
private final Player captor;
|
||||
|
||||
/**
|
||||
* List of all captives currently owned by this captor.
|
||||
* Thread-safe to avoid concurrent modification during iteration.
|
||||
*
|
||||
* Phase 14.1.6: Changed from List<PlayerBindState> to List<IBondageState>
|
||||
* Phase 17: Renamed from slaves to captives
|
||||
*/
|
||||
private final List<IBondageState> captives;
|
||||
|
||||
/**
|
||||
* Create a new captor manager for the given player.
|
||||
*
|
||||
* @param captor The player who will be the captor
|
||||
*/
|
||||
public PlayerCaptorManager(Player captor) {
|
||||
this.captor = captor;
|
||||
this.captives = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// ICaptor Implementation
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from addSlave to addCaptive
|
||||
*/
|
||||
@Override
|
||||
public synchronized void addCaptive(IBondageState captive) {
|
||||
if (captive == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[PlayerCaptorManager] Attempted to add null captive"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!captives.contains(captive)) {
|
||||
captives.add(captive);
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[PlayerCaptorManager] {} captured {} (total captives: {})",
|
||||
captor.getName().getString(),
|
||||
captive.getKidnappedName(),
|
||||
captives.size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from removeSlave to removeCaptive
|
||||
*
|
||||
* Thread Safety: Synchronized on 'this' to match addCaptive and freeAllCaptives.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void removeCaptive(
|
||||
IBondageState captive,
|
||||
boolean transportState
|
||||
) {
|
||||
if (captive == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[PlayerCaptorManager] Attempted to remove null captive"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (captives.remove(captive)) {
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[PlayerCaptorManager] {} freed {} (remaining captives: {})",
|
||||
captor.getName().getString(),
|
||||
captive.getKidnappedName(),
|
||||
captives.size()
|
||||
);
|
||||
|
||||
// If requested, also despawn the transport entity
|
||||
if (transportState && captive.getTransport() != null) {
|
||||
captive.getTransport().discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from canEnslave to canCapture
|
||||
*/
|
||||
@Override
|
||||
public boolean canCapture(IBondageState target) {
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// From original code (PlayerBindState.java:195-225):
|
||||
// Can capture if:
|
||||
// - Target is tied up, OR
|
||||
// - Target has collar AND collar has this captor as owner
|
||||
|
||||
// Phase 14.1.6: Use asLivingEntity() instead of getPlayer()
|
||||
net.minecraft.world.entity.LivingEntity targetEntity =
|
||||
target.asLivingEntity();
|
||||
if (targetEntity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if target is tied up
|
||||
if (target.isTiedUp()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if target has collar with this captor as owner
|
||||
if (target.hasCollar()) {
|
||||
ItemStack collar = target.getEquipment(BodyRegionV2.NECK);
|
||||
if (collar.getItem() instanceof ItemCollar collarItem) {
|
||||
if (
|
||||
collarItem.getOwners(collar).contains(this.captor.getUUID())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from canFree to canRelease
|
||||
*/
|
||||
@Override
|
||||
public boolean canRelease(IBondageState captive) {
|
||||
if (captive == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can only release if this manager is the captive's captor
|
||||
return captive.getCaptor() == this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 17: Renamed from allowSlaveTransfer to allowCaptiveTransfer
|
||||
*/
|
||||
@Override
|
||||
public boolean allowCaptiveTransfer() {
|
||||
// Players always allow captive transfer
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 17: Renamed from allowMultipleSlaves to allowMultipleCaptives
|
||||
*/
|
||||
@Override
|
||||
public boolean allowMultipleCaptives() {
|
||||
// Players can have multiple captives
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from onSlaveLogout to onCaptiveLogout
|
||||
* Note: For NPC captives, this is never called (NPCs don't log out)
|
||||
*/
|
||||
@Override
|
||||
public void onCaptiveLogout(IBondageState captive) {
|
||||
if (captive == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[PlayerCaptorManager] Captive {} logged out while captured by {}",
|
||||
captive.getKidnappedName(),
|
||||
captor.getName().getString()
|
||||
);
|
||||
|
||||
// Keep captive in list - they might reconnect
|
||||
// Transport entity will despawn after timeout
|
||||
// On reconnect, checkStillCaptive() will clean up if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from onSlaveReleased to onCaptiveReleased
|
||||
*/
|
||||
@Override
|
||||
public void onCaptiveReleased(IBondageState captive) {
|
||||
if (captive == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[PlayerCaptorManager] Captive {} was released from {}",
|
||||
captive.getKidnappedName(),
|
||||
captor.getName().getString()
|
||||
);
|
||||
|
||||
// No special action needed - already removed from list by removeCaptive()
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.6: Changed parameter from PlayerBindState to IBondageState
|
||||
* Phase 17: Renamed from onSlaveStruggle to onCaptiveStruggle
|
||||
*/
|
||||
@Override
|
||||
public void onCaptiveStruggle(IBondageState captive) {
|
||||
if (captive == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[PlayerCaptorManager] Captive {} struggled (captor: {})",
|
||||
captive.getKidnappedName(),
|
||||
captor.getName().getString()
|
||||
);
|
||||
|
||||
// Phase 8: No action for basic struggle
|
||||
// Phase 14: Shock collar would activate here
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 17: Renamed from hasSlaves to hasCaptives
|
||||
*/
|
||||
@Override
|
||||
public boolean hasCaptives() {
|
||||
return !captives.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getEntity() {
|
||||
return captor;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Additional Methods
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Frees all captives currently owned by this captor.
|
||||
*
|
||||
* Phase 17: Renamed from freeAllSlaves to freeAllCaptives
|
||||
*
|
||||
* Thread Safety: Synchronized on 'this' to match addCaptive and removeCaptive.
|
||||
*
|
||||
* @param transportState If true, destroy the transporter entities
|
||||
*/
|
||||
public synchronized void freeAllCaptives(boolean transportState) {
|
||||
// Use a copy to avoid concurrent modification while iterating
|
||||
List<IBondageState> copy = new ArrayList<>(captives);
|
||||
for (IBondageState captive : copy) {
|
||||
captive.free(transportState);
|
||||
}
|
||||
captives.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees all captives with default behavior (destroy transport entities).
|
||||
*/
|
||||
public void freeAllCaptives() {
|
||||
freeAllCaptives(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of the captive list.
|
||||
* Safe for iteration without concurrent modification issues.
|
||||
*
|
||||
* Phase 17: Renamed from getSlaves to getCaptives
|
||||
*
|
||||
* @return Copy of the current captive list
|
||||
*/
|
||||
public List<IBondageState> getCaptives() {
|
||||
return new ArrayList<>(captives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of captives currently owned.
|
||||
*
|
||||
* Phase 17: Renamed from getSlaveCount to getCaptiveCount
|
||||
*
|
||||
* @return Captive count
|
||||
*/
|
||||
public int getCaptiveCount() {
|
||||
return captives.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer all captives from this captor to a new captor.
|
||||
* Used when this player gets captured themselves.
|
||||
*
|
||||
* From original code:
|
||||
* - When a player gets captured, their captives transfer to new captor
|
||||
* - Prevents circular capture issues
|
||||
*
|
||||
* Phase 17: Renamed from transferAllSlavesTo to transferAllCaptivesTo
|
||||
*
|
||||
* @param newCaptor The new captor to transfer captives to
|
||||
*/
|
||||
public void transferAllCaptivesTo(ICaptor newCaptor) {
|
||||
if (newCaptor == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[PlayerCaptorManager] Attempted to transfer captives to null captor"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (captives.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[PlayerCaptorManager] Transferring {} captives from {} to {}",
|
||||
captives.size(),
|
||||
captor.getName().getString(),
|
||||
newCaptor.getEntity().getName().getString()
|
||||
);
|
||||
|
||||
// Create copy to avoid concurrent modification
|
||||
List<IBondageState> captivesToTransfer = new ArrayList<>(captives);
|
||||
|
||||
for (IBondageState captive : captivesToTransfer) {
|
||||
if (captive != null) {
|
||||
captive.transferCaptivityTo(newCaptor);
|
||||
}
|
||||
}
|
||||
|
||||
// All captives should now be removed from this manager's list
|
||||
if (!captives.isEmpty()) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[PlayerCaptorManager] {} captives remain after transfer - cleaning up",
|
||||
captives.size()
|
||||
);
|
||||
captives.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the captor player.
|
||||
*
|
||||
* @return The player who owns this manager
|
||||
*/
|
||||
public Player getCaptor() {
|
||||
return captor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up invalid captives from the list.
|
||||
* Removes captives that are no longer valid (offline, transport gone, etc.).
|
||||
*
|
||||
* Phase 17: Renamed from cleanupInvalidSlaves to cleanupInvalidCaptives
|
||||
*
|
||||
* Should be called periodically (e.g., on tick).
|
||||
*/
|
||||
public void cleanupInvalidCaptives() {
|
||||
captives.removeIf(captive -> {
|
||||
if (captive == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove if not actually captured anymore
|
||||
if (!captive.isCaptive()) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[PlayerCaptorManager] Removing invalid captive {}",
|
||||
captive.getKidnappedName()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove if captured by different captor
|
||||
if (captive.getCaptor() != this) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[PlayerCaptorManager] Removing captive {} (belongs to different captor)",
|
||||
captive.getKidnappedName()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Backward Compatibility (Phase 17)
|
||||
// ========================================
|
||||
}
|
||||
Reference in New Issue
Block a user