// Harmony prefix to override entire method to potentially fix NRE [HarmonyPatch(typeof(ChunkManager), nameof(ChunkManager.GetNextChunkToProvide))] public class ChunkManagerPatches { [HarmonyPrefix] public static bool Prefix(ChunkManager __instance, ref long __result) { int chunkPositionsCount = 0; lock (__instance.lockObject) { __instance.m_AllChunkPositions.list.CopyTo(__instance.allChunkPositionsCopy); chunkPositionsCount = __instance.m_AllChunkPositions.list.Count; } ChunkCluster chunkCache = __instance.m_World.ChunkCache; // added th== null check to preempt going through while loops and a stack trace to see where it possibly originates from if (chunkCache == null) { Log.Error($"ChunkManager::GetNextChunkToProvide - chunkCache == null here - why?? - Stacktrace: {System.Environment.StackTrace}"); // todo - find out why chunkCache would be null here, only seldomly __result = long.MaxValue; return false; } int num2 = 0; while (chunkCache != null && num2 < chunkPositionsCount) { long num3 = __instance.allChunkPositionsCopy[num2]; if (WorldChunkCache.extractClrIdx(num3) == 0 && !chunkCache.ContainsChunkSync(num3)) { __result = num3; return false; } num2++; } // chunkCache could be null here randomly - This line is where the NRE occurs. Extra null check added here if (chunkCache != null && chunkCache.ChunkProvider != null && chunkCache.ChunkProvider.GetRequestedChunks() != null) { HashSetList requestedChunks = chunkCache.ChunkProvider.GetRequestedChunks(); lock (requestedChunks.list) { if (requestedChunks.list.Count > 0) { long num4 = chunkCache.ChunkProvider.GetRequestedChunks().list[requestedChunks.list.Count - 1]; requestedChunks.Remove(num4); __result = num4; return false; } } } __result = long.MaxValue; // Don't process the original method return false; } }