feat: complete ONI Agent project with full Mod API, Python toolchain, and development guide
- 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
This commit is contained in:
163
tools/oni_builder.py
Normal file
163
tools/oni_builder.py
Normal file
@ -0,0 +1,163 @@
|
||||
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>")
|
||||
Reference in New Issue
Block a user