Commit Graph

22 Commits

Author SHA1 Message Date
NotEvil
f945e9449b feat(D-01/E): quickwins — debug toggle, HumanChairHelper move, collar equip
Q1: Remove F9 debug toggle from GltfAnimationApplier + delete dead
    GltfRenderLayer + remove keybind registration

Q2: Move HumanChairHelper from state/ to util/ — pure utility with
    no state dependency. 7 import updates.

Q3: Wire NECK collar equip flow in DataDrivenBondageItem:
    - Target must be tied up (V1 rule preserved)
    - Distance + line-of-sight validation
    - Owner added to NBT before equip via CollarHelper.addOwner()
    - V2EquipmentHelper handles conflict resolution
    - ModSounds.COLLAR_PUT played on success
    - OwnershipComponent.onEquipped registers in CollarRegistry
2026-04-15 10:57:01 +02:00
NotEvil
d6bb030ad7 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
NotEvil
199bf00aef feat(D-01/E): BuiltInLockComponent for organic items (E2)
- New BuiltInLockComponent: blocksUnequip() returns true (permanent lock)
- ComponentType: add BUILT_IN_LOCK enum value
- 8 organic item JSONs updated (slime, vine, web, tape variants)
- DataDrivenBondageItem: add hasBuiltInLock() static helper
2026-04-15 03:11:15 +02:00
NotEvil
3df979ceee fix(D-01/D): checkup cleanup — 5 issues resolved
1. LockableComponent: remove duplicate "Lockable" tooltip line
   (ILockable.appendLockTooltip already handles lock status display)
2. ILockable/IHasResistance Javadoc: update @link refs from deleted
   V1 classes to V2 AbstractV2BondageItem/DataDrivenBondageItem
3. SettingsAccessor Javadoc: remove stale BindVariant @link references
4. DataDrivenBondageItem: update NECK block comment (remove branch ref)
5. Delete empty bondage3d/gags/ directory
2026-04-15 02:52:27 +02:00
NotEvil
679d7033f9 feat(D-01/B): add can_attach_padlock field to data-driven items (B0)
- DataDrivenItemDefinition: add canAttachPadlock boolean (default true)
- DataDrivenItemParser: parse "can_attach_padlock" from JSON
- DataDrivenBondageItem: add static canAttachPadlockTo(stack) method
- AnvilEventHandler: check V2 definition before allowing padlock attach
2026-04-14 17:47:32 +02:00
NotEvil
df56ebb6bc fix(D-01/A): adversarial review fixes — 4 logic bugs
1. NECK region explicitly blocked in interactLivingEntity() — prevents
   V2 collars equipping without ownership setup (latent, no JSONs yet)

2. Swap rollback safety: if re-equip fails after swap failure, drop the
   old bind as item entity instead of losing it silently

3. GaggingComponent: cache GagMaterial at construction time — eliminates
   valueOf() log spam on every chat message with misconfigured material

4. Dual-bind prevention: check both V1 isTiedUp() AND V2 region occupied
   in TyingInteractionHelper and PacketSelfBondage to prevent equipping
   V2 bind on top of V1 bind
2026-04-14 16:48:50 +02:00
NotEvil
eee4825aba feat(D-01/A): NPC speed reduction for V2 items (A12)
- onEquipped: apply RestraintEffectUtils speed reduction for non-Player
  entities with ARMS region and legs bound. Full immobilization for
  WRAP/LATEX_SACK pose types.
- onUnequipped: remove speed reduction for non-Player entities
- Players use MovementStyleManager (V2 tick-based), not this legacy path
2026-04-14 16:07:41 +02:00
NotEvil
737a4fd59b feat(D-01/A): interaction routing + TyingInteractionHelper (A8)
- DataDrivenBondageItem.use(): shift+click cycles bind mode for ARMS items
- DataDrivenBondageItem.interactLivingEntity(): region-based routing
  - ARMS → TyingInteractionHelper (tying task with progress bar)
  - NECK → deferred to Branch C (no V2 collar JSONs yet)
  - Other regions → instant equip via parent AbstractV2BondageItem
- TyingInteractionHelper: extracted tying flow using V2TyingPlayerTask
  - Distance/LoS validation, swap if already tied, task lifecycle
2026-04-14 15:35:31 +02:00
NotEvil
751bad418d feat(D-01/A): poseType, helpers, OWNERSHIP ComponentType (A4, A5, A6)
- DataDrivenItemDefinition: add poseType field, parsed from JSON "pose_type"
- PoseTypeHelper: resolves PoseType from V2 definition or V1 ItemBind fallback
- BindModeHelper: static bind mode NBT utilities (isBindItem, hasArmsBound,
  hasLegsBound, cycleBindModeId) — works for V1 and V2 items
- CollarHelper: complete static utility class for collar operations with
  dual-path V2/V1 dispatch (ownership, features, shock, GPS, choke, alert)
