Maps are editor-built scenes: [Tool] Playground/Crag, headless rebuild for agents
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>
This commit is contained in:
1 parent
3e300c7f04
commit
df7a2c5a89
17 files changed
+6863
-65
No files matched your search
@@ -0,0 +1,68 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user