Page 1 of 1

Examine savegames

Posted: Thu Nov 03, 2016 3:15 pm
by ixu
I'm searching for a way get the mod names and their versions from a savegame, something like mod-list.json.

Re: Examine savegames

Posted: Fri Dec 02, 2016 6:01 pm
by d4rkpl4y3r
I am a bit late for the question but I figured it out for 0.14 savegames.

The info you want from the save zip is the level-init.dat file.

Here is C++ code to output all mods with version numbers by reading from said file:

Code: Select all

int main()
{
    string file = "C:\\Users\\USER\\Desktop\\level-init.dat";
    char* buffer = new char[257];
    ifstream is(file, ifstream::binary);
    is.read(buffer, 48);
    is.read(buffer, 4);
    int modCount = buffer[0];
    while (modCount > 0)
    {
        is.read(buffer, 1);
        int length = buffer[0];
        is.read(buffer, length);
        buffer[length] = 0;
        cout << buffer;
        is.read(buffer, 3);
        cout << " v" << ((int)buffer[0]) << '.' << ((int)buffer[1]) << '.' << ((int)buffer[2]) << endl;
        modCount--;
    }
}

Re: Examine savegames

Posted: Sat Dec 03, 2016 10:52 am
by ixu
Thanks. Works fine.
I did it in C#.
I think it is not suitable to present the code here (It's almost the same, but adapted to my style.)
If you want to have a look at it, it will be on github soon.

Get mods/versions from saved games in Node.js

Posted: Sun Dec 11, 2016 5:54 am
by AlyxDeLunar
Woo! You guys rock (especially you d4rkpl4y3r). This came right when I was stuck trying to read the save files. I'm working in Node.js and came up with a code solution by pretty much ripping off your code :D

Code: Select all

var fs = require('fs');
fs.readFile('level-init.dat', function(error, buffer) {
    if(error) console.log(error);
    else {
        var modCount = buffer.readUIntBE(48, 1); 
        for(var i = modCount, pos = 52; i > 0; i--) {
            var length = buffer.readUIntBE(pos, 1);
            
            var modName = buffer.toString('utf-8', pos, pos + length + 2).trim();
            var vMajor  = buffer.readUIntBE(pos + length + 1, 1);
            var vMinor  = buffer.readUIntBE(pos + length + 2, 1);
            var vPatch  = buffer.readUIntBE(pos + length + 3, 1);
            
            var fullVersion = 'v' + vMajor + '.' + vMinor + '.' + vPatch;
            
            console.log(modName, fullVersion);
            
            pos += length + 4;
        }
    }
});

Re: Examine savegames

Posted: Wed Nov 22, 2017 2:09 pm
by bpot
I know it's an old post but i found this and couldn't get AlexDeLunars node version to work properly on my version 15 save game. So after a little investigation i found out that the offset between mods in 15 has gone up from 4 to 8 and there is a little position error when reading the mod name, it should be pos+1.

Here is the updated version for both lversion 15 and 14 savegames ( you can get the factorio version from offset 2 and 4 )

Code: Select all

const fs = require('fs');

function read15() {
   fs.readFile('version15.dat', function(error, buffer) {
       if(error) console.log(error);
       else {
         let mods = []
         let modCount = buffer.readUIntBE( 48, 1 )
         for ( var i = modCount, pos = 52; i > 0; i-- ) {
            let length = buffer.readUIntBE( pos, 1 )

            let modName = buffer.toString( 'utf-8', pos+1, pos + length + 1 )
            let vMajor = buffer.readUIntBE( pos + length + 1, 1 )
            let vMinor = buffer.readUIntBE( pos + length + 2, 1 )
            let vPatch = buffer.readUIntBE( pos + length + 3, 1 )

            let fullVersion = 'v' + vMajor + '.' + vMinor + '.' + vPatch

            console.log(modName, fullVersion);

            pos += length + 8;
         }
      }
   });
}

function read14() {
   fs.readFile('version14.dat', function(error, buffer) {
       if(error) console.log(error);
       else {
         let mods = []
         let modCount = buffer.readUIntBE( 48, 1 )
         for ( var i = modCount, pos = 52; i > 0; i-- ) {
            let length = buffer.readUIntBE( pos, 1 )

            let modName = buffer.toString( 'utf-8', pos+1, pos + length + 1 )
            let vMajor = buffer.readUIntBE( pos + length + 1, 1 )
            let vMinor = buffer.readUIntBE( pos + length + 2, 1 )
            let vPatch = buffer.readUIntBE( pos + length + 3, 1 )

            let fullVersion = 'v' + vMajor + '.' + vMinor + '.' + vPatch

            console.log(modName, fullVersion);

            pos += length + 4
         }
      }
   });
}
And last but not least thinks for the help on this one, i would properly not have found this on my own =)