gmiclotte / gear-optimizer

Gear optimizer for NGU Idle.
26 stars 19 forks source link

Error loading save, basically a null ref exception #111

Open jshepler opened 2 months ago

jshepler commented 2 months ago

My mods add some extra data to the save using a Dictionary<string, object> and it seems the parser you use may not know how to handle it. The value property is there though is undefined, and line 16 assumes that because it exists it must have a value. Does this parser not know how to handle a dictionary - i.e. should the value property actually have a value but the parser doesn't know how to set it?

Anyway, here's a shot of the error and I've attached a save you can use to test with, if you want to dig into it.

image

QuickSave_2024-09-11_15-38-27.txt

There's a way to do a clean save so GO can import it, but it seems a number of people are too lazy to RTFM and so don't know to do that and then complain my mods prevents them from using GO. I'm going to start working on figuring out how to save arbitrary data without using a Dictionary, but I thought I'd let you know about it.

Maybe it's an easy fix for GO to not choke on modded saves? I assume just add a check for undefined and skip it. If the dictionary that I add is the only issue, it can be ignored since GO doesn't care about it.

jshepler commented 2 months ago

I had a similar error loading a clean save: QuickSave (CLEAN)_2024-09-15_23-15-41.txt

image

Digging more into it, turns out the parser is hitting a different, unrelated error which is caught. The parser stops, but the code continues as if it didn't and hits data that doesn't have a value because the parser didn't finish.

In this case, the actual error is:

image

and if you work up the call stack, you can find where it's being caught and eaten at line 91. It breaks out of the parsing early and returns what it got, which will obviously cause problems since the rest of the data wasn't parsed.

Going through the cards, the only ones with weird names are THE END cards. Sure enough, the import is successful after yeeting those cards. I don't know why, the name doesn't have any non-standard characters that I can see: ^!!;;;[4V OF #$^&*FEdXCUy ee44-*()

Anyway, I went back to the other save - the modded one - and it's dying at line 281 as the parser doesn't support type 2, whatever that is. I think it might be MemberTypeInfo from the BinaryFormatter spec. In the parser, the method getTypeSpec (line 275), types 2 and 5 are not handled - Object and ObjectArray. My mod is adding Dictionary<string, object> and so I'm thinking it's choking on the object type?

So again, the exception is caught at the same place, the parse() method exits early, and so has missing data which causes the error I first posted about since the value never gets set.

I don't know if you can fix the parser - I know you didn't write it.

gmiclotte commented 2 months ago

Hi, I was just looking at this, and the parsing being stopped early is indeed the main issue.

I'm currently trying to extend the parser, so it can properly read all the data. It looks doable, but it might take a while.

Thanks for the save files, that really helps a lot.

gmiclotte commented 2 months ago

I had a similar error loading a clean save: QuickSave (CLEAN)_2024-09-15_23-15-41.txt

This clean save should now load fine in GO v0.9.8. Certain card names were not strings but references to strings, these should now be handled correctly.

As for the modded save, each time I fix one issue, another emerges—the joys of sequential parsing. I’m also still figuring out the dictionary encoding, so part of the fix is currently hardcoded, tailored to this specific modded data, and will need a proper generalized refactor. Time to read the MS-NRBF docs again.

This might take a while to fully resolve.

jshepler commented 2 months ago

Interesting... I assume it's a space-saving optimization. Since I had two cards with the exact same name, no need to duplicate it when just need one and the other references it. Now it makes sense why the import worked when I only removed one of THE END cards (didn't matter which one).

I tried reading the spec once, but quickly lost interest. Good on you! :)

jshepler commented 2 months ago

I changed from Dictionary<string, object> to a DTO. Some of the data my mods use are dictionaries, just not generic object values. This time the import dies for not supporting type 6.

A modded save using the DTO: QuickSave_2024-09-19_14-30-47.txt

If it helps, here's the class:

[Serializable]
public class ModData
{
    public bool AutoQuestingEnabled = false;
    public string[] LastYggRewards = new string[21];
    public Loadout LastLoadout = null;
    public float BM_IronPill_LastGained = 0f;
    public List<int> WishQueue = new();
    public Dictionary<int, int[]> EnabledEnergyIDs = [];
    public Dictionary<int, int[]> EnabledMagicIDs = [];
    public Dictionary<int, int[]> EnabledRes3IDs = [];
    public double TotalTimePlayedNormal = 0.0;
    public double TotalTimePlayedEvil = 0.0;
    public double TotalTimePlayedSadistic = 0.0;
    public int AutoMayGenMode = 0;
    public long ExpGainedLastRB = 0L;
    public long ExpGainedThisRB = 0L;
    public long SeedsGainedLastRB = 0L;
    public long SeedsGainedThisRB = 0L;
    public long PoopGainedLastRB = 0L;
    public long PoopGainedThisRB = 0L;
    public long APGainedLastRB = 0L;
    public long APGainedThisRB = 0L;
    public long QPGainedLastRB = 0L;
    public long QPGainedThisRB = 0L;
    public long PPGainedLastRB = 0L;
    public long PPGainedThisRB = 0L;
    public int CurrentDiggerLoadoutId = 0;
    public float CubePowerBoostThisRB = 0f;
    public float CubePowerBoostLastRB = 0f;
    public float CubeToughnessBoostThisRB = 0f;
    public float CubeToughnessBoostLastRB = 0f;
    public Dictionary<int, List<int>> DiggerLoadouts = new() { { 0, new() }, { 1, new() }, { 2, new() } };
    public Dictionary<int, List<long>> DiggerLevels = new() { { 0, new() }, { 1, new() }, { 2, new() } };
    public double LastRebirthTime = 0.0;
}
jshepler commented 2 months ago

Here's a modded save that doesn't have those 5 dictionaries in the DTO. Import still fails for type 6.

QuickSave_2024-09-19_14-27-05.txt

gmiclotte commented 1 day ago

Hi, quick update. I’ve been busy with other responsibilities, so it took a (long) while, but I made a new JavaScript library to parse MS-NRBF data, and it seems to work. Next step is integrating it with the Gear Optimizer, but that might again take some time.

Thanks for all the save files and for your patience!