scenes/maps/playground.tscn and crag.tscn are generated by the map scripts' Rebuild (inspector button, or godot-mono --headless --path . tools/rebuild_maps.tscn) and loaded as saved by the game, so hand edits stick. The crag route is saved as Marker3D nodes and crag_spike checks the saved scene. Layout verified identical to the code-built one (tools/map_dump.tscn). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
69 lines
2.3 KiB
C#
69 lines
2.3 KiB
C#
using Godot;
|
|
|
|
// Headless map rebuild for agents (same as pressing each map's "Rebuild" button in the editor and
|
|
// saving): loads each map scene, regenerates its children from code and saves it back.
|
|
// godot-mono --headless --path . tools/rebuild_maps.tscn [-- only=playground|crag]
|
|
// Prints "MAPS: rebuilt <path> (<n> nodes)" per map and "MAPS: done". Overwrites hand edits in those
|
|
// scenes — that's what Rebuild means.
|
|
public partial class RebuildMaps : Node
|
|
{
|
|
public static readonly string[] Maps = { "res://scenes/maps/playground.tscn", "res://scenes/maps/crag.tscn" };
|
|
|
|
public override void _Ready()
|
|
{
|
|
string only = null;
|
|
foreach (string a in OS.GetCmdlineUserArgs())
|
|
if (a.StartsWith("only="))
|
|
only = a[5..];
|
|
bool ok = true;
|
|
foreach (string path in Maps)
|
|
{
|
|
if (only != null && !path.Contains(only))
|
|
continue;
|
|
ok &= RebuildOne(path);
|
|
}
|
|
GD.Print(ok ? "MAPS: done" : "MAPS: FAILED");
|
|
GetTree().Quit(ok ? 0 : 1);
|
|
}
|
|
|
|
private bool RebuildOne(string path)
|
|
{
|
|
Node map = ResourceLoader.Load<PackedScene>(path, null, ResourceLoader.CacheMode.Ignore).Instantiate();
|
|
AddChild(map); // in the tree, so joint paths and globals resolve like in the editor
|
|
switch (map)
|
|
{
|
|
case Playground p:
|
|
p.Rebuild();
|
|
break;
|
|
case Crag c:
|
|
c.Rebuild();
|
|
break;
|
|
default:
|
|
GD.PushError($"MAPS: {path} root is not a map ({map.GetType().Name})");
|
|
return false;
|
|
}
|
|
RemoveChild(map);
|
|
PackedScene packed = new();
|
|
Error err = packed.Pack(map);
|
|
if (err == Error.Ok)
|
|
err = ResourceSaver.Save(packed, path);
|
|
int count = CountOwned(map, map);
|
|
map.Free();
|
|
if (err != Error.Ok)
|
|
{
|
|
GD.PushError($"MAPS: saving {path} failed: {err}");
|
|
return false;
|
|
}
|
|
GD.Print($"MAPS: rebuilt {path} ({count} nodes)");
|
|
return true;
|
|
}
|
|
|
|
private static int CountOwned(Node root, Node n)
|
|
{
|
|
int c = 0;
|
|
foreach (Node child in n.GetChildren())
|
|
c += (child.Owner == root ? 1 : 0) + CountOwned(root, child);
|
|
return c;
|
|
}
|
|
}
|