public static void Calculate(Level level) { var chunks = level.GetLoadedChunks().OrderBy(column => column.x).ThenBy(column => column.z); SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.WorldProvider); _chunkCount = chunks.Count(); if (_chunkCount == 0) { return; } CheckIfSpawnIsMiddle(chunks, level.SpawnPoint.GetCoordinates3D()); 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; if (calculator.TrackResults) { tickerHighPrecisionTimer = new HighPrecisionTimer(100, _ => calculator.SnapshotVisits()); } 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"); if (calculator.TrackResults) { Task.Run(() => { tickerHighPrecisionTimer?.Dispose(); calculator.SnapshotVisits(); calculator.SnapshotVisits(); if (calculator.RenderingTasks.Count == 0) { return; } // Start with an end-frame (twitter thumbs) var last = calculator.RenderingTasks.Last(); calculator.RenderingTasks.Remove(last); calculator.RenderingTasks.Insert(0, last); calculator.RenderVideo(); Log.Debug($"Movie rendered."); }); } //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)}"); //} }