extends Node
## Startup (2026-10-02): main.gd loads its gameplay scripts on first use (perf_apply.py hunk 6), so the title
## screen no longer waits ~2.5 s for the HUD, every window, the local server, the views and the skill FX to
## compile. While the title is up (added by main._title_backdrop once the backdrop is built) this node compiles
## them in the background: it walks their static preload("...") graph and loads it leaves-first, one script per
## frame (each load then only compiles that one file -> short hitches instead of one long freeze). When the
## player starts before it is done, the rest simply compiles on first use. Frees itself when finished.

const ROOTS := ["res://scripts/hud.gd", "res://scripts/server/local_server.gd", "res://scripts/player.gd",
	"res://scripts/monster.gd", "res://scripts/auto_play.gd", "res://scripts/skill_fx.gd", "res://scripts/hit_feel.gd",
	"res://scripts/loot.gd", "res://scripts/npc.gd", "res://scripts/skill_area.gd", "res://scripts/skill_zone.gd",
	# HUD parts loaded with load() (not in the preload graph): the Constellation / Asura panels, Starwell / Stable
	"res://scripts/ui/constellation_ui.gd", "res://scripts/ui/asura_ui.gd", "res://scripts/ui/starwell_ui.gd",
	"res://scripts/ui/stable_ui.gd"]
## never warmed: test-only scripts (compiled by --selftest / shot runs on demand)
const SKIP := ["res://scripts/selftest.gd", "res://scripts/skill_fx_test.gd", "res://scripts/skill_fx_shot.gd"]

var _todo: Array = []
var _seen := {}
var _re := RegEx.create_from_string("preload\\(\"(res://[^\"]+\\.gd)\"\\)")
var _t0 := 0


func _ready() -> void:
	name = "BootPrewarm"
	if DisplayServer.get_name() == "headless":
		queue_free()
		return
	_t0 = Time.get_ticks_msec()
	for r in ROOTS:
		_walk(r)


func _walk(path: String) -> void:
	if _seen.has(path) or path in SKIP:
		return
	_seen[path] = true
	if ResourceLoader.has_cached(path):
		return
	var f := FileAccess.open(path, FileAccess.READ)
	if f == null:
		return
	for m in _re.search_all(f.get_as_text()):
		_walk(m.get_string(1))
	_todo.append(path)


func _process(_d: float) -> void:
	# a frame budget of ~1 script: the title keeps animating between loads
	var t := Time.get_ticks_usec()
	while not _todo.is_empty() and Time.get_ticks_usec() - t < 8000:
		var p: String = _todo.pop_front()
		if not ResourceLoader.has_cached(p):
			load(p)
	if _todo.is_empty():
		if "--envfps" in OS.get_cmdline_user_args():
			print("SHOT prewarm done %d scripts in %.2f s" % [_seen.size(), (Time.get_ticks_msec() - _t0) / 1000.0])
		queue_free()
