public static void GetTouchableRegions(Thing thing, Map map, List <WaterRegion> outRegions, bool allowAdjacenttEvenIfCantTouch = false) { outRegions.Clear(); CellRect cellRect = thing.OccupiedRect(); CellRect cellRect2 = cellRect; if (WaterRegionListersUpdater.CanRegisterInAdjacentRegions(thing)) { cellRect2 = cellRect2.ExpandedBy(1); } CellRect.CellRectIterator iterator = cellRect2.GetIterator(); while (!iterator.Done()) { IntVec3 intVec = iterator.Current; if (intVec.InBoundsShip(map)) { WaterRegion validRegionAt_NoRebuild = MapExtensionUtility.GetExtensionToMap(map).getWaterRegionGrid.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 || ShipReachabilityImmediate.CanReachImmediateShip(intVec, thing, map, PathEndMode.Touch, null)) { outRegions.Add(validRegionAt_NoRebuild); } } } iterator.MoveNext(); } }
public void RemoveRegion(WaterRegion r) { if (!this.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 }), false); return; } this.regions.Remove(r); if (r.touchesMapEdge) { this.numRegionsTouchingMapEdge--; } if (this.regions.Count == 0) { //this.Group = null; /*this.cachedOpenRoofCount = -1; * this.cachedOpenRoofState = null; * this.statsAndRoleDirty = true;*/ MapExtensionUtility.GetExtensionToMap(this.Map).getWaterRegionGrid.allRooms.Remove(this); } }
//FloodAndSetRooms //FloodAndSetNewRegionIndex public static bool WithinRegions(this IntVec3 A, IntVec3 B, Map map, int regionLookCount, TraverseParms traverseParams, RegionType traversableRegionTypes = RegionType.Set_Passable) { WaterRegion region = WaterGridsUtility.GetRegion(A, map, traversableRegionTypes); if (region is null) { return(false); } WaterRegion regB = WaterGridsUtility.GetRegion(B, map, traversableRegionTypes); if (regB is null) { return(false); } if (region == regB) { return(true); } WaterRegionEntryPredicate entryCondition = (WaterRegion from, WaterRegion r) => r.Allows(traverseParams, false); bool found = false; WaterRegionProcessor regionProcessor = delegate(WaterRegion r) { if (r == regB) { found = true; return(true); } return(false); }; WaterRegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, regionLookCount, traversableRegionTypes); return(found); }
public WaterRegion TryGenerateRegionFrom(IntVec3 root) { RegionType expectedRegionType = WaterRegionTypeUtility.GetExpectedRegionType(root, this.map); if (expectedRegionType == RegionType.None) { return(null); } if (this.working) { Log.Error("Trying to generate a new water region but we are currently generating one. Nested calls are not allowed.", false); return(null); } this.working = true; WaterRegion result; try { this.regionGrid = MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionGrid; this.newReg = WaterRegion.MakeNewUnfilled(root, this.map); this.newReg.type = expectedRegionType; //Portal type? this.FloodFillAndAddCells(root); this.CreateLinks(); this.RegisterThingsInRegionListers(); result = this.newReg; } finally { this.working = false; } return(result); }
public static void BreadthFirstTraverse(WaterRegion root, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions = 999999, RegionType traversableRegionTypes = RegionType.Set_Passable) { if (WaterRegionTraverser.freeWorkers.Count == 0) { Log.Error("No free workers for BFS. Either BFS recurred deeper than " + WaterRegionTraverser.NumWorkers + ", or a bug has put this system in an inconsistent state. Resetting.", false); return; } if (root is null) { Log.Error("BFS with null root region.", false); return; } WaterRegionTraverser.BFSWorker bfsworker = WaterRegionTraverser.freeWorkers.Dequeue(); try { bfsworker.BreadthFirstTraverseWork(root, entryCondition, regionProcessor, maxRegions, traversableRegionTypes); } catch (Exception ex) { Log.Error("Exception in BreadthFirstTraverse: " + ex.ToString(), false); } finally { bfsworker.Clear(); WaterRegionTraverser.freeWorkers.Enqueue(bfsworker); } }
public static void MarkRegionsBFS(WaterRegion root, WaterRegionEntryPredicate entryCondition, int maxRegions, int inRadiusMark, RegionType traversableRegionTypes = RegionType.Set_Passable) { WaterRegionTraverser.BreadthFirstTraverse(root, entryCondition, delegate(WaterRegion r) { r.mark = inRadiusMark; return(false); }, maxRegions, traversableRegionTypes); }
private void QueueNewOpenRegion(WaterRegion region) { if (region.closedIndex[this.closedArrayPos] == this.closedIndex) { throw new InvalidOperationException("Region is already closed; you can't open it. Region: " + region.ToString()); } this.open.Enqueue(region); region.closedIndex[this.closedArrayPos] = this.closedIndex; }
public bool Allows(TraverseParms tp, bool isDestination) { if (tp.mode != TraverseMode.PassAllDestroyableThings && tp.mode != TraverseMode.PassAllDestroyableThingsNotWater && !this.type.Passable()) { return(false); } if (tp.maxDanger < Danger.Deadly && tp.pawn != null) { Danger danger = this.DangerFor(tp.pawn); if (isDestination || danger == Danger.Deadly) { WaterRegion region = WaterRegionAndRoomQuery.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 (this.door == null) { return(true); } ByteGrid avoidGrid = tp.pawn.GetAvoidGrid(true); if (avoidGrid != null && avoidGrid[this.door.Position] == 255) { return(false); } if (tp.pawn.HostileTo(this.door)) { return(this.door.CanPhysicallyPass(tp.pawn) || tp.canBash); } return(this.door.CanPhysicallyPass(tp.pawn) && !this.door.IsForbiddenToPass(tp.pawn)); } case TraverseMode.PassDoors: return(true); case TraverseMode.NoPassClosedDoors: return(this.door == null || this.door.FreePassage); case TraverseMode.PassAllDestroyableThings: return(true); case TraverseMode.NoPassClosedDoorsOrWater: return(this.door == null || this.door.FreePassage); case TraverseMode.PassAllDestroyableThingsNotWater: return(true); default: throw new NotImplementedException(); } }
public static WaterRegion RegionAt(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { if (!c.InBoundsShip(map)) { return(null); } WaterRegion validRegionAt = MapExtensionUtility.GetExtensionToMap(map).getWaterRegionGrid.GetValidRegionAt(c); return(!(validRegionAt is null) && (validRegionAt.type & allowedRegionTypes) != RegionType.None ? validRegionAt : null); }
//GetRoomGroup public static WaterRoom RoomAtFast(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { WaterRegion validRegionAt = MapExtensionUtility.GetExtensionToMap(map)?.getWaterRegionGrid?.GetValidRegionAt(c); if (!(validRegionAt is null) && (validRegionAt.type & allowedRegionTypes) != RegionType.None) { return(validRegionAt.Room); } return(null); }
public WaterRegion GetValidRegionAt_NoRebuild(IntVec3 c) { if (!c.InBoundsShip(this.map)) { Log.Error("Tried to get valid region out of bounds at " + c, false); } WaterRegion region = this.regionGrid[this.map.cellIndices.CellToIndex(c)]; return(!(region is null) && region.valid ? region : null); }
public static void BreadthFirstTraverse(IntVec3 start, Map map, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions = 999999, RegionType traversableRegionTypes = RegionType.Set_Passable) { WaterRegion region = WaterGridsUtility.GetRegion(start, map, traversableRegionTypes); if (region is null) { return; } WaterRegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, maxRegions, traversableRegionTypes); }
public override bool Equals(object obj) { if (obj is null) { return(false); } WaterRegion region = obj as WaterRegion; return(!(region is null) && region.id == this.id); }
public WaterRegion GetValidRegionAt(IntVec3 c) { if (!c.InBoundsShip(this.map)) { Log.Error("Tried to get valid water region out of bounds at " + c, false); } if (!MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionAndRoomUpdater.Enabled&& MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionAndRoomUpdater.AnythingToRebuild) { Log.Warning("Trying to get valid water region at " + c + " but RegionAndRoomUpdater is disabled. The result may be incorrect.", false); } MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionAndRoomUpdater.TryRebuildWaterRegions(); WaterRegion region = this.regionGrid[this.map.cellIndices.CellToIndex(c)]; return(!(region is null) && region.valid ? region : null); }
public void Register(WaterRegion reg) { if (this.regions[0] == reg || this.regions[1] == reg) { Log.Error(string.Concat(new object[] { "Tried to double-register water region ", reg.ToString(), " in ", this }), false); return; } if (this.RegionA is null || !this.RegionA.valid) { this.RegionA = reg; }
public void UpdateClean() { for (int i = 0; i < 16; i++) { if (this.curCleanIndex >= this.regionGrid.Length) { this.curCleanIndex = 0; } WaterRegion region = this.regionGrid[this.curCleanIndex]; if (!(region is null) && !region.valid) { this.regionGrid[this.curCleanIndex] = null; } this.curCleanIndex++; } }
public void BreadthFirstTraverseWork(WaterRegion root, WaterRegionEntryPredicate entryCondition, WaterRegionProcessor regionProcessor, int maxRegions, RegionType traversableRegionTypes) { if ((root.type & traversableRegionTypes) == RegionType.None) { return; } this.closedIndex += 1u; this.open.Clear(); this.numRegionsProcessed = 0; this.QueueNewOpenRegion(root); while (this.open.Count > 0) { WaterRegion region = this.open.Dequeue(); if (ShipHarmony.debug) { region.Debug_Notify_Traversed(); } if (!(regionProcessor is null) && regionProcessor(region)) { this.FinalizeSearch(); return; } if (WaterRegionTraverser.ShouldCountRegion(region)) { this.numRegionsProcessed++; } if (this.numRegionsProcessed >= maxRegions) { this.FinalizeSearch(); return; } for (int i = 0; i < region.links.Count; i++) { WaterRegionLink regionLink = region.links[i]; for (int j = 0; j < 2; j++) { WaterRegion region2 = regionLink.regions[j]; if (!(region2 is null) && region2.closedIndex[this.closedArrayPos] != this.closedIndex && (region2.type & traversableRegionTypes) != RegionType.None && (entryCondition is null || entryCondition(region, region2))) { this.QueueNewOpenRegion(region2); } } } } this.FinalizeSearch(); }
private void RegenerateNewWaterRegions() { this.newRegions.Clear(); List <IntVec3> cells = this.map.regionDirtyer.DirtyCells; foreach (IntVec3 c in cells) { if (WaterGridsUtility.GetRegion(c, this.map, RegionType.Set_All) is null) { WaterRegion region = MapExtensionUtility.GetExtensionToMap(map).getWaterRegionmaker.TryGenerateRegionFrom(c); if (!(region is null)) { this.newRegions.Add(region); } } } }
public void TryRegenerateRegionFrom(WaterRegion region, IntVec3 root) { if (this.working) { Log.Error("Trying to regenerate a current water region but we are currently generating one. Nested calls are not allowed.", false); return; } this.working = true; try { this.FloodFillAndAddCells(root); this.CreateLinks(); this.RegisterThingsInRegionListers(); } finally { this.working = false; } }
public static bool TryFindRandomReachableCellNear(IntVec3 root, Map map, float radius, TraverseParms traverseParms, Predicate <IntVec3> validator, out IntVec3 result, Predicate <WaterRegion> regionValidator, int maxRegions = 999999) { if (map is null) { Log.ErrorOnce("Tried to find reachable cell using SPExtended in a null map", 61037855, false); result = IntVec3.Invalid; return(false); } WaterRegion region = WaterGridsUtility.GetRegion(root, map, RegionType.Set_Passable); if (region is null) { result = IntVec3.Invalid; return(false); } result = CellFinderExtended.RandomEdgeCell(Find.World.CoastDirectionAt(map.Tile), map, (IntVec3 c) => GenGridShips.Standable(c, map, MapExtensionUtility.GetExtensionToMap(map)) && !c.Fogged(map)); return(true); }
public static WaterRegion MakeNewUnfilled(IntVec3 root, Map map) { WaterRegion region = new WaterRegion(); region.debug_makeTick = Find.TickManager.TicksGame; region.id = WaterRegion.nextId; WaterRegion.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); }
public void AddRegion(WaterRegion r) { if (this.regions.Contains(r)) { Log.Error(string.Concat(new object[] { "Tried to add the same region twice to Room. region=", r, ", room=", this }), false); return; } this.regions.Add(r); if (r.touchesMapEdge) { this.numRegionsTouchingMapEdge++; } if (this.regions.Count == 1) { MapExtensionUtility.GetExtensionToMap(this.Map).getWaterRegionGrid.allRooms.Add(this); } }
public void DebugDraw() { if (this.map != Find.CurrentMap) { return; } //Region Traversal if (ShipHarmony.debug) { CellRect currentViewRect = Find.CameraDriver.CurrentViewRect; currentViewRect.ClipInsideMap(this.map); foreach (IntVec3 c in currentViewRect) { WaterRegion validRegionAt = this.GetValidRegionAt(c); if (!(validRegionAt is null) && !this.drawnRegions.Contains(validRegionAt)) { validRegionAt.DebugDraw(); this.drawnRegions.Add(validRegionAt); } } this.drawnRegions.Clear(); } IntVec3 intVec = Verse.UI.MouseCell(); if (intVec.InBoundsShip(this.map)) { //Room? //Room Group? WaterRegion regionAt_NoRebuild_InvalidAllowed = this.GetRegionAt_NoRebuild_InvalidAllowed(intVec); if (!(regionAt_NoRebuild_InvalidAllowed is null)) { regionAt_NoRebuild_InvalidAllowed.DebugDrawMouseover(); } } }
public static bool TryFindRandomCellInWaterRegion(this WaterRegion 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 void SetRegionAt(IntVec3 c, WaterRegion reg) { this.regionGrid[this.map.cellIndices.CellToIndex(c)] = reg; }
public static WaterRoom RoomAt(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { WaterRegion region = WaterRegionAndRoomQuery.RegionAt(c, map, allowedRegionTypes); return(region is null ? null : region.Room); }
public static bool ShouldCountRegion(WaterRegion r) { return(!r.IsDoorway); }