コード例 #1
0
ファイル: ChunkColumn.cs プロジェクト: reicheltp/octoawesome
 /// <summary>
 /// Erzeugt eine neue Instanz einer ChunkColumn.
 /// </summary>
 /// <param name="chunks">Die Chunks für die Säule</param>
 /// <param name="planet">Der Index des Planeten</param>
 /// <param name="columnIndex">Die Position der Säule</param>
 public ChunkColumn(IChunk[] chunks, int planet, Index2 columnIndex)
     : this()
 {
     Planet = planet;
     Chunks = chunks;
     Index = columnIndex;
 }
コード例 #2
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;
 }
コード例 #3
0
        /// <summary>
        /// Gibt einen abonnierten Chunk wieder frei.
        /// </summary>
        /// <param name="planet">Die Id des Planeten</param>
        /// <param name="position">Die Position des freizugebenden Chunks</param>
        public void Release(int planet, Index2 position)
        {
            CacheItem cacheItem = null;

            lock (lockObject)
            {
                if (!cache.TryGetValue(new Index3(position, planet), out cacheItem))
                {
                    throw new NotSupportedException("Kein Chunk für Position in Cache");
                }

                cacheItem.References--;
            }
        }
コード例 #4
0
 /// <summary>
 /// Setzt den Zentrums-Chunk für diesen lokalen Cache.
 /// </summary>
 /// <param name="planet">Der Planet, auf dem sich der Chunk befindet</param>
 /// <param name="index">Die Koordinaten an der sich der Chunk befindet</param>
 /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param>
 public void SetCenter(IPlanet planet, Index2 index, Action <bool> successCallback = null)
 {
     if (_loadingTask != null && !_loadingTask.IsCompleted)
     {
         _cancellationToken.Cancel();
         _cancellationToken = new CancellationTokenSource();
         _loadingTask       = _loadingTask.ContinueWith(_ => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback));
     }
     else
     {
         _cancellationToken = new CancellationTokenSource();
         _loadingTask       = Task.Factory.StartNew(() => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback));
     }
 }
コード例 #5
0
        /// <summary>
        /// Liefert den Chunk an der angegebenen Chunk-Koordinate zurück.
        /// </summary>
        /// <param name="x">X Koordinate</param>
        /// <param name="y">Y Koordinate</param>
        /// <param name="z">Z Koordinate</param>
        /// <returns>Instanz des Chunks</returns>
        public IChunk GetChunk(int x, int y, int z)
        {
            if (Planet == null || z < 0 || z >= Planet.Size.Z)
                return null;

            x = Index2.NormalizeAxis(x, Planet.Size.X);
            y = Index2.NormalizeAxis(y, Planet.Size.Y);

            IChunkColumn chunkColumn = chunkColumns[FlatIndex(x, y)];

            if (chunkColumn != null && chunkColumn.Index.X == x && chunkColumn.Index.Y == y)
                return chunkColumn.Chunks[z];

            return null;
        }
コード例 #6
0
        /// <summary>
        /// Setzt den Zentrums-Chunk für diesen lokalen Cache.
        /// </summary>
        /// <param name="planet">Der Planet, auf dem sich der Chunk befindet</param>
        /// <param name="index">Die Koordinaten an der sich der Chunk befindet</param>
        /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param>
        public bool SetCenter(Index2 index, Action<bool> successCallback = null)
        {
            using (taskSemaphore.Wait())
            {
                var callerName = new StackFrame(1).GetMethod().Name;
                logger.Debug($"Set Center from {callerName}");
                CenterPosition = index;

                if (_loadingTask != null && !_loadingTask.IsCompleted)
                {
                    logger.Debug("Continue with task on index " + index);
                    _loadingTask = _loadingTask.ContinueWith(_ => InternalSetCenter(_cancellationToken.Token, index, successCallback));
                }
                else
                {
                    logger.Debug("New task on index " + index);
                    _cancellationToken?.Cancel();
                    _cancellationToken?.Dispose();
                    _cancellationToken = new CancellationTokenSource();
                    _loadingTask = Task.Run(() => InternalSetCenter(_cancellationToken.Token, index, successCallback));
                }
            }
            return true;
        }
