示例#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
        private bool ProcessLighting(ChunkCoordinates[] renderedChunks)
        {
            bool processed = false;

            if (BlockLightCalculations.TryProcess(
                    blockCoordinates => { return(Chunks.ContainsKey((ChunkCoordinates)blockCoordinates)); },
                    out BlockCoordinates coordinates))
            {
                if (coordinates.Y < 0 || coordinates.Y >= 256)
                {
                    return(false);
                }

                ChunkCoordinates cc = (ChunkCoordinates)coordinates;

                if (TryGetChunk(cc, out var c))
                {
                    c.GetSection(coordinates.Y)?.SetBlockLightScheduled(
                        coordinates.X & 0x0f, coordinates.Y - 16 * (coordinates.Y >> 4), coordinates.Z & 0x0f, true);

                    //ScheduleChunkUpdate(cc, ScheduleType.Lighting);
                }

                return(true);
            }

            return(false);
        }
示例#3
0
 public void RecalculateLight(Level level, AnvilWorldProvider wp)
 {
     while (wp.LightSources.Count > 0)
     {
         var block = wp.LightSources.Dequeue();
         block = level.GetBlock(block.Coordinates);
         BlockLightCalculations.Calculate(level, block);
     }
 }
        public static void RecalculateLight(Level level, AnvilWorldProvider anvilWorldProvider)
        {
            SkyLightCalculations.Calculate(level);

            while (anvilWorldProvider.LightSources.Count > 0)
            {
                var block = anvilWorldProvider.LightSources.Dequeue();
                BlockLightCalculations.Calculate(level, block.Coordinates);
            }
        }
示例#5
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>();
        }
示例#6
0
        public static void RecalculateBlockLight(Level level, AnvilWorldProvider wp)
        {
            Queue <Block> sources = new Queue <Block>(wp.LightSources);

            while (sources.Count > 0)
            {
                var block = sources.Dequeue();
                if (block == null)
                {
                    continue;
                }

                block = level.GetBlock(block.Coordinates);
                BlockLightCalculations.Calculate(level, block);
            }
        }
示例#7
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;
            }
        }
示例#8
0
        /// <inheritdoc />
        public void RemoveChunk(ChunkCoordinates position, bool dispose = true)
        {
            BlockLightCalculations.Remove(position);

            if (Chunks.TryRemove(position, out var column))
            {
                foreach (var blockEntity in column.GetBlockEntities)
                {
                    World.EntityManager.RemoveBlockEntity(
                        new BlockCoordinates((column.X << 4) + blockEntity.X, blockEntity.Y, (column.Z << 4) + blockEntity.Z));
                }

                UpdateQueue.Remove(position);
                UpdateBorderQueue.Remove(position);

                if (dispose)
                {
                    column.Dispose();
                }
            }
        }
示例#9
0
        /// <inheritdoc />
        public void AddChunk(ChunkColumn chunk, ChunkCoordinates position, bool doUpdates = false)
        {
            //chunk.CalculateHeight();

            Chunks.AddOrUpdate(
                position, coordinates => chunk, (coordinates, column) =>
            {
                if (!ReferenceEquals(column, chunk))
                {
                    column.Dispose();
                }

                return(chunk);
            });

            if (chunk.IsNew)
            {
                var chunkpos = new BlockCoordinates(position.X << 4, 0, position.Z << 4);

                foreach (var ls in chunk.GetLightSources())
                {
                    BlockLightCalculations.Enqueue(chunkpos + ls);
                }

                //SkyLightCalculations s = new SkyLightCalculations();

                //SkyLightCalculator.Calculate(chunk, position);
            }

            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);
            }

            ScheduleChunkUpdate(position, ScheduleType.Full);
            //UpdateQueue.Enqueue(position);
        }
示例#10
0
 public void NewArena(MapInfo map)
 {
     lock (LevelSync)
     {
         AnvilWorldProvider l;
         if (OnlyRead)
         {
             l = map.ProviderCache;
         }
         else
         {
             l = map.ProviderCache.Clone() as AnvilWorldProvider;
         }
         int id = LevelCount;
         if (LevelPoolId.Count > 0)
         {
             id = LevelPoolId.First();
             LevelPoolId.Remove(id);
         }
         else
         {
             LevelCount++;
             id = LevelCount;
         }
         var level = new xCoreLevel(l, Game.Context.Server.LevelManager.EntityManager, Game, map, id);
         LevelCount++;
         level.Initialize();
         SkyLightCalculations.Calculate(level);
         while (l.LightSources.Count > 0)
         {
             var block = l.LightSources.Dequeue();
             block = level.GetBlock(block.Coordinates);
             BlockLightCalculations.Calculate(level, block);
         }
         Game.Initialization(level);
         Levels.Add(level);
     }
 }
示例#11
0
        public void ResetMap()
        {
            //if (_worldProvider == null) throw new Exception($"Can not get level from the WorldProvider");
            AnvilWorldProvider worldProvider = WorldProvider as AnvilWorldProvider;
            //worldProvider._chunkCache.Clear();
            //worldProvider = Map.ProviderCache.Clone() as AnvilWorldProvider;
            ConcurrentDictionary <ChunkCoordinates, ChunkColumn> chunkCache = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>();

            foreach (KeyValuePair <ChunkCoordinates, ChunkColumn> valuePair in Map.ProviderCache._chunkCache)
            {
                chunkCache.TryAdd(valuePair.Key, (ChunkColumn)valuePair.Value?.Clone());
            }
            worldProvider._chunkCache.Clear();
            worldProvider._chunkCache = chunkCache;
            SkyLightCalculations.Calculate(this);
            while (worldProvider.LightSources.Count > 0)
            {
                var block = worldProvider.LightSources.Dequeue();
                block = this.GetBlock(block.Coordinates);
                BlockLightCalculations.Calculate(this, block);
            }
            //WorldProvider. = worldProvider;
        }
