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)
This commit is contained in:
NotEvil
2026-04-15 03:23:49 +02:00
parent 199bf00aef
commit d6bb030ad7
17 changed files with 76 additions and 228 deletions

View File

@@ -172,47 +172,17 @@ public class PacketLockpickAttempt {
!targetStack.isEmpty() &&
targetStack.getItem() instanceof ILockable lockable
) {
// Get lock resistance BEFORE clearing it
int lockResistance = lockable.getCurrentLockResistance(targetStack);
// Unlock the item
lockable.setLockedByKeyUUID(targetStack, null);
lockable.clearLockResistance(targetStack);
TiedUpMod.LOGGER.info(
"[PacketLockpickAttempt] Player {} successfully picked lock on {} ({}, resistance was {})",
"[PacketLockpickAttempt] Player {} successfully picked lock on {} ({})",
player.getName().getString(),
targetStack.getDisplayName().getString(),
targetRegion,
lockResistance
targetRegion
);
// Deduct lock resistance from bind resistance
PlayerBindState state = PlayerBindState.getInstance(player);
if (state != null && state.isTiedUp() && lockResistance > 0) {
int currentBindResistance = state.getCurrentBindResistance();
int newBindResistance = Math.max(
0,
currentBindResistance - lockResistance
);
state.setCurrentBindResistance(newBindResistance);
TiedUpMod.LOGGER.info(
"[PacketLockpickAttempt] Deducted {} from bind resistance: {} -> {}",
lockResistance,
currentBindResistance,
newBindResistance
);
// Check if player escaped (resistance = 0)
if (newBindResistance <= 0) {
state.getStruggleBinds().successActionExternal(state);
TiedUpMod.LOGGER.info(
"[PacketLockpickAttempt] Player {} escaped via lockpick!",
player.getName().getString()
);
}
}
// Lock is now unlocked -- bind resistance is tracked separately via IHasResistance
}
// Damage lockpick

View File

@@ -432,26 +432,6 @@ public class PacketSlaveItemManage {
// Lock with keyUUID
lockable.setLockedByKeyUUID(itemStack, keyUUID);
if (
region == BodyRegionV2.ARMS &&
itemStack.getItem() instanceof com.tiedup.remake.items.base.IHasResistance resistanceItem
) {
int currentResistance = resistanceItem.getCurrentResistance(
itemStack,
target
);
int lockResistance = lockable.getLockResistance(); // Configurable via ModConfig
resistanceItem.setCurrentResistance(
itemStack,
currentResistance + lockResistance
);
TiedUpMod.LOGGER.info(
"[PacketSlaveItemManage] Added {} lock resistance to bind (total: {})",
lockResistance,
currentResistance + lockResistance
);
}
TiedUpMod.LOGGER.info(
"[PacketSlaveItemManage] {} locked {}'s {} with key {}",
sender.getName().getString(),
@@ -528,7 +508,6 @@ public class PacketSlaveItemManage {
// Unlock the item - just unlock, keep padlock attached (can be re-locked)
lockable.setLockedByKeyUUID(itemStack, null);
lockable.clearLockResistance(itemStack); // Clear any struggle progress
// Note: Padlock is only dropped on REMOVE, not on UNLOCK
TiedUpMod.LOGGER.info(