- ComponentType: add OWNERSHIP enum value
- OwnershipComponent: stub class (lifecycle hooks added in next commit)
2026-04-14 15:23:08 +02:00
NotEvil
b81d3eed95 feat(D-01/A): config-driven components + tooltip hook (A1, A2, A3)
- ResistanceComponent: resistanceId delegates to SettingsAccessor at runtime,
  fallback to hardcoded base for backward compat
- GaggingComponent: material field delegates to GagMaterial enum from ModConfig,
  explicit comprehension/range overrides take priority
- IItemComponent: add default appendTooltip() method
- ComponentHolder: iterate components for tooltip contribution
- 6 components implement appendTooltip (lockable, resistance, gagging, shock,
  gps, choking)
- DataDrivenBondageItem: call holder.appendTooltip() in appendHoverText()
2026-04-14 15:05:48 +02:00
NotEvil
90bc890b95 fix(D-01): synchronize reload paths and capture snapshot locally (RISK-001, RISK-002) 2026-04-14 02:46:09 +02:00
NotEvil
bfcc20d242 fix(D-01): compact constructor defaults null componentConfigs to empty (RISK-004)
Add compact constructor to DataDrivenItemDefinition that defaults null
componentConfigs to Map.of(). This makes the field guaranteed non-null,
allowing removal of null checks in hasComponent() and
DataDrivenItemRegistry.buildComponentHolders().
2026-04-14 02:29:25 +02:00
NotEvil
bb589d44f8 fix(D-01): warn on non-object component config, deep-copy configs (RISK-001, RISK-002)
- Deep-copy JsonObject configs via deepCopy() before storing in the
  definition to prevent external mutation of the parsed JSON tree
- Log a warning when a component config value is not a JsonObject,
  making misconfigured JSON easier to diagnose
2026-04-14 02:27:59 +02:00
NotEvil
456335e0dd fix(D-01): wire LockableComponent.lockResistance via getItemLockResistance() (BUG-003)
- Remove redundant blocksUnequip() from LockableComponent since
  AbstractV2BondageItem.canUnequip() already checks ILockable.isLocked()
- Add DataDrivenBondageItem.getItemLockResistance(ItemStack) that reads
  the per-item lock resistance from the LockableComponent, falling back
  to the global config value when absent
2026-04-14 02:27:37 +02:00
NotEvil
1327e3bfc3 fix(D-01): atomic snapshot for registry to prevent torn reads (BUG-001)
Replace two separate volatile fields (DEFINITIONS, COMPONENT_HOLDERS)
with a single RegistrySnapshot record swapped atomically. This prevents
race conditions where a reader thread could see new definitions paired
with stale/empty component holders between the two volatile writes.
2026-04-14 02:25:57 +02:00
NotEvil
84f4c3a53f feat(D-01): implement ResistanceComponent, improve stack-aware resistance lookup 2026-04-14 02:01:46 +02:00
NotEvil
3a1f401ccf feat(D-01): delegate DataDrivenBondageItem lifecycle to components
Override onEquipped(), onUnequipped(), and canUnequip() in
DataDrivenBondageItem to delegate to the item's ComponentHolder.
The canUnequip() override preserves the existing lock check from
AbstractV2BondageItem via super.canUnequip().

Add a static getComponent() helper for external code to retrieve
a typed component from any data-driven item stack.
2026-04-14 01:47:19 +02:00
NotEvil
a781dad597 feat(D-01): instantiate ComponentHolder per item definition on reload
Add a parallel COMPONENT_HOLDERS volatile cache to DataDrivenItemRegistry,
rebuilt from raw componentConfigs every time definitions are loaded via
reload() or mergeAll(). Cleared alongside DEFINITIONS in clear().

Two accessor methods allow looking up a ComponentHolder by ItemStack
(reads tiedup_item_id NBT) or by ResourceLocation directly.
2026-04-14 01:46:19 +02:00
NotEvil
750be66d80 feat(D-01): parse component configs from item JSON definitions
Add componentConfigs field (Map<ComponentType, JsonObject>) to
DataDrivenItemDefinition record. The parser now reads an optional
"components" JSON block, resolves each key via ComponentType.fromKey(),
and stores the raw JsonObject configs for later instantiation.
2026-04-14 01:44:19 +02:00
NotEvil
e17998933c Add creator field and enriched tooltip for data-driven items
- Add optional "creator" JSON field to display author name in tooltip
- Show body regions, movement style, lock status, and escape difficulty
- Show pose priority and item ID in advanced mode (F3+H)
- Update ARTIST_GUIDE.md field reference and test JSON
2026-04-13 04:00:27 +02:00
NotEvil
a71093ba9c Remove internal phase comments and format code
Strip all Phase references, TODO/FUTURE roadmap notes, and internal
planning comments from the codebase. Run Prettier for consistent
formatting across all Java files.
2026-04-12 01:25:55 +02:00
NotEvil
f6466360b6 Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies,
and third-party source dumps. Add proper README, update .gitignore,
clean up Makefile.
2026-04-12 00:51:22 +02:00