extends SceneTree ## Synthetic main-thread scene, ownership, boundary and timing regression for ## ADT water finalization. const FINALIZER_SCRIPT := preload("res://src/render/liquid/adt_water_scene_finalizer.gd") const FINALIZER_PATH := "res://src/render/liquid/adt_water_scene_finalizer.gd" const LOADER_PATH := "res://src/scenes/streaming/streaming_world_loader.gd" func _initialize() -> void: var failures: Array[String] = [] _verify_invalid_and_dry_input(failures) _verify_build_attach_geometry_and_owner(failures) _verify_ownership_boundaries(failures) var elapsed_milliseconds := _verify_bounded_timing(failures) if not failures.is_empty(): for failure in failures: push_error("ADT_WATER_SCENE_FINALIZER: %s" % failure) quit(1) return print( "ADT_WATER_SCENE_FINALIZER PASS cases=8 iterations=100 elapsed_ms=%.3f" % elapsed_milliseconds ) quit(0) func _verify_invalid_and_dry_input(failures: Array[String]) -> void: var finalizer: RefCounted = FINALIZER_SCRIPT.new() var tile_root := Node3D.new() _expect_null( finalizer.call("attach_water_scene", {}, Vector3.ZERO, tile_root, null), "empty water data returns null", failures ) _expect_equal(tile_root.get_child_count(), 0, "empty data does not mutate tile", failures) _expect_null( finalizer.call("attach_water_scene", _synthetic_water_data(), Vector3.ZERO, null, null), "missing tile root returns null", failures ) _expect_null( finalizer.call( "attach_water_scene", {"chunks": [{"origin": Vector3.ZERO, "liquids": []}]}, Vector3.ZERO, tile_root, null ), "dry parsed ADT returns null", failures ) _expect_equal(tile_root.get_child_count(), 0, "dry data does not mutate tile", failures) tile_root.free() func _verify_build_attach_geometry_and_owner(failures: Array[String]) -> void: var finalizer: RefCounted = FINALIZER_SCRIPT.new() var editor_scene_root := Node3D.new() var tile_root := Node3D.new() get_root().add_child(editor_scene_root) editor_scene_root.add_child(tile_root) var tile_origin := Vector3(10.0, 20.0, 30.0) var water_root: Node3D = finalizer.call( "attach_water_scene", _synthetic_water_data(tile_origin), tile_origin, tile_root, editor_scene_root ) _expect_not_null(water_root, "synthetic liquid builds a water root", failures) if water_root != null: _expect_true(water_root.get_parent() == tile_root, "water root attached once", failures) _expect_equal(tile_root.get_child_count(), 1, "tile owns one water root", failures) _expect_true(water_root.owner == editor_scene_root, "water root editor owner", failures) _expect_equal(water_root.get_child_count(), 1, "one liquid surface grouped", failures) if water_root.get_child_count() == 1: var liquid_mesh_instance := water_root.get_child(0) as MeshInstance3D _expect_not_null(liquid_mesh_instance, "liquid child is MeshInstance3D", failures) if liquid_mesh_instance != null: _expect_true( liquid_mesh_instance.owner == editor_scene_root, "liquid child editor owner", failures ) var liquid_mesh := liquid_mesh_instance.mesh as ArrayMesh _expect_not_null(liquid_mesh, "liquid surface has ArrayMesh", failures) if liquid_mesh != null: _expect_equal( liquid_mesh.surface_get_array_len(0), 4, "one enabled liquid cell has four vertices", failures ) _expect_equal( liquid_mesh.surface_get_array_index_len(0), 6, "one enabled liquid cell has six indices", failures ) editor_scene_root.free() func _verify_ownership_boundaries(failures: Array[String]) -> void: var finalizer_source := FileAccess.get_file_as_string(FINALIZER_PATH) var loader_source := FileAccess.get_file_as_string(LOADER_PATH) _expect_true( finalizer_source.contains("ADT_BUILDER_SCRIPT.build_tile_water_scene"), "finalizer retains existing ADTBuilder implementation", failures ) _expect_true( finalizer_source.contains("tile_root.add_child(water_root)"), "finalizer owns water subtree attachment", failures ) _expect_equal( loader_source.count("_adt_water_scene_finalizer.attach_water_scene("), 2, "both loader water paths delegate finalization", failures ) _expect_false( loader_source.contains("_builder.build_tile_water_scene"), "loader no longer builds water scenes directly", failures ) _expect_true( loader_source.contains("state[\"water_loaded\"] = true"), "loader retains water-loaded timing", failures ) _expect_true( loader_source.contains("WATER_FINALIZE"), "loader retains finalization permit ownership", failures ) func _verify_bounded_timing(failures: Array[String]) -> float: var finalizer: RefCounted = FINALIZER_SCRIPT.new() var tile_root := Node3D.new() var started_microseconds := Time.get_ticks_usec() for _iteration in range(100): finalizer.call("attach_water_scene", {}, Vector3.ZERO, tile_root, null) var elapsed_milliseconds := float(Time.get_ticks_usec() - started_microseconds) / 1000.0 _expect_true(elapsed_milliseconds < 1000.0, "100 empty attempts under 1 second", failures) _expect_equal(tile_root.get_child_count(), 0, "timing loop creates no nodes", failures) tile_root.free() return elapsed_milliseconds func _synthetic_water_data(tile_origin: Vector3 = Vector3.ZERO) -> Dictionary: var liquid_mask := PackedByteArray() liquid_mask.resize(64) liquid_mask.fill(0) liquid_mask[0] = 1 var liquid_heights := PackedFloat32Array() liquid_heights.resize(81) liquid_heights.fill(tile_origin.y + 5.0) return { "chunks": [{ "origin": tile_origin, "liquids": [{ "liquid_id": 7, "mask": liquid_mask, "heights": liquid_heights, }], }], } func _expect_true(condition: bool, label: String, failures: Array[String]) -> void: if not condition: failures.append(label) func _expect_false(condition: bool, label: String, failures: Array[String]) -> void: _expect_true(not condition, label, failures) func _expect_null(value: Variant, label: String, failures: Array[String]) -> void: _expect_true(value == null, label, failures) func _expect_not_null(value: Variant, label: String, failures: Array[String]) -> void: _expect_true(value != null, label, failures) func _expect_equal(actual: int, expected: int, label: String, failures: Array[String]) -> void: if actual != expected: failures.append("%s expected=%d actual=%d" % [label, expected, actual])