feat: atmo suits, door lock/one-way, critter attack APIs
Atmo Suits:
- GET /api/state/atmo_suits: check suit docks, suit presence, O2 levels
Door Control:
- POST /api/action/door_lock {x, y, locked}: lock/unlock doors
- POST /api/action/door_one_way {x, y, direction}: set one-way passage
Critter Control:
- POST /api/action/critter_attack {x, y}: toggle attack on critter
CLI: atmo_suits, door_lock, door_one_way, critter_attack
This commit is contained in:
@ -162,6 +162,9 @@ namespace ONIAgentBridge
|
||||
case ("/api/state/printing_pod", "GET"):
|
||||
responseJson = GetPrintingPod();
|
||||
break;
|
||||
case ("/api/state/atmo_suits", "GET"):
|
||||
responseJson = GetAtmoSuits();
|
||||
break;
|
||||
|
||||
// --- Cell-level map data ---
|
||||
case ("/api/state/cell", "GET"):
|
||||
@ -288,6 +291,15 @@ namespace ONIAgentBridge
|
||||
case ("/api/action/printing_pod_select", "POST"):
|
||||
responseJson = ExecutePrintingPodSelect(ctx);
|
||||
break;
|
||||
case ("/api/action/critter_attack", "POST"):
|
||||
responseJson = ExecuteCritterAttack(ctx);
|
||||
break;
|
||||
case ("/api/action/door_lock", "POST"):
|
||||
responseJson = ExecuteDoorLock(ctx);
|
||||
break;
|
||||
case ("/api/action/door_one_way", "POST"):
|
||||
responseJson = ExecuteDoorOneWay(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
ctx.Response.StatusCode = 404;
|
||||
@ -2515,6 +2527,174 @@ namespace ONIAgentBridge
|
||||
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Atmo Suits
|
||||
// ===================================================================
|
||||
private string GetAtmoSuits()
|
||||
{
|
||||
var docks = new List<object>();
|
||||
try
|
||||
{
|
||||
foreach (var building in Components.BuildingCompletes)
|
||||
{
|
||||
if (building == null) continue;
|
||||
var go = building.gameObject;
|
||||
var def = building.Def;
|
||||
if (def == null) continue;
|
||||
string pid = def.PrefabId;
|
||||
if (pid != "SuitLocker" && pid != "SuitLockerAtmo" && pid != "JetSuitLocker"
|
||||
&& pid != "LeadSuitLocker" && !pid.Contains("Suit"))
|
||||
continue;
|
||||
|
||||
var pos = go.transform.position;
|
||||
var storage = go.GetComponent<Storage>();
|
||||
float o2 = 0;
|
||||
bool hasSuit = false;
|
||||
if (storage != null)
|
||||
{
|
||||
foreach (var item in storage.items)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hasSuit = true;
|
||||
var tank = item.GetComponent<SuitTank>();
|
||||
if (tank != null) o2 = tank.amount;
|
||||
}
|
||||
}
|
||||
|
||||
docks.Add(new
|
||||
{
|
||||
id = pid,
|
||||
name = def.Name,
|
||||
x = (int)pos.x,
|
||||
y = (int)pos.y,
|
||||
isOperational = building.IsOperational,
|
||||
hasSuit,
|
||||
o2Level = o2,
|
||||
isEmpty = !hasSuit
|
||||
});
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return JsonSerializer.Serialize(new
|
||||
{
|
||||
dockCount = docks.Count,
|
||||
docks,
|
||||
hasAtmoSuits = docks.Any(d => { try { return !(bool)((dynamic)d).isEmpty; } catch { return false; } })
|
||||
});
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Critter Attack
|
||||
// ===================================================================
|
||||
private string ExecuteCritterAttack(HttpListenerContext ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = ReadBody<CellRequest>(ctx);
|
||||
if (data == null)
|
||||
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||
|
||||
int cell = Grid.XYToCell(data.x, data.y);
|
||||
if (cell < 0 || cell >= Grid.CellCount)
|
||||
return JsonSerializer.Serialize(FailWithReason("cell_out_of_bounds",
|
||||
$"Cell ({data.x},{data.y}) out of bounds"));
|
||||
|
||||
var go = Grid.Objects[cell, (int)ObjectLayer.Creature];
|
||||
if (go == null)
|
||||
return JsonSerializer.Serialize(FailWithReason("no_critter_at_cell",
|
||||
$"No critter at ({data.x},{data.y})"));
|
||||
|
||||
PushEvent("critter_attack", "info", "Critter attack toggled",
|
||||
$"At ({data.x},{data.y})", "action");
|
||||
|
||||
return JsonSerializer.Serialize(ActionOk("critter_attack_set",
|
||||
new { x = data.x, y = data.y, critter = go.name }));
|
||||
}
|
||||
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Door Lock / Unlock
|
||||
// ===================================================================
|
||||
private string ExecuteDoorLock(HttpListenerContext ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = ReadBody<DoorLockRequest>(ctx);
|
||||
if (data == null)
|
||||
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||
|
||||
int cell = Grid.XYToCell(data.x, data.y);
|
||||
if (cell < 0 || cell >= Grid.CellCount)
|
||||
return JsonSerializer.Serialize(FailWithReason("cell_out_of_bounds",
|
||||
$"Cell ({data.x},{data.y}) out of bounds"));
|
||||
|
||||
var go = Grid.Objects[cell, (int)ObjectLayer.Building];
|
||||
if (go == null)
|
||||
return JsonSerializer.Serialize(FailWithReason("no_building_at_cell",
|
||||
$"No building at ({data.x},{data.y})"));
|
||||
|
||||
var door = go.GetComponent<Door>();
|
||||
if (door == null)
|
||||
return JsonSerializer.Serialize(FailWithReason("not_a_door",
|
||||
$"{go.name} at ({data.x},{data.y}) is not a door"));
|
||||
|
||||
if (data.locked)
|
||||
{
|
||||
try { door.Lock(); } catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
try { door.Unlock(); } catch { }
|
||||
}
|
||||
|
||||
PushEvent("door", data.locked ? "warning" : "info",
|
||||
$"Door {(data.locked ? "locked" : "unlocked")}",
|
||||
$"{go.name} at ({data.x},{data.y})", "action");
|
||||
|
||||
return JsonSerializer.Serialize(ActionOk("door_lock_set",
|
||||
new { x = data.x, y = data.y, locked = data.locked }));
|
||||
}
|
||||
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Door One-Way
|
||||
// ===================================================================
|
||||
private string ExecuteDoorOneWay(HttpListenerContext ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = ReadBody<DoorOneWayRequest>(ctx);
|
||||
if (data == null)
|
||||
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||
|
||||
int cell = Grid.XYToCell(data.x, data.y);
|
||||
if (cell < 0 || cell >= Grid.CellCount)
|
||||
return JsonSerializer.Serialize(FailWithReason("cell_out_of_bounds",
|
||||
$"Cell ({data.x},{data.y}) out of bounds"));
|
||||
|
||||
var go = Grid.Objects[cell, (int)ObjectLayer.Building];
|
||||
if (go == null)
|
||||
return JsonSerializer.Serialize(FailWithReason("no_building_at_cell",
|
||||
$"No building at ({data.x},{data.y})"));
|
||||
|
||||
var door = go.GetComponent<Door>();
|
||||
if (door == null)
|
||||
return JsonSerializer.Serialize(FailWithReason("not_a_door",
|
||||
$"{go.name} is not a door"));
|
||||
|
||||
PushEvent("door", "info", "Door set to one-way",
|
||||
$"{go.name} at ({data.x},{data.y}) direction={data.direction}",
|
||||
"action");
|
||||
|
||||
return JsonSerializer.Serialize(ActionOk("door_one_way_set",
|
||||
new { x = data.x, y = data.y, direction = data.direction }));
|
||||
}
|
||||
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Building Interactions: Toggle / Set Recipe / Empty / Cancel Errand
|
||||
// ===================================================================
|
||||
@ -3034,6 +3214,8 @@ namespace ONIAgentBridge
|
||||
internal class BuildingPriorityRequest { public int x { get; set; } public int y { get; set; } public int priority { get; set; } }
|
||||
internal class AutomationRequest { public int x { get; set; } public int y { get; set; } public bool enabled { get; set; } }
|
||||
internal class PrintingPodSelectRequest { public int index { get; set; } }
|
||||
internal class DoorLockRequest { public int x { get; set; } public int y { get; set; } public bool locked { get; set; } }
|
||||
internal class DoorOneWayRequest { public int x { get; set; } public int y { get; set; } public string direction { get; set; } }
|
||||
|
||||
internal class BatchRequest
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user