136 lines
4.4 KiB
GDScript
136 lines
4.4 KiB
GDScript
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_<oid>=<Formen>|<Typ-Zähler>|<Gesamt-AABB>`
|
|
## (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 <projekt> -s <abs>/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()
|