- Implement all Mod API endpoints (buildings, research, geysers, alerts, critters, deconstruct, prioritize, research, schedule, wardrobe) - Enhance Python tools with comprehensive CLI, analysis (O2/food/power/temp/water), and 7 blueprints (SPOM, toilet, ranch, farm, cooling, bedroom) - Add utility scripts: auto_repair, auto_analyze, watch mode, setup - Write Agent-Mod integration constraints and development guide - Create skills directory with ONI agent skill definition
164 lines
5.8 KiB
Python
164 lines
5.8 KiB
Python
import json
|
|
import sys
|
|
from oni_api import api_post
|
|
|
|
BLUEPRINTS = {
|
|
'spom': {
|
|
'name': 'SPOM (Self-Powered Oxygen Module)',
|
|
'description': 'Standard Rodriguez SPOM: electrolyzer + hydrogen generators',
|
|
'size': {'width': 8, 'height': 6},
|
|
'dig': {'x': -1, 'y': -1, 'width': 10, 'height': 8},
|
|
'buildings': [
|
|
{'id': 'Electrolyzer', 'x': 3, 'y': 2},
|
|
{'id': 'GasPump', 'x': 1, 'y': 2},
|
|
{'id': 'GasPump', 'x': 5, 'y': 2},
|
|
{'id': 'HydrogenGenerator', 'x': 1, 'y': 0},
|
|
{'id': 'HydrogenGenerator', 'x': 4, 'y': 0},
|
|
{'id': 'GasFilter', 'x': 3, 'y': 0},
|
|
],
|
|
},
|
|
'spom_mini': {
|
|
'name': 'Mini SPOM',
|
|
'description': 'Compact electrolyzer + 1 hydrogen generator for early game',
|
|
'size': {'width': 5, 'height': 4},
|
|
'dig': {'x': -1, 'y': -1, 'width': 7, 'height': 6},
|
|
'buildings': [
|
|
{'id': 'Electrolyzer', 'x': 2, 'y': 1},
|
|
{'id': 'GasPump', 'x': 1, 'y': 1},
|
|
{'id': 'HydrogenGenerator', 'x': 2, 'y': 0},
|
|
],
|
|
},
|
|
'toilet_loop': {
|
|
'name': 'Bathroom Water Loop',
|
|
'description': 'Lavatory -> Water Purifier -> Lavatory closed loop',
|
|
'size': {'width': 8, 'height': 4},
|
|
'dig': {'x': -1, 'y': -1, 'width': 10, 'height': 6},
|
|
'buildings': [
|
|
{'id': 'Lavatory', 'x': 1, 'y': 1},
|
|
{'id': 'Lavatory', 'x': 3, 'y': 1},
|
|
{'id': 'WaterPurifier', 'x': 6, 'y': 1},
|
|
{'id': 'LiquidPump', 'x': 6, 'y': 2},
|
|
],
|
|
},
|
|
'ranch_hatch': {
|
|
'name': 'Hatch Ranch',
|
|
'description': 'Standard hatch ranching module with feeder and incubator',
|
|
'size': {'width': 10, 'height': 6},
|
|
'dig': {'x': -1, 'y': -1, 'width': 12, 'height': 8},
|
|
'buildings': [
|
|
{'id': 'RanchStation', 'x': 1, 'y': 1},
|
|
{'id': 'Incubator', 'x': 4, 'y': 1},
|
|
{'id': 'StorageLocker', 'x': 8, 'y': 1},
|
|
],
|
|
},
|
|
'farm_mealwood': {
|
|
'name': 'Mealwood Farm',
|
|
'description': 'Basic mealwood farm: 5 planter boxes + storage',
|
|
'size': {'width': 6, 'height': 4},
|
|
'dig': {'x': -1, 'y': -1, 'width': 8, 'height': 6},
|
|
'buildings': [
|
|
{'id': 'PlanterBox', 'x': 1, 'y': 1},
|
|
{'id': 'PlanterBox', 'x': 3, 'y': 1},
|
|
{'id': 'PlanterBox', 'x': 5, 'y': 1},
|
|
{'id': 'PlanterBox', 'x': 1, 'y': 3},
|
|
{'id': 'PlanterBox', 'x': 3, 'y': 3},
|
|
{'id': 'StorageLocker', 'x': 5, 'y': 3},
|
|
],
|
|
},
|
|
'cooling': {
|
|
'name': 'Steam Turbine Cooler',
|
|
'description': 'Liquid cooling loop with steam turbine + aquatuner',
|
|
'size': {'width': 8, 'height': 6},
|
|
'dig': {'x': -1, 'y': -1, 'width': 10, 'height': 8},
|
|
'buildings': [
|
|
{'id': 'SteamTurbine', 'x': 1, 'y': 4},
|
|
{'id': 'SteamTurbine', 'x': 5, 'y': 4},
|
|
{'id': 'Aquatuner', 'x': 2, 'y': 1},
|
|
{'id': 'LiquidPump', 'x': 5, 'y': 1},
|
|
],
|
|
},
|
|
'bedroom': {
|
|
'name': 'Barracks / Bedroom',
|
|
'description': 'Basic bedroom module with cots and decorations',
|
|
'size': {'width': 8, 'height': 4},
|
|
'dig': {'x': -1, 'y': -1, 'width': 10, 'height': 6},
|
|
'buildings': [
|
|
{'id': 'Bed', 'x': 1, 'y': 1},
|
|
{'id': 'Bed', 'x': 3, 'y': 1},
|
|
{'id': 'Bed', 'x': 5, 'y': 1},
|
|
{'id': 'LadderBed', 'x': 1, 'y': 3},
|
|
{'id': 'LadderBed', 'x': 3, 'y': 3},
|
|
{'id': 'FlowerVase', 'x': 6, 'y': 1},
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
def list_blueprints():
|
|
print(f"Available Blueprints ({len(BLUEPRINTS)}):")
|
|
print("=" * 60)
|
|
for key, bp in BLUEPRINTS.items():
|
|
print(f" {key:16s} {bp['name']:28s} {bp['size']['width']}x{bp['size']['height']}")
|
|
print(f" {'':16s} {bp['description']}")
|
|
print()
|
|
|
|
|
|
def apply_blueprint(name, origin_x, origin_y):
|
|
bp = BLUEPRINTS.get(name)
|
|
if not bp:
|
|
print(f"[!] Blueprint '{name}' not found")
|
|
print(f" Use 'list' to see available blueprints")
|
|
return False
|
|
|
|
print(f"Applying blueprint: {bp['name']}")
|
|
print(f" Origin: ({origin_x}, {origin_y})")
|
|
print(f" Size: {bp['size']['width']} x {bp['size']['height']}")
|
|
print()
|
|
|
|
results = []
|
|
|
|
dig = bp.get('dig', {'x': -1, 'y': -1, 'width': bp['size']['width'] + 2, 'height': bp['size']['height'] + 2})
|
|
dig_result = api_post('/api/action/dig', {
|
|
'x': origin_x + dig['x'],
|
|
'y': origin_y + dig['y'],
|
|
'width': dig['width'],
|
|
'height': dig['height'],
|
|
})
|
|
status = 'OK' if 'error' not in dig_result else dig_result.get('error', 'fail')
|
|
print(f" [Dig] area ({dig['width']}x{dig['height']}): {status}")
|
|
|
|
for b in bp['buildings']:
|
|
x = origin_x + b['x']
|
|
y = origin_y + b['y']
|
|
result = api_post('/api/action/build', {
|
|
'buildingId': b['id'],
|
|
'x': x,
|
|
'y': y,
|
|
})
|
|
ok = 'error' not in result
|
|
results.append({'building': b['id'], 'x': x, 'y': y, 'ok': ok})
|
|
status = 'OK' if ok else result.get('error', 'fail')
|
|
print(f" [Build] {b['id']:20s} at ({x:3d}, {y:3d}): {status}")
|
|
|
|
ok_count = sum(1 for r in results if r['ok'])
|
|
print()
|
|
print(f" Result: {ok_count}/{len(results)} buildings placed")
|
|
return ok_count == len(results)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cmd = sys.argv[1] if len(sys.argv) > 1 else 'list'
|
|
|
|
if cmd == 'list':
|
|
list_blueprints()
|
|
elif cmd == 'build':
|
|
if len(sys.argv) < 4:
|
|
print("Usage: python oni_builder.py build <blueprint_name> <origin_x> <origin_y>")
|
|
print()
|
|
list_blueprints()
|
|
sys.exit(1)
|
|
success = apply_blueprint(sys.argv[2], int(sys.argv[3]), int(sys.argv[4]))
|
|
sys.exit(0 if success else 1)
|
|
else:
|
|
print("Usage: python oni_builder.py <list|build>")
|