- assets/audio/music/zombie_industrial_loop.ogg: 57.60 s Ogg Vorbis loop generated locally with YuE2-3B on the Tesla V100 (score written for this track; vocals removed with HTDemucs). The loop is spliced at the track's structural repeat with a 0.6 s crossfade: measured seam dip <= 1.6 dB. - scripts/main.gd: "Music" AudioStreamPlayer at -11 dB, started at boot on desktop and on the start click on Web (browser autoplay policy). It forces stream.loop at runtime because the Web staging step re-imports the OGG with loop=false. - tools/test_music.gd: soundtrack test (loop, length, volume, playback, still playing after player death). - docs/MUSIC.md: source, loop construction, verification, licence. - docs/WEB-DEPLOY.md: release ab6054111f5919a8 notes. Initial commit of the project.
4.7 KiB
Web build and compressed deployment
URL: https://enne2.net/pub/zombie-fps/ Server: debian@enne2.net (bastion). Web root: /home/debian/public_html/zombie-fps/.
Build
Use installed Godot 4.7.1 executable, not the Godot 4.3 on PATH:
G="$HOME/.local/opt/godot-4.7.1/Godot_v4.7.1-stable_linux.x86_64"
"$G" --headless --path /home/enne2/dev/zombie-fps --script res://tools/export_web_assets.gd
python3 /home/enne2/dev/zombie-fps/tools/prepare_web.py
"$G" --headless --path /home/enne2/dev/zombie-fps/build/web-stage --import
mkdir -p /home/enne2/dev/zombie-fps/build/web
"$G" --headless --path /home/enne2/dev/zombie-fps/build/web-stage --export-release Web /home/enne2/dev/zombie-fps/build/web/index.html
python3 /home/enne2/dev/zombie-fps/tools/package_web_release.py
Staging excludes native addons, source MDL assets, unused world weapon scenes, extraction tools. Runtime uses native SCN models. Web renderer is Compatibility, with CPU particles and floor blood patches instead of Forward+ decals. Browser click starts waves and captures mouse. Single-thread Web export does not require cross-origin isolation server headers.
Versioned compression
package_web_release.py computes a content hash, writes build/web-deploy/releases// and gzip level 9 sidecars, verifying decompression. Original and gzip mtimes match. Root index.html uses a base href to the immutable release directory; original fileSizes remain uncompressed sizes as expected by Godot. Originals remain available for clients rejecting gzip.
Upload new immutable directory first, never overwrite an existing hash. Then atomically replace root index.html. Keep previous releases for open tabs/rollback. Do not delete them during routine deployment.
Nginx snippet source: tools/nginx-zombie-fps.conf. Installed at /etc/nginx/snippets/zombie-fps.conf and included only by enne2.net's HTTPS server in /etc/nginx/conf.d/enne2.conf. gzip_static on, Vary Accept-Encoding, correct application/wasm MIME. Root HTML no-cache; versioned files public,max-age=31536000,immutable. Other /pub/ sites unchanged. No Brotli module installed.
Protected configuration backup: /etc/nginx/zombie-fps-backup-9d706e724b0a/. Original root HTML backup: /home/debian/zombie-fps-backups/index-before-compression.html. Tools/apply_nginx_compression.py validates nginx -t, reloads, and restores config on failure. Always obtain approval for server changes.
Verified release 7d3c1fb9d96da215
- Main text/binary payloads: 42,303,791 -> 11,035,976 bytes (gzip, ~74% reduction).
- WASM: 39,513,091 -> 10,074,664 bytes.
- PCK: 2,495,216 -> 887,112 bytes.
- JS: 279,815 -> 68,657 bytes.
- HTTPS downloaded gzip responses decompress exactly to local files; hashes match.
- identity and gzip;q=0 clients receive originals. Vary header present.
- Browser first load: WASM transfer 10,074,964 bytes including resource-timing overhead; PCK 887,412. Resource durations ~513/522ms on frigate's connection (not universal startup time).
- Browser reload: WASM/PCK/JS transferSize 0; cache reads ~16/4/4ms. Godot loading overlay removed, game initialized on both loads.
This reduces network transfer, not engine compile/initialization cost. Further gains would require a custom stripped Godot Web template; not built here. Valve copyrighted assets remain subject to redistribution rights; user explicitly stated the necessary rights for public deployment.
Verified release ab6054111f5919a8 (soundtrack)
First release that ships the looping industrial metal soundtrack (see docs/MUSIC.md).
- PCK: 2,568,000 -> 3,632,524 bytes (+1,064,524, i.e. the 1.0 MB Ogg Vorbis was the only new payload).
- All payloads: 43,441,099 -> 12,089,938 bytes gzip.
- Uploaded 14 files as a new immutable directory; remote sha256 identical to local for all 14; previous releases kept (4e181f0fe5d02cc9, 7d3c1fb9d96da215, 7d55da56077f8eee).
- Root index.html replaced by atomic rename; backup at /home/debian/zombie-fps-backups/index-before-music.html.
- HTTPS: root 200 text/html no-cache with the new base href; PCK byte-identical after gzip decode (3,632,524 bytes); versioned files application/wasm, Vary, immutable one year.
- Browser: Godot 4.7.1, WebGL 2.0 Compatibility, single-threaded; the click starts wave 1 (HUD
ONDATA 1, 250 points) with zombies, blood decals and the damage vignette.
Staging trap: prepare_web.py ignores *.import, so the staging project re-imports the OGG with loop=false. main.gd sets stream.loop at runtime; this was verified in exactly that condition by running test_music inside build/web-stage with the PulseAudio driver (loop false at load -> true after setup, playback advancing).
Bastion disk: 1.4 GB free on / (97% used). Do not accumulate releases without checking space, and delete old ones only with approval.