예제 #1
0
    /// <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);
        }
    }
예제 #2
0
    /// <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);
            }
        }
    }
예제 #3
0
    /// <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);
    }
예제 #4
0
    /// <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);
    }
예제 #5
0
    /// <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);
    }
예제 #6
0
    /// <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);
    }