Commit Graph

566 Commits

Author SHA1 Message Date
Z. Cliffe Schreuders
6b1d73f987 feat: Enhance objectives system with new NPC interactions and Ink dialogue integration 2025-11-26 11:18:25 +00:00
Z. Cliffe Schreuders
412cebb65c feat: Add objectives system with policy methods and test scenarios 2025-11-26 09:43:06 +00:00
Z. Cliffe Schreuders
9d6d7709c3 feat: Implement Objectives System with UI and Server Sync
- Added ObjectivesManager to track mission objectives and tasks.
- Created ObjectivesPanel for displaying objectives in a collapsible HUD.
- Integrated objectives state restoration from the server during game initialization.
- Implemented task completion and unlocking mechanisms via game actions.
- Added CSS styles for the objectives panel with a pixel-art aesthetic.
- Developed a test scenario to validate the objectives system functionality.
- Updated database schema to include fields for tracking completed objectives and tasks.
2025-11-26 00:50:32 +00:00
Z. Cliffe Schreuders
150518b4c4 feat: Include objectives state in server response and implement event emissions for door unlocks and key pickups 2025-11-25 23:19:11 +00:00
Z. Cliffe Schreuders
575dc9aad0 Add updated TODO checklist and corrected code snippets for objectives system
- Created an updated TODO checklist outlining phases and tasks for the objectives system implementation.
- Added corrected code snippets for critical fixes, including door unlock event emission and key pickup event handling.
- Documented necessary changes to ensure proper event emissions for objectives tracking.
- Reviewed and approved the implementation plan with minor corrections regarding door unlock events.
2025-11-25 23:13:58 +00:00
Z. Cliffe Schreuders
26fc297ad8 Refactor tests and improve NPC handling
- Updated NPC ink loading tests to ensure proper handling of missing story files.
- Adjusted lazy loading tests for rooms to enhance clarity and maintainability.
- Enhanced unlock system tests by adding inventory checks for keys.
- Refined filtered scenario tests to ensure accurate preservation of game state.
- Improved game model tests to validate unlock functionality with various inventory scenarios.
2025-11-25 16:28:18 +00:00
Z. Cliffe Schreuders
b317103c83 fix: Update CI test command and adjust RuboCop configuration for string literals 2025-11-25 16:14:46 +00:00
Z. Cliffe Schreuders
6d06a33a07 Add rubocop-rails-omakase to Gemfile for CI linting
The CI workflow was failing because rubocop was not available in the bundle.
Adding rubocop-rails-omakase which provides the omakase Ruby styling rules
that are configured in .rubocop.yml.
2025-11-25 16:07:05 +00:00
Z. Cliffe Schreuders
50e262c15d Fix GitHub CI configuration for Rails engine
- Fix test command syntax: change 'bin/rails db:test:prepare test' to 'bin/rails test:prepare'
- Remove unnecessary dependencies: google-chrome-stable, curl, libjemalloc2, libvips
- Remove unused screenshot upload step (no system tests)
- Remove commented Redis service configuration
- Simplify to only install sqlite3 for testing
2025-11-25 16:07:05 +00:00
Z. Cliffe Schreuders
659644b3da feat: Update CyBOK logo and enhance mission index styles with new CSS files 2025-11-25 16:03:09 +00:00
Z. Cliffe Schreuders
3cc9fafcec feat: Enhance mission management with CyBOK integration and collection filtering
- Added `Cybok` model to manage CyBOK entries associated with missions.
- Implemented `by_collection` scope in `Mission` model for filtering missions by collection.
- Updated `missions_controller` to filter missions based on the selected collection.
- Introduced `CybokSyncService` for syncing CyBOK data from mission metadata to the database.
- Created new views and partials for displaying CyBOK information with tooltips using Tippy.js.
- Added metadata fields to `break_escape_missions` for `secgen_scenario` and `collection`.
- Enhanced mission seeding logic to support new metadata and CyBOK entries.
- Added multiple new mission scenarios with associated metadata.
2025-11-25 15:20:05 +00:00
Z. Cliffe Schreuders
797b075cbe feat: Add mission metadata and CyBOK integration with JSON schema and example files 2025-11-25 14:59:57 +00:00
Z. Cliffe Schreuders
9cad11a853 fix: Correct key pin values for CEO office key to ensure proper unlocking 2025-11-25 14:59:49 +00:00
Z. Cliffe Schreuders
0d7ba1f2fc feat: Enhance key selection process by storing original inventory keys and correct key ID for retries 2025-11-24 13:52:07 +00:00
Z. Cliffe Schreuders
5ecfa5db27 feat: Implement KeyCutCalculator utility for consistent key cut depth calculations across the game
refactor: Update key-lock system and minigame starters to utilize KeyCutCalculator for cut depth generation
chore: Normalize keyPins in scenario data to align with new cut depth calculations
2025-11-24 13:41:35 +00:00
Z. Cliffe Schreuders
96cec569f7 Add tests for door unlock mechanics using keys and lockpicks
- Implemented tests to validate unlocking doors with the correct key in inventory.
- Added tests to ensure doors cannot be unlocked without the required key.
- Included scenarios for using lockpicks to unlock doors, bypassing key requirements.
- Ensured that keys take precedence over lockpick attempts when both are available.
- Added checks for accessing unlocked doors regardless of the unlocking method.
- Created helper tests to verify the presence of keys and lockpicks in the player's inventory.
2025-11-24 11:19:45 +00:00
Z. Cliffe Schreuders
b4b95928da feat: Enhance inventory management with server-side validation and CSRF protection 2025-11-24 11:17:39 +00:00
Z. Cliffe Schreuders
7efb758087 refactor: Simplify NPC dialogue structure and remove unnecessary speaker tags for improved readability 2025-11-24 10:20:05 +00:00
Z. Cliffe Schreuders
2c8757de3e Add character registry and NPC management features
- Implemented a global character registry to manage player and NPC data.
- Added methods for setting the player, registering NPCs, and retrieving character information.
- Integrated character registry updates into the NPC manager for seamless NPC registration.
- Created test scenarios for line prefix speaker format, including narrator modes and background changes.
- Developed comprehensive NPC sprite test scenario with various NPC interactions and items.
2025-11-24 02:21:31 +00:00
Z. Cliffe Schreuders
48e7860e0f Add comprehensive review and implementation plan for line prefix speaker format
- Created COMPREHENSIVE_REVIEW.md detailing architecture, risk assessment, and recommendations for the line prefix speaker format implementation.
- Developed README.md summarizing the implementation plan assessment, key findings, and integration of the Background[] feature.
- Included detailed risk assessment, updated timeline estimates, and success criteria for the implementation.
- Recommended enhancements for security, performance, reliability, and deployment strategies.
- Established a phased approach for implementation with clear priorities and next steps for the team and content creators.
2025-11-24 00:07:38 +00:00
Z. Cliffe Schreuders
843879cd62 feat: Enhance NPC chat system with narrator character support, default speaker behavior, and improved NPC behavior tags
- Implemented narrator syntax to display character portraits during narration.
- Changed default speaker behavior to default to the main NPC for unprefixed lines.
- Enhanced NPC behavior tags to support no parameters, comma-separated lists, wildcard patterns, and an "all" keyword.
- Added comprehensive testing requirements for narrator, default speaker, and NPC behavior tags.
- Updated documentation to reflect new features and usage examples.
- Addressed critical and high-priority issues from REVIEW1, including function naming conflicts, regex security, and empty dialogue validation.
- Improved code organization and backward compatibility.
2025-11-23 22:52:20 +00:00
Z. Cliffe Schreuders
5a997e38f7 Enhance NPC collision detection: add checks for table objects in NPC behavior and log successful collisions for better debugging. 2025-11-23 10:39:44 +00:00
Z. Cliffe Schreuders
59f096fdba Add wall escape functionality for NPCs: implement checks and escape logic for NPCs stuck in walls, enhancing collision handling and movement responsiveness. 2025-11-23 01:46:04 +00:00
Z. Cliffe Schreuders
98104b59a8 Enhance NPC behavior: implement home return functionality for stationary NPCs when pushed away from their starting position 2025-11-23 01:27:20 +00:00
Z. Cliffe Schreuders
279cc0125d Fix avatar URL resolution in contact list: ensure full URL is used for non-relative avatar paths 2025-11-22 13:59:21 +00:00
Z. Cliffe Schreuders
140def5650 Add Spotify play button and styles for improved music integration 2025-11-22 01:54:00 +00:00
Z. Cliffe Schreuders
f8bdb73a06 Improve door and unlock interaction handling: deactivate door sprites immediately upon opening, clean up interaction indicators, and ensure proper checks for inactive or destroyed doors. 2025-11-22 01:37:41 +00:00
Z. Cliffe Schreuders
83055f7589 Cancel click-to-move when keyboard input is detected to improve player control responsiveness 2025-11-22 01:30:44 +00:00
Z. Cliffe Schreuders
ac727f4422 Enhance unlock functionality: refactor door unlocking to async, validate NPC permissions via server, and ensure player state integrity 2025-11-22 01:25:36 +00:00
Z. Cliffe Schreuders
ef27265c8c Simplify NPC unlock to use standard unlock flow
PROBLEM:
Previous implementation had unnecessary complexity with npcUnlockedTargets
tracking. NPC unlocks should just work like any other unlock method.

