diff --git a/app/models/break_escape/game.rb b/app/models/break_escape/game.rb index d17e594..5fca34c 100644 --- a/app/models/break_escape/game.rb +++ b/app/models/break_escape/game.rb @@ -144,7 +144,13 @@ module BreakEscape if target_type == 'door' room = room_data(target_id) - return false unless room && room['locked'] + return false unless room + + # Handle unlocked doors - allow access without lock validation + if method == 'unlocked' || !room['locked'] + Rails.logger.info "[BreakEscape] Door is unlocked, granting access" + return true + end case method when 'key', 'lockpick', 'biometric', 'bluetooth', 'rfid' @@ -166,21 +172,25 @@ module BreakEscape if object Rails.logger.info "[BreakEscape] Found object: id=#{object['id']}, name=#{object['name']}, locked=#{object['locked']}, requires=#{object['requires']}" - end - next unless object && object['locked'] + # Handle unlocked objects - allow access without lock validation + if method == 'unlocked' || !object['locked'] + Rails.logger.info "[BreakEscape] Object is unlocked, granting access" + return true + end - case method - when 'key', 'lockpick', 'biometric', 'bluetooth', 'rfid' - # Client validated the unlock - trust it - return true - when 'pin', 'password' - result = object['requires'].to_s == attempt.to_s - Rails.logger.info "[BreakEscape] Password validation: required='#{object['requires']}', attempt='#{attempt}', result=#{result}" - return result + case method + when 'key', 'lockpick', 'biometric', 'bluetooth', 'rfid' + # Client validated the unlock - trust it + return true + when 'pin', 'password' + result = object['requires'].to_s == attempt.to_s + Rails.logger.info "[BreakEscape] Password validation: required='#{object['requires']}', attempt='#{attempt}', result=#{result}" + return result + end end end - Rails.logger.warn "[BreakEscape] Object not found or not locked: #{target_id}" + Rails.logger.warn "[BreakEscape] Object not found: #{target_id}" false end end diff --git a/public/break_escape/js/systems/doors.js b/public/break_escape/js/systems/doors.js index be4008a..31ecca4 100644 --- a/public/break_escape/js/systems/doors.js +++ b/public/break_escape/js/systems/doors.js @@ -544,37 +544,40 @@ export function createDoorSpritesForRoom(roomId, position) { } // Function to handle door interactions -function handleDoorInteraction(doorSprite) { +async function handleDoorInteraction(doorSprite) { const player = window.player; if (!player) return; - + const distance = Phaser.Math.Distance.Between( player.x, player.y, doorSprite.x, doorSprite.y ); - + const DOOR_INTERACTION_RANGE = 2 * TILE_SIZE; - + if (distance > DOOR_INTERACTION_RANGE) { console.log('Door too far to interact'); return; } - + const props = doorSprite.doorProperties; console.log(`Interacting with door: ${props.roomId} -> ${props.connectedRoom}`); - + // Check if locks are disabled for testing if (window.DISABLE_LOCKS) { console.log('LOCKS DISABLED FOR TESTING - Opening door directly'); openDoor(doorSprite); return; } - + if (props.locked) { console.log(`Door is locked. Type: ${props.lockType}, Requires: ${props.requires}`); // Use unified unlock system for consistent behavior with items handleUnlock(doorSprite, 'door'); } else { + console.log('Door is unlocked, notifying server to grant access'); + // Notify server to add room to unlockedRooms even for unlocked doors + const serverResponse = await notifyServerUnlock(doorSprite, 'door', 'unlocked'); openDoor(doorSprite); } } diff --git a/public/break_escape/js/systems/interactions.js b/public/break_escape/js/systems/interactions.js index 7c4d020..2d5bd1d 100644 --- a/public/break_escape/js/systems/interactions.js +++ b/public/break_escape/js/systems/interactions.js @@ -13,6 +13,33 @@ export function setGameInstance(gameInstance) { gameRef = gameInstance; } +// Helper function to notify server for unlocked container access +async function notifyServerForUnlockedContainer(sprite) { + const apiClient = window.ApiClient || window.APIClient; + const gameId = window.breakEscapeConfig?.gameId; + + if (!apiClient || !gameId) { + console.warn('ApiClient or gameId not available, skipping server notification'); + return; + } + + try { + const targetId = sprite.scenarioData?.id || sprite.scenarioData?.name || sprite.objectId; + console.log(`Notifying server of unlocked container access: ${targetId}`); + + const response = await apiClient.unlock('object', targetId, null, 'unlocked'); + + // If server returned contents, populate them + if (response.hasContents && response.contents && sprite.scenarioData) { + console.log('Server returned container contents:', response.contents); + sprite.scenarioData.contents = response.contents; + } + } catch (error) { + console.error('Failed to notify server of unlocked container access:', error); + // Continue anyway - don't block the user experience + } +} + // Helper function to calculate interaction distance with direction-based offset // Extends reach from the edge of the player sprite in the direction the player is facing function getInteractionDistance(playerSprite, targetX, targetY) { @@ -695,17 +722,19 @@ export function handleObjectInteraction(sprite) { // Handle container items (suitcase, briefcase, bags, bins, etc.) - check BEFORE lock check if (data.type === 'suitcase' || data.type === 'briefcase' || data.type === 'bag1' || data.type === 'bin1' || data.contents) { console.log('CONTAINER ITEM INTERACTION', data); - + // Check if container is locked if (data.locked === true) { console.log('CONTAINER LOCKED - UNLOCK SYSTEM WILL HANDLE', data); handleUnlock(sprite, 'item'); return; } - - // Container is unlocked (or has no lock) - launch the container minigame - console.log('CONTAINER UNLOCKED/OPEN - LAUNCHING MINIGAME', data); - handleContainerInteraction(sprite); + + // Container is unlocked (or has no lock) - notify server and launch the container minigame + console.log('CONTAINER UNLOCKED/OPEN - NOTIFYING SERVER AND LAUNCHING MINIGAME', data); + notifyServerForUnlockedContainer(sprite).then(() => { + handleContainerInteraction(sprite); + }); return; }