extends RefCounted class_name SvmapMigration ## Migration veralteter Objekt-IDs beim Laden (Karte 25.10.: test.svmap mit ## gelöschten Pilz-Objekten ließ sich nicht mehr öffnen, V7). ## ## Regel: Eine ID, die nicht (mehr) in der Bibliothek steht, wird per Ersatz-Tabelle ## durch ein passendes Pack-Objekt ersetzt (Position, Drehung, Skalierung, Gruppe ## bleiben). Gibt es keinen Ersatz, wird das Objekt übersprungen und gemeldet — ## nie ein Absturz, nie stilles Verschwinden. Die Datei selbst ändert sich erst ## beim Speichern (Undo/Neu-Laden bleibt möglich). ## Präfix → Ersatz-ID (Pilze waren kleine kollisionslose Bodendeko → Gras 003). const ERSATZ_PRAEFIX := { "pilz_": "grass_003", } ## Ersatz-ID für eine unbekannte ID ("" = keiner). static func ersatz_fuer(oid: String, lib: Dictionary) -> String: for praefix in ERSATZ_PRAEFIX: if oid.begins_with(praefix): var neu: String = ERSATZ_PRAEFIX[praefix] return neu if lib.has(neu) else "" return "" ## Migriert data["objects"] in place. Rückgabe: ## {"ersetzt": {alt_id: {"neu": id, "anzahl": n}}, "entfernt": {alt_id: n}, "gesamt": n} static func migriere_objekte(data: Dictionary, manifest: Dictionary) -> Dictionary: var bericht := {"ersetzt": {}, "entfernt": {}, "gesamt": 0} var objects: Variant = data.get("objects", null) if not (objects is Array): return bericht var lib: Dictionary = manifest.get("objects", {}) var neu_liste: Array = [] for obj in (objects as Array): if not (obj is Dictionary) or not (obj.get("id", null) is String) \ or lib.has(obj["id"]): neu_liste.append(obj) continue var alt: String = obj["id"] var ersatz := ersatz_fuer(alt, lib) bericht["gesamt"] += 1 if ersatz.is_empty(): bericht["entfernt"][alt] = int(bericht["entfernt"].get(alt, 0)) + 1 continue var kopie: Dictionary = (obj as Dictionary).duplicate(true) kopie["id"] = ersatz neu_liste.append(kopie) var eintrag: Dictionary = bericht["ersetzt"].get(alt, {"neu": ersatz, "anzahl": 0}) eintrag["anzahl"] = int(eintrag["anzahl"]) + 1 bericht["ersetzt"][alt] = eintrag if int(bericht["gesamt"]) > 0: data["objects"] = neu_liste return bericht ## Menschenlesbare Zusammenfassung (deutsch) für die Statuszeile. static func zusammenfassung(bericht: Dictionary, lib: Dictionary) -> String: var teile: PackedStringArray = [] for alt in bericht.get("ersetzt", {}): var e: Dictionary = bericht["ersetzt"][alt] var neu_name := str(lib.get(e["neu"], {}).get("name_de", e["neu"])) teile.append("%d× „%s“ durch „%s“ ersetzt" % [e["anzahl"], alt, neu_name]) for alt in bericht.get("entfernt", {}): teile.append("%d× „%s“ übersprungen (kein Ersatz)" % [bericht["entfernt"][alt], alt]) return ", ".join(teile)