public static void BreadthFirstTraverse(VehicleRegion root, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions = 999999, RegionType traversableRegionTypes = RegionType.Set_Passable) { if (freeWorkers.Count == 0) { Log.Error("No free workers for BFS. Either BFS recurred deeper than " + NumWorkers + ", or a bug has put this system in an inconsistent state. Resetting."); return; } if (root is null) { Log.Error("BFS with null root region."); return; } BFSWorker bfsworker = freeWorkers.Dequeue(); try { bfsworker.BreadthFirstTraverseWork(root, entryCondition, regionProcessor, maxRegions, traversableRegionTypes); } catch (Exception ex) { Log.Error("Exception in BreadthFirstTraverse: " + ex.ToString()); } finally { bfsworker.Clear(); freeWorkers.Enqueue(bfsworker); } }
//FloodAndSetRooms //FloodAndSetNewRegionIndex public static bool WithinRegions(this IntVec3 A, IntVec3 B, Map map, int regionLookCount, TraverseParms traverseParams, RegionType traversableRegionTypes = RegionType.Set_Passable) { VehicleRegion region = VehicleGridsUtility.GetRegion(A, map, traversableRegionTypes); if (region is null) { return(false); } VehicleRegion regB = VehicleGridsUtility.GetRegion(B, map, traversableRegionTypes); if (regB is null) { return(false); } if (region == regB) { return(true); } bool entryCondition(VehicleRegion from, VehicleRegion r) => r.Allows(traverseParams, false); bool found = false; bool regionProcessor(VehicleRegion r) { if (r == regB) { found = true; return(true); } return(false); } BreadthFirstTraverse(region, entryCondition, regionProcessor, regionLookCount, traversableRegionTypes); return(found); }
internal void Notify_WalkabilityChanged(IntVec3 c) { regionsToDirty.Clear(); for (int i = 0; i < 9; i++) { IntVec3 c2 = c + GenAdj.AdjacentCellsAndInside[i]; if (c2.InBounds(map)) { VehicleRegion regionAt_NoRebuild_InvalidAllowed = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetRegionAt_NoRebuild_InvalidAllowed(c2); if (regionAt_NoRebuild_InvalidAllowed != null && regionAt_NoRebuild_InvalidAllowed.valid) { regionsToDirty.Add(regionAt_NoRebuild_InvalidAllowed); } } } for (int j = 0; j < regionsToDirty.Count; j++) { SetRegionDirty(regionsToDirty[j], true); } regionsToDirty.Clear(); if (c.Walkable(map) && !dirtyCells.Contains(c)) { dirtyCells.Add(c); } }
private void SetRegionDirty(VehicleRegion reg, bool addCellsToDirtyCells = true) { if (!reg.valid) { return; } reg.valid = false; reg.Room = null; for (int i = 0; i < reg.links.Count; i++) { reg.links[i].Deregister(reg); } reg.links.Clear(); if (addCellsToDirtyCells) { foreach (IntVec3 intVec in reg.Cells) { dirtyCells.Add(intVec); if (DebugViewSettings.drawRegionDirties) { map.debugDrawer.FlashCell(intVec, 0f, null, 50); } } } }
public VehicleRegion TryGenerateRegionFrom(IntVec3 root) { RegionType expectedRegionType = WaterRegionTypeUtility.GetExpectedRegionType(root, this.map); if (expectedRegionType == RegionType.None) { return(null); } if (working) { Log.Error("Trying to generate a new water region but we are currently generating one. Nested calls are not allowed."); return(null); } working = true; VehicleRegion result; try { regionGrid = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid; newReg = VehicleRegion.MakeNewUnfilled(root, map); newReg.type = expectedRegionType; //Add portal type? FloodFillAndAddCells(root); CreateLinks(); RegisterThingsInRegionListers(); result = newReg; } finally { working = false; } return(result); }
public static VehicleRoom FloodAndSetRooms(VehicleRegion root, Map map, VehicleRoom existingRoom) { VehicleRoom floodingRoom; if (existingRoom == null) { floodingRoom = VehicleRoom.MakeNew(map); } else { floodingRoom = existingRoom; } root.Room = floodingRoom; if (!root.type.AllowsMultipleRegionsPerRoom()) { return(floodingRoom); } bool entryCondition(VehicleRegion from, VehicleRegion r) => r.type == root.type && r.Room != floodingRoom; bool regionProcessor(VehicleRegion r) { r.Room = floodingRoom; return(false); } BreadthFirstTraverse(root, entryCondition, regionProcessor, 999999, RegionType.Set_All); return(floodingRoom); }
public static void GetTouchableRegions(Thing thing, Map map, List <VehicleRegion> outRegions, bool allowAdjacenttEvenIfCantTouch = false) { outRegions.Clear(); CellRect cellRect = thing.OccupiedRect(); CellRect cellRect2 = cellRect; if (CanRegisterInAdjacentRegions(thing)) { cellRect2 = cellRect2.ExpandedBy(1); } foreach (IntVec3 intVec in cellRect2) { if (intVec.InBoundsShip(map)) { VehicleRegion validRegionAt_NoRebuild = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetValidRegionAt_NoRebuild(intVec); if (!(validRegionAt_NoRebuild is null) && validRegionAt_NoRebuild.type.Passable() && !outRegions.Contains(validRegionAt_NoRebuild)) { if (cellRect.Contains(intVec)) { outRegions.Add(validRegionAt_NoRebuild); } else if (allowAdjacenttEvenIfCantTouch || VehicleReachabilityImmediate.CanReachImmediateShip(intVec, thing, map, PathEndMode.Touch, null)) { outRegions.Add(validRegionAt_NoRebuild); } } } } }
public static void MarkRegionsBFS(VehicleRegion root, WaterRegionEntryPredicate entryCondition, int maxRegions, int inRadiusMark, RegionType traversableRegionTypes = RegionType.Set_Passable) { BreadthFirstTraverse(root, entryCondition, delegate(VehicleRegion r) { r.mark = inRadiusMark; return(false); }, maxRegions, traversableRegionTypes); }
public bool Allows(TraverseParms tp, bool isDestination) { if (tp.mode != TraverseMode.PassAllDestroyableThings && tp.mode != TraverseMode.PassAllDestroyableThingsNotWater && !type.Passable()) { return(false); } if (tp.maxDanger < Danger.Deadly && tp.pawn != null) { Danger danger = DangerFor(tp.pawn); if (isDestination || danger == Danger.Deadly) { VehicleRegion region = VehicleRegionAndRoomQuery.GetRegion(tp.pawn, RegionType.Set_All); if ((region == null || danger > region.DangerFor(tp.pawn)) && danger > tp.maxDanger) { return(false); } } } switch (tp.mode) { case TraverseMode.ByPawn: { if (door == null) { return(true); } ByteGrid avoidGrid = tp.pawn.GetAvoidGrid(true); if (avoidGrid != null && avoidGrid[door.Position] == 255) { return(false); } if (tp.pawn.HostileTo(door)) { return(door.CanPhysicallyPass(tp.pawn) || tp.canBash); } return(door.CanPhysicallyPass(tp.pawn) && !door.IsForbiddenToPass(tp.pawn)); } case TraverseMode.PassDoors: return(true); case TraverseMode.NoPassClosedDoors: return(door == null || door.FreePassage); case TraverseMode.PassAllDestroyableThings: return(true); case TraverseMode.NoPassClosedDoorsOrWater: return(door == null || door.FreePassage); case TraverseMode.PassAllDestroyableThingsNotWater: return(true); default: throw new NotImplementedException(); } }
private void QueueNewOpenRegion(VehicleRegion region) { if (region.closedIndex[closedArrayPos] == closedIndex) { throw new InvalidOperationException("Region is already closed; you can't open it. Region: " + region.ToString()); } open.Enqueue(region); region.closedIndex[closedArrayPos] = closedIndex; }
public static VehicleRegion RegionAt(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { if (!c.InBoundsShip(map)) { return(null); } VehicleRegion validRegionAt = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetValidRegionAt(c); return(!(validRegionAt is null) && (validRegionAt.type & allowedRegionTypes) != RegionType.None ? validRegionAt : null); }
//GetRoomGroup public static VehicleRoom RoomAtFast(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { VehicleRegion validRegionAt = map.GetCachedMapComponent <VehicleMapping>()?.VehicleRegionGrid?.GetValidRegionAt(c); if (!(validRegionAt is null) && (validRegionAt.type & allowedRegionTypes) != RegionType.None) { return(validRegionAt.Room); } return(null); }
public static void BreadthFirstTraverse(IntVec3 start, Map map, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions = 999999, RegionType traversableRegionTypes = RegionType.Set_Passable) { VehicleRegion region = VehicleGridsUtility.GetRegion(start, map, traversableRegionTypes); if (region is null) { return; } BreadthFirstTraverse(region, entryCondition, regionProcessor, maxRegions, traversableRegionTypes); }
public VehicleRegion GetValidRegionAt_NoRebuild(IntVec3 c) { if (!c.InBoundsShip(map)) { Log.Error("Tried to get valid region out of bounds at " + c); } VehicleRegion region = regionGrid[map.cellIndices.CellToIndex(c)]; return(!(region is null) && region.valid ? region : null); }
public VehicleRegion GetValidRegionAt(IntVec3 c) { if (!c.InBoundsShip(map)) { Log.Error("Tried to get valid water region out of bounds at " + c); } if (!map.GetCachedMapComponent <VehicleMapping>().VehicleRegionAndRoomUpdater.Enabled&& map.GetCachedMapComponent <VehicleMapping>().VehicleRegionAndRoomUpdater.AnythingToRebuild) { Log.Warning("Trying to get valid water region at " + c + " but RegionAndRoomUpdater is disabled. The result may be incorrect."); } map.GetCachedMapComponent <VehicleMapping>().VehicleRegionAndRoomUpdater.TryRebuildWaterRegions(); VehicleRegion region = regionGrid[map.cellIndices.CellToIndex(c)]; return(!(region is null) && region.valid ? region : null); }
public void Register(VehicleRegion reg) { if (regions[0] == reg || regions[1] == reg) { Log.Error(string.Concat(new object[] { "Tried to double-register water region ", reg.ToString(), " in ", this })); return; } if (RegionA is null || !RegionA.valid) { RegionA = reg; }
public void UpdateClean() { for (int i = 0; i < CleanSquaresPerFrame; i++) { if (curCleanIndex >= regionGrid.Length) { curCleanIndex = 0; } VehicleRegion region = regionGrid[curCleanIndex]; if (!(region is null) && !region.valid) { regionGrid[curCleanIndex] = null; } curCleanIndex++; } }
public void BreadthFirstTraverseWork(VehicleRegion root, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions, RegionType traversableRegionTypes) { if ((root.type & traversableRegionTypes) == RegionType.None) { return; } closedIndex += 1u; open.Clear(); numRegionsProcessed = 0; QueueNewOpenRegion(root); while (open.Count > 0) { VehicleRegion region = open.Dequeue(); if (VehicleHarmony.debug) { region.Debug_Notify_Traversed(); } if (!(regionProcessor is null) && regionProcessor(region)) { FinalizeSearch(); return; } if (ShouldCountRegion(region)) { numRegionsProcessed++; } if (numRegionsProcessed >= maxRegions) { FinalizeSearch(); return; } for (int i = 0; i < region.links.Count; i++) { VehicleRegionLink regionLink = region.links[i]; for (int j = 0; j < 2; j++) { VehicleRegion region2 = regionLink.regions[j]; if (!(region2 is null) && region2.closedIndex[closedArrayPos] != closedIndex && (region2.type & traversableRegionTypes) != RegionType.None && (entryCondition is null || entryCondition(region, region2))) { QueueNewOpenRegion(region2); } } } } FinalizeSearch(); }
internal void Notify_ThingAffectingRegionsSpawned(Thing b) { regionsToDirty.Clear(); foreach (IntVec3 c in b.OccupiedRect().ExpandedBy(1).ClipInsideMap(b.Map)) { VehicleRegion validRegionAt_NoRebuild = b.Map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetValidRegionAt_NoRebuild(c); if (validRegionAt_NoRebuild != null) { regionsToDirty.Add(validRegionAt_NoRebuild); } } for (int i = 0; i < regionsToDirty.Count; i++) { SetRegionDirty(regionsToDirty[i], true); } regionsToDirty.Clear(); }
public static void FloodAndSetNewRegionIndex(VehicleRegion root, int newRegionGroupIndex) { root.newRegionGroupIndex = newRegionGroupIndex; if (!root.type.AllowsMultipleRegionsPerRoom()) { return; } bool entryCondition(VehicleRegion from, VehicleRegion r) => r.type == root.type && r.newRegionGroupIndex < 0; bool regionProcessor(VehicleRegion r) { r.newRegionGroupIndex = newRegionGroupIndex; return(false); } BreadthFirstTraverse(root, entryCondition, regionProcessor, 999999, RegionType.Set_All); }
private void RegenerateNewWaterRegions() { newRegions.Clear(); List <IntVec3> cells = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionDirtyer.DirtyCells; foreach (IntVec3 c in cells) { if (VehicleGridsUtility.GetRegion(c, map, RegionType.Set_All) is null) { VehicleRegion region = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionMaker.TryGenerateRegionFrom(c); if (!(region is null)) { newRegions.Add(region); } } } }
public void TryRegenerateRegionFrom(VehicleRegion region, IntVec3 root) { if (working) { Log.Error("Trying to regenerate a current water region but we are currently generating one. Nested calls are not allowed."); return; } working = true; try { FloodFillAndAddCells(root); CreateLinks(); RegisterThingsInRegionListers(); } finally { working = false; } }
public static VehicleRegion MakeNewUnfilled(IntVec3 root, Map map) { VehicleRegion region = new VehicleRegion(); region.debug_makeTick = Find.TickManager.TicksGame; region.id = nextId; nextId++; region.mapIndex = (sbyte)map.Index; region.precalculatedHashCode = Gen.HashCombineInt(region.id, 1295813358); region.extentsClose.minX = root.x; region.extentsClose.maxX = root.x; region.extentsClose.minZ = root.z; region.extentsClose.maxZ = root.z; region.extentsLimit.minX = root.x - root.x % GridSize; region.extentsLimit.maxX = root.x + GridSize - (root.x + GridSize) % GridSize - 1; region.extentsLimit.minZ = root.z - root.z % GridSize; region.extentsLimit.maxZ = root.z + GridSize - (root.z + GridSize) % GridSize - 1; region.extentsLimit.ClipInsideMap(map); return(region); }
internal void Notify_ThingAffectingRegionsDespawned(Thing b) { regionsToDirty.Clear(); VehicleRegion validRegionAt_NoRebuild = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetValidRegionAt_NoRebuild(b.Position); if (validRegionAt_NoRebuild != null) { regionsToDirty.Add(validRegionAt_NoRebuild); } foreach (IntVec3 c in GenAdj.CellsAdjacent8Way(b)) { if (c.InBounds(map)) { VehicleRegion validRegionAt_NoRebuild2 = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.GetValidRegionAt_NoRebuild(c); if (validRegionAt_NoRebuild2 != null) { regionsToDirty.Add(validRegionAt_NoRebuild2); } } } for (int i = 0; i < regionsToDirty.Count; i++) { SetRegionDirty(regionsToDirty[i], true); } regionsToDirty.Clear(); if (b.def.size.x == 1 && b.def.size.z == 1) { dirtyCells.Add(b.Position); return; } CellRect cellRect = b.OccupiedRect(); for (int j = cellRect.minZ; j <= cellRect.maxZ; j++) { for (int k = cellRect.minX; k <= cellRect.maxX; k++) { IntVec3 item = new IntVec3(k, 0, j); dirtyCells.Add(item); } } }
public static bool TryFindRandomReachableCellNear(IntVec3 root, Map map, float radius, TraverseParms traverseParms, Predicate <IntVec3> validator, Predicate <VehicleRegion> regionValidator, out IntVec3 result, int maxRegions = 999999) { if (map is null) { Log.ErrorOnce("Tried to find reachable cell using SPExtended in a null map", 61037855); result = IntVec3.Invalid; return(false); } VehicleRegion region = VehicleGridsUtility.GetRegion(root, map, RegionType.Set_Passable); if (region is null) { result = IntVec3.Invalid; return(false); } Rot4 dir = Find.World.CoastDirectionAt(map.Tile).IsValid ? Find.World.CoastDirectionAt(map.Tile) : !Find.WorldGrid[map.Tile].Rivers.NullOrEmpty() ? Ext_Map.RiverDirection(map) : Rot4.Invalid; result = RandomEdgeCell(dir, map, (IntVec3 c) => GenGridVehicles.Standable(c, map) && !c.Fogged(map), 0); return(true); }
public void AddRegion(VehicleRegion region) { if (Regions.Contains(region)) { Log.Error(string.Concat(new object[] { "Tried to add the same region twice to Room. region=", region, ", room=", this })); return; } Regions.Add(region); if (region.touchesMapEdge) { numRegionsTouchingMapEdge++; } if (Regions.Count == 1) { Map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.allRooms.Add(this); } }
public void RemoveRegion(VehicleRegion r) { if (!Regions.Contains(r)) { Log.Error(string.Concat(new object[] { "Tried to remove region from Room but this region is not here. region=", r, ", room=", this })); return; } Regions.Remove(r); if (r.touchesMapEdge) { numRegionsTouchingMapEdge--; } if (Regions.Count == 0) { Map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.allRooms.Remove(this); } }
public void DebugDraw() { if (map != Find.CurrentMap) { return; } //Region Traversal if (VehicleHarmony.debug) { CellRect currentViewRect = Find.CameraDriver.CurrentViewRect; currentViewRect.ClipInsideMap(map); foreach (IntVec3 c in currentViewRect) { VehicleRegion validRegionAt = GetValidRegionAt(c); if (!(validRegionAt is null) && !drawnRegions.Contains(validRegionAt)) { validRegionAt.DebugDraw(); drawnRegions.Add(validRegionAt); } } drawnRegions.Clear(); } IntVec3 intVec = Verse.UI.MouseCell(); if (intVec.InBoundsShip(map)) { //Room? //Room Group? VehicleRegion regionAt_NoRebuild_InvalidAllowed = GetRegionAt_NoRebuild_InvalidAllowed(intVec); if (!(regionAt_NoRebuild_InvalidAllowed is null)) { regionAt_NoRebuild_InvalidAllowed.DebugDrawMouseover(); } } }
public static bool TryFindRandomCellInWaterRegion(this VehicleRegion reg, Predicate <IntVec3> validator, out IntVec3 result) { for (int i = 0; i < 10; i++) { result = reg.RandomCell; if (validator is null || validator(result)) { return(true); } } List <IntVec3> workingCells = new List <IntVec3>(reg.Cells); workingCells.Shuffle <IntVec3>(); foreach (IntVec3 c in workingCells) { result = c; if (validator is null || validator(result)) { return(true); } } result = reg.RandomCell; return(false); }
public static bool ShouldCountRegion(VehicleRegion r) { return(!r.IsDoorway); }