ioquake / ioq3

The ioquake3 community effort to continue supporting/developing id's Quake III Arena
https://www.ioquake3.org/
GNU General Public License v2.0
2.34k stars 523 forks source link

Multiplayer in Emscripten builds! #673

Open jdarpinian opened 1 week ago

jdarpinian commented 1 week ago

This relies on the HumbleNet library to emulate BSD sockets over WebRTC DataChannel. Actual unreliable UDP packets are used so performance should be similar to native. WebRTC connection establishment requires a signaling server which is built separately.

The dedicated server binary can now be built in WASM and run in the browser. It should also be possible to build a native dedicated server (or client) with USE_HUMBLENET and connect it to browser clients over WebRTC via the same HumbleNet signaling server. However, this would require importing more code from humblenet and libwebrtc, and has not been tried yet.

NuclearMonster commented 1 week ago

Thank you for submitting this PR! I appreciate your effort in proposing HumbleNet as a solution for multiplayer. Before it’s potentially merged by another maintainer, I’d like to take a bit more time to carefully consider its inclusion. While I usually prefer adding new libraries to ioquake3 only when absolutely necessary, I believe it’s important to explore all options. I apologize if this feels like a delay, but my aim is to ensure we make the best possible decision. If anyone can highlight why this library is the optimal solution, that would be very helpful. I'm just not super familiar with what our options are here.

jdarpinian commented 1 week ago

Sure. The only way to do direct peer-to-peer communication and/or UDP-style unreliable/out-of-order delivery in all major web browsers today is WebRTC. Unfortunately WebRTC is a giant ball of complexity. Emscripten unfortunately provides no built-in way to use WebRTC. WebRTC at minimum requires a special signaling server to bootstrap the peer-to-peer connection.

HumbleNet takes WebRTC's complexity and hides it behind the BSD sockets interface. This means ioquake3's existing network code works almost entirely unchanged. It also provides an implementation of the required signaling server for establishing peer-to-peer connections.

Without HumbleNet, you could use Emscripten's built-in WebSockets support, but would lose peer-to-peer capabilities and be stuck with TCP instead of UDP. Or, you could try the relatively new WebTransport for UDP support, but it still doesn't support direct peer-to-peer connections. And Emscripten doesn't support WebTransport, so you would need to write a bunch of custom JS/C glue code. Or, similarly, you could write a bunch of custom JS/C glue code to use WebRTC directly, plus your own implementation of a separate signaling server. Or, you could use a different C/C++ library and signaling server for WebRTC, such as https://github.com/paullouisageneau/datachannel-wasm, but that one doesn't provide the BSD sockets API so you would need to write a new network backend for it instead of using the existing networking code as-is.