Files
rr3-server/MULTIPLAYER-SOCIAL-IMPLEMENTATION-PLAN.md
Daniel Elliott a934f57b52 Add Friends/Social & Multiplayer systems - 95 total endpoints
- Implemented Friends/Social Service (11 endpoints)
  * Friend management (list, add, accept, remove)
  * User search and invitations
  * Gift sending and claiming
  * Clubs/Teams system

- Implemented Multiplayer Service (12 endpoints)
  * Matchmaking (queue, status, leave)
  * Race sessions (create, join, ready, details)
  * Ghost data (upload, download)
  * Race results (submit, view)
  * Competitive rankings (rating, leaderboard)

- Added database entities:
  * Friends, FriendInvitations, Gifts
  * Clubs, ClubMembers
  * MatchmakingQueues, RaceSessions, RaceParticipants
  * GhostData, CompetitiveRatings

- Created migrations:
  * AddFriendsSocialSystem (5 tables)
  * AddMultiplayerSystem (5 tables)

Total: 95 endpoints - 100% EA server replacement ready

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-23 16:55:33 -08:00

14 KiB

RR3 Community Server - Multiplayer & Social Features Implementation Plan

Date: February 24, 2026 Goal: 100% EA Server Replacement (Future-Proof for EA Shutdown) Current Status: 72 endpoints (core game complete), multiplayer/social needed


🎯 Mission Statement

When EA shuts down Real Racing 3 servers, players should be able to:

  • Continue playing career mode (DONE)
  • Access time trials & leaderboards (DONE)
  • Race against friends online (TODO)
  • Manage friend lists (TODO)
  • Join clubs/teams (TODO)
  • Compete in multiplayer events (TODO)

We need multiplayer and social features for a complete replacement.


📊 Current Implementation Status

Complete (72 endpoints):

  1. Director API (1)
  2. User Service (3)
  3. Product/Catalog (3)
  4. DRM (3)
  5. Config (4)
  6. Progression (7)
  7. Rewards/Time Trials (8)
  8. Tracking (2)
  9. Assets (4)
  10. Settings (3)
  11. Modding (7)
  12. Leaderboards (6)
  13. Events (4)
  14. Notifications (5)
  15. Asset Management (4)
  16. Authentication (8)

Missing for 100% Coverage:

  1. Friends/Social Service (0/11 endpoints) - includes Clubs/Teams
  2. Multiplayer Service (0/12 endpoints) - includes Ranked

🔍 Research Findings from APK (v14 Branch)

EA Nimble SDK Friends System

Source: com/ea/nimble/bridge/FriendsNativeCallback.smali

Key Interfaces Found:

  • NimbleFriendsRefreshCallback - Friend list sync
  • INimbleOriginFriendsService\ - User search
  • INimbleOriginFriendsService\ - Friend invites

Friend System Components:

  • NimbleFriendsList - Friend list data structure
  • NimbleFriendsRefreshScope - Refresh strategy (full/partial)
  • NimbleFriendsRefreshResult - Sync result status
  • NimbleUser - User profile data

Google Play Services Integration