SOLUTION:
1. Removed npcUnlockedTargets tracking (not needed)
2. NPC unlocks now use standard unlockedRooms/unlockedObjects arrays
3. Updated validate_unlock to check if already unlocked FIRST:
   - If in player_state unlocked list → grant access
   - If method='unlocked' → verify against scenario data locked field
   - Otherwise → validate normally

This fixes the race condition issue:
- NPC calls unlock API with method='npc'
- Server validates NPC has permission
- Server adds to unlockedRooms (normal unlock)
- Later when player opens door, client sends method='unlocked'
- Server sees it's already in unlockedRooms OR unlocked in scenario → grants access

Changes:
- app/models/break_escape/game.rb: Remove npc_unlock_target!/npc_unlocked?, check unlocked state first
- app/controllers/break_escape/games_controller.rb: Remove npc_unlock_target! calls
- test/integration/unlock_system_test.rb: Update tests for simplified approach

All 37 tests passing, 122 assertions
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
a36c0da04e Fix test errors and add route name for room endpoint
- Added 'as: room' to room route to fix room_game_url helper
- Fixed TypeError in initialize_player_state by using .dup instead of .deep_dup
- Simplified npcUnlockedTargets initialization test to avoid edge case
- All 38 tests now passing with 129 assertions
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
c5eca9cc60 Fix NPC unlock race condition with persistent server-side tracking
PROBLEM:
NPC unlocks had timing-dependent behavior:
- If NPC unlocked door BEFORE room loaded: client saw it as unlocked
- If NPC unlocked door AFTER room loaded: door sprite stayed locked

