Home

Awesome

Please refer to DelayNoMoreUnity for a Unity rebuild with .net backend.

Preface

This project is a demo for a websocket-based rollback netcode inspired by GGPO.

Demo recorded over INTERNET (Phone-Wifi v.s. PC-Wifi UDP holepunched) using an input delay of 6 frames, and it feels SMOOTH when playing!

Merged_cut_annotated_spedup

(battle between 2 celluar 4G users using Android phones, original video here)

Phone4g_battle_spedup

Since v1.0.13, smoothness in worst cases (e.g. turn-around on ground, in air and after dashing) is drastically improved due to update of prediction approach. The gifs and corresponding screenrecordings above are not updated because there's no big difference when network is good -- however, input delay is now set to 4 frames -- while input delay = 6 frames was used in the screenrecordings -- and smoothness is even better now (well there's a new screenrecording for PcWifi vs Android4g here). Key changes are listed below.

As lots of feedbacks ask for a discussion on using UDP instead, I tried to summarize my personal opinion about it in ConcerningEdgeCases -- since v0.9.25, the project is actually equipped with UDP capabilities as follows.

Notable Features

(how input delay roughly works)

input_delay_intro

(how rollback-and-chase in this project roughly works)

server_clients rollback_and_chase_intro

(By use of GopherJs, the frontend codes for dynamics are now automatically generated) floating_point_accumulation_err

1. Building & running

1.1 Tools to install

Backend

Frontend

1.2 Provisioning

Backend/Database

It's strongly recommended that skeema is used for provisioning the required schema in MySQL instance. When using skeema the steps are as follows.

### Mandatory after an initial clone
user@proj-root/database/skeema-repo-root> cp .skeema.template .skeema

### Mandatory
user@proj-root/database/skeema-repo-root> skeema push

On Windows 10/11, you can compile skeema from source and config the host to be 127.0.0.1 instead of localhost to use it, i.e. circumventing the pitfall for MySQL unix socket connection on Windows.

Backend/Golang

user@proj-root/battle_srv/configs> cp -r ./configs.template ./configs

Frontend

user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js

1.3 Actual building & running

Backend

### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself
user@anywhere> mysqld

### The following command runs redis-server in foreground, it's OK to put it in background
user@anywhere> redis-server

### on Windows using TDM-GCC: mingw32-make run-test 
user@proj-root/battle_srv> make run-test

Frontend

The easy way is to try out 2 players with test accounts on a same machine.

How-to-play-1

How-to-play-2

How-to-play-3

How-to-play-4

2 Troubleshooting

2.1 Redis snapshot writing failure

ErrFatal        {"err": "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error."}

Just restart your redis-server process.

2.2 Why not show "PING value" on frontend display?

The most important reason for not showing "PING value" is simple: in most games the "PING value" is collected by a dedicated kernel thread which doesn't interfere the UI thread or the primary networking thread. As this demo primarily runs on browser by far, I don't have this capability easily.

Moreover, in practice I found that to spot sync anomalies, the following tools are much more useful than the "PING VALUE".

There's also some useful information displayed on the frontend when true == Map.showNetworkDoctorInfo. networkstats

2.3 WIN32 platform tool versioning

visual_studio When building for native platforms, it's much more convenient to trigger the CocosCreator project forming frmo CLI, e.g.

shell> cd <proj-root>
shell> /path/to/CocosCreator.exe --path ./frontend --build "platform=win32;debug=true"
shell> cd ./frontend/build/jsb-link/frameworks/runtime-src/proj.win32 && MSBUILD DelayNoMore.vcxproj -property:Configuration=Debug

or

shell> cd <proj-root>
shell> /path/to/CocosCreator.exe --path ./frontend --build "platform=win32;debug=false"
shell> cd ./frontend/build/jsb-link/frameworks/runtime-src/proj.win32 && MSBUILD DelayNoMore.vcxproj -property:Configuration=Release

for release.

If MSBUILD command is not yet added to PATH, Use Get-Command MSBUILD in Developer Command Prompt for VS 2017/2019 to see where the command should come from and add it to PATH.

Similarly for Android release build

shell> cd <proj-root>
shell> /path/to/CocosCreator.exe --path ./frontend --build "platform=android;debug=false"
shell> cd ./frontend/build/jsb-link/frameworks/runtime-src/proj.android-studio && ./gradlew assembleRelease

2.4 CococCreator native build reloading

CocosCreator doesn't have perfect file cache management during native project building, use "Developer Tools > Reload" to reset the IDE status upon mysterious errors. ccc_reload

Another issue is with the package name, see the screenshot below, kindly note that after successfully building with a blank package name, you can then re-fill the desired package name and build again! ccc_package_name

2.5 Checking UDP port binding result

*nix

netstat -anp | grep <your_port>

Windows

netstat -ano | grep <your_port>

2.6 Checking native code crash on non-rooted Android phone

DeveloperOs> adb bugreport ./logs.zip
# The file "logs.zip" will be automatically pulled to current folder of the DeveloperOS, copy "logs/FS/data/tomestones" out of the zip, then use the binary "$NDK_ROOT/ndk-stack" to analyze whichever tombstone you're interested in, for example, I often use the following
DeveloperOs> ${NDK_ROOT}/ndk-stack.cmd -sym \path\to\DelayNoMore\frontend\build\jsb-link\frameworks\runtime-src\proj.android-studio\app\build\intermediates\ndkBuild\debug\obj\local\arm64-v8a -dump \path\to\tombstones\tombstone_03  
# The param "-sym \path\to\objs" tells "ndk-stack" to decode "tombstone_03" with symbols provided by all the files inside that "\path\to\objs".