private static Chunk CreateEmptyChunk() { var chunk = new Chunk(); for (var y = 1; y < Chunk.Size - 1; y++) for (var x = 1; x < Chunk.Size - 1; x++) chunk[x, y] = v0(PathTile.Default); return chunk; }
/// <summary> /// Obtains the <see cref="Chunk"/> with the specified index. /// If the chunk is already loaded, it is returned. /// Otherwise, it is loaded from <see cref="Storage"/>. /// </summary> /// <param name="index">Chunk index</param> /// <returns>The desired chunk. If the chunk could not be loaded, a new empty chunk is returned</returns> public async Task<IChunk> GetAsync(Point index) { // If chunk already loaded, return it immediately IChunk alreadyLoadedChunk; if (Chunks.TryGetValue(index, out alreadyLoadedChunk)) return alreadyLoadedChunk; // If chunk is already being loaded, await its loader task (do not start a second task) LoadingChunkToken loadingChunkToken; if (ChunksLoading.TryGetValue(index, out loadingChunkToken)) return await loadingChunkToken.LoaderTask; // Otherwise, begin loading the chunk var token = new LoadingChunkToken { Cancellation = new CancellationTokenSource() }; ChunksLoading.Add(index, token); IChunk chunk = null; try { token.LoaderTask = Storage.LoadAsync(index, token.Cancellation.Token); chunk = await token.LoaderTask; token.Cancellation.Token.ThrowIfCancellationRequested(); // Handle cancellation in case storage doesn't } catch (OperationCanceledException) { // Chunk loading was cancelled by an Unload(...) call, do nothing } catch { // Something else happened, throw throw; } if (chunk == null) { // If chunk loading fails, create an empty chunk // (empty chunks won't be saved) chunk = new Chunk(); } else { // The storage might have its own caching strategies and // reuse chunks it has once loaded, so we need to work with // a copy of the loaded chunk. chunk = chunk.Clone(); } ChunksLoading.Remove(index); Chunks.Add(index, chunk); return chunk; }
private Chunk(Chunk chunk) { _tiles = chunk._tiles.ToArray(); _tileMetadata = chunk._tileMetadata.ToArray(); HasChanged = false; }