### CMake Project Setup Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/extras/CMakeLists.txt Sets the minimum required CMake version and defines the project name. This is a standard starting point for CMake projects. ```cmake cmake_minimum_required(VERSION 3.22.1) Project(Pluvia) ``` -------------------------------- ### GOG Library Management and Downloads Source: https://context7.com/utkarshdalal/gamenative/llms.txt Manages game libraries, checks installation status, and initiates game downloads. Requires game IDs and install paths. The download progress can be tracked. ```kotlin // Library management and downloads lifecycleScope.launch { // Refresh library from GOG servers val gamesCount = GOGService.refreshLibrary(context).getOrNull() // Get game info val gameId = "gog_12345" val game = GOGService.getGOGGameOf(gameId) // Check installation status val isInstalled = GOGService.isGameInstalled(gameId) val (isValid, errorMessage) = GOGService.verifyInstallation(gameId) // Download game val installPath = GOGConstants.getGameInstallPath(game.title) val downloadResult = GOGService.downloadGame( context = context, gameId = gameId, installPath = installPath, containerLanguage = "en-US" ) downloadResult.onSuccess { it?.let { // Track progress while (it.isActive()) { Log.d("GOG", "Progress: ${(it.getProgress() * 100).toInt()}%") delay(1000) } } } } ``` -------------------------------- ### Initialize Steam Service and QR Authentication Source: https://context7.com/utkarshdalal/gamenative/llms.txt Demonstrates starting the Steam service within an Activity and executing the QR code authentication flow. ```kotlin // Starting the Steam service with authentication class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Start Steam service SteamService.start(this) // Listen for connection events PluviaApp.events.on { Log.d("Steam", "Steam service is ready") } } // QR Code authentication flow private fun startQrAuth() { lifecycleScope.launch { // Get QR code challenge URL val qrSession = SteamService.startQrAuth { challengeUrl -> // Display this URL as a QR code for user to scan with Steam mobile app displayQrCode(challengeUrl) } // Poll for authentication result val result = qrSession.pollAuthSessionStatus() if (result.accountName.isNotEmpty()) { // Authentication successful Log.d("Steam", "Logged in as: ${result.accountName}") } } } } ``` -------------------------------- ### Build GOG Library Item Source: https://context7.com/utkarshdalal/gamenative/llms.txt Generates a LibraryItem from GOGGame data. Utilizes GOGGame object for game information and installation status. ```kotlin fun buildGOGLibraryItem(gogGame: GOGGame): LibraryItem { return LibraryItem( appId = "GOG_${gogGame.id}", name = gogGame.title, iconHash = gogGame.iconUrl, capsuleImageUrl = gogGame.backgroundImageUrl, headerImageUrl = gogGame.galaxyBackgroundImageUrl, gameSource = GameSource.GOG, isInstalled = gogGame.isInstalled ) } ``` -------------------------------- ### Build Epic Library Item Source: https://context7.com/utkarshdalal/gamenative/llms.txt Constructs a LibraryItem from EpicGame data. Uses EpicGame object for details and installation status. ```kotlin fun buildEpicLibraryItem(epicGame: EpicGame): LibraryItem { return LibraryItem( appId = "EPIC_${epicGame.id}", name = epicGame.title, iconHash = epicGame.iconUrl, // Full URL for Epic capsuleImageUrl = epicGame.thumbnailUrl, headerImageUrl = epicGame.headerImageUrl, gameSource = GameSource.EPIC, isInstalled = epicGame.isInstalled ) } ``` -------------------------------- ### Build Steam Library Item Source: https://context7.com/utkarshdalal/gamenative/llms.txt Creates a LibraryItem from SteamApp data. Requires SteamApp object and uses SteamService to check installation status. ```kotlin fun buildSteamLibraryItem(steamApp: SteamApp): LibraryItem { return LibraryItem( appId = "STEAM_${steamApp.id}", name = steamApp.name, iconHash = steamApp.iconHash, capsuleImageUrl = "https://cdn.cloudflare.steamstatic.com/steam/apps/${steamApp.id}/library_600x900.jpg", headerImageUrl = "https://cdn.cloudflare.steamstatic.com/steam/apps/${steamApp.id}/header.jpg", heroImageUrl = "https://cdn.cloudflare.steamstatic.com/steam/apps/${steamApp.id}/library_hero.jpg", gameSource = GameSource.STEAM, isInstalled = SteamService.isAppInstalled(steamApp.id) ) } ``` -------------------------------- ### Configure CMake Project Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Sets the minimum required CMake version and project name. This is a standard starting point for any CMake project. ```cmake cmake_minimum_required(VERSION 3.22.1) project(PRoot) ``` -------------------------------- ### Manage Steam Library and Downloads Source: https://context7.com/utkarshdalal/gamenative/llms.txt Retrieves owned games, checks installation status, and manages the download process with progress tracking. ```kotlin // Checking library and downloading a game lifecycleScope.launch { // Get user's owned games val ownedGames = SteamService.getOwnedGames() // Check if a game is installed val appId = 12345 val isInstalled = SteamService.isAppInstalled(appId) // Get download size information val depots = SteamService.getDownloadableDepots(appId) val totalSize = depots.values.sumOf { it.manifests["public"]?.size ?: 0L } // Start download with progress tracking val downloadInfo = SteamService.downloadApp( context = this@MainActivity, appId = appId, depotIds = depots.keys.toList(), branch = "public", installPath = SteamService.getAppDirPath(appId) ) // Monitor download progress downloadInfo.addProgressListener { progress -> Log.d("Download", "Progress: ${(progress * 100).toInt()}%") } // Get ETA for download val etaMillis = downloadInfo.getEstimatedTimeRemaining() Log.d("Download", "ETA: ${etaMillis?.let { it / 1000 / 60 }} minutes") } ``` -------------------------------- ### Manage Epic Game Lifecycle Source: https://context7.com/utkarshdalal/gamenative/llms.txt Provides methods to check installation status, retrieve paths, uninstall games, and perform logout operations. ```kotlin // Managing Epic game lifecycle lifecycleScope.launch { // Check if installed val isInstalled = EpicService.isGameInstalled(context, appId) // Get install path val path = EpicService.getInstallPath(appId) // Get launch executable val executable = EpicService.getInstalledExe(appId) // Delete/uninstall game EpicService.deleteGame(context, appId).onSuccess { Log.d("Epic", "Game uninstalled successfully") } // Logout from Epic EpicService.logout(context) } ``` -------------------------------- ### Launch Game in Container Source: https://context7.com/utkarshdalal/gamenative/llms.txt Initiates game launch within its configured Wine container. This function determines the correct executable path based on the game source and starts the game activity. ```kotlin fun launchGame(context: Context, libraryItem: LibraryItem) { val containerId = "${libraryItem.gameSource.name}_${libraryItem.gameId}" val containerManager = ContainerManager(context) val container = containerManager.getContainer(containerId) // Get executable path based on game source lifecycleScope.launch { val executablePath = when (libraryItem.gameSource) { GameSource.STEAM -> SteamService.getInstalledExe(libraryItem.gameId) GameSource.EPIC -> EpicService.getLaunchExecutable(libraryItem.gameId) GameSource.GOG -> GOGService.getLaunchExecutable(libraryItem.appId, container) else -> container.executablePath } // Set executable and launch container.executablePath = executablePath container.installPath = when (libraryItem.gameSource) { GameSource.STEAM -> SteamService.getAppDirPath(libraryItem.gameId) GameSource.EPIC -> EpicService.getInstallPath(libraryItem.gameId) ?: "" GameSource.GOG -> GOGService.getInstallPath(libraryItem.appId) ?: "" else -> "" } // Start the game activity val intent = Intent(context, XServerActivity::class.java).apply { putExtra("container_id", containerId) } context.startActivity(intent) } } ``` -------------------------------- ### GOG Authentication and Validation Source: https://context7.com/utkarshdalal/gamenative/llms.txt Handles GOG authentication using an authorization code and validates existing credentials. Ensure the GOGService is started after successful authentication. ```kotlin // GOG authentication lifecycleScope.launch { val result = GOGService.authenticateWithCode(context, authorizationCode) result.onSuccess { Log.d("GOG", "Authenticated: ${it.username}") GOGService.start(context) } // Validate existing credentials val isValid = GOGService.validateCredentials(context).getOrNull() ?: false } ``` -------------------------------- ### Get Platform-Specific Icon URL from LibraryItem Source: https://context7.com/utkarshdalal/gamenative/llms.txt Accesses the clientIconUrl property of a LibraryItem to get the appropriate icon URL for the platform (Steam, Epic, GOG). ```kotlin val iconUrl = libraryItem.clientIconUrl // Steam: "https://media.steampowered.com/steamcommunity/public/images/apps/12345/abc123.ico" // Epic: Direct URL from iconHash // GOG: "https://images.gog.com/..." or full URL ``` -------------------------------- ### Define LibraryItem Data Model Source: https://context7.com/utkarshdalal/gamenative/llms.txt Represents a unified game entry across platforms. Includes fields for app ID, name, icons, installation status, and source. ```kotlin data class LibraryItem( val index: Int = 0, val appId: String = "", // Format: "STEAM_12345" or "EPIC_uuid" or "GOG_123" val name: String = "", val iconHash: String = "", val capsuleImageUrl: String = "", val headerImageUrl: String = "", val heroImageUrl: String = "", val gridHeroImageScale: Float = 1f, val isShared: Boolean = false, val gameSource: GameSource = GameSource.STEAM, val compatibilityStatus: GameCompatibilityStatus? = null, val sizeBytes: Long = 0L, val isInstalled: Boolean = false ) ``` -------------------------------- ### Create and Configure Game Container Source: https://context7.com/utkarshdalal/gamenative/llms.txt Use this function to create a new Wine container for a game, setting up screen, graphics, emulator, and Wine versions. Ensure necessary context and game source information are provided. ```kotlin fun createGameContainer(context: Context, gameSource: GameSource, gameId: Int): Container { val containerManager = ContainerManager(context) val containerId = "${gameSource.name}_$gameId" // Get default container settings optimized for device ContainerUtils.setContainerDefaults(context) val containerData = ContainerUtils.getDefaultContainerData() // Create container with custom settings val container = containerManager.createContainer(containerId) ?: containerManager.getContainer(containerId) container.apply { // Screen and graphics settings screenSize = "1280x720" graphicsDriver = "Wrapper" // Turnip for Adreno GPUs dxwrapper = "dxvk" // Configure DXVK settings dxwrapperConfig = buildString { append("version=${DefaultVersion.DXVK},") append("framerate=60,") append("async=1,") append("vkd3dVersion=${DefaultVersion.VKD3D},") append("vkd3dLevel=12_1") } // Emulator settings (Box64 or FEXCore) emulator = "FEXCore" box64Version = DefaultVersion.BOX64 box64Preset = Box86_64Preset.PERFORMANCE // Wine version wineVersion = "proton-9.0-arm64ec" wow64Mode = true // Game-specific settings envVars = Container.DEFAULT_ENV_VARS language = "english" localSavesOnly = false steamOfflineMode = false } containerManager.saveContainer(container) return container } ``` -------------------------------- ### Download and Manage Epic Games Source: https://context7.com/utkarshdalal/gamenative/llms.txt Demonstrates fetching game manifest sizes, handling DLC, and initiating game downloads with progress monitoring. ```kotlin // Downloading an Epic game lifecycleScope.launch { val appId = 12345 // GameNative internal ID val game = EpicService.getEpicGameOf(appId) // Get download and install sizes val sizes = EpicService.fetchManifestSizes(context, appId) Log.d("Epic", "Download size: ${sizes.downloadSize}, Install size: ${sizes.installSize}") // Check for DLC val dlcList = EpicService.getDLCForGame(appId) val dlcIds = dlcList.map { it.id } // Start download val installPath = EpicConstants.getGameInstallPath(context, game.appName) val result = EpicService.downloadGame( context = context, appId = appId, dlcGameIds = dlcIds, installPath = installPath, containerLanguage = "en-US" ) result.onSuccess { downloadInfo -> // Monitor progress while (downloadInfo.isActive()) { val progress = downloadInfo.getProgress() val (downloaded, total) = downloadInfo.getBytesProgress() Log.d("Epic", "Downloaded: $downloaded / $total bytes (${(progress * 100).toInt()}%)") delay(1000) } } } ``` -------------------------------- ### Configure SteamGridDB API Key Source: https://github.com/utkarshdalal/gamenative/blob/master/README.md To enable automatic fetching of game images for Custom Games, add your SteamGridDB API key to the `local.properties` file. If not configured, the app will log a message but continue to function without fetching images. ```properties STEAMGRIDDB_API_KEY=your_api_key_here ``` -------------------------------- ### Monitor Download Progress and Status Source: https://context7.com/utkarshdalal/gamenative/llms.txt Use this to track download progress, update UI via listeners, and poll for detailed status including ETA. ```kotlin // Monitoring download with detailed progress fun monitorDownload(downloadInfo: DownloadInfo) { // Set total expected bytes for accurate progress downloadInfo.setTotalExpectedBytes(totalBytes) // Add progress listener downloadInfo.addProgressListener { progress -> updateProgressUI(progress) } // Status message updates lifecycleScope.launch { downloadInfo.getStatusMessageFlow().collect { message -> message?.let { statusText.text = it } } } // Poll for detailed progress lifecycleScope.launch { while (downloadInfo.isActive()) { val progress = downloadInfo.getProgress() val (downloaded, total) = downloadInfo.getBytesProgress() val etaMillis = downloadInfo.getEstimatedTimeRemaining() val etaText = etaMillis?.let { val minutes = it / 1000 / 60 val seconds = (it / 1000) % 60 "${minutes}m ${seconds}s" } ?: "Calculating..." Log.d("Download", buildString { append("Progress: ${(progress * 100).toInt()}% ") append("($downloaded / $total bytes) ") append("ETA: $etaText") }) delay(1000) } // Check final state val finalProgress = downloadInfo.getProgress() when { finalProgress >= 1.0f -> Log.d("Download", "Download completed successfully") finalProgress < 0f -> Log.e("Download", "Download failed") else -> Log.w("Download", "Download paused or cancelled") } } } ``` -------------------------------- ### Add Executable Library Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Defines a shared library (executable) named 'libproot.so' with multiple source files. This is the main component of the project. ```cmake add_executable(libproot.so src/cli/cli.c src/cli/proot.c src/cli/note.c src/execve/enter.c src/execve/exit.c src/execve/elf.c src/execve/auxv.c src/path/binding.c src/path/glue.c src/path/canon.c src/path/path.c src/path/proc.c src/path/temp.c src/syscall/seccomp.c src/syscall/syscall.c src/syscall/chain.c src/syscall/enter.c src/syscall/exit.c src/syscall/sysnum.c src/syscall/socket.c src/syscall/heap.c src/syscall/rlimit.c src/tracee/tracee.c src/tracee/mem.c src/tracee/reg.c src/tracee/event.c src/tracee/seccomp.c src/ptrace/ptrace.c src/ptrace/wait.c) ``` -------------------------------- ### Cancel and Resume Downloads Source: https://context7.com/utkarshdalal/gamenative/llms.txt Manage download cancellation and identify resumable partial downloads across supported game services. ```kotlin // Cancelling and resuming downloads fun cancelDownload(downloadInfo: DownloadInfo, gameSource: GameSource, gameId: Any) { // Cancel persists progress for resume downloadInfo.cancel() // Or cancel via service when (gameSource) { GameSource.STEAM -> SteamService.cancelDownload(gameId as Int) GameSource.EPIC -> EpicService.cancelDownload(gameId as Int) GameSource.GOG -> GOGService.cancelDownload(gameId as String) } } // Check for partial downloads that can be resumed suspend fun checkResumableDownloads() { // Steam partial downloads val steamPartials = SteamService.getPartialDownloads() // Epic partial downloads val epicPartials = EpicService.getPartialDownloads() // GOG partial downloads val gogPartials = GOGService.getPartialDownloads() steamPartials.forEach { appId -> Log.d("Resume", "Found resumable Steam download: $appId") } } ``` -------------------------------- ### Link Libraries Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Links the 'libproot.so' executable against the 'talloc' static library. This makes the functionality of 'talloc' available to 'libproot.so'. ```cmake target_link_libraries(libproot.so talloc) ``` -------------------------------- ### CMake build configuration for PatchElf Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/patchelf/CMakeLists.txt Defines the project structure and build settings for the PatchElf library. ```cmake cmake_minimum_required(VERSION 3.22.1) project(PatchElf) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") include_directories(src) add_library(patchelf SHARED src/patchelf.cc) target_link_libraries(patchelf) ``` -------------------------------- ### CMake configuration for XConnectorPatch Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/xconnectorpatch/CMakeLists.txt Defines the project requirements and links the shared library against the system log library. ```cmake cmake_minimum_required(VERSION 3.22.1) project(XConnectorPatch C) add_library(xconnectorpatch SHARED xconnectorpatch.c) target_link_libraries(xconnectorpatch log) ``` -------------------------------- ### GOG Cloud Saves Synchronization Source: https://context7.com/utkarshdalal/gamenative/llms.txt Synchronizes cloud saves for a given application ID, supporting both download and upload actions. Logs the completion status of the synchronization. ```kotlin // GOG cloud saves synchronization lifecycleScope.launch { val appId = "GOG_12345" // Container ID format // Sync saves before launching (download from cloud) val downloadSuccess = GOGService.syncCloudSaves( context = context, appId = appId, preferredAction = "download" ) // After game exits, upload saves to cloud val uploadSuccess = GOGService.syncCloudSaves( context = context, appId = appId, preferredAction = "upload" ) Log.d("GOG", "Cloud save sync completed: download=$downloadSuccess, upload=$uploadSuccess") } ``` -------------------------------- ### CMake Project Configuration Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/CMakeLists.txt Defines the project requirements, compiler flags, subdirectories, and shared library build targets. ```cmake cmake_minimum_required(VERSION 3.22.1) Project(Pluvia) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wno-unused-function -Wimplicit-function-declaration") #add_subdirectory(proot) add_subdirectory(virglrenderer) add_subdirectory(patchelf) add_library(winlator SHARED winlator/drawable.c winlator/gpu_image.c winlator/sysvshared_memory.c winlator/xconnector_epoll.c winlator/alsa_client.c winlator/patchelf_wrapper.cpp) target_link_libraries(winlator log android jnigraphics aaudio EGL GLESv2 GLESv3) ``` -------------------------------- ### Link Libraries to Target in CMake Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/extras/CMakeLists.txt Links the 'extras' target to various system and custom libraries. Ensure these libraries are available in your build environment. ```cmake target_link_libraries(extras log android EGL GLESv2 GLESv3 adrenotools) ``` -------------------------------- ### Add Static Library Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Defines a static library named 'talloc' from the specified source file. Static libraries are linked directly into the executable. ```cmake add_library(talloc STATIC talloc/talloc.c) ``` -------------------------------- ### Add Shared Library Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Defines a shared library named 'proot-loader' from its source file. Shared libraries can be loaded at runtime. ```cmake add_library(proot-loader SHARED src/loader/loader.c) ``` -------------------------------- ### Include Directories Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Specifies directories to be searched for header files. This is necessary for including custom headers in your source files. ```cmake include_directories(src talloc) ``` -------------------------------- ### CMake build configuration for VirGLRenderer Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/virglrenderer/CMakeLists.txt Defines the project structure, source files, and dependencies for building the VirGLRenderer shared library. ```cmake cmake_minimum_required(VERSION 3.22.1) project(VirGLRenderer) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wno-unused-function -Wimplicit-function-declaration") include_directories(src src/gallium/include src/gallium/auxiliary src/gallium/auxiliary/util server) add_library(virglrenderer SHARED src/iov.c src/vrend_blitter.c src/vrend_decode.c src/vrend_formats.c src/vrend_object.c src/vrend_renderer.c src/vrend_shader.c server/virgl_server.c server/virgl_server_shm.c server/virgl_server_renderer.c src/gallium/auxiliary/util/u_format.c src/gallium/auxiliary/util/u_format_table.c src/gallium/auxiliary/util/u_texture.c src/gallium/auxiliary/util/u_hash_table.c src/gallium/auxiliary/util/u_debug.c src/gallium/auxiliary/util/u_cpu_detect.c src/gallium/auxiliary/util/u_bitmask.c src/gallium/auxiliary/util/u_surface.c src/gallium/auxiliary/util/u_math.c src/gallium/auxiliary/util/u_debug_describe.c src/gallium/auxiliary/cso_cache/cso_cache.c src/gallium/auxiliary/cso_cache/cso_hash.c src/gallium/auxiliary/tgsi/tgsi_dump.c src/gallium/auxiliary/tgsi/tgsi_ureg.c src/gallium/auxiliary/tgsi/tgsi_build.c src/gallium/auxiliary/tgsi/tgsi_scan.c src/gallium/auxiliary/tgsi/tgsi_info.c src/gallium/auxiliary/tgsi/tgsi_parse.c src/gallium/auxiliary/tgsi/tgsi_text.c src/gallium/auxiliary/tgsi/tgsi_strings.c src/gallium/auxiliary/tgsi/tgsi_sanity.c src/gallium/auxiliary/tgsi/tgsi_iterate.c src/gallium/auxiliary/tgsi/tgsi_util.c src/gallium/auxiliary/tgsi/tgsi_transform.c src/gallium/auxiliary/os/os_misc.c) target_link_libraries(virglrenderer log android EGL GLESv2 GLESv3) ``` -------------------------------- ### Synchronizing Steam cloud saves in Kotlin Source: https://context7.com/utkarshdalal/gamenative/llms.txt Uses lifecycleScope to perform cloud synchronization on a background thread, including path resolution and conflict handling. ```kotlin // Synchronizing Steam cloud saves lifecycleScope.launch(Dispatchers.IO) { val appId = 12345 val steamApp = SteamService.getSteamApp(appId) val clientId = SteamService.getClientId() // Define path resolver for save locations val prefixToPath: (String) -> String = { prefix -> when (prefix) { "GameInstall" -> SteamService.getAppDirPath(appId) "WinAppDataLocal" -> "$containerPath/drive_c/users/xuser/AppData/Local" "WinAppDataRoaming" -> "$containerPath/drive_c/users/xuser/AppData/Roaming" "SteamUserData" -> "$containerPath/drive_c/users/xuser/steam_userdata/$appId" else -> "$containerPath/drive_c" } } // Sync cloud saves with progress callback val syncDeferred = SteamAutoCloud.syncUserFiles( appInfo = steamApp, clientId = clientId, steamInstance = steamService, steamCloud = steamCloud, preferredSave = SaveLocation.None, // Auto-detect, or Local/Remote to force prefixToPath = prefixToPath, onProgress = { message, progress -> Log.d("CloudSync", "$message: ${(progress * 100).toInt()}%") } ) // Wait for sync and handle result val postSyncInfo = syncDeferred.await() when (postSyncInfo?.syncResult) { SyncResult.Success -> Log.d("CloudSync", "Sync completed successfully") SyncResult.UpToDate -> Log.d("CloudSync", "Already up to date") SyncResult.Conflict -> { // User must choose between local and remote saves Log.d("CloudSync", "Conflict detected!") Log.d("CloudSync", "Remote timestamp: ${postSyncInfo.remoteTimestamp}") Log.d("CloudSync", "Local timestamp: ${postSyncInfo.localTimestamp}") // Re-sync with user preference val resolvedSync = SteamAutoCloud.syncUserFiles( appInfo = steamApp, clientId = clientId, steamInstance = steamService, steamCloud = steamCloud, preferredSave = SaveLocation.Remote, // Use cloud save prefixToPath = prefixToPath ).await() } SyncResult.DownloadFail -> Log.e("CloudSync", "Failed to download saves") SyncResult.UpdateFail -> Log.e("CloudSync", "Failed to upload saves") else -> Log.e("CloudSync", "Unknown sync error") } // Log sync metrics postSyncInfo?.let { info -> Log.d("CloudSync", "Files downloaded: ${info.filesDownloaded}") Log.d("CloudSync", "Files uploaded: ${info.filesUploaded}") Log.d("CloudSync", "Bytes downloaded: ${info.bytesDownloaded}") Log.d("CloudSync", "Bytes uploaded: ${info.bytesUploaded}") } } ``` -------------------------------- ### Define Shared Library in CMake Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/extras/CMakeLists.txt Creates a shared library named 'extras' with specified source files. This is used for dynamic linking. ```cmake add_library(extras SHARED gpu_image.c vulkan.c) ``` -------------------------------- ### Authenticate with Epic Games Source: https://context7.com/utkarshdalal/gamenative/llms.txt Handles OAuth authentication using an authorization code and checks for existing stored credentials. ```kotlin // Epic Games authentication with authorization code class EpicLoginActivity : AppCompatActivity() { // Complete OAuth flow with authorization code from Epic login page private fun authenticateWithEpic(authorizationCode: String) { lifecycleScope.launch { val result = EpicService.authenticateWithCode( context = this@EpicLoginActivity, authorizationCode = authorizationCode ) result.onSuccess { credentials -> Log.d("Epic", "Authenticated as: ${credentials.displayName}") Log.d("Epic", "Account ID: ${credentials.accountId}") // Start Epic service after authentication EpicService.start(this@EpicLoginActivity) }.onFailure { error -> Log.e("Epic", "Authentication failed: ${error.message}") } } } // Check for existing credentials private fun checkExistingAuth() { if (EpicService.hasStoredCredentials(this)) { lifecycleScope.launch { val credentials = EpicService.getStoredCredentials(this@EpicLoginActivity) credentials.onSuccess { EpicService.start(this@EpicLoginActivity) } } } } } ``` -------------------------------- ### Set C Flags Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/proot/CMakeLists.txt Configures C compiler flags for optimization and warning suppression. Use this to adjust build performance and strictness. ```cmake set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wno-unused-function -Wimplicit-function-declaration") ``` -------------------------------- ### Steam Service API Source: https://context7.com/utkarshdalal/gamenative/llms.txt APIs for interacting with the Steam service, including authentication, library management, and game downloads. ```APIDOC ## Steam Service API ### Description APIs for interacting with the Steam service, including authentication, library management, and game downloads. ### Starting the Steam Service ```kotlin // Starting the Steam service with authentication class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Start Steam service SteamService.start(this) // Listen for connection events PluviaApp.events.on { Log.d("Steam", "Steam service is ready") } } } ``` ### QR Code Authentication ```kotlin // QR Code authentication flow private fun startQrAuth() { lifecycleScope.launch { // Get QR code challenge URL val qrSession = SteamService.startQrAuth { // Display this URL as a QR code for user to scan with Steam mobile app displayQrCode(challengeUrl) } // Poll for authentication result val result = qrSession.pollAuthSessionStatus() if (result.accountName.isNotEmpty()) { // Authentication successful Log.d("Steam", "Logged in as: ${result.accountName}") } } } ``` ### Library and Game Download Management ```kotlin // Checking library and downloading a game lifecycleScope.launch { // Get user's owned games val ownedGames = SteamService.getOwnedGames() // Check if a game is installed val appId = 12345 val isInstalled = SteamService.isAppInstalled(appId) // Get download size information val depots = SteamService.getDownloadableDepots(appId) val totalSize = depots.values.sumOf { it.manifests["public"]?.size ?: 0L } // Start download with progress tracking val downloadInfo = SteamService.downloadApp( context = this@MainActivity, appId = appId, depotIds = depots.keys.toList(), branch = "public", installPath = SteamService.getAppDirPath(appId) ) // Monitor download progress downloadInfo.addProgressListener { Log.d("Download", "Progress: ${(progress * 100).toInt()}%") } // Get ETA for download val etaMillis = downloadInfo.getEstimatedTimeRemaining() Log.d("Download", "ETA: ${etaMillis?.let { it / 1000 / 60 }} minutes") } ``` ``` -------------------------------- ### Include Subdirectory in CMake Source: https://github.com/utkarshdalal/gamenative/blob/master/app/src/main/cpp/extras/CMakeLists.txt Adds the 'adrenotools' subdirectory to the build. This is useful for modularizing larger projects. ```cmake add_subdirectory(adrenotools) ``` -------------------------------- ### Extract Numeric Game ID from LibraryItem Source: https://context7.com/utkarshdalal/gamenative/llms.txt Retrieves the numeric part of the appId from a LibraryItem. Assumes appId is prefixed with a platform identifier like 'STEAM_'. ```kotlin val libraryItem = buildSteamLibraryItem(steamApp) val numericId = libraryItem.gameId // Returns 12345 from "STEAM_12345" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.