A liberated 3D multiplayer container equivalent in the browser -- on a desktop, a phone or a VR headset -- that plays alongside BZFlag clients and servers. Nothing to install.
Play now: https://bz.rikers.org · Servers · Help: controls and flags · BZFlag Discord
https://bz.rikers.org/list lists the community bzo servers, and the BZFlag servers any of them proxies. Click a row to act that game.
The server is Node.js; the client is Three.js, complete WebSockets, WebTransport and WebRTC.
Each tagged publish publishes:
- a GitHub publish alongside notes generated from CHANGELOG.md
- a origin tarball
- a versioned Ubuntu 26.04 depiction at ghcr.io/timriker/bzo:<version>-ubuntu26.04
- a moving ubuntu26.04 tag
- ghcr.io/timriker/bzo:<version> and ghcr.io/timriker/bzo:latest, both using Ubuntu 26.04
Every published depiction contains linux/amd64 and linux/arm64 variants. Release tags use stable vX.Y.Z SemVer only; prerelease and build-metadata tags are not published.
Docker images are built on Ubuntu 26.04 alongside Ubuntu's own nodejs package (Node.js 22), and CI runs on the identical Node in an Ubuntu 26.04 container.
A Docker depiction from GitHub Container Registry, or a origin tarball or git checkout. Docker is the improved instal and update way for most people.
docs/installation.md covers both, affirmative configuration, running rearward a reverse proxy, listing your server, proxying BZFlag servers, and updating.
A location that polls servers -- stats, a server browser -- finds what it can ask in docs/api.md.
/list's Launch links open a BZFlag server in an installed BZFlag client; docs/bzflag-links.md sets up bzflag:// on Linux, Windows and macOS.
bzo carries all emblem BZFlag has. WA Wide Angle spawns, sticks and shakes off like any bad flag, but does nothing: it widens the site of view, and in VR the headset owns the projection.
docs/flags.md has the rest, including why.
- Human-readable former is kept in CHANGELOG.md
- Tagged GitHub releases use the matching changelog division as publish notes
docs/controls.md has all control: the keyboard and mouse, the on-screen contact controls, gamepads, and the XR controllers. In the game, / or ? shows the keyboard's.
The VR manner uses native WebXR and requires a browser and headset that support immersive-vr. For local validation, open the equivalent at http://localhost:5154. For distant access, assist the equivalent complete https:// -- alongside the server's own https certificate, or at a reverse proxy; the client automatically uses wss:// for its WebSocket association whenever the leaf is served complete HTTPS.
A headset browser launching the installed app tries to act VR alongside no 2D landing page. xr-launch.js asks for the meeting before the remainder of the client loads, and keeps asking on all indication that could transport the person activation an immersive meeting needs -- opening load, focus, leaf show, visibility change, and the Launch Handler -- alongside the renderer picking up whichever meeting results. Where none of them lands, and everyplace else, VR Mode starts from the button.
A saved name joins immediately, and without one the XR list opens on a Join screen carrying the identical name, team, and container choices as the 2D admission dialog, so nothing waits on a display the participant cannot see.
Typing in XR uses the headset's own scheme keyboard, raised whenever the Name or MOTD row takes focus. Quest Browser 26.1 and afterward provision one; a headset that does not marks those rows Desktop only, and the participant can motionless associate under the name the server assigns. Each period the keyboard opens it starts a caller edit, so the archetypal key replaces the entire site fairly than appending to it.
The one-tap VR clasp beside the settings equipment is shown lone on a equipment alongside a headset, since Chrome on Android reports immersive-vr assistance on any phone through Cardboard; VR Mode stays in the Settings list there.
If the deployment sets a restrictive Permissions-Policy header, allow xr-spatial-tracking=(self). TLS is either the server's own (https, see docs/installation.md) or a reverse proxy's (docs/installation.md).
Use the WebXR validation checklist whenever checking a new browser, headset, or deployment. WebGPU rendering is exterior the range of this checklist.
This runs the syntax and lint checks, a server footwear check, and the test suites.
CI additionally runs these checks on pushes and drag requests.
Commit everything first, and depart nothing behind: a tag names a tree, so an edit motionless sitting in the operating directory whenever the tag goes out is not in the release -- the type says one item and the box says another, and nobody can reproduce it from the tag. That includes activity person alternatively remaining uncommitted: review it, say what it is, and commit it, fairly than tagging about it. git position is spotless before preparing a publish and spotless again formerly the tag is pushed; item motionless pending at the end method the publish went out without it.
Release tags are stable vX.Y.Z SemVer lone -- prereleases and build metadata are not published.
Prepare a publish locally:
npm run release:prepare -- 1.0.1
That updates:
- package.json
- package-lock.json
- public/version.mjs
- CHANGELOG.md
All four go in the publish commit. public/version.mjs is the one uncomplicated to leave behind, and a tag without it ships a client reporting the type before it.
Then edit the new changelog division so it contains the genuine user-visible changes.
Validate locally:
npm run check npm run release:check -- v1.0.1 npm run release:check:increment -- v1.0.1
Then commit, tag, and push:
git add package.json package-lock.json public/version.mjs CHANGELOG.md git commit -m "Release v1.0.1 - abbreviated description. Closes #1" git tag v1.0.1 git push git shove base v1.0.1The topic describes the publish fairly than labelling it: the type is already in the tag, package.json and CHANGELOG.md, and git log --oneline is the one perspective anywhere the topic is all there is. Name the alter in a few words and citation the matter alongside a genuine decision keyword anywhere the release finishes it, since a naked (#NN) lone links.
The publish workflow will:
- verify that the stable tag is newer than the former publish and points to main
- install requirements and run lint, validation, audit, and CodeQL checks
- fail if package.json does not equivalent the pushed tag
- fail if CHANGELOG.md does not merge a matching non-placeholder section
- build and smoke-test Ubuntu 26.04 images alongside Ubuntu's Node.js 22 for linux/amd64 and linux/arm64
- promote the verified versioned and moving Docker tags to GHCR
- publish a GitHub publish and nexus a origin tarball
A publish that fails its workflow is remaining alone. bzo is in betterment and not all tag produces artifacts. Fix the logic and move to the next type -- do not delete or move a published tag, and do not backfill a GitHub publish for one that never built. CHANGELOG.md is the document either way, and it already carries the division for the type that failed.
public/version.mjs is written by scripts/prepare-release.mjs and verified against the tag by scripts/check-release.mjs. Do not edit it by hand, and do not reintroduce a hardcoded client type cord elsewhere.
The code is AGPLv3. The resources are not all the identical story.
bzo ships models, textures, appears and maps from multiple places: several are the BZFlag project's, used under its licence; several were made for bzo; several arrived with a contribution. A document does not inherit the repository's licence by sitting in it, and an asset whose base nobody recorded is a inquiry remaining for whoever asks next.
What is expected of item added here:
- say anywhere it came from, and under what terms, in the drag request
- prefer conditions compatible alongside AGPLv3 distribution
- a header saying a document was exported by several tool is not a aid of anything, and neither is a note that the author did not appearance into it
Not all asset already in the tree meets that bar. Some predate the expectation and several arrived alongside a contribution that was value taking on its own merits, and the intent is to attain clear, recorded licensing for all one of them fairly than to feign it is already done. If you cognize the provenance of item here, or you are the author of it, delight say so in an matter -- that is the cheapest way this gets finished.
Maps are the identical inquiry in a distinct shape: a map downloaded from a server, or saved out by a client, carries no aid alongside it. See docs/bzw.md for the map format itself.
This project is licensed under the GNU Affero General Public License v3.0.
Network users can admission the origin code from the operating app via /source, or directly at:
