public virtual void FixVacuum(MapIndices indices) { var tile = GetTile(indices); if (tile?.GridIndex != _gridId) { return; } var adjacent = GetAdjacentTiles(indices); tile.Air = new GasMixture(GetVolumeForCells(1), AtmosphereSystem) { Temperature = Atmospherics.T20C }; Tiles[indices] = tile; var ratio = 1f / adjacent.Count; foreach (var(_, adj) in adjacent) { var mix = adj.Air.RemoveRatio(ratio); tile.Air.Merge(mix); adj.Air.Merge(mix); } }
private List <MapIndices> FindConnectedCells(MapIndices start) { var inner = new HashSet <MapIndices>(); var edge = new HashSet <MapIndices> { start }; // Basic inner/edge finder // The inner list is all the positions we know are empty, and take no further actions. // The edge list is all the positions for whom we have not searched their neighbours. // Move stuff from edge to inner, while adding adjacent empty locations to edge // When edge is empty, we have filled the entire room. while (edge.Count > 0) { var temp = new List <MapIndices>(edge); edge.Clear(); foreach (var pos in temp) { inner.Add(pos); if (IsSpace(pos)) { return(null); } Check(inner, edge, pos, Direction.North); Check(inner, edge, pos, Direction.South); Check(inner, edge, pos, Direction.East); Check(inner, edge, pos, Direction.West); } } return(new List <MapIndices>(inner)); }
public void PryTile(MapIndices indices) { if (!Owner.TryGetComponent(out IMapGridComponent? mapGridComponent)) { return; } if (IsSpace(indices) || IsAirBlocked(indices)) { return; } var mapGrid = mapGridComponent.Grid; var tile = mapGrid.GetTileRef(indices).Tile; var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.TypeId]; var underplating = _tileDefinitionManager["underplating"]; mapGrid.SetTile(indices, new Tile(underplating.TileId)); //Actually spawn the relevant tile item at the right position and give it some offset to the corner. var tileItem = _serverEntityManager.SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, mapGrid)); tileItem.Transform.WorldPosition += (0.2f, 0.2f); }
private GasOverlayMessage?ChunkToMessage(GasOverlayChunk chunk) { // Chunk data should already be up to date. // Only send relevant tiles to client. var tileData = new List <(MapIndices, GasOverlayData)>(); for (var x = 0; x < ChunkSize; x++) { for (var y = 0; y < ChunkSize; y++) { // TODO: Check could be more robust I think. var data = chunk.TileData[x, y]; if ((data.Gas == null || data.Gas.Length == 0) && data.FireState == 0 && data.FireTemperature == 0.0f) { continue; } var indices = new MapIndices(chunk.MapIndices.X + x, chunk.MapIndices.Y + y); tileData.Add((indices, data)); } } if (tileData.Count == 0) { return(null); } return(new GasOverlayMessage(chunk.GridIndices, tileData)); }
public void FixVacuum(MapIndices indices) { if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) { return; } var tile = GetTile(indices); if (tile?.GridIndex != mapGrid.Grid.Index) { return; } var adjacent = GetAdjacentTiles(indices); tile.Air = new GasMixture(GetVolumeForCells(1)) { Temperature = Atmospherics.T20C }; _tiles[indices] = tile; var ratio = 1f / adjacent.Count; foreach (var(direction, adj) in adjacent) { var mix = adj.Air.RemoveRatio(ratio); tile.Air.Merge(mix); adj.Air.Merge(mix); } }
public override void Update(float frameTime) { AccumulatedFrameTime += frameTime; _updateCooldown = 1 / _configManager.GetCVar <float>("net.atmosdbgoverlaytickrate"); if (AccumulatedFrameTime < _updateCooldown) { return; } // This is the timer from GasTileOverlaySystem AccumulatedFrameTime -= _updateCooldown; var currentTick = _gameTiming.CurTick; // Now we'll go through each player, then through each chunk in range of that player checking if the player is still in range // If they are, check if they need the new data to send (i.e. if there's an overlay for the gas). // Afterwards we reset all the chunk data for the next time we tick. foreach (var session in PlayerObservers) { if (session.AttachedEntity == null) { continue; } var entity = session.AttachedEntity; var worldBounds = Box2.CenteredAround(entity.Transform.WorldPosition, new Vector2(LocalViewRange, LocalViewRange)); foreach (var grid in _mapManager.FindGridsIntersecting(entity.Transform.MapID, worldBounds)) { if (!_entityManager.TryGetEntity(grid.GridEntityId, out var gridEnt)) { continue; } if (!gridEnt.TryGetComponent <GridAtmosphereComponent>(out var gam)) { continue; } var entityTile = grid.GetTileRef(entity.Transform.Coordinates).GridIndices; var baseTile = new MapIndices(entityTile.X - (LocalViewRange / 2), entityTile.Y - (LocalViewRange / 2)); var debugOverlayContent = new AtmosDebugOverlayData[LocalViewRange * LocalViewRange]; var index = 0; for (var y = 0; y < LocalViewRange; y++) { for (var x = 0; x < LocalViewRange; x++) { var mapIndices = new MapIndices(baseTile.X + x, baseTile.Y + y); debugOverlayContent[index++] = ConvertTileToData(gam.GetTile(mapIndices)); } } RaiseNetworkEvent(new AtmosDebugOverlayMessage(grid.Index, baseTile, debugOverlayContent), session.ConnectedClient); } } }
private void UpdatePosition() { if (!_mapManager.TryGetGrid(Owner.Transform.GridID, out var grid)) { Logger.WarningS(LogCategory, "Entity {0} snapgrid didn't find grid {1}. Race condition?", Owner.Uid, Owner.Transform.GridID); return; } if (IsSet) { grid.RemoveFromSnapGridCell(Position, Offset, this); } IsSet = true; var oldPos = Position; Position = grid.SnapGridCellFor(Owner.Transform.GridPosition, Offset); grid.AddToSnapGridCell(Position, Offset, this); if (oldPos != Position) { OnPositionChanged?.Invoke(); } }
public TileAtmosphere?GetTile(MapIndices indices) { if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) { return(null); } if (_tiles.TryGetValue(indices, out var tile)) { return(tile); } // We don't have that tile! if (IsSpace(indices)) { var space = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(int.MaxValue) { Temperature = Atmospherics.TCMB }); space.Air.MarkImmutable(); return(space); } return(null); }
public bool Execute(IDebugConsole console, params string[] args) { if (args.Length != 2 && args.Length != 3) { console.AddLine("Must pass exactly 2 or 3 arguments", Color.Red); return(false); } var gridID = new GridId(int.Parse(args[0], CultureInfo.InvariantCulture)); var indexSplit = args[1].Split(','); var x = int.Parse(indexSplit[0], CultureInfo.InvariantCulture); var y = int.Parse(indexSplit[1], CultureInfo.InvariantCulture); var indices = new MapIndices(x, y); SnapGridOffset offset = SnapGridOffset.Center; if (args.Length == 3) { offset = (SnapGridOffset)Enum.Parse(typeof(SnapGridOffset), args[2]); } var mapMan = IoCManager.Resolve <IMapManager>(); var grid = mapMan.GetGrid(gridID); foreach (var entity in grid.GetSnapGridCell(indices, offset)) { console.AddLine(entity.Owner.Uid.ToString()); } return(false); }
public TemperatureExposeEvent(MapIndices indices, GridId gridId, GasMixture air, float temperature, float volume) { Indices = indices; Grid = gridId; Air = air; Temperature = temperature; Volume = volume; }
/// <summary> /// Flags Dirty if the data is different. /// </summary> /// <param name="data"></param> /// <param name="indices"></param> public void Update(SharedGasTileOverlaySystem.GasOverlayData data, MapIndices indices) { DebugTools.Assert(InBounds(indices)); var(offsetX, offsetY) = (indices.X - MapIndices.X, indices.Y - MapIndices.Y); TileData[offsetX, offsetY] = data; }
public TileAtmosphere(GridAtmosphereComponent atmosphereComponent, GridId gridIndex, MapIndices gridIndices, GasMixture mixture = null) { IoCManager.InjectDependencies(this); _gridAtmosphereComponent = atmosphereComponent; GridIndex = gridIndex; GridIndices = gridIndices; Air = mixture; }
public static bool PryTile(this MapIndices indices, GridId gridId, IMapManager?mapManager = null, ITileDefinitionManager?tileDefinitionManager = null, IEntityManager?entityManager = null) { mapManager ??= IoCManager.Resolve <IMapManager>(); var grid = mapManager.GetGrid(gridId); var tileRef = grid.GetTileRef(indices); return(tileRef.PryTile(mapManager, tileDefinitionManager, entityManager)); }
public virtual void PryTile(MapIndices indices) { if (IsSpace(indices) || IsAirBlocked(indices)) { return; } indices.PryTile(_gridId, _mapManager, _tileDefinitionManager, _serverEntityManager); }
public void SetTileOverlay(GridId gridIndex, MapIndices indices, GasData[] gasData, int fireState = 0, float fireTemperature = 0f) { if (!_overlay.TryGetValue(gridIndex, out var _)) { _overlay[gridIndex] = new Dictionary <MapIndices, GasOverlayData>(); } _overlay[gridIndex][indices] = new GasOverlayData(fireState, fireTemperature, gasData); _queue.Add(GetData(gridIndex, indices)); }
public void _setChunkDirty(IMapGrid grid, MapIndices chunk) { var data = _mapChunkData[grid.Index]; if (data.TryGetValue(chunk, out var datum)) { datum.Dirty = true; } // Don't need to set it if we don't have an entry since lack of an entry is treated as dirty. }
public void Invalidate(GridId gridIndex, MapIndices indices) { if (!_invalid.TryGetValue(gridIndex, out var set) || set == null) { set = new HashSet <MapIndices>(); _invalid.Add(gridIndex, set); } set.Add(indices); }
public void Invalidate(GridId gridIndex, MapIndices indices) { if (!_invalidTiles.TryGetValue(gridIndex, out var existing)) { existing = new HashSet <MapIndices>(); _invalidTiles[gridIndex] = existing; } existing.Add(indices); }
public static IEnumerable <IEntity> GetEntitiesInTileFast(this MapIndices indices, GridId gridId, GridTileLookupSystem?gridTileLookup = null) { var turf = indices.GetTileRef(gridId); if (turf == null) { return(Enumerable.Empty <IEntity>()); } return(GetEntitiesInTileFast(turf.Value, gridTileLookup)); }
private PathfindingChunk CreateChunk(GridId gridId, MapIndices indices) { var newChunk = new PathfindingChunk(gridId, indices); newChunk.Initialize(); if (!_graph.ContainsKey(gridId)) { _graph.Add(gridId, new Dictionary <MapIndices, PathfindingChunk>()); } _graph[gridId].Add(indices, newChunk); return(newChunk); }
public bool InBounds(MapIndices mapIndices) { if (mapIndices.X < _indices.X || mapIndices.Y < _indices.Y) { return(false); } if (mapIndices.X >= _indices.X + ChunkSize || mapIndices.Y >= _indices.Y + ChunkSize) { return(false); } return(true); }
private AirtightComponent GetObstructingComponent(MapIndices indices) { foreach (var v in _grid.GetSnapGridCell(indices, SnapGridOffset.Center)) { if (v.Owner.TryGetComponent <AirtightComponent>(out var ac)) { return(ac); } } return(null); }
public Dictionary <Direction, TileAtmosphere> GetAdjacentTiles(MapIndices indices) { var sides = new Dictionary <Direction, TileAtmosphere>(); foreach (var dir in Cardinal()) { var side = indices.Offset(dir); sides[dir] = GetTile(side); } return(sides); }
internal GridTileLookupChunk(GridId gridId, MapIndices indices) { GridId = gridId; Indices = indices; for (var x = 0; x < ChunkSize; x++) { for (var y = 0; y < ChunkSize; y++) { _nodes[x, y] = new GridTileLookupNode(this, new MapIndices(Indices.X + x, Indices.Y + y)); } } }
private void MergeAtmospheres(MapIndices pos) { var adjacent = new HashSet <Atmosphere>(GetAdjacentAtmospheres(pos).Values); // If this block doesn't separate two atmospheres, there's nothing to do if (adjacent.Count <= 1) { return; } var allCells = new List <MapIndices> { pos }; foreach (var atmos in adjacent) { allCells.AddRange(FindRoomContents(atmos)); } // Fuse all adjacent atmospheres Atmosphere replacement; if (adjacent.Contains(null)) { replacement = null; } else { replacement = new Atmosphere(GetVolumeForCells(allCells.Count)); foreach (var atmos in adjacent) { if (atmos == null) { continue; } // Copy all the gasses across foreach (var gas in atmos.Gasses) { replacement.Add(gas.Gas, gas.Volume, atmos.Temperature); } } } foreach (var cellPos in allCells) { _atmospheres[cellPos] = replacement; } }
private void Check(ICollection <MapIndices> inner, ISet <MapIndices> edges, MapIndices pos, Direction dir) { pos += (MapIndices)dir.CardinalToIntVec(); if (IsObstructed(pos)) { return; } if (inner.Contains(pos)) { return; } edges.Add(pos); }
public virtual void PryTile(MapIndices indices) { if (!Owner.TryGetComponent(out IMapGridComponent? mapGridComponent)) { return; } if (IsSpace(indices) || IsAirBlocked(indices)) { return; } var mapGrid = mapGridComponent.Grid; indices.PryTile(mapGrid.Index, _mapManager, _tileDefinitionManager, _serverEntityManager); }
public AtmosDebugOverlayData?GetData(GridId gridIndex, MapIndices indices) { if (!_tileData.TryGetValue(gridIndex, out var srcMsg)) { return(null); } var relative = indices - srcMsg.BaseIdx; if (relative.X < 0 || relative.Y < 0 || relative.X >= LocalViewRange || relative.Y >= LocalViewRange) { return(null); } return(srcMsg.OverlayData[relative.X + (relative.Y * LocalViewRange)]); }
public Dictionary <Direction, TileAtmosphere> GetAdjacentTiles(MapIndices indices) { var sides = new Dictionary <Direction, TileAtmosphere>(); foreach (var dir in Cardinal) { var side = indices.Offset(dir); var tile = GetTile(side); if (tile?.Air != null) { sides[dir] = tile; } } return(sides); }
/// <summary> /// Return our neighboring nodes (even across chunks) /// </summary> /// <returns></returns> public IEnumerable <PathfindingNode> GetNeighbors() { List <PathfindingChunk> neighborChunks = null; if (ParentChunk.OnEdge(this)) { neighborChunks = ParentChunk.RelevantChunks(this).ToList(); } for (var x = -1; x <= 1; x++) { for (var y = -1; y <= 1; y++) { if (x == 0 && y == 0) { continue; } var indices = new MapIndices(TileRef.X + x, TileRef.Y + y); if (ParentChunk.InBounds(indices)) { var(relativeX, relativeY) = (indices.X - ParentChunk.Indices.X, indices.Y - ParentChunk.Indices.Y); yield return(ParentChunk.Nodes[relativeX, relativeY]); } else { DebugTools.AssertNotNull(neighborChunks); // Get the relevant chunk and then get the node on it foreach (var neighbor in neighborChunks) { // A lot of edge transitions are going to have a single neighboring chunk // (given > 1 only affects corners) // So we can just check the count to see if it's inbound if (neighborChunks.Count > 0 && !neighbor.InBounds(indices)) { continue; } var(relativeX, relativeY) = (indices.X - neighbor.Indices.X, indices.Y - neighbor.Indices.Y); yield return(neighbor.Nodes[relativeX, relativeY]); break; } } } } }