コード例 #7
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten Z-Achse.
 /// </summary>
 /// <param name="z">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceZ(int z, int size)
 {
     return(Index2.ShortestDistanceOnAxis(Z, z, size));
 }
コード例 #8
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die Z-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">Maximalwert für Z</param>
 public void NormalizeZ(int size)
 {
     Z = Index2.NormalizeAxis(Z, size);
 }
コード例 #9
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten X-Achse.
 /// </summary>
 /// <param name="x">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceX(int x, int size)
 {
     return(Index2.ShortestDistanceOnAxis(X, x, size));
 }
コード例 #10
0
        /// <summary>
        /// Gibt einen abonnierten Chunk wieder frei.
        /// </summary>
        /// <param name="planet">Die Id des Planeten</param>
        /// <param name="position">Die Position des freizugebenden Chunks</param>
        public void Release(int planet, Index2 position)
        {
            CacheItem cacheItem = null;
            lock (lockObject)
            {
                if (!cache.TryGetValue(new Index3(position, planet), out cacheItem))
                {
                    throw new NotSupportedException("Kein Chunk für Position in Cache");
                }

                cacheItem.References--;
            }
        }
コード例 #11
0
ファイル: ChunkColumn.cs プロジェクト: fnawratil/octoawesome
        /// <summary>
        /// Deserialisiert die Chunksäule aus dem angegebenen Stream.
        /// </summary>
        /// <param name="stream">Quellstream</param>
        /// <param name="definitionManager">Der verwendete DefinitionManager</param>
        /// <param name="columnIndex">Die Position der Säule</param>
        /// <param name="planetId">Der Index des Planeten</param>
        public void Deserialize(BinaryReader reader, IDefinitionManager definitionManager)
        {
            bool longIndex = reader.ReadByte() > 0;

            // Phase 1 (Column Meta: Heightmap, populated, chunkcount)
            Chunks = new Chunk[reader.ReadByte()]; // Chunk Count

            Populated = reader.ReadBoolean();      // Populated

            Index  = new Index2(reader.ReadInt32(), reader.ReadInt32());
            Planet = reader.ReadInt32();

            for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap
            {
                for (int x = 0; x < Chunk.CHUNKSIZE_X; x++)
                {
                    Heights[x, y] = reader.ReadUInt16();
                }
            }

            int[] counter = new int[Chunks.Length];

            for (int i = 0; i < Chunks.Length; i++) // ChangeCounter
            {
                counter[i] = reader.ReadInt32();
            }

            // Phase 2 (Block Definitionen)
            List <IDefinition>          types = new List <IDefinition>();
            Dictionary <ushort, ushort> map   = new Dictionary <ushort, ushort>();

            int typecount = longIndex ? reader.ReadUInt16() : reader.ReadByte();

            for (int i = 0; i < typecount; i++)
            {
                string        typeName        = reader.ReadString();
                IDefinition[] definitions     = definitionManager.GetDefinitions().ToArray();
                var           blockDefinition = definitions.FirstOrDefault(d => d.GetType().FullName == typeName);
                types.Add(blockDefinition);

                map.Add((ushort)types.Count, (ushort)(Array.IndexOf(definitions, blockDefinition) + 1));
            }

            // Phase 3 (Chunk Infos)
            for (int c = 0; c < Chunks.Length; c++)
            {
                IChunk chunk = Chunks[c] = new Chunk(new Index3(Index, c), Planet);
                chunk.Changed += OnChunkChanged;
                chunk.SetColumn(this);

                for (int i = 0; i < chunk.Blocks.Length; i++)
                {
                    ushort typeIndex = longIndex ? reader.ReadUInt16() : reader.ReadByte();
                    chunk.MetaData[i] = 0;
                    if (typeIndex > 0)
                    {
                        chunk.Blocks[i] = map[typeIndex];

                        var definition = (IBlockDefinition)definitionManager.GetDefinitionByIndex(map[typeIndex]);

                        if (definition.HasMetaData)
                        {
                            chunk.MetaData[i] = reader.ReadInt32();
                        }
                    }
                }
                chunk.ChangeCounter = counter[c];
            }

            //Entities lesen
            var count = reader.ReadInt32();

            for (int i = 0; i < count; i++)
            {
                var name   = reader.ReadString();
                var length = reader.ReadInt32();

                byte[] buffer = new byte[length];
                reader.Read(buffer, 0, length);

                try
                {
                    var type = Type.GetType(name);

                    if (type == null)
                    {
                        continue;
                    }

                    Entity entity = (Entity)Activator.CreateInstance(type);

                    using (MemoryStream memorystream = new MemoryStream(buffer))
                    {
                        using (BinaryReader componentbinarystream = new BinaryReader(memorystream))
                        {
                            entity.Deserialize(componentbinarystream, definitionManager);
                        }
                    }

                    Entities.Add(entity);
                }
                catch (Exception)
                {
                }
            }
        }
