/// <summary>
        /// Add <paramref name="item"/> to the NonFull cache if qualified.
        /// </summary>
        /// <param name="item"> Item to add. </param>
        private void AddToNonFull(Thing item)
        {
            // Possible states:
            // 1. Item stack count equals to stack limit.
            // 2. Item not in cache.
            // 3. Item in cache.

            ThingDef def           = item.def;
            int      defStackLimit = def.stackLimit;

            // State 1
            if (item.stackCount == defStackLimit)
            {
                return;
            }

            // State 2
            if (!NonFullThings.TryGetValue(item, out Thing value))
            {
                NonFullThings[item] = item;
                return;
            }

            // State 3
            // Update() method will take care of the change related to value.
            // Note: Steps are taken to clean up the spawn setup for item if TryAbsorbStack() returns true,
            // because item is DeSpawned when in the process of spawning.
            // Detail can check in the Harmony patch to GenSpawn.Spawn() and Thing.SpawnSetup().
            if (!value.TryAbsorbStack(item, true))
            {
                this.NonFullThings[item] = item;
            }
        }
 public void Clear()
 {
     ThingCache.Clear();
     NonFullThings.Clear();
     TotalWeight = 0;
     Count       = 0;
 }
 /// <summary>
 /// Remove item from NonFull cache.
 /// </summary>
 /// <param name="item"> Item to remove. </param>
 /// <remarks> If the add and update operation runs correctly, there will always be only one or zero non-full stack per kind. </remarks>
 private void RemoveFromNonFull(Thing item)
 {
     if (NonFullThings.TryGetValue(item, out Thing nonFullThings) &&
         nonFullThings == item)
     {
         NonFullThings.Remove(item);
     }
 }
        public int SpareSpaceOnNonFull(Thing thing)
        {
            if (NonFullThings.TryGetValue(thing, out Thing value))
            {
                return(thing.def.stackLimit - value.stackCount);
            }

            return(0);
        }
        /// <summary>
        /// Update items in storage.
        /// </summary>
        /// <param name="item"> The updated item. </param>
        /// <summary>
        ///     There could be many reason why the stackCount of an item changes in storage,
        /// e.g., decay, partially taken out for construction of projects. Therefore, it is necessary
        /// to update the NonFullThings here.
        /// </summary>
        public void Update(Thing item)
        {
            // Do not update things that are not already in storage.
            if (!this.ThingCache.TryGetValue(item.def, out Dictionary <Thing, float> things))
            {
                return;
            }

            if (!things.ContainsKey(item))
            {
                return;
            }

            float newWeight   = item.GetStatValue(StatDefOf.Mass) * item.stackCount;
            float oldWeight   = things[item];
            float deltaWeight = newWeight - oldWeight;

            TotalWeight += deltaWeight;
            things[item] = newWeight;

            if (this.NonFullThings.TryGetValue(item, out Thing nonFullThing))
            {
                if (item.stackCount == item.def.stackLimit)
                {
                    if (nonFullThing == item)
                    {
                        NonFullThings.Remove(item);
                    }
                }
                else
                {
                    // Possible states:
                    // 1. Item is the same as the one stored in NonFullThings, no action required.
                    // 2. Item is not the same as the one in NonFullThings.

                    // State 2
                    if (nonFullThing != item)
                    {
                        // TryAbsorbStack() will trigger a re-entry to this method for nonFullThing.
                        // The other branches in this method will take care of the re-entry.
                        if (!nonFullThing.TryAbsorbStack(item, true))
                        {
                            NonFullThings[item] = item;
                        }
                    }
                }
            }
            else
            {
                if (item.stackCount != item.def.stackLimit)
                {
                    this.NonFullThings[item] = item;
                }
            }
        }