Replies: 7 (Who?), Viewed: 327 times.
Virtual gardener
staff: administrator
Original Poster
#1 Old 15th Jul 2020 at 2:29 PM
Default Keeping book in inventory on save load
Hey there!

For the sewing table, I'm currently trying to deal with a bug that I can't seem to find the answer to. So hopefully someone might be able to help  The issue currently is that a sim can buy a book, have it in their inventories and once you save & quit, come back again later, the books have disappeared.

Now on a global way, I load in the books as followed:
Code:
        private static bool sObjectGroupCreated = false;
        
        private static List<XmlDbData> sDelayedSkillBooks = new List<XmlDbData>();

      static GlobalOptionsSewingTable()
        {
            LoadSaveManager.ObjectGroupsPreLoad += GlobalOptionsSewingTable.OnPreload;
            World.OnWorldLoadFinishedEventHandler += new EventHandler(OnWorldLoadFinished);
        }

        static void OnPreload()
        { 
                   if (!sObjectGroupCreated)
                    {
                        sObjectGroupCreated = true;
                        if (sDelayedSkillBooks.Count > 0)
                        {
                            foreach (XmlDbData sDelayedSkillBook in sDelayedSkillBooks)
                            {
                                ParseBooks();
                            }
                            sDelayedSkillBooks.Clear();
                            Bookstore.mItemDictionary.Clear();
                            Bookstore.LoadData();
                        }
                  }
      }
        public static void OnWorldLoadFinished(object sender, EventArgs e)
        {
           if (!alreadyParsed)
            {
                ParseBooks();
            }
            alreadyParsed = true;      
      }

Now the onworldfinished stuff is obviously getting the stuff loaded in the bookstore. For that, I use the code Arsil wrote: https://modthesims.info/showthread....802#post4675802

But I actually don't know the load save mechanism to know what parses the books right back into a sim's inventory. 

Thanks!
Advertisement
Field Researcher
#2 Old 16th Jul 2020 at 2:36 AM Last edited by gamefreak130 : 16th Jul 2020 at 3:34 AM.
Quote:
Originally Posted by Lyralei
Hey there!

For the sewing table, I'm currently trying to deal with a bug that I can't seem to find the answer to. So hopefully someone might be able to help  The issue currently is that a sim can buy a book, have it in their inventories and once you save & quit, come back again later, the books have disappeared.

Now the onworldfinished stuff is obviously getting the stuff loaded in the bookstore. For that, I use the code Arsil wrote: https://modthesims.info/showthread....802#post4675802

But I actually don't know the load save mechanism to know what parses the books right back into a sim's inventory. 

Thanks!


Hmm...I'm not quite sure what the issue is here. Parsing the book data on preload should be enough to keep the books from getting clobbered by the game. Maybe try just turning the OnWorldLoadFinished() function into the new ObjectGroupsPreLoadHandler? The ParseBooks() function should not be called multiple times, as attempting to add an already-existing key into a dictionary throws an error in C#.

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Virtual gardener
staff: administrator
Original Poster
#3 Old 16th Jul 2020 at 12:21 PM
Quote:
Originally Posted by gamefreak130
Hmm...I'm not quite sure what the issue is here. Parsing the book data on preload should be enough to keep the books from getting clobbered by the game. Maybe try just turning the OnWorldLoadFinished() function into the new ObjectGroupsPreLoadHandler? The ParseBooks() function should not be called multiple times, as attempting to add an already-existing key into a dictionary throws an error in C#.
Yeah that's a good point, thinking about it, it makes no sense really to have the same code on preload and Worldloadfinished. :p Now I used to load the books in on worldloadfinished before adding it also on preload but that didn't do the trick either. 
Virtual gardener
staff: administrator
Original Poster
#4 Old 18th Jul 2020 at 11:04 AM
So I decided to try and see if it works on just preload, but that doesn't seem to even load it in the bookstores. So I think this really needs to be done on onworldloadfinished (Which makes sense, since OnPreload is while loading the world. So no everything is probably instantiated yet). 

I'll dig a bit deeper, but I think you might be right on the dictionary issue.

EDIT I think it might help to also share the ParseBooks code, although that's entirely Arsil's code:

Code:
        public static void ParseBooks()
		{
			string text = "BooksSewable";
			XmlDbData xmlDbData = XmlDbData.ReadData(text);
			if (xmlDbData != null && xmlDbData.Tables != null)
			{
				try
				{
					sDelayedSkillBooks.Add(xmlDbData);
					BookData.LoadBookData(xmlDbData, "BookSkill", BookData.BookType.Skill);
					bool loaded = true;
					if(loaded)
					{
						Bookstore.mItemDictionary.Clear();
						Bookstore.LoadData();
					}
				}
				catch (Exception ex)
				{
					SimpleMessageDialog.Show("Arsil's CustomBookLoader", ex.StackTrace);
					SimpleMessageDialog.Show("[DEBUG] Arsil's CustomBookLoader", "Error parsing custom book data from " + text);
				}
			}
			else
			{
				SimpleMessageDialog.Show("[DEBUG] Arsil's CustomBookLoader", "Resource " + text + " of type _XML not found or with no data defined!");
			}
		
Virtual gardener
staff: administrator
Original Poster
#5 Old 18th Jul 2020 at 1:21 PM
Checking the code on how the game re-gets data from a file save, or particularly, how it gets the saved inventory data and puts it right back in the sim's inventory list, makes me feel like at some point the books are considered 'dead' or it's being deleted later on due to them being faulty somehow.

Inventory just really seems like on gamestates (gamestate in this case being reloading the save/game), re-doing checks which aren't initially done on regular gameplay, it, therefore, sees the custom books as 'bad'. But I'm just not sure how to debug that currently.
Field Researcher
#6 Old 18th Jul 2020 at 6:06 PM
You're mostly right. To make a long story short, as soon as a book object is loaded from a save, the game attempts to find that book's data in the associated book data dictionary. If it doesn't find it, then the game immediately calls Dispose() and the book is destroyed. All of this happens before OnWorldLoadFinished, so injecting your custom data then will do nothing.

It's odd that the Bookstore data isn't loading properly for you. Out of sheer curiosity, I disassembled your pure script assembly from v1.0.1, and reassembled it with the following quick-and-dirty edits:

Code:
static GlobalOptionsSewingTable()
{
	LoadSaveManager.ObjectGroupsPreLoad += new ObjectGroupsPreLoadHandler(GlobalOptionsSewingTable.OnPreload);
	LoadSaveManager.ObjectGroupsPreLoad += new ObjectGroupsPreLoadHandler(GlobalOptionsSewingTable.ParseBooks); // Parse books on PreLoad
	World.OnWorldLoadFinishedEventHandler += new EventHandler(GlobalOptionsSewingTable.OnWorldLoadFinished);
	World.OnWorldQuitEventHandler += new EventHandler(GlobalOptionsSewingTable.OnWorldQuit);
}


Code:
public static void OnWorldLoadFinished(object sender, EventArgs e)
{
	// Inject interactions, add listeners, etc.
	if (!GlobalOptionsSewingTable.alreadyParsed)
	{
                // Removed ParseBooks()
                // Quitting to main menu and loading another game will throw an error because of a lack of this check
                // I don't care because CIL is hard 
	}
	GlobalOptionsSewingTable.alreadyParsed = true;
}


After making these changes, the books load fine, and I still see them appear properly in bookstores (as long as you don't quit to main menu and reload, of course).

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Virtual gardener
staff: administrator
Original Poster
#7 Old 19th Jul 2020 at 2:48 PM
Quote:
Originally Posted by gamefreak130
You're mostly right. To make a long story short, as soon as a book object is loaded from a save, the game attempts to find that book's data in the associated book data dictionary. If it doesn't find it, then the game immediately calls Dispose() and the book is destroyed. All of this happens before OnWorldLoadFinished, so injecting your custom data then will do nothing.

It's odd that the Bookstore data isn't loading properly for you. Out of sheer curiosity, I disassembled your pure script assembly from v1.0.1, and reassembled it with the following quick-and-dirty edits:

Code:
static GlobalOptionsSewingTable()
{
   LoadSaveManager.ObjectGroupsPreLoad += new ObjectGroupsPreLoadHandler(GlobalOptionsSewingTable.OnPreload);
   LoadSaveManager.ObjectGroupsPreLoad += new ObjectGroupsPreLoadHandler(GlobalOptionsSewingTable.ParseBooks); // Parse books on PreLoad
   World.OnWorldLoadFinishedEventHandler += new EventHandler(GlobalOptionsSewingTable.OnWorldLoadFinished);
   World.OnWorldQuitEventHandler += new EventHandler(GlobalOptionsSewingTable.OnWorldQuit);
}


Code:
public static void OnWorldLoadFinished(object sender, EventArgs e)
{
   // Inject interactions, add listeners, etc.
   if (!GlobalOptionsSewingTable.alreadyParsed)
   {
                // Removed ParseBooks()
                // Quitting to main menu and loading another game will throw an error because of a lack of this check
                // I don't care because CIL is hard 
   }
   GlobalOptionsSewingTable.alreadyParsed = true;
}


After making these changes, the books load fine, and I still see them appear properly in bookstores (as long as you don't quit to main menu and reload, of course).
The current code also works with the bookstores, it just seems that when the sim has bought the book and has it in their inventories, and you happen to save, quit and reload the game later on, the books have completely disappeared. They'll still be in the bookstore, just not in the sim's inventory anymore.

Lemme try the quick and dirty edits though! I'll then do the more hardcore logistics from there :p

I'll let you know how it goes!
Virtual gardener
staff: administrator
Original Poster
#8 Old 19th Jul 2020 at 2:59 PM
Huh, that actually did it! That was waaay too easy from where I was going with this code, lol. But thank you so much! Of course, I need to test it a bit more throughout, but thank you so much!
Back to top