コード例 #12
0
ファイル: ChunkColumn.cs プロジェクト: reicheltp/octoawesome
        /// <summary>
        /// Deserialisiert die Chunksäule aus dem angegebenen Stream.
        /// </summary>
        /// <param name="stream">Quellstream</param>
        /// <param name="definitionManager">Der verwendete DefinitionManager</param>
        /// <param name="columnIndex">Die Position der Säule</param>
        /// <param name="planetId">Der Index des Planeten</param>
        public void Deserialize(Stream stream, IDefinitionManager definitionManager, int planetId, Index2 columnIndex)
        {
            using (BinaryReader br = new BinaryReader(stream))
            {
                bool longIndex = br.ReadByte() > 0;

                // Phase 1 (Column Meta: Heightmap, populated, chunkcount)
                Chunks = new Chunk[br.ReadByte()]; // Chunk Count
                Planet = planetId;
                Index = columnIndex;

                Populated = br.ReadBoolean(); // Populated
                for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap
                    for (int x = 0; x < Chunk.CHUNKSIZE_X; x++)
                        Heights[x, y] = br.ReadUInt16();

                int[] counter = new int[Chunks.Length];
                for (int i = 0; i < Chunks.Length; i++) // ChangeCounter
                    counter[i] = br.ReadInt32();

                // Phase 2 (Block Definitionen)
                List<IBlockDefinition> types = new List<IBlockDefinition>();
                Dictionary<ushort, ushort> map = new Dictionary<ushort, ushort>();

                int typecount = longIndex ? br.ReadUInt16() : br.ReadByte();
                for (int i = 0; i < typecount; i++)
                {
                    string typeName = br.ReadString();
                    IBlockDefinition[] definitions = definitionManager.GetBlockDefinitions().ToArray();
                    var blockDefinition = definitions.FirstOrDefault(d => d.GetType().FullName == typeName);
                    types.Add(blockDefinition);

                    map.Add((ushort)types.Count, (ushort)(Array.IndexOf(definitions, blockDefinition) + 1));
                }

                // Phase 3 (Chunk Infos)
                for (int c = 0; c < Chunks.Length; c++)
                {
                    IChunk chunk = Chunks[c] = new Chunk(new Index3(columnIndex, c), planetId);
                    for (int i = 0; i < chunk.Blocks.Length; i++)
                    {
                        ushort typeIndex = longIndex ? br.ReadUInt16() : br.ReadByte();
                        chunk.MetaData[i] = 0;
                        if (typeIndex > 0)
                        {
                            chunk.Blocks[i] = map[typeIndex];

                            var definition = definitionManager.GetBlockDefinitionByIndex(map[typeIndex]);
                            if (definition.HasMetaData)
                                chunk.MetaData[i] = br.ReadInt32();
                        }
                    }
                    chunk.ChangeCounter = counter[c];
                }
            }
        }
