Asset request/response pipeline #6

Merged
kit merged 5 commits from feature/3-asset-pipeline into dev 2026-03-16 08:35:24 +00:00
Owner

Summary

Implements the asset delivery system (closes #3) so the web client can request and receive raw Source engine files from the server.

Server side (native module)

  • Handles asset_request JSON messages from WebSocket clients
  • Reads files via IFileSystem::Open() — transparently supports VPKs, workshop GMAs, and loose files
  • Path validation: extension whitelist (.mdl, .vtx, .vvd, .vtf, .vmt, .bsp, .phy, .ani, .wav, .mp3), rejects .. traversal and absolute paths
  • 64MB per-file size cap
  • Sends binary response: MSG_ASSET_DATA (0x10) header with path length + path + raw bytes

Client side

  • AssetCache class with IndexedDB persistence and in-memory hot cache
  • Deduplicates concurrent requests for the same asset path
  • Protocol parser (parseBinaryMessage) now dispatches both snapshot and asset binary frames
  • Connection.requestAsset(path) sends JSON request
  • connection.onAssetData / connection.onAssetError callbacks
  • Debug access via window.__webstream

Foundation for

  • #4 (BSP map rendering) — client can now request .bsp files
  • #5 (MDL model rendering) — client can now request .mdl/.vtx/.vvd/.vtf files

Test plan

  • Connect web client to a running GMod server with the module loaded
  • Verify handshake arrives with model table
  • Open browser console, run __webstream.assetCache.get('models/props_c17/oildrum001a.mdl') — should request from server and return ArrayBuffer
  • Verify the asset is cached in IndexedDB on subsequent calls
  • Attempt path traversal (../cfg/server.cfg) — should get asset_error response
  • Attempt disallowed extension (.lua, .cfg) — should get asset_error response
## Summary Implements the asset delivery system (closes #3) so the web client can request and receive raw Source engine files from the server. ### Server side (native module) - Handles `asset_request` JSON messages from WebSocket clients - Reads files via `IFileSystem::Open()` — transparently supports VPKs, workshop GMAs, and loose files - Path validation: extension whitelist (`.mdl`, `.vtx`, `.vvd`, `.vtf`, `.vmt`, `.bsp`, `.phy`, `.ani`, `.wav`, `.mp3`), rejects `..` traversal and absolute paths - 64MB per-file size cap - Sends binary response: `MSG_ASSET_DATA` (0x10) header with path length + path + raw bytes ### Client side - `AssetCache` class with IndexedDB persistence and in-memory hot cache - Deduplicates concurrent requests for the same asset path - Protocol parser (`parseBinaryMessage`) now dispatches both snapshot and asset binary frames - `Connection.requestAsset(path)` sends JSON request - `connection.onAssetData` / `connection.onAssetError` callbacks - Debug access via `window.__webstream` ## Foundation for - #4 (BSP map rendering) — client can now request `.bsp` files - #5 (MDL model rendering) — client can now request `.mdl`/`.vtx`/`.vvd`/`.vtf` files ## Test plan - [ ] Connect web client to a running GMod server with the module loaded - [ ] Verify handshake arrives with model table - [ ] Open browser console, run `__webstream.assetCache.get('models/props_c17/oildrum001a.mdl')` — should request from server and return ArrayBuffer - [ ] Verify the asset is cached in IndexedDB on subsequent calls - [ ] Attempt path traversal (`../cfg/server.cfg`) — should get `asset_error` response - [ ] Attempt disallowed extension (`.lua`, `.cfg`) — should get `asset_error` response
Server side:
- Read game files via IFileSystem (VPKs, workshop, loose files)
- Path validation: extension whitelist, no traversal, no absolute paths
- 64MB per-file size limit
- Binary response: MSG_ASSET_DATA (0x10) with path + raw bytes

Client side:
- AssetCache with IndexedDB persistence and in-memory hot cache
- Deduplicates concurrent requests for the same path
- Protocol parser handles both snapshot and asset binary frames
- Connection.requestAsset() sends JSON request to server

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace eiface.h include with engine_mini.h — a minimal wrapper that
  calls IVEngineServer methods through vtable offsets, avoiding the
  convar.h include chain that creates unresolvable tier1 link deps
- Change output extension from .so to .dll (GMod x86-64 uses .dll even
  on Linux)
- Default webstream_autostart to 1 and start immediately on require
  (Initialize hook may have already fired by autorun time)
- Expose camera and freecam on window.__webstream for debugging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
IFileSystem may not be thread-safe, so asset file reads must happen on
the game thread rather than the WebSocket callback thread. Requests are
now queued from the WS thread and processed in the Think hook via
process_asset_requests().

Verified working against a live GMod x86-64 server:
- MDL from VPK: 1788 bytes, correct IDST magic
- BSP map file: 36.7 MB, correct VBSP magic
- Path traversal (../cfg/server.cfg): rejected
- Disallowed extension (.lua): rejected

Also fixes modelTable handshake reference so debug access works.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Client now automatically requests all game assets when connecting:
- BSP map file on handshake
- MDL + VTX + VVD + PHY for each model in the model table
- New model IDs from snapshots trigger requests for late arrivals
- Brush models (*1, *2) are skipped (embedded in BSP)

Asset loading improvements:
- Failed paths (null) are cached in memory to prevent re-requests
- Optional companion files (.phy, .vtx, .vvd) log silently on failure
- HUD shows live asset count with loading indicator
- Fix modelTable handshake reference (merge into existing object)
- Fix HUD update timer (was comparing already-updated lastTime)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused queue_asset_request declaration from server.h
- Only .phy is truly optional — VTX and VVD are required for model
  rendering, so their errors should be visible when Phase 3 arrives

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
kit merged commit 74c8feb34c into dev 2026-03-16 08:35:24 +00:00
kit deleted branch feature/3-asset-pipeline 2026-03-16 08:35:25 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kit/gmod-web-stream!6
No description provided.