Files
TiedUp-/src/main/java/com/tiedup/remake/tasks/V2TyingPlayerTask.java
NotEvil 75679c6718 feat(D-01/E): resistance & lock system rework (E1-E7)
E1: Initialize currentResistance in NBT at equip time from
    ResistanceComponent — eliminates MAX-scan fallback bug

E2: BuiltInLockComponent for organic items (already committed)

E3: canStruggle refactor — new model:
    - ARMS: always struggle-able (no lock gating)
    - Non-ARMS: only if locked OR built-in lock
    - Removed dead isItemLocked() from StruggleState + overrides

E4: canUnequip already handled by BuiltInLockComponent.blocksUnequip()
    via ComponentHolder delegation

E5: Help/assist mechanic deferred (needs UI design)

E6: Removed lock resistance from ILockable (5 methods + NBT key deleted)
    - GenericKnife: new knifeCutProgress NBT for cutting locks
    - StruggleAccessory: accessoryStruggleResistance NBT replaces lock resistance
    - PacketV2StruggleStart: uses config-based padlock resistance
    - All lock/unlock packets cleaned of initializeLockResistance/clearLockResistance

E7: Fixed 3 pre-existing bugs:
    - B2: DataDrivenItemRegistry.clear() synchronized on RELOAD_LOCK
    - B3: V2TyingPlayerTask validates heldStack before equip (prevents duplication)
    - B5: EntityKidnapperMerchant.remove() cleans playerToMerchant map (memory leak)
2026-04-15 03:23:49 +02:00

104 lines
3.6 KiB
Java

package com.tiedup.remake.tasks;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.bondage.V2EquipResult;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
/**
* Tying task for V2 bondage items.
*
* Unlike {@link TyingPlayerTask} which calls {@code targetState.equip(BodyRegionV2.ARMS, bind)} (V1 equip),
* this task uses {@link V2EquipmentHelper#equipItem(LivingEntity, ItemStack)} on completion.
*
* Progress bar, duration, and packet flow are identical to V1 tying.
*/
public class V2TyingPlayerTask extends TyingPlayerTask {
/**
* The live reference to the player's held ItemStack (for consumption on completion).
* The parent class's {@code bind} field holds a copy for display/matching.
*/
private final ItemStack heldStack;
/**
* Create a V2 tying task.
*
* @param bind Copy of the item being equipped (for display/matching)
* @param heldStack Live reference to the player's held ItemStack (for consumption)
* @param targetState The target's IBondageState state
* @param targetEntity The target entity
* @param seconds Duration in seconds
* @param level The world
* @param kidnapper The player performing the tying (self for self-bondage)
*/
public V2TyingPlayerTask(
ItemStack bind,
ItemStack heldStack,
IBondageState targetState,
LivingEntity targetEntity,
int seconds,
Level level,
Player kidnapper
) {
super(bind, targetState, targetEntity, seconds, level, kidnapper);
this.heldStack = heldStack;
}
/**
* V2 completion: equip via V2EquipmentHelper instead of V1 putBindOn.
*
* This REPLACES the parent's onComplete entirely. The parent would call
* targetState.equip(BodyRegionV2.ARMS, bind) which is V1-only.
*/
@Override
protected void onComplete() {
if (!isTargetValid()) {
TiedUpMod.LOGGER.warn(
"[V2TyingPlayerTask] Target entity no longer valid, cancelling"
);
stop();
return;
}
TiedUpMod.LOGGER.info(
"[V2TyingPlayerTask] Tying complete for {}",
targetEntity.getName().getString()
);
// Validate heldStack hasn't changed during tying (e.g. player swapped items)
if (heldStack.isEmpty() || !ItemStack.isSameItemSameTags(heldStack, bind)) {
TiedUpMod.LOGGER.warn("[V2TyingPlayerTask] heldStack changed during tying — aborting");
stop();
return;
}
// Equip via V2 system
V2EquipResult result = V2EquipmentHelper.equipItem(targetEntity, bind);
if (result.isSuccess()) {
for (ItemStack displaced : result.displaced()) {
targetEntity.spawnAtLocation(displaced);
}
// Consume the held item
heldStack.shrink(1);
TiedUpMod.LOGGER.debug(
"[V2TyingPlayerTask] V2 equip succeeded, item consumed"
);
} else {
TiedUpMod.LOGGER.warn(
"[V2TyingPlayerTask] V2 equip BLOCKED after tying — regions may have changed"
);
}
// Mark task as stopped
stop();
// Send completion packets (shared with V1 via parent)
sendCompletionPackets();
}
}