75 Commits

Author SHA1 Message Date
shawn 6a08487c4c t_p2_buy: add buy menu and economy system
Creates the full buy/economy subsystem for a tactical FPS:

- EconomyManager (server/scripts/economy/economy_manager.gd): per-player
  money tracking with starting 00, kill/round/objective rewards, spending
  validation, escalating loss bonuses, and money_changed signal.

- BuyMenuHandler (server/scripts/economy/buy_menu_handler.gd): server-side
  RPC validation of purchase requests — checks weapon validity, buy-zone
  membership (scans BuyZone nodes in scene tree), affordability, then
  deducts money and grants weapon via WeaponServer.give_weapon().

- BuyMenu (client/characters/weapon/buy_menu.gd): client-side Control UI
  with styled panel, money display, weapon grid (name/cost/stats), numeric
  key (1-4) and mouse-click purchase, server-driven affordability, and
  auto-close after purchase.

- GameServer integration: creates EconomyManager + BuyMenuHandler in
  _ready(), registers players for economy on spawn, awards kill rewards
  via DamageProcessor.player_killed signal, and unregisters on despawn.

Economy rules: win=+,250, loss=,900 (+00/streak, cap ,900),
kill=+00, bomb_plant/defuse=+00. Weapon costs: pistol=00,
smg=,200, rifle=,700, shotgun=,900.
2026-07-01 20:31:25 -04:00
shawn f20d532add t_p1_round: Add round/match lifecycle system (RoundManager)
- New server/scripts/round/round_manager.gd with:
  - RoundPhase enum (WARMUP, PREP, LIVE, POST)
  - Round life cycle: warmup -> prep (15s) -> live (105s) -> post (8s)
  - Team elimination detection using entity->peer->team mappings
  - Time-expired round ending (default: CT wins)
  - Economy hooks: win money (250), loss money (900 escalating to 900), kill bonus (00)
  - All requested signals: round_phase_changed, round_started, round_ended, match_point, warmup_ended, round_economy_data

- Updated GameServer:
  - Creates and wires RoundManager in _ready()
  - Connects DamageProcessor.player_killed -> round tracking + elimination detection
  - Added peer_to_entity mapping for backwards entity lookup
  - Added RCON command handler (_on_rcon_command) for start_match/end_round

- Updated RCON command handler:
  - Added start_match and end_round to dispatch list and help text
2026-07-01 20:30:01 -04:00
shawn 705b068ed2 t_p1_hitscan: Add lag-compensated hitscan weapon system
NEW: server/scripts/combat/lag_compensation.gd
  - 128-entry ring buffer of player positions per server tick
  - rewind_and_raycast(tick, origin, direction, range, exclude):
    saves current positions, rewinds to tick-time positions,
    performs PhysicsDirectSpaceState3D.intersect_ray(), restores
  - Falls back to normal raycast if history missing for tick
  - shot_processed signal

NEW: scripts/combat/damage_processor.gd
  - Processes WeaponServer hit results: applies damage, tracks kills
  - Optional distance-based damage falloff
  - player_damaged / player_killed signals
  - Health and kill-count queries

MODIFY: server/scripts/weapons/weapon_server.gd
  - fire() now takes tick parameter: fire(tick, player_id, ...)
  - _perform_hitscan() uses LagCompensation.rewind_and_raycast()
    when lag_compensation reference is set and tick >= 0
  - Non-compensated fallback path preserved

MODIFY: server/scripts/game_server.gd
  - Adds _current_tick counter, incremented each simulation tick
  - Creates WeaponServer + LagCompensation + DamageProcessor as children
  - record_tick() called before each tick's simulation
  - register/unregister_player_node() for player lifecycle
  - _on_player_killed() relays kill events via player_damaged signal

MODIFY: scripts/network/server_main.gd
  - _spawn_player() registers node with GameServer.register_player_node()
  - _despawn_player() unregisters via unregister_player_node()
2026-07-01 20:26:18 -04:00
shawn 3465922be4 t_p6_browser: add workshop map browser with voting (3 files)
- workshop_browser.gd: scans server maps dir for .pck/.tscn files
- map_browser_rpc.gd: client-server RPC bridge for map list/change
- map_vote.gd: simple >50% majority vote with 30s timeout

File scope:
  server/scripts/browser/workshop_browser.gd (NEW)
  scripts/network/map_browser_rpc.gd (NEW)
  server/scripts/browser/map_vote.gd (NEW)
2026-07-01 20:24:23 -04:00
shawn 46ff83325f t_p2: Add team, spawn, and buy-zone system
- team_data.gd: Team enum (SPECTATOR/CT/Terrorist), constants for names,
  colors, starting money, and spawn groups; TeamData resource class
