diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index abed1b1d..457a7e44 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -311,12 +311,14 @@ jobs:
node --test "port/web/tests/*.test.js"
python3 -m pytest -q tools/test_web_build.py
- - name: Test in Chromium
+ - name: Test in Chromium and Firefox
run: |
npm install --no-save --prefix "$RUNNER_TEMP/playwright" playwright@1.58
- "$RUNNER_TEMP/playwright/node_modules/.bin/playwright" install --with-deps chromium
+ "$RUNNER_TEMP/playwright/node_modules/.bin/playwright" install --with-deps chromium firefox
NODE_PATH="$RUNNER_TEMP/playwright/node_modules" node port/web/tests/smoke.mjs dist/halo-web-release
NODE_PATH="$RUNNER_TEMP/playwright/node_modules" node port/web/tests/rooms.mjs dist/halo-web-release
+ # (the native builds' WebRTC, port/linux/src/p2p_webrtc.c, with both)
+ NODE_PATH="$RUNNER_TEMP/playwright/node_modules" node port/web/tests/webrtc_native.mjs chromium firefox
- name: Compile cache
run: ccache --show-stats
diff --git a/AGENTS.md b/AGENTS.md
index 1520c37b..25d74530 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -90,6 +90,7 @@ python tools/test_light_storage.py
python tools/test_death_timing.py
python -m pytest -q tools/test_web_build.py # the web build's graph, sockets, menus
node --test "port/web/tests/*.test.js" # the web page's importer and service worker
+node port/web/tests/webrtc_native.mjs chromium firefox # the native builds' WebRTC with browsers (Playwright)
```
`tools/harness/README.md` explains how to add an asset-free test: the code
@@ -137,6 +138,11 @@ read `xbox/include`. To add a name, follow `port/include/xdk/README.md`.
do not play together.
- Only the host decides; clients predict their own players. Read
`port/linux/NETCODE.md` before changing the netcode.
+- Internet play is the same code in every build, the web's too: a browser's
+ tunnel is a WebRTC data channel (`port/web/src/web_p2p.c`), which the
+ native builds take on their tunnel's socket (`p2p_webrtc.c`, `posix_dtls.c`).
+ Check a change with both (`port/web/tests/webrtc_native.mjs`, and with the
+ maps `port/web/tests/internet.mjs`).
- Anything another machine sends is untrusted: check sizes, indices and
rates, as the existing handlers do. `debug.network_corrupt` tests this.
diff --git a/README.md b/README.md
index 20f0997e..7f6bec46 100644
--- a/README.md
+++ b/README.md
@@ -76,11 +76,13 @@ functions. These are almost the same on all platforms.
The game can play system link games on a local network and on the internet:
- A system link game can have up to 128 players on up to 128 machines.
-- Linux, Windows and Android machines can play in the same game. Browsers
- play each other in rooms, over WebRTC, as a local network
- ([port/web/README.md](port/web/README.md)); they cannot join the other
- builds' games (browsers have no UDP).
-- An invite link lets a machine join a game on the internet. No server of
+- Linux, Windows and Android machines and browsers can play in the same
+ game. On a local network, the native builds play system link; browsers
+ play each other in rooms, over WebRTC
+ ([port/web/README.md](port/web/README.md)).
+- An invite link, or the server browser, lets a machine join a game on the
+ internet, browsers too: a native build takes a browser's WebRTC
+ ([port/linux/README.md](port/linux/README.md), "Browsers"). No server of
this project is necessary.
- The netcode is new. Each machine moves its own player at once,
and the host makes the decisions for the game. Refer to
diff --git a/port/android/README.md b/port/android/README.md
index c3b1fc11..e82bc9c2 100644
--- a/port/android/README.md
+++ b/port/android/README.md
@@ -336,8 +336,9 @@ and supplies the thread pointer and TLS.
- Gives the audio callback of SDL to a thread with a guest stack
(`host/host_sdl.c`).
- Does the calls of the guest: system calls (`host/host_syscall.c`), SDL
- (`host/host_sdl.c`), OpenGL ES (`host/host_gl.c`), and the file and socket
- functions of `port/linux/src/posix_*.c`.
+ (`host/host_sdl.c`), OpenGL ES (`host/host_gl.c`), and the file, socket,
+ UPnP and DTLS functions of `port/linux/src/posix_*.c` (DTLS with Mbed TLS,
+ for internet play with browsers: `posix_dtls.c`).
The guest calls the host through stubs (`tools/android_imports.py`). The
two ABIs use the same registers for 32-bit integers, floats and pointers.
diff --git a/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.network_setup.xml b/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.network_setup.xml
index 16eba385..e10edc90 100644
--- a/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.network_setup.xml
+++ b/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.network_setup.xml
@@ -13,18 +13,18 @@
-
+
-
+
-
+
-
+
-
+
@@ -32,7 +32,7 @@
-
+
diff --git a/port/assets/network/brokers.txt b/port/assets/network/brokers.txt
index f583f8d7..e2966d2a 100644
--- a/port/assets/network/brokers.txt
+++ b/port/assets/network/brokers.txt
@@ -3,7 +3,9 @@
# them. The game uses every one at once (up to 4), so any one working is
# enough. One host:port on each line; "#" starts a comment.
# (The game reads this file beside config.toml: network.brokers_file. An
-# update replaces it; keep a list of your own under another name.)
+# update replaces it; keep a list of your own under another name. The web
+# build reaches the last three over their secure WebSockets:
+# port/linux/src/p2p_signal.c.)
opence.milenko.org:1883
broker.emqx.io:1883
broker.hivemq.com:1883
diff --git a/port/linux/NETCODE.md b/port/linux/NETCODE.md
index 95af6272..285bf5f8 100644
--- a/port/linux/NETCODE.md
+++ b/port/linux/NETCODE.md
@@ -184,7 +184,10 @@ lists a public game with a password with its invite's token sealed with the
password's key (`p2p_lobby.c`), a listing of another layout; version 21
sends each killing blow again reliably and an object come to rest three
times (a client waits for a player's blow before its body dies without one),
-and switches co-op's BSP on the host's crossing alone.
+and switches co-op's BSP on the host's crossing alone; version 26 has each
+machine say its WebRTC in internet play's signalling (a native build's
+certificate, a browser's ICE credentials too), so that browsers play
+(port/linux/README.md, "Browsers").
A client plays by its host's rules: in another's game (searching for it,
in its lobby, or playing it) the developer console, the telnet console
@@ -614,7 +617,10 @@ swap the bots' wandering does not reach (`debug.network_test_pickup_weapon`
picks the weapon: the first whose tag name has it in it, as "sniper"), and `debug.network_test_score`
shortens the game, to test the next (`host: