public void ManageChunks() { if (currentChunk == null) { currentChunk = new Chunk() { coords = currentCoords }; } int N = Game.GameConfig.renderDistance; int xmin = (int)currentCoords.x - N; int ymin = (int)currentCoords.y - N; int zmin = (int)currentCoords.z - N; int xmax = (int)currentCoords.x + N; int ymax = (int)currentCoords.y + N; int zmax = (int)currentCoords.z + N; List<Vector3> results = new List<Vector3>(); for (int x = xmin; x <= xmax; x++) { for (int y = Mathf.Max(ymin, -x - zmax); y <= Mathf.Min(ymax, -x - zmin); y++) { int z = -x - y; results.Add(new Vector3(x, y, z)); } } /// This code has been created by the awesome JohnyCilhokla /// for an old version of Koxel. I (Pixel) edited to make it work /// for the latest version. /// Thank you so much, Johny! :D ❤ /// https://twitter.com/JohnyCilohokla foreach (Vector3 coords in results) { bool create = false; if (chunksStore.ContainsKey(coords)) { ChunkInfo chunkInfo = chunksStore[coords]; lock (unloadChunks) { if (Monitor.TryEnter(chunkInfo, 0)) { try { if (chunkInfo.chunk == null && chunkInfo.data == null || (!chunkInfo.isLoaded && !chunkInfo.isLoading)) { create = true; } else if (chunkInfo.isUnloading) // chunk is queued to be unloaded { chunkInfo.isUnloading = false; // remove unload flag unloadChunks.Remove(chunkInfo); // remove from the unload queue } } finally { Monitor.Exit(chunkInfo); } } } } else { create = true; } if (create) { ChunkData data; /// load the chunk data here /// this will save the main thread from doing that /// you could/should also generate the chunks here and save the generated data /// (then just setup the tiles/create objects in the main thread) if (Game.SaveManager.IsChunkSaved(coords)) { data = Game.SaveManager.LoadChunk(coords); } else { data = new ChunkData(coords); } ChunkInfo chunkInfo = new ChunkInfo(data); chunksStore[coords] = chunkInfo; // add to the chunk store map lock (loadChunks) { chunkInfo.isLoading = true; // add load flag loadChunks.Add(chunkInfo); // add to the load queue } } } List<Vector2> removals = new List<Vector2>(); var it = chunksStore.GetEnumerator(); while (it.MoveNext()) // loop through each chunk { Vector2 pos = it.Current.Key; ChunkInfo chunkInfo = it.Current.Value; if (Monitor.TryEnter(chunkInfo, 0)) { try { if ((chunkInfo.isLoaded && !chunkInfo.isUnloading) || (!chunkInfo.isLoaded && chunkInfo.isLoading)) { if (pos.x < xmin - 1 || pos.x > xmax + 1 || pos.y < Mathf.Max(ymin, -pos.x - zmax) - 1 || pos.y > Mathf.Min(ymax, -pos.x - zmin) + 1) // check if the chunk it outside of the "view" { if (chunkInfo.isLoaded) { lock (unloadChunks) { chunkInfo.isUnloading = true; // add unload flag unloadChunks.Add(chunkInfo); // add to the unload queue } } else { lock (loadChunks) { chunkInfo.isLoading = false; // remove load flag loadChunks.Remove(chunkInfo); // remove from the load queue } } } } if (chunkInfo.data == null && chunkInfo.chunk == null) { removals.Add(pos); } } finally { Monitor.Exit(chunkInfo); } } } foreach (Vector2 removal in removals) { chunksStore.Remove(removal); } }
public void RemoveChunk(Chunk chunk) { Chunks.Remove(chunk.coords); Game.ObjectPooler.PoolObject(chunk.gameObject); }