public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
        {
            MicroWorkGiverDef mdef = def as MicroWorkGiverDef;

            if (mdef == null)
            {
                return(false);
            }

            if (t.Map.designationManager.DesignationOn(t, mdef.designationDef) == null)
            {
                return(false);
            }

            if (pawn.CanReserve(t, 1, -1, null, forced))
            {
                List <Building> list = new List <Building>();
                foreach (var user in mdef.recipeDef.AllRecipeUsers)
                {
                    if (t.Map.listerBuildings.AllBuildingsColonistOfDef(user).Where(
                            x => !x.IsForbidden(pawn) &&
                            pawn.CanReserve(x, 1, -1, null, forced) &&
                            (x as IBillGiver) != null &&
                            (x as IBillGiver).CurrentlyUsableForBills() &&
                            pawn.CanReach(x, PathEndMode.InteractionCell, Danger.Deadly)
                            ).FirstOrDefault() != null)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn)
        {
            MicroWorkGiverDef mdef = def as MicroWorkGiverDef;

            if (mdef == null)
            {
                yield break;
            }

            foreach (Designation des in pawn.Map.designationManager.SpawnedDesignationsOfDef(mdef.designationDef))
            {
                if (!des.target.HasThing)
                {
                    Log.ErrorOnce("MicroRecipe designation has no target.", 63126);
                }
                else
                {
                    yield return(des.target.Thing);
                }
            }
            yield break;
        }
        public static void Populate()
        {
            List <RecipeDef>    list  = DefDatabase <RecipeDef> .AllDefsListForReading;
            List <WorkGiverDef> gList = DefDatabase <WorkGiverDef> .AllDefsListForReading;

            UnityEngine.Material mat = DesignationDefOf.Uninstall.iconMat;

            foreach (var rec in list.Where(x => x.AllRecipeUsers?.OfType <BuildableDef>().Any() == true &&
                                           x.ingredients?.Count() == 1 &&
                                           x.ingredients[0]?.filter?.AnyAllowedDef?.stackLimit < 2 &&
                                           x.fixedIngredientFilter?.AllowedThingDefs != null))
            {
                foreach (var rUser in rec.AllRecipeUsers.Where(y => y is BuildableDef))
                {
                    IEnumerable <WorkGiverDef> gListSel = gList.Where(x => x.fixedBillGiverDefs?.Contains(rUser) == true &&
                                                                      (x.giverClass == typeof(WorkGiver_DoBill) || x.giverClass.IsSubclassOf(typeof(WorkGiver_DoBill))));

                    if (gListSel == null)
                    {
                        continue;
                    }

                    WorkGiverDef wGiverDef = gListSel.FirstOrDefault();

                    if (wGiverDef == null)
                    {
                        continue;
                    }

                    DesignationDef dDef = DefDatabase <DesignationDef> .AllDefsListForReading.FirstOrDefault(x => x.defName == rec.defName + "Designation");

                    if (dDef == null)
                    {
                        dDef = new DesignationDef()
                        {
                            defName    = rec.defName + "Designation",
                            iconMat    = MaterialPool.MatFrom("Designations/General", ShaderDatabase.MetaOverlay),
                            targetType = TargetType.Thing
                        };

                        DefDatabase <DesignationDef> .Add(dDef);
                    }

                    foreach (var def in rec.fixedIngredientFilter.AllowedThingDefs)
                    {
                        if (def.comps != null)
                        {
                            def.comps.Add(new CompProperties_ApplicableDesignation()
                            {
                                designationDef = dDef
                            });
                        }
                    }

                    string wgname = $"{wGiverDef.defName}_{rec.defName}_DesignationWorkGiver";

                    WorkGiverDef wgDef = null;
                    gListSel = gList.Where(x => x.defName == wgname);

                    if (gListSel != null)
                    {
                        wgDef = gListSel.FirstOrDefault();
                    }

                    if (wgDef == null && wGiverDef.workType != null && wGiverDef.requiredCapacities != null)
                    {
                        JobDef jDef = JobDefOf.DoBill;

                        if (wGiverDef.giverClass != typeof(WorkGiver_DoBill))
                        {
                            RecipeJobDef rj = DefDatabase <RecipeJobDef> .AllDefsListForReading.FirstOrDefault(x => x.defName == rec.defName);

                            if (rj == null)
                            {
                                rj = DefDatabase <RecipeJobDef> .AllDefsListForReading.FirstOrDefault(x => x.workerClass == rec.workerClass);
                            }

                            if (rj == null)
                            {
                                Log.Message($"Couldn't find a proper RecipeJobDef for redefined DoBill task {wGiverDef.defName}");
                                continue;
                            }

                            jDef = DefDatabase <JobDef> .AllDefsListForReading.FirstOrDefault(x => x.defName == rj.jobName);

                            if (jDef == null)
                            {
                                Log.Message($"Couldn't find a JobDef({rj.jobName}) for RecipeJobDef({rj.defName})");
                                continue;
                            }
                        }
                        wgDef = new MicroWorkGiverDef()
                        {
                            workGiverDef       = wGiverDef,
                            recipeDef          = rec,
                            designationDef     = dDef,
                            defName            = wgname,
                            label              = wGiverDef.label,
                            giverClass         = typeof(WorkGiver_MicroRecipe),
                            jobDef             = jDef,
                            workType           = wGiverDef.workType,
                            priorityInType     = wGiverDef.priorityInType - 5,
                            verb               = wGiverDef.verb,
                            gerund             = wGiverDef.verb,
                            requiredCapacities = new List <PawnCapacityDef>(wGiverDef.requiredCapacities),
                            prioritizeSustains = wGiverDef.prioritizeSustains
                        };
                        DefDatabase <WorkGiverDef> .Add(wgDef);

                        wgDef.workType.workGiversByPriority.Add(wgDef);
                    }
                }
            }
        }
        public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
        {
            MicroWorkGiverDef mdef = def as MicroWorkGiverDef;

            if (mdef == null)
            {
                return(null);
            }

            LocalTargetInfo target = t;

            if (!pawn.CanReserve(target, 1, -1, null, forced) || t.IsBurning() || t.IsForbidden(pawn))
            {
                return(null);
            }

            List <Building> list = new List <Building>();

            foreach (var user in mdef.recipeDef.AllRecipeUsers)
            {
                List <Building> buildings = t.Map.listerBuildings.AllBuildingsColonistOfDef(user).Where(
                    x => !x.IsForbidden(pawn) && pawn.CanReserve(x, 1, -1, null, forced) &&
                    (x as IBillGiver) != null && (x as IBillGiver).CurrentlyUsableForBills() &&
                    pawn.CanReach(x, PathEndMode.InteractionCell, Danger.Deadly)).ToList();
                list.AddRange(buildings);
            }

            if (list.NullOrEmpty())
            {
                return(null);
            }
            //
            list.SortBy(x => x.TryGetComp <CompRefuelable>() == null || x.TryGetComp <CompRefuelable>().HasFuel ? 0f : 99999f + x.Position.DistanceTo(t.Position));

            Thing building = null;

            foreach (var l in list)
            {
                CompRefuelable compRefuelable = l.TryGetComp <CompRefuelable>();
                if (compRefuelable != null && !compRefuelable.HasFuel)
                {
                    if (RefuelWorkGiverUtility.CanRefuel(pawn, l, forced))
                    {
                        return(RefuelWorkGiverUtility.RefuelJob(pawn, l, forced, null, null));
                    }
                }
                else
                {
                    building = l;
                    break;
                }
            }

            Job job = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, building as IBillGiver, null);

            if (job != null)
            {
                return(job);
            }

            job = new Job(mdef.jobDef, building);
            job.targetQueueB = new List <LocalTargetInfo>(1);
            job.countQueue   = new List <int>(1);
            job.targetQueueB.Add(t);
            job.countQueue.Add(1);
            job.haulMode = HaulMode.ToCellNonStorage;
            Bill            bill = mdef.recipeDef.MakeNewBill();
            Bill_Production bp   = bill as Bill_Production;

            if (bp != null)
            {
                bp.repeatCount++;
                bp.SetStoreMode(BillStoreModeDefOf.DropOnFloor);
            }

            job.bill = bill;

            return(job);
        }
            static void Postfix()
            {
                List <RecipeDef>    list  = DefDatabase <RecipeDef> .AllDefsListForReading;
                List <WorkGiverDef> gList = DefDatabase <WorkGiverDef> .AllDefsListForReading;

                foreach (var rec in list.Where(x => x.AllRecipeUsers.FirstOrDefault(y => y is BuildableDef) != null && x.ingredients.Count() == 1 && x.ingredients[0].filter.AnyAllowedDef.stackLimit < 2))
                {
                    foreach (var rUser in rec.AllRecipeUsers.Where(y => y is BuildableDef))
                    {
                        WorkGiverDef wGiverDef = gList.Where(x => !x.fixedBillGiverDefs.NullOrEmpty() &&
                                                             x.fixedBillGiverDefs.Contains(rUser) &&
                                                             (x.giverClass == typeof(WorkGiver_DoBill) /* || x.giverClass.IsSubclassOf(typeof(WorkGiver_DoBill))*/)).FirstOrDefault();

                        if (wGiverDef == null)
                        {
                            continue;
                        }

                        DesignationDef dDef = DefDatabase <DesignationDef> .AllDefsListForReading.FirstOrDefault(x => x.defName == rec.defName + "Designation");

                        if (dDef == null)
                        {
                            dDef = new DesignationDef()
                            {
                                defName     = rec.defName + "Designation",
                                texturePath = "Designations/Uninstall",
                                iconMat     = MaterialPool.MatFrom("Designations/Uninstall", ShaderDatabase.MetaOverlay),
                                targetType  = TargetType.Thing
                            };
                            DefDatabase <DesignationDef> .Add(dDef);
                        }
                        //Log.Message($"rDef={rec},bDef={rUser},dDef={dDef}");

                        foreach (var def in rec.fixedIngredientFilter.AllowedThingDefs)
                        {
                            def.comps.Add(new CompProperties_ApplicableDesignation()
                            {
                                designationDef = dDef
                            });
                        }

                        string       wgname = $"{wGiverDef.defName}_{rec.defName}_DesignationWorkGiver";
                        WorkGiverDef wgDef  = gList.Where(x => x.defName == wgname).FirstOrDefault();
                        if (wgDef == null)
                        {
                            wgDef = new MicroWorkGiverDef()
                            {
                                recipeDef          = rec,
                                designationDef     = dDef,
                                defName            = wgname,
                                label              = wGiverDef.label,
                                giverClass         = typeof(WorkGiver_MicroRecipe),
                                workType           = wGiverDef.workType,
                                priorityInType     = wGiverDef.priorityInType - 5,
                                verb               = wGiverDef.verb,
                                gerund             = wGiverDef.verb,//wGiverDef.gerund,
                                requiredCapacities = new List <PawnCapacityDef>(wGiverDef.requiredCapacities),
                                prioritizeSustains = wGiverDef.prioritizeSustains
                            };
                            DefDatabase <WorkGiverDef> .Add(wgDef);

                            wgDef.workType.workGiversByPriority.Add(wgDef);
                        }
                    }
                }
            }