Files
TiedUp-/src/main/java/com/tiedup/remake/state/components/PlayerStruggle.java
NotEvil 22d79a452b refactor(S-02/S-05): extract PlayerMovement component + fix thread safety
- Extract 11 movement fields from PlayerBindState into PlayerMovement component
- Replace volatile isStruggling/struggleStartTick pair with atomic StruggleSnapshot record
- Remove 5+2 misleading synchronized keywords (different monitors, all server-thread-only)
- Update all 36 MovementStyleManager field accesses to use getMovement() getters/setters
2026-04-15 16:48:22 +02:00

126 lines
4.2 KiB
Java

package com.tiedup.remake.state.components;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.state.struggle.StruggleBinds;
import com.tiedup.remake.state.struggle.StruggleCollar;
import net.minecraft.world.entity.player.Player;
/**
* Component responsible for struggle mechanics and resistance management.
*
* Single Responsibility: Struggle state and resistance tracking
* Complexity: MEDIUM (volatile fields, animation coordination)
* Risk: MEDIUM (thread-safety requirements)
*
* Threading: Uses host's volatile fields for animation state (isStruggling, struggleStartTick)
*
* Note: StruggleBinds and StruggleCollar require PlayerBindState parameter.
* Since PlayerBindState implements IPlayerBindStateHost, we can safely cast.
*/
public class PlayerStruggle {
private final IPlayerBindStateHost host;
private final PlayerBindState state; // Cast reference for struggle system
private final StruggleBinds struggleBindState;
private final StruggleCollar struggleCollarState;
public PlayerStruggle(IPlayerBindStateHost host) {
this.host = host;
// Safe cast: PlayerBindState implements IPlayerBindStateHost
this.state = (PlayerBindState) host;
// Initialize sub-states for struggling
this.struggleBindState = new StruggleBinds();
this.struggleCollarState = new StruggleCollar();
}
// ========== Struggle Methods ==========
/**
* Entry point for the Struggle logic (Key R).
* Distributes effort between Binds and Collar.
*
* Thread Safety: Must be called from the server thread (packet handlers use enqueueWork).
*/
public void struggle() {
if (struggleBindState != null) struggleBindState.struggle(state);
if (struggleCollarState != null) struggleCollarState.struggle(state);
}
/**
* Restores resistance to base values when a master tightens the ties.
*
* Thread Safety: Must be called from the server thread.
*/
public void tighten(Player tightener) {
if (struggleBindState != null) struggleBindState.tighten(
tightener,
state
);
if (struggleCollarState != null) struggleCollarState.tighten(
tightener,
state
);
}
/**
* Get the StruggleBinds instance for external access (mini-game system).
*/
public StruggleBinds getStruggleBinds() {
return struggleBindState;
}
/**
* Set a cooldown on struggle attempts (used after mini-game exhaustion).
* @param seconds Cooldown duration in seconds
*/
public void setStruggleCooldown(int seconds) {
if (
struggleBindState != null &&
host.getPlayer() != null &&
host.getLevel() != null
) {
struggleBindState.setExternalCooldown(seconds, host.getLevel());
}
}
/**
* v2.5: Check if struggle cooldown is active.
* @return true if cooldown is active (cannot struggle yet)
*/
public boolean isStruggleCooldownActive() {
return (
struggleBindState != null && struggleBindState.isCooldownActive()
);
}
/**
* v2.5: Get remaining struggle cooldown in seconds.
* @return Remaining seconds, or 0 if no cooldown
*/
public int getStruggleCooldownRemaining() {
return struggleBindState != null
? struggleBindState.getRemainingCooldownSeconds()
: 0;
}
// ========== Animation Control ==========
// Note: Animation state (isStruggling, struggleStartTick) is managed by host
// via IPlayerBindStateHost interface (volatile fields for thread-safety)
/**
* Check if struggle animation should stop (duration expired).
* @param currentTick Current game time tick
* @return True if animation has been playing for >= 80 ticks
*/
public boolean shouldStopStruggling(long currentTick) {
if (!host.isStruggling()) return false;
return (
(currentTick - host.getStruggleStartTick()) >=
com.tiedup.remake.util.GameConstants.STRUGGLE_ANIMATION_DURATION_TICKS
);
}
}