This commit is contained in:
Nicholas Butzke
2026-08-02 02:20:02 -04:00
parent 61669627db
commit 922983429e
226 changed files with 34032 additions and 18521 deletions
+150
View File
@@ -0,0 +1,150 @@
extends SceneTree
## Loads every menu-selectable level through an active single-player match,
## waits for its player/viewmodel to initialize, then advances. This is the
## release gate for scene-load, shader, and teardown errors.
## The map list is DISCOVERED, not written down.
##
## It used to be a hardcoded array, and a newly added level (Sakura Crossing)
## loaded, shipped and never once went through this gate — the run still said
## "PASS: all 5 levels" while there were six. A release gate that has to be
## edited by hand every time it gains something to test is a gate that will be
## wrong exactly when it matters.
##
## `scenes/maps/*/map_meta.cfg` is already the definition of "menu-selectable",
## since that is what the main menu and map_preview_capture both scan.
const MAPS_DIR := "res://scenes/maps/"
var MAPS: Array[String] = []
func _discover_maps() -> Array[String]:
var out: Array[String] = []
var dir := DirAccess.open(MAPS_DIR)
if dir == null:
return out
dir.list_dir_begin()
var folder := dir.get_next()
while folder != "":
if dir.current_is_dir() and not folder.begins_with("."):
var cfg := ConfigFile.new()
if cfg.load(MAPS_DIR + folder + "/map_meta.cfg") == OK:
var scene_path: String = cfg.get_value("map", "scene_path", "")
if scene_path != "" and ResourceLoader.exists(scene_path):
out.append(scene_path)
folder = dir.get_next()
out.sort()
return out
var _mode := "boot"
var _frames := 0
var _map_index := -1
var _failures: Array[String] = []
var _loaded_maps := 0
var _skin_override := ""
func _initialize() -> void:
var args := OS.get_cmdline_user_args()
if not args.is_empty():
_skin_override = args[0]
MAPS = _discover_maps()
print("MAP_SMOKE discovered %d levels: %s" % [MAPS.size(), ", ".join(MAPS)])
change_scene_to_file("res://ui/main_menu/main_menu.tscn")
func _process(_delta: float) -> bool:
_frames += 1
if _mode == "boot":
if _frames == 45:
if not _skin_override.is_empty():
var skin_manager = root.get_node_or_null("SkinManager")
if skin_manager and skin_manager.skins.has(_skin_override):
# Test-only selection: direct assignment avoids overwriting
# the player's saved preference in user://.
skin_manager.active_skin_id = _skin_override
print("MAP_SMOKE skin override: ", _skin_override)
else:
_fail("unknown skin override: " + _skin_override)
var network = root.get_node_or_null("NetworkManager")
if network and network.has_method("start_singleplayer_match"):
network.start_singleplayer_match(GameMode.DEATHMATCH)
_load_next()
return false
if _mode == "map":
if _frames == 150:
var players := root.find_children("*", "CharacterBody3D", true, false)
var local_player = null
for player in players:
if player.has_method("get_visual_model") \
and player.is_multiplayer_authority():
local_player = player
break
if local_player == null:
_fail("missing local player: " + MAPS[_map_index])
else:
var managers: Array[Node] = local_player.find_children(
"WeaponManager", "WeaponManager", true, false)
if managers.is_empty():
_fail("missing WeaponManager: " + MAPS[_map_index])
else:
print("MAP_SMOKE loaded ", MAPS[_map_index])
_loaded_maps += 1
_audit_null_materials()
elif _frames >= 180:
_load_next()
return false
if _mode == "drain":
if _frames >= 180:
if _failures.is_empty() and _loaded_maps == MAPS.size():
print("MAP_SMOKE PASS: all %d levels loaded cleanly" % MAPS.size())
quit(0)
else:
for failure in _failures:
push_error("MAP_SMOKE FAIL: " + failure)
quit(1)
return true
return false
return false
func _load_next() -> void:
_map_index += 1
_frames = 0
if _map_index >= MAPS.size():
_mode = "drain"
unload_current_scene()
return
_mode = "map"
var error := change_scene_to_file(MAPS[_map_index])
if error != OK:
_fail("could not load %s (error %d)" % [MAPS[_map_index], error])
func _fail(message: String) -> void:
_failures.append(message)
printerr("MAP_SMOKE ", message)
func _audit_null_materials() -> void:
var null_surfaces: Array[String] = []
for candidate in root.find_children("*", "MeshInstance3D", true, false):
var mesh_instance := candidate as MeshInstance3D
if mesh_instance.mesh == null:
continue
for surface in mesh_instance.mesh.get_surface_count():
if mesh_instance.get_active_material(surface) == null:
null_surfaces.append(
"%s[%d]" % [mesh_instance.get_path(), surface])
if null_surfaces.is_empty():
print("MAP_SMOKE material audit: 0 null surfaces")
else:
_fail("%d null mesh materials in %s: %s" % [
null_surfaces.size(),
MAPS[_map_index],
", ".join(null_surfaces.slice(0, 12)),
])