Suppress Inventory Monitor when auto 'Loading on Start'

Bonfyre

New member
HandleWillStartLoadingSave event not fired when Saver is loaded on start up (after the manager is already loaded) therefore the monitors are never suppressed on auto loads.

When Load On Start is required in your saver (the saver is created after the manager), you never get the load events since it calls if (m_LoadOnStart) { Load(); }(edited)

I think we need a new event or the event needs to be moved to the saver load level?
 
How about we disable the Inventory Monitor only when the Inventory Saver loads the Inventory Data?

So the new InventorySaver script deserialize and load function woul look like this:
Code:
/// <summary>
/// Deserialize and load the save data.
/// </summary>
/// <param name="serializedSaveData">The serialized save data.</param>
public override void DeserializeAndLoadSaveData(Serialization serializedSaveData)
{
    if (m_Inventory == null) { return; }
    
    if (!m_Additive) {
        var itemCollectionCount = m_Inventory.GetItemCollectionCount();
        for (int i = 0; i < itemCollectionCount; i++) {
            m_Inventory.GetItemCollection(i).RemoveAll();
        }
    }
    var savedData = serializedSaveData.DeserializeFields(MemberVisibility.All) as InventorySaveData?;
    if (savedData.HasValue == false) {
        return;
    }
    var inventorySaveData = savedData.Value;
    if (inventorySaveData.ItemIDAmountsPerCollection == null) { return; }
    
    EventHandler.ExecuteEvent(m_Inventory.gameObject, EventNames.c_InventoryGameObject_InventoryMonitorListen_Bool, false);
    for (int i = 0; i < inventorySaveData.ItemIDAmountsPerCollection.Length; i++) {
        var itemIDAmounts = inventorySaveData.ItemIDAmountsPerCollection[i];
        var itemAmounts = new ItemAmount[itemIDAmounts.Length];
        for (int j = 0; j < itemIDAmounts.Length; j++) {
            if (InventorySystemManager.ItemRegister.TryGetValue(itemIDAmounts[j].ID, out var item) == false) {
                Debug.LogWarning($"Saved Item ID {itemIDAmounts[j].ID} could not be retrieved from the Inventory System Manager.");
                continue;
            }
            itemAmounts[j] = new ItemAmount(item, itemIDAmounts[j].Amount);
        }
        var itemCollection = m_Inventory.GetItemCollection(i);
        if (itemCollection == null) {
            Debug.LogWarning("Item Collection from save data is missing in the scene.");
        } else {
            m_Inventory.GetItemCollection(i).AddItems(itemAmounts);
        }
    }
    
    EventHandler.ExecuteEvent(m_Inventory.gameObject, EventNames.c_InventoryGameObject_InventoryMonitorListen_Bool, true);
}




And for those who use the Integration with the Character Controller can do something similar for the InventoryBridgeSaver


Code:
/// <summary>
/// Deserialize and load the save data.
/// </summary>
/// <param name="serializedSaveData">The serialized save data.</param>
public override void DeserializeAndLoadSaveData(Serialization serializedSaveData)
{
    if (m_Inventory == null) { return; }
    var savedData = serializedSaveData.DeserializeFields(MemberVisibility.All) as InventoryBridgeSaveData?;
    if (savedData.HasValue == false) {
        return;
    }
    var inventorySaveData = savedData.Value;
    if (inventorySaveData.ItemIDAmountsPerCollection == null) { return; }
    
    EventHandler.ExecuteEvent(m_Inventory.gameObject, EventNames.c_InventoryGameObject_InventoryMonitorListen_Bool, false);
    // Restore the ItemSets. This should be done before adding any items so the ItemSets are correct.
    for (int i = 0; i < inventorySaveData.CategoryItemSets.Length; i++) {
        Debug.Log($"item set {i} count {inventorySaveData.CategoryItemSets[i].ItemSetList.Count}");
    }
    m_ItemSetManager.CopyFrom(inventorySaveData.CategoryItemSets);
    // Restore the items.
    for (int i = 0; i < inventorySaveData.ItemIDAmountsPerCollection.Length; i++) {
        var itemCollection = m_Inventory.GetItemCollection(i);
        if (itemCollection == null) {
            Debug.LogWarning("Item Collection from save data is missing in the scene.");
            continue;
        }
        // The Loadout should not be restored as it stays constant.
        if (itemCollection.Purpose == ItemCollectionPurpose.Loadout) {
            continue;
        }
        var itemIDAmounts = inventorySaveData.ItemIDAmountsPerCollection[i];
        var itemAmounts = new ItemAmount[itemIDAmounts.Length];
        for (int j = 0; j < itemIDAmounts.Length; j++) {
            if (InventorySystemManager.ItemRegister.TryGetValue(itemIDAmounts[j].ID, out var item) == false) {
                Debug.LogWarning($"Saved Item ID {itemIDAmounts[j].ID} could not be retrieved from the Inventory System Manager.");
                continue;
            }
            itemAmounts[j] = new ItemAmount(item, itemIDAmounts[j].Amount);
        }
        
        itemCollection.AddItems(itemAmounts);
    }
    
    EventHandler.ExecuteEvent(m_Inventory.gameObject, EventNames.c_InventoryGameObject_InventoryMonitorListen_Bool, true);
    //Wait for a frame such that the start function of items can get called.
    StartCoroutine(EquipItemNextFrame(inventorySaveData));
}

I hope that solves your issue
 
`SetMonitoredInventory` in `InventoryMonitor` is never called to register these events. Do I need to call this?
 
When I add this to the Awake method in the `InventoryMonitor` everything works as expected.
C#:
if (m_MonitoredInventory != null) {
    SetMonitoredInventory(m_MonitoredInventory);
}
 
Nevermind I realized that is if you want to monitor more than one inventory. I have no idea why its not working yet.
 
I'm very sorry, that was a mistake on my part, I should have tested the monitor more throroughly.

I moved a few things around, now I set the register in a single place. And I only call it in start or if some other function sets the Inventory.
Hopefully that works better. Please find the new InventoryMonitor attached, let me know if you need anything else.
 

Attachments

  • InventoryMonitor.cs
    15 KB · Views: 3
@Bonfyre i managed to do This by simply disabling the parent monitor object.
Then after all your code is loaded enable it again with a waitUntil inumerator loop
 
Top