Files
tactical-shooter/client/tools/validate_map
shawn e7299b17e9 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)
2026-07-02 17:39:22 -04:00
..

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 MeshInstance3D nodes ≤ 50,000
  • Per-mesh breakdown printed for debugging
  • Warns on individual meshes exceeding 5K triangles
  • Warns if no MeshInstance3D nodes found (empty map)

3. Texture Sizes (validate_textures.gd)

  • All material textures (albedo, normal, roughness, metallic, ORM, emission, AO) ≤ 1024×1024
  • Checks StandardMaterial3D, ORMMaterial3D, and ShaderMaterial (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 + SpotLight3D4
  • DirectionalLight3D counts toward dynamic budget if light_bake_mode ≠ Static
  • LightmapGI node present and baked (light_data ≠ null)
  • Lightmap quality, bounces, texel scale, and max texture size checked
  • WorldEnvironment configured with Environment resource
  • ReflectionProbe presence 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

  1. Create tools/validate_map/validate_<name>.gd extending RefCounted
  2. Implement func validate(scene_root: Node, scene_path: String) -> Dictionary
  3. Return {"pass": bool, "errors": [String], "warnings": [String]}
  4. Add a _run_module("<name>", instance, scene_path) call in validate_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)