Last active 7 months ago

Linux steam proton multiplayer desync script

Revision 3f3b078af350c0bb6775fd6975468b690f105b66

README.md Raw

I wanted to play Sins of the solar Empire 2 with my friends. Proton and Lutris works great for SP, but MP was broke.

First blocker was forcing the CPU architecture: (you can also edit this via ctrl+shift+s while in game)

The second was that there were desync issues, which the community found and fixed for other games. These desync issues seem to be fairly common with multiplayer games using proton. So you can always try this and copy the backup files back (.bak) if it didn't work. This version adds sha256 checksums of the .exe files. If you run into issues with "command not found", try dos2unix steam_patch_mp_desync.sh then retry.

The below script is a more agnostic version of the original script to be more generic and work with most games by passing the APP ID

chmod +x steam_patch_mp_desync.sh
./steam_patch_mp_desync.sh 111011

To get a list of installed apps run it without a app id

./steam_patch_mp_desync.sh

Provide a steam ID from below
1493710		Proton Experimental
1575940		Sins of a Solar Empire II
1628350		Steam Linux Runtime 3.0 (sniper)
1782120		ZERO Sievert
1794680		Vampire Survivors
228980		Steamworks Common Redistributables
250900		The Binding of Isaac: Rebirth
2805730		Proton 9.0
2828860		The Forever Winter
427520		Factorio
469600		Legion TD 2


example for 'Legion TD 2' would be ./steam_patch_mp_desync.sh

For deck users just override the STEAM_USER variable while running it if it doesn't default to the right user.

STEAM_USER=deck ./steam_patch_mp_desync.sh 11011

If you have additional drives setup in steam you'll need to set the full path to steamapps directory

STEAM_DIR="/mnt/games/steam/steamapps" ./steam_patch_mp_desync.sh 11011
steam_patch_mp_desync.sh Raw
1#!/bin/bash
2
3set -e
4
5APP_ID=${1}
6STEAM_USER=$USER
7STEAM_DIR="/home/${STEAM_USER}/.steam/steam/steamapps"
8APP_DIR="${STEAM_DIR}/compatdata/${APP_ID}"
9WIN_DIR="${APP_DIR}/pfx/drive_c/windows"
10WIN_SYS32_DIR="${WIN_DIR}/system32"
11WIN_SYS64_DIR="${WIN_DIR}/syswow64"
12VC_REDIST_x64_CKSUM=5eea714e1f22f1875c1cb7b1738b0c0b1f02aec5ecb95f0fdb1c5171c6cd93a3
13VC_REDIST_x86_CKSUM=fdd1e1f0dcae2d0aa0720895eff33b927d13076e64464bb7c7e5843b7667cd14
14
15function list_apps() {
16 echo "Provide a steam ID from below"
17 for d in ${STEAM_DIR}/appmanifest*.acf; do
18 id=$(sed -rn 's/\s+"appid"\s+"(.+)\"/\1/p' < $d)
19 name=$(sed -rn 's/\s+"name"\s+"(.+)\"/\1/p' < $d)
20 echo -e "$id\t\t$name"
21 done
22 echo
23 echo
24 echo example for \'$name\' would be $0 $appid
25 echo
26}
27
28
29function check_deps() {
30 which sha256sum > /dev/null || (echo "sha256sum is required (on Ubuntu you can install it with 'sudo apt-get install coreutils')" && exit 1)
31 which curl > /dev/null || (echo "curl is required (on Ubuntu you can install it with 'sudo apt-get install curl')" && exit 1)
32 which cabextract > /dev/null || (echo "cabextract is required (on Ubuntu you can install it with 'sudo apt-get install cabextract')" && exit 1)
33 test -d ${APP_DIR} || ( echo "$APP_DIR does not exist; application is not supported or installed" && exit 1)
34 test -d ${WIN_DIR} || ( echo "$WIN_DIR does not exist; application is not supported or installed" && exit 1)
35}
36
37function cleanup() {
38 local arch=$1
39
40 rm -f vc_redist.$arch.exe
41 rm -rf 0 a{0..11} u{0..31}
42}
43
44function backup() {
45 files="ucrtbase.dll concrt140.dll msvcp140.dll vcamp140.dll vccorlib140.dll vcomp140.dll vcruntime140.dll"
46 for f in $files; do
47 test -f $f || continue
48 echo "Backing up $f => ${f}.bak"
49 cp -n $f ${f}.bak 2> /dev/null || true
50 done
51
52}
53
54function download_and_replace() {
55 local arch=$1
56 echo "Downloading vc_redist.$arch.exe"
57 curl -s -O https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.$arch.exe
58 echo "Validating archive"
59 csum="VC_REDIST_${arch}_CKSUM"
60 rm -f tmp.sha256
61 echo "${!csum} vc_redist.$arch.exe" > tmp.sha256
62 sha256sum -c tmp.sha256 || rm -f tmp.sha256
63 echo "Extracting archive"
64 cabextract -q vc_redist.$arch.exe 2>/dev/null
65 cabextract -q a10 2>/dev/null
66 echo "Extraction done"
67}
68
69function replace_dlls() {
70 local dir=$1
71 local arch=$2
72
73 echo "Patching $dir with arch $2"
74 pushd "${dir}" > /dev/null
75
76 backup
77 cleanup $arch
78 download_and_replace $arch
79 cleanup $arch
80 popd > /dev/null
81
82 echo "Patching complete!"
83}
84
85if [ -z "${APP_ID}" ]; then
86 list_apps
87 exit 1
88fi
89
90check_deps
91replace_dlls "${WIN_SYS32_DIR}" x64
92replace_dlls "${WIN_SYS64_DIR}" x86
93