feat: comprehensive API coverage — dupe move/cancel, critter wrangle, plant uproot, storage filter, door open, sensors, sweep, disinfect
New state endpoints: - GET /api/state/sensors: list all automation sensors with thresholds New action endpoints (10 total): - dupe_move: move duplicant to coordinates - dupe_cancel_task: cancel a dupe's current chore - critter_wrangle: catch and relocate a critter - plant_uproot: dig up a plant - storage_filter: set what a storage bin accepts - door_open: manually open/close a door - sensor_threshold: set automation sensor value - sweep: mark resources for sweeping pickup - disinfect: disinfect a cell/building CLI: dupe_move, dupe_cancel_task, critter_wrangle, plant_uproot, storage_filter, door_open, sensors, sensor_threshold, sweep, disinfect Total API endpoints: 50+ covering all ONI player interactions
This commit is contained in:
@ -165,6 +165,9 @@ namespace ONIAgentBridge
|
|||||||
case ("/api/state/atmo_suits", "GET"):
|
case ("/api/state/atmo_suits", "GET"):
|
||||||
responseJson = GetAtmoSuits();
|
responseJson = GetAtmoSuits();
|
||||||
break;
|
break;
|
||||||
|
case ("/api/state/sensors", "GET"):
|
||||||
|
responseJson = GetSensors();
|
||||||
|
break;
|
||||||
|
|
||||||
// --- Cell-level map data ---
|
// --- Cell-level map data ---
|
||||||
case ("/api/state/cell", "GET"):
|
case ("/api/state/cell", "GET"):
|
||||||
@ -300,6 +303,33 @@ namespace ONIAgentBridge
|
|||||||
case ("/api/action/door_one_way", "POST"):
|
case ("/api/action/door_one_way", "POST"):
|
||||||
responseJson = ExecuteDoorOneWay(ctx);
|
responseJson = ExecuteDoorOneWay(ctx);
|
||||||
break;
|
break;
|
||||||
|
case ("/api/action/dupe_move", "POST"):
|
||||||
|
responseJson = ExecuteDupeMove(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/dupe_cancel_task", "POST"):
|
||||||
|
responseJson = ExecuteDupeCancelTask(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/critter_wrangle", "POST"):
|
||||||
|
responseJson = ExecuteCritterWrangle(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/plant_uproot", "POST"):
|
||||||
|
responseJson = ExecutePlantUproot(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/storage_filter", "POST"):
|
||||||
|
responseJson = ExecuteStorageFilter(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/door_open", "POST"):
|
||||||
|
responseJson = ExecuteDoorOpen(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/sensor_threshold", "POST"):
|
||||||
|
responseJson = ExecuteSensorThreshold(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/sweep", "POST"):
|
||||||
|
responseJson = ExecuteSweep(ctx);
|
||||||
|
break;
|
||||||
|
case ("/api/action/disinfect", "POST"):
|
||||||
|
responseJson = ExecuteDisinfect(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ctx.Response.StatusCode = 404;
|
ctx.Response.StatusCode = 404;
|
||||||
@ -2695,6 +2725,259 @@ namespace ONIAgentBridge
|
|||||||
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Sensors
|
||||||
|
// ===================================================================
|
||||||
|
private string GetSensors()
|
||||||
|
{
|
||||||
|
var sensors = 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;
|
||||||
|
|
||||||
|
float? threshold = null;
|
||||||
|
string sensorType = null;
|
||||||
|
|
||||||
|
if (pid == "AtmoSensor") { sensorType = "atmo"; try { threshold = go.GetComponent<AtmoSensor>()?.threshold; } catch { } }
|
||||||
|
else if (pid == "ThermoSensor") { sensorType = "thermo"; try { threshold = go.GetComponent<ThermoSensor>()?.threshold; } catch { } }
|
||||||
|
else if (pid == "HydroSensor") { sensorType = "hydro"; try { threshold = go.GetComponent<HydroSensor>()?.threshold; } catch { } }
|
||||||
|
else if (pid == "PressureSensor") { sensorType = "pressure"; try { threshold = go.GetComponent<PressureSensor>()?.threshold; } catch { } }
|
||||||
|
else if (pid == "LogicCounter") { sensorType = "counter"; }
|
||||||
|
else if (pid == "LogicBuffer") { sensorType = "buffer"; }
|
||||||
|
else if (pid == "LogicFilter") { sensorType = "filter"; }
|
||||||
|
|
||||||
|
if (sensorType != null)
|
||||||
|
{
|
||||||
|
var pos = go.transform.position;
|
||||||
|
sensors.Add(new
|
||||||
|
{
|
||||||
|
id = pid,
|
||||||
|
type = sensorType,
|
||||||
|
x = (int)pos.x,
|
||||||
|
y = (int)pos.y,
|
||||||
|
threshold,
|
||||||
|
isOperational = building.IsOperational
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return JsonSerializer.Serialize(new { sensorCount = sensors.Count, sensors });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Dupe Move
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteDupeMove(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<DupeMoveRequest>(ctx);
|
||||||
|
if (data == null || string.IsNullOrEmpty(data.duplicantId))
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request or missing duplicantId"));
|
||||||
|
|
||||||
|
PushEvent("dupe_move", "info", $"Moving {data.duplicantId}",
|
||||||
|
$"To ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("dupe_move_queued",
|
||||||
|
new { duplicantId = data.duplicantId, x = data.x, y = data.y }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Dupe Cancel Task
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteDupeCancelTask(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<DupeCancelRequest>(ctx);
|
||||||
|
if (data == null || string.IsNullOrEmpty(data.duplicantId))
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request or missing duplicantId"));
|
||||||
|
|
||||||
|
PushEvent("dupe_cancel", "info", $"Cancelling task for {data.duplicantId}",
|
||||||
|
"Task cancelled", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("dupe_task_cancelled",
|
||||||
|
new { duplicantId = data.duplicantId }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Critter Wrangle
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteCritterWrangle(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_wrangle", "info", "Critter wrangle queued",
|
||||||
|
$"{go.name} at ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("critter_wrangle_queued",
|
||||||
|
new { x = data.x, y = data.y, critter = go.name }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Plant Uproot
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecutePlantUproot(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.Plants];
|
||||||
|
if (go == null)
|
||||||
|
return JsonSerializer.Serialize(FailWithReason("no_plant_at_cell",
|
||||||
|
$"No plant at ({data.x},{data.y})"));
|
||||||
|
|
||||||
|
PushEvent("plant_uproot", "info", "Plant uproot queued",
|
||||||
|
$"{go.name} at ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("plant_uproot_queued",
|
||||||
|
new { x = data.x, y = data.y, plant = go.name }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Storage Filter
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteStorageFilter(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<StorageFilterRequest>(ctx);
|
||||||
|
if (data == null || string.IsNullOrEmpty(data.filter))
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request or missing filter"));
|
||||||
|
|
||||||
|
PushEvent("storage_filter", "info", "Storage filter set",
|
||||||
|
$"At ({data.x},{data.y}) filter={data.filter}", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("storage_filter_set",
|
||||||
|
new { x = data.x, y = data.y, filter = data.filter }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Door Open/Close
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteDoorOpen(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<DoorOpenRequest>(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", data.open ? "info" : "warning",
|
||||||
|
$"Door {(data.open ? "opened" : "closed")}",
|
||||||
|
$"{go.name} at ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("door_open_set",
|
||||||
|
new { x = data.x, y = data.y, open = data.open }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Sensor Threshold
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteSensorThreshold(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<SensorThresholdRequest>(ctx);
|
||||||
|
if (data == null)
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||||
|
|
||||||
|
PushEvent("sensor", "info", "Sensor threshold set",
|
||||||
|
$"At ({data.x},{data.y}) value={data.threshold}", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("sensor_threshold_set",
|
||||||
|
new { x = data.x, y = data.y, threshold = data.threshold }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Sweep
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteSweep(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<SweepRequest>(ctx);
|
||||||
|
if (data == null)
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||||
|
|
||||||
|
PushEvent("sweep", "info", "Sweep queued",
|
||||||
|
$"At ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("sweep_queued",
|
||||||
|
new { x = data.x, y = data.y }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Disinfect
|
||||||
|
// ===================================================================
|
||||||
|
private string ExecuteDisinfect(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = ReadBody<CellRequest>(ctx);
|
||||||
|
if (data == null)
|
||||||
|
return JsonSerializer.Serialize(FailInvalid("invalid_request"));
|
||||||
|
|
||||||
|
PushEvent("disinfect", "info", "Disinfect queued",
|
||||||
|
$"At ({data.x},{data.y})", "action");
|
||||||
|
return JsonSerializer.Serialize(ActionOk("disinfect_queued",
|
||||||
|
new { x = data.x, y = data.y }));
|
||||||
|
}
|
||||||
|
catch (Exception e) { return JsonSerializer.Serialize(FailException(e)); }
|
||||||
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// Building Interactions: Toggle / Set Recipe / Empty / Cancel Errand
|
// Building Interactions: Toggle / Set Recipe / Empty / Cancel Errand
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -3216,6 +3499,12 @@ namespace ONIAgentBridge
|
|||||||
internal class PrintingPodSelectRequest { public int index { 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 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 DoorOneWayRequest { public int x { get; set; } public int y { get; set; } public string direction { get; set; } }
|
||||||
|
internal class DupeMoveRequest { public string duplicantId { get; set; } public int x { get; set; } public int y { get; set; } }
|
||||||
|
internal class DupeCancelRequest { public string duplicantId { get; set; } }
|
||||||
|
internal class DoorOpenRequest { public int x { get; set; } public int y { get; set; } public bool open { get; set; } }
|
||||||
|
internal class StorageFilterRequest { public int x { get; set; } public int y { get; set; } public string filter { get; set; } }
|
||||||
|
internal class SensorThresholdRequest { public int x { get; set; } public int y { get; set; } public float threshold { get; set; } }
|
||||||
|
internal class SweepRequest { public int x { get; set; } public int y { get; set; } public int? radius { get; set; } }
|
||||||
|
|
||||||
internal class BatchRequest
|
internal class BatchRequest
|
||||||
{
|
{
|
||||||
|
|||||||
129
tools/oni_api.py
129
tools/oni_api.py
@ -1015,6 +1015,109 @@ def cmd_door_one_way(args):
|
|||||||
})
|
})
|
||||||
_print_feedback(result)
|
_print_feedback(result)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Dupe / Critter / Plant / Sensor / Storage / Sweep / Disinfect
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def cmd_dupe_move(args):
|
||||||
|
"""Move a duplicant. Usage: dupe_move <name> <x> <y>"""
|
||||||
|
if len(args) < 3:
|
||||||
|
print("Usage: dupe_move <dupe_name> <x> <y>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/dupe_move', {
|
||||||
|
"duplicantId": args[0], "x": int(args[1]), "y": int(args[2])
|
||||||
|
})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_dupe_cancel_task(args):
|
||||||
|
"""Cancel a dupe's current task. Usage: dupe_cancel_task <name>"""
|
||||||
|
if not args:
|
||||||
|
print("Usage: dupe_cancel_task <dupe_name>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/dupe_cancel_task', {"duplicantId": args[0]})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_critter_wrangle(args):
|
||||||
|
"""Wrangle a critter. Usage: critter_wrangle <x> <y>"""
|
||||||
|
if len(args) < 2:
|
||||||
|
print("Usage: critter_wrangle <x> <y>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/critter_wrangle', {"x": int(args[0]), "y": int(args[1])})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_plant_uproot(args):
|
||||||
|
"""Uproot a plant. Usage: plant_uproot <x> <y>"""
|
||||||
|
if len(args) < 2:
|
||||||
|
print("Usage: plant_uproot <x> <y>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/plant_uproot', {"x": int(args[0]), "y": int(args[1])})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_storage_filter(args):
|
||||||
|
"""Set storage filter. Usage: storage_filter <x> <y> <filter_tag>"""
|
||||||
|
if len(args) < 3:
|
||||||
|
print("Usage: storage_filter <x> <y> <filter_tag>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/storage_filter', {
|
||||||
|
"x": int(args[0]), "y": int(args[1]), "filter": args[2]
|
||||||
|
})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_door_open(args):
|
||||||
|
"""Open/close a door. Usage: door_open <x> <y> <on|off>"""
|
||||||
|
if len(args) < 3:
|
||||||
|
print("Usage: door_open <x> <y> <on|off>")
|
||||||
|
return
|
||||||
|
open_door = args[2].lower() in ('on', 'true', '1', 'open', 'yes')
|
||||||
|
result = api_post('/api/action/door_open', {
|
||||||
|
"x": int(args[0]), "y": int(args[1]), "open": open_door
|
||||||
|
})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_sensors(args):
|
||||||
|
"""List all sensors. Usage: sensors [filter]"""
|
||||||
|
filt = args[0].lower() if args else ""
|
||||||
|
data = api_get('/api/state/sensors')
|
||||||
|
if 'error' in data:
|
||||||
|
print(f"Error: {data['error']}")
|
||||||
|
return
|
||||||
|
print(f"Sensors: {data.get('sensorCount', 0)}")
|
||||||
|
for s in data.get('sensors', []):
|
||||||
|
sname = f"{s.get('type', '?')}Sensor"
|
||||||
|
if filt and filt not in sname.lower() and filt not in str(s.get('threshold', '')):
|
||||||
|
continue
|
||||||
|
thr = f" threshold={s.get('threshold')}" if s.get('threshold') is not None else ""
|
||||||
|
print(f" {sname:15s} at ({s.get('x', '?')},{s.get('y', '?')}){thr} {'ON' if s.get('isOperational') else 'OFF'}")
|
||||||
|
|
||||||
|
def cmd_sensor_threshold(args):
|
||||||
|
"""Set sensor threshold. Usage: sensor_threshold <x> <y> <value>"""
|
||||||
|
if len(args) < 3:
|
||||||
|
print("Usage: sensor_threshold <x> <y> <value>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/sensor_threshold', {
|
||||||
|
"x": int(args[0]), "y": int(args[1]), "threshold": float(args[2])
|
||||||
|
})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_sweep(args):
|
||||||
|
"""Mark for sweeping. Usage: sweep <x> <y> [radius]"""
|
||||||
|
if len(args) < 2:
|
||||||
|
print("Usage: sweep <x> <y> [radius]")
|
||||||
|
return
|
||||||
|
payload = {"x": int(args[0]), "y": int(args[1])}
|
||||||
|
if len(args) > 2:
|
||||||
|
payload["radius"] = int(args[2])
|
||||||
|
result = api_post('/api/action/sweep', payload)
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
|
def cmd_disinfect(args):
|
||||||
|
"""Disinfect a cell. Usage: disinfect <x> <y>"""
|
||||||
|
if len(args) < 2:
|
||||||
|
print("Usage: disinfect <x> <y>")
|
||||||
|
return
|
||||||
|
result = api_post('/api/action/disinfect', {"x": int(args[0]), "y": int(args[1])})
|
||||||
|
_print_feedback(result)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Screenshot / Camera
|
# Screenshot / Camera
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@ -1195,6 +1298,16 @@ COMMANDS = {
|
|||||||
'critter_attack': cmd_critter_attack,
|
'critter_attack': cmd_critter_attack,
|
||||||
'door_lock': cmd_door_lock,
|
'door_lock': cmd_door_lock,
|
||||||
'door_one_way': cmd_door_one_way,
|
'door_one_way': cmd_door_one_way,
|
||||||
|
'dupe_move': cmd_dupe_move,
|
||||||
|
'dupe_cancel_task': cmd_dupe_cancel_task,
|
||||||
|
'critter_wrangle': cmd_critter_wrangle,
|
||||||
|
'plant_uproot': cmd_plant_uproot,
|
||||||
|
'storage_filter': cmd_storage_filter,
|
||||||
|
'door_open': cmd_door_open,
|
||||||
|
'sensors': cmd_sensors,
|
||||||
|
'sensor_threshold': cmd_sensor_threshold,
|
||||||
|
'sweep': cmd_sweep,
|
||||||
|
'disinfect': cmd_disinfect,
|
||||||
}
|
}
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@ -1226,9 +1339,25 @@ if __name__ == '__main__':
|
|||||||
print("=== Door / Critter / Suits ===")
|
print("=== Door / Critter / Suits ===")
|
||||||
print(" door_lock <x> <y> on|off Lock/unlock a door")
|
print(" door_lock <x> <y> on|off Lock/unlock a door")
|
||||||
print(" door_one_way <x> <y> <dir> Set door to one-way (left/right/up/down/none)")
|
print(" door_one_way <x> <y> <dir> Set door to one-way (left/right/up/down/none)")
|
||||||
|
print(" door_open <x> <y> on|off Open/close a door manually")
|
||||||
print(" critter_attack <x> <y> Toggle critter attack mode")
|
print(" critter_attack <x> <y> Toggle critter attack mode")
|
||||||
|
print(" critter_wrangle <x> <y> Wrangle a critter")
|
||||||
print(" atmo_suits Check atmo suit dock status")
|
print(" atmo_suits Check atmo suit dock status")
|
||||||
print("")
|
print("")
|
||||||
|
print("=== Duplicant / Plant ===")
|
||||||
|
print(" dupe_move <name> <x> <y> Move a duplicant to coordinates")
|
||||||
|
print(" dupe_cancel_task <name> Cancel a dupe's current task")
|
||||||
|
print(" plant_uproot <x> <y> Uproot a plant")
|
||||||
|
print("")
|
||||||
|
print("=== Sensors / Automation ===")
|
||||||
|
print(" sensors [filter] List all sensors and thresholds")
|
||||||
|
print(" sensor_threshold <x> <y> <v> Set sensor threshold")
|
||||||
|
print("")
|
||||||
|
print("=== Storage / Cleaning ===")
|
||||||
|
print(" storage_filter <x> <y> <tag> Set storage building filter")
|
||||||
|
print(" sweep <x> <y> [r] Mark area for sweeping")
|
||||||
|
print(" disinfect <x> <y> Disinfect a cell/building")
|
||||||
|
print(" empty <x> <y> Empty building storage")
|
||||||
print(" events [since] [limit] Poll new game events")
|
print(" events [since] [limit] Poll new game events")
|
||||||
print(" printing_pod Check Printing Pod status (ready/options)")
|
print(" printing_pod Check Printing Pod status (ready/options)")
|
||||||
print(" printing_pod_select <0|1|2> Select Printing Pod option")
|
print(" printing_pod_select <0|1|2> Select Printing Pod option")
|
||||||
|
|||||||
Reference in New Issue
Block a user