using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; using UnityEngine.SceneManagement; public class Inventory : MonoBehaviour { //perhaps use these additional slots for holsters attached to the player? public List additionalSlots; public GameObject itemContainerPrefab; private List _inventorySlots; public InventorySaveData inventorySaveData; private void Awake() { _inventorySlots = new List(); foreach (var inventorySlot in additionalSlots) { inventorySlot.SetParentInventory(this); _inventorySlots.Add(inventorySlot); } Debug.Log(_inventorySlots.Count); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; var inventorySlotsInChildren = GetComponentsInChildren(); foreach (var inventorySlot in inventorySlotsInChildren) { inventorySlot.SetParentInventory(this); _inventorySlots.Add(inventorySlot); } } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } public bool AddItem(ItemData item) { if (item.canStack) { return AddItem(ConvertToInventoryItem(item)); } return AddToFirstOpenSlot(item.prefab.gameObject); } public bool AddItem(InventoryItem item) { //Stacks the item if it already exists in the inventory. foreach (var inventorySlot in _inventorySlots.Where(inventorySlot => inventorySlot.ContainsItem(item.GetItemid()))) { inventorySlot.GetItem().ChangeCount(item.saveData.count); return true; } return AddToFirstOpenSlot(item.gameObject); } private bool AddToFirstOpenSlot(GameObject item) { foreach (var inventorySlot in _inventorySlots.Where(inventorySlot => !inventorySlot.ContainsItem())) { inventorySlot.AssignItem(item); return true; } return false; } private void AddToSpecificSlot(GameObject item, int slot) { _inventorySlots[slot].AssignItem(item); } private InventoryItem ConvertToInventoryItem(ItemData item) { var inventoryItem = Instantiate(itemContainerPrefab, transform); itemContainerPrefab.GetComponent().itemPrefab = item.prefab.gameObject; return inventoryItem.gameObject.GetComponent(); } public void SaveInventory() { inventorySaveData.inventoryContents.Clear(); foreach (var inventoryItem in _inventorySlots.Select(inventorySlot => inventorySlot.GetItem())) { //adds an itemsavedata to the list if it exists or an empty one if it doesnt inventorySaveData.inventoryContents.Add(inventoryItem != null ? inventoryItem.saveData : new ItemSaveData()); } var json = JsonUtility.ToJson(inventorySaveData); Debug.Log(json); using var sw = new StreamWriter(Path.Combine(Application.persistentDataPath, "invSave.dat")); sw.Write(json); Debug.Log("Inv data saved!"); } public IEnumerator LoadInventory() { //Wait for 1 second after loading the scene to prevent missing prefabs. (1 second delay might also break something in the future) yield return new WaitForSeconds(1); //todo make this modular, currently only supports one inventory, although the slots can be anywhere. if (File.Exists(Path.Combine(Application.persistentDataPath, "invSave.dat"))) { var saveData = JsonUtility.FromJson(File.ReadAllText(Path.Combine(Application.persistentDataPath, "invSave.dat"))); Debug.Log(saveData); Debug.Log("Inv data loaded! total "+saveData.inventoryContents.Count); for (var i = 0; i < saveData.inventoryContents.Count; i++) { //prevents overwriting inventory slots when there is something already in there. //if (_inventorySlots[i]._itemInSlot != null) continue; var data = saveData.inventoryContents[i]; //if there isnt an item in the slot the count is 0 Debug.Log(data.assetPath + " "+data.count); if (data.count == 0) continue; //Loads the prefab from resources folder var load = Resources.Load(data.assetPath, typeof(GameObject)) as GameObject; if (load == null) { Debug.LogError("Didn't find a prefab at " + data.assetPath); yield break; } Debug.Log(load); AddToSpecificSlot(load, i); //sets the count after the item has been converted into inventoryitem if (load.GetComponent().canStack) _inventorySlots[i]._itemInSlot.GetComponent().saveData.count = data.count; } } else Debug.LogError("There is no save data!"); } void OnSceneLoaded(Scene scene, LoadSceneMode mode) { Debug.Log("OnSceneLoaded: " + scene.name); //primitive check to only load the inventory when you are in the home scene. if (scene.name.Contains("Homebase")) StartCoroutine(LoadInventory()); } }