Пример #1
0
 public Index2 PointToMapPosition(Point pt)
 {
     if (Map == null)
         return new Index2();
     Index2 ind = new Index2((int)(pt.X / scale + offsetX), (int)(pt.Y / scale + offsetY));
     ind.NormalizeXY(new Index2(Map.Planet.Size.X * Chunk.CHUNKSIZE_X, Map.Planet.Size.Y * Chunk.CHUNKSIZE_Y));
     return ind;
 }
Пример #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, 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);
        }
Пример #3
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, 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);
        }
Пример #4
0
 /// <summary>
 /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich.
 /// </summary>
 /// <param name="index">Der zu normalisierende Index2</param>
 /// <param name="size">3D Size</param>
 public static Index2 NormalizeXY(Index2 index, Index3 size)
 {
     index.NormalizeXY(size);
     return(index);
 }
Пример #5
0
 /// <summary>
 /// Normalisiert den Wert von X und Y auf den angegebenen Grenzbereich.
 /// </summary>
 /// <param name="index">Der zu normalisierende Index2</param>
 /// <param name="size">3D Size</param>
 public static Index2 NormalizeXY(Index2 index,Index3 size)
 {
     index.NormalizeXY(size);
     return index;
 }
Пример #6
0
        private void RenderToBackBuffer()
        {
            int offsetX = (int)(this.offsetX / Chunk.CHUNKSIZE_X), offsetY = (int)(this.offsetY / Chunk.CHUNKSIZE_Y);
            BitmapData bmpData = backBuffer.LockBits(new Rectangle(new Point(), backBuffer.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            int[] emptyData = new int[Chunk.CHUNKSIZE_X * Chunk.CHUNKSIZE_Y];
            unsafe
            {
                int* ptr = (int*)bmpData.Scan0;
                for (int y = offsetY ; y < offsetY + sizeY; y++)
                {
                    for (int x = offsetX ; x < offsetX + sizeX; x++)
                    {
                        if ((y - offsetY) < 0 || (x - offsetX) < 0)
                            continue;
                        Index2 normalized = new Index2(x, y);
                        normalized.NormalizeXY(Map.Planet.Size);
                        int index = normalized.Y * Map.Planet.Size.X + normalized.X;
                        int offset = (y - offsetY) * Chunk.CHUNKSIZE_Y * backBuffer.Width + (x - offsetX) * Chunk.CHUNKSIZE_X;
                        if (Map.Chunks[index] == null)
                        {
                            CopyRegion(backBuffer, ptr, offset, Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y, emptyData);
                            continue;
                        }
                        int[] bmp = Map.Chunks[index].GetBitmapData();

                        if (bmp == null)
                            continue;

                        CopyRegion(backBuffer, ptr, offset, Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y, bmp);
                        //Chunk.CHUNKSIZE_X, Chunk.CHUNKSIZE_Y
                        index++;
                    }
                }
            }
            backBuffer.UnlockBits(bmpData);
        }
Пример #7
0
        void LoadViewRange(int offsetX, int offsetY, int sizeX, int sizeY)
        {
            for (int y = offsetY; y < offsetY + sizeY; y++)
            {
                for (int x = offsetX; x < offsetX + sizeX; x++)
                {

                    Index2 normalized = new Index2(x, y);
                    normalized.NormalizeXY(Map.Planet.Size);
                    int index = normalized.Y * Map.Planet.Size.X + normalized.X;
                    if (Map.Chunks[index] != null)
                        continue;

                    IChunk[] tempChunks = Map.Generator.GenerateChunk (BlockDefinitionManager.GetBlockDefinitions(), Map.Planet, normalized);
                    Map.Chunks[index] = new Chunk2D(tempChunks);
                    if (!IsHandleCreated)
                        return;

                }

            }
        }
Пример #8
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, Index2 index, Action<bool> successCallback)
        {
            // Planet resetten falls notwendig
            if (this.planet != planet)
                InitializePlanet(planet);

            if (planet == null)
            {
                if (successCallback != null) successCallback(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)
            {
                if (successCallback != null) successCallback(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);
                    chunkColumns[flatIndex] = null;
                    chunkColumn = null;
                }

                // Zweite Abbruchmöglichkeit
                if (token.IsCancellationRequested)
                {
                    if (successCallback != null) successCallback(false);
                    return;
                }

                // Neuen Chunk laden
                if (chunkColumn == null)
                {
                    chunkColumn = globalCache.Subscribe(planet.Id, new Index2(chunkColumnIndex));
                    chunkColumns[flatIndex] = chunkColumn;
                }

                // Dritte Abbruchmöglichkeit
                if (token.IsCancellationRequested)
                {
                    if (successCallback != null) successCallback(false);
                    return;
                }
            }

            if (successCallback != null) successCallback(true);
        }