- 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>
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):
- Director API (1)
- User Service (3)
- Product/Catalog (3)
- DRM (3)
- Config (4)
- Progression (7)
- Rewards/Time Trials (8)
- Tracking (2)
- Assets (4)
- Settings (3)
- Modding (7)
- Leaderboards (6)
- Events (4)
- Notifications (5)
- Asset Management (4)
- Authentication (8)
⏳ Missing for 100% Coverage:
- Friends/Social Service (0/11 endpoints) - includes Clubs/Teams
- 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 syncINimbleOriginFriendsService\- User searchINimbleOriginFriendsService\- Friend invites
Friend System Components:
NimbleFriendsList- Friend list data structureNimbleFriendsRefreshScope- Refresh strategy (full/partial)NimbleFriendsRefreshResult- Sync result statusNimbleUser- 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:
- Google Play for matchmaking/lobby
- 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),targetSynergyIdortargetUsername - 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,sessionIdorjoinCode - 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,synergyIdorleaderboardRank - 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:
- Polling: Clients poll session status every 100-200ms during race
- Long-polling: Keep connection open, server responds when state changes
- 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:
- Get player's rating
- Find players within ±200 rating
- Match by closest rating
- 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
- START: Friends system database schema
- Create FriendsController.cs
- Test friend add/remove with basic UI
- Move to multiplayer once friends work
- 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!