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)
104 lines
3.6 KiB
Java
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();
|
|
}
|
|
}
|