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
| 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 |
| 93 |