mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
docs: Add simplified Rails Engine migration approach
RECOMMENDED APPROACH: 12-14 weeks instead of 22 weeks KEY SIMPLIFICATIONS: - Use JSON storage for game state (already in that format) - 3 database tables instead of 10+ - game_instances (with player_state JSONB) - scenarios (with scenario_data JSONB) - npc_scripts (Ink JSON) - 6 API endpoints instead of 15+ - Bootstrap game - Load room (when unlocked) - Attempt unlock - Update inventory - Load NPC script (on encounter) - Sync state (periodic) VALIDATION STRATEGY: - Validate unlock attempts (server has solutions) - Validate room/object access (check unlocked state) - Validate inventory changes (check item in unlocked location) - NPCs: Load Ink scripts on encounter, run conversations 100% client-side - NPC door unlocks: Simple check (encountered NPC + scenario permission) WHAT WE DON'T TRACK: - Every event (client-side only) - Every conversation turn (no sync needed) - Every minigame action (only result matters) - Complex NPC permissions (simple rule: encountered = trusted) BENEFITS: - Faster development (12-14 weeks vs 22 weeks) - Easier maintenance (JSON matches existing format) - Better performance (fewer queries, JSONB indexing) - More flexible (easy to modify game state structure) - Simpler logic (clear validation rules) Updated README_UPDATED.md to recommend simplified approach first. Complex approach documentation retained for reference.
This commit is contained in:
@@ -12,26 +12,36 @@ This directory contains comprehensive plans for migrating BreakEscape from a sta
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 📋 Start Here
|
||||
### 🚀 **RECOMMENDED: Simplified Approach**
|
||||
|
||||
1. **[UPDATED_MIGRATION_STATUS.md](./UPDATED_MIGRATION_STATUS.md)** ⭐ **READ THIS FIRST**
|
||||
1. **[SIMPLIFIED_APPROACH.md](./SIMPLIFIED_APPROACH.md)** ⭐ **START HERE**
|
||||
- **12-14 weeks** instead of 22 weeks
|
||||
- **3 database tables** instead of 10+
|
||||
- **6 API endpoints** instead of 15+
|
||||
- JSON-based storage (matches existing format)
|
||||
- Simple validation rules
|
||||
- **This is the recommended implementation path**
|
||||
|
||||
### 📚 Alternative: Full Analysis (Original Complex Approach)
|
||||
|
||||
2. **[UPDATED_MIGRATION_STATUS.md](./UPDATED_MIGRATION_STATUS.md)**
|
||||
- Comprehensive status of what's changed since original plans
|
||||
- What's been implemented (NPCs, Events, Game State)
|
||||
- What still needs to be done (server-side sync)
|
||||
- Updated timeline (22 weeks vs 18 weeks)
|
||||
- Risk assessment and success metrics
|
||||
- Timeline: 22 weeks
|
||||
- ⚠️ More complex than needed - see SIMPLIFIED_APPROACH.md instead
|
||||
|
||||
2. **[progress/CLIENT_SERVER_SEPARATION_PLAN.md](./progress/CLIENT_SERVER_SEPARATION_PLAN.md)** ⭐ **READ THIS SECOND**
|
||||
3. **[progress/CLIENT_SERVER_SEPARATION_PLAN.md](./progress/CLIENT_SERVER_SEPARATION_PLAN.md)**
|
||||
- System-by-system separation strategy
|
||||
- Updated with NPC, Event, and Game State systems
|
||||
- Detailed implementation examples
|
||||
- Migration checklist with 9 phases (was 7)
|
||||
- Migration checklist with 9 phases
|
||||
- ⚠️ Over-engineered - see SIMPLIFIED_APPROACH.md instead
|
||||
|
||||
3. **[progress/RAILS_ENGINE_MIGRATION_PLAN.md](./progress/RAILS_ENGINE_MIGRATION_PLAN.md)**
|
||||
4. **[progress/RAILS_ENGINE_MIGRATION_PLAN.md](./progress/RAILS_ENGINE_MIGRATION_PLAN.md)**
|
||||
- Complete Rails Engine creation guide
|
||||
- Database schema (needs updates for new systems)
|
||||
- Phase-by-phase implementation (18 week plan)
|
||||
- Deployment checklist
|
||||
- Database schema for complex approach
|
||||
- Phase-by-phase implementation
|
||||
- ⚠️ Use simplified schema from SIMPLIFIED_APPROACH.md instead
|
||||
|
||||
---
|
||||
|
||||
@@ -122,7 +132,9 @@ This directory contains comprehensive plans for migrating BreakEscape from a sta
|
||||
|
||||
## Updated Migration Timeline
|
||||
|
||||
### Total Duration: 22 weeks (~5.5 months)
|
||||
### ⚠️ NOTE: This is the complex approach timeline. See SIMPLIFIED_APPROACH.md for 12-14 week alternative.
|
||||
|
||||
### Total Duration: 22 weeks (~5.5 months) - COMPLEX APPROACH
|
||||
|
||||
**Breakdown:**
|
||||
- Weeks 1-4: Server Infrastructure (Rails Engine, Database, Models)
|
||||
@@ -366,18 +378,36 @@ end
|
||||
|
||||
## Conclusion
|
||||
|
||||
The codebase has matured significantly with production-ready implementations of NPCs, events, and game state. The original migration plans are fundamentally sound but need:
|
||||
The codebase has matured significantly with production-ready implementations of NPCs, events, and game state.
|
||||
|
||||
- ✅ 4 additional weeks for new systems
|
||||
- ✅ Updated database schema
|
||||
- ✅ Additional API endpoints
|
||||
- ✅ More comprehensive testing
|
||||
### ⭐ RECOMMENDED: Simplified Approach
|
||||
|
||||
**The migration is READY TO BEGIN** with these updated plans.
|
||||
**See SIMPLIFIED_APPROACH.md** for the recommended implementation:
|
||||
- **12-14 weeks** (vs 22 weeks)
|
||||
- **3 tables** (vs 10+)
|
||||
- **6 endpoints** (vs 15+)
|
||||
- JSON-based storage
|
||||
- Simple validation rules
|
||||
- Much easier to maintain
|
||||
|
||||
**Estimated Completion:** 22 weeks from start
|
||||
**Confidence Level:** High
|
||||
**Risk Level:** Medium (manageable with incremental approach)
|
||||
### Alternative: Complex Approach (This Document)
|
||||
|
||||
The detailed plans in this document are fundamentally sound but over-engineered:
|
||||
- ⚠️ 22 weeks timeline
|
||||
- ⚠️ 10+ database tables
|
||||
- ⚠️ 15+ API endpoints
|
||||
- ⚠️ Complex state management
|
||||
|
||||
**We recommend starting with the simplified approach.**
|
||||
|
||||
**Estimated Completion:**
|
||||
- Simplified: 12-14 weeks
|
||||
- Complex: 22 weeks
|
||||
|
||||
**Confidence Level:** High (both approaches)
|
||||
**Risk Level:**
|
||||
- Simplified: Low
|
||||
- Complex: Medium
|
||||
|
||||
---
|
||||
|
||||
|
||||
543
planning_notes/rails-engine-migration/SIMPLIFIED_APPROACH.md
Normal file
543
planning_notes/rails-engine-migration/SIMPLIFIED_APPROACH.md
Normal file
@@ -0,0 +1,543 @@
|
||||
# Simplified Rails Engine Migration Approach
|
||||
## Last Updated: 2025-11-20
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
**Keep it simple:** Use JSON storage for game state (it's already in that format), validate only what matters, and minimize server round-trips.
|
||||
|
||||
---
|
||||
|
||||
## What We Actually Need to Track
|
||||
|
||||
### 1. **Scenario JSON (Filtered for Client)**
|
||||
**Server stores:** Complete scenario with solutions
|
||||
**Client receives:** Filtered JSON with:
|
||||
- Room layouts (connections, types)
|
||||
- Objects visible but lock requirements hidden
|
||||
- NPCs present but Ink scripts loaded on-demand
|
||||
- No PINs, passwords, key IDs, or container contents
|
||||
|
||||
### 2. **Player Current State (Simple JSON)**
|
||||
```json
|
||||
{
|
||||
"currentRoom": "room_reception",
|
||||
"position": { "x": 100, "y": 200 },
|
||||
"unlockedRooms": ["room_reception", "room_office"],
|
||||
"unlockedObjects": ["desk_drawer_123", "safe_456"],
|
||||
"inventory": [
|
||||
{ "type": "key", "name": "Office Key", "key_id": "office_key_1" },
|
||||
{ "type": "lockpick", "name": "Lockpick Set" }
|
||||
],
|
||||
"encounteredNPCs": ["security_guard", "receptionist"],
|
||||
"globalVariables": {
|
||||
"alarm_triggered": false,
|
||||
"player_favor": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That's it! One JSON blob per player per scenario.
|
||||
|
||||
### 3. **NPC Ink Scripts (Lazy Loaded)**
|
||||
- When player encounters NPC → load Ink script
|
||||
- All conversation happens client-side
|
||||
- Only validate if NPC grants door unlock (simple check: has player encountered this NPC?)
|
||||
|
||||
---
|
||||
|
||||
## Simplified Database Schema
|
||||
|
||||
### One Main Table: `game_instances`
|
||||
|
||||
```ruby
|
||||
create_table :game_instances do |t|
|
||||
t.references :user, null: false
|
||||
t.references :scenario, null: false
|
||||
|
||||
# Game state as JSON
|
||||
t.jsonb :player_state, default: {
|
||||
currentRoom: 'room_reception',
|
||||
position: { x: 0, y: 0 },
|
||||
unlockedRooms: [],
|
||||
unlockedObjects: [],
|
||||
inventory: [],
|
||||
encounteredNPCs: [],
|
||||
globalVariables: {}
|
||||
}
|
||||
|
||||
# Metadata
|
||||
t.string :status, default: 'in_progress' # in_progress, completed, abandoned
|
||||
t.datetime :started_at
|
||||
t.datetime :completed_at
|
||||
t.integer :score, default: 0
|
||||
|
||||
t.timestamps
|
||||
|
||||
t.index [:user_id, :scenario_id], unique: true
|
||||
t.index :player_state, using: :gin # For JSON queries
|
||||
end
|
||||
|
||||
create_table :scenarios do |t|
|
||||
t.string :name, null: false
|
||||
t.text :description
|
||||
t.jsonb :scenario_data # Complete scenario JSON (with solutions)
|
||||
t.boolean :published, default: false
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :npc_scripts do |t|
|
||||
t.references :scenario, null: false
|
||||
t.string :npc_id, null: false
|
||||
t.text :ink_script # Ink JSON
|
||||
t.timestamps
|
||||
|
||||
t.index [:scenario_id, :npc_id], unique: true
|
||||
end
|
||||
```
|
||||
|
||||
**That's it! 3 tables instead of 10+**
|
||||
|
||||
---
|
||||
|
||||
## Simplified API Endpoints
|
||||
|
||||
### 1. Bootstrap Game
|
||||
```
|
||||
GET /api/games/:game_id/bootstrap
|
||||
|
||||
Response:
|
||||
{
|
||||
"startRoom": "room_reception",
|
||||
"scenarioName": "CEO Heist",
|
||||
"playerState": { currentRoom, position, inventory, ... },
|
||||
"roomLayout": {
|
||||
// Just room IDs and connections, no solutions
|
||||
"room_reception": {
|
||||
"connections": { "north": "room_office" },
|
||||
"locked": false
|
||||
},
|
||||
"room_office": {
|
||||
"connections": { "south": "room_reception", "north": "room_ceo" },
|
||||
"locked": true // But no lockType or requires!
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Load Room (When Unlocked)
|
||||
```
|
||||
GET /api/games/:game_id/rooms/:room_id
|
||||
|
||||
Server checks: Is room in playerState.unlockedRooms?
|
||||
- Yes → Return room data (objects, but still no lock solutions)
|
||||
- No → 403 Forbidden
|
||||
|
||||
Response:
|
||||
{
|
||||
"roomId": "room_office",
|
||||
"objects": [
|
||||
{
|
||||
"type": "desk",
|
||||
"name": "Desk",
|
||||
"locked": true, // But no "requires" field
|
||||
"observations": "A locked desk drawer"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Attempt Unlock
|
||||
```
|
||||
POST /api/games/:game_id/unlock
|
||||
|
||||
Body:
|
||||
{
|
||||
"targetType": "door|object",
|
||||
"targetId": "room_ceo|desk_drawer_123",
|
||||
"method": "key|pin|password|lockpick",
|
||||
"attempt": "1234|password123|key_id_5"
|
||||
}
|
||||
|
||||
Server:
|
||||
- Loads complete scenario JSON
|
||||
- Checks if attempt matches requirement
|
||||
- If valid:
|
||||
- Adds to playerState.unlockedRooms or unlockedObjects
|
||||
- Returns unlocked content
|
||||
- If invalid:
|
||||
- Returns failure message
|
||||
|
||||
Response (success):
|
||||
{
|
||||
"success": true,
|
||||
"type": "door",
|
||||
"roomData": { ... } // If door
|
||||
// OR
|
||||
"contents": [ ... ] // If container
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Update Inventory
|
||||
```
|
||||
POST /api/games/:game_id/inventory
|
||||
|
||||
Body:
|
||||
{
|
||||
"action": "add|remove",
|
||||
"item": { "type": "key", "name": "Office Key", "key_id": "..." }
|
||||
}
|
||||
|
||||
Server validates:
|
||||
- For "add": Is item in an unlocked container/room?
|
||||
- Updates playerState.inventory
|
||||
|
||||
Response:
|
||||
{ "success": true, "inventory": [...] }
|
||||
```
|
||||
|
||||
### 5. Load NPC Script (On Encounter)
|
||||
```
|
||||
GET /api/games/:game_id/npcs/:npc_id/script
|
||||
|
||||
Server checks: Is NPC in current room OR already in playerState.encounteredNPCs?
|
||||
- Yes → Return Ink script
|
||||
- No → 403 Forbidden
|
||||
|
||||
Side effect: Add to playerState.encounteredNPCs
|
||||
|
||||
Response:
|
||||
{
|
||||
"npcId": "security_guard",
|
||||
"inkScript": { ... }, // Full Ink JSON
|
||||
"eventMappings": [...],
|
||||
"timedMessages": [...]
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Sync State (Periodic)
|
||||
```
|
||||
PUT /api/games/:game_id/state
|
||||
|
||||
Body:
|
||||
{
|
||||
"currentRoom": "room_office",
|
||||
"position": { "x": 150, "y": 220 },
|
||||
"globalVariables": { "alarm_triggered": false }
|
||||
}
|
||||
|
||||
Server: Merges into playerState (validates room is unlocked)
|
||||
```
|
||||
|
||||
**That's it! 6 endpoints instead of 15+**
|
||||
|
||||
---
|
||||
|
||||
## What We DON'T Track Server-Side
|
||||
|
||||
### ❌ Every Event
|
||||
- No event logging (unless needed for analytics later)
|
||||
- NPCs listen to events client-side only
|
||||
|
||||
### ❌ Every Conversation Turn
|
||||
- All NPC dialogue happens client-side
|
||||
- No conversation history sync needed
|
||||
- No story state tracking
|
||||
|
||||
### ❌ Every Minigame Action
|
||||
- Minigames run 100% client-side
|
||||
- Only unlock validation matters
|
||||
|
||||
### ❌ Complex Permissions
|
||||
- No NPCPermission table
|
||||
- Simple rule: If player encountered NPC, NPC can do its thing
|
||||
|
||||
---
|
||||
|
||||
## Validation Strategy (Simplified)
|
||||
|
||||
### When Server Validates
|
||||
|
||||
1. **Unlock Attempts** ✅
|
||||
- Check attempt against scenario JSON
|
||||
- Update unlocked state
|
||||
|
||||
2. **Inventory Changes** ✅
|
||||
- Verify item exists in unlocked location
|
||||
- Update inventory JSON
|
||||
|
||||
3. **Room Access** ✅
|
||||
- Check room in unlockedRooms
|
||||
- Return filtered room data
|
||||
|
||||
4. **NPC Script Loading** ✅
|
||||
- Check NPC encountered or in current room
|
||||
- Return Ink script
|
||||
|
||||
### When Server Doesn't Validate
|
||||
|
||||
1. **Conversations** ❌ - All client-side
|
||||
2. **Movement** ❌ - Trust client position
|
||||
3. **Events** ❌ - Client-side only
|
||||
4. **Minigame Actions** ❌ - Only result matters
|
||||
5. **Global Variables** ❌ - Sync periodically, don't validate every change
|
||||
|
||||
---
|
||||
|
||||
## NPC Door Unlock Simplification
|
||||
|
||||
**Scenario defines:** NPC can unlock door X
|
||||
```json
|
||||
{
|
||||
"id": "security_guard",
|
||||
"canUnlock": ["room_server"]
|
||||
}
|
||||
```
|
||||
|
||||
**Client requests:** NPC unlock door
|
||||
```
|
||||
POST /api/games/:game_id/npc_unlock
|
||||
|
||||
Body:
|
||||
{
|
||||
"npcId": "security_guard",
|
||||
"doorId": "room_server"
|
||||
}
|
||||
|
||||
Server validates:
|
||||
- Is NPC in playerState.encounteredNPCs?
|
||||
- Does scenario say NPC can unlock this door?
|
||||
- If yes: Add to unlockedRooms, return room data
|
||||
```
|
||||
|
||||
**No conversation tracking, no trust levels, no complex permissions!**
|
||||
|
||||
---
|
||||
|
||||
## Migration Timeline (Simplified)
|
||||
|
||||
### Total: 12-14 weeks (vs 22 weeks original)
|
||||
|
||||
**Weeks 1-2:** Setup
|
||||
- Create Rails Engine
|
||||
- 3 database tables
|
||||
- Import scenarios as JSON
|
||||
|
||||
**Weeks 3-4:** Core API
|
||||
- Bootstrap endpoint
|
||||
- Room loading
|
||||
- Unlock validation
|
||||
|
||||
**Weeks 5-6:** Client Integration
|
||||
- Modify loadRoom() to fetch from server
|
||||
- Add unlock validation
|
||||
- NPC script lazy loading
|
||||
|
||||
**Weeks 7-8:** Inventory & State Sync
|
||||
- Inventory API
|
||||
- State sync endpoint
|
||||
- Offline queue
|
||||
|
||||
**Weeks 9-10:** NPC Integration
|
||||
- NPC script loading
|
||||
- NPC door unlock (simple validation)
|
||||
- Import all Ink scripts
|
||||
|
||||
**Weeks 11-12:** Testing & Polish
|
||||
- Integration testing
|
||||
- Performance optimization
|
||||
- Security audit
|
||||
|
||||
**Weeks 13-14:** Deployment
|
||||
- Staging deployment
|
||||
- Load testing
|
||||
- Production deployment
|
||||
|
||||
**Savings: 8-10 weeks** by simplifying!
|
||||
|
||||
---
|
||||
|
||||
## Implementation Example: Unlock Validation
|
||||
|
||||
### Server-Side (Simple)
|
||||
|
||||
```ruby
|
||||
class Api::UnlockController < ApplicationController
|
||||
def create
|
||||
game = GameInstance.find(params[:game_id])
|
||||
|
||||
# Load complete scenario (has solutions)
|
||||
scenario = game.scenario.scenario_data
|
||||
|
||||
target_type = params[:target_type] # 'door' or 'object'
|
||||
target_id = params[:target_id]
|
||||
attempt = params[:attempt]
|
||||
method = params[:method]
|
||||
|
||||
# Find target in scenario
|
||||
target = find_target(scenario, target_type, target_id)
|
||||
|
||||
# Validate attempt
|
||||
is_valid = validate_attempt(target, attempt, method)
|
||||
|
||||
if is_valid
|
||||
# Update player state JSON
|
||||
if target_type == 'door'
|
||||
game.player_state['unlockedRooms'] << target_id
|
||||
room_data = get_filtered_room_data(scenario, target_id)
|
||||
|
||||
game.save!
|
||||
render json: { success: true, roomData: room_data }
|
||||
else
|
||||
game.player_state['unlockedObjects'] << target_id
|
||||
contents = target['contents'] || []
|
||||
|
||||
game.save!
|
||||
render json: { success: true, contents: contents }
|
||||
end
|
||||
else
|
||||
render json: { success: false, message: 'Invalid attempt' }, status: 422
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_attempt(target, attempt, method)
|
||||
case method
|
||||
when 'key'
|
||||
target['requires'] == attempt # key_id matches
|
||||
when 'pin', 'password'
|
||||
target['requires'] == attempt # PIN/password matches
|
||||
when 'lockpick'
|
||||
true # Client-side minigame passed, trust it
|
||||
end
|
||||
end
|
||||
|
||||
def get_filtered_room_data(scenario, room_id)
|
||||
room = scenario['rooms'][room_id].dup
|
||||
|
||||
# Remove solutions from objects
|
||||
room['objects']&.each do |obj|
|
||||
obj.delete('requires')
|
||||
obj.delete('contents') if obj['locked']
|
||||
end
|
||||
|
||||
room
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Client-Side (Unchanged)
|
||||
|
||||
```javascript
|
||||
async function handleUnlock(lockable, type) {
|
||||
// Show minigame or prompt (unchanged)
|
||||
const attempt = await getUnlockAttempt(lockable);
|
||||
|
||||
// NEW: Validate with server
|
||||
const response = await fetch(`/api/games/${gameId}/unlock`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
targetType: type,
|
||||
targetId: lockable.objectId,
|
||||
method: lockable.lockType,
|
||||
attempt: attempt
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Unlock locally
|
||||
unlockTarget(lockable, type);
|
||||
|
||||
// If door, load room
|
||||
if (type === 'door' && result.roomData) {
|
||||
createRoom(result.roomData.roomId, result.roomData, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Benefits of Simplified Approach
|
||||
|
||||
### 1. **Faster Development**
|
||||
- 12-14 weeks vs 22 weeks
|
||||
- 3 tables vs 10+
|
||||
- 6 endpoints vs 15+
|
||||
|
||||
### 2. **Easier Maintenance**
|
||||
- JSON storage matches existing format
|
||||
- No ORM complexity
|
||||
- Simple queries
|
||||
|
||||
### 3. **Better Performance**
|
||||
- Fewer database queries
|
||||
- Single JSON blob vs many joins
|
||||
- JSONB indexing is fast
|
||||
|
||||
### 4. **Flexible**
|
||||
- Easy to add new fields to JSON
|
||||
- No migrations for game state changes
|
||||
- Scenarios stay as JSON files
|
||||
|
||||
### 5. **Simpler Logic**
|
||||
- No complex permissions
|
||||
- No conversation state tracking
|
||||
- Clear validation rules
|
||||
|
||||
---
|
||||
|
||||
## What We Give Up (And Why It's OK)
|
||||
|
||||
### ❌ Conversation History Persistence
|
||||
**Why OK:** NPCs work great client-side. If player refreshes, conversation resets. This is fine for a game session.
|
||||
|
||||
### ❌ Detailed Event Analytics
|
||||
**Why OK:** Can add later if needed. Start simple.
|
||||
|
||||
### ❌ Global Variable Validation
|
||||
**Why OK:** Sync periodically, rollback if server detects cheating. Don't block gameplay.
|
||||
|
||||
### ❌ Fine-Grained Permissions
|
||||
**Why OK:** Simple rules work: encountered NPC = trusted. Scenario defines what NPCs can do.
|
||||
|
||||
---
|
||||
|
||||
## Security Model (Simplified)
|
||||
|
||||
### What's Secure ✅
|
||||
- Scenario solutions never sent to client
|
||||
- Unlock validation server-side
|
||||
- Room/object access controlled
|
||||
- NPC scripts lazy-loaded
|
||||
|
||||
### What's Client-Trust ⚠️
|
||||
- Player position (low risk)
|
||||
- Global variables (sync server, detect cheating)
|
||||
- Minigame success (only door unlock matters)
|
||||
|
||||
### What We Detect
|
||||
- Player accessing unearned rooms → 403
|
||||
- Invalid unlock attempts → 422
|
||||
- Impossible inventory items → reject
|
||||
|
||||
**Good enough for educational game!**
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
**Original approach:** Complex, over-engineered, 22 weeks
|
||||
**Simplified approach:** Pragmatic, maintainable, 12-14 weeks
|
||||
|
||||
**Key insight:** We don't need to track everything. Just track:
|
||||
1. What's unlocked (rooms/objects)
|
||||
2. What player has (inventory)
|
||||
3. Who player met (NPCs)
|
||||
4. Where player is (room/position)
|
||||
|
||||
Everything else can stay client-side!
|
||||
|
||||
**Ready to implement this simpler approach.**
|
||||
Reference in New Issue
Block a user