コード例 #13
0
ファイル: Index2.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Normalisiert die Y-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Größe (Y-Anzeil wird genommen)</param>
 public void NormalizeY(Index2 size)
 {
     NormalizeY(size.Y);
 }
コード例 #14
0
ファイル: Index3.cs プロジェクト: marsat02/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen.
 /// </summary>
 /// <param name="destination">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public Index3 ShortestDistanceXY(Index3 destination, Index2 size)
 => new Index3(
     ShortestDistanceX(destination.X, size.X),
     ShortestDistanceY(destination.Y, size.Y),
     destination.Z - Z);
コード例 #15
0
 public bool IsChunkLoaded(int planet, Index2 position)
 => cache.ContainsKey(new Index3(position, planet));
コード例 #16
0
ファイル: Index3.cs プロジェクト: marsat02/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten Y-Achse.
 /// </summary>
 /// <param name="y">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceY(int y, int size)
 => Index2.ShortestDistanceOnAxis(Y, y, size);
コード例 #17
0
ファイル: Index3.cs プロジェクト: marsat02/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten Z-Achse.
 /// </summary>
 /// <param name="z">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceZ(int z, int size)
 => Index2.ShortestDistanceOnAxis(Z, z, size);
コード例 #18
0
ファイル: Index3.cs プロジェクト: marsat02/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten X-Achse.
 /// </summary>
 /// <param name="x">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceX(int x, int size)
 => Index2.ShortestDistanceOnAxis(X, x, size);
コード例 #19
0
ファイル: Index3.cs プロジェクト: marsat02/octoawesome
 /// <summary>
 /// Normalisiert die X- und Y-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">Maximalwert für X und Y</param>
 public void NormalizeXY(Index2 size)
 => NormalizeXY(size.X, size.Y);
コード例 #20
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);
        }
コード例 #21
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Initialisierung
 /// </summary>
 /// <param name="index">2D-Basis</param>
 /// <param name="z">Z-Anteil</param>
 public Index3(Index2 index, int z) : this(index.X, index.Y, z)
 {
 }
コード例 #22
0
ファイル: Index2.cs プロジェクト: reicheltp/octoawesome
 /// <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;
 }
コード例 #23
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die X-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Size</param>
 public void NormalizeX(Index2 size)
 {
     NormalizeX(size.X);
 }
コード例 #24
0
ファイル: Index3.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Normalisiert die X-, Y- und Z-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Size</param>
 /// <param name="z">Z-Anteil</param>
 public void NormalizeXYZ(Index2 size, int z)
 {
     NormalizeXYZ(size.X, size.Y, z);
 }
コード例 #25
0
ファイル: Index2.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Normalisiert die X-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Größe (X-Anzeil wird genommen)</param>
 public void NormalizeX(Index2 size)
 {
     NormalizeX(size.X);
 }
コード例 #26
0
ファイル: Index3.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen.
 /// </summary>
 /// <param name="destination">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public Index3 ShortestDistanceXY(Index3 destination, Index2 size)
 {
     return new Index3(
         ShortestDistanceX(destination.X, size.X),
         ShortestDistanceY(destination.Y, size.Y),
         destination.Z - Z);
 }
コード例 #27
0
 /// <summary>
 /// Liefert den Chunk, sofern geladen.
 /// </summary>
 /// <param name="planet">Die Id des Planeten</param>
 /// <param name="position">Die Position des zurückzugebenden Chunks</param>
 /// <returns>Chunk Instanz oder null, falls nicht geladen</returns>
 public IChunkColumn Peek(int planet, Index2 position)
 {
     CacheItem cacheItem = null;
     if (cache.TryGetValue(new Index3(position, planet), out cacheItem))
     {
         return cacheItem.ChunkColumn;
     }
     return null;
 }
