예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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;
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }