robophred / oni-save-parser Goto Github PK
View Code? Open in Web Editor NEWParses save files for the game "Oxygen Not Included".
License: MIT License
Parses save files for the game "Oxygen Not Included".
License: MIT License
Open archive version restrictions to support new version modifications.
Hi, I'm trying to find all farm tiles or planterboxes in a save file that contain mealwood. It's not super obvious to me how to traverse the game objects to find what im looking for.
I've tried this:
const { readFileSync } = require("fs");
const {
parseSaveGame,
writeSaveGame,
getBehavior,
AIAttributeLevelsBehavior
} = require("oni-save-parser");
const fs = require('fs');
function loadFile(fileName) {
const fileData = readFileSync(fileName); //`./test-data/${fileName}.sav`
return parseSaveGame(fileData.buffer);
}
function saveFile(fileName, save) {
const fileData = writeSaveGame(save);
fs.writeFileSync(fileName, new Uint8Array(fileData)); // ./test-data/${fileName}.sav
}
let fileName = 'aa';
if (process.argv[2]) {
fileName = process.argv[2];
}
const saveData = loadFile(fileName);
const stuff = saveData.gameObjects.find(e => e.name === "BasicPlantFood")
const farmTile = saveData.gameObjects.find(e => e.name === "FarmTile")
let ftn = 0 ;
for (ft of farmTile.gameObjects) {
ftn++
console.log("FarmTile:", ft)
for (be of ft.behaviors) {
console.log(ft.name, be.name)
if (be.name === "Storage") {
console.log("FarmTile.behaviors[~Storage]:", be)
}
}
break
}
console.log( JSON.stringify(farmTile))
Can you provide any guidance here?
Is there any documentation you used to understand how the save file is structured?
Core request is to tweak the element and temperature on new saves (presumably, ahead of discovery).
These exist in 2 forms through the game. Before they are discovered, they are a WorldSpawner. After, they are a "Geyser" Prefab.
These are simple. I found one before, and it stores the element ID, temperature, and a few other values.
I need to look this up again; I do not have access to ONI at the moment.
"Geyser"
Geyser prefab behavior chunk example:
first entry in THE LOST CITY challenge geyser prefabs.
[
{
"name": "KPrefabID",
"hasParseData": true,
"parsedData": {
"InstanceID": 2002
},
"extraData": null
},
{
"name": "SavedObject",
"hasParseData": true,
"parsedData": {
"inStorage": false
},
"extraData": null
},
{
"name": "StateMachineController",
"hasParseData": true,
"parsedData": {},
"extraData": {}
},
{
"name": "PrimaryElement",
"hasParseData": true,
"parsedData": {
"ElementID": -355957251,
"_Temperature": 374.4565124511719,
"diseaseID": {
"hash": 0
},
"diseaseCount": 0,
"Units": 1
},
"extraData": null
},
{
"name": "Klei.AI.Modifiers",
"hasParseData": true,
"parsedData": {},
"extraData": {}
},
{
"name": "Geyser",
"hasParseData": true,
"parsedData": {},
"extraData": null
},
{
"name": "ElementEmitter",
"hasParseData": true,
"parsedData": {},
"extraData": null
}
]
First of all, please allow me to thank you for designing a website so that we can use the tool quickly. But I hope you'll enable us to use earlier versions of the tools. I have a 7.15 archive. And I found that it was too late. I can't upgrade this archive to 7.17. If so, the program will flash back. I think there is something wrong with my archive. I studied for a long time, because I didn't really have any knowledge about the code, I didn't succeed in the end. I hope you can open up early tools to help me, thank you.
CURRENT_VERSION_MINOR changing it to 12 seems okay as far as I can tell.
Maybe some option for the user to accept the risk of corrupting their save?
New geyser types in src/save-structure/const-data/geysers/geyser-type.ts
"molten_aluminum",
"molten_tungsten",
"molten_niobium",
"liquid_sulfur",
"molten_steel",
"molten_glass",
"liquid_coolant",
"liquid_ethanol",
Edit: Something is wrong with molten_niobium, it doesn't appear in the list, tried using NiobiumGeyser. Didn't help either
Hi @RoboPhred, I realize I haven't so much as asked you a question yet, but I wanted to thank you for all of your help. I was able to develop a .NET Standard lib (Deserializer only ATM) based on your work. It's taken me weeks and I've learned a lot in the process, and finally have a complete 7.11 parse. If you have the time to review my work, I'd like to know if there are glaring differences between my deserialized results and yours. Or any suggestions on how I can do things better. Much of the code will look familiar to you, and some things I changed drastically to fit a model I'm more familiar with. https://github.com/bryan5989/OniSaveParser/tree/master
I've attached a JSON output.
output.txt
I made a quick saver.js
in the root of a built oni-save-parser
to test outputing the save in a JSON file to facilitate editing with a standard text editor.
const savefile = `Hydrocarbon Eden`;
const savepath = '/home/xaekai/.config/unity3d/Klei/Oxygen Not Included/save_files/';
const fs = require('fs');
const {
parseSaveGame,
writeSaveGame,
getBehavior,
AIAttributeLevelsBehavior
} = require("./lib/index.js");
function loadJSON(filename){
console.log('loading savedata from JSON', filename);
// we could just use "require(`./${filename}.json`);" but this is more symmetrical
const savedata = JSON.parse(fs.readFileSync(`${filename}.json`).toString());
return savedata;
}
function loadFile(filename) {
console.log('loading savefile', filename);
const fileData = fs.readFileSync(`${filename}.sav`);
return parseSaveGame(fileData.buffer);
}
function saveFile(filename, savedata) {
console.log('writing savedata to', filename);
// debug
console.log('formatSave')
const formatSave = writeSaveGame(savedata);
console.log('serializing')
const serialized = new Uint8Array(formatSave)
fs.writeFileSync(`${filename}.sav`, serialized);
}
function saveJSON(filename, savedata) {
console.log('writing savefile JSON', filename);
fs.writeFileSync(`${filename}.json`, JSON.stringify(savedata, null, 2));
}
let savedata;
const loadsave = 1; // load the savefile
const savejson = 1; // save the savedata to JSON
const loadjson = 1; // load the savedata from JSON
const savesave = 1; // resave the savefile
const file = `${savepath}${savefile}`
if(loadsave){ savedata = loadFile(file); }
if(savejson){ saveJSON(file, savedata); }
if(loadjson){ savedata = loadJSON(file); }
if(savesave){ saveFile(file, savedata); }
But it doesn't survive the roundtrip. writeSaveGame chokes on the data when it's loaded from JSON.
I managed to do what I immediately wanted to through a node repl to edit the live object, but I thought I'd ask about this anyway, so maybe I can expand this into a full blown commandline save editor that can resave manually edited JSON files, among other things.
One section of the game remains uninterpreted at
oni-save-parser/src/save-structure/parser.ts
Line 110 in df9698a
Could this segment potentially contain data related to the DLC, such as geysers on the other asteroids?
Upon further investigation using Duplicity, I noticed that only the gameObjects of my initial asteroid are visible. The coordinates are represented as X, Y, Z, but there is no apparent "planet" marker. Is there a marker that I may be overlooking?
I am curious about how ToolsNotIncluded.net manages to depict the entire cluster's layout from a single save game.
When you have time, can you please update sim-hashes to current SU content? We do not have supercoolant, isolator and other space materials from SU. Also, are these only consts from .Net assembly or may be they are stored in a save somehow?
I'd like to be able to extract all the material counts from the save files, to get the same numbers you can see on the side of the game screen. I tried querying the saveData.body.gameObjects for a given material, but I don't think the data there includes counts of that material found within storage bins.
Using a save file from a freshly created game, I believe I can confirm the above by noting that FieldRation (aka nutrient bars) are not found in the gameObjects list, however if you query the RationBox object you will find that there's 2k+ bytes of data remaining in the extraData field for the behavior named "Storage". I tried dumping this data, but I do not know how to parse it, but it does seem to contain the string 'FieldRation" and I suspect it also includes a count here.
I would like to help you extend this library but I'm unfamiliar with how the typescript files describing the save file format operate. I did try to duplicate one of the behaviors to parse the "Storage" behavior here, but I had no luck. If you can point me towards documentation on how to understand this framework better perhaps I can try to be of more help.
As provided by @khakulov
if (name === 'MinionModifiers') {
extraData = {};
const needCount = reader.readInt32();
extraData.needs = new Array(needCount);
for (let i = 0; i < needCount; i++) {
extraData.needs[i] = {
name: reader.readKleiString(),
valueLength: reader.readInt32(),
value: reader.readSingle(),
};
}
const effectCount = reader.readInt32();
extraData.effects = new Array(effectCount);
for (let i = 0; i < effectCount; i++) {
extraData.effects[i] = {
name: reader.readKleiString(),
value1: reader.readInt32(),
value2: reader.readInt32(),
messageId: reader.readKleiString(),
messageString: reader.readKleiString(),
};
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.