Last active 7 months ago

Linux steam proton multiplayer desync script

mxywes revised this gist 7 months ago. Go to revision

2 files changed, 136 insertions

README.md(file created)

@@ -0,0 +1,44 @@
1 + I wanted to play Sins of the solar Empire 2 with my friends. Proton and Lutris works great for SP, but MP was broke.
2 +
3 + First blocker was [forcing](https://steamcommunity.com/app/1575940/discussions/1/7026264603287932608/#c7026264603289995255) the CPU architecture: (you can also edit this via ctrl+shift+s while in game)
4 +
5 + The second was that there were desync issues, which the [community found and fixed](https://steamcommunity.com/app/1575940/discussions/1/7026264603287932608/#c7026264836515783746) for [other games](https://gist.github.com/reneklacan/7825b82723bf0534cbd2eae014e121ca). 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.
6 +
7 + 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
8 +
9 + ```
10 + chmod +x steam_patch_mp_desync.sh
11 + ./steam_patch_mp_desync.sh 111011
12 + ```
13 +
14 + To get a list of installed apps run it without a app id
15 +
16 + ```
17 + ./steam_patch_mp_desync.sh
18 +
19 + Provide a steam ID from below
20 + 1493710 Proton Experimental
21 + 1575940 Sins of a Solar Empire II
22 + 1628350 Steam Linux Runtime 3.0 (sniper)
23 + 1782120 ZERO Sievert
24 + 1794680 Vampire Survivors
25 + 228980 Steamworks Common Redistributables
26 + 250900 The Binding of Isaac: Rebirth
27 + 2805730 Proton 9.0
28 + 2828860 The Forever Winter
29 + 427520 Factorio
30 + 469600 Legion TD 2
31 +
32 +
33 + example for 'Legion TD 2' would be ./steam_patch_mp_desync.sh
34 + ```
35 +
36 + For deck users just override the `STEAM_USER` variable while running it if it doesn't default to the right user.
37 + ```
38 + STEAM_USER=deck ./steam_patch_mp_desync.sh 11011
39 + ```
40 +
41 + If you have additional drives setup in steam you'll need to set the full path to `steamapps` directory
42 + ```
43 + STEAM_DIR="/mnt/games/steam/steamapps" ./steam_patch_mp_desync.sh 11011
44 + ```

steam_patch_mp_desync.sh(file created)

@@ -0,0 +1,92 @@
1 + #!/bin/bash
2 +
3 + set -e
4 +
5 + APP_ID=${1}
6 + STEAM_USER=$USER
7 + STEAM_DIR="/home/${STEAM_USER}/.steam/steam/steamapps"
8 + APP_DIR="${STEAM_DIR}/compatdata/${APP_ID}"
9 + WIN_DIR="${APP_DIR}/pfx/drive_c/windows"
10 + WIN_SYS32_DIR="${WIN_DIR}/system32"
11 + WIN_SYS64_DIR="${WIN_DIR}/syswow64"
12 + VC_REDIST_x64_CKSUM=5eea714e1f22f1875c1cb7b1738b0c0b1f02aec5ecb95f0fdb1c5171c6cd93a3
13 + VC_REDIST_x86_CKSUM=fdd1e1f0dcae2d0aa0720895eff33b927d13076e64464bb7c7e5843b7667cd14
14 +
15 + function 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 +
29 + function 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 +
37 + function 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 +
44 + function 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 +
54 + function 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 +
69 + function 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 +
85 + if [ -z "${APP_ID}" ]; then
86 + list_apps
87 + exit 1
88 + fi
89 +
90 + check_deps
91 + replace_dlls "${WIN_SYS32_DIR}" x64
92 + replace_dlls "${WIN_SYS64_DIR}" x86
Newer Older