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

@@ -384,26 +384,27 @@ public class GenericKnife extends Item implements IKnife {
return;
}
// Accessory IS locked - reduce lock resistance
// Accessory IS locked - reduce lock resistance via knife cut progress
ILockable lockable = (ILockable) accessory.getItem();
int currentRes = lockable.getCurrentLockResistance(accessory);
int newRes = Math.max(0, currentRes - speed);
lockable.setCurrentLockResistance(accessory, newRes);
int cutProgress = com.tiedup.remake.util.ItemNBTHelper.getInt(accessory, "knifeCutProgress");
int newProgress = cutProgress + speed;
int lockResistance = com.tiedup.remake.core.SettingsAccessor.getPadlockResistance(null);
com.tiedup.remake.util.ItemNBTHelper.setInt(accessory, "knifeCutProgress", newProgress);
TiedUpMod.LOGGER.debug(
"[GenericKnife] {} cutting {} lock: resistance {} -> {}",
"[GenericKnife] {} cutting {} lock: progress {} / {}",
player.getName().getString(),
target,
currentRes,
newRes
newProgress,
lockResistance
);
// Check if lock is destroyed
if (newRes <= 0) {
if (newProgress >= lockResistance) {
// Destroy the lock (remove padlock, clear lock state)
lockable.setLockedByKeyUUID(accessory, null); // Unlocks and clears locked state
lockable.setLockable(accessory, false); // Remove padlock entirely
lockable.clearLockResistance(accessory);
com.tiedup.remake.util.ItemNBTHelper.remove(accessory, "knifeCutProgress");
lockable.setJammed(accessory, false);
state.clearKnifeCutTarget();

View File

@@ -214,7 +214,6 @@ public class ItemLockpick extends Item {
if (success) {
// SUCCESS: Unlock the item, PRESERVE the padlock
lockable.setLockedByKeyUUID(targetStack, null); // Unlock
lockable.clearLockResistance(targetStack); // Clear struggle progress
// lockable stays true - padlock preserved!
SystemMessageManager.sendToPlayer(

View File

@@ -222,20 +222,6 @@ public interface ILockable {
*/
String NBT_JAMMED = "jammed";
/**
* Get the resistance added by the lock for struggle mechanics.
*
* <p>When locked, this value is added to the item's base resistance.
* Configurable via server config and GameRule.</p>
*
* @return Lock resistance value (default: 250, configurable)
*/
default int getLockResistance() {
return com.tiedup.remake.core.SettingsAccessor.getPadlockResistance(
null
);
}
/**
* Check if the lock is jammed (lockpick failed critically).
*
@@ -266,63 +252,6 @@ public interface ILockable {
}
}
// ========== LOCK RESISTANCE (for struggle) ==========
/**
* NBT key for current lock resistance during struggle.
*/
String NBT_LOCK_RESISTANCE = "lockResistance";
/**
* Get the current lock resistance remaining for struggle.
* Initialized to getLockResistance() (configurable, default 250) when first locked.
*
* @param stack The ItemStack to check
* @return Current lock resistance (0 if not locked or fully struggled)
*/
default int getCurrentLockResistance(ItemStack stack) {
if (stack.isEmpty()) return 0;
// If locked but no resistance stored yet, initialize it
if (
isLocked(stack) &&
!ItemNBTHelper.contains(stack, NBT_LOCK_RESISTANCE)
) {
return getLockResistance(); // Configurable via ModConfig
}
return ItemNBTHelper.getInt(stack, NBT_LOCK_RESISTANCE);
}
/**
* Set the current lock resistance remaining for struggle.
*
* @param stack The ItemStack to modify
* @param resistance The new resistance value
*/
default void setCurrentLockResistance(ItemStack stack, int resistance) {
ItemNBTHelper.setInt(stack, NBT_LOCK_RESISTANCE, resistance);
}
/**
* Initialize lock resistance when item is locked.
* Called when setLockedByKeyUUID is called with a non-null UUID.
*
* @param stack The ItemStack to initialize
*/
default void initializeLockResistance(ItemStack stack) {
setCurrentLockResistance(stack, getLockResistance());
}
/**
* Clear lock resistance when item is unlocked.
*
* @param stack The ItemStack to clear
*/
default void clearLockResistance(ItemStack stack) {
ItemNBTHelper.remove(stack, NBT_LOCK_RESISTANCE);
}
// ========== LOCK BREAKING (struggle/force) ==========
/**
@@ -334,7 +263,6 @@ public interface ILockable {
* <li>Unlocks the item (lockedByKeyUUID = null)</li>
* <li>Removes the lockable flag (no more padlock slot)</li>
* <li>Clears any jam state</li>
* <li>Clears stored lock resistance</li>
* </ul>
*
* @param stack The ItemStack to break the lock on
@@ -344,6 +272,5 @@ public interface ILockable {
setLockedByKeyUUID(stack, null);
setLockable(stack, false);
setJammed(stack, false);
clearLockResistance(stack);
}
}

View File

@@ -394,7 +394,6 @@ public class GenericClothes extends Item implements ILockable, IV2BondageItem {
stack.getOrCreateTag().putBoolean(NBT_LOCKED, state);
if (!state) {
// When unlocking, clear lock-related data
clearLockResistance(stack);
setJammed(stack, false);
}
return stack;
@@ -439,7 +438,6 @@ public class GenericClothes extends Item implements ILockable, IV2BondageItem {
if (keyUUID != null) {
tag.putUUID(NBT_LOCKED_BY_KEY_UUID, keyUUID);
setLocked(stack, true);
initializeLockResistance(stack);
} else {
tag.remove(NBT_LOCKED_BY_KEY_UUID);
setLocked(stack, false);