/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, Index2 index, Action<bool> successCallback) { if (Planet == null) { successCallback?.Invoke(true); return; } List<Index2> requiredChunkColumns = new List<Index2>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Index2 local = new Index2(index.X + x, index.Y + y); local.NormalizeXY(Planet.Size); requiredChunkColumns.Add(local); } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } foreach (var chunkColumnIndex in requiredChunkColumns .OrderBy(c => index.ShortestDistanceXY(c, new Index2(Planet.Size)) .LengthSquared())) { int localX = chunkColumnIndex.X & mask; int localY = chunkColumnIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunkColumn chunkColumn = chunkColumns[flatIndex]; // Alten Chunk entfernen, falls notwendig using (semaphore.Wait()) { if (chunkColumn != null && chunkColumn.Index != chunkColumnIndex) { //logger.Debug($"Remove Chunk: {chunkColumn.Index}, new: {chunkColumnIndex}"); globalCache.Release(chunkColumn.Index); chunkColumns[flatIndex] = null; chunkColumn = null; } } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } using (semaphore.Wait()) { // Neuen Chunk laden if (chunkColumn == null) { chunkColumn = globalCache.Subscribe(new Index2(chunkColumnIndex)); if (chunkColumn?.Index != chunkColumnIndex) logger.Error($"Loaded Chunk Index: {chunkColumn?.Index}, wanted: {chunkColumnIndex} "); if (chunkColumns[flatIndex] != null) logger.Error($"Chunk in Array!!: {flatIndex}, on index: {chunkColumns[flatIndex].Index} "); chunkColumns[flatIndex] = chunkColumn; if (chunkColumn == null) { successCallback?.Invoke(false); return; } } } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } } successCallback?.Invoke(true); }
/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, IPlanet planet, Index2 index, Action <bool> successCallback) { if (planet == null) { successCallback?.Invoke(true); return; } List <Index2> requiredChunkColumns = new List <Index2>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { Index2 local = new Index2(index.X + x, index.Y + y); local.NormalizeXY(planet.Size); requiredChunkColumns.Add(local); } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } foreach (var chunkColumnIndex in requiredChunkColumns .OrderBy(c => index.ShortestDistanceXY(c, new Index2(planet.Size)) .LengthSquared())) { int localX = chunkColumnIndex.X & mask; int localY = chunkColumnIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunkColumn chunkColumn = chunkColumns[flatIndex]; // Alten Chunk entfernen, falls notwendig if (chunkColumn != null && chunkColumn.Index != chunkColumnIndex) { globalCache.Release(planet.Id, chunkColumn.Index, IsPassive); chunkColumns[flatIndex] = null; chunkColumn = null; } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } // Neuen Chunk laden if (chunkColumn == null) { chunkColumn = globalCache.Subscribe(planet.Id, new Index2(chunkColumnIndex), IsPassive); chunkColumns[flatIndex] = chunkColumn; if (chunkColumn == null) { successCallback?.Invoke(false); return; } } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { successCallback?.Invoke(false); return; } } successCallback?.Invoke(true); }
/// <summary> /// Interne Methode, in der der zentrale Chunk gesetzt wird. Die Chunks um den Zentrumschunk werden auch nachgeladen falls nötig /// </summary> /// <param name="token">Token, um zu prüfen, ob die aktualisierung abgeborchen werden soll</param> /// <param name="planet">Der Planet, auf dem die Chunks aktualisiert werden sollen</param> /// <param name="index">Der ins Zentrum zu setzende Chunk</param> /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param> private void InternalSetCenter(CancellationToken token, IPlanet planet, Index3 index, Action <bool> successCallback) { // Planet resetten falls notwendig if (this.planet != planet) { InitializePlanet(planet); } if (planet == null) { if (successCallback != null) { successCallback(true); } return; } List <Index3> requiredChunks = new List <Index3>(); for (int x = -range; x <= range; x++) { for (int y = -range; y <= range; y++) { for (int z = 0; z < planet.Size.Z; z++) { Index3 local = new Index3(index.X + x, index.Y + y, z); local.NormalizeXY(planet.Size); requiredChunks.Add(local); } } } // Erste Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) { successCallback(false); } return; } foreach (var chunkIndex in requiredChunks.OrderBy(c => index.ShortestDistanceXYZ(c, planet.Size).LengthSquared())) { int localX = chunkIndex.X & mask; int localY = chunkIndex.Y & mask; int flatIndex = FlatIndex(localX, localY); IChunk chunk = chunks[flatIndex][chunkIndex.Z]; // Alten Chunk entfernen, falls notwendig if (chunk != null && chunk.Index != chunkIndex) { globalCache.Release(new PlanetIndex3(planet.Id, chunk.Index), writable); chunks[flatIndex][chunkIndex.Z] = null; chunk = null; } // Zweite Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) { successCallback(false); } return; } // Neuen Chunk laden if (chunk == null) { chunk = globalCache.Subscribe(new PlanetIndex3(planet.Id, chunkIndex), writable); chunks[flatIndex][chunkIndex.Z] = chunk; } // Dritte Abbruchmöglichkeit if (token.IsCancellationRequested) { if (successCallback != null) { successCallback(false); } return; } } if (successCallback != null) { successCallback(true); } }