Initial commit: RR3 APK and documentation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
393
WHEN_ASSETS_ARRIVE.md
Normal file
393
WHEN_ASSETS_ARRIVE.md
Normal file
@@ -0,0 +1,393 @@
|
||||
# Real Racing 3 - Asset Import Quick Start Guide
|
||||
**FOR WHEN DISCORD SENDS YOU THE FILES**
|
||||
|
||||
---
|
||||
|
||||
## 📥 Step 1: Receive the Assets
|
||||
|
||||
Discord will likely send you:
|
||||
- A .zip/.7z/.tar.gz archive (2-5 GB)
|
||||
- Or a Google Drive/Mega/Dropbox link
|
||||
- Or multiple .pak/.pvr/.dat files
|
||||
|
||||
---
|
||||
|
||||
## 📦 Step 2: Extract & Organize
|
||||
|
||||
### If it's an archive:
|
||||
```powershell
|
||||
# Extract to temporary location
|
||||
cd E:\rr3\
|
||||
7z x assets-from-discord.zip -o"assets-temp"
|
||||
```
|
||||
|
||||
### Check what you got:
|
||||
```powershell
|
||||
cd E:\rr3\assets-temp
|
||||
Get-ChildItem -Recurse | Group-Object Extension | Sort-Object Count -Descending
|
||||
```
|
||||
|
||||
**You should see:**
|
||||
- `.pak` files (main game assets)
|
||||
- `.pvr` files (textures - PowerVR format)
|
||||
- `.dat` files (game data)
|
||||
- `.atlas` files (sprite sheets)
|
||||
- `.z` files (compressed data)
|
||||
- `.fsh`/`.vsh` files (shaders)
|
||||
|
||||
---
|
||||
|
||||
## ✅ Step 3: Verify with Manifests (CRITICAL!)
|
||||
|
||||
Run the verification script:
|
||||
|
||||
```powershell
|
||||
cd E:\rr3\
|
||||
|
||||
# Create verification script
|
||||
@'
|
||||
$manifestPath = "E:\rr3\RR3CommunityServer\RR3CommunityServer\Assets\manifests\"
|
||||
$assetsPath = "E:\rr3\assets-temp\"
|
||||
|
||||
Write-Host "Verifying assets against manifests..." -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$verified = 0
|
||||
$failed = 0
|
||||
$missing = 0
|
||||
|
||||
# Read all manifests
|
||||
Get-ChildItem $manifestPath -Filter "*.txt" | ForEach-Object {
|
||||
$manifest = Get-Content $_.FullName
|
||||
|
||||
foreach ($line in $manifest) {
|
||||
if ($line -match '^/') {
|
||||
$parts = $line -split "`t"
|
||||
$path = $parts[0]
|
||||
$expectedMd5 = $parts[1]
|
||||
$fileName = [System.IO.Path]::GetFileName($path)
|
||||
|
||||
# Find file
|
||||
$file = Get-ChildItem $assetsPath -Recurse -Filter $fileName | Select-Object -First 1
|
||||
|
||||
if ($file) {
|
||||
# Calculate MD5
|
||||
$md5 = Get-FileHash $file.FullName -Algorithm MD5
|
||||
$actualMd5 = $md5.Hash.ToLower()
|
||||
|
||||
if ($actualMd5 -eq $expectedMd5) {
|
||||
$verified++
|
||||
Write-Host "✅ $fileName" -ForegroundColor Green
|
||||
} else {
|
||||
$failed++
|
||||
Write-Host "❌ $fileName - MD5 mismatch!" -ForegroundColor Red
|
||||
Write-Host " Expected: $expectedMd5" -ForegroundColor Gray
|
||||
Write-Host " Got: $actualMd5" -ForegroundColor Gray
|
||||
}
|
||||
} else {
|
||||
$missing++
|
||||
Write-Host "⚠️ $fileName - NOT FOUND" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "═══════════════════════════════════════════" -ForegroundColor Cyan
|
||||
Write-Host "VERIFICATION COMPLETE" -ForegroundColor Cyan
|
||||
Write-Host "═══════════════════════════════════════════" -ForegroundColor Cyan
|
||||
Write-Host "✅ Verified: $verified" -ForegroundColor Green
|
||||
Write-Host "❌ Failed: $failed" -ForegroundColor Red
|
||||
Write-Host "⚠️ Missing: $missing" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
if ($failed -eq 0 -and $missing -lt 100) {
|
||||
Write-Host "🎉 Assets are GOOD! Ready to deploy!" -ForegroundColor Green -BackgroundColor DarkGreen
|
||||
} else {
|
||||
Write-Host "⚠️ Some issues found - check with Discord" -ForegroundColor Yellow
|
||||
}
|
||||
'@ | Out-File verify-assets.ps1
|
||||
|
||||
# Run it
|
||||
.\verify-assets.ps1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 Step 4: Copy to Server
|
||||
|
||||
Once verified, copy to the server:
|
||||
|
||||
```powershell
|
||||
# Copy all verified assets to server
|
||||
$destination = "E:\rr3\RR3CommunityServer\RR3CommunityServer\Assets\downloaded\"
|
||||
|
||||
# Create directory structure
|
||||
New-Item -ItemType Directory -Force -Path $destination
|
||||
|
||||
# Copy files (preserving structure if possible)
|
||||
Copy-Item -Path "E:\rr3\assets-temp\*" -Destination $destination -Recurse -Force
|
||||
|
||||
Write-Host "✅ Assets copied to server!" -ForegroundColor Green
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Step 5: Import to Database
|
||||
|
||||
Create asset records in database:
|
||||
|
||||
```powershell
|
||||
cd E:\rr3\RR3CommunityServer
|
||||
|
||||
# Create import script
|
||||
@'
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RR3CommunityServer.Data;
|
||||
|
||||
var dbPath = "rr3community.db";
|
||||
var assetsPath = "Assets/downloaded";
|
||||
var manifestsPath = "Assets/manifests";
|
||||
|
||||
Console.WriteLine("Importing assets to database...");
|
||||
|
||||
using var db = new RR3DbContext(
|
||||
new DbContextOptionsBuilder<RR3DbContext>()
|
||||
.UseSqlite($"Data Source={dbPath}")
|
||||
.Options
|
||||
);
|
||||
|
||||
int imported = 0;
|
||||
|
||||
// Read manifests
|
||||
foreach (var manifestFile in Directory.GetFiles(manifestsPath, "*.txt"))
|
||||
{
|
||||
var lines = File.ReadAllLines(manifestFile);
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith("/"))
|
||||
{
|
||||
var parts = line.Split('\t');
|
||||
var path = parts[0];
|
||||
var md5 = parts[1];
|
||||
var compressedSize = long.Parse(parts[2]);
|
||||
var uncompressedSize = long.Parse(parts[3]);
|
||||
|
||||
var fileName = Path.GetFileName(path);
|
||||
|
||||
// Check if asset exists
|
||||
if (!db.GameAssets.Any(a => a.EaCdnPath == path))
|
||||
{
|
||||
// Find local file
|
||||
var localFiles = Directory.GetFiles(assetsPath, fileName, SearchOption.AllDirectories);
|
||||
var localPath = localFiles.FirstOrDefault();
|
||||
|
||||
var asset = new GameAsset
|
||||
{
|
||||
AssetType = DetermineAssetType(path),
|
||||
FileName = fileName,
|
||||
EaCdnPath = path,
|
||||
LocalPath = localPath,
|
||||
FileSize = uncompressedSize,
|
||||
CompressedSize = compressedSize,
|
||||
Md5Hash = md5,
|
||||
ContentType = DetermineContentType(path),
|
||||
Category = DetermineCategory(path),
|
||||
DownloadedAt = localPath != null ? DateTime.UtcNow : null,
|
||||
AccessCount = 0
|
||||
};
|
||||
|
||||
db.GameAssets.Add(asset);
|
||||
imported++;
|
||||
|
||||
if (imported % 100 == 0)
|
||||
{
|
||||
Console.WriteLine($"Imported {imported} assets...");
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db.SaveChanges();
|
||||
Console.WriteLine($"✅ Import complete! {imported} assets added to database.");
|
||||
|
||||
static string DetermineAssetType(string path)
|
||||
{
|
||||
if (path.Contains("car")) return "car";
|
||||
if (path.Contains("track")) return "track";
|
||||
if (path.Contains("audio")) return "audio";
|
||||
if (path.Contains("gui")) return "ui";
|
||||
return "other";
|
||||
}
|
||||
|
||||
static string DetermineContentType(string path)
|
||||
{
|
||||
var ext = Path.GetExtension(path).ToLower();
|
||||
return ext switch
|
||||
{
|
||||
".pak" => "application/octet-stream",
|
||||
".pvr" => "image/pvr",
|
||||
".dat" => "application/octet-stream",
|
||||
".atlas" => "application/octet-stream",
|
||||
".z" => "application/x-compress",
|
||||
_ => "application/octet-stream"
|
||||
};
|
||||
}
|
||||
|
||||
static string DetermineCategory(string path)
|
||||
{
|
||||
if (path.Contains("/car")) return "cars";
|
||||
if (path.Contains("/track")) return "tracks";
|
||||
if (path.Contains("/audio")) return "audio";
|
||||
if (path.Contains("/gui")) return "ui";
|
||||
return "general";
|
||||
}
|
||||
'@ | Out-File -Encoding UTF8 import-assets.csx
|
||||
|
||||
# Run with dotnet-script (if installed) or manually add to server
|
||||
Write-Host "⚠️ Import script created: import-assets.csx" -ForegroundColor Yellow
|
||||
Write-Host "Run this inside your server project to populate the database" -ForegroundColor Gray
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Step 6: Test Server
|
||||
|
||||
```powershell
|
||||
cd E:\rr3\RR3CommunityServer\RR3CommunityServer
|
||||
|
||||
# Start server
|
||||
dotnet run
|
||||
|
||||
# In another terminal, test:
|
||||
curl https://localhost:5001/content/api/status
|
||||
|
||||
# Should return JSON with:
|
||||
# "availableAssets": (big number)
|
||||
# "status": "ready"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 Step 7: Modify APK
|
||||
|
||||
### Option A: APK Tool (Full Recompile)
|
||||
|
||||
```powershell
|
||||
# Decompile
|
||||
apktool d realracing3.apk -o rr3-decompiled
|
||||
|
||||
# Edit smali or resources to change Director URL
|
||||
# From: https://syn-dir.sn.eamobile.com
|
||||
# To: https://YOUR_SERVER_IP:5001
|
||||
|
||||
# Recompile
|
||||
apktool b rr3-decompiled -o rr3-modded.apk
|
||||
|
||||
# Sign
|
||||
jarsigner -keystore my.keystore rr3-modded.apk my-key
|
||||
|
||||
# Install
|
||||
adb install rr3-modded.apk
|
||||
```
|
||||
|
||||
### Option B: Hosts File (Easier but requires root)
|
||||
|
||||
**On Android device:**
|
||||
```bash
|
||||
# Root required
|
||||
su
|
||||
mount -o remount,rw /system
|
||||
echo "YOUR_SERVER_IP syn-dir.sn.eamobile.com" >> /etc/hosts
|
||||
echo "YOUR_SERVER_IP cloudcell.ea.com" >> /etc/hosts
|
||||
```
|
||||
|
||||
**On Windows (for emulator):**
|
||||
```powershell
|
||||
# Edit C:\Windows\System32\drivers\etc\hosts
|
||||
# Add these lines:
|
||||
192.168.1.100 syn-dir.sn.eamobile.com
|
||||
192.168.1.100 cloudcell.ea.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Step 8: LAUNCH THE GAME!
|
||||
|
||||
1. Install modded APK or set up hosts file
|
||||
2. Launch Real Racing 3
|
||||
3. Game contacts your server (not EA!)
|
||||
4. Downloads assets from your server
|
||||
5. **PROFIT!** 🏎️💨
|
||||
|
||||
---
|
||||
|
||||
## 📊 Expected Results
|
||||
|
||||
### First Launch:
|
||||
```
|
||||
Game → Director Service (your server) ✅
|
||||
Game → Authentication (your server) ✅
|
||||
Game → Asset manifest (your server) ✅
|
||||
Game → Downloads .pak files (your server) ✅
|
||||
Game → PLAYABLE! 🎮
|
||||
```
|
||||
|
||||
### What You'll See in Server Logs:
|
||||
```
|
||||
[INFO] Director request for package: com.ea.games.r3_row
|
||||
[INFO] GetDeviceID request: hardware=abc123
|
||||
[INFO] Asset download request: /gui_assets/sprites.atlas
|
||||
[INFO] Serving asset: /gui_assets/sprites.atlas (3015 bytes)
|
||||
[INFO] Asset download request: /cars/porsche_911_gt3.pak
|
||||
[INFO] Serving asset: /cars/porsche_911_gt3.pak (5.2 MB)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔥 Quick Checklist
|
||||
|
||||
When assets arrive:
|
||||
|
||||
- [ ] Download/extract files
|
||||
- [ ] Run verification script (check MD5s)
|
||||
- [ ] Copy to `Assets/downloaded/`
|
||||
- [ ] Import to database (optional but recommended)
|
||||
- [ ] Test server: `curl https://localhost:5001/content/api/status`
|
||||
- [ ] Modify APK or hosts file
|
||||
- [ ] Install & launch game
|
||||
- [ ] **CELEBRATE!** 🎉
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Troubleshooting
|
||||
|
||||
### Assets downloaded but game shows black screen?
|
||||
- Check server logs for 404 errors
|
||||
- Verify file paths match manifest paths
|
||||
- Ensure file permissions are correct
|
||||
|
||||
### Game can't connect to server?
|
||||
- Check firewall allows port 5001
|
||||
- Verify APK modification worked
|
||||
- Try hosts file method instead
|
||||
- Check server is running: `netstat -an | findstr 5001`
|
||||
|
||||
### MD5 verification failed?
|
||||
- Files might be corrupted during transfer
|
||||
- Ask Discord for re-upload
|
||||
- Check if files were unzipped correctly
|
||||
|
||||
---
|
||||
|
||||
## 📞 Next Step
|
||||
|
||||
**Just wait for Discord response now!**
|
||||
|
||||
When they send files, follow this guide step-by-step and you'll have RR3 running in no time! 🏁
|
||||
Reference in New Issue
Block a user