From d6bb030ad77a2d426a7ea61bf1f8336d0d0d136b Mon Sep 17 00:00:00 2001 From: NotEvil Date: Wed, 15 Apr 2026 03:23:49 +0200 Subject: [PATCH] feat(D-01/E): resistance & lock system rework (E1-E7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../entities/EntityKidnapperMerchant.java | 4 + .../com/tiedup/remake/items/GenericKnife.java | 19 ++--- .../com/tiedup/remake/items/ItemLockpick.java | 1 - .../tiedup/remake/items/base/ILockable.java | 73 ------------------- .../remake/items/clothes/GenericClothes.java | 2 - .../minigame/StruggleSessionManager.java | 20 ++--- .../minigame/PacketLockpickAttempt.java | 36 +-------- .../network/slave/PacketSlaveItemManage.java | 21 ------ .../state/struggle/StruggleAccessory.java | 53 ++++++-------- .../remake/state/struggle/StruggleBinds.java | 26 ------- .../remake/state/struggle/StruggleCollar.java | 13 ++-- .../remake/state/struggle/StruggleState.java | 10 --- .../remake/tasks/V2TyingPlayerTask.java | 7 ++ .../datadriven/DataDrivenBondageItem.java | 10 +++ .../datadriven/DataDrivenItemRegistry.java | 4 +- .../bondage/network/PacketV2LockToggle.java | 3 - .../network/PacketV2StruggleStart.java | 2 +- 17 files changed, 76 insertions(+), 228 deletions(-) diff --git a/src/main/java/com/tiedup/remake/entities/EntityKidnapperMerchant.java b/src/main/java/com/tiedup/remake/entities/EntityKidnapperMerchant.java index 1874af7..50c4e62 100644 --- a/src/main/java/com/tiedup/remake/entities/EntityKidnapperMerchant.java +++ b/src/main/java/com/tiedup/remake/entities/EntityKidnapperMerchant.java @@ -889,6 +889,10 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite { // Clear trading players to prevent dangling references if (!this.level().isClientSide) { int count = tradingPlayers.size(); + // Clean up reverse-lookup map BEFORE clearing to prevent memory leak + for (UUID playerUuid : tradingPlayers) { + playerToMerchant.remove(playerUuid); + } this.tradingPlayers.clear(); if (count > 0) { TiedUpMod.LOGGER.debug( diff --git a/src/main/java/com/tiedup/remake/items/GenericKnife.java b/src/main/java/com/tiedup/remake/items/GenericKnife.java index 7018f6d..6fc83fb 100644 --- a/src/main/java/com/tiedup/remake/items/GenericKnife.java +++ b/src/main/java/com/tiedup/remake/items/GenericKnife.java @@ -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(); diff --git a/src/main/java/com/tiedup/remake/items/ItemLockpick.java b/src/main/java/com/tiedup/remake/items/ItemLockpick.java index 6814ceb..a3b44db 100644 --- a/src/main/java/com/tiedup/remake/items/ItemLockpick.java +++ b/src/main/java/com/tiedup/remake/items/ItemLockpick.java @@ -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( diff --git a/src/main/java/com/tiedup/remake/items/base/ILockable.java b/src/main/java/com/tiedup/remake/items/base/ILockable.java index 3ded9e7..d14e90f 100644 --- a/src/main/java/com/tiedup/remake/items/base/ILockable.java +++ b/src/main/java/com/tiedup/remake/items/base/ILockable.java @@ -222,20 +222,6 @@ public interface ILockable { */ String NBT_JAMMED = "jammed"; - /** - * Get the resistance added by the lock for struggle mechanics. - * - *

When locked, this value is added to the item's base resistance. - * Configurable via server config and GameRule.

- * - * @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 { *
  • Unlocks the item (lockedByKeyUUID = null)
  • *
  • Removes the lockable flag (no more padlock slot)
  • *
  • Clears any jam state
  • - *
  • Clears stored lock resistance
  • * * * @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); } } diff --git a/src/main/java/com/tiedup/remake/items/clothes/GenericClothes.java b/src/main/java/com/tiedup/remake/items/clothes/GenericClothes.java index 706083a..2f1173a 100644 --- a/src/main/java/com/tiedup/remake/items/clothes/GenericClothes.java +++ b/src/main/java/com/tiedup/remake/items/clothes/GenericClothes.java @@ -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); diff --git a/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java b/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java index 258721f..9ecdb06 100644 --- a/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java +++ b/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java @@ -622,18 +622,14 @@ public class StruggleSessionManager { ); if (accessoryStack.isEmpty()) return; - if ( - accessoryStack.getItem() instanceof - com.tiedup.remake.items.base.ILockable lockable - ) { - // Update the lock resistance to match session state - lockable.setCurrentLockResistance( - accessoryStack, - session.getCurrentResistance() - ); - // Sync V2 equipment state - V2EquipmentHelper.sync(player); - } + // Update accessory struggle resistance in dedicated NBT key + com.tiedup.remake.util.ItemNBTHelper.setInt( + accessoryStack, + "accessoryStruggleResistance", + session.getCurrentResistance() + ); + // Sync V2 equipment state + V2EquipmentHelper.sync(player); return; } diff --git a/src/main/java/com/tiedup/remake/network/minigame/PacketLockpickAttempt.java b/src/main/java/com/tiedup/remake/network/minigame/PacketLockpickAttempt.java index 1505d90..6cf0b64 100644 --- a/src/main/java/com/tiedup/remake/network/minigame/PacketLockpickAttempt.java +++ b/src/main/java/com/tiedup/remake/network/minigame/PacketLockpickAttempt.java @@ -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 diff --git a/src/main/java/com/tiedup/remake/network/slave/PacketSlaveItemManage.java b/src/main/java/com/tiedup/remake/network/slave/PacketSlaveItemManage.java index 6b941c7..b40735d 100644 --- a/src/main/java/com/tiedup/remake/network/slave/PacketSlaveItemManage.java +++ b/src/main/java/com/tiedup/remake/network/slave/PacketSlaveItemManage.java @@ -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( diff --git a/src/main/java/com/tiedup/remake/state/struggle/StruggleAccessory.java b/src/main/java/com/tiedup/remake/state/struggle/StruggleAccessory.java index b61bbc3..30464d2 100644 --- a/src/main/java/com/tiedup/remake/state/struggle/StruggleAccessory.java +++ b/src/main/java/com/tiedup/remake/state/struggle/StruggleAccessory.java @@ -1,12 +1,15 @@ package com.tiedup.remake.state.struggle; +import com.tiedup.remake.core.SettingsAccessor; import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager.MessageCategory; import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.state.PlayerBindState; +import com.tiedup.remake.util.ItemNBTHelper; import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; +import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -32,28 +35,36 @@ public class StruggleAccessory extends StruggleState { this.accessoryRegion = accessoryRegion; } + /** NBT key for accessory struggle progress (replaces removed ILockable lock resistance). */ + private static final String NBT_ACCESSORY_STRUGGLE = "accessoryStruggleResistance"; + /** * Get the current resistance for this accessory. - * Accessories have 0 base resistance - only lock resistance exists. - * Resistance is stored in the item's NBT to persist between attempts. + * Accessories have 0 base resistance -- when locked, resistance comes from + * {@link SettingsAccessor#getPadlockResistance}. Stored in a dedicated NBT + * key on the accessory stack to persist between attempts. * * @param state The player's bind state - * @return Current resistance value (0 if not locked, 250 if locked and not yet struggled) + * @return Current resistance value (0 if not locked) */ @Override protected int getResistanceState(PlayerBindState state) { ItemStack stack = getAccessoryStack(state); if (stack.isEmpty()) return 0; - if (stack.getItem() instanceof ILockable lockable) { - return lockable.getCurrentLockResistance(stack); + if (stack.getItem() instanceof ILockable lockable && lockable.isLocked(stack)) { + // If no struggle progress stored yet, initialize from config + if (!ItemNBTHelper.contains(stack, NBT_ACCESSORY_STRUGGLE)) { + return SettingsAccessor.getPadlockResistance(null); + } + return ItemNBTHelper.getInt(stack, NBT_ACCESSORY_STRUGGLE); } return 0; } /** * Set the current resistance for this accessory struggle. - * Stored in the item's NBT to persist between attempts. + * Stored in a dedicated NBT key on the accessory stack. * * @param state The player's bind state * @param resistance The new resistance value @@ -63,9 +74,7 @@ public class StruggleAccessory extends StruggleState { ItemStack stack = getAccessoryStack(state); if (stack.isEmpty()) return; - if (stack.getItem() instanceof ILockable lockable) { - lockable.setCurrentLockResistance(stack, resistance); - } + ItemNBTHelper.setInt(stack, NBT_ACCESSORY_STRUGGLE, resistance); } /** @@ -87,29 +96,15 @@ public class StruggleAccessory extends StruggleState { return false; } - // Only locked accessories can be struggled against - if (!(stack.getItem() instanceof ILockable lockable)) { + // Only require struggle if LOCKED or has BUILT_IN_LOCK. + // Unlocked accessories without built-in lock can be freely removed (no struggle needed). + boolean isLocked = stack.getItem() instanceof ILockable lockable && lockable.isLocked(stack); + boolean hasBuiltInLock = DataDrivenBondageItem.hasBuiltInLock(stack); + if (!isLocked && !hasBuiltInLock) { return false; } - return lockable.isLocked(stack); - } - - /** - * Check if the accessory is locked. - * - * @param state The player's bind state - * @return true if the accessory is locked - */ - @Override - protected boolean isItemLocked(PlayerBindState state) { - ItemStack stack = getAccessoryStack(state); - if ( - stack.isEmpty() || !(stack.getItem() instanceof ILockable lockable) - ) { - return false; - } - return lockable.isLocked(stack); + return true; } /** diff --git a/src/main/java/com/tiedup/remake/state/struggle/StruggleBinds.java b/src/main/java/com/tiedup/remake/state/struggle/StruggleBinds.java index 833db65..ea72013 100644 --- a/src/main/java/com/tiedup/remake/state/struggle/StruggleBinds.java +++ b/src/main/java/com/tiedup/remake/state/struggle/StruggleBinds.java @@ -1,6 +1,5 @@ package com.tiedup.remake.state.struggle; -import com.tiedup.remake.core.SettingsAccessor; import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager.MessageCategory; import com.tiedup.remake.core.TiedUpMod; @@ -93,31 +92,6 @@ public class StruggleBinds extends StruggleState { return true; } - /** - * Check if the bind item is locked. - * Used by StruggleState to apply x10 resistance penalty. - * - * @param state The player's bind state - * @return true if the bind is locked - */ - @Override - protected boolean isItemLocked(PlayerBindState state) { - Player player = state.getPlayer(); - if (player == null) return false; - - ItemStack bindStack = V2EquipmentHelper.getInRegion( - player, - BodyRegionV2.ARMS - ); - if (bindStack.isEmpty()) return false; - - // Works for both V1 (ItemBind) and V2 (DataDrivenBondageItem) via ILockable - if (bindStack.getItem() instanceof ILockable lockable) { - return lockable.isLocked(bindStack); - } - return false; - } - /** * Called when the player successfully escapes from their binds. * Drops all bondage items and completely unties the player. diff --git a/src/main/java/com/tiedup/remake/state/struggle/StruggleCollar.java b/src/main/java/com/tiedup/remake/state/struggle/StruggleCollar.java index fbe2b1d..79ec1ef 100644 --- a/src/main/java/com/tiedup/remake/state/struggle/StruggleCollar.java +++ b/src/main/java/com/tiedup/remake/state/struggle/StruggleCollar.java @@ -107,13 +107,12 @@ public class StruggleCollar extends StruggleState { return false; } - // Check if locked (works for V1 and V2 via ILockable) - if (collar.getItem() instanceof ILockable lockable) { - if (!lockable.isLocked(collar)) { - TiedUpMod.LOGGER.debug("[StruggleCollar] Collar is not locked"); - return false; - } - } else { + // Only require struggle if LOCKED or has BUILT_IN_LOCK. + // Unlocked collars without built-in lock can be freely removed (no struggle needed). + boolean isLocked = collar.getItem() instanceof ILockable lockable && lockable.isLocked(collar); + boolean hasBuiltInLock = DataDrivenBondageItem.hasBuiltInLock(collar); + if (!isLocked && !hasBuiltInLock) { + TiedUpMod.LOGGER.debug("[StruggleCollar] Collar is not locked and has no built-in lock — no struggle needed"); return false; } diff --git a/src/main/java/com/tiedup/remake/state/struggle/StruggleState.java b/src/main/java/com/tiedup/remake/state/struggle/StruggleState.java index 308523a..4cf4122 100644 --- a/src/main/java/com/tiedup/remake/state/struggle/StruggleState.java +++ b/src/main/java/com/tiedup/remake/state/struggle/StruggleState.java @@ -212,16 +212,6 @@ public abstract class StruggleState { */ protected abstract boolean canStruggle(PlayerBindState state); - /** - * Check if the item being struggled against is locked. - * - * @param state The player's bind state - * @return true if the item is locked - */ - protected boolean isItemLocked(PlayerBindState state) { - return false; // Default: not locked, subclasses override - } - /** * Check if debug logging is enabled. * diff --git a/src/main/java/com/tiedup/remake/tasks/V2TyingPlayerTask.java b/src/main/java/com/tiedup/remake/tasks/V2TyingPlayerTask.java index f36f27c..b80349b 100644 --- a/src/main/java/com/tiedup/remake/tasks/V2TyingPlayerTask.java +++ b/src/main/java/com/tiedup/remake/tasks/V2TyingPlayerTask.java @@ -70,6 +70,13 @@ public class V2TyingPlayerTask extends TyingPlayerTask { 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()) { diff --git a/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenBondageItem.java b/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenBondageItem.java index 5b1507c..6d3e61c 100644 --- a/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenBondageItem.java +++ b/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenBondageItem.java @@ -356,6 +356,16 @@ public class DataDrivenBondageItem extends AbstractV2BondageItem { holder.onEquipped(stack, entity); } + // Initialize currentResistance in NBT from ResistanceComponent at equip time. + // This avoids the MAX-scan fallback in getBaseResistance(entity) which returns + // the highest resistance across ALL equipped data-driven items. + ResistanceComponent resistComp = getComponent(stack, ComponentType.RESISTANCE, ResistanceComponent.class); + if (resistComp != null) { + com.tiedup.remake.items.base.IHasResistance resistanceItem = + (com.tiedup.remake.items.base.IHasResistance) stack.getItem(); + resistanceItem.setCurrentResistance(stack, resistComp.getBaseResistance()); + } + // NPC speed reduction (players use MovementStyleManager, not this legacy path) if (!(entity instanceof Player)) { Set regions = getOccupiedRegions(stack); diff --git a/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenItemRegistry.java b/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenItemRegistry.java index 1c72af3..0be4bb5 100644 --- a/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenItemRegistry.java +++ b/src/main/java/com/tiedup/remake/v2/bondage/datadriven/DataDrivenItemRegistry.java @@ -139,7 +139,9 @@ public final class DataDrivenItemRegistry { * Clear all definitions. Called on world unload or for testing. */ public static void clear() { - SNAPSHOT = RegistrySnapshot.EMPTY; + synchronized (RELOAD_LOCK) { + SNAPSHOT = RegistrySnapshot.EMPTY; + } } // ===== COMPONENT HOLDERS ===== diff --git a/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2LockToggle.java b/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2LockToggle.java index 488514a..565fb11 100644 --- a/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2LockToggle.java +++ b/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2LockToggle.java @@ -129,7 +129,6 @@ public class PacketV2LockToggle { UUID keyUUID = heldKey.getKeyUUID(heldKeyStack); lockable.setLockedByKeyUUID(stack, keyUUID); - lockable.initializeLockResistance(stack); TiedUpMod.LOGGER.debug( "[V2LockToggle] Locked region {} on entity {}", @@ -142,12 +141,10 @@ public class PacketV2LockToggle { if (hasMasterKey) { lockable.setLockedByKeyUUID(stack, null); - lockable.clearLockResistance(stack); } else if (heldKey != null) { UUID keyUUID = heldKey.getKeyUUID(heldKeyStack); if (!lockable.matchesKey(stack, keyUUID)) return; lockable.setLockedByKeyUUID(stack, null); - lockable.clearLockResistance(stack); } else { return; } diff --git a/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2StruggleStart.java b/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2StruggleStart.java index d8ca9a9..bf91b25 100644 --- a/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2StruggleStart.java +++ b/src/main/java/com/tiedup/remake/v2/bondage/network/PacketV2StruggleStart.java @@ -84,7 +84,7 @@ public class PacketV2StruggleStart { if (stack.getItem() instanceof ILockable lockable) { isLocked = lockable.isLocked(stack); if (isLocked) { - resistance += lockable.getCurrentLockResistance(stack); + resistance += com.tiedup.remake.core.SettingsAccessor.getPadlockResistance(null); } }