126 lines
6.9 KiB
GDScript
126 lines
6.9 KiB
GDScript
extends SceneTree
|
|
|
|
var failures: Array[String] = []
|
|
|
|
|
|
func _init() -> void:
|
|
var event_bus: Node = load("res://autoload/event_bus.gd").new()
|
|
_expect(not event_bus.has_signal("action_judged"), "EventBus should not expose legacy action_judged")
|
|
event_bus.free()
|
|
var rhythm: Node = load("res://autoload/rhythm_manager.gd").new()
|
|
_expect(not rhythm.has_signal("action_judged"), "RhythmManager should not expose legacy action_judged")
|
|
rhythm.free()
|
|
for runtime_path: String in [
|
|
"res://autoload/rhythm_manager.gd",
|
|
"res://autoload/event_bus.gd",
|
|
"res://scenes/components/action_controller.gd",
|
|
"res://scenes/ui/rhythm_track.gd",
|
|
]:
|
|
if not FileAccess.file_exists(runtime_path):
|
|
continue
|
|
_expect(not _read_text(runtime_path).contains("action_judged"), "%s should not reference action_judged" % runtime_path)
|
|
for rule_path: String in [
|
|
"res://scenes/combat/action_resolver.gd",
|
|
"res://scenes/components/action_controller.gd",
|
|
]:
|
|
_expect(not _read_text(rule_path).contains("get_current_state_name"), "%s should not use legacy state API for rule context" % rule_path)
|
|
var state_machine_source := _read_text("res://scenes/components/state_machine.gd")
|
|
_expect(not state_machine_source.contains("state_names"), "StateMachine should not keep legacy state_names")
|
|
_expect(not state_machine_source.contains("get_current_state_name"), "StateMachine should not expose legacy get_current_state_name")
|
|
_expect(not state_machine_source.contains("\"state\""), "StateMachine.build_context should not emit legacy state")
|
|
_expect(not state_machine_source.contains("func can_start_action"), "StateMachine should not own action permission rules")
|
|
_expect(not state_machine_source.contains("func can_move_freely"), "StateMachine should not own movement permission rules")
|
|
var action_rule_source := _read_text("res://scripts/resolvers/action_rule_resolver.gd")
|
|
_expect(not action_rule_source.contains("legacy_state"), "ActionRuleResolver should not fallback to legacy state context")
|
|
for marker_path: String in [
|
|
"res://scenes/ui/rhythm_track.gd",
|
|
"res://tests/test_chart_layer.gd",
|
|
"res://tests/test_ui_animation_regression.gd",
|
|
]:
|
|
if not FileAccess.file_exists(marker_path):
|
|
continue
|
|
var marker_source := _read_text(marker_path)
|
|
_expect(not marker_source.contains("enemy_prepare_attack"), "%s should not keep legacy enemy_prepare_attack marker" % marker_path)
|
|
_expect(not marker_source.contains("enemy_attack_active"), "%s should not keep legacy enemy_attack_active marker" % marker_path)
|
|
_expect(not marker_source.contains("enemy_recovery"), "%s should not keep legacy enemy_recovery marker" % marker_path)
|
|
var action_controller_source := _read_text("res://scenes/components/action_controller.gd")
|
|
_expect(not action_controller_source.contains("action_executor.execute(current_action, StringName(str(current_intent.judgement.get(\"label\", \"perfect\"))), burst_component)"), "ActionController should not pass BurstComponent as a stat provider")
|
|
_expect(not action_controller_source.contains("resolve_cost\", action, burst_component"), "ActionController cost resolution should use EffectContainer, not BurstComponent provider")
|
|
var burst_source := _read_text("res://scenes/components/burst_component.gd")
|
|
_expect(not burst_source.contains("judgement_scale"), "BurstComponent should not directly mutate RhythmManager.judgement_scale")
|
|
for presentation_path: String in [
|
|
"res://scenes/characters/character.gd",
|
|
"res://scenes/characters/player.gd",
|
|
"res://scenes/components/movement_motor.gd",
|
|
]:
|
|
var presentation_source := _read_text(presentation_path)
|
|
_expect(not presentation_source.contains("Character.State"), "%s should not reference legacy Character.State" % presentation_path)
|
|
_expect(not presentation_source.contains("enum State"), "%s should use explicit presentation constants, not legacy Character.State enum" % presentation_path)
|
|
_expect(not FileAccess.file_exists("res://scenes/rhythm/rhythm_conductor.gd"), "Legacy rhythm_conductor.gd should be removed")
|
|
_expect(not FileAccess.file_exists("res://tests/test_rhythm_conductor.gd"), "Legacy rhythm conductor test should be removed")
|
|
var charge_source := _read_text("res://scenes/components/charge_component.gd")
|
|
for charge_needle: String in ["release_requested", "begin_hold", "finish_hold", "skill_a_charge_release", "skill_d_charge_release"]:
|
|
_expect(not charge_source.contains(charge_needle), "ChargeComponent should not keep legacy charge API: %s" % charge_needle)
|
|
var player_source := _read_text("res://scenes/characters/player.gd")
|
|
for player_needle: String in ["_held_symbols", "_is_symbol_held"]:
|
|
_expect(not player_source.contains(player_needle), "Player should not keep legacy held-symbol cache: %s" % player_needle)
|
|
var action_script: Script = load("res://resources/action_data.gd")
|
|
if action_script == null:
|
|
failures.append("ActionData script should load for required_state cleanup")
|
|
else:
|
|
var action: Resource = action_script.new() as Resource
|
|
_expect(not _has_property(action, "required_state"), "ActionData should not expose legacy required_state")
|
|
for property_name: String in ["energy_cost", "energy_reward", "spawns_projectile", "projectile_scene", "damage", "cancel_window", "has_super_armor", "displacement"]:
|
|
_expect(not _has_property(action, property_name), "ActionData should not expose legacy field %s" % property_name)
|
|
for doc_path: String in [
|
|
"res://AGENTS.md",
|
|
"res://docs/当前项目评估文档.md",
|
|
]:
|
|
if not FileAccess.file_exists(doc_path):
|
|
continue
|
|
_expect(not _read_text(doc_path).contains("required_state"), "%s should not describe required_state as an active compatibility field" % doc_path)
|
|
for artifact_path: String in [
|
|
"res://assets/art/characters/jump.png",
|
|
"res://assets/art/characters/jump.png.import",
|
|
"res://assets/art/characters/katana_attack_sheathe.png",
|
|
"res://assets/art/characters/katana_attack_sheathe.png.import",
|
|
"res://assets/art/characters/player_idle.png",
|
|
"res://assets/art/characters/player_idle.png.import",
|
|
"res://assets/art/characters/player_punch.png",
|
|
"res://assets/art/characters/player_punch.png.import",
|
|
"res://addons/limboai/bin/limboai.gdextension",
|
|
]:
|
|
_expect(not FileAccess.file_exists(artifact_path), "Unused legacy artifact should be removed: %s" % artifact_path)
|
|
_expect(DirAccess.open("res://something") == null, "Placeholder something/ directory should be removed")
|
|
_finish()
|
|
|
|
|
|
func _read_text(path: String) -> String:
|
|
var file := FileAccess.open(path, FileAccess.READ)
|
|
if file == null:
|
|
failures.append("Could not read %s" % path)
|
|
return ""
|
|
return file.get_as_text()
|
|
|
|
|
|
func _has_property(object: Object, property_name: String) -> bool:
|
|
for property: Dictionary in object.get_property_list():
|
|
if property.get("name") == property_name:
|
|
return true
|
|
return false
|
|
|
|
|
|
func _expect(condition: bool, label: String) -> void:
|
|
if not condition:
|
|
failures.append(label)
|
|
|
|
|
|
func _finish() -> void:
|
|
if failures.is_empty():
|
|
print("PASS v2 terms cleanup")
|
|
quit(0)
|
|
else:
|
|
for failure: String in failures:
|
|
push_error(failure)
|
|
quit(1)
|