Ported the save extractor
This commit is contained in:
parent
2d46b7ad6c
commit
274cc0c495
36
SaveExtractor/README.md
Normal file
36
SaveExtractor/README.md
Normal 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/
|
||||
```
|
114
SaveExtractor/saveextractor.py
Normal file
114
SaveExtractor/saveextractor.py
Normal 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))
|
13
metadata.xml
13
metadata.xml
@ -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)
|
||||
|
||||
[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]
|
||||
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.
|
||||
|
||||
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"/>
|
||||
|
Loading…
Reference in New Issue
Block a user