Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ endif()
if(EMSCRIPTEN)
set(SDL2_MIXER_FOUND TRUE)
set(HAVE_LIBSDL2_MIXER TRUE)
set(HAVE_NET TRUE)
set(HAVE_WEBSOCKET_NET TRUE)
else()
find_package(SDL2 2.0.7 REQUIRED)

Expand Down Expand Up @@ -258,6 +260,7 @@ else()
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} \
${SHARED_EMSCRIPTEN_FLAGS} \
-sASYNCIFY \
-sEMULATE_FUNCTION_POINTER_CASTS=1 \
-sFULL_ES2=1 \
-sINITIAL_MEMORY=64MB \
Expand Down
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,26 @@ Note that the choice of features you can bind (link) buttons to is currently lim
Networking Support
------------------

WebSockets support for multiplayer has not yet been added.
Browser multiplayer now uses a WebSocket relay transport.

It should be possible to connect to a WebSockets proxy to enable online play, but Dwasm will need rebuilding with the appropriate proxy configuration.
The game client still speaks the existing PrBoom packet protocol from `protocol.h`. The only transport change is that browser builds send and receive those packet bytes inside binary WebSocket frames instead of UDP datagrams.

The relay is expected to sit between the browser and the normal Doom server path:

- Browser client: binary WebSocket frames carrying raw Doom packet bytes.
- Relay/proxy: unwraps each frame and forwards the payload to the existing UDP server, and wraps UDP replies back into binary WebSocket frames.
- Native client/server: unchanged and still use the existing SDL_net UDP path.

To join a relay-backed server from the browser, pass the usual `-net` argument with a WebSocket URL or host:port pair. Examples:

https://127.0.0.1/?-net&wss%3A%2F%2Frelay.example%2Fdoom
http://127.0.0.1/?-net&ws://127.0.0.1:8000/doom

When the page is served over `https://`, the relay must also be reachable over `wss://` or the browser will block the connection as mixed content. Use `ws://` only from an `http://` page, localhost-style development setup, or another browser context that explicitly permits it.

If you use a bare `host:port`, Dwasm will automatically choose `ws://` or `wss://` to match the page, so an `https://` page will prefer a secure relay automatically.

Browser multiplayer keeps the network loop active even while the window is unfocused. This avoids browser clients falling behind and dropping from a live match just because the player switched to another window or browser during play.

Cheat Codes
-----------
Expand Down Expand Up @@ -220,6 +237,8 @@ Many soundfont compilations on the Internet can sound great sometimes, but terri

To build the main project, place `prboomx.wad` and other files (such as an IWAD) that you would like to include into the `wasm/fs` folder. All filenames must be in **lowercase**.

WebAssembly builds now enable the Doom client netcode by default and use Asyncify so the existing packet wait loops can yield safely while waiting for WebSocket traffic.

Next, run these commands in the Dwasm folder. Replace `/tmp/gl4es` with your GL4ES build, if applicable. If you decided not to include WebGL support, *completely* remove the option `-DGL4ES_PATH=/tmp/gl4es`.

mkdir build
Expand All @@ -236,6 +255,8 @@ The process will output the following into the `build` folder:

These files can then be placed on a web server. To reduce bandwidth and download time, compress all the files using GZip (or better, Brotli) compression, host the files statically, and verify the web browser is doing the decompression for each file.

For multiplayer, deploy a relay endpoint that accepts binary WebSocket frames and forwards the raw payload bytes to the existing Doom UDP server. The browser client does not speak JSON and does not change the packet layout.

A GZ-compressed build should be as little as (approximately) 1 megabyte, not including resources you add.

### Standalone / Single-File Version
Expand Down
1 change: 1 addition & 0 deletions cmake/config.h.cin
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#cmakedefine HAVE_LIBSDL2_IMAGE
#cmakedefine HAVE_LIBSDL2_MIXER
#cmakedefine HAVE_NET
#cmakedefine HAVE_WEBSOCKET_NET
#cmakedefine USE_SDL_NET

#cmakedefine HAVE_LIBPCREPOSIX
Expand Down
12 changes: 11 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,22 @@ set(MUS2MID_SRC
set(SDLDOOM_SOURCES
SDL/i_joy.c
SDL/i_main.c
SDL/i_network.c
SDL/i_sound.c
SDL/i_sshot.c
SDL/i_system.c
SDL/i_video.c
)

if(EMSCRIPTEN)
set(NET_TRANSPORT_SOURCE
WASM/wasm_network.c
)
else()
set(NET_TRANSPORT_SOURCE
SDL/i_network.c
)
endif()

set(PCSOUND_SOURCES
PCSOUND/pcsound.c
PCSOUND/pcsound.h
Expand Down Expand Up @@ -266,6 +275,7 @@ set(PRBOOM_PLUS_SOURCES
${WAD_SRC}
${MUS2MID_SRC}
${SDLDOOM_SOURCES}
${NET_TRANSPORT_SOURCE}
${PCSOUND_SOURCES}
${TEXTSCREEN_SOURCES}
${DOOMMUSIC_SOURCES}
Expand Down
2 changes: 1 addition & 1 deletion src/SDL/i_network.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void I_Disconnect(void)
* Sets the given socket non-blocking, binds to the given port, or first
* available if none is given
*/
UDP_SOCKET I_Socket(Uint16 port)
UDP_SOCKET I_Socket(unsigned short port)
{
if(port)
return (SDLNet_UDP_Open(port));
Expand Down
9 changes: 7 additions & 2 deletions src/SDL/i_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
#include "lprintf.h"
#include "doomtype.h"
#include "doomdef.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#ifndef PRBOOM_SERVER
#include "d_player.h"
#include "m_fixed.h"
Expand All @@ -101,9 +104,11 @@

void I_uSleep(unsigned long usecs)
{
#ifndef __EMSCRIPTEN__
#ifdef __EMSCRIPTEN__
emscripten_sleep((unsigned int)(usecs / 1000));
#else
SDL_Delay(usecs/1000);
#endif // !__EMSCRIPTEN__
#endif
}

#ifndef PRBOOM_SERVER
Expand Down
Loading