extends SceneTree ## Editor-Tests (headless): feines Material-Raster (Karte 24.10., Sly: „feiner malen“). ## godot --headless --path . -s res://tests/test_mal_fein.gd ## ## F1 Ziel-Raster: 1024 m/129 → 1025 (1 m), 256 m/129 → 257 (1 m), 2048 m → 1025. ## F2 Neue Map startet mit feinem Raster und ist sofort gültig (V1–V16). ## F3 Alte Karte (Raster = Höhenraster) wird beim Anheben optisch identisch ## übernommen und ist danach gültig. ## F4 Pinsel 2 m auf 1024-m-Map ändert nur ~π·2² Punkte (nicht eine 8-m-Zelle). ## F5 V15 lehnt kaputte material_resolution / falsche Länge ab. ## F6 Speichern → Laden → identische Schicht (Roundtrip mit Prüfsumme). ## F7 Resize (1024 → 2048 m) hält die gemalte Stelle an derselben Weltposition. var failures := 0 var checks := 0 func _initialize() -> void: _f1() _f2_f4_f6_f7() _f3() _f5() print("test_mal_fein: %d/%d ok" % [checks - failures, checks]) quit(1 if failures > 0 else 0) func _check(cond: bool, label: String) -> void: checks += 1 print("%s: %s" % ["ok " if cond else "FAIL", label]) if not cond: failures += 1 func _f1() -> void: _check(SvmapIO.material_resolution_for(129, 1024.0, 1024.0) == 1025, "F1 1024 m/129 → 1025") _check(SvmapIO.material_resolution_for(129, 256.0, 256.0) == 257, "F1 256 m/129 → 257") _check(SvmapIO.material_resolution_for(129, 2048.0, 2048.0) == 1025, "F1 2048 m → gedeckelt 1025") _check(SvmapIO.material_resolution_for(129, 64.0, 64.0) == 129, "F1 kleine Map bleibt beim Höhenraster") func _f2_f4_f6_f7() -> void: var doc := SvmapDocument.create_new("Fein", 1024.0, "mittag") var t: Dictionary = doc["terrain"] _check(SvmapIO.material_resolution(t) == 1025, "F2 neue Map: material_resolution 1025") _check(SvmapIO._validate_core(doc).is_empty(), "F2 neue Map gültig (%s)" % str(SvmapIO._validate_core(doc))) var mats := SvmapIO.decode_materials(t) _check(mats.size() == 1025 * 1025, "F2 Schicht hat 1025² Punkte") # F4: Pinsel 2 m Sand mitten auf die Map var changed := TerrainField.apply_material_brush(mats, 1025, 1024.0, 1024.0, 10.3, -7.6, 2.0, 1) var n := 0 for v in mats: if v == 1: n += 1 _check(changed and n >= 8 and n <= 20, "F4 2-m-Pinsel ändert %d Punkte (≈ π·2² = 12,6; alt: 1 Zelle à 8 m)" % n) t["materials_r8_b64"] = SvmapIO.encode_materials(mats) # F6: Roundtrip var path := "user://test_mal_fein.svmap" var sv := SvmapIO.save_to_file(path, doc) _check(bool(sv["ok"]), "F6 speichern ok (%s)" % str(sv.get("errors", []))) var ld := SvmapIO.load_from_file(path) _check(bool(ld["ok"]), "F6 laden ok (%s)" % str(ld.get("errors", []))) if bool(ld["ok"]): var m2 := SvmapIO.decode_materials(ld["data"]["terrain"]) _check(m2 == mats, "F6 Schicht bitgleich nach Roundtrip") DirAccess.remove_absolute(ProjectSettings.globalize_path(path)) # F7: Resize auf 2048 m — Sand bleibt bei (10.3, -7.6) var big := SvmapDocument.resize_terrain(doc, 2048.0, 2048.0) var bt: Dictionary = big["terrain"] var bm := SvmapIO.material_resolution(bt) var bmats := SvmapIO.decode_materials(bt) var gx := int(roundf((10.3 / 2048.0 + 0.5) * float(bm - 1))) var gz := int(roundf((-7.6 / 2048.0 + 0.5) * float(bm - 1))) _check(bmats.size() == bm * bm and int(bmats[gz * bm + gx]) == 1, "F7 Resize 2048 m (Raster %d): Sand an derselben Weltstelle" % bm) _check(SvmapIO._validate_core(big).is_empty(), "F7 Resize-Ergebnis gültig") func _f3() -> void: # Alte Karte simulieren: Material-Raster = Höhenraster (129), ohne Feld. var doc := SvmapDocument.create_new("Alt", 1024.0, "mittag") var t: Dictionary = doc["terrain"] var old := PackedByteArray() old.resize(129 * 129) for i in old.size(): old[i] = (i * 7) % 20 t.erase("material_resolution") t["materials_r8_b64"] = SvmapIO.encode_materials(old) _check(SvmapIO._validate_core(doc).is_empty(), "F3 alte Karte (ohne Feld) gültig") _check(SvmapIO.upgrade_material_layer(t), "F3 Anheben meldet Änderung") _check(SvmapIO.material_resolution(t) == 1025, "F3 danach Raster 1025") var m := SvmapIO.decode_materials(t) var same := true for z in 129: for x in 129: if SvmapIO.material_at_height_point(m, 1025, 129, x, z) != int(old[z * 129 + x]): same = false _check(same, "F3 jeder Höhenpunkt behält sein Material (optisch identisch)") _check(SvmapIO._validate_core(doc).is_empty(), "F3 angehobene Karte gültig") _check(not SvmapIO.upgrade_material_layer(t), "F3 zweites Anheben ändert nichts") func _f5() -> void: var doc := SvmapDocument.create_new("Kaputt", 1024.0, "mittag") var t: Dictionary = doc["terrain"] t["material_resolution"] = 1000 # (1000−1) kein Vielfaches von 128 _check(_has_v15(SvmapIO._validate_core(doc)), "F5 material_resolution nicht auf dem Raster → V15") t["material_resolution"] = 2049 _check(_has_v15(SvmapIO._validate_core(doc)), "F5 material_resolution > 1025 → V15") t["material_resolution"] = 1025 var short := PackedByteArray() short.resize(129 * 129) t["materials_r8_b64"] = SvmapIO.encode_materials(short) _check(_has_v15(SvmapIO._validate_core(doc)), "F5 Schichtlänge passt nicht → V15") func _has_v15(errs: PackedStringArray) -> bool: for e in errs: if str(e).begins_with("V15"): return true return false func _only_checksum(errs: PackedStringArray) -> bool: for e in errs: if not str(e).begins_with("V13"): return false return true