Jump to content

programmatically update saved game time


Recommended Posts

Spoiler

const fs = require('fs');
const got = require('got');
const { execFile } = require('child_process');

const url = 'https://api.truckersmp.com/v2/game_time';
const exeRegex = /^(?:[a-z]:)?[\/\\]{0,2}(?:[.\/\\ ](?![.\/\\\n])|[^<>:"|?*.\/\\ \n])+\.exe$/gmi;
const siiRegex = /^(?:[a-z]:)?[\/\\]{0,2}(?:[.\/\\ ](?![.\/\\\n])|[^<>:"|?*.\/\\ \n])+\.sii$/gmi;

const prefixUrl = '';
const headers = {
  Accept: "application/json"
};
const isStream = false;

const options = {
  prefixUrl,
  ...headers,
  isStream
}

let executable = "./SII_Decrypt.exe";
let inputfile = "info.sii";
let outputfile = `updated-${inputfile}`;

const useArguments = () => {
  const args = process.argv.slice(2);
  let optionValueIndex;
  args.forEach((value, index) => {
    switch (value) {
      case "-d":
        optionValueIndex = index + 1;
        try {
          executable = args[optionValueIndex].match(exeRegex).toString();
        } catch (e) {
          console.log('invalid decryptor executable specified, using SII_Decrypt.exe as default');
        }
        break;
      case "-i":
        optionValueIndex = index + 1;
        try {
          inputfile = args[optionValueIndex].match(siiRegex).toString();
        } catch (e) {
          console.log(`invalid save game file specified ${args[optionValueIndex]}. Using info.sii instead`);
        }
        console.log(`args set inputfile to: ${inputfile}`);
        break;
      case "-o":
        optionValueIndex = index + 1;
        try {
          outputfile = args[optionValueIndex].match(siiRegex).toString();
        } catch (e) {
          console.log(`invalid output time format specified ${args[optionValueIndex]}. Using 'updated-info.sii' instead`);
        }
        console.log(`args set outputfile to: ${outputfile}`);
        break;
      default:
        console.log(`args value ${value}`);
    }
  });
}

const getResponseHeaders = (url, options) => {
  return got(url, options);
}

const decryptSaveGame = (
  decryptionExecutable,
  inputFile,
  outputFile) => {
  try {
    const proc = execFile(decryptionExecutable, [inputFile, outputFile]);
    proc.on("close", (code) => {
      if (code === 0) {
        console.log(`decryption successful`);
      } else {
        console.log(`decryption process closed with code ${code}`);
      }
    });
  } catch (error) {
    console.log(`error while trying to decrypt save game: ${error}`);
  }
}

const getMPTimestamp = async () => {
  try {
    const response = await getResponseHeaders(url, options);
    console.log(`response : ${response.body}`);
    return JSON.parse(response.body).game_time;
  } catch (error) {
    if (error.response) {
      //HTTP rejection
      const code = error.response.statusCode;
      const message = error.response.statusMessage;
      console.log(`
            statusCode ${code}\n
            message: ${message}\n
            options: ${JSON.stringify(options)}\n
            url: ${error.response.requestUrl}
            `);
    } else {
      //bug
      console.log(`ERROR\n ${error.stack}`);
    }
  }
};

const updateTimeStamp = (async () => {
  useArguments();
  decryptSaveGame(executable, inputfile, outputfile);
  const time = await getMPTimestamp();
  const file = fs.readFileSync(`${outputfile}`);
  const updatedFile = Buffer.from(file.toString().replace(/^(\s+)?time:\s\d*/gm, ` time: ${time}`));
  fs.writeFileSync(`${outputfile}`, updatedFile);
})();

 

 

Just felt like having a bit of a mess around practicing some random JS stuff using a simple API call and in place editing of a save game related file. Code in the spoiler is result of quarantine Sunday :)

Basically what it's supposed to do:
- get MP game time using the API
- decrypt the (provided) info.sii file

- update the info.sii file time

 

Say you've been offline for a couple days and the MP Server clock been ticking away while your save-game time sat there statically in your file-system and you start the game, straight away your clock is behind the servers' and your little AI workers have not progressed at all. Now if you'd run this update script to pull the save-game time forward in your file-system to quite close to the server time prior starting the game, you'll have jumped forward in time and suddenly your AI workers will have completed their rides as current game-time is most likely beyond their completion time :D (theoretically anyway).

 

What do you need?

- You need follow and complete the guide found elsewhere in this forum to change the way save-games are saved. (change a value '0' into a '2' in your game config file pertaining to save-game format)
- download the SII_Decrypt.exe you can find linked in places on this forum/website. This executable needs to be called by the script in order to decrypt it.

- nodejs installed

- node package 'got' installed ('npm install got'). This is a simple http library to make the API calls with.

- save the code in a JS file (e.g.  "index.js")

Once saved in a file you should be able to simply call it as:

node index.js

The script out of the box assumes files are present in it's current directory where it is run.
Default assumptions are the decryption executable filename (SII_Decrypt.exe), the info.sii filename (info.sii) and the output will be a new file called 'updated-info.sii' as not to override the original provided file. These values can be overridden by using flags. An example:

node index.js -d decrypt.exe -i info-copy.sii -o my-new-info.sii

where:
-d            name/location of the decryption executable (e.g. you might have renamed SII_Decrypt.exe)
- i            input filename
- o           output filename
Full paths to absolute locations/filenames "should" also work (fingers crossed) as input, but has not been thoroughly tested or anything. (e.g. "C:\Users\Yourmum\documents\save-game-edit\info.sii")

 


*** Disclaimer ***
Again, for me it was just a bit about trying to get my head around some concepts as I go along learning stuff, fighting boredom and thought it might be fun for people to mess with, so why not share the fun! I feel some of the things set out might be extensible as well (e.g. programmatic updating of 'save.sii' in particular areas, like grabbing a list of cities from a flat-file and inserting them into a bunch of discovered dealers and recruitment agencies :D ). I realize it by no means represents a full project or clean/proper best practices coding ?, it was also not intended to be!
 

  • Thanks 1
Link to comment
Share on other sites

  • 3 years later...

I see this suggestion and have reviewed the JS code and descriptions provided to you. First of all, I understand that this piece of code is a practical and fun experience in the application development process. I also notice that the code serves a useful purpose, it is used to update the time of game recordings.

The main purpose of the code is to update the time of game recording in accordance with the server time in multiplayer games. In this way, by ensuring that the game progresses in real time, artificial intelligence employees also allow them to complete it correctly. This can offer a more realistic and enjoyable experience while playing the game.

I see that certain prerequisites must be met for the code to work. Among them is the modification of the game configuration file to Decrypt the saved games with a different value (2 instead of 0), SII_Decrypt.it involves downloading a file called exe and installing certain node packages.

In the descriptions of the code, it is stated that users can personalize the application by changing some parameters. In this way, users can specify the desired file names and locations.

As a note, a statement was also made stating that the code was shared for practical and entertainment purposes only and was not coded with a complete project or best practice standards.

Overall, this piece of code can offer a fun experience for those who want to learn new about JavaScript and game development and improve their skills. It can also be a useful tool that users can use to edit game logs and update them in accordance with the server time. However, it is important to use the code carefully and meet the prerequisites specified in advance.

As a result, I appreciate that this piece of code was shared, and others shared this fun and informative experience as well. In addition to having fun, such codes can be a great learning tool for understanding different concepts and techniques during the application development process.

Karakteriniz düzgün olsun ki gerisini hallederiz..

My first condition is that your character is not broken...

AlparslanK

 

Link to comment
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.