Phase 7: netfox + godot-jolt stack upgrade
Stack installed: - netfox v1.35.3 (core + extras + noray + internals) - godot-jolt v0.16.0-stable Architecture: - Server: ENet transport (works headless, no netfox deps) - Client/Editor: netfox rollback (RollbackSynchronizer, TickInterpolator) New/modified: - docs/migration-netfox-plan.md — migration architecture - scripts/network/network_manager.gd — netfox-aware ENet fallback - scripts/network/player.gd — clean base player - client/characters/player_netfox.gd — rollback player w/ WeaponManager - client/characters/input/player_net_input.gd — BaseNetInput subclass - client/characters/character/fps_character_controller.gd — netfox input feed - client/weapons/ — weapon data, registry, TacticalWeaponHitscan, WeaponManager - client/scripts/round_replicator.gd — client-side round state bridge - server/scripts/round_manager.gd — improved state machine - server/scripts/plugin_api/plugin_manager.gd — refined plugin system - config: enemy_tag, ally_tag for meatball targeting Removed: old C++ SimulationServer GDExtension (replaced by netfox rollback)
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
extends SceneTree
|
||||
|
||||
# Generalised Lightmap Baking Config Checker
|
||||
# ==========================================
|
||||
# Validates that a map scene's LightmapGI is configured correctly for baking.
|
||||
# Generalised replacement for scripts/bake_lighting.gd — works on ANY map scene.
|
||||
#
|
||||
# Note: Godot 4.7 LightmapGI baking is editor-only. This script validates
|
||||
# configuration only; actual baking must be done from the Godot editor.
|
||||
#
|
||||
# Usage:
|
||||
# godot --headless --script bake_lightmaps.gd -- res://maps/my_map.tscn
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 — All checks passed (or warnings only)
|
||||
# 1 — One or more checks failed (fatal)
|
||||
# 2 — Scene file could not be loaded
|
||||
|
||||
var _scene_path: String = ""
|
||||
var _checks: Array = [] # [label, passed, is_warning]
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_parse_args()
|
||||
if _scene_path.is_empty():
|
||||
printerr("ERROR: No scene path provided.")
|
||||
print("Usage: godot --headless --script bake_lightmaps.gd -- res://maps/my_map.tscn")
|
||||
quit(2)
|
||||
return
|
||||
|
||||
print("")
|
||||
print("=== Lightmap Baking Config Checker: %s ===" % _scene_path)
|
||||
print("")
|
||||
|
||||
var scene = ResourceLoader.load(_scene_path)
|
||||
if not scene:
|
||||
printerr("ERROR: Could not load scene: %s" % _scene_path)
|
||||
quit(2)
|
||||
return
|
||||
|
||||
var instance = scene.instantiate()
|
||||
if not instance:
|
||||
printerr("ERROR: Could not instantiate scene!")
|
||||
quit(2)
|
||||
return
|
||||
|
||||
root.add_child(instance)
|
||||
print("Scene loaded and instantiated successfully.")
|
||||
print("")
|
||||
print("Note: Godot 4.x LightmapGI baking is editor-only.")
|
||||
print("This script validates configuration only.")
|
||||
print("To bake: Open scene in editor > Select LightmapGI > 'Bake Lightmap'")
|
||||
print("")
|
||||
|
||||
var lightmap: LightmapGI = _find_node_of_type(instance, LightmapGI)
|
||||
if not lightmap:
|
||||
printerr("ERROR: No LightmapGI node found in scene!")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
_print_config(lightmap)
|
||||
_run_checks(lightmap, instance)
|
||||
_print_results()
|
||||
|
||||
|
||||
func _parse_args() -> void:
|
||||
var args := OS.get_cmdline_args()
|
||||
var found_sep := false
|
||||
for a in args:
|
||||
if a == "--":
|
||||
found_sep = true
|
||||
continue
|
||||
if found_sep and not a.begins_with("-"):
|
||||
_scene_path = a
|
||||
return
|
||||
for a in args:
|
||||
if a.contains("res://") or a.ends_with(".tscn"):
|
||||
_scene_path = a
|
||||
return
|
||||
|
||||
|
||||
func _check(label: String, passed: bool, is_warning: bool = false) -> void:
|
||||
_checks.append([label, passed, is_warning])
|
||||
|
||||
|
||||
func _print_config(lightmap: LightmapGI) -> void:
|
||||
print(" LightmapGI configuration:")
|
||||
print(" Quality: ", _quality_name(lightmap.quality), " (", lightmap.quality, ")")
|
||||
print(" Bounces: ", lightmap.bounces)
|
||||
print(" Texel Scale: ", lightmap.texel_scale)
|
||||
print(" Max Tex Size: ", lightmap.max_texture_size)
|
||||
print(" Interior: ", lightmap.interior)
|
||||
print(" Denoiser: ", lightmap.is_using_denoiser())
|
||||
print(" Energy: ", lightmap.lightmap_energy)
|
||||
print(" Bias: ", lightmap.lightmap_probe_bias)
|
||||
|
||||
if lightmap.light_data != null:
|
||||
print(" Baked data: PRESENT ✓")
|
||||
else:
|
||||
print(" Baked data: NOT YET BAKED")
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
func _run_checks(lightmap: LightmapGI, instance: Node) -> void:
|
||||
# Configuration checks
|
||||
_check("Quality ≥ Medium (1)", lightmap.quality >= 1)
|
||||
_check("Bounces ≥ 2", lightmap.bounces >= 2)
|
||||
_check("Texel Scale ≤ 2.0", lightmap.texel_scale <= 2.0)
|
||||
_check("Interior = true", lightmap.interior == true)
|
||||
|
||||
# Denoiser recommended
|
||||
_check("Use denoiser enabled", lightmap.is_using_denoiser(), true)
|
||||
|
||||
# Max texture size ≤ 4096 (sanity)
|
||||
_check("Max texture size ≤ 4096", lightmap.max_texture_size <= 4096)
|
||||
|
||||
# Energy shouldn't be zero
|
||||
_check("Lightmap energy > 0", lightmap.lightmap_energy > 0)
|
||||
|
||||
# Check for lightmap-enabled meshes
|
||||
var meshes: Array = _find_nodes_of_type(instance, MeshInstance3D)
|
||||
var static_meshes := 0
|
||||
var dynamic_meshes := 0
|
||||
for mi in meshes:
|
||||
if mi.gi_mode == GeometryInstance3D.GI_MODE_STATIC:
|
||||
static_meshes += 1
|
||||
elif mi.gi_mode == GeometryInstance3D.GI_MODE_DYNAMIC:
|
||||
dynamic_meshes += 1
|
||||
|
||||
_check("Static geometry meshes found for lightmapping", static_meshes > 0)
|
||||
|
||||
# Baked data status (informational)
|
||||
if lightmap.light_data != null:
|
||||
print(" ✓ Lightmap has baked data.")
|
||||
# Check bake timestamp if available
|
||||
var ld = lightmap.light_data
|
||||
if ld is LightmapGIData and ld.has_method("get_user_data"):
|
||||
print(" Bake data size: %d bytes" % ld.get_user_data().size())
|
||||
else:
|
||||
print(" ⚠ Lightmap NOT YET BAKED. Open in Godot editor and bake.")
|
||||
|
||||
# Summary
|
||||
print("")
|
||||
print(" Geometry summary:")
|
||||
print(" MeshInstance3D nodes: %d" % meshes.size())
|
||||
print(" GI_MODE_STATIC: %d" % static_meshes)
|
||||
print(" GI_MODE_DYNAMIC: %d" % dynamic_meshes)
|
||||
|
||||
|
||||
func _print_results() -> void:
|
||||
print("")
|
||||
print(" ─── Validation Results ───")
|
||||
var passed := 0
|
||||
var failed := 0
|
||||
var warnings := 0
|
||||
for c in _checks:
|
||||
if c[1]:
|
||||
passed += 1
|
||||
print(" ✓ %s" % c[0])
|
||||
else:
|
||||
if c[2]:
|
||||
warnings += 1
|
||||
print(" ⚠ %s" % c[0])
|
||||
else:
|
||||
failed += 1
|
||||
print(" ✗ %s" % c[0])
|
||||
|
||||
print("")
|
||||
print(" Passed: %d Warnings: %d Failed: %d" % [passed, warnings, failed])
|
||||
print("")
|
||||
|
||||
if failed > 0:
|
||||
printerr("Validation FAILED — %d check(s) failed." % failed)
|
||||
quit(1)
|
||||
else:
|
||||
print("=== Config check complete ===")
|
||||
quit(0)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
func _quality_name(q: int) -> String:
|
||||
match q:
|
||||
0: return "Low"
|
||||
1: return "Medium"
|
||||
2: return "High"
|
||||
3: return "Ultra"
|
||||
return "Unknown"
|
||||
|
||||
|
||||
func _find_node_of_type(parent: Node, type: Script) -> Node:
|
||||
for child in parent.get_children():
|
||||
if is_instance_of(child, type):
|
||||
return child
|
||||
var found = _find_node_of_type(child, type)
|
||||
if found:
|
||||
return found
|
||||
return null
|
||||
|
||||
|
||||
func _find_nodes_of_type(parent: Node, type: Script) -> Array:
|
||||
var results: Array = []
|
||||
for child in parent.get_children():
|
||||
if is_instance_of(child, type):
|
||||
results.append(child)
|
||||
results.append_array(_find_nodes_of_type(child, type))
|
||||
return results
|
||||
Reference in New Issue
Block a user