diff --git a/public/break_escape/js/minigames/password/password-minigame.js b/public/break_escape/js/minigames/password/password-minigame.js index c797d3e..bb7d0a1 100644 --- a/public/break_escape/js/minigames/password/password-minigame.js +++ b/public/break_escape/js/minigames/password/password-minigame.js @@ -373,23 +373,68 @@ export class PasswordMinigame extends MinigameScene { } } - submitPassword() { + async submitPassword() { if (!this.gameState.isActive) return; - + const enteredPassword = this.passwordField.value.trim(); - + if (!enteredPassword) { this.showFailure("Please enter a password", false, 2000); return; } - + this.gameData.attempts++; this.attemptsDisplay.textContent = this.gameData.attempts; - - if (enteredPassword === this.correctPassword) { - this.passwordCorrect(); + + // Check if we need server-side validation (correctPassword is null) + if (this.correctPassword === null && window.APIClient && window.gameId) { + await this.validatePasswordWithServer(enteredPassword); } else { - this.passwordIncorrect(); + // Client-side validation (backwards compatibility) + if (enteredPassword === this.correctPassword) { + this.passwordCorrect(); + } else { + this.passwordIncorrect(); + } + } + } + + async validatePasswordWithServer(enteredPassword) { + try { + // Get lockable object and type from params + const lockable = this.params.lockable || this.params.sprite; + const targetType = this.params.type || 'object'; // 'door' or 'object' + + // Get target ID from lockable + let targetId; + if (targetType === 'door') { + targetId = lockable.doorProperties?.connectedRoom || lockable.doorProperties?.roomId; + } else { + targetId = lockable.scenarioData?.id || lockable.scenarioData?.name || lockable.objectId; + } + + if (!targetId) { + console.error('Could not determine targetId for unlock validation'); + this.passwordIncorrect(); + return; + } + + console.log('Validating password with server:', { targetType, targetId, attempt: enteredPassword }); + + // Call server API for validation + const response = await window.APIClient.unlock(targetType, targetId, enteredPassword, 'password'); + + if (response.success) { + this.passwordCorrect(); + } else { + this.passwordIncorrect(); + } + } catch (error) { + console.error('Server validation error:', error); + this.showFailure("Network error. Please try again.", false, 3000); + // Decrease attempts counter since this wasn't a real attempt + this.gameData.attempts--; + this.attemptsDisplay.textContent = this.gameData.attempts; } } diff --git a/public/break_escape/js/minigames/pin/pin-minigame.js b/public/break_escape/js/minigames/pin/pin-minigame.js index 52d5ddf..2965b34 100644 --- a/public/break_escape/js/minigames/pin/pin-minigame.js +++ b/public/break_escape/js/minigames/pin/pin-minigame.js @@ -240,31 +240,73 @@ export class PinMinigame extends MinigameScene { this.updateDisplay(); } - handleEnter() { + async handleEnter() { if (this.isLocked || this.currentInput.length !== this.pinLength) { return; } - + this.attemptCount++; - const isCorrect = this.currentInput === this.correctPin; - + + // Check if we need server-side validation (correctPin is null) + let isCorrect; + if (this.correctPin === null && window.APIClient && window.gameId) { + isCorrect = await this.validatePinWithServer(this.currentInput); + } else { + // Client-side validation (backwards compatibility) + isCorrect = this.currentInput === this.correctPin; + } + // Record attempt const attempt = { input: this.currentInput, isCorrect: isCorrect, timestamp: new Date(), - feedback: (this.infoLeakToggleElement?.checked || this.infoLeakMode) ? this.calculateFeedback(this.currentInput) : null + feedback: (this.infoLeakToggleElement?.checked || this.infoLeakMode) && this.correctPin ? this.calculateFeedback(this.currentInput) : null }; - + this.attempts.push(attempt); this.updateAttemptsDisplay(); - + if (isCorrect) { this.handleSuccess(); } else { this.handleFailure(); } } + + async validatePinWithServer(enteredPin) { + try { + // Get lockable object and type from params + const lockable = this.params.lockable || this.params.sprite; + const targetType = this.params.type || 'object'; // 'door' or 'object' + + // Get target ID from lockable + let targetId; + if (targetType === 'door') { + targetId = lockable.doorProperties?.connectedRoom || lockable.doorProperties?.roomId; + } else { + targetId = lockable.scenarioData?.id || lockable.scenarioData?.name || lockable.objectId; + } + + if (!targetId) { + console.error('Could not determine targetId for unlock validation'); + return false; + } + + console.log('Validating PIN with server:', { targetType, targetId, attempt: enteredPin }); + + // Call server API for validation + const response = await window.APIClient.unlock(targetType, targetId, enteredPin, 'pin'); + + return response.success; + } catch (error) { + console.error('Server validation error:', error); + this.showFailure("Network error. Please try again.", false, 3000); + // Decrease attempts counter since this wasn't a real attempt + this.attemptCount--; + return false; + } + } calculateFeedback(input) { // Mastermind-style feedback: right number in right place, right number in wrong place diff --git a/public/break_escape/js/systems/minigame-starters.js b/public/break_escape/js/systems/minigame-starters.js index 5be2675..ee2138a 100644 --- a/public/break_escape/js/systems/minigame-starters.js +++ b/public/break_escape/js/systems/minigame-starters.js @@ -526,9 +526,11 @@ export function startPinMinigame(lockable, type, correctPin, callback) { title: `Enter PIN for ${type}`, correctPin: correctPin, maxAttempts: 3, - pinLength: correctPin.length, + pinLength: correctPin ? correctPin.length : 4, // Default to 4 if null (server-side validation) hasPinCracker: hasPinCracker, allowBackspace: true, + lockable: lockable, + type: type, // Pass type for server validation onComplete: (success, result) => { if (success) { console.log('PIN MINIGAME SUCCESS'); @@ -579,6 +581,7 @@ export function startPasswordMinigame(lockable, type, correctPassword, callback, postitNote: options.postitNote || '', showPostit: options.showPostit || false, lockable: lockable, + type: type, // Pass type for server validation requiresKeyboardInput: true, // Password minigame needs keyboard for text input onComplete: (success, result) => { if (success) {