示例#12
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>();
        }
示例#13
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);
        }
示例#14
0
        public static void RecalculateBlockLight(Level level, AnvilWorldProvider wp)
        {
            var sources = wp.LightSources.ToArray();

            Parallel.ForEach(sources, block => { BlockLightCalculations.Calculate(level, block.Coordinates); });
        }
示例#15
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);
        }
示例#16
0
 private bool ProcessLighting()
 {
     return(BlockLightCalculations.Process(
                Chunks.FirstOrDefault(x => BlockLightCalculations.HasEnqueued(x.Key)).Key));
 }
示例#17
0
        public LevelPoolGame(xCoreGames core, xCoreInterface game, bool onlyread, bool parse)
        {
            Random rnd     = new Random();
            var    timings = new Stopwatch();

            timings.Start();
            string basepath = Config.GetProperty("PluginDirectory", "Plugins") + "\\" + game.NameGame;

            for (int id = 1; id <= game.ArenaLoaded; id++)
            {
                if (Maps.Count == 0)
                {
                    DirectoryInfo dirInfo = new DirectoryInfo(basepath);
                    foreach (var dir in dirInfo.GetDirectories())
                    {
                        var     provider = new AnvilWorldProvider(basepath + "\\" + dir.Name);
                        var     cfg      = File.ReadAllText(basepath + "\\" + dir.Name + "\\config.json");
                        JObject jobj     = JObject.Parse(cfg);
                        Maps.Add(dir.Name, new MapInfo(dir.Name, jobj));
                        Maps[dir.Name].ProviderCache = provider;
                        Maps[dir.Name].ProviderCache.Initialize();
                        Maps[dir.Name].ProviderCache.PruneAir();
                        Maps[dir.Name].ProviderCache.MakeAirChunksAroundWorldToCompensateForBadRendering();
                    }
                }

                string map = Maps.Keys.ElementAt(rnd.Next(0, Maps.Keys.Count - 1));

                Level levelkey = Levels.FirstOrDefault(l => l.LevelId.Equals(game.NameGame + id, StringComparison.InvariantCultureIgnoreCase));
                if (levelkey == null)
                {
                    AnvilWorldProvider provider;
                    //provider = Maps[map].ProviderCache;
                    //if (!Maps[map].ProviderBool)
                    //{
                    if (onlyread)
                    {
                        provider = Maps[map].ProviderCache;
                    }
                    else
                    {
                        provider = Maps[map].ProviderCache.Clone() as AnvilWorldProvider;
                    }
                    //}
                    var level = new xCoreLevel(provider, game.Context.Server.LevelManager.EntityManager, game, Maps[map], LevelCount);
                    LevelCount++;
                    level.Initialize();
                    SkyLightCalculations.Calculate(level);
                    while (provider.LightSources.Count > 0)
                    {
                        var block = provider.LightSources.Dequeue();
                        block = level.GetBlock(block.Coordinates);
                        BlockLightCalculations.Calculate(level, block);
                    }
                    if (parse)
                    {
                        int X = Maps[map].Center.X;
                        int Z = Maps[map].Center.Z;
                        List <BlockCoordinates> BE = new List <BlockCoordinates>();
                        if (Maps[map].CacheBlockEntites == null)
                        {
                            int startX = Math.Min(X - 256, X + 256);
                            int endX   = Math.Max(X - 256, X + 256);
                            int startY = Math.Min(11, 129);
                            int endY   = Math.Max(11, 129);
                            int startZ = Math.Min(Z - 256, Z + 256);
                            int endZ   = Math.Max(Z - 256, Z + 256);
                            for (int x = startX; x <= endX; ++x)
                            {
                                for (int y = startY; y <= endY; ++y)
                                {
                                    for (int z = startZ; z <= endZ; ++z)
                                    {
                                        var         bc = new BlockCoordinates(x, y, z);
                                        BlockEntity blockentity;
                                        if ((blockentity = level.GetBlockEntity(bc)) != null)
                                        {
                                            if (blockentity is ChestBlockEntity)
                                            {
                                                if (!BE.Contains(blockentity.Coordinates))
                                                {
                                                    BE.Add(blockentity.Coordinates);
                                                }
                                            }
                                            else if (blockentity is Sign)
                                            {
                                                CleanSignText(((Sign)blockentity).GetCompound(), "Text1");
                                                CleanSignText(((Sign)blockentity).GetCompound(), "Text2");
                                                CleanSignText(((Sign)blockentity).GetCompound(), "Text3");
                                                CleanSignText(((Sign)blockentity).GetCompound(), "Text4");
                                                BE.Add(bc);
                                            }
                                        }
                                    }
                                }
                            }
                            for (int x = startX; x <= endX; ++x)
                            {
                                for (int z = startZ; z <= endZ; ++z)
                                {
                                    var bc = new BlockCoordinates(x, 127, z);
                                    MiNET.Blocks.Block b = level.GetBlock(bc);
                                    if (b.Id == 95)
                                    {
                                        level.SetAir(bc, false);
                                    }
                                }
                            }
                        }
                        if (Maps[map].CacheBlockEntites == null)
                        {
                            Maps[map].CacheBlockEntites = BE;
                        }
                    }
                    game.Initialization(level);
                    Levels.Add(level);
                }
            }
            Core     = core;
            Game     = game;
            OnlyRead = onlyread;
            timings.Stop();
            Log.Info("Loaded " + Levels.Count + " arenas . Load time " + timings.ElapsedMilliseconds + " ms");
            _tickerHighPrecisionTimer = new Timer(QueueTimer, null, 0, 1000);
        }