# RR3 Asset Extraction & Management System Complete toolkit for extracting, packing, and managing Real Racing 3 `.z` asset files (ZLIB compressed textures/data). ## ๐Ÿ“ Directory Structure ``` RR3CommunityServer/ โ”œโ”€โ”€ Tools/ โ”‚ โ”œโ”€โ”€ extract_z_asset.sh # Linux/Unix extraction script โ”‚ โ”œโ”€โ”€ batch_extract_z_assets.sh # Linux/Unix batch extraction โ”‚ โ”œโ”€โ”€ pack_z_asset.sh # Linux/Unix packing script โ”‚ โ””โ”€โ”€ extract_z_asset.ps1 # Windows PowerShell extraction โ”œโ”€โ”€ RR3CommunityServer/ โ”‚ โ”œโ”€โ”€ Services/ โ”‚ โ”‚ โ””โ”€โ”€ AssetExtractionService.cs # C# service for server-side extraction โ”‚ โ””โ”€โ”€ Controllers/ โ”‚ โ””โ”€โ”€ AssetManagementController.cs # API endpoints for asset management ``` --- ## ๐Ÿš€ Quick Start ### Linux/Unix Systems **Extract single .z file:** ```bash cd RR3CommunityServer/Tools chmod +x extract_z_asset.sh ./extract_z_asset.sh /path/to/sprites_0.etc.dds.z ``` **Batch extract entire directory:** ```bash chmod +x batch_extract_z_assets.sh ./batch_extract_z_assets.sh /path/to/assets/directory ``` **Pack file to .z format:** ```bash chmod +x pack_z_asset.sh ./pack_z_asset.sh sprites_0.etc.dds ``` ### Windows Systems **PowerShell extraction:** ```powershell cd RR3CommunityServer\Tools .\extract_z_asset.ps1 -InputFile "C:\path\to\sprites_0.etc.dds.z" ``` **With custom output directory:** ```powershell .\extract_z_asset.ps1 -InputFile "C:\assets\file.z" -OutputDir "C:\extracted" ``` --- ## ๐Ÿ”ง Server Integration ### 1. Register Service Add to `Program.cs`: ```csharp builder.Services.AddScoped(); ``` ### 2. API Endpoints #### Extract Single Asset ```http POST /api/AssetManagement/extract Content-Type: application/json { "fileName": "sprites_0.etc.dds.z", "outputPath": "extracted/sprites_0.etc.dds" // optional } ``` **Response:** ```json { "resultCode": 0, "message": "Success", "data": { "inputFile": "/assets/sprites_0.etc.dds.z", "outputFile": "/assets/extracted/sprites_0.etc.dds", "size": 1048576 } } ``` #### Pack Asset to .z Format ```http POST /api/AssetManagement/pack Content-Type: application/json { "fileName": "sprites_0.etc.dds", "outputPath": "packed/sprites_0.etc.dds.z" // optional } ``` #### Batch Extract Directory ```http POST /api/AssetManagement/batch-extract Content-Type: application/json { "inputDirectory": "raw_assets", "outputDirectory": "extracted_assets" // optional } ``` **Response:** ```json { "resultCode": 0, "message": "Success", "data": { "totalFiles": 150, "successful": 148, "failed": 2, "results": [ { "inputFile": "sprites_0.etc.dds.z", "outputFile": "sprites_0.etc.dds", "status": "success", "error": null } ] } } ``` #### List Available Assets ```http GET /api/AssetManagement/list?directory=textures ``` **Response:** ```json { "resultCode": 0, "message": "Success", "data": { "directory": "/assets/textures", "fileCount": 45, "files": [ { "fileName": "sprites_0.etc.dds.z", "relativePath": "textures/sprites_0.etc.dds.z", "size": 524288, "modified": "2026-02-18T10:30:00Z" } ] } } ``` --- ## ๐Ÿ”ฌ Technical Details ### .z File Format RR3 uses ZLIB-compressed files with `.z` extension: 1. **Magic Bytes**: `0x78` followed by `0x9C`, `0xDA`, or `0x01` 2. **Compression**: Standard ZLIB/Deflate algorithm (level 9) 3. **Format**: Can contain multiple ZLIB blocks concatenated 4. **Content**: Usually DDS textures (ETC2 for Android, BC3 for PC) ### Extraction Algorithm ``` 1. Read file into byte array 2. Scan for ZLIB magic bytes (0x78 0x9C/0xDA/0x01) 3. Attempt decompression from each position 4. Concatenate all successfully decompressed blocks 5. Write output file ``` ### Performance - **Single file extraction**: ~50-200ms per file (depending on size) - **Batch extraction**: Parallel processing available - **Compression ratio**: Typically 60-80% for textures - **Memory**: Loads entire file into memory (ensure sufficient RAM for large files) --- ## ๐Ÿ“ฆ Integration with Custom Content System ### Auto-Extract Uploaded Custom Content ```csharp public async Task UploadCustomTexture(IFormFile file) { // Save uploaded .z file var savedPath = await SaveUploadedFile(file); // Auto-extract if it's a .z file if (file.FileName.EndsWith(".z")) { var extractedPath = await _assetExtraction.ExtractZFileAsync(savedPath); // Process extracted DDS/texture await ProcessTexture(extractedPath); } return Ok(); } ``` ### Custom Car/Track Workflow ``` 1. User uploads custom car skin (PNG) 2. Server converts PNG โ†’ DDS (using ImageMagick/Compressonator) 3. Server packs DDS โ†’ .z using AssetExtractionService 4. Server stores .z file in database 5. APK downloads .z file when user selects custom car 6. APK extracts .z โ†’ DDS on device 7. Game renders custom texture ``` --- ## ๐Ÿงช Testing ### Test Extraction ```bash # Test single file ./extract_z_asset.sh test_assets/sprites_0.etc.dds.z # Verify output file test_assets/sprites_0.etc.dds # Should show: DDS image data # Test round-trip ./pack_z_asset.sh test_assets/sprites_0.etc.dds ./extract_z_asset.sh test_assets/sprites_0.etc.dds.z test_assets/sprites_0_roundtrip.etc.dds diff test_assets/sprites_0.etc.dds test_assets/sprites_0_roundtrip.etc.dds ``` ### Test API Endpoints ```bash # Start server cd RR3CommunityServer/RR3CommunityServer dotnet run # Test extraction endpoint curl -X POST http://localhost:5143/api/AssetManagement/extract \ -H "Content-Type: application/json" \ -d '{"fileName": "sprites_0.etc.dds.z"}' # Test batch extraction curl -X POST http://localhost:5143/api/AssetManagement/batch-extract \ -H "Content-Type: application/json" \ -d '{"inputDirectory": "raw_assets"}' # List assets curl http://localhost:5143/api/AssetManagement/list ``` --- ## ๐Ÿ”’ Security Considerations ### Path Traversal Protection The API endpoints use `Path.Combine` with a base path to prevent directory traversal attacks: ```csharp var filePath = Path.Combine(_assetBasePath, request.FileName); // request.FileName = "../../../etc/passwd" โ†’ blocked by Path.Combine ``` ### File Size Limits Consider adding file size limits in production: ```csharp [RequestSizeLimit(100_000_000)] // 100 MB max public async Task ExtractAsset([FromBody] ExtractRequest request) ``` ### Authentication Add authentication middleware for production: ```csharp [Authorize(Roles = "Admin,Moderator")] public class AssetManagementController : ControllerBase ``` --- ## ๐Ÿ› Troubleshooting ### "No valid ZLIB blocks found" **Cause**: File is not ZLIB compressed or is corrupted. **Fix**: Verify file with hex editor (should start with `78 9C` or `78 DA`). ### "Permission denied" **Linux/Unix**: ```bash chmod +x *.sh sudo chown $USER:$USER /path/to/assets ``` **Windows**: Run PowerShell as Administrator. ### "Python 3 not found" **Linux**: ```bash # Ubuntu/Debian sudo apt install python3 # RedHat/CentOS sudo yum install python3 ``` **Windows**: Install from [python.org](https://www.python.org/) --- ## ๐Ÿ“Š File Format Reference ### DDS (DirectDraw Surface) Standard texture format used by RR3: - **Android**: ETC2_RGBA compression - **PC**: BC3 (DXT5) compression - **Header**: 128 bytes (DDS magic + DDS_HEADER) - **Mipmaps**: Usually included for LOD ### Conversion Tools For converting between formats: - **PNG โ†’ DDS**: AMD Compressonator CLI, ImageMagick - **DDS โ†’ PNG**: Noesis, GIMP with DDS plugin - **DDS compression**: `-fd ETC2_RGBA` (Android), `-fd BC3` (PC) --- ## ๐ŸŽฏ Next Steps 1. **โœ… COMPLETED**: Cross-platform extraction scripts 2. **โœ… COMPLETED**: C# service for server-side extraction 3. **โœ… COMPLETED**: API endpoints for asset management 4. **TODO**: Image conversion pipeline (PNG โ†” DDS) 5. **TODO**: Asset validation (verify DDS headers, check corruption) 6. **TODO**: Asset CDN integration (serve extracted assets) 7. **TODO**: Custom content moderation system --- ## ๐Ÿ“ License Part of the RR3 Community Server project. For preservation and modding purposes only. --- ## ๐Ÿค Credits - **Original Tool**: [Tankonline/Real-Racing-3-Texture-Extraction-Tool](https://github.com/Tankonline/Real-Racing-3-Texture-Extraction-Tool) - **Cross-Platform Implementation**: RR3 Community Server Team - **ZLIB**: Standard Python `zlib` module / .NET `System.IO.Compression`