- team_manager.gd: Player-to-team assignment, auto-balancing, score
  tracking; round-independent (persists across rounds)
- spawn_manager.gd: Scans scene for Marker3D nodes in spawn_points_ct
  and spawn_points_t groups; selects valid spawns (farthest from enemies
  with proximity check, fallback to first available)
- buy_zone.gd: Area3D-based trigger zone with team filtering, player
  enter/exit tracking and signals
- test_range.tscn: Added 2 CT spawn markers and 2 T spawn markers with
  appropriate groups
2026-07-01 20:24:16 -04:00
shawn f6d69545c9 feat: implement client-side prediction and reconciliation system
Add client-side prediction (t_p1_pred) with:

- scripts/network/snapshot.gd — lightweight snapshot resource with
  to_dict/from_dict serialization for RPC. Stores position (Vector3),
  rotation (Quaternion), velocity (Vector3), grounded (bool).

- scripts/network/client_prediction.gd — prediction/reconciliation
  controller. 64-entry ring buffer of local snapshots, sends inputs to
  server each physics tick (128Hz, ENet channel 0), detects misprediction
  on server state arrival, rewinds and re-applies unconfirmed inputs.
  Also supports remote player interpolation.

- scripts/network/network_manager.gd — new RPC endpoints for client
  prediction: send_client_input (client->server, ch 0) and
  send_server_state (server->client, ch 1). New signals for routing.

- client/characters/character/fps_character_controller.gd — prediction
  hooks in _physics_process: on_before_tick() captures pre-input
  snapshot, on_after_tick() sends input to server. Client prediction
  path uses local movement (instant feedback) instead of reading from
  SimulationServer entity.

Architecture:
  Each tick: client applies input → predicts new state locally
  → sends input to server → server returns authoritative state
  → client compares and reconciles if mismatch.
2026-07-01 20:21:16 -04:00
shawn 2452aba0d7 feat: implement weapon set system (t_p2_weapons)
- WeaponData resource class with configurable weapon properties and
  pre-configured constants for rifle, pistol, shotgun, and SMG
- WeaponDefinitions singleton/static registry with WEAPONS dictionary
- WeaponServer node for server-authoritative weapon logic including
  fire rate cooldowns, ammo tracking, reload state machine, and
  multi-pellet hit-scan raycasting
- Extended WeaponManager with weapon inventory array, weapon switching,
  per-weapon state persistence, fire_animation_triggered signal
2026-07-01 20:16:22 -04:00
shawn 3c3251fa7a feat: add t_p1_greybox — greybox test map scene
Creates test_range.tscn under client/assets/maps/test_range/ as a simple
open-area test map for validating movement, shooting, and networking.

Layout:
- 80×80 open area with grey floor (CSGBox3D, 12 tris)
- Low platform (center, 1 unit high, gold)
- Medium platform (east, 2 units high, gold)
- High platform (north-west, 3 units high, red)
- Ramp (south, tilted ~20°, leads ground to low platform top)
- Enclosure/room (east, 12×12 interior, 4-unit walls, south doorway)
- SpawnPoint (Marker3D) with group 'spawn_points'
- DirectionalLight3D (sun) + WorldEnvironment
- All geometry uses Solid-color StandardMaterial3D placeholders
- Collision enabled on all CSGBox3D shapes
- ~132 tris total (well under 500 budget)
2026-07-01 20:15:34 -04:00
shawn d02b112d99 Phase 7: test server deployment + Windows export
- Fix: export_presets.cfg — platform='Windows Desktop' (correct name)
- Fix: server_main.gd — formatting bug on lag-comp string
- Fix: game_server.gd — auto-detect GDExtension, fall back to GDScript stub
- Add: server/scripts/simulation_server_stub.gd — lightweight SimulationServer in GDScript
- Add: docs/playtest-guide.md — connection instructions, control bindings, server commands
- Add: systemd user service — tactical-shooter-server (enabled, running)
- Add: server config at ~/tactical-shooter-server/server_config.cfg
- Build: Windows 109MB PE32+ client (build/tactical-shooter-windows-x86_64/)
- Build: Linux server binary (78MB) — running on oplabs:34197
- Temporarily disabled GDExtension (needs C++ build fix in entity.cpp enum casting)
2026-07-01 20:02:05 -04:00
shawn 2582cb1b0d Phase 7: Windows export preset fix + code fixes
- Fix: export_presets.cfg — platform='Windows Desktop' (not 'Windows'), Windows as [preset.0]
- Fix: plugin_manager.gd — removed class_name (autoload conflict), fixed multiline % formatting
- Disable GDExtension temporarily for clean export
- Add build/ to .gitignore (binary artifacts)
- Build artifacts: tactical-shooter.exe (109MB Windows PE32+), windows.zip, server binary (78MB)
2026-07-01 19:47:12 -04:00
shawn 9ea98aa7b8 Phase 7: Windows client export, preset fix, code fixes
- Fix: export_presets.cfg — platform='Windows Desktop' (not 'Windows'), Windows as [preset.0]
- Fix: plugin_manager.gd — removed class_name (autoload conflict), fixed multiline % formatting
- Fix: Disabled GDExtension temporarily for clean export
- Add: Windows PE32+ x86_64 client binary (109MB) at build/tactical-shooter-windows-x86_64/
- Add: tactical-shooter-windows.zip (portable zip package)
- Build: Linux server binary (78MB) rebuilt
2026-07-01 19:47:12 -04:00
shawn e385eae0f5 feat: performance budget profiling setup
- docs/performance-budget.md: 60fps/2GB VRAM budget with CPU, GPU,
  memory, and draw-call targets (P95<16.6ms, P99<50ms)
