Exemplo n.º 1
0
        public static void Calculate(World level)
        {
            var chunks = level.ChunkManager.GetAllChunks().Select(x => x.Value).Cast <ChunkColumn>().OrderBy(column => column.X)
                         .ThenBy(column => column.Z);

            SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.ChunkManager);

            //var blockAccess = level;

            _chunkCount = chunks.Count();

            if (_chunkCount == 0)
            {
                return;
            }

            CheckIfSpawnIsMiddle(chunks, level.SpawnPoint);

            Stopwatch sw = new Stopwatch();

            sw.Start();

            //Parallel.ForEach(chunks, chunk => chunk.RecalcHeight());

            //Log.Debug($"Recalc height level {level.LevelName}({level.LevelId}) for {_chunkCount} chunks, {_chunkCount*16*16*256} blocks. Time {sw.ElapsedMilliseconds}ms");

            SkyLightCalculations calculator = new SkyLightCalculations(Config.GetProperty("CalculateLights.MakeMovie", false));

            int midX = calculator.GetMidX(chunks.ToArray());

            //int width = calculator.GetWidth(chunks.ToArray());

            sw.Restart();

            HighPrecisionTimer tickerHighPrecisionTimer = null;

            calculator.StartTimeInMilliseconds = Environment.TickCount;

            var t0 = Task.Run(() =>
            {
                var pairs = chunks.OrderBy(pair => pair.X).ThenBy(pair => pair.Z).Where(chunk => chunk.X <= midX).OrderByDescending(pair => pair.X).ThenBy(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            var t5 = Task.Run(() =>
            {
                var pairs = chunks.OrderByDescending(pair => pair.X).ThenBy(pair => pair.Z).Where(chunk => chunk.X > midX).OrderBy(pair => pair.X).ThenByDescending(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            var t1 = Task.Run(() =>
            {
                var pairs = chunks.OrderBy(pair => pair.X).ThenBy(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            var t2 = Task.Run(() =>
            {
                var pairs = chunks.OrderByDescending(pair => pair.X).ThenByDescending(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            var t3 = Task.Run(() =>
            {
                var pairs = chunks.OrderByDescending(pair => pair.X).ThenBy(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            var t4 = Task.Run(() =>
            {
                var pairs = chunks.OrderBy(pair => pair.X).ThenByDescending(pair => pair.Z).ToArray();
                calculator.CalculateSkyLights(blockAccess, pairs);
            });

            Task.WaitAll(t0, t1, t2, t3, t4, t5);

            Log.Debug($"Recalc skylight for {_chunkCount:N0} chunks, {_chunkCount * 16 * 16 * 256:N0} blocks. Touches={calculator.visits:N0} Time {sw.ElapsedMilliseconds:N0}ms");

            //foreach (var chunk in chunks)
            //{
            //	calculator.ShowHeights(chunk);
            //}

            //var chunkColumn = chunks.First(column => column.x == -1 && column.z == 0 );
            //if (chunkColumn != null)
            //{
            //	Log.Debug($"Heights:\n{Package.HexDump(chunkColumn.height)}");
            //	Log.Debug($"skylight.Data:\n{Package.HexDump(chunkColumn.skyLight.Data, 64)}");
            //}
        }
Exemplo n.º 2
0
        public void Calculate(World level, BlockCoordinates coordinates)
        {
            int currentLight = level.GetSkyLight(coordinates);

            var         cc     = new ChunkCoordinates(coordinates);
            ChunkColumn chunk  = (ChunkColumn)level.GetChunkColumn(cc.X, cc.Z);
            var         height = chunk.GetRecalculatedHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f);

            Queue <BlockCoordinates> sourceQueue = new Queue <BlockCoordinates>();

            sourceQueue.Enqueue(coordinates);
            if (currentLight != 0)
            {
                Queue <BlockCoordinates>   resetQueue = new Queue <BlockCoordinates>();
                HashSet <BlockCoordinates> visits     = new HashSet <BlockCoordinates>();

                // Reset all lights that potentially derive from this
                resetQueue.Enqueue(coordinates);

                Queue <BlockCoordinates> deleteQueue = new Queue <BlockCoordinates>();
                while (resetQueue.Count > 0)
                {
                    var coord = resetQueue.Dequeue();
                    if (visits.Contains(coord))
                    {
                        continue;
                    }

                    visits.Add(coord);

                    if (coord.DistanceTo(coordinates) > 16)
                    {
                        continue;
                    }

                    ResetLight(level, resetQueue, sourceQueue, coord);
                    if (!sourceQueue.Contains(coord))
                    {
                        deleteQueue.Enqueue(coord);
                    }
                }

                level.SetSkyLight(coordinates, 0);

                foreach (var delete in deleteQueue)
                {
                    level.SetSkyLight(delete, 0);
                }
            }
            else
            {
                sourceQueue.Enqueue(coordinates);
                sourceQueue.Enqueue(coordinates.BlockUp());
                sourceQueue.Enqueue(coordinates.BlockDown());
                sourceQueue.Enqueue(coordinates.BlockWest());
                sourceQueue.Enqueue(coordinates.BlockEast());
                sourceQueue.Enqueue(coordinates.BlockNorth());
                sourceQueue.Enqueue(coordinates.BlockSouth());
            }

            chunk.SetHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f, (short)height);

            // Recalc
            Queue <BlockCoordinates>   lightBfQueue = new Queue <BlockCoordinates>(sourceQueue);
            HashSet <BlockCoordinates> lightBfSet   = new HashSet <BlockCoordinates>(sourceQueue);

            SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.ChunkManager);

            Calculate(blockAccess, lightBfQueue, lightBfSet);
        }