public static void AddInventory(Colony colony, ushort type, int amount)
        {
            ColonyStatistics    stats     = Statistics.GetColonyStats(colony);
            TimedItemStatistics itemStats = stats.GetTimedItemStats(type);

            itemStats.AddInventory(amount);

            RemoveConsumerAddProducer(itemStats, ScientistJobSettingsHookOnNPCAtJob.npc, amount);
            RemoveConsumerAddProducer(itemStats, GuardJobSettingsHookShootAtTarget.npc, amount);
            RemoveConsumerAddProducer(itemStats, BlockFarmAreaJobHookOnNPCAtJob.npc, amount);
            RemoveConsumerAddProducer(itemStats, FarmAreaJobHookOnNPCAtJob.npc, amount);
            RemoveConsumerAddProducer(itemStats, BuilderBasicHookDoJob.npc, amount);
            RemoveConsumerAddProducer(itemStats, ColonyShopVisitTrackerHookOnVisit.npc, amount);
            RemoveConsumerAddProducer(itemStats, AbstractAreaJobHookOnNPCAtStockpile.npc, amount);

            if (ColonyShopVisitTrackerHookOnVisit.isFood)
            {
                // wonder if this gets ever called ? It shouldn't though
                itemStats.UseAsFood(-amount);
            }

            if (RuleHookTryExecute.trading)
            {
                itemStats.TradeIn(amount);
            }
        }
        public static void RemoveInventory(Colony colony, ushort type, int amount)
        {
            ColonyStatistics    stats     = Statistics.GetColonyStats(colony);
            TimedItemStatistics itemStats = stats.GetTimedItemStats(type);

            itemStats.RemoveInventory(amount);

            AddConsumerRemoveProducer(itemStats, ScientistJobSettingsHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, GuardJobSettingsHookShootAtTarget.npc, amount);
            AddConsumerRemoveProducer(itemStats, BlockFarmAreaJobHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, FarmAreaJobHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, BuilderBasicHookDoJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, ColonyShopVisitTrackerHookOnVisit.npc, amount);
            AddConsumerRemoveProducer(itemStats, AbstractAreaJobHookOnNPCAtStockpile.npc, amount);

            if (ColonyShopVisitTrackerHookOnVisit.isFood)
            {
                itemStats.UseAsFood(amount);
            }

            if (RuleHookTryExecute.trading)
            {
                itemStats.TradeOut(amount);
            }
        }
        public void OnNPCCraftedRecipe(IJob job, Recipe recipe, List <RecipeResult> result)
        {
            if (job == null || job.NPC == null || job.NPC.Colony == null)
            {
                return;
            }

            ColonyStatistics stats = GetColonyStats(job.NPC.Colony);

            if (recipe != null)
            {
                foreach (var item in recipe.Requirements)
                {
                    var itemStat = stats.GetTimedItemStats(item.Type);
                    itemStat.Consume(item.Amount);
                    itemStat.AddConsumer(job.NPC.ID);
                }
            }

            if (result != null)
            {
                foreach (var item in result)
                {
                    var itemStat = stats.GetTimedItemStats(item.Type);
                    itemStat.Produce(item.Amount);
                    itemStat.AddProducer(job.NPC.ID);
                }
            }
        }
        public static void RemoveInventory(Colony colony, ushort type, int amount)
        {
            DebugLog.Write(MethodBase.GetCurrentMethod().DeclaringType + "::" + MethodBase.GetCurrentMethod().Name, "Type: " + type.ToString() + ", Amount: " + amount.ToString());

            ColonyStatistics    stats     = Statistics.GetColonyStats(colony);
            TimedItemStatistics itemStats = stats.GetTimedItemStats(type);

            itemStats.RemoveInventory(amount);

            AddConsumerRemoveProducer(itemStats, ScientistJobSettingsHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, GuardJobSettingsHookShootAtTarget.npc, amount);
            AddConsumerRemoveProducer(itemStats, BlockFarmAreaJobHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, FarmAreaJobHookOnNPCAtJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, BuilderBasicHookDoJob.npc, amount);
            AddConsumerRemoveProducer(itemStats, ColonyShopVisitTrackerHookOnVisit.npc, amount);
            AddConsumerRemoveProducer(itemStats, AbstractAreaJobHookOnNPCAtStockpile.npc, amount);

            if (ItemTypes.GetType(type).ColonyPointsMeal > 0)
            {
                itemStats.UseAsFood(amount);
            }

            if (RuleHookTryExecute.trading)
            {
                itemStats.TradeOut(amount);
            }
        }
        public void OnNPCRecruited(NPCBase npc)
        {
            if (npc == null || npc.Colony == null)
            {
                return;
            }

            ColonyStatistics stats = GetColonyStats(npc.Colony);

            stats.NPCProduce();

            AddProducerConsumer(npc, npc.Job);
        }
        public void OnNPCLoaded(NPCBase npc, JSONNode json)
        {
            if (npc == null || npc.Colony == null)
            {
                return;
            }

            ColonyStatistics stats = GetColonyStats(npc.Colony);

            stats.NPCProduce();

            AddProducerConsumer(npc, npc.Job);
        }
        public void OnNPCDied(NPCBase npc)
        {
            if (npc == null || npc.Colony == null)
            {
                return;
            }

            ColonyStatistics stats = GetColonyStats(npc.Colony);

            stats.NPCConsume();

            RemoveProducerConsumer(npc, npc.Job);
        }
        public void OnNPCGathered(IJob job, Pipliz.Vector3Int pos, List <ItemTypes.ItemTypeDrops> items)
        {
            if (job == null || job.NPC == null || job.NPC.Colony == null || items == null)
            {
                return;
            }

            ColonyStatistics stats = GetColonyStats(job.NPC.Colony);

            foreach (var item in items)
            {
                var itemStat = stats.GetTimedItemStats(item.Type);
                itemStat.Produce(item.Amount);
                itemStat.AddProducer(job.NPC.ID);
            }
        }
        // Maybe add these too: (?)
        // JobFinder

        // Maybe I should wait until NPC is at stockpile and hook into the NPC.Inventory.Dump function? (often found in OnNPCAtStockpile)
        // That would be actualy more accurate than Crafted/Gathered, because these callbacks are called before the items are in the inventory
        // .. which means that if an NPC dies it's not accounted for correctly? but... is is much easier to keep track of recipes this way..
        // or process the NPC inventory on death.. but then how do we know if the NPC got it from the stockpile (Consumer) or produced it (Producer)?
        // is the Job still valid? and looping al items to check the hashSets would be kinda inneficient.. maybe use the global statistic? But that's per item haha

        public static ColonyStatistics GetColonyStats(Colony colony)
        {
            if (colony == null)
            {
                return(null);
            }

            ColonyStatistics stats;

            if (!colonyStats.TryGetValue(colony, out stats))
            {
                stats = new ColonyStatistics();
                colonyStats.Add(colony, stats);
            }

            return(stats);
        }