extends SceneTree ## Identitäts-Vertrag, KOLLISION ALLER OBJEKTE (Military-Pack-Umstellung, ## 25.10.2026): JEDES Registry-Objekt läuft durch die Kollider-Bauer aller drei ## Projekte — ## A) Editor (KolliderBau.kollider) ## B) Client (SvmapWorld._collider) ## C) Server (SvmapLoader._object_body) ## und druckt je Objekt `IDENT k_=||` ## (Maßstab 1.7, damit scale-Fehler auffallen). Der Runner ## (run_kollision_alle_identitaet.sh) verlangt IDENTISCHE Zeilen in allen drei ## Projekten — Editor-Playtest, Quest-Client und Server kollidieren dann überall ## gleich (Trimesh, Verbund, Stamm, none). ## Das Skript liegt im EDITOR-Repo und wird je Projekt gefahren: ## godot4 --headless --path -s /tests/probe_kollision_alle_ident.gd ## Bewusst load() statt class_name (läuft in DREI Projekten). const MASSSTAB := 1.7 const PROJEKTE := { "ScopedVR Map Editor": "editor", "ScopedVR": "client", "ScopedVR Match-Server": "server", } func _initialize() -> void: var projekt := "" var fa := FileAccess.open("res://project.godot", FileAccess.READ) if fa != null: for zeile in fa.get_as_text().split("\n"): var t := zeile.strip_edges() if t.begins_with("config/name="): projekt = t.trim_prefix("config/name=").strip_edges().trim_prefix("\"").trim_suffix("\"") break var art: String = PROJEKTE.get(projekt, "") if art.is_empty(): printerr("IDENT FAIL: unbekanntes Projekt ", projekt) quit(1) return var lib_text := FileAccess.get_file_as_string("res://library/objects.json") var parsed: Variant = JSON.parse_string(lib_text) if not (parsed is Dictionary): printerr("IDENT FAIL: library/objects.json unlesbar") quit(1) return var objs: Dictionary = (parsed as Dictionary).get("objects", {}) var skript: Script = null var instanz: Object = null match art: "editor": skript = load("res://core/svmap/kollider_bau.gd") "client": skript = load("res://scripts/world/svmap_world.gd") instanz = skript.new() "server": skript = load("res://src/maps/svmap_loader.gd") if skript == null: printerr("IDENT FAIL: Loader-Skript nicht ladbar in ", projekt) quit(1) return var oids: Array = objs.keys() oids.sort() for oid in oids: var col: Dictionary = (objs[oid] as Dictionary).get("collision", {}) var body: Node = null match art: "editor": body = skript.call("kollider", col, MASSSTAB) "client": body = instanz.call("_collider", col, MASSSTAB) "server": body = skript.call("_object_body", {"id": str(oid), "pos": [0.0, 0.0, 0.0], "rot_y_deg": 0.0, "scale": MASSSTAB}, {"collision": col}) print("IDENT k_%s=%s" % [oid, _beschreibe(body)]) if body != null: body.free() print("IDENT_PROJEKT=", projekt) if instanz != null: (instanz as Node).free() quit(0) ## Formen-Zahl | Typ-Zähler | Gesamt-AABB (Fußpunkt-Koordinaten, 1 mm gerundet). func _beschreibe(body: Node) -> String: var n := 0 var typen := {} var mn := Vector3(INF, INF, INF) var mx := -Vector3(INF, INF, INF) for k in body.get_children(): if not (k is CollisionShape3D): continue var cs := k as CollisionShape3D if cs.shape == null: continue n += 1 var t := cs.shape.get_class() typen[t] = int(typen.get(t, 0)) + 1 var box := _shape_aabb(cs.shape) var xf := Transform3D(Basis.from_euler(cs.rotation), cs.position) for ix in [0, 1]: for iy in [0, 1]: for iz in [0, 1]: var ecke := box.position + Vector3(box.size.x * ix, box.size.y * iy, box.size.z * iz) var w := xf * ecke mn = mn.min(w) mx = mx.max(w) var ts: Array = typen.keys() ts.sort() var tz: PackedStringArray = [] for t in ts: tz.append("%s:%d" % [t, int(typen[t])]) if n == 0: return "0||leer" return "%d|%s|%.3f,%.3f,%.3f|%.3f,%.3f,%.3f" % [n, ",".join(tz), mn.x, mn.y, mn.z, mx.x, mx.y, mx.z] func _shape_aabb(s: Shape3D) -> AABB: if s is BoxShape3D: var sz := (s as BoxShape3D).size return AABB(-sz * 0.5, sz) if s is CylinderShape3D: var c := s as CylinderShape3D return AABB(Vector3(-c.radius, -c.height * 0.5, -c.radius), Vector3(c.radius * 2.0, c.height, c.radius * 2.0)) if s is SphereShape3D: var r := (s as SphereShape3D).radius return AABB(Vector3(-r, -r, -r), Vector3(r * 2.0, r * 2.0, r * 2.0)) if s is ConcavePolygonShape3D: var f := (s as ConcavePolygonShape3D).get_faces() if f.is_empty(): return AABB() var a := AABB(f[0], Vector3.ZERO) for v in f: a = a.expand(v) return a return AABB()