コード例 #28
0
ファイル: Index3.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Initialisierung
 /// </summary>
 /// <param name="index">2D-Basis</param>
 /// <param name="z">Z-Anteil</param>
 public Index3(Index2 index, int z) : this(index.X, index.Y, z) { }
コード例 #29
0
        /// <summary>
        /// Abonniert einen Chunk.
        /// </summary>
        /// <param name="planet">Die Id des Planeten</param>
        /// <param name="position">Position des Chunks</param>
        /// <returns></returns>
        public IChunkColumn Subscribe(int planet, Index2 position)
        {
            CacheItem cacheItem = null;

            lock (lockObject)
            {
                if (!cache.TryGetValue(new Index3(position, planet), out cacheItem))
                {
                    cacheItem = new CacheItem()
                    {
                        References = 0,
                        ChunkColumn = null,
                    };

                    cache.Add(new Index3(position, planet), cacheItem);
                }

                cacheItem.References++;
            }

            lock (cacheItem)
            {
                if (cacheItem.ChunkColumn == null)
                {
                    cacheItem.ChunkColumn = loadDelegate(planet, position);
                    cacheItem.SavedChangeCounter = cacheItem.ChunkColumn.Chunks.Select(c => c.ChangeCounter).ToArray();
                }
            }

            return cacheItem.ChunkColumn;
        }
コード例 #30
0
 /// <summary>
 /// Erzeugt eine neue Instanz einer ChunkColumn.
 /// </summary>
 /// <param name="chunks">Die Chunks für die Säule</param>
 /// <param name="planet">Der Index des Planeten</param>
 /// <param name="columnIndex">Die Position der Säule</param>
 public ChunkColumn(IChunk[] chunks, int planet, Index2 columnIndex) : this()
 {
     Planet = planet;
     Chunks = chunks;
     Index  = columnIndex;
 }
コード例 #31
0
ファイル: Index2.cs プロジェクト: nreusch/octoawesome
 /// <summary>
 /// Initialisierung
 /// </summary>
 /// <param name="value">Initialwerte</param>
 public Index2(Index2 value) : this(value.X, value.Y)
 {
 }
コード例 #32
0
        /// <summary>
        /// Deserialisiert die Chunksäule aus dem angegebenen Stream.
        /// </summary>
        /// <param name="stream">Quellstream</param>
        /// <param name="definitionManager">Der verwendete DefinitionManager</param>
        /// <param name="columnIndex">Die Position der Säule</param>
        /// <param name="planetId">Der Index des Planeten</param>
        public void Deserialize(Stream stream, IDefinitionManager definitionManager, int planetId, Index2 columnIndex)
        {
            using (BinaryReader br = new BinaryReader(stream))
            {
                bool longIndex = br.ReadByte() > 0;

                // Phase 1 (Column Meta: Heightmap, populated, chunkcount)
                Chunks = new Chunk[br.ReadByte()]; // Chunk Count
                Planet = planetId;
                Index  = columnIndex;

                Populated = br.ReadBoolean();               // Populated
                for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap
                {
                    for (int x = 0; x < Chunk.CHUNKSIZE_X; x++)
                    {
                        Heights[x, y] = br.ReadUInt16();
                    }
                }

                int[] counter = new int[Chunks.Length];
                for (int i = 0; i < Chunks.Length; i++) // ChangeCounter
                {
                    counter[i] = br.ReadInt32();
                }

                // Phase 2 (Block Definitionen)
                List <IBlockDefinition>     types = new List <IBlockDefinition>();
                Dictionary <ushort, ushort> map   = new Dictionary <ushort, ushort>();

                int typecount = longIndex ? br.ReadUInt16() : br.ReadByte();
                for (int i = 0; i < typecount; i++)
                {
                    string             typeName    = br.ReadString();
                    IBlockDefinition[] definitions = definitionManager.GetBlockDefinitions().ToArray();
                    var blockDefinition            = definitions.FirstOrDefault(d => d.GetType().FullName == typeName);
                    types.Add(blockDefinition);

                    map.Add((ushort)types.Count, (ushort)(Array.IndexOf(definitions, blockDefinition) + 1));
                }

                // Phase 3 (Chunk Infos)
                for (int c = 0; c < Chunks.Length; c++)
                {
                    IChunk chunk = Chunks[c] = new Chunk(new Index3(columnIndex, c), planetId);
                    for (int i = 0; i < chunk.Blocks.Length; i++)
                    {
                        ushort typeIndex = longIndex ? br.ReadUInt16() : br.ReadByte();
                        chunk.MetaData[i] = 0;
                        if (typeIndex > 0)
                        {
                            chunk.Blocks[i] = map[typeIndex];

                            var definition = definitionManager.GetBlockDefinitionByIndex(map[typeIndex]);
                            if (definition.HasMetaData)
                            {
                                chunk.MetaData[i] = br.ReadInt32();
                            }
                        }
                    }
                    chunk.ChangeCounter = counter[c];
                }
            }
        }
