private static bool BuildThreadPrefix(HeightmapBuilder __instance) { ZLog.Log("Builder started"); while (!__instance.m_stop) { if (!BetterContinents.ConfigExperimentalParallelChunksBuild.Value) { __instance.m_lock.WaitOne(); bool flag = __instance.m_toBuild.Count > 0; __instance.m_lock.ReleaseMutex(); if (flag) { __instance.m_lock.WaitOne(); HeightmapBuilder.HMBuildData hmbuildData = __instance.m_toBuild[0]; __instance.m_lock.ReleaseMutex(); var st = new Stopwatch(); st.Start(); __instance.Build(hmbuildData); buildTimes.Add(st.ElapsedMilliseconds); if (buildTimes.Count > 100) { buildTimes.RemoveAt(0); } BetterContinents.Log($"Average chunk build time with vanilla {buildTimes.Average()} ms"); __instance.m_lock.WaitOne(); __instance.m_toBuild.Remove(hmbuildData); __instance.m_ready.Add(hmbuildData); while (__instance.m_ready.Count > 16) { __instance.m_ready.RemoveAt(0); } __instance.m_lock.ReleaseMutex(); } Thread.Sleep(10); } else { __instance.m_lock.WaitOne(); var buildTasks = __instance.m_toBuild .Select(b => new { task = Task.Run(() => BuildFn(__instance, b)), buildData = b }) .ToList(); // Important to use ToList for force immediate enumeration inside the lock! __instance.m_toBuild.Clear(); __instance.m_lock.ReleaseMutex(); if (buildTasks.Any()) { var st = new Stopwatch(); st.Start(); Task.WaitAll(buildTasks.Select(bt => bt.task).ToArray()); buildTimes.Add(st.ElapsedMilliseconds / (float)buildTasks.Count); if (buildTimes.Count > 100) { buildTimes.RemoveAt(0); } BetterContinents.Log($"Average chunk build time with MT {buildTimes.Average()} ms"); __instance.m_lock.WaitOne(); foreach (var bt in buildTasks) { __instance.m_ready.Add(bt.buildData); } while (__instance.m_ready.Count > 16) { __instance.m_ready.RemoveAt(0); } __instance.m_lock.ReleaseMutex(); } } Thread.Sleep(10); } return(false); }
public static void BeginTerrainChanges() { // Stop and reset the heightmap generator first HeightmapBuilder.instance.Dispose(); var _ = new HeightmapBuilder(); }