diff --git a/mod/ONIAgentBridge.cs b/mod/ONIAgentBridge.cs index 5ffc628..dbafea2 100644 --- a/mod/ONIAgentBridge.cs +++ b/mod/ONIAgentBridge.cs @@ -1,3 +1,9 @@ +// ===================================================================== +// ONI Agent Bridge Mod +// 67 API calls marked 🔶 UNVERIFIED — need in-game compilation to verify +// Fix pattern: remove // 🔶, replace with // ✅ once confirmed working +// ===================================================================== + using HarmonyLib; using KMod; using System; @@ -790,7 +796,7 @@ namespace ONIAgentBridge skillLevels = skills?.GetTotalSkillPointsGained() ?? 0, currentChore = ai?.GetCurrentChore()?.GetType()?.Name ?? "idle", isSleeping = nav?.IsMoving() == false && ai?.GetCurrentChore()?.GetType()?.Name == "SleepChore", - health = health?.GetHealth() ?? 100, + health = health?.GetHealth() ?? 100, // 🔶 UNVERIFIED: Health component GetHealth()/GetMaxHealth() methods healthMax = health?.GetMaxHealth() ?? 100, inVacuum, inCO2, @@ -876,7 +882,7 @@ namespace ONIAgentBridge isOperational = building?.IsOperational ?? false, isPowered = energy?.IsPowered ?? true, powerWatt = energy?.WattsNeededWhenActive ?? 0, - health = health?.GetHealth() ?? 100, + health = health?.GetHealth() ?? 100, // 🔶 UNVERIFIED: Health component GetHealth()/GetMaxHealth() methods maxHealth = health?.GetMaxHealth() ?? 100, storageCapacity = storage?.capacityKg ?? 0, storageMass = storage?.MassStored() ?? 0, @@ -916,14 +922,14 @@ namespace ONIAgentBridge var activeTechs = new List(); try { - foreach (var tech in Research.Instance?.GetActiveResearchTechnologies() ?? new List()) + foreach (var tech in Research.Instance?.GetActiveResearchTechnologies() ?? new List()) // 🔶 UNVERIFIED: Research.GetActiveResearchTechnologies() method { activeTechs.Add(new { id = tech.Id, name = tech.Name, progress = tech.Progress(), - pointsRequired = tech.pointsForCompletion, + pointsRequired = tech.pointsForCompletion, // 🔶 UNVERIFIED: Tech.pointsForCompletion property type = tech.category?.Name ?? "" }); } @@ -1149,7 +1155,7 @@ namespace ONIAgentBridge var list = new List(); try { - foreach (var kv in Assets.BuildingDefs) + foreach (var kv in Assets.BuildingDefs) // 🔶 UNVERIFIED: Assets.BuildingDefs may not be a collection { if (kv == null) continue; list.Add(new @@ -1410,7 +1416,7 @@ namespace ONIAgentBridge private string GetBuildingRegistry() { var list = new List(); - foreach (var def in Assets.BuildingDefs) + foreach (var def in Assets.BuildingDefs) // 🔶 UNVERIFIED: Assets.BuildingDefs may not be a collection { if (def == null) continue; list.Add(new @@ -1679,7 +1685,7 @@ namespace ONIAgentBridge $"Selected {tech.Name}", "action", entity: data.techId); - Research.Instance?.QueueResearch(tech); + Research.Instance?.QueueResearch(tech); // 🔶 UNVERIFIED: Research.QueueResearch(Tech) method return JsonSerializer.Serialize(ActionOk("research_queued", new { techId = data.techId, name = tech.Name })); } @@ -1781,7 +1787,7 @@ namespace ONIAgentBridge // No body needed, but accept optional { "reason": "..." } string reason = data?.reason ?? "AI operation in progress"; - SpeedControlScreen.Instance?.Pause(false, true); + SpeedControlScreen.Instance?.Pause(false, true); // 🔶 UNVERIFIED: Pause/Unpause/SetSpeed method signatures on SpeedControlScreen PushEvent("pause", "info", "Game paused", $"Game paused by AI: {reason}", "system"); @@ -1800,8 +1806,8 @@ namespace ONIAgentBridge if (speed < 1) speed = 1; if (speed > 3) speed = 3; - SpeedControlScreen.Instance?.Unpause(true); - SpeedControlScreen.Instance?.SetSpeed(speed); + SpeedControlScreen.Instance?.Unpause(true); // 🔶 UNVERIFIED: Pause/Unpause/SetSpeed method signatures on SpeedControlScreen + SpeedControlScreen.Instance?.SetSpeed(speed); // 🔶 UNVERIFIED: Pause/Unpause/SetSpeed method signatures on SpeedControlScreen PushEvent("unpause", "info", "Game resumed", $"Game resumed by AI at {speed}x speed", "system"); @@ -1826,7 +1832,7 @@ namespace ONIAgentBridge bool isPaused = SpeedControlScreen.Instance?.IsPaused ?? false; if (!isPaused) { - SpeedControlScreen.Instance?.SetSpeed(speed); + SpeedControlScreen.Instance?.SetSpeed(speed); // 🔶 UNVERIFIED: Pause/Unpause/SetSpeed method signatures on SpeedControlScreen } PushEvent("speed", "info", $"Game speed set to {speed}x", @@ -2101,20 +2107,20 @@ namespace ONIAgentBridge var circuits = new List(); try { - var mgr = Game.Instance?.circuitManager; + var mgr = Game.Instance?.circuitManager; // 🔶 UNVERIFIED: Game.Instance.circuitManager — may be electricalManager if (mgr != null) { - foreach (var circuit in mgr.GetCircuits()) + foreach (var circuit in mgr.GetCircuits()) // 🔶 UNVERIFIED: circuitManager.GetCircuits() method may not exist { if (circuit == null) continue; circuits.Add(new { id = circuit.ID, - wattsUsed = circuit.WattsUsed, - wattsGenerated = circuit.WattsGenerated, - maxWatts = circuit.MaxWatts, - isOverloaded = circuit.WattsUsed > circuit.MaxWatts, - isPowered = circuit.WattsGenerated > 0 + wattsUsed = circuit.WattsUsed, // 🔶 UNVERIFIED: Circuit property names may differ + wattsGenerated = circuit.WattsGenerated, // 🔶 UNVERIFIED: Circuit property names may differ + maxWatts = circuit.MaxWatts, // 🔶 UNVERIFIED: Circuit property names may differ + isOverloaded = circuit.WattsUsed > circuit.MaxWatts, // 🔶 UNVERIFIED: Circuit property names may differ + isPowered = circuit.WattsGenerated > 0 // 🔶 UNVERIFIED: Circuit property names may differ }); } } @@ -2128,9 +2134,9 @@ namespace ONIAgentBridge generators.Add(new { name = gen.name, - watts = gen.WattageRating, + watts = gen.WattageRating, // 🔶 UNVERIFIED: Generator property names may differ isActive = gen.IsPowered, - circuitID = gen.CircuitID + circuitID = gen.CircuitID // 🔶 UNVERIFIED: Generator property names may differ }); } @@ -2149,23 +2155,23 @@ namespace ONIAgentBridge { if (type == "all" || type == "liquid") { - var flow = Game.Instance?.liquidConduitFlow; + var flow = Game.Instance?.liquidConduitFlow; // 🔶 UNVERIFIED: Game.Instance.liquidConduitFlow — may be different conduit system if (flow != null) { int count = 0; - foreach (var conduit in Components.LiquidConduits) + foreach (var conduit in Components.LiquidConduits) // 🔶 UNVERIFIED: Components.LiquidConduits / GasConduits may not exist { if (conduit == null || count > 200) break; - var contents = flow.GetContents(conduit.GetCell()); - if (contents != null && contents.mass > 0) + var contents = flow.GetContents(conduit.GetCell()); // 🔶 UNVERIFIED: Conduit.GetCell() method + if (contents != null && contents.mass > 0) // 🔶 UNVERIFIED: ConduitContents property names { segments.Add(new { type = "liquid", - element = contents.element?.name ?? "unknown", - mass = contents.mass, - temperature = contents.temperature, - cell = conduit.GetCell() + element = contents.element?.name ?? "unknown", // 🔶 UNVERIFIED: ConduitContents property names + mass = contents.mass, // 🔶 UNVERIFIED: ConduitContents property names + temperature = contents.temperature, // 🔶 UNVERIFIED: ConduitContents property names + cell = conduit.GetCell() // 🔶 UNVERIFIED: Conduit.GetCell() method }); count++; } @@ -2174,23 +2180,23 @@ namespace ONIAgentBridge } if (type == "all" || type == "gas") { - var flow = Game.Instance?.gasConduitFlow; + var flow = Game.Instance?.gasConduitFlow; // 🔶 UNVERIFIED: Game.Instance.gasConduitFlow — may be different conduit system if (flow != null) { int count = 0; - foreach (var conduit in Components.GasConduits) + foreach (var conduit in Components.GasConduits) // 🔶 UNVERIFIED: Components.LiquidConduits / GasConduits may not exist { if (conduit == null || count > 200) break; - var contents = flow.GetContents(conduit.GetCell()); - if (contents != null && contents.mass > 0) + var contents = flow.GetContents(conduit.GetCell()); // 🔶 UNVERIFIED: Conduit.GetCell() method + if (contents != null && contents.mass > 0) // 🔶 UNVERIFIED: ConduitContents property names { segments.Add(new { type = "gas", - element = contents.element?.name ?? "unknown", - mass = contents.mass, - temperature = contents.temperature, - cell = conduit.GetCell() + element = contents.element?.name ?? "unknown", // 🔶 UNVERIFIED: ConduitContents property names + mass = contents.mass, // 🔶 UNVERIFIED: ConduitContents property names + temperature = contents.temperature, // 🔶 UNVERIFIED: ConduitContents property names + cell = conduit.GetCell() // 🔶 UNVERIFIED: Conduit.GetCell() method }); count++; } @@ -2330,7 +2336,7 @@ namespace ONIAgentBridge var germs = new Dictionary(); for (int i = 0; i < Math.Min(Grid.CellCount, 5000); i += 10) { - foreach (var kv in Grid.Germs) + foreach (var kv in Grid.Germs) // 🔶 UNVERIFIED: Grid.Germs API — may not exist or have different type { float count = kv.Key; if (count > 0) @@ -2430,7 +2436,7 @@ namespace ONIAgentBridge var list = new List(); try { - string savePath = SaveLoader.GetActiveSaveFilePath(); + string savePath = SaveLoader.GetActiveSaveFilePath(); // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist var dir = System.IO.Path.GetDirectoryName(savePath); if (dir != null && System.IO.Directory.Exists(dir)) { @@ -2452,9 +2458,9 @@ namespace ONIAgentBridge var data = ReadBody(ctx); string name = data?.name ?? $"oni_agent_save_cycle{GameClock.Instance?.GetCycle() ?? 0}"; string path = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), + System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist name + ".sav"); - SaveLoader.Save(path, true, true); + SaveLoader.Save(path, true, true); // 🔶 UNVERIFIED: SaveLoader.Save/Load method signatures PushEvent("save", "info", "Game saved", $"Saved as {name}", "system"); return JsonSerializer.Serialize(ActionOk("game_saved", new { name, path })); } @@ -2469,9 +2475,9 @@ namespace ONIAgentBridge if (data == null || string.IsNullOrEmpty(data.name)) return JsonSerializer.Serialize(FailWithReason("missing_name", "Save name is required")); string path = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), + System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist data.name + ".sav"); - SaveLoader.Save(path, true, true); + SaveLoader.Save(path, true, true); // 🔶 UNVERIFIED: SaveLoader.Save/Load method signatures PushEvent("save", "info", "Game saved", $"Saved as {data.name}", "system"); return JsonSerializer.Serialize(ActionOk("game_saved", new { name = data.name, path })); } @@ -2486,13 +2492,13 @@ namespace ONIAgentBridge if (data == null || string.IsNullOrEmpty(data.name)) return JsonSerializer.Serialize(FailWithReason("missing_name", "Load name is required")); string path = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), + System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist data.name + ".sav"); if (!System.IO.File.Exists(path)) return JsonSerializer.Serialize(FailWithReason("save_not_found", $"Save '{data.name}' not found")); PushEvent("load", "warning", "Loading save", $"Loading {data.name}", "system"); - SaveLoader.Load(path, true); + SaveLoader.Load(path, true); // 🔶 UNVERIFIED: SaveLoader.Save/Load method signatures return JsonSerializer.Serialize(ActionOk("game_loaded", new { name = data.name, path })); } catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); } @@ -2524,12 +2530,12 @@ namespace ONIAgentBridge { try { - var cam = CameraController.Instance; + var cam = CameraController.Instance; // 🔶 UNVERIFIED: CameraController.Instance may not be the correct singleton if (cam == null) return JsonSerializer.Serialize(new { error = "camera_unavailable" }); var pos = cam.transform.position; float zoom = 1f; - try { zoom = Camera.main?.orthographicSize ?? 30f; } catch { } + try { zoom = Camera.main?.orthographicSize ?? 30f; } catch { } // 🔶 UNVERIFIED: Camera.main.orthographicSize setter may not work in ONI return JsonSerializer.Serialize(new { @@ -2550,7 +2556,7 @@ namespace ONIAgentBridge if (data == null) return JsonSerializer.Serialize(FailInvalid("invalid_request")); - var cam = CameraController.Instance; + var cam = CameraController.Instance; // 🔶 UNVERIFIED: CameraController.Instance may not be the correct singleton if (cam == null) return JsonSerializer.Serialize(FailWithReason("camera_unavailable", "Camera not available")); @@ -2571,7 +2577,7 @@ namespace ONIAgentBridge var pos = cam.transform.position; float currentZoom = 1f; - try { currentZoom = Camera.main?.orthographicSize ?? 30f; } catch { } + try { currentZoom = Camera.main?.orthographicSize ?? 30f; } catch { } // 🔶 UNVERIFIED: Camera.main.orthographicSize setter may not work in ONI return JsonSerializer.Serialize(ActionOk("camera_moved", new { @@ -2593,7 +2599,7 @@ namespace ONIAgentBridge try { string dir = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), + System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist "oni_agent_screenshots"); if (!System.IO.Directory.Exists(dir)) System.IO.Directory.CreateDirectory(dir); @@ -2603,7 +2609,7 @@ namespace ONIAgentBridge string relPath = path; // Use Unity's ScreenCapture - ScreenCapture.CaptureScreenshot(path); + ScreenCapture.CaptureScreenshot(path); // 🔶 UNVERIFIED: ScreenCapture may not be available in ONI Unity version _lastScreenshotPath = path; PushEvent("screenshot", "info", "Screenshot taken", filename, "system"); @@ -2627,7 +2633,7 @@ namespace ONIAgentBridge { // Fallback: look for most recent screenshot string dir = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), + System.IO.Path.GetDirectoryName(SaveLoader.GetActiveSaveFilePath()), // 🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist "oni_agent_screenshots"); if (System.IO.Directory.Exists(dir)) { @@ -2671,7 +2677,7 @@ namespace ONIAgentBridge var list = new List(); try { - foreach (var def in Assets.BuildingDefs) + foreach (var def in Assets.BuildingDefs) // 🔶 UNVERIFIED: Assets.BuildingDefs may not be a collection { if (def == null) continue; var tech = Research.Instance?.GetResearchTechnologies() @@ -2715,9 +2721,9 @@ namespace ONIAgentBridge var pod = Game.Instance?.printingPod; if (pod != null) { - isReady = pod.IsReady(); - cyclesUntilNext = pod.CyclesUntilReady(); - var offers = pod.GetCurrentOffers(); + isReady = pod.IsReady(); // 🔶 UNVERIFIED: PrintingPod methods IsReady/CyclesUntilReady — may differ + cyclesUntilNext = pod.CyclesUntilReady(); // 🔶 UNVERIFIED: PrintingPod methods IsReady/CyclesUntilReady — may differ + var offers = pod.GetCurrentOffers(); // 🔶 UNVERIFIED: PrintingPod.GetCurrentOffers() return type if (offers != null) { int idx = 0; @@ -2725,7 +2731,7 @@ namespace ONIAgentBridge { string desc = ""; string type = "unknown"; - try { desc = offer.GetName(); } catch { } + try { desc = offer.GetName(); } catch { } // 🔶 UNVERIFIED: CarePackage/PrintingPodOffer.GetName() method try { type = offer.GetType().Name; } catch { } options.Add(new @@ -2785,9 +2791,9 @@ namespace ONIAgentBridge try { var pod = Game.Instance?.printingPod; - if (pod != null && pod.IsReady()) + if (pod != null && pod.IsReady()) // 🔶 UNVERIFIED: PrintingPod methods IsReady/CyclesUntilReady — may differ { - pod.SelectOffer(index); + pod.SelectOffer(index); // 🔶 UNVERIFIED: PrintingPod.SelectOffer(int) method PushEvent("printing_pod", "info", $"Selected printing pod option {index}", $"Selected option {index}", "action"); return JsonSerializer.Serialize(ActionOk("printing_pod_selected", @@ -2917,11 +2923,11 @@ namespace ONIAgentBridge if (data.locked) { - try { door.Lock(); } catch { } + try { door.Lock(); } catch { } // 🔶 UNVERIFIED: Door.Lock()/Unlock() methods may not exist } else { - try { door.Unlock(); } catch { } + try { door.Unlock(); } catch { } // 🔶 UNVERIFIED: Door.Lock()/Unlock() methods may not exist } PushEvent("door", data.locked ? "warning" : "info", @@ -2989,7 +2995,7 @@ namespace ONIAgentBridge float? threshold = null; string sensorType = null; - if (pid == "AtmoSensor") { sensorType = "atmo"; try { threshold = go.GetComponent()?.threshold; } catch { } } + if (pid == "AtmoSensor") { sensorType = "atmo"; try { threshold = go.GetComponent()?.threshold; } catch { } } // 🔶 UNVERIFIED: AtmoSensor/ThermoSensor/HydroSensor threshold property else if (pid == "ThermoSensor") { sensorType = "thermo"; try { threshold = go.GetComponent()?.threshold; } catch { } } else if (pid == "HydroSensor") { sensorType = "hydro"; try { threshold = go.GetComponent()?.threshold; } catch { } } else if (pid == "PressureSensor") { sensorType = "pressure"; try { threshold = go.GetComponent()?.threshold; } catch { } } @@ -3284,8 +3290,8 @@ namespace ONIAgentBridge { try { - var sim = Game.Instance?.simOverlayManager; - string current = sim?.currentOverlay?.ToString() ?? "none"; + var sim = Game.Instance?.simOverlayManager; // 🔶 UNVERIFIED: Game.Instance.simOverlayManager may not exist + string current = sim?.currentOverlay?.ToString() ?? "none"; // 🔶 UNVERIFIED: currentOverlay.ToString() may not yield expected overlay names var overlays = new List { "none", "power", "temperature", "light", "decor", "gas", "liquid", "automation", "rooms", "germs", "materials", "suits", "crops", "radiation", "priority" }; @@ -3458,7 +3464,7 @@ namespace ONIAgentBridge $"{go.name} at ({data.x},{data.y}) cannot be toggled")); bool newState = !oper.IsOperational; - oper.SetFlag(Operational.ActiveFlag, newState); + oper.SetFlag(Operational.ActiveFlag, newState); // 🔶 UNVERIFIED: Operational.SetFlag signature — may need different approach PushEvent("toggle", newState ? "info" : "warning", $"Building toggled {(newState ? "ON" : "OFF")}", $"{go.name} at ({data.x},{data.y})", "action"); @@ -3508,7 +3514,7 @@ namespace ONIAgentBridge $"{go.name} at ({data.x},{data.y}) has no storage to empty")); float mass = storage.MassStored(); - storage.DropAll(false, true); + storage.DropAll(false, true); // 🔶 UNVERIFIED: Storage.DropAll() parameters may differ PushEvent("empty", "info", "Storage emptied", $"{go.name} at ({data.x},{data.y}) dropped {mass} kg", "action"); @@ -3562,7 +3568,7 @@ namespace ONIAgentBridge return JsonSerializer.Serialize(FailWithReason("unknown_tech", $"Tech '{techId}' not found")); - Research.Instance?.CancelResearch(tech); + Research.Instance?.CancelResearch(tech); // 🔶 UNVERIFIED: Research.CancelResearch(Tech) method PushEvent("research_cancel", "info", "Research cancelled", $"Cancelled {tech.Name}", "action"); return JsonSerializer.Serialize(ActionOk("research_cancelled", new { techId, name = tech.Name })); } @@ -3939,7 +3945,7 @@ namespace ONIAgentBridge internal class SaveRequest { public string name { get; set; } } internal class LoadRequest { public string name { get; set; } } internal class AssignJobRequest { public string duplicantId { get; set; } public string choreGroup { get; set; } public string buildingId { get; set; } } - internal class PipeWireRequest { public int x1 { get; set; } public int y1 { get; set; } public int? x2 { get; set; } public int? y2 { get; set; } public string type { get; set; } public string material { get; set; } public bool? bridge { get; set; } public string mode { get; set; } } + internal class PipeWireRequest { public int x1 { get; set; } public int y1 { get; set; } public int? x2 { get; set; } public int? y2 { get; set; } public string type { get; set; } public string material { get; set; } public bool? bridge { get; set; } public string mode { get; set; } } // 🔶 UNVERIFIED: Nullable parameters may not serialize correctly internal class CameraRequest { public int? x { get; set; } public int? y { get; set; } public float? zoom { get; set; } } internal class CellRequest { public int x { get; set; } public int y { get; set; } } internal class RecipeRequest { public int x { get; set; } public int y { get; set; } public string recipeId { get; set; } } diff --git a/scripts/annotate_apis.py b/scripts/annotate_apis.py new file mode 100644 index 0000000..f8b9bc4 --- /dev/null +++ b/scripts/annotate_apis.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +""" +Annotate uncertain C# APIs in the Mod source with verification markers. +Reads ONIAgentBridge.cs, adds // 🔶 UNVERIFIED: comments on uncertain API calls, +and writes back with all annotations. +""" + +import re + +with open('mod/ONIAgentBridge.cs', 'r') as f: + content = f.read() + lines = content.split('\n') + +annotations = {} +# Track by line number (1-indexed) +for i, line in enumerate(lines, 1): + s = line.strip() + + # Skip comments and using directives + if s.startswith('//') or s.startswith('/*') or s.startswith('using ') or s.startswith('#') or s.startswith('*'): + continue + + # === SpeedControlScreen === + if 'SpeedControlScreen.Instance' in s and ('Pause(' in s or 'Unpause(' in s or 'SetSpeed(' in s): + annotations[i] = '🔶 UNVERIFIED: Pause/Unpause/SetSpeed method signatures on SpeedControlScreen' + + # === Circuit Manager === + if 'circuitManager' in s: + annotations[i] = '🔶 UNVERIFIED: Game.Instance.circuitManager — may be electricalManager' + if 'mgr.GetCircuits()' in s: + annotations[i] = '🔶 UNVERIFIED: circuitManager.GetCircuits() method may not exist' + if 'circuit.WattsUsed' in s or 'circuit.WattsGenerated' in s or 'circuit.MaxWatts' in s: + annotations[i] = '🔶 UNVERIFIED: Circuit property names may differ' + if 'gen.WattageRating' in s or 'gen.CircuitID' in s: + annotations[i] = '🔶 UNVERIFIED: Generator property names may differ' + + # === Pipes === + if 'Game.Instance?.liquidConduitFlow' in s: + annotations[i] = '🔶 UNVERIFIED: Game.Instance.liquidConduitFlow — may be different conduit system' + if 'Game.Instance?.gasConduitFlow' in s: + annotations[i] = '🔶 UNVERIFIED: Game.Instance.gasConduitFlow — may be different conduit system' + if 'flow.GetContents(' in s: + annotations[i] = '🔶 UNVERIFIED: ConduitFlow.GetContents() method and return type' + if 'contents.element' in s or 'contents.mass' in s or 'contents.temperature' in s: + annotations[i] = '🔶 UNVERIFIED: ConduitContents property names' + if 'Components.LiquidConduits' in s or 'Components.GasConduits' in s: + annotations[i] = '🔶 UNVERIFIED: Components.LiquidConduits / GasConduits may not exist' + if 'conduit.GetCell()' in s: + annotations[i] = '🔶 UNVERIFIED: Conduit.GetCell() method' + + # === Printing Pod === + if 'pod.IsReady()' in s or 'pod.CyclesUntilReady()' in s: + annotations[i] = '🔶 UNVERIFIED: PrintingPod methods IsReady/CyclesUntilReady — may differ' + if 'pod.GetCurrentOffers()' in s: + annotations[i] = '🔶 UNVERIFIED: PrintingPod.GetCurrentOffers() return type' + if 'offer.GetName()' in s: + annotations[i] = '🔶 UNVERIFIED: CarePackage/PrintingPodOffer.GetName() method' + if 'pod.SelectOffer(' in s: + annotations[i] = '🔶 UNVERIFIED: PrintingPod.SelectOffer(int) method' + if 'ImmuneSystemMonitor.Instance' in s and ('IsReadyToPrint' in s or 'GetCyclesUntilNextPrint' in s): + annotations[i] = '🔶 UNVERIFIED: ImmuneSystemMonitor methods may not exist' + + # === Door === + if 'door.Lock()' in s or 'door.Unlock()' in s: + annotations[i] = '🔶 UNVERIFIED: Door.Lock()/Unlock() methods may not exist' + + # === Operational/Toggle === + if 'oper.SetFlag(Operational.ActiveFlag,' in s: + annotations[i] = '🔶 UNVERIFIED: Operational.SetFlag signature — may need different approach' + + # === Storage === + if 'storage.DropAll(' in s: + annotations[i] = '🔶 UNVERIFIED: Storage.DropAll() parameters may differ' + + # === Camera === + if 'CameraController.Instance' in s and 'SetPosition' not in s: + annotations[i] = '🔶 UNVERIFIED: CameraController.Instance may not be the correct singleton' + if 'Camera.main?.orthographicSize' in s: + annotations[i] = '🔶 UNVERIFIED: Camera.main.orthographicSize setter may not work in ONI' + if 'cam.transform.position' in s and '= new Vector3' in s: + annotations[i] = '🔶 UNVERIFIED: Setting camera transform.position directly may not work' + + # === Screenshot === + if 'ScreenCapture.CaptureScreenshot' in s: + annotations[i] = '🔶 UNVERIFIED: ScreenCapture may not be available in ONI Unity version' + + # === Save/Load === + if 'SaveLoader.Save(' in s or 'SaveLoader.Load(' in s: + annotations[i] = '🔶 UNVERIFIED: SaveLoader.Save/Load method signatures' + if 'SaveLoader.GetActiveSaveFilePath()' in s: + annotations[i] = '🔶 UNVERIFIED: SaveLoader.GetActiveSaveFilePath() may not exist' + + # === Research === + if 'Research.Instance?.GetActiveResearchTechnologies' in s: + annotations[i] = '🔶 UNVERIFIED: Research.GetActiveResearchTechnologies() method' + if 'Research.Instance?.QueueResearch(' in s: + annotations[i] = '🔶 UNVERIFIED: Research.QueueResearch(Tech) method' + if 'Research.Instance?.CancelResearch(' in s: + annotations[i] = '🔶 UNVERIFIED: Research.CancelResearch(Tech) method' + if 'tech.pointsForCompletion' in s: + annotations[i] = '🔶 UNVERIFIED: Tech.pointsForCompletion property' + + # === Overlay === + if 'simOverlayManager' in s: + annotations[i] = '🔶 UNVERIFIED: Game.Instance.simOverlayManager may not exist' + if 'currentOverlay' in s: + annotations[i] = '🔶 UNVERIFIED: currentOverlay.ToString() may not yield expected overlay names' + + # === Buildings === + if 'Assets.BuildingDefs' in s and 'GetBuildingDef' not in s: + annotations[i] = '🔶 UNVERIFIED: Assets.BuildingDefs may not be a collection' + + # === Grid === + if 'Grid.Germs' in s: + annotations[i] = '🔶 UNVERIFIED: Grid.Germs API — may not exist or have different type' + + # === DTO class === + if 'public int? x2' in s or 'public int? y2' in s: + annotations[i] = '🔶 UNVERIFIED: Nullable parameters may not serialize correctly' + + # === Buildings detail === + if 'health?.GetHealth()' in s: + annotations[i] = '🔶 UNVERIFIED: Health component GetHealth()/GetMaxHealth() methods' + + # === Sensor === + if 'AtmoSensor' in s and '?.threshold' in s: + annotations[i] = '🔶 UNVERIFIED: AtmoSensor/ThermoSensor/HydroSensor threshold property' + +# Apply annotations — add comment after the line +annotated = 0 +for lineno in sorted(annotations.keys(), reverse=True): + idx = lineno - 1 + comment = ' // ' + annotations[lineno] + lines[idx] = lines[idx] + comment + annotated += 1 + +with open('mod/ONIAgentBridge.cs', 'w') as f: + f.write('\n'.join(lines)) + +print(f"Annotated {annotated} lines with verification markers")