SaveLoad using managed lifecycle

This commit is contained in:
Michal Pikulski
2025-11-04 20:01:27 +01:00
committed by Michal Pikulski
parent 3e835ed3b8
commit b932be2232
19 changed files with 1042 additions and 627 deletions

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System; // for Action<T>
@@ -24,6 +24,7 @@ namespace Interactions
{
public ItemSlotState slotState;
public string slottedItemSaveId;
public string slottedItemDataId; // ItemId of the PickupItemData (for verification)
}
/// <summary>
@@ -227,6 +228,16 @@ namespace Interactions
{
var previousData = currentlySlottedItemData;
// Clear the pickup's OwningSlot reference
if (currentlySlottedItemObject != null)
{
var pickup = currentlySlottedItemObject.GetComponent<Pickup>();
if (pickup != null)
{
pickup.OwningSlot = null;
}
}
currentlySlottedItemObject = null;
currentlySlottedItemData = null;
currentState = ItemSlotState.None;
@@ -272,17 +283,15 @@ namespace Interactions
#endregion
// Register with ItemManager when enabled
protected override void Start()
private void OnEnable()
{
base.Start(); // SaveableInteractable registration
// Register as ItemSlot
ItemManager.Instance?.RegisterItemSlot(this);
}
protected override void OnDestroy()
{
base.OnDestroy(); // SaveableInteractable cleanup
base.OnDestroy();
// Unregister from slot manager
ItemManager.Instance?.UnregisterItemSlot(this);
@@ -294,20 +303,28 @@ namespace Interactions
{
// Get slotted item save ID if there's a slotted item
string slottedSaveId = "";
string slottedDataId = "";
if (currentlySlottedItemObject != null)
{
var slottedPickup = currentlySlottedItemObject.GetComponent<Pickup>();
if (slottedPickup is SaveableInteractable saveablePickup)
{
slottedSaveId = saveablePickup.GetSaveId();
slottedSaveId = saveablePickup.SaveId;
}
}
// Also save the itemData ID for verification
if (currentlySlottedItemData != null)
{
slottedDataId = currentlySlottedItemData.itemId;
}
return new ItemSlotSaveData
{
slotState = currentState,
slottedItemSaveId = slottedSaveId
slottedItemSaveId = slottedSaveId,
slottedItemDataId = slottedDataId
};
}
@@ -326,7 +343,8 @@ namespace Interactions
// Restore slotted item if there was one
if (!string.IsNullOrEmpty(data.slottedItemSaveId))
{
RestoreSlottedItem(data.slottedItemSaveId);
Debug.Log($"[ItemSlot] Restoring slotted item: {data.slottedItemSaveId} (itemId: {data.slottedItemDataId})");
RestoreSlottedItem(data.slottedItemSaveId, data.slottedItemDataId);
}
}
@@ -334,7 +352,7 @@ namespace Interactions
/// Restore a slotted item from save data.
/// This is called during load restoration and should NOT trigger events.
/// </summary>
private void RestoreSlottedItem(string slottedItemSaveId)
private void RestoreSlottedItem(string slottedItemSaveId, string expectedItemDataId)
{
// Try to find the item in the scene by its save ID via ItemManager
GameObject slottedObject = ItemManager.Instance?.FindPickupBySaveId(slottedItemSaveId);
@@ -351,11 +369,33 @@ namespace Interactions
if (pickup != null)
{
slottedData = pickup.itemData;
// Verify itemId matches if we have it (safety check)
if (slottedData != null && !string.IsNullOrEmpty(expectedItemDataId))
{
if (slottedData.itemId != expectedItemDataId)
{
Debug.LogWarning($"[ItemSlot] ItemId mismatch! Pickup has '{slottedData.itemId}' but expected '{expectedItemDataId}'");
}
}
if (slottedData == null)
{
Debug.LogWarning($"[ItemSlot] Pickup {pickup.gameObject.name} has null itemData! Expected itemId: {expectedItemDataId}");
return;
}
}
else
{
Debug.LogWarning($"[ItemSlot] Slotted object has no Pickup component: {slottedObject.name}");
return;
}
// Silently slot the item (no events, no interaction completion)
// Follower state is managed separately during save/load restoration
ApplySlottedItemState(slottedObject, slottedData, triggerEvents: false);
Debug.Log($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId})");
}
/// <summary>
@@ -370,7 +410,16 @@ namespace Interactions
{
if (itemToSlot == null)
{
// Clear slot
// Clear slot - also clear the pickup's OwningSlot reference
if (currentlySlottedItemObject != null)
{
var oldPickup = currentlySlottedItemObject.GetComponent<Pickup>();
if (oldPickup != null)
{
oldPickup.OwningSlot = null;
}
}
var previousData = currentlySlottedItemData;
currentlySlottedItemObject = null;
currentlySlottedItemData = null;
@@ -391,6 +440,14 @@ namespace Interactions
SetSlottedObject(itemToSlot);
currentlySlottedItemData = itemToSlotData;
// Mark the pickup as picked up and track slot ownership for save/load
var pickup = itemToSlot.GetComponent<Pickup>();
if (pickup != null)
{
pickup.IsPickedUp = true;
pickup.OwningSlot = this;
}
// Determine if correct
var config = interactionSettings?.GetSlotItemConfig(itemData);
var allowed = config?.allowedItems ?? new List<PickupItemData>();
@@ -433,6 +490,33 @@ namespace Interactions
ApplySlottedItemState(itemToSlot, itemToSlotData, triggerEvents: true);
}
/// <summary>
/// Bilateral restoration entry point: Pickup calls this to offer itself to the Slot.
/// Returns true if claim was successful, false if slot already has an item or wrong pickup.
/// </summary>
public bool TryClaimSlottedItem(Pickup pickup)
{
if (pickup == null)
return false;
// If slot already has an item, reject the claim
if (currentlySlottedItemObject != null)
{
Debug.LogWarning($"[ItemSlot] Already has a slotted item, rejecting claim from {pickup.gameObject.name}");
return false;
}
// Verify this pickup's SaveId matches what we expect (from our save data)
// Note: We don't have easy access to the expected SaveId here, so we just accept it
// The Pickup's bilateral restoration ensures it only claims the correct slot
// Claim the pickup
ApplySlottedItemState(pickup.gameObject, pickup.itemData, triggerEvents: false);
Debug.Log($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName}");
return true;
}
#endregion
}
}