Ported the save extractor

This commit is contained in:
theo@manjaro 2023-06-10 13:21:39 +02:00
parent 2d46b7ad6c
commit 274cc0c495
3 changed files with 159 additions and 6 deletions

36
SaveExtractor/README.md Normal file
View File

@ -0,0 +1,36 @@
# SaveExtractor.py
A save file extractor for The Binding Of Isaac: Repentance.
Ported from [wofsauge/IsaacSavegameReader](https://github.com/wofsauge/IsaacSavegameReader/blob/main/Program.cs#L228), in order to be more easily ran on Linux.
It generates files that can be used in External Item Descriptions, and Dead God Helper. Theses files contain information about which items were already picked up.
## Usage
```sh
python ./saveextractor.py path/to/savefile.dat saveid
```
It will generate the following files in the current directory:
- `eid_savegame.lua` to be put in EID's mod folder, inside the `scripts` subfolder
- `saveX.dat` to be put in DeadGod Helper's data folder
## Example
Since I'm on Linux (and using the Steam version of TBOI), folders are a little bit different than on Windows, more info for save files location [here](https://github.com/Zamiell/isaac-faq/blob/main/directories-and-save-files.md)
### Extracting information from save file 2
The number `196602716` corresponds to my Steam Account ID, it will be different on your side.
```sh
python ./saveextractor.py ~/.steam/steam/userdata/196602716/250900/remote/rep_persistentgamedata2.dat 2
```
### Moving generated files to the corresponding location
```sh
mv save2.dat ~/.local/share/Steam/steamapps/common/The\ Binding\ of\ Isaac\ Rebirth/data/deadgod\ helper/
mv eid_savegames.lua ~/.local/share/Steam/steamapps/common/The\ Binding\ of\ Isaac\ Rebirth/mods/external\ item\ descriptions_836319872/scripts/
```

View File

@ -0,0 +1,114 @@
#!/bin/env python
# Ported from https://github.com/wofsauge/IsaacSavegameReader/blob/main/Program.cs#L228
import sys
REP_ITEMSTART = 0x00000AB6 + 4
REP_NBITEMS = 732
EID_FILE = "eid_savegames.lua"
DGH_FILE1 = "saveX.dat"
def loadFromFile(filename, itemstart, nbitems):
table = []
try:
file = open(filename, "rb")
except FileNotFoundError:
print(f"File not found: {filename}", file=sys.stderr)
for i in range(nbitems):
table.append(0)
return table
data = file.read(1)
i = 0
while data:
if (i > itemstart) and i - itemstart <= nbitems:
table.append(int.from_bytes(data, byteorder='big'))
# Should be 1 (for already seen), or 0
data = file.read(1)
i += 1
file.close()
return table
def eidfile(t1, saveid):
content = "-- Auto generated from a python script\n"
content += "if EID then\n"
content += "\tEID.SaveGame = {}\n"
content += "\tEID.SaveGame.Platform = \"Steam\"\n"
content += "\tEID.SaveGame.UserID = \"0\"\n"
content += "\tEID.SaveGame.UserName = \"username\"\n"
for savefileindex in range(3):
content += f"\tEID.SaveGame[{savefileindex+1}] = {{\n"
content += "\t\tItemCollection = {\n\t\t\t"
for i, v in enumerate(table):
if savefileindex + 1 == saveid:
content += f"[{i+1}]={'true' if v==1 else 'false'}, "
else:
content += f"[{i+1}]=false, "
content += "\n\t\t},\n"
content += "\t\tItemNeedsPickup = {\n\t\t\t"
for i, v in enumerate(table):
if savefileindex + 1 == saveid:
content += f"[{i+1}]={'true' if v==0 else 'false'}, "
else:
content += f"[{i+1}]=true, "
content += "\n\t\t}\n\t}\n"
content += "end"
return content
def dghfile(table):
content = '{'
content += '"settings":{"visual":true,"eid":true,"showonmodded":true,"showonblind":false},'
content += '"seen":['
for i, v in enumerate(table):
if table[i] == 1:
content += "true"
else:
content += "false"
if i < len(table) - 1:
content += ", "
content += "],"
content += ' "seenmodded":{}}'
return content
def isHelp(args):
return ("--help" in args) or ("-h" in args)
if __name__ == "__main__":
args = sys.argv
if len(args) < 3 or isHelp(args):
print(f"USAGE: python {args[0]} path/to/persistengamedata.dat slotnumber")
print("This will generate the following files:")
print("\t- eid_savegames.lua , used by External Items Description (to be placed in EID's script folder)")
print("\t- saveX.dat , used by Dead God Helper (to be placed in Dead God Helper data folder)")
else:
saveid = 1
error = False
try:
saveid = int(args[2])
if not (saveid <= 3 and saveid >= 1):
error = True
except ValueError:
error = True
if error:
print(f"Invalid save ID: '{args[2]}'")
print("Please retry with a number between 1 and 3!")
exit(1)
table = loadFromFile(args[1], REP_ITEMSTART, REP_NBITEMS)
with open(EID_FILE, "w") as f:
f.write(eidfile(table, saveid))
with open(DGH_FILE1.replace("X", str(saveid)), "w") as f:
f.write(dghfile(table))

View File

@ -7,20 +7,23 @@
Easily spot items that were not previously picked up on this savefile. Very useful when you're trying to get a second or third Dead God.
Now supports modded items!
I made it mainly for myself, because it was annoying to go back to the menu every time I encountered an item I was unsure about.
There's an integration with External Item Description.
It is also compatible with Mod Config Menu, if you want to toggle things (such as displaying info when on Curse Of The Blind)
Since mods can't directly access the savefile, this mod takes it upon itself to track wich items are picked up. This means that the first time you install this mod, everything will be marked as unseen.
[strike]There's however a limitation: since (to my knowledge) there's no way to get information about seen items from the savefile, this mod takes it upon itself to track which item you picked up. (This means that when you install the mod for the first time, every item will be tagged as unseen)[/strike]
EDIT: Turns out EID already has a support for this, using a save extractor, if you want to go down that route, here's the link to the extractor : https://github.com/wofsauge/External-Item-Descriptions/tree/master/scripts
This mod is still somewhat relevant if you do not want to use external tools ^^
Turns out EID already has a some support for this, using a save extractor. If you want to go down that route, here's the link to the extractor : https://github.com/wofsauge/External-Item-Descriptions/tree/master/scripts
However, EID's save extractor doesn't really work on Linux, so I made a port of it in python, in order to be more easily ran. This port is available here : https://forge.chapril.org/ayte/DeadGodHelper/src/branch/main/SaveExtractor
This mod is still relevant in itself if you do not want to use external tools, or you want to track modded items ^^
Anyway, I hope that this mod will be useful to someone :)
(Source code is available at https://forge.chapril.org/ayte/DeadGodHelper)</description>
<version>1.9</version>
Source code is available at https://forge.chapril.org/ayte/DeadGodHelper</description>
<version>1.10</version>
<visibility>Public</visibility>
<tag id="Items"/>
<tag id="Graphics"/>