Пример #1
0
        public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world)
        {
            Graphics = graphics;
            World    = world;

            Options   = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions;
            Resources = serviceProvider.GetRequiredService <ResourceManager>();

            var stillAtlas = Resources.Atlas.GetStillAtlas();

            var fogStart = 0;

            Shaders = new RenderingShaders(Graphics);
            Shaders.SetTextures(stillAtlas);
            Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0));

            RenderDistance = Options.VideoOptions.RenderDistance;

            Options.VideoOptions.RenderDistance.Bind(
                (value, newValue) =>
            {
                RenderDistance = newValue;
            });

            Chunks            = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>();
            CancellationToken = new CancellationTokenSource();

            BlockLightCalculations = new BlockLightCalculations((World)world);
            SkyLightCalculator     = new SkyLightCalculations();

            Func <ChunkCoordinates, ChunkCoordinates, int> orderingTool = (a, b) =>
            {
                var pos       = new ChunkCoordinates(World.Camera.Position);
                var aDistance = a.DistanceTo(pos);
                var bDistance = b.DistanceTo(pos);

                if (aDistance < bDistance)
                {
                    return(-1);
                }

                if (bDistance > aDistance)
                {
                    return(1);
                }

                return(0);
            };

            UpdateQueue       = new FancyQueue <ChunkCoordinates>();
            UpdateBorderQueue = new FancyQueue <ChunkCoordinates>();
            FastUpdateQueue   = new FancyQueue <ChunkCoordinates>();
        }
Пример #2
0
        public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world)
        {
            Graphics = graphics;
            World    = world;

            Options   = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions;
            Resources = serviceProvider.GetRequiredService <ResourceManager>();

            var stillAtlas = Resources.Atlas.GetStillAtlas();

            var fogStart = 0;

            Shaders = new RenderingShaders(Graphics);
            Shaders.SetTextures(stillAtlas);
            Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0));

            _renderSampler.MaxMipLevel = stillAtlas.LevelCount;

            RenderDistance = Options.VideoOptions.RenderDistance;

            Options.VideoOptions.RenderDistance.Bind(
                (value, newValue) =>
            {
                RenderDistance = newValue;
            });

            Chunks            = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>();
            CancellationToken = new CancellationTokenSource();

            BlockLightCalculations = new BlockLightCalculations(world, CancellationToken.Token);
            SkyLightCalculator     = new SkyLightCalculations(CancellationToken.Token);

            UpdateQueue       = new FancyQueue <ChunkCoordinates>();
            UpdateBorderQueue = new FancyQueue <ChunkCoordinates>();
            FastUpdateQueue   = new FancyQueue <ChunkCoordinates>();
        }
Пример #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);
        }