- 03 Jul, 2026 12 commits
-
-
Mahmoud Aglan authored
Phase 4: getPipCount now accepts variant param (fixes wrong pip count for thirtyone variant), backgammon quit button shows confirmation dialog in live mode. Phase 3: syncPassToServer no longer pre-increments moveCount before network success, winners array guards against empty state.players. Phase 2: ludo bot "thinking" indicator uses dedicated .pp-status span instead of clobbering the player name. Phase 6: chat.php unread/recent queries batched into single DB calls instead of N+1 per friendship. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Phase 5: queue 60s timeout with retry prompt, match history accepts game_key, spectate routes to correct game scene, shop shows "owned" indicator, profile shows dash instead of 1200 for unrated players. Phase 6: remove duplicate disconnectWatch calls (use match-session only), fix auth.php double token verification with requireAuthUser(), cascade delete related data on account deletion. Phase 1: fix opponentRating using actual rating in live mode instead of botElos lookup. Fix achievements recursive mount — update in-place instead of re-calling mountAchievements. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- friends.js: add unmountFriends() to clear refresh/invite timers - play/mod.js: register unmountLobby for game-lobby scene - social/mod.js: register unmountFriends for friends scene - net.js: add 10s request timeout via AbortController - net.js: add mutex for token refresh (prevents duplicate refresh calls) - notifications.js: don't auto-mark-read on mount; add explicit button - chat.js: pass lastTime as 'after' param for incremental fetch Fixes WTF #38, #63, #66, #69, #91, #175 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- modal.js: dismiss existing modal before showing new one (prevents stacking) - scene.js: call unmount on current scene during replace() and switchWorld() - chat.js: remove || true from scroll condition (only auto-scroll on new msgs) - shop/browse.js: check gems affordability alongside coins - ludo/game.js: fix undefined isLoser — use isLastPlace - backgammon/rules.js: fix VARIANTS.standard crash — use VARIANTS.sheshbesh - backgammon/game.js: sanitize opponentName and avatar URL (XSS prevention) Fixes WTF #22, #25, #26, #59, #68, #71, #113 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Phase 1 fixes: - lobby.js: guest waits 2.5s before entering game (gives host time to detect) - challenge.js: validate match_id exists before navigating to lobby - match-session.js: remove visibilitychange listener on destroy (memory leak fix) - match-session.js: only fire onConnectionRestored after actual disconnection - net.js: handle non-JSON server responses gracefully (nginx 502 pages etc) - result.js: pass actual timeControl to rematch instead of hardcoded rapid_10_0 - Remove dead chess/logic/live.js and ludo/logic/live.js (unused) Fixes WTF #15, #19, #23, #24, #35, #37, #54, #150 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Reject invalid time_control values before DB write - Reject invalid game_key values before DB write - Also added missing DB indexes and reward_config rows via migration Fixes WTF #schema-2-3, Phase 0.7-0.9 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Replace wildcard CORS (Access-Control-Allow-Origin: *) with domain whitelist across all 37 API files via shared includes/cors.php - friends.php: sanitize PostgREST filter inputs (strip special chars from search) - friends.php: validate UUID format for profile ID lookups - friends.php: verify user is invite target before accept/decline (domino, ludo, chess) - config/constants.php: read secrets from .env file or env vars (no more hardcoded keys) - Add .env to .gitignore Fixes WTF #5-6, #9-11 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- handleGameMove: verify caller is a player in the match before allowing moves - handleResign: verify participant before allowing resignation - handleDraw: verify participant + use merge_game_state RPC (preserves heartbeat data) - handleComplete: verify participant + validate winners are actual match players (prevents coin exploit) - handleFindActiveMatch: restrict to own user only (prevents info disclosure) - Validate result enum values in handleComplete Fixes WTF #1-4, #46 Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Prioritized plan to go from 240 WTFs to all 4 games working in multiplayer. Phase 0 locks down security, phases 1-4 bring each game online, phases 5-7 polish UX/stability/theming. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
SSHed into Supabase DB and compared all table schemas, RLS policies, RPCs, enums, indexes, and reward_config rows against what the code expects. Found 21 mismatches including: service key bypassing RLS (making RLS useless), missing indexes, missing reward rows, handleDraw destroying game_state, and complete_match trusting client-provided winners array. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Full codebase scan covering security, bugs, race conditions, UX dead ends, theming violations, dead code, and user journey problems. Includes root cause analysis for broken friend invites and priority fix list. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 25 Jun, 2026 3 commits
-
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Adds range slider sections for HUD, Tab Bar, Home Page, Quick Actions, Game Tiles, Game Menu Sheet, Menu Buttons, Menu Chips, and Bot Cards — covering all sizing, spacing, padding, margin, and font controls. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- All Arabic labels replaced with English descriptive labels - API save_theme now also writes local theme.json (prevents stale overrides) - Added Ludo Board Colors section (9 controls) - Added Backgammon Board Colors section (14 controls) - Page lang/dir switched from ar/rtl to en/ltr Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 23 Jun, 2026 5 commits
-
-
Mahmoud Aglan authored
Root cause: draw offers stored in game_state were lost when a concurrent move write did read→merge→write (non-atomic). Now uses PostgreSQL jsonb || operator via merge_game_state() RPC for atomic merges. Also adds: - mp_log table for server-side multiplayer event logging - Frontend sessionStorage logging (sessionStorage.mp_log) for debugging draw offers, moves, and poll events - Logging on match_created, move, resign, draw_accepted, game_state_merge Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Screenshots confirm: moves sync to opponent board, resign shows victory screen. Both directions verified via Puppeteer + API. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The `matches` table has no `last_activity` or `ended_at` columns. PostgREST rejects the entire PATCH when ANY column doesn't exist, causing every move update and resignation to silently fail. - Remove `last_activity` from handleGameMove (column doesn't exist) - Change `ended_at` to `completed_at` in handleResign, handleDraw, handleComplete (correct column name per DB schema) This was the root cause of zero sync in multiplayer chess. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Add dequeue handler to backgammon-match.php (was missing) - Add 90-second stale entry cleanup to ludo/domino/backgammon queues - Add atomic opponent claiming (conditional update) to prevent race conditions - Fix client queue.js to route dequeue to correct game endpoint - Register unmountQueue for proper cleanup when exiting search screen - Remove json_encode on jsonb fields in backgammon (prevent double-encoding) Fixes: self-matching, ghost queue entries, and race condition where two players simultaneously claim the same opponent. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The root cause: PHP's json_encode() was used on jsonb fields before passing to SupabaseClient->insert/update, which json_encodes the entire payload. This double-encoded game_state into a JSON string scalar. When the match_heartbeat RPC did `jsonb_string || jsonb_object`, PostgreSQL created an array instead of merging, corrupting game_state. The polling logic then couldn't find move_count or last_move in the array, so moves never synced between players. Fix: pass PHP arrays directly for all jsonb columns (game_state, moves, positions, scores, winners, hands, boneyard). The Supabase client handles encoding once at the HTTP layer. Also: when reading game_state back from the DB, handle the case where PostgREST returns it as a decoded array/object (not a string) since jsonb columns are deserialized automatically. Affected: chess, ludo, domino — all multiplayer match creation and move/state updates. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 22 Jun, 2026 1 commit
-
-
Mahmoud Aglan authored
Use Math.min() scaling (same approach as chess pieces) instead of forcing sprites into a square bounding box which stretched non-square pawn images uploaded via admin branding. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 21 Jun, 2026 4 commits
-
-
Mahmoud Aglan authored
The notifications API selected a column 'metadata' that doesn't exist in the table (actual column is 'data'). This caused PostgREST to return an error, which the error handler caught and returned empty. Users never saw their notifications. Also added body_ar to the select and frontend display. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Ludo: - Add endingGame guard to prevent double endGame calls - Parse server winners from live polling (fixes empty leaderboard when opponent wins remotely) - Fix win/loss detection: last place = loss (was broken for 2-player) Chess: - Add 5s failsafe timer: result screen shows even if network hangs - Deduplicate navigation logic with navigated flag - Prevent double-navigation if both .then and failsafe fire Backgammon: - Add scene.exitGameMode() to both result navigation paths (was missing, could leave UI in game-mode state) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Without this, the render loop, polling, heartbeat, and turn timers would continue running after navigating away from the game scene. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Chess: - "التحليل التفصيلي" button in review now navigates to chess-analysis (interactive move-by-move board with eval bar) instead of scene.pop() Ludo: - Complete leaderboard showing all players ranked 1st-4th - Each player shown with their name, color dot, and medal/rank - Current player highlighted with gold border - Proper rewards display (coins + XP + rating change) - Pass playerNames and playerColors from game to result scene Backgammon: - Add rewards display (coins + XP) to result screen - Emit coins:earned and xp:earned events for HUD sync Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 20 Jun, 2026 8 commits
-
-
Mahmoud Aglan authored
showOpponentPopup existed but was never called. Now tapping an opponent's panel in live mode opens their profile with add-friend option. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- endGame and handleExit pass mode/numPlayers/seats/humanCount/difficulty to the result scene - Result "play again" restarts with same settings (not always 4p bot) - Live mode "play again" goes to queue (finds new match, not old one) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- afterMove: use boardSlot for firework/flash colors (not player index) - afterMove: in local-multi, ANY human capturing triggers celebration (not just player 0) - botLoop: capture detection checks all human players in local-multi (not just myPlayerIndex=0) - animateDice: shake dice-area for all human players in local-multi (previously only shook for player 0, panel for others) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Critical bug: handleRoll used myPlayerIndex (always 0) instead of game.currentPlayer, so in local-multi the dice always moved Red's pieces regardless of whose turn it was. Fixes: - handleRoll uses game.currentPlayer for dice animation, getValidMoves, and getBotMove (no longer hardcoded to player 0) - updatePanels checks game.currentPlayer.finished (not myPlayerIndex) - Turn status badge shows player name + color in local-multi mode - Live multiplayer: fetch and display opponent avatar (not just name) - Update PLAYER_NAMES array when opponent profile loads - All juice.burst/fireworkBurst use boardSlot for correct colors Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- mountGame reads playerCount from params (queue passes it from room) - Server accepts player_count in queue request, creates matching positions - Queue response includes player_count for both players - onMatchFound propagates playerCount to game scene - 2-player live matches now create only 2 positions (not 4 with bots) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Default seats for 2 players: [0, 2] (BL vs TR) instead of [0, 1] (adjacent) - Panel layout: opponent at top-right for 2-player (diagonally opposite) - Corner glow uses boardSlot instead of player index - Dim inactive home zones, home columns, center triangles, start squares - Matches the getSeatPositions() in room.js which already returned [0, 2] Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Replace opacity 0.3 dim with proper contextual states - Add turn-status badge showing "دورك!" / "دور [player]" / "Bot يفكر..." - Roll button shows contextual text: "ارمِ النرد" / "اختر قطعة" / "انتظر دورك" / "Bot يلعب..." - Dice box stays visible during opponent turns (greyed, not hidden) - Emote button always accessible (social action, not gated by turn) - Smooth CSS transitions on dice-area background, button color, dice opacity - Flash notification (inset glow + haptic) when turn comes to you - Timer bar fades more during opponent turn for clearer contrast Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Eliminates the conflict between matchLive.start() and the game's own startLudoPolling() which caused race conditions. Consolidates to a single poller with: proper turn_count diffing, remote dice display via showRemoteDice(), explicit game.rolled reset on turn transitions, stale dice display fix, diceAnimating stuck-flag safety valve, double-poll prevention in handleNonPlayerTurn, heartbeat timer cleanup, and an unmountGame export for proper teardown. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 19 Jun, 2026 7 commits
-
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The VARIANTS object has keys 'sheshbesh', 'mahbousa', 'thirtyone' but getPipCount referenced 'standard' which is undefined, causing 'Cannot read properties of undefined (reading normPos)' and preventing the entire board from rendering. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Player cards now use store player data (avatar_url, display_name, level) - Opponent shows bot icon or opponent data for multiplayer - Active turn highlight on player cards with green glow border - Cube value display in match info area - Professional dark gradient background with proper hierarchy - Controls bar with proper spacing and button styling - Doubling offer dialog with backdrop blur and better layout - Turn badge repositioned to top-center with pill shape - Emote panel centered with backdrop blur - All interactive elements have proper touch targets (40px+) - Safe area inset for bottom bar Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Remove DPR ctx.scale() that compounded every frame and broke all rendering - Use logical pixel dimensions directly (canvas.width = logical size) - Fix isSel/isValid closures that caused undefined reference errors in checker glow - Simplify game scene: roll button is now a normal element in .bgg-controls (not overlay) - Event handlers correctly scale click coords via rect ratio - Remove unused getCheckerScreenPos import from move-animator - All buttons (roll, double, emote, quit) bind via addEventListener properly Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- 60fps requestAnimationFrame game loop with dt-based particle physics - 3D checkers with radial gradients, specular highlights, drop shadows - Wood-grain board texture with gradient triangles and bevel frame - Physics-based dice with bounce damping, spin, and staggered animation - Arc-based move animations with easeOutBack overshoot - Particle burst on hit (red/orange sparks) and bear-off (green stars) - Confetti celebration on match win with canvas animation - Full multiplayer sync via match-session + server polling - Bot AI with animated moves (arc + SFX per piece) - Admin branding: 14 board colors + 7 game settings (durations, particles) - CSS tokens for all backgammon board colors (--bg-*) - Theme.js maps branding values to CSS vars + window.__EL3AB_THEME Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- sheshbesh (شيش بيش): standard backgammon with hitting - mahbousa (محبوسة): tapa-style, land on opponent to trap (no hitting) - thirtyone (٣١): gul-bara race variant, all pieces start stacked Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-