/// <inheritdoc /> public void AddChunk(ChunkColumn chunk, ChunkCoordinates position, bool doUpdates = false) { if (CancellationToken.IsCancellationRequested) { return; } //chunk.CalculateHeight(); if (chunk.IsNew) { SkyLightCalculator.RecalcSkyLight(chunk, World); BlockLightCalculations.Recalculate(chunk); } foreach (var blockEntity in chunk.GetBlockEntities) { var coordinates = new BlockCoordinates(blockEntity.X, blockEntity.Y, blockEntity.Z); //World.SetBlockEntity(coordinates.X, coordinates.Y, coordinates.Z, blockEntity); World.EntityManager.AddBlockEntity(coordinates, blockEntity); } Chunks.AddOrUpdate( position, coordinates => chunk, (coordinates, column) => { if (!ReferenceEquals(column, chunk)) { column.Dispose(); } return(chunk); }); ScheduleChunkUpdate(position, ScheduleType.Full); //UpdateQueue.Enqueue(position); }
/// <inheritdoc /> public void Dispose() { if (_disposed) { return; } try { //Graphics?.Dispose(); BlockLightCalculations?.Dispose(); BlockLightCalculations = null; SkyLightCalculator?.Dispose(); SkyLightCalculator = null; _renderSampler.Dispose(); CancellationToken.Cancel(); UpdateQueue.Clear(); FastUpdateQueue.Clear(); UpdateBorderQueue.Clear(); foreach (var chunk in Chunks) { chunk.Value.Dispose(); } Chunks.Clear(); foreach (var rendered in _renderedChunks) { rendered.Dispose(); } _renderedChunks = null; } finally { _disposed = true; } }
private bool ProcessQueue() { if (Interlocked.Read(ref _threadsRunning) >= Options.VideoOptions.ChunkThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= queue.Count) { return(false); } Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (queue.TryDequeue(out var chunkCoordinates, cc => { return(IsWithinView(cc, World.Camera)); })) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } //SkyLightCalculator.TryProcess(chunkCoordinates); bool newChunk = chunk.IsNew; if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } chunk.UpdateBuffer(Graphics, World, chunkCoordinates.DistanceTo(new ChunkCoordinates(World.Camera.Position)) <= RenderDistance / 2); if (newChunk) { ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border | ScheduleType.Lighting); ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border | ScheduleType.Lighting); } } finally { //Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }
private bool ProcessQueue() { var maxThreads = Options.VideoOptions.ChunkThreads.Value; if (Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } FancyQueue <ChunkCoordinates> queue = FastUpdateQueue; if (queue.IsEmpty) { queue = UpdateQueue; } if (queue.IsEmpty) { queue = UpdateBorderQueue; } //maxThreads = Math.Max(1, Math.Min(Options.VideoOptions.ChunkThreads, EnqueuedChunkUpdates / 4)); if (queue.IsEmpty || Interlocked.Read(ref _threadsRunning) >= maxThreads) { return(false); } //if (Interlocked.Read(ref _threadsRunning) ) Interlocked.Increment(ref _threadsRunning); ThreadPool.QueueUserWorkItem( oo => { try { while (!CancellationToken.IsCancellationRequested && queue.TryDequeue(out var chunkCoordinates, cc => IsWithinView(cc, World.Camera))) { if (TryGetChunk(chunkCoordinates, out var chunk)) { if (!Monitor.TryEnter(chunk.UpdateLock, 0)) { continue; } try { bool newChunk = chunk.IsNew; if (BlockLightCalculations != null) { if (newChunk) { //BlockLightCalculations.Recalculate(chunk); } if (BlockLightCalculations.HasEnqueued(chunkCoordinates)) { BlockLightCalculations.Process(chunkCoordinates); } } //SkyLightCalculator.TryProcess(chunkCoordinates); if (SkyLightCalculator != null) { if (newChunk) { SkyLightCalculator.RecalcSkyLight(chunk, World); } } chunk.UpdateBuffer(Graphics, World); /* if (newChunk) * { * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X + 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X - 1, chunk.Z), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z + 1), ScheduleType.Border); * ScheduleChunkUpdate(new ChunkCoordinates(chunk.X, chunk.Z - 1), ScheduleType.Border); * }*/ } finally { Scheduled.Remove(chunkCoordinates); Monitor.Exit(chunk.UpdateLock); } } if (queue != FastUpdateQueue && !FastUpdateQueue.IsEmpty) { queue = FastUpdateQueue; } else if (queue == FastUpdateQueue && FastUpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateBorderQueue && !UpdateQueue.IsEmpty) { queue = UpdateQueue; } else if (queue == UpdateQueue && UpdateQueue.IsEmpty) { queue = UpdateBorderQueue; } } } finally { Interlocked.Decrement(ref _threadsRunning); } }); return(true); }