# 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 ```bash # 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: ```bash 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` + `SpotLight3D` ≤ **4** - `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_.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("", 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)