コード例 #33
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die X-, Y- und Z-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Size</param>
 /// <param name="z">Z-Anteil</param>
 public void NormalizeXYZ(Index2 size, int z)
 {
     NormalizeXYZ(size.X, size.Y, z);
 }
コード例 #34
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die Y-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">2D-Size</param>
 public void NormalizeY(Index2 size)
 {
     NormalizeY(size.Y);
 }
コード例 #35
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf einer normalisierten Y-Achse.
 /// </summary>
 /// <param name="y">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public int ShortestDistanceY(int y, int size)
 {
     return(Index2.ShortestDistanceOnAxis(Y, y, size));
 }
コード例 #36
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;

                }

            }
        }
コード例 #37
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen.
 /// </summary>
 /// <param name="destination">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public Index2 ShortestDistanceXY(Index2 destination, Index2 size)
 {
     return(new Index2(
                ShortestDistanceX(destination.X, size.X),
                ShortestDistanceY(destination.Y, size.Y)));
 }
コード例 #38
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);
        }
コード例 #39
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die X-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">Maximalwert für X</param>
 public void NormalizeX(int size)
 {
     X = Index2.NormalizeAxis(X, size);
 }
コード例 #40
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);
        }
コード例 #41
0
ファイル: Index3.cs プロジェクト: BlackOrca/octoawesome
 /// <summary>
 /// Normalisiert die Y-Achse auf die angegebene Größe.
 /// </summary>
 /// <param name="size">Maximalwert für Y</param>
 public void NormalizeY(int size)
 {
     Y = Index2.NormalizeAxis(Y, size);
 }