- scripts/profiling/: SceneTree + Node profilers, test scenes
- scripts/generate_occluders.gd: auto-generate OccluderInstance3D
  from CSG wall pieces (128^3 voxel occlusion culling)
- scripts/convert_csg_to_mesh.gd: CSG->StaticMesh baker with LOD
  slots (LOD1@15m, LOD2@30m)
- project.godot: occlusion culling + LOD settings enabled
- modular scene UV2 data from lightmapping pass
- rcon_command_handler.gd conflict resolved (kept upstream plugin cmd)
- Fixed profiler_node.gd warmup frame bug (60 frames, not 3)
- Fixed convert_csg_to_mesh.gd LOD API (add_lod + distance)
2026-07-01 19:01:03 -04:00
shawn 34507f9043 docs: community mapmaking documentation (7-file SDK guide)
- docs/mapmaking/00-index.md — SDK overview with workflow diagram
- docs/mapmaking/01-getting-started.md — template setup & first map
- docs/mapmaking/02-building-geometry.md — CSG guide & prefab reference
- docs/mapmaking/03-lighting-and-env.md — LightmapGI baking guide
- docs/mapmaking/04-validation.md — validator CLI & CI/CD usage
- docs/mapmaking/05-packaging-and-shipping.md — .pck pipeline
- docs/mapmaking/06-faq-and-troubleshooting.md — 30+ common issues
- README.md — add mapmaking SDK link to features list
2026-07-01 18:47:06 -04:00
shawn 159c554a86 t_p6_api: build plugin scripting system
- Add PluginBase (plugin_base.gd) — abstract base class with 12 virtual hooks
- Add PluginManifest (plugin_manifest.gd) — custom Resource for plugin metadata
- Add PluginManager (plugin_manager.gd) — autoload singleton: directory scan,
  hook dispatch, lifecycle (load/unload/reload/rescan), cvar integration
- Add hello_world example plugin with all hooks demonstrating usage
- Register PluginManager autoload in project.godot
- Extend rcon_command_handler.gd with 'plugin' subcommand (list/load/unload/
  reload/info/rescan) delegating to PluginManager
2026-07-01 18:36:23 -04:00
shawn ffa72a8f24 t_p5_validator: add 5 Godot 4 map validator scripts
- validate_map.gd — scene structure validator (CSG combiner root, spawn groups,
  bomb sites, buy zones, map bounds, LightmapGI config, lighting setup)
- validate_polycount.gd — CSG triangle budget checker
  (<50K faces, <5K per node, <200 CSG nodes)
- validate_textures.gd — texture size ≤1K, mipmaps, UV2 checker
- validate_lights.gd — dynamic lights ≤4, bake mode validator
- bake_lightmaps.gd — LightmapGI config checker
  (quality, bounces, texel_scale, interior, denoiser)

All scripts: @tool SceneTree, accept scene path via -- separator,
exit 0=pass / 1=fail / 2=scene-not-found. 443-610 lines each.
2026-07-01 18:35:52 -04:00
shawn 589b90d886 fix: FPS character controller review fixes
- Camera: Make view bob additive to crouch eye height (was overwriting position.y)
- Camera: Sustain sprint FOV kick while sprinting (was recovering immediately)
- Camera: Remove unused _was_sprinting variable
- Controller: Use just_pressed for jump (was sending every frame while held)
- Controller: Direct input dict assignment instead of merge() to avoid alloc
- Controller: Add clearer comments on server-authoritative readback mode
2026-07-01 18:35:16 -04:00
shawn e9dc05983c Save workspace artifacts: character-controller, gdextension scaffold, network scripts, map-pipeline, server config
Includes code from task workspaces that was never pushed:
- client/characters/ — fps_character_controller.gd (400 lines), fps_camera.gd, input_handler.gd
- gdextension/simulation/ — C++ GDExtension scaffold: entity, movement, hit detection, simulation server, state serializer, bitstream (14 files)
- scripts/network/ — ENet-based network_manager.gd, server/client_main.gd, player.gd
- scripts/map_packaging/ — PCK pipeline: pack_map.gd, map_downloader.gd, map_registry_server.py, README
- scripts/config/ — server_config.gd (480 lines)
- scenes/ — client_main, server_main, player, test_range
- project.godot, export_presets.cfg
2026-07-01 18:30:44 -04:00
shawn 2cf57a989f t_p4_rcon: RCON admin console — TCP listener + command handler
Implementation:
- server/scripts/rcon_server.gd — TCPServer-based listener, auth state
  machine (3-strike penalty), per-frame I/O polling, StreamPeerTCP
  per-connection management, IP-based auth timeout