SOLUTION:
1. Server-side persistent tracking:
   - Added npcUnlockedTargets array to player_state
   - Track all NPC unlocks separately from unlockedRooms/unlockedObjects
   - Initialize npcUnlockedTargets in new games

2. Server merges NPC unlock state:
   - filtered_room_data checks npcUnlockedTargets
   - Marks doors/containers as unlocked if NPC unlocked them
   - Works regardless of when room is loaded

3. Client updates existing sprites:
   - NPC unlock handler finds ALL door sprites for target room
   - Updates sprite state immediately after server unlock
   - Handles both pre-loaded and late-loaded rooms

Changes:
- app/models/break_escape/game.rb: Add npc_unlock_target!, npc_unlocked?, merge state in filtered_room_data
- app/controllers/break_escape/games_controller.rb: Track NPC unlocks in unlock endpoint
- public/break_escape/js/minigames/person-chat/person-chat-conversation.js: Update all door sprites after NPC unlock
- public/break_escape/js/systems/doors.js: Export unlockDoor globally
- test/integration/unlock_system_test.rb: Add 4 tests for persistent NPC unlock state
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
d3b31b4368 Add comprehensive unlock system tests
Created test suite with 34 tests covering all unlock scenarios and security:

DOOR TESTS (10 tests):
- PIN/password validation (correct/incorrect, case sensitivity)
- Key unlocks (client-validated)
- Unlocked doors (method='unlocked')

