#if UNITY_EDITOR using System; using System.IO; using System.Linq; using System.Reflection; using Newtonsoft.Json; using UnityEditor; using UnityEngine; // Fixed CLI helpers; no arbitrary method names or process-marker deletion. public static class KVGameplayLoopSetup { static string Root => Path.GetFullPath(Path.Combine(Application.dataPath,"../../CodexOutput/upserver/KVGameplayLoopTests")); static Type Find(string name) => AppDomain.CurrentDomain.GetAssemblies().Select(a=>a.GetType("game.PlayerDataStorage."+name)).FirstOrDefault(t=>t!=null) ?? throw new InvalidOperationException("Gameplay assembly not loaded."); static object ReadProperty(Type type,string name) => type.GetProperty(name,BindingFlags.Static|BindingFlags.NonPublic)?.GetValue(null); public static async System.Threading.Tasks.Task RunValidationAsync(string caseId) { string methodName; switch (caseId) { case "equipment-chain": methodName = "VerifyEquipmentForEditorAsync"; break; case "fishing-consume": methodName = "VerifyFishingForEditorAsync"; break; case "fishing-reward": methodName = "VerifyFishingRewardForEditorAsync"; break; case "fishing-original-reward": methodName = "VerifyOriginalFishingRewardForEditorAsync"; break; case "fishing-original-consume": methodName = "VerifyOriginalFishingForEditorAsync"; break; default: throw new ArgumentException("Unknown fixed validation case."); } if(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling || EditorApplication.isUpdating) { throw new InvalidOperationException("Idle editor required."); } var method = Find("PlayerKVGameplayLoop").GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic); if (method == null) { throw new InvalidOperationException("Fixed equipment validation entry unavailable."); } return await (System.Threading.Tasks.Task)method.Invoke(null,null); } public static string State() { var type=Find("PlayerKVGameplayLoop"); var history=Path.Combine(Root,"run-control"); return JsonConvert.SerializeObject(new{project=Application.dataPath,playing=EditorApplication.isPlaying, enabled=ReadProperty(type,"Enabled"),ready=ReadProperty(type,"Ready"),error=ReadProperty(type,"Error"),run=ReadProperty(type,"RunPath"), permitExists=File.Exists(Path.Combine(Root,"permit.json")), processMarkers=Directory.Exists(history)?Directory.GetFiles(history,"*.claimed").Select(Path.GetFileName).OrderBy(x=>x).ToArray():Array.Empty()}); } public static string InspectPFBackup(string path) { if(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling || EditorApplication.isUpdating) throw new InvalidOperationException("Idle editor required."); var method=Find("PlayerKVGameplayLoop").GetMethod("InspectPFBackupForEditor",BindingFlags.Static|BindingFlags.NonPublic); try { return (string)method.Invoke(null,new object[]{path}); } catch(TargetInvocationException e) { throw e.InnerException ?? e; } } } #endif