/// <summary> /// Gets the top-level ItemStorage containing this storage. I.e. if this /// is a crate inside a backpack will return the crate ItemStorage. If this is not in anything /// will simply return this /// </summary> /// <returns></returns> public GameObject GetRootStorageOrPlayer() { try { ItemStorage storage = this; var pickupable = storage.GetComponent <Pickupable>(); while (pickupable != null && pickupable.ItemSlot != null) { storage = pickupable.ItemSlot.ItemStorage; pickupable = storage.GetComponent <Pickupable>(); if (pickupable == null) { if (storage.player != null) { return(storage.player.gameObject); } } } return(storage.gameObject); } catch (NullReferenceException exception) { Logger.LogError("Caught NRE in ItemStorage: " + exception.Message, Category.Inventory); return(null); } }
/// <summary> /// Can be called client and server side to free up the cached /// slots in this storage. Should be called when storage is going to be destroyed or /// will be no longer known by the client. On server side, also destroys all the items in the slot. /// </summary> public static void Free(ItemStorage storageToFree) { if (CustomNetworkManager.Instance != null && CustomNetworkManager.Instance._isServer) { // destroy all items in the slots foreach (var slot in storageToFree.GetItemSlots()) { if (slot.Item != null) { Inventory.ServerDespawn(slot); } } } if (storageToFree.GetComponent <NetworkIdentity>()) { var instanceID = storageToFree.GetComponent <NetworkIdentity>().GetInstanceID(); slots.TryGetValue(instanceID, out var dict); if (dict != null) { dict.Clear(); slots.Remove(instanceID); } } }
/// <summary> /// Gets the top-level ItemStorage containing this storage. I.e. if this /// is a crate inside a backpack will return the backpack ItemStorage. If this is not in anything /// will simply return this /// </summary> /// <returns></returns> public ItemStorage GetRootStorage() { ItemStorage storage = this; var pickupable = storage.GetComponent <Pickupable>(); while (pickupable != null && pickupable.ItemSlot != null) { storage = pickupable.ItemSlot.ItemStorage; pickupable = storage.GetComponent <Pickupable>(); } return(storage); }
/// <summary> /// Gets the top-level ItemStorage containing this storage. I.e. if this /// is a crate inside a backpack will return the crate ItemStorage. If this is not in anything /// will simply return this /// </summary> /// <returns></returns> public GameObject GetRootStorageOrPlayer() { ItemStorage storage = this; var pickupable = storage.GetComponent <Pickupable>(); while (pickupable != null && pickupable.ItemSlot != null) { storage = pickupable.ItemSlot.ItemStorage; pickupable = storage.GetComponent <Pickupable>(); if (pickupable == null) { if (storage.player != null) { return(storage.player.gameObject); } } } return(storage.gameObject); }
/// <summary> /// Checks if the indicated item can fit in this slot. /// </summary> /// <param name="toStore"></param> /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param> /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param> /// <returns></returns> public bool CanFit(Pickupable toStore, bool ignoreOccupied = false, GameObject examineRecipient = null) { if (toStore == null) { return(false); } if (IsEnabled == false) { return(false); } ItemStorage storageToCheck = itemStorage; StorageIdentifier storeIdentifier = toStore.GetComponent <StorageIdentifier>(); //Check if there is a deny entry for this toStore item if (storageToCheck != null && storeIdentifier != null) { InteractableStorage interactiveStorage = storageToCheck.GetComponent <InteractableStorage>(); if (interactiveStorage != null) { if (interactiveStorage.denyStorageOfStorageItems.HasFlag(storeIdentifier.StorageItemName)) { Logger.LogTrace($"Cannot fit {toStore} in slot {ToString()}, item was blacklisted.", Category.Inventory); if (examineRecipient) { Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't be placed there!"); } return(false); } } } //go through this slot's ancestors and make sure none of them ARE toStore, //as that would create a loop in the inventory hierarchy int count = 0; while (storageToCheck != null) { if (storageToCheck.gameObject == toStore.gameObject) { Logger.LogTraceFormat( "Cannot fit {0} in slot {1}, this would create an inventory hierarchy loop (putting the" + " storage inside itself)", Category.Inventory, toStore, ToString()); if (examineRecipient) { Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go inside itself!"); } return(false); } //get parent item storage if it exists var pickupable = storageToCheck.GetComponent <Pickupable>(); if (pickupable != null && pickupable.ItemSlot != null) { storageToCheck = pickupable.ItemSlot.ItemStorage; } else { storageToCheck = null; } count++; if (count > 5) { Logger.LogTraceFormat( "Something went wrong when adding {0} in slot {1}, aborting!", Category.Inventory, toStore, ToString()); return(false); } } //if the slot already has an item, it's allowed to stack only if the item to add can stack with //the existing item. if (!ignoreOccupied && item != null) { var thisStackable = item.GetComponent <Stackable>(); var otherStackable = toStore.GetComponent <Stackable>(); var stackResult = thisStackable != null && otherStackable != null && thisStackable.CanAccommodate(otherStackable); if (!stackResult) { Logger.LogTraceFormat( "Cannot stack {0} in slot {1}", Category.Inventory, toStore, ToString()); } else { Logger.LogTraceFormat( "Can stack {0} in slot {1}", Category.Inventory, toStore, ToString()); } return(stackResult); } //no item in slot and no inventory loop created, //check if this storage can fit this according to its specific capacity logic var canFit = itemStorage.ItemStorageCapacity.CanFit(toStore, this.slotIdentifier); if (canFit) { return(true); } if (examineRecipient) { //if this is going in a player's inventory, use a more appropriate message. var targetPlayerScript = ItemStorage.GetComponent <PlayerScript>(); if (targetPlayerScript != null) { //going into a top-level inventory slot of a player Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go in that slot."); } else { //going into something else Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} doesn't fit in the {ItemStorage.gameObject.ExpensiveName()}."); } } return(false); }
/// <summary> /// Checks if the indicated item can fit in this slot. /// </summary> /// <param name="toStore"></param> /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param> /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param> /// <returns></returns> public bool CanFit(Pickupable toStore, bool ignoreOccupied = false, GameObject examineRecipient = null) { if (toStore == null) { return(false); } //go through this slot's ancestors and make sure none of them ARE toStore, //as that would create a loop in the inventory hierarchy ItemStorage storageToCheck = itemStorage; while (storageToCheck != null) { if (storageToCheck.gameObject == toStore.gameObject) { Logger.LogTraceFormat( "Cannot fit {0} in slot {1}, this would create an inventory hierarchy loop (putting the" + " storage inside itself)", Category.Inventory, toStore, ToString()); if (examineRecipient) { Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go inside itself!"); } return(false); } //get parent item storage if it exists var pickupable = storageToCheck.GetComponent <Pickupable>(); if (pickupable != null && pickupable.ItemSlot != null) { storageToCheck = pickupable.ItemSlot.ItemStorage; } else { storageToCheck = null; } } //if the slot already has an item, it's allowed to stack only if the item to add can stack with //the existing item. if (!ignoreOccupied && item != null) { var thisStackable = item.GetComponent <Stackable>(); var otherStackable = toStore.GetComponent <Stackable>(); return(thisStackable != null && otherStackable != null && thisStackable.CanAccommodate(otherStackable)); } //no item in slot and no inventory loop created, //check if this storage can fit this according to its specific capacity logic var canFit = itemStorage.ItemStorageCapacity.CanFit(toStore, this.slotIdentifier); if (canFit) { return(true); } if (examineRecipient) { //if this is going in a player's inventory, use a more appropriate message. var targetPlayerScript = ItemStorage.GetComponent <PlayerScript>(); if (targetPlayerScript != null) { //going into a top-level inventory slot of a player Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go in that slot."); } else { //going into something else Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} doesn't fit in the {ItemStorage.gameObject.ExpensiveName()}."); } } return(false); }