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); }
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); }