diff --git a/.gitignore b/.gitignore
index 0f3f289..d07d1b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
backups
save
-7z.exe
-node.exe
-config.json
\ No newline at end of file
+*.exe
+*.7z
+config.json
diff --git a/README.md b/README.md
index 523e6e6..45658b7 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,65 @@
# SnowRunnerSaveMerge
-Tool for SnowRunner to enable progress sync from you co-op host
+Tool for SnowRunner to enable progress sync from you co-op host.
+
+## Requirements
+Written in Node v 22.2.0 for Windows
+
+Need to provide 7z.exe in the same directory as script for compression
+
+## Usage
+This script will overwrite most of your save file, it's best to only use this with a save file dedicated to co-op play, with a consistent host!
+Your save file must be on the same slot in game as the host!
+
+### Installation
+1. Download the saveMerge.js file or clone the repo.
+1. Run the script once to create template config file
+1. Fill your config according to instructions inside
+1. Make sure your load location and backup location exist
+1. Copy 7z.exe to the repo directory
+
+### Running the script
+It's best to run the script directly after ending your game session. To prevent accidental merges with old files if hosts save was uploaded more than 1 hour ago the script will not automatically download and merge it. If you're sure that the file is correct, download it manually and extract the files in you load location `remote` directory then run just `merge` operation
+
+#### Host
+1. Get all your vehicles inside a garage, best to retain them
+1. Leave all newly acquired trucks, that the guest doesn't have, outside on the map
+1. Exit the game
+1. Run the script with `upload` operation `node .\saveMerge.js upload` additionally provide save slot if different than first
+
+#### Guest
+1. Get all your vehicles inside a garage, best to retain them
+1. Exit the game
+1. Run the script with `download` and `merge` operations `node .\saveMerge.js download,merge` additionally provide save slot if different than first
+1. Restart Steam for safety. Sometimes the game behaves funny if steam is not restarted after save manipulation
+
+#### Things that will be overwritten
+- Map files
+- Visited maps
+- Watch towers
+- Upgrades
+- Tasks
+- Contracts
+- Objective states (half completed tasks etc.)
+- Game settings (hard mode, recover and fuel costs etc.)
+- Waypoints, not sure if it matters, but the game creates new array elements for them only on host side. You have to redo your route when joining anyway.
+
+#### Things that are preserved
+- Trucks (customizations, addons etc.)
+- Money
+- Exp
+
+#### Auto save backup
+1. Run the script with `backup` operation `node .\saveMerge.js backup`, save slot doesn't matter in this case. Whole save is backed up so it still might useful in single player game
+1. The script will enter an endless loop that will backup you saves every set interval, default 10 minutes
+1. Do not exit the script while files are copying, there is a message displayed when it's safe to kill the script
+
+### Script help as shown when used with unknown operation
+
+ saveMerge [operations=download,merge] [save_slot=1]
+
+ operations - comma separated list of operations, from these: download, merge, upload, backup
+ download - download save from file.io, this will delete contents of loadLocation
+ merge - merge the save from loadLocation
+ upload - pack the current save and upload to filebin.net
+ backup - will auto backup save file on set interval
+ save_slot - which slot to merge, values 1 to 4 are accepted, need to play on the same slot as host
\ No newline at end of file
diff --git a/saveMerge.js b/saveMerge.js
index 87749e9..44c7bfb 100644
--- a/saveMerge.js
+++ b/saveMerge.js
@@ -5,7 +5,7 @@ const exec = require("child_process").execSync;
var CONFIG = null;
const configTemplate = {
- "info": "This script will overwrite most of you save file, it's best to only use this with a save file dedicated to co-op play, with a consistent host!",
+ "info": "This script will overwrite most of your save file, it's best to only use this with a save file dedicated to co-op play, with a consistent host!",
"saveLocation": "C:/Program Files (x86)/Steam/userdata//1465360",
"loadLocation": "./save",
"backupLocation": "./backups",
@@ -194,9 +194,11 @@ async function main(args) {
break;
case "upload":
+ // Create 7z archive from latest backup
let archivePath = `${__dirname}\\${backupName}.7z`;
exec(`${__dirname}\\7z.exe a ${archivePath} ${__dirname}\\backups\\${backupName}\\*`);
+ // Upload the file to filebin
fileInput = await fs.readFile(archivePath);
await fetch(CONFIG.filebinURL + "/" + backupName + ".7z", {
body: fileInput,
@@ -207,15 +209,17 @@ async function main(args) {
method: "POST"
});
+ // Remove the archive
await fs.rm(archivePath);
break;
case "backup":
+ // Auto backcup will loop forever and create a backup of you save files every set interval
while (true) {
console.log("Waiting for next backup, you can stop the script using Ctrl+C!");
await sleep(CONFIG.backupInterval);
- await backupSave();
console.log("Performing backup, wait before terminating the program!");
+ await backupSave();
}
break;
@@ -224,32 +228,15 @@ async function main(args) {
Unknown parameter!\n\
saveMerge [operations=download,merge] [save_slot=1]\n\
\n\
- operations - comma separated list of operations, from these: download, merge, upload\n\
+ operations - comma separated list of operations, from these: download, merge, upload, backup\n\
download - download save from file.io, this will delete contents of loadLocation\n\
merge - merge the save from loadLocation\n\
upload - pack the current save and upload to filebin.net\n\
backup - will auto backup save file on set interval\n\
- save_slot - which slot to merge, values 1 to 4 are accepted");
+ save_slot - which slot to merge, values 1 to 4 are accepted, need to play on the same slot as host");
return;
}
}
-
-
-
- // case "upload": // from saveLocation backups
-
- // if (operation == "upload") {
-
- // fileInput = await fs.readFile("./remote.7z");
- // await fetch("https://filebin.net/plrho4w60pe25pae/SR_24-06-10_01-35.7z", {
- // body: fileInput,
- // headers: {
- // Accept: "application/json",
- // "Content-Type": "application/octet-stream"
- // },
- // method: "POST"
- // });
- // }
}
main(process.argv);
\ No newline at end of file