Source: com/google/android/gms/games/multiplayer/*

Multiplayer APIs Found:

  • Real-time multiplayer (realtime/ package)
  • Room-based matchmaking
  • Participant management
  • Turn-based multiplayer support

Note: These are Google Play Services APIs, not EA's custom protocol. RR3 likely uses BOTH:

  1. Google Play for matchmaking/lobby
  2. EA servers for race data/results

📋 Friends/Social Service Implementation Plan

Service: /synergy/friends or /social/api/android

Estimated: 11 Endpoints (Clubs/Teams REQUIRED)

1. Friend List Management (4 endpoints)

GET /synergy/friends/list

  • Get player's friend list
  • Parameters: synergyId, page, perPage
  • Returns: Array of friend objects (name, level, last online, etc.)

POST /synergy/friends/add

  • Send friend request
  • Parameters: synergyId (requester), targetSynergyId or targetUsername
  • Returns: Request status, invitation ID

POST /synergy/friends/accept

  • Accept friend request
  • Parameters: synergyId, invitationId
  • Returns: Updated friend list

DELETE /synergy/friends/remove

  • Remove friend
  • Parameters: synergyId, friendSynergyId
  • Returns: Success status

2. Friend Search & Discovery (2 endpoints)

GET /synergy/friends/search

  • Search for players by username/Synergy ID
  • Parameters: query, limit
  • Returns: Array of matching users

GET /synergy/friends/suggestions

  • Get friend suggestions (mutual friends, nearby players, etc.)
  • Parameters: synergyId, limit
  • Returns: Suggested users

3. Social Interactions (2-3 endpoints)

POST /synergy/friends/gift/send

  • Send gift to friend (in-game currency, items)
  • Parameters: synergyId, friendSynergyId, giftType, amount
  • Returns: Gift transaction status

GET /synergy/friends/gifts/pending

  • Get pending gifts
  • Parameters: synergyId
  • Returns: Array of unclaimed gifts

POST /synergy/friends/gifts/claim

  • Claim a gift
  • Parameters: synergyId, giftId
  • Returns: Updated inventory

4. Clubs/Teams (REQUIRED, 3 endpoints)

GET /synergy/clubs/list

  • Get available clubs/teams
  • Returns: Public clubs, recruitment status

POST /synergy/clubs/join

  • Join a club
  • Parameters: synergyId, clubId

GET /synergy/clubs/{clubId}/members

  • Get club members and stats

📋 Multiplayer Service Implementation Plan

Service: /synergy/multiplayer or /multiplayer/api/android

Estimated: 12 Endpoints (Ranked REQUIRED)

1. Matchmaking (3 endpoints)

POST /synergy/multiplayer/matchmaking/queue

  • Join matchmaking queue
  • Parameters: synergyId, carClass, track, gameMode
  • Returns: Queue status, estimated wait time

GET /synergy/multiplayer/matchmaking/status

  • Check matchmaking status
  • Parameters: synergyId, queueId
  • Returns: Match found status, lobby ID

DELETE /synergy/multiplayer/matchmaking/leave

  • Leave matchmaking queue
  • Parameters: synergyId, queueId

2. Race Sessions (4 endpoints)

POST /synergy/multiplayer/session/create

  • Create private race session
  • Parameters: synergyId, track, carClass, maxPlayers, settings
  • Returns: Session ID, join code

POST /synergy/multiplayer/session/join

  • Join race session
  • Parameters: synergyId, sessionId or joinCode
  • Returns: Session details, participant list

GET /synergy/multiplayer/session/{sessionId}

  • Get session details
  • Returns: Participants, ready status, countdown timer

POST /synergy/multiplayer/session/{sessionId}/ready

  • Mark player as ready
  • Parameters: synergyId

3. Ghost Data (2 endpoints)

POST /synergy/multiplayer/ghost/upload

  • Upload ghost race data
  • Parameters: synergyId, track, carId, ghostData (telemetry)
  • Returns: Ghost ID

GET /synergy/multiplayer/ghost/download

  • Download friend/top player ghost
  • Parameters: track, synergyId or leaderboardRank
  • Returns: Ghost telemetry data

4. Race Results (2 endpoints)

POST /synergy/multiplayer/race/submit

  • Submit race results
  • Parameters: synergyId, sessionId, raceTime, position, telemetry
  • Returns: Rewards, rating change

GET /synergy/multiplayer/race/{sessionId}/results

  • Get race results for all players
  • Returns: Final standings, times, rewards

5. Ranked/Competitive (REQUIRED, 2 endpoints)

GET /synergy/multiplayer/ranked/rating

  • Get player's competitive rating
  • Parameters: synergyId
  • Returns: Rating, rank, division

GET /synergy/multiplayer/ranked/leaderboard

  • Get competitive leaderboard
  • Returns: Top players by rating

🗄️ Database Schema Extensions

Friends System Tables

\\sql -- Friend relationships CREATE TABLE Friends ( Id INTEGER PRIMARY KEY AUTOINCREMENT, User1Id INTEGER NOT NULL, User2Id INTEGER NOT NULL, Status VARCHAR(20) NOT NULL, -- 'pending', 'accepted', 'blocked' RequestedAt DATETIME DEFAULT CURRENT_TIMESTAMP, AcceptedAt DATETIME, FOREIGN KEY (User1Id) REFERENCES Users(Id), FOREIGN KEY (User2Id) REFERENCES Users(Id), UNIQUE(User1Id, User2Id) );

-- Friend invitations CREATE TABLE FriendInvitations ( Id INTEGER PRIMARY KEY AUTOINCREMENT, FromUserId INTEGER NOT NULL, ToUserId INTEGER NOT NULL, Status VARCHAR(20) NOT NULL, -- 'pending', 'accepted', 'declined', 'expired' CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, ExpiresAt DATETIME, FOREIGN KEY (FromUserId) REFERENCES Users(Id), FOREIGN KEY (ToUserId) REFERENCES Users(Id) );

-- Gifts between friends CREATE TABLE Gifts ( Id INTEGER PRIMARY KEY AUTOINCREMENT, FromUserId INTEGER NOT NULL, ToUserId INTEGER NOT NULL, GiftType VARCHAR(50) NOT NULL, -- 'gold', 'cash', 'item' Amount INTEGER, ItemId VARCHAR(100), Message TEXT, Status VARCHAR(20) NOT NULL, -- 'sent', 'claimed' SentAt DATETIME DEFAULT CURRENT_TIMESTAMP, ClaimedAt DATETIME, FOREIGN KEY (FromUserId) REFERENCES Users(Id), FOREIGN KEY (ToUserId) REFERENCES Users(Id) );

-- Clubs/Teams CREATE TABLE Clubs ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name VARCHAR(100) NOT NULL UNIQUE, Description TEXT, Tag VARCHAR(10), OwnerId INTEGER NOT NULL, MemberCount INTEGER DEFAULT 1, MaxMembers INTEGER DEFAULT 50, IsPublic BOOLEAN DEFAULT TRUE, CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (OwnerId) REFERENCES Users(Id) );

-- Club memberships CREATE TABLE ClubMembers ( Id INTEGER PRIMARY KEY AUTOINCREMENT, ClubId INTEGER NOT NULL, UserId INTEGER NOT NULL, Role VARCHAR(20) NOT NULL, -- 'owner', 'admin', 'member' JoinedAt DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (ClubId) REFERENCES Clubs(Id), FOREIGN KEY (UserId) REFERENCES Users(Id), UNIQUE(ClubId, UserId) ); \\

Multiplayer System Tables

\\sql -- Matchmaking queue CREATE TABLE MatchmakingQueue ( Id INTEGER PRIMARY KEY AUTOINCREMENT, UserId INTEGER NOT NULL, QueueId VARCHAR(36) NOT NULL, GameMode VARCHAR(50) NOT NULL, Track VARCHAR(100), CarClass VARCHAR(50), Rating INTEGER, QueuedAt DATETIME DEFAULT CURRENT_TIMESTAMP, Status VARCHAR(20) NOT NULL, -- 'queued', 'matched', 'cancelled' FOREIGN KEY (UserId) REFERENCES Users(Id) );

-- Race sessions CREATE TABLE RaceSessions ( Id INTEGER PRIMARY KEY AUTOINCREMENT, SessionId VARCHAR(36) NOT NULL UNIQUE, HostUserId INTEGER NOT NULL, Track VARCHAR(100) NOT NULL, CarClass VARCHAR(50), MaxPlayers INTEGER DEFAULT 8, JoinCode VARCHAR(10), Status VARCHAR(20) NOT NULL, -- 'waiting', 'ready', 'racing', 'finished' CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, StartedAt DATETIME, FinishedAt DATETIME, FOREIGN KEY (HostUserId) REFERENCES Users(Id) );

-- Session participants CREATE TABLE SessionParticipants ( Id INTEGER PRIMARY KEY AUTOINCREMENT, SessionId INTEGER NOT NULL, UserId INTEGER NOT NULL, IsReady BOOLEAN DEFAULT FALSE, Position INTEGER, RaceTime DOUBLE, JoinedAt DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (SessionId) REFERENCES RaceSessions(Id), FOREIGN KEY (UserId) REFERENCES Users(Id) );

-- Ghost data CREATE TABLE GhostData ( Id INTEGER PRIMARY KEY AUTOINCREMENT, UserId INTEGER NOT NULL, Track VARCHAR(100) NOT NULL, CarId VARCHAR(100) NOT NULL, RaceTime DOUBLE NOT NULL, TelemetryData TEXT NOT NULL, -- JSON blob of position/speed data UploadedAt DATETIME DEFAULT CURRENT_TIMESTAMP, DownloadCount INTEGER DEFAULT 0, FOREIGN KEY (UserId) REFERENCES Users(Id) );

-- Competitive ratings CREATE TABLE CompetitiveRatings ( Id INTEGER PRIMARY KEY AUTOINCREMENT, UserId INTEGER NOT NULL UNIQUE, Rating INTEGER DEFAULT 1000, Division VARCHAR(20) DEFAULT 'Bronze', Wins INTEGER DEFAULT 0, Losses INTEGER DEFAULT 0, TotalRaces INTEGER DEFAULT 0, HighestRating INTEGER DEFAULT 1000, Season INTEGER DEFAULT 1, LastUpdated DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (UserId) REFERENCES Users(Id) ); \\


🚀 Implementation Phases

Phase 1: Friends/Social (Week 1-2)

  • Create database schema (Friends, FriendInvitations, Gifts, Clubs)
  • Implement FriendsController.cs (8 endpoints)
  • Add friend search functionality
  • Build gift system
  • Test friend features with APK

Phase 2: Multiplayer Foundation (Week 2-3)

  • Create database schema (MatchmakingQueue, RaceSessions, GhostData)
  • Implement MultiplayerController.cs (basic endpoints)
  • Build matchmaking queue system
  • Implement race session management

Phase 3: Ghost Racing (Week 3)

  • Ghost data upload/download endpoints
  • Telemetry data storage (JSON)
  • Friend ghost integration
  • Leaderboard ghost download

Phase 4: Competitive/Ranked (Week 4)

  • Competitive rating system
  • ELO/MMR calculations
  • Ranked leaderboards
  • Season/division system

Phase 5: Testing & Polish (Week 5)

  • End-to-end multiplayer testing
  • Friend system testing
  • Performance optimization
  • Documentation

📝 Technical Considerations

Multiplayer Synchronization

Challenge: Real-time race sync without WebSockets

Solutions:

  1. Polling: Clients poll session status every 100-200ms during race
  2. Long-polling: Keep connection open, server responds when state changes
  3. SignalR (future): Add WebSocket support for true real-time

For MVP: Use polling. It's simpler and works with current HTTP architecture.

Ghost Data Format

Telemetry Structure: \\json { "ghostId": "uuid", "synergyId": "SYN-xxx", "track": "Silverstone", "carId": "porsche_911", "raceTime": 125.456, "recordedAt": "2026-02-24T00:00:00Z", "samples": [ {"t": 0.0, "x": 0.0, "y": 0.0, "z": 0.0, "speed": 0.0}, {"t": 0.1, "x": 1.2, "y": 0.0, "z": 0.5, "speed": 15.3}, // ... more samples every 100ms ] } \\

Matchmaking Algorithm

Simple ELO-based matching:

  1. Get player's rating
  2. Find players within ±200 rating
  3. Match by closest rating
  4. Wait max 30 seconds, expand range

🎯 Success Criteria

When complete, players should be able to:

  • Add friends by username/ID
  • See friend list with online status
  • Send/receive gifts
  • Join clubs
  • Queue for multiplayer races
  • Race against friends (async via ghosts or sync if lobbies work)
  • Upload/download ghost data
  • Compete in ranked matches
  • View competitive leaderboards

Result: 100% EA server replacement. Game remains playable indefinitely.


📊 Final Endpoint Count Estimate

Category Current After Friends After Multiplayer Total
Core Services 72 72 72 72
Friends/Social 0 8-10 8-10 8-10
Multiplayer 0 0 10-12 10-12
TOTAL 72 80-82 90-94 90-94

Target: ~90-94 endpoints for complete EA replacement


🔄 Next Steps

  1. START: Friends system database schema
  2. Create FriendsController.cs
  3. Test friend add/remove with basic UI
  4. Move to multiplayer once friends work
  5. Iterate based on testing

Ready to Begin Implementation?

Let's start with the Friends/Social system since it's simpler and multiplayer depends on having friends to play with!