/// <summary>
        /// Normalisiert den ChunkIndex auf die gegebenen Limits.
        /// </summary>
        /// <param name="limit"></param>
        public void NormalizeChunkIndexXY(Index3 limit)
        {
            Index3 index = ChunkIndex;

            index.NormalizeXY(limit);
            ChunkIndex = index;
        }
Exemple #2
0
        /// <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);
            }
        }
        /// <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);
        }