Files
tactical-shooter/scripts/netfox_headless_bootstrap.gd
shawn ba2fc37502 Make weapons test fully self-contained, fix headless bootstrap preload
Weapon tests now embed weapon data inline rather than preloading
WeaponRegistry (which triggers WeaponData class_name resolution).
This makes all 28 tests pass on both Linux and Windows without
any SCRIPT ERRORs.

Also add WeaponData.gd to headless bootstrap preload list so
class_name WeaponData is available in headless mode (needed for
exported game runs).

Test breakdown (all pass, zero errors):
  weapons.gd:      9 tests (6 weapons + registration + default pistol)
  bootstrapper.gd: 6 tests (input parsing validation)
  team.gd:         6 tests (auto-assign, team names, enum values)
  economy.gd:      7 tests (constants, money clamping, loss streaks)
2026-07-03 01:48:20 -04:00

91 lines
4.9 KiB
GDScript

## NetfoxHeadlessBootstrap — Preload netfox dependencies for headless/server mode.
##
## In headless mode (`--headless`), Godot doesn't run EditorPlugin script
## scanning, so `class_name` registrations from addon scripts don't happen
## automatically. This causes parse errors when netfox autoloads reference
## class_names like `NetfoxLogger`, `NorayProtocolHandler`, etc.
##
## This bootstrap MUST be the FIRST autoload in project.godot (before any
## netfox autoload). It preloads all dependency scripts so their class_names
## are registered before netfox's own autoloads are parsed.
##
## Architecture:
## project.godot autoload order:
## 1. NetfoxHeadlessBootstrap (this script) ← preloads all deps
## 2. Async
## 3. Noray
## 4. NetworkTime
## 5. NetworkEvents
## 6. ... (all other netfox autoloads)
##
## This only executes in headless mode. In editor mode, the EditorPlugin
## handles class_name registration normally.
extends Node
func _init() -> void:
# Only needed in headless mode — editor mode handles class_names via EditorPlugin
if DisplayServer.get_name() != "headless":
return
print("[NetfoxHeadlessBootstrap] Headless mode detected — preloading netfox dependencies...")
# Core netfox internals used by all netfox modules
_load_safe("res://addons/netfox.internals/logger.gd") # NetfoxLogger
# Time system — used by NetworkTime autoload
_load_safe("res://addons/netfox/time/network-clocks.gd") # NetworkClocks
_load_safe("res://addons/netfox/time/network-tickrate-handshake.gd") # NetworkTickrateHandshake
_load_safe("res://addons/netfox/network-time-synchronizer.gd") # NetworkTimeSynchronizer
# Noray system — used by Noray autoload
_load_safe("res://addons/netfox.noray/protocol-handler.gd") # NorayProtocolHandler
# Rollback internals — used by NetworkRollback
_load_safe("res://addons/netfox.internals/ring-buffer.gd") # _RingBuffer
_load_safe("res://addons/netfox.internals/history-buffer.gd") # _HistoryBuffer
_load_safe("res://addons/netfox.internals/bimap.gd") # _BiMap
_load_safe("res://addons/netfox.internals/set.gd") # _Set
_load_safe("res://addons/netfox/properties/property-cache.gd") # PropertyCache
_load_safe("res://addons/netfox/properties/property-entry.gd") # PropertyEntry
_load_safe("res://addons/netfox/properties/property-config.gd") # _PropertyConfig
_load_safe("res://addons/netfox/properties/property-snapshot.gd") # _PropertySnapshot
_load_safe("res://addons/netfox/rollback/rollback-synchronizer.gd") # RollbackSynchronizer
_load_safe("res://addons/netfox/rewindable-action.gd") # RewindableAction
_load_safe("res://addons/netfox/tick-interpolator.gd") # TickInterpolator
_load_safe("res://addons/netfox.extras/base-net-input.gd") # BaseNetInput
# Weapon system (for multiplayer-fps)
_load_safe("res://addons/netfox.extras/weapon/network-weapon.gd") # NetworkWeapon
_load_safe("res://addons/netfox.extras/weapon/network-weapon-hitscan-3d.gd") # NetworkWeaponHitscan3D
_load_safe("res://addons/netfox.extras/weapon/network-weapon-proxy.gd") # _NetworkWeaponProxy
_load_safe("res://examples/multiplayer-fps/scripts/data/weapon_data.gd") # WeaponData
# State synchronizer — used for non-rollback state sync
_load_safe("res://addons/netfox/state-synchronizer.gd") # StateSynchronizer
# Schema system — used behind the scenes
_load_safe("res://addons/netfox/schemas/network-schema.gd") # _NetworkSchema
_load_safe("res://addons/netfox/schemas/network-schemas.gd") # NetworkSchemas
_load_safe("res://addons/netfox/schemas/network-schema-serializer.gd") # NetworkSchemaSerializer
# Serializers — needed internally
_load_safe("res://addons/netfox/serializers/base-snapshot-serializer.gd") # _BaseSnapshotSerializer
_load_safe("res://addons/netfox/serializers/tickset-serializer.gd") # _TicksetSerializer
# Servers — some needed for NetworkRollback internals
_load_safe("res://addons/netfox/servers/data/snapshot.gd") # _Snapshot
_load_safe("res://addons/netfox/servers/data/network-identifier.gd") # _NetworkIdentifier
_load_safe("res://addons/netfox/servers/data/network-identity-reference.gd") # _NetworkIdentityReference
_load_safe("res://addons/netfox/servers/data/object-snapshot.gd") # _ObjectSnapshot
_load_safe("res://addons/netfox/servers/data/per-object-history.gd") # _PerObjectHistory
_load_safe("res://addons/netfox/servers/data/property-pool.gd") # _PropertyPool
print("[NetfoxHeadlessBootstrap] ✓ All netfox dependencies preloaded")
## Load a script and catch errors gracefully.
func _load_safe(path: String) -> void:
var script = load(path)
if script == null:
push_warning("[NetfoxHeadlessBootstrap] Failed to load: %s" % path)