コード例 #42
0
        /// <summary>
        /// Deserialisiert die Chunksäule aus dem angegebenen Stream.
        /// </summary>
        /// <param name="stream">Quellstream</param>
        /// <param name="definitionManager">Der verwendete DefinitionManager</param>
        /// <param name="columnIndex">Die Position der Säule</param>
        /// <param name="planetId">Der Index des Planeten</param>
        public void Deserialize(BinaryReader reader)
        {
            var longIndex = reader.ReadByte() > 0;

            // Phase 1 (Column Meta: Heightmap, populated, chunkcount)
            Chunks = new Chunk[reader.ReadByte()]; // Chunk Count

            Populated = reader.ReadBoolean();      // Populated

            Index = new Index2(reader.ReadInt32(), reader.ReadInt32());
            int planetId = reader.ReadInt32();

            var resManager = TypeContainer.Get <IResourceManager>();

            Planet = resManager.GetPlanet(planetId);

            for (var y = 0; y < Chunk.CHUNKSIZE_Y; y++) // Heightmap
            {
                for (var x = 0; x < Chunk.CHUNKSIZE_X; x++)
                {
                    Heights[x, y] = reader.ReadUInt16();
                }
            }


            // Phase 2 (Block Definitionen)
            var types = new List <IDefinition>();
            var map   = new Dictionary <ushort, ushort>();

            int typecount = longIndex ? reader.ReadUInt16() : reader.ReadByte();

            for (var i = 0; i < typecount; i++)
            {
                var           typeName        = reader.ReadString();
                IDefinition[] definitions     = DefinitionManager.GetDefinitions().ToArray();
                IDefinition   blockDefinition = definitions.FirstOrDefault(d => d.GetType().FullName == typeName);
                types.Add(blockDefinition);

                map.Add((ushort)types.Count, (ushort)(Array.IndexOf(definitions, blockDefinition) + 1));
            }

            // Phase 3 (Chunk Infos)
            for (var c = 0; c < Chunks.Length; c++)
            {
                IChunk chunk = Chunks[c] = new Chunk(new Index3(Index, c), Planet);
                chunk.Changed += OnChunkChanged;
                chunk.SetColumn(this);

                for (var i = 0; i < chunk.Blocks.Length; i++)
                {
                    var typeIndex = longIndex ? reader.ReadUInt16() : reader.ReadByte();
                    chunk.MetaData[i] = 0;
                    if (typeIndex > 0)
                    {
                        chunk.Blocks[i] = map[typeIndex];

                        var definition = (IBlockDefinition)DefinitionManager.GetDefinitionByIndex(map[typeIndex]);

                        if (definition.HasMetaData)
                        {
                            chunk.MetaData[i] = reader.ReadInt32();
                        }
                    }
                }
            }
        }
コード例 #43
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);
        }
コード例 #44
0
ファイル: Index2.cs プロジェクト: BlackOrca/octoawesome
 /// <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);
 }
コード例 #45
0
ファイル: Index2.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Ermittelt die kürzeste Entfernung zum Ziel auf den normalisierten Achsen.
 /// </summary>
 /// <param name="destination">Ziel</param>
 /// <param name="size">Normalisierungsgröße</param>
 /// <returns>Entfernung</returns>
 public Index2 ShortestDistanceXY(Index2 destination, Index2 size)
 {
     return new Index2(
         ShortestDistanceX(destination.X, size.X), 
         ShortestDistanceY(destination.Y, size.Y));
 }
コード例 #46
0
ファイル: Index2.cs プロジェクト: RapidHelmus/octoawesome
 /// <summary>
 /// Initialisierung
 /// </summary>
 /// <param name="value">Initialwerte</param>
 public Index2(Index2 value) : this(value.X, value.Y) {}
コード例 #47
0
 /// <summary>
 /// Setzt den Zentrums-Chunk für diesen lokalen Cache.
 /// </summary>
 /// <param name="planetid">ID des Planet, auf dem sich der Chunk befindet</param>
 /// <param name="index">Die Koordinaten an der sich der Chunk befindet</param>
 /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param>
 public bool SetCenter(int planetid, Index2 index, Action <bool> successCallback = null)
 => SetCenter(globalCache.GetPlanet(planetid), index, successCallback);
コード例 #48
0
 /// <summary>
 /// Setzt den Zentrums-Chunk für diesen lokalen Cache.
 /// </summary>
 /// <param name="planet">Der Planet, auf dem sich der Chunk befindet</param>
 /// <param name="index">Die Koordinaten an der sich der Chunk befindet</param>
 /// <param name="successCallback">Routine die Aufgerufen werden soll, falls das setzen erfolgreich war oder nicht</param>
 public void SetCenter(IPlanet planet, Index2 index, Action<bool> successCallback = null)
 {
     if (_loadingTask != null && !_loadingTask.IsCompleted)
     {
         _cancellationToken.Cancel();
         _cancellationToken = new CancellationTokenSource();
         _loadingTask = _loadingTask.ContinueWith(_ => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback));
     }
     else
     {
         _cancellationToken = new CancellationTokenSource();
         _loadingTask = Task.Factory.StartNew(() => InternalSetCenter(_cancellationToken.Token, planet, index, successCallback));
     }
 }