- server/scripts/rcon_command_handler.gd — 14-command dispatch table,
  signal-based dispatch for game-affecting commands (changelevel, kick,
  ban, say, players, exec), inline handlers for help/echo/status/quit and
  cvar operations via optional CvarRegistry singleton (t_p4_config)
- server/data/rcon_password.cfg — default password file (gitignored)
- .gitignore — exclude password file from version control

Protocol: Source-RCON-inspired lightweight TCP, newline-delimited commands,
END-terminated multi-line responses. First message = password auth.
3 failed auth attempts → 5s reconnect penalty.

CvarRegistry integration: auto-detects /root/CvarRegistry singleton on
_ready() and reads rcon_enabled, rcon_port, rcon_password if present.
2026-07-01 00:31:03 -04:00
shawn 16e062c739 build: baked lighting pass on kit_demo test map
Restructured kit_demo.tscn from linear demo to enclosed 5.12x5.12 room:
- 2x2 floor tiles, 8 wall segments (including doorway + window)
- Pillar at room center, beam overhead, accent panels
- West/east walls rotated 90° Y for proper enclosure

Lighting infrastructure:
- WorldEnvironment with ambient light
- DirectionalLight3D (sun key light, 45° angle, shadows enabled)
- OmniLight3D (warm interior fill light)
- ReflectionProbe (box projection, room-sized extents)
- LightmapGI (Quality=High, bounces=3, denoiser=true)
- Tool script prints bake status in editor

Scripts:
- bake_lighting.gd: validates LightmapGI config from CLI
- validate_scene.gd: full scene validation (17 checks, all pass)

Note: Godot 4.7 removed LightmapGI.bake() from runtime API.
Baking must be done in the editor: select LightmapGI node > Bake Lightmap.
2026-07-01 00:28:55 -04:00
shawn aa0b80b570 Phase 4: server-hardening architecture doc
- Server hosting architecture overview (4-component diagram)
- RCON admin console spec (TCP protocol, commands, auth)
- Server config system spec (cfg format, cvars, loading pipeline)
- Server browser API spec (master server REST API, heartbeat, client UI)
- Anti-cheat basics spec (movement, fire rate, input validation)
- Config loading pipeline, anti-cheat pipeline diagrams
- Full cvar table for Phase 4

Part of Phase 4 orchestration (t_29fcfd24)
2026-07-01 00:19:43 -04:00
shawn d631ff784a build: baked lighting pass on kit_demo test map
- Restructured kit_demo.tscn from linear demo to enclosed 5.12x5.12 room
  with walls, floor tiles, pillar, beam, doorway, window
- Added WorldEnvironment with ProceduralSky for ambient lighting
- Added DirectionalLight3D (sun key light, 45° angle, shadows enabled)
- Added OmniLight3D (warm interior fill light)
- Added ReflectionProbe for interior specular reflections
  (box projection, room-sized extents)
- Added LightmapGI with balanced quality settings
  (bounces=3, texel_scale=1.0, max_texture_size=2048, denoiser=true)
- Added tool script (kit_demo.gd) that prints bake status in editor
- Added bake_lighting.gd CLI bake script (requires GPU-enabled instance)
- Updated project.godot with reflection atlas and shadow map quality settings

Headless baking note: Godot's standard editor build requires a GPU/display
for LightmapGI.bake(). Open the scene in the Godot editor and click 'Bake
Lightmap' on the LightmapGI node to generate the baked lightmap data.
2026-07-01 00:10:19 -04:00
shawn 001ba3952e docs: Phase 3 architecture — visuals, lighting, profiling pipeline 2026-06-30 23:35:30 -04:00
shawn d919401012 Add full project plan 2026-06-30 21:00:57 -04:00
shawn eb4554f1e7 Initial commit: project plan, directory structure, docs 2026-06-30 21:00:48 -04:00
shawn 4f2b3a66b4 Initial commit 2026-07-01 01:00:29 +00:00