using System.IO; using ADOFAIRenderer.Core; using ADOFAIRenderer.Util; using HarmonyLib; using UnityEngine; namespace ADOFAIRenderer.Patch.Game { [HarmonyPatch(typeof(scnGame))] // ReSharper disable once InconsistentNaming public static class scnGamePatch { [HarmonyPrefix] [HarmonyPatch("UpdateVideo")] // ReSharper disable once InconsistentNaming public static bool ReplaceVideo(scnGame __instance) { // Only replace when rendering is active if (!RenderManager.IsActive) { // Remove FFmpeg player if it was attached previously var oldPlayer = __instance.videoBG.gameObject.GetComponent(); if (oldPlayer != null) { Object.Destroy(oldPlayer); } // Re-enable native player component __instance.videoBG.enabled = true; return true; // Execute original } string text = __instance.levelData.miscSettings.GetString("bgVideo"); if (string.IsNullOrEmpty(text)) { __instance.videoBG.gameObject.SetActive(false); return false; // Skip original } __instance.videoBG.gameObject.SetActive(true); // We can only play external video files via FFmpegNativeDecoder. // Internal/Bundle level background videos are built-in VideoClips, so we fallback to native Unity VideoPlayer. if (ADOBase.isInternalLevel || ADOBase.isBundleLevel) { __instance.videoBG.enabled = true; return true; // Execute original } // Custom level video path var videoPath = Path.Combine(Path.GetDirectoryName(ADOBase.levelPath) ?? "", text); if (!File.Exists(videoPath)) { return true; // Let the original print error } // Disable native VideoPlayer component (to prevent it from attempting real-time playback and sync errors) var targetCamera = __instance.videoBG.targetCamera; if (!targetCamera) { var camGo = GameObject.Find("BGStaticCam"); if (camGo != null) { targetCamera = camGo.GetComponent(); } } __instance.videoBG.enabled = false; // Add or retrieve our custom FFmpeg video background player var player = __instance.videoBG.gameObject.GetComponent(); if (player == null) { player = __instance.videoBG.gameObject.AddComponent(); } var isLooping = __instance.levelData.miscSettings.GetBool("loopVideo"); // Initialize player. If targetTexture is null (CameraFarPlane mode), it will build a quad in front of targetCamera. player.Init(videoPath, __instance.videoBG.targetTexture, isLooping, targetCamera, __instance.videoBG.gameObject); return false; // Skip original UpdateVideo } } }