ioquake / ioq3

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

Multiplayer in Emscripten builds! #673

Closed jdarpinian closed 4 months ago

jdarpinian commented 5 months 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 5 months 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 5 months 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.

zturtleman commented 4 months ago

The code isn't very intrusive and the HumbleNet library is impressive for what it does. I'm personally not excited about adding it but I don't have major complaint if it does get added. (I haven't tested it and I don't plan to use it.)

It appears to expose the IP addresses of everyone who simply have the web client open to everyone connected to the HumbleNet WebRTC signal server. This is not good for privacy if deployed on the public Internet.

I'm leery of supporting peer-to-peer WebRTC for anonymous online game multiplayer at all due to inherently exposing the IP addresses of players to each other.


I'm personally not interested in web-only multiplayer but I would not want to add HumbleNet—an unmaintained C++ library with embedded TLS (SSL) library—to the game server to support web clients. Though I'm also not really interested in working on alternative methods for ioquake3 web client multiplayer as I don't have a game (with free data) I want to deploy on the public Internet and run a specific server application for the web clients.

It may be possible to use a SOCKS proxy (net_socksServer cvar) to connect to all Quake 3 game servers without any changes to the ioquake3 web client. This would be WebSocket to the SOCKS proxy and then be converted to UDP to the game server. I read @/briancullinan2 uses it for his web client but I don't know the details. A new issue could be opened for this if anyone has any interest or suggestion related to it.

NuclearMonster commented 4 months ago

Thank you for the PR and feedback. At this time I believe it's best to close this PR rather than leave it open. We may come back to HumbleNet at a later date, but for now I am not confident that merging this library is the right choice.