CONTAINER TESTS (8 tests):
- PIN/password validation
- Key, lockpick, biometric, bluetooth, RFID unlocks
- Unlocked containers

NPC UNLOCK TESTS (6 tests):
 NPC can unlock door/container if encountered and has permission
🔒 SECURITY: Fails if NPC not encountered
🔒 SECURITY: Fails if NPC lacks permission for that target
🔒 SECURITY: Fails for non-existent NPC
🔒 SECURITY: Fails if unlockable is not an array

SECURITY TESTS - BYPASS PREVENTION (4 tests):
🔒 CRITICAL: Locked door CANNOT be bypassed with method='unlocked'
🔒 CRITICAL: Locked container CANNOT be bypassed with method='unlocked'
 Unlocked door CAN use method='unlocked'
 Unlocked container CAN use method='unlocked'

ERROR CASES (3 tests):
- Non-existent doors/objects return 422
- Invalid methods return 422

DATA FILTERING (2 tests):
- Verify 'requires' field filtered from responses
- Verify recursive filtering of contents

INTEGRATION (1 test):
- Multiple sequential unlocks
- Idempotent operations

Test Results: 34 runs, 115 assertions, 0 failures

Server Implementation:
- validate_npc_unlock: Validates NPC encounter and permission list
- find_npc_in_scenario: Searches all rooms for NPC
- method='npc': New unlock method requiring NPC id as attempt

Client Implementation:
- Updated handleUnlockDoor to call server API with method='npc'
- Server validates all NPC unlock requests
- No client-side lock manipulation

Security Principle: All unlock authorization is server-side.
Client cannot bypass locks by manipulating state or claiming NPC unlocks.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
65ede66810 CRITICAL SECURITY FIX: Prevent client bypass with method='unlocked'
Fixed critical vulnerability where ANY locked door/container could be bypassed
by sending method='unlocked' to the server.

The Vulnerability:
- Server used OR logic: if method == 'unlocked' || !room['locked']
- This meant: "If client says unlocked OR room is unlocked, grant access"
- Attacker could bypass ANY lock by sending method='unlocked'
- Example exploit: {targetType: "door", targetId: "ceo", method: "unlocked"}

The Fix:
- Changed to AND logic: if method == 'unlocked' && !room['locked']
- Now means: "Only if client says unlocked AND room is ACTUALLY unlocked"
- Added explicit rejection: return false if method='unlocked' on locked item
- Server now logs SECURITY VIOLATION when bypass is attempted

Changes:
- game.rb:151: Changed || to && for doors
- game.rb:157-160: Added explicit rejection for locked doors
- game.rb:185: Changed || to && for objects
- game.rb:191-194: Added explicit rejection for locked objects

Tests Added (4 new security tests):
1. Verify locked door CANNOT be bypassed with method='unlocked' (422 error)
2. Verify locked container CANNOT be bypassed with method='unlocked' (422 error)
3. Verify unlocked door CAN use method='unlocked' (200 success)
4. Verify unlocked container CAN use method='unlocked' (200 success)

Test Results: 28 tests, 95 assertions, 0 failures

Security Principle: Client state is NEVER trusted for authorization.
Server validates against its own scenario_data, not client claims.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
bda90baeab Fix unlocked doors/containers not opening after security changes
Fixed issue where unlocked doors and containers wouldn't open because
getLockRequirements functions returned null for unlocked items, causing
early return.

Changes:
- Handle case where lockRequirements is null (unlocked item) by calling
  server verification
- Updated getLockRequirementsForDoor to return data even for unlocked doors
- Updated getLockRequirementsForItem to include 'locked' field
- Now both locked and unlocked items go through proper server validation

Flow for unlocked items:
1. getLockRequirements returns null (no lock data) OR returns {locked: false}
2. Call notifyServerUnlock with method='unlocked'
3. Server validates item is actually unlocked in scenario_data
4. Server returns roomData (doors) or contents (containers)
5. Client proceeds to open/display content
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
424f69186c SECURITY: Enforce server-side validation for all door/container access
Critical security fix: Removed client-side lock state checking that allowed
bypass of server validation. Clients can no longer manipulate lock states to
gain unauthorized access.

Previous vulnerability:
- Client checked props.locked (client-side data)
- If false, directly called notifyServerUnlock with method='unlocked'
- Server trusted this without validating its own scenario data
- Attacker could: set doorSprite.doorProperties.locked = false, then access

New secure flow:
- Client ALWAYS calls handleUnlock regardless of perceived lock state
- handleUnlock calls server with method='unlocked' for unlocked items
- Server ALWAYS validates against its own scenario_data
- Server only grants access if item is actually unlocked in server state
- Client state is never trusted for authorization decisions

Changes:
- doors.js: Removed client-side lock check, always call handleUnlock
- unlock-system.js: Handle unlocked items by verifying with server
- interactions.js: Removed client-side container lock check
- interactions.js: Removed notifyServerForUnlockedContainer helper

Security principle: Never trust the client. All authorization must be
server-side based on server state, not client-reported state.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
81e9c71b6f Add comprehensive unlock system tests
Created extensive test suite covering all lock types and unlock scenarios:

DOOR TESTS:
- PIN validation (server-side) - correct/incorrect attempts
- Password validation (server-side) - correct/incorrect, case sensitivity
- Key unlocks (client-validated, server-trusted)
- Unlocked doors (method='unlocked')

CONTAINER TESTS:
- PIN validation (server-side) - correct/incorrect attempts
- Password validation (server-side) - correct/incorrect, empty attempts
- Key unlocks (client-validated)
- Lockpick unlocks (client-validated)
- Biometric unlocks (client-validated)
- Bluetooth unlocks (client-validated)
- RFID unlocks (client-validated)
- Unlocked containers (method='unlocked')

ERROR CASES:
- Non-existent doors/objects
- Invalid methods
- Multiple unlocks and idempotency

SECURITY TESTS:
- Verify 'requires' field is filtered from responses
- Verify contents are filtered recursively

INTEGRATION TESTS:
- Multiple sequential unlocks
- State persistence
- Idempotent operations

Also fixed: Game model generate_scenario_data now uses ||= to allow
test scenarios to override mission data.

Test Results: 24 tests, 83 assertions, 0 failures
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
cda71cf6f3 SECURITY: Enforce server-side validation for all PIN/password attempts
Critical security fix: PIN and password minigames were falling back to
client-side validation when the correct answer was available. This allowed
players to bypass security by inspecting client-side code.

Changes:
- PIN minigame: ALWAYS use server-side validation, never client-side
- Password minigame: ALWAYS use server-side validation, never client-side
- If API client is unavailable, fail securely by rejecting the attempt
- Removed backwards compatibility code that allowed client-side validation

Security principle: Never trust the client for authentication/authorization.
All PIN and password validation must go through the server.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
d59aaf51f9 Export notifyServerUnlock from unlock-system.js
Fixed ReferenceError where notifyServerUnlock was not defined in doors.js.
The function was internal to unlock-system.js but is now needed by doors.js
for notifying the server when unlocked doors are opened.

Changes:
- Export notifyServerUnlock from unlock-system.js
- Import notifyServerUnlock in doors.js
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
b2c8362d91 Allow unlocked doors and containers to notify server for access
Fixed issue where unlocked doors/containers couldn't be opened because
the server wasn't being notified to add them to unlockedRooms/unlockedObjects.

Server changes (game.rb):
- Updated validate_unlock to accept method='unlocked' for unlocked targets
- Added logic to grant access for unlocked doors/objects without validation

Client changes (doors.js):
- Updated handleDoorInteraction to notify server for unlocked doors
- Calls notifyServerUnlock with method='unlocked' before opening

Client changes (interactions.js):
- Added notifyServerForUnlockedContainer helper function
- Updated container interaction to notify server before launching minigame

This ensures that all room/container access is properly authorized on the
server side, preventing 403 Forbidden errors when loading room/container data.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
3494c739a5 Trust client validation for item-based unlock methods
Updated validate_unlock to use two-tier validation model:
- Server trusts client validation for item-based locks (key, lockpick, biometric, bluetooth, rfid)
- Server validates knowledge-based locks (pin, password)

This fixes 422 errors when unlocking with keys/lockpicking where attempt is nil,
since these methods don't require server-side answer validation.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
a3d1ba3826 Add server-side unlock notification for all lock types
- Created notifyServerUnlock helper function to DRY up code
- Updated lockpicking, key, biometric, bluetooth, and RFID unlocks to call server API
- All unlock methods now:
  1. Validate unlock client-side (minigame/item check)
  2. Notify server to update player_state
  3. Receive room/container data in response
  4. Pass serverResponse to unlockTarget

This ensures:
- Server tracks all unlocks in player_state (unlockedRooms/unlockedObjects)
- Room endpoint can validate access (403 if not unlocked)
- Single API call returns data needed (roomData for doors, contents for containers)
- Consistent behavior across all lock types
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
d2901eafa7 Optimize unlock flow to use single API call for doors and containers
Server-side changes:
- Unlock endpoint already returns roomData for doors

Client-side changes:
- Pass serverResponse through minigame callback chain
- Store serverResponse in minigame gameResult (password & PIN)
- Update minigame-starters to pass result to callbacks
- Update unlock-system callbacks to accept and pass serverResponse
- Pass roomData to unlockDoor for doors
- Cache roomData in roomDataCache before loadRoom is called
- loadRoom checks cache before making API call

Benefits:
- Doors: Unlock + room load = 1 API call instead of 2
- Containers: Unlock + contents = 1 API call instead of 2
- More efficient, faster user experience
- Consistent pattern for both doors and containers
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
77544520aa Return container contents in unlock API response
- Add find_object_in_scenario helper to locate objects by ID or name
- Include hasContents and contents fields in unlock response for containers
- Update password and PIN minigames to populate scenarioData.contents from server response
- This allows the container minigame to launch after successful server-side unlock

Without this, the contents field was filtered for security, preventing the container UI from launching.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
a02d2e3a82 Import ApiClient in main game and use correct gameId path
- Import ApiClient in game.js to ensure window.ApiClient is set early
- Use window.breakEscapeConfig?.gameId instead of window.gameId in minigames
- Consistent with the rest of the codebase

Without importing ApiClient in the main game flow, window.ApiClient wasn't available when minigames needed it.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
4676e43122 Fix ApiClient name and handle empty string as null in minigames
- Use correct ApiClient casing (window.ApiClient not window.APIClient)
- Check for both null and empty string to trigger server validation
- Add fallback to support both naming conventions
- Add debug logging to show which validation method is used

The ApiClient is exported as window.ApiClient but code was checking for window.APIClient.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
3bc9d9a0b1 Fix password minigame submit button and add debug logging
- Make submit button always visible (not just when hints are enabled)
- Add console logging to track validation flow
- Debug why server validation isn't being triggered

This ensures users can submit passwords and helps diagnose validation issues.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
8328374e5f Add logging and name fallback to unlock validation
- Add detailed logging to validate_unlock method to debug validation issues
- Check both object 'id' and 'name' fields when searching for objects
- Log password comparison details for debugging

This helps diagnose why correct passwords might not be accepted.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
02fc7f6876 Add server-side validation support to password and PIN minigames
- Update password minigame to call server API when correctPassword is null
- Update PIN minigame to call server API when correctPin is null
- Pass lockable and type parameters to minigames for server validation
- Maintain backwards compatibility with client-side validation
- Handle network errors gracefully without counting failed attempts

This allows minigames to validate attempts server-side for security, preventing client-side answer spoofing.
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
b27cde13d0 Fix unlock detection to work with server-side data filtering
- Update unlock-system.js to check 'locked' field instead of 'requires' for lock detection
- Pass null for key/pin/password required values (server validates)
- Preserve 'requires' field for biometric/bluetooth locks (contains item identifiers, not answers)
- Update both Game model and controller filtering methods

Fixes issue where locked objects didn't prompt for unlock after server-side filtering was implemented.
2025-11-22 00:46:55 +00:00