/// <summary>
        /// Adiciona novo chunk no cache de memoria
        /// </summary>
        /// <param name="chunk">Chunk a ser adiciona no cache de memoria</param>
        /// <returns>Retorna ID na memoria gerado para o chunk ou -1 caso não consiga adicionar o id de memoria do chunk é atualizado no objeto caso tenha sucesso</returns>
        public long AddChunk(Data.ChunkData chunk)
        {
            if (chunk == null)
            {
                return(-1);
            }

            int positionHashKey = chunk.Position.GetHashCode();
            //busca ou cria index para o hash
            var  positionIndexedChunks = this.PositionIndexedChunks.GetOrAdd(positionHashKey, new List <Data.ChunkData>());
            long MemoryID = -1;

            //incrementa ID
            lock (LockChunkMemoryIDIncrement)
            {
                LastChunkMemoryID++;
                MemoryID = LastChunkMemoryID;
            }

            var hashKey = MemoryID.GetHashCode();
            //Tenta adicionar na memoria e no hashIndex
            var chunks = this.ChunksByMemoryID.GetOrAdd(hashKey, new List <Data.ChunkData>());

            lock (chunks)
            {
                chunks.Add(chunk);
            }

            chunk.MemoryID = MemoryID;
            lock (positionIndexedChunks)
            {
                //adiciona no index
                positionIndexedChunks.Add(chunk);
            }

            return(MemoryID);
        }
        private void LoadChunk(byte[] data)
        {
            try
            {
                WaitingResponse = false;
                bool           isPart2 = false;
                Data.ChunkData chunk   = null;
                if (!Data.ChunkData.TryDeserialize(data,
                                                   ref chunk,
                                                   (position) =>
                {
                    isPart2 = true;
                    return(GameApplication.Current.Terrain.ChunkByPosition(position, false));
                }) ||
                    chunk == null)
                {
                    SendFailedMessage();
                    return;
                }

                if (chunk.MemoryID == -1 && GameApplication.Current.Terrain.AddChunk(chunk) == -1)
                {
                    SendFailedMessage();
                    return;
                }
                SendSucessMessage();
                if (isPart2 && !IsTerrainStartPoint)
                {
                    RequestEnded = true;
                }
            }
            catch (Exception)
            {
                SendFailedMessage();
            }
        }