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>
63 lines
3.0 KiB
C#
63 lines
3.0 KiB
C#
using Godot;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
// Dumps the map layout (type, transform, shape/mesh size, groups) sorted, for before/after comparison.
|
|
// godot-mono --headless --path . tools/map_dump.tscn -- out=<file>
|
|
public partial class MapDump : Node3D
|
|
{
|
|
private int _frame;
|
|
|
|
public override void _Ready()
|
|
{
|
|
foreach (string path in RebuildMaps.Maps)
|
|
AddChild(GD.Load<PackedScene>(path).Instantiate());
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if (++_frame < 3)
|
|
return;
|
|
string outPath = "/tmp/claude-1000/maps/dump.txt";
|
|
foreach (string a in OS.GetCmdlineUserArgs())
|
|
if (a.StartsWith("out="))
|
|
outPath = a[4..];
|
|
var lines = new List<string>();
|
|
foreach (Node map in GetChildren())
|
|
Walk(map, map.GetType().Name, lines);
|
|
lines.Sort(System.StringComparer.Ordinal);
|
|
System.IO.File.WriteAllLines(outPath, lines);
|
|
GD.Print($"MAPDUMP: {lines.Count} nodes → {outPath}");
|
|
GetTree().Quit();
|
|
}
|
|
|
|
private static string R(Vector3 v) => $"({v.X:F3},{v.Y:F3},{v.Z:F3})";
|
|
|
|
private void Walk(Node n, string map, List<string> lines)
|
|
{
|
|
foreach (Node ch in n.GetChildren())
|
|
{
|
|
string info = ch.GetClass();
|
|
if (ch is Node3D n3)
|
|
{
|
|
Transform3D t = n3.GlobalTransform;
|
|
info += $" o{R(t.Origin)} x{R(t.Basis.X)} y{R(t.Basis.Y)}";
|
|
}
|
|
if (ch is CollisionShape3D cs && cs.Shape is BoxShape3D bs) info += $" box{R(bs.Size)}";
|
|
if (ch is CollisionShape3D cc && cc.Shape is CylinderShape3D cy) info += $" cyl{cy.Radius:F3}/{cy.Height:F3}";
|
|
if (ch is CollisionShape3D cp && cp.Shape is SphereShape3D sp) info += $" sph{sp.Radius:F3}";
|
|
if (ch is MeshInstance3D mi && mi.GetSurfaceOverrideMaterial(0) is StandardMaterial3D m) info += $" col{m.AlbedoColor.ToHtml()} sh{(int)mi.CastShadow}";
|
|
if (ch is Label3D l) info += $" text[{l.Text}] px{l.PixelSize:F4}";
|
|
if (ch is CollisionObject3D co) info += $" L{co.CollisionLayer}/{co.CollisionMask}";
|
|
if (ch is RigidBody3D rb) info += $" m{rb.Mass:F2} f{rb.PhysicsMaterialOverride?.Friction:F2}";
|
|
var groups = ch.GetGroups().Select(g => g.ToString()).Where(g => !g.StartsWith("_")).OrderBy(g => g);
|
|
info += " g[" + string.Join(",", groups) + "]";
|
|
if (ch is Joint3D j) info += $" joint {j.GetNodeOrNull(j.NodeA)?.GetClass()}@{R((j.GetNodeOrNull(j.NodeA) as Node3D)?.GlobalPosition ?? Vector3.Zero)}-{j.GetNodeOrNull(j.NodeB)?.GetClass()}@{R((j.GetNodeOrNull(j.NodeB) as Node3D)?.GlobalPosition ?? Vector3.Zero)}";
|
|
if (ch.GetType().Name == "TeleportMarker" || ch.SceneFilePath != "") info += $" scene[{ch.SceneFilePath}] label[{ch.Get("MarkerLabel")}]";
|
|
lines.Add($"{map}: {info}");
|
|
if (ch.SceneFilePath == "")
|
|
Walk(ch, map, lines);
|
|
}
|
|
}
|
|
}
|