Esempio n. 1
0
        public static Thing RegionwiseBFSWorker(IntVec3 root, Map map, ThingRequest req, PathEndMode peMode, TraverseParms traverseParams, Predicate <Thing> validator, Func <Thing, float> priorityGetter, int minRegions, int maxRegions, float maxDistance, RegionType traversableRegionTypes = RegionType.Set_Passable, bool ignoreEntirelyForbiddenRegions = false)
        {
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                Log.Error("RegionwiseBFSWorker with traverseParams.mode PassAllDestroyableThings. Use ClosestThingGlobal.");
                return(null);
            }
            Region region = root.GetRegion(map, traversableRegionTypes);

            if (region == null)
            {
                return(null);
            }
            float maxDistSquared = maxDistance * maxDistance;
            RegionEntryPredicate entryCondition = (Region from, Region to) => to.Allows(traverseParams, false) && (maxDistance > 5000f || to.extentsClose.ClosestDistSquaredTo(root) < maxDistSquared);
            Thing           closestThing        = null;
            float           closestDistSquared  = 9999999f;
            float           bestPrio            = -3.40282347E+38f;
            int             regionsSeen         = 0;
            RegionProcessor regionProcessor     = delegate(Region r)
            {
                if (r.portal == null && !r.Allows(traverseParams, true))
                {
                    return(false);
                }
                if (!ignoreEntirelyForbiddenRegions || !r.IsForbiddenEntirely(traverseParams.pawn))
                {
                    List <Thing> list = r.ListerThings.ThingsMatching(req);
                    for (int i = 0; i < list.Count; i++)
                    {
                        Thing thing = list[i];
                        if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, peMode, traverseParams.pawn))
                        {
                            float num = (priorityGetter == null) ? 0f : priorityGetter(thing);
                            if (num >= bestPrio)
                            {
                                float num2 = (float)(thing.Position - root).LengthHorizontalSquared;
                                if ((num > bestPrio || num2 < closestDistSquared) && num2 < maxDistSquared && (validator == null || validator(thing)))
                                {
                                    closestThing       = thing;
                                    closestDistSquared = num2;
                                    bestPrio           = num;
                                }
                            }
                        }
                    }
                }
                regionsSeen++;
                return(regionsSeen >= minRegions && closestThing != null);
            };

            RegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, maxRegions, traversableRegionTypes);
            return(closestThing);
        }
Esempio n. 2
0
        public static Thing RegionwiseBFSWorker(IntVec3 root, Map map, ThingRequest req, PathEndMode peMode, TraverseParms traverseParams, Predicate <Thing> validator, Func <Thing, float> priorityGetter, int minRegions, int maxRegions, float maxDistance, out int regionsSeen, RegionType traversableRegionTypes = RegionType.Set_Passable, bool ignoreEntirelyForbiddenRegions = false)
        {
            regionsSeen = 0;
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                Log.Error("RegionwiseBFSWorker with traverseParams.mode PassAllDestroyableThings. Use ClosestThingGlobal.");
                return(null);
            }
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater)
            {
                Log.Error("RegionwiseBFSWorker with traverseParams.mode PassAllDestroyableThingsNotWater. Use ClosestThingGlobal.");
                return(null);
            }
            if (!req.IsUndefined && !req.CanBeFoundInRegion)
            {
                Log.ErrorOnce(string.Concat("RegionwiseBFSWorker with thing request group ", req.group, ". This group is never stored in regions. Most likely a global search should have been used."), 385766189);
                return(null);
            }
            Region region = root.GetRegion(map, traversableRegionTypes);

            if (region == null)
            {
                return(null);
            }
            float maxDistSquared = maxDistance * maxDistance;
            RegionEntryPredicate entryCondition = delegate(Region from, Region to)
            {
                if (!to.Allows(traverseParams, isDestination: false))
                {
                    return(false);
                }
                return(maxDistance > 5000f || to.extentsClose.ClosestDistSquaredTo(root) < maxDistSquared);
            };
            Thing           closestThing       = null;
            float           closestDistSquared = 9999999f;
            float           bestPrio           = float.MinValue;
            int             regionsSeenScan    = 0;
            RegionProcessor regionProcessor    = delegate(Region r)
            {
                if (RegionTraverser.ShouldCountRegion(r))
                {
                    regionsSeenScan++;
                }
                if (!r.IsDoorway && !r.Allows(traverseParams, isDestination: true))
                {
                    return(false);
                }
                if (!ignoreEntirelyForbiddenRegions || !r.IsForbiddenEntirely(traverseParams.pawn))
                {
                    List <Thing> list = r.ListerThings.ThingsMatching(req);
                    for (int i = 0; i < list.Count; i++)
                    {
                        Thing thing = list[i];
                        if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, peMode, traverseParams.pawn))
                        {
                            float num = ((priorityGetter != null) ? priorityGetter(thing) : 0f);
                            if (!(num < bestPrio))
                            {
                                float num2 = (thing.Position - root).LengthHorizontalSquared;
                                if ((num > bestPrio || num2 < closestDistSquared) && num2 < maxDistSquared && (validator == null || validator(thing)))
                                {
                                    closestThing       = thing;
                                    closestDistSquared = num2;
                                    bestPrio           = num;
                                }
                            }
                        }
                    }
                }
                return(regionsSeenScan >= minRegions && closestThing != null);
            };

            RegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, maxRegions, traversableRegionTypes);
            regionsSeen = regionsSeenScan;
            return(closestThing);
        }