e7299b17e9
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)
3.5 KiB
3.5 KiB
Map Validator Scripts
Validator scripts for Tactical Shooter map scenes. Run against any .tscn file to
check structural integrity, performance budget, and lighting correctness before
packaging.
Usage
# From the project root or anywhere with --path pointing at the Godot project
godot --path client --script tools/validate_map.gd -- res://maps/mymap.tscn
The -- separates Godot engine args from user args. The scene path must be a
res://-prefixed Godot resource path.
Exit Codes
| Code | Meaning | Description |
|---|---|---|
| 0 | PASS | All checks passed, no warnings |
| 1 | WARNINGS | Passed with non-blocking suggestions |
| 2 | ERRORS | Failed — must-fix items found |
Use exit codes in CI/CD pipelines to gate map merges:
godot --path client --script tools/validate_map.gd -- res://maps/mymap.tscn
if [ $? -eq 2 ]; then
echo "Map validation FAILED — fix errors before submitting"
exit 1
fi
Validator Modules
1. Scene Structure (validate_scene.gd)
- Scene root is a
Node3D - Required node types present:
WorldEnvironment,LightmapGI - Required Godot groups assigned to one node each:
ct_spawn,t_spawn,buy_zone,bomb_site,cubemap_origin - Node naming follows PascalCase convention
2. Polygon Count (validate_polycount.gd)
- Total mesh triangle count across all
MeshInstance3Dnodes ≤ 50,000 - Per-mesh breakdown printed for debugging
- Warns on individual meshes exceeding 5K triangles
- Warns if no
MeshInstance3Dnodes found (empty map)
3. Texture Sizes (validate_textures.gd)
- All material textures (albedo, normal, roughness, metallic, ORM, emission, AO) ≤ 1024×1024
- Checks
StandardMaterial3D,ORMMaterial3D, andShaderMaterial(Texture2D params) - Warns on textures > 512×512 (suggested for secondary surfaces)
- LightmapGI baked textures checked separately
4. Lights & Lightmap (validate_lights.gd)
- Dynamic (non-baked)
OmniLight3D+SpotLight3D≤ 4 DirectionalLight3Dcounts toward dynamic budget if light_bake_mode ≠ StaticLightmapGInode present and baked (light_data ≠ null)- Lightmap quality, bounces, texel scale, and max texture size checked
WorldEnvironmentconfigured with Environment resourceReflectionProbepresence and settings- Warns on dynamic lights with shadows enabled (performance cost)
Architecture
client/tools/
├── validate_map.gd # Main entry point: parses args, loads scene, runs modules
└── validate_map/
├── validate_scene.gd # Scene structure validator
├── validate_polycount.gd # Polygon count validator
├── validate_textures.gd # Texture size validator
└── validate_lights.gd # Light/lightmap validator
All modules are @tool RefCounted scripts exporting a single validate(scene_root: Node, scene_path: String) -> Dictionary function.
Adding a New Validator
- Create
tools/validate_map/validate_<name>.gdextendingRefCounted - Implement
func validate(scene_root: Node, scene_path: String) -> Dictionary - Return
{"pass": bool, "errors": [String], "warnings": [String]} - Add a
_run_module("<name>", instance, scene_path)call invalidate_map.gd:_ready()
Requirements
- Godot 4.x
- The map scene must be self-contained (all resources accessible via
res://paths) - Run from a terminal (not embedded in a running game)