protected ValueTask <int> ReadFromChunkAsync(string chunkType, long position, byte[] buffer, int length) { if (_chunks == null || ChunkReader == null) { return(new ValueTask <int>(0)); } else if (length <= 0) { throw new ArgumentOutOfRangeException(nameof(length)); } Chunk?ch = null; foreach (var c in _chunks) { if (c.Name == chunkType) { ch = c; break; } } if (ch == null) { return(new ValueTask <int>(0)); } int requested = (int)Math.Min(length, ch.Value.Length - position); if (requested <= 0) { return(new ValueTask <int>(0)); } return(ChunkReader.ReadAtAsync(ch.Value.Position + position, buffer, requested)); }
private void SetContent(Block block, uint data, Liquid liquid, LiquidLevel level, bool isStatic, Vector3i position, bool tickLiquid) { Chunk? chunk = GetChunkWithPosition(position); if (chunk == null) return; uint val = Section.Encode(block, data, liquid, level, isStatic); chunk.GetSection(position.Y >> Section.SectionSizeExp).SetContent(position, val); if (tickLiquid) liquid.TickNow(this, position, level, isStatic); // Block updates - Side is passed out of the perspective of the block receiving the block update. foreach (BlockSide side in BlockSide.All.Sides()) { Vector3i neighborPosition = side.Offset(position); (BlockInstance? blockNeighbor, LiquidInstance? liquidNeighbor) = GetContent(neighborPosition); blockNeighbor?.Block.BlockUpdate(this, neighborPosition, blockNeighbor.Data, side.Opposite()); liquidNeighbor?.Liquid.TickSoon(this, neighborPosition, liquidNeighbor.IsStatic); } ProcessChangedSection(chunk, position); }
public MinecraftBlock?Lookup(Vector <int> Location) { if (Location.Y < 0 || Location.Y >= ChunkYSize) { return(null); } else { int chunkxloc = (Location.X % ChunkXSize + ChunkXSize) % ChunkXSize; int chunkyloc = (Location.Z % ChunkZSize + ChunkZSize) % ChunkZSize; Point <int> chunkkey = new Point <int>((Location.X - chunkxloc) / ChunkXSize, (Location.Z - chunkyloc) / ChunkZSize); Chunk? chunk = this.LoadChunk(chunkkey); if (chunk == null) { return(null); } else { return(chunk.Value.Lookup(new Vector <int>( chunkxloc, Location.Y, chunkyloc))); } } }
/////////////////////////////////////////////////////////////////////// // Private Methods // /////////////////////////////////////////////////////////////////////// // Inspect the RIFF chunks for the necessary Wave file information private Chunk[] CheckChunks() { Chunk?fmt = null, data = null; // Search through all chunks for the required chunk IDs for (int x = 0; x < Chunks.Length; x++) { if (Chunks[x].ID.Equals("fmt ")) // Audio format information { fmt = Chunks[x]; } if (Chunks[x].ID.Equals("data")) // Audio sample data { data = Chunks[x]; } } // Ensure all required chunks were found if (fmt == null || data == null || ((Chunk)fmt).Size < 16) { throw new Exception("Invalid wave file"); } // Return all required chunks as an array return(new Chunk[2] { (Chunk)fmt, (Chunk)data }); }
public Terrain GetTerrainOrNull(int x, int y) { Chunk?chunk = TryGetChunk(x, y); if (chunk != null) { return(chunk.Value.terrain); } return(null); }
public Chunk GetChunk(Chunk.Coords coords) { Chunk?chunkOrNull = TryGetChunk(coords); if (chunkOrNull != null) { return((Chunk)chunkOrNull); } ShowChunk(coords); return((Chunk)TryGetChunk(coords)); }
public void RemoveChunk(Chunk.Coords coords) { Chunk?chunkOrNull = TryGetChunk(coords); if (chunkOrNull != null) { Chunk chunk = (Chunk)chunkOrNull; Destroy(chunk.terrain.gameObject); Destroy(chunk.terrain.terrainData); Destroy(chunk.terrain); chunkMap.Remove(coords); } }
private void ModifyWorldData(Vector3i position, uint clearMask, uint addMask) { Chunk? chunk = GetChunkWithPosition(position); if (chunk == null) return; uint val = chunk.GetSection(position.Y >> Section.SectionSizeExp).GetContent(position); val &= clearMask; val |= addMask; chunk.GetSection(position.Y >> Section.SectionSizeExp).SetContent(position, val); ProcessChangedSection(chunk, position); }
public MinecraftBlock?Lookup(Vector <int> Location) { int cx = Location.X / ChunkXSize; int cz = Location.Z / ChunkZSize; int cix = Location.X - (cx * ChunkXSize); int ciz = Location.Z - (cz * ChunkZSize); Chunk?chunk = this._Chunks[cx, cz]; if (chunk.HasValue) { return(chunk.Value.Lookup(new Vector <int>(cix, Location.Y, ciz))); } else { return(null); } }
private void SetupNeighbors(int x, int y) { Chunk.Coords coords = new Chunk.Coords(x, y); Chunk? chunk = TryGetChunk(x, y); if (chunk == null) { return; } Terrain left = GetTerrainOrNull(coords.x - 1, coords.y); Terrain top = GetTerrainOrNull(coords.x, coords.y + 1); Terrain right = GetTerrainOrNull(coords.x + 1, coords.y); Terrain bottom = GetTerrainOrNull(coords.x, coords.y - 1); chunk.Value.terrain.SetNeighbors(left, top, right, bottom); }
private void RetrieveContent(Vector3i position, out Block? block, out uint data, out Liquid? liquid, out LiquidLevel level, out bool isStatic) { Chunk? chunk = GetChunkWithPosition(position); if (chunk != null) { uint val = chunk.GetSection(position.Y >> Section.SectionSizeExp).GetContent(position); Section.Decode(val, out block, out data, out liquid, out level, out isStatic); return; } block = null; data = 0; liquid = null; level = 0; isStatic = false; }
private static IEnumerable <Chunk> MergeSmall(int limit, IEnumerable <Chunk> input) { Chunk?current = null; foreach (var c in input) { if (c.Count < limit) { if (current.HasValue) { current = current.Value.Union(c); } else { current = c; } if (current.Value.Count >= limit) { yield return(current.Value); current = null; } } else { yield return(c); } } if (current.HasValue) { yield return(current.Value); current = null; } }
public async Task <Chunk> GenerateChunkAsync(int x, int z, World world, Chunk?chunk = null) { if (chunk is { isGenerated : true })
/// <summary> /// Schedule the destruction of this block. /// </summary> /// <param name="world">The world in which the block is located.</param> /// <param name="position">The position of the block that will be scheduled to be destroyed.</param> protected void ScheduleDestroy(World world, Vector3i position) { Chunk?chunk = world.GetChunkWithPosition(position); chunk?.ScheduleBlockTick(new BlockTick(position, this, TickOperation.Destroy), ScheduledDestroyOffset); }
/// <summary> /// Schedules a tick according to the given tick offset; /// </summary> /// <param name="world">The world in which the block is.</param> /// <param name="position">The position of the block a tick should be scheduled for.</param> /// <param name="tickOffset">The offset in frames to when the block should be ticked.</param> protected void ScheduleTick(World world, Vector3i position, int tickOffset) { Chunk?chunk = world.GetChunkWithPosition(position); chunk?.ScheduleBlockTick(new BlockTick(position, this, TickOperation.Tick), tickOffset); }
/// <summary> /// Schedules a tick according to the viscosity. /// </summary> protected void ScheduleTick(World world, Vector3i position) { Chunk?chunk = world.GetChunkWithPosition(position); chunk?.ScheduleLiquidTick(new LiquidTick(position, this), Viscosity); }