extends SceneTree var failures: Array[String] = [] func _init() -> void: _run.call_deferred() func _run() -> void: _check_phase0_files() _check_directories() _check_project_settings() _check_phase1_files() _finish() func _check_phase0_files() -> void: _expect(_file_contains("res://.gitignore", ".godot/"), ".gitignore should ignore .godot/") _expect(_file_contains("res://.gitignore", ".DS_Store"), ".gitignore should ignore .DS_Store") _expect(_file_contains("res://.gitignore", "*.import.tmp"), ".gitignore should ignore *.import.tmp") _expect(FileAccess.file_exists("res://README.md"), "README.md should exist") _expect(_file_contains("res://docs/decisions.md", "body collision audit"), "docs/decisions.md should record the body collision audit") _expect(_file_contains("res://docs/decisions.md", "player_body"), "body collision audit should record player_body layer decision") _expect(_file_contains("res://docs/decisions.md", "enemy_body"), "body collision audit should record enemy_body layer decision") func _check_directories() -> void: for dir_path: String in [ "res://autoload", "res://scripts/resolvers", "res://resources/actions", "res://resources/actions/enemies", "res://resources/effects", "res://resources/charts", "res://scenes/characters", "res://scenes/chart", "res://scenes/combat", "res://scenes/components", "res://scenes/enemies", "res://scenes/ground", "res://scenes/main", "res://scenes/stage", "res://scenes/ui", "res://assets/art", "res://assets/audio", "res://assets/ui", "res://tools", "res://tests", "res://docs", ]: _expect(DirAccess.open(dir_path) != null, "%s should exist" % dir_path) _expect(DirAccess.open("res://resources/effects/time_phase") != null, "resources/effects/time_phase should contain implemented time-phase effects") func _check_project_settings() -> void: var expected_layers := { "layer_names/2d_physics/layer_1": "world", "layer_names/2d_physics/layer_2": "player_hurtbox", "layer_names/2d_physics/layer_3": "enemy_hurtbox", "layer_names/2d_physics/layer_4": "player_hitbox", "layer_names/2d_physics/layer_5": "enemy_hitbox", "layer_names/2d_physics/layer_6": "player_body", "layer_names/2d_physics/layer_7": "enemy_body", } for key: String in expected_layers: _expect(ProjectSettings.has_setting(key), "%s should be configured" % key) if ProjectSettings.has_setting(key): _expect_equal(str(ProjectSettings.get_setting(key)), expected_layers[key], "%s name" % key) for autoload_name: String in ["EventBus", "RhythmManager"]: var key := "autoload/%s" % autoload_name _expect(ProjectSettings.has_setting(key), "%s should be registered as an autoload" % autoload_name) if ProjectSettings.has_setting("autoload/EventBus"): _expect(str(ProjectSettings.get_setting("autoload/EventBus")).contains("res://autoload/event_bus.gd"), "EventBus autoload path") if ProjectSettings.has_setting("autoload/RhythmManager"): _expect(str(ProjectSettings.get_setting("autoload/RhythmManager")).contains("res://autoload/rhythm_manager.gd"), "RhythmManager autoload path") _expect_action_unbound("move_left") _expect_action_unbound("move_right") _expect_action_key("combo_a", KEY_A) _expect_action_key("combo_d", KEY_D) _expect_action_key("combo_w", KEY_W) _expect_action_key("combo_s", KEY_S) _expect_action_key("combo_space", KEY_SPACE) func _check_phase1_files() -> void: _expect(FileAccess.file_exists("res://autoload/event_bus.gd"), "event_bus.gd should be migrated") _expect(FileAccess.file_exists("res://autoload/event_bus.gd.uid"), "event_bus.gd.uid should be migrated") _expect(FileAccess.file_exists("res://autoload/rhythm_manager.gd"), "rhythm_manager.gd should be migrated") _expect(FileAccess.file_exists("res://autoload/rhythm_manager.gd.uid"), "rhythm_manager.gd.uid should be migrated") _expect(FileAccess.file_exists("res://assets/audio/song.ogg"), "song.ogg should be migrated") _expect(FileAccess.file_exists("res://assets/audio/song.ogg.import"), "song.ogg.import should be migrated") func _expect_action_unbound(action_name: StringName) -> void: _expect(InputMap.has_action(action_name), "%s action should exist" % action_name) if InputMap.has_action(action_name): _expect_int(InputMap.action_get_events(action_name).size(), 0, "%s should be registered but physically unbound" % action_name) func _expect_action_key(action_name: StringName, keycode: Key) -> void: _expect(InputMap.has_action(action_name), "%s action should exist" % action_name) var found := false if InputMap.has_action(action_name): for event: InputEvent in InputMap.action_get_events(action_name): var key := event as InputEventKey if key != null and (key.physical_keycode == keycode or key.keycode == keycode): found = true _expect(found, "%s should bind %s" % [action_name, OS.get_keycode_string(keycode)]) func _file_contains(path: String, needle: String) -> bool: if not FileAccess.file_exists(path): return false var file := FileAccess.open(path, FileAccess.READ) if file == null: return false var text := file.get_as_text() file.close() return text.contains(needle) func _expect(condition: bool, label: String) -> void: if not condition: failures.append(label) func _expect_equal(actual, expected, label: String) -> void: if actual != expected: failures.append("%s: expected %s, got %s" % [label, str(expected), str(actual)]) func _expect_int(actual: int, expected: int, label: String) -> void: if actual != expected: failures.append("%s: expected %d, got %d" % [label, expected, actual]) func _finish() -> void: if failures.is_empty(): print("PASS migration phase 0/1") quit(0) else: for failure: String in failures: push_error(failure) quit(1)