Пример #1
0
 public void UnloadEntities(ChunkCoordinates coordinates)
 {
     foreach (var entity in Entities.ToArray())
     {
         if (new ChunkCoordinates(entity.Value.KnownPosition).Equals(coordinates))
         {
             Remove(entity.Value.UUID);
         }
     }
 }
Пример #2
0
        public ChunkData(ChunkCoordinates coordinates)
        {
            Coordinates = coordinates;
            var availableStages = Enum.GetValues(typeof(RenderStage));

            _stages = new ChunkRenderStage[availableStages.Length];


            Interlocked.Increment(ref _instances);
        }
Пример #3
0
        public IChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            IChunkColumn c = new ChunkColumn()
            {
                X = chunkCoordinates.X,
                Z = chunkCoordinates.Z
            };

            for (int x = 0; x < ChunkColumn.ChunkWidth; x++)
            {
                for (int z = 0; z < ChunkColumn.ChunkDepth; z++)
                {
                    for (int y = 0; y < ChunkColumn.ChunkHeight; y++)
                    {
                        if (c.X == 0 && c.Z == 0)
                        {
                            IBlockState block;
                            switch (y >> 4)
                            {
                            case 0:
                                block = _dirt;
                                break;

                            case 1:
                                block = _stone;
                                break;

                            case 2:
                                block = _cobble;
                                break;

                            case 3:
                                block = _grass;
                                break;

                            //case 4:
                            //    break;
                            default:
                                continue;
                            }

                            c.SetBlockState(x, y, z, block);
                        }
                        else
                        {
                            //c.SetBlockState(x, y, z, _air);
                        }

                        c.SetSkyLight(x, y, z, 15);
                    }
                    c.SetHeight(x, z, 0);
                }
            }
            return(c);
        }
Пример #4
0
        public virtual ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates, bool cacheOnly = false)
        {
            var chunk = WorldProvider.GenerateChunkColumn(chunkCoordinates, cacheOnly);

            if (chunk != null)
            {
                Level.EventDispatcher.DispatchEvent(new ChunkGeneratedEvent(chunkCoordinates, chunk, Level));
            }

            return(chunk);
        }
Пример #5
0
 internal void SetChunkData(ChunkCoordinates coords, AnvilRegionHeaderChunkData data)
 {
     //if (_chunkLocations.ContainsKey(coords))
     //{
     _chunkLocations[coords] = data;
     //}
     //else
     //{
     //	_chunkLocations.Add(coords, data);
     //}
 }
Пример #6
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            ChunkColumn chunk = new ChunkColumn();

            chunk.x = chunkCoordinates.X;
            chunk.z = chunkCoordinates.Z;

            PopulateChunk(chunk);

            return(chunk);
        }
Пример #7
0
        public ChunkManager(IServiceProvider serviceProvider, GraphicsDevice graphics, World world)
        {
            Graphics = graphics;
            World    = world;

            Options   = serviceProvider.GetRequiredService <IOptionsProvider>().AlexOptions;
            Resources = serviceProvider.GetRequiredService <ResourceManager>();

            var stillAtlas = Resources.Atlas.GetStillAtlas();

            var fogStart = 0;

            Shaders = new RenderingShaders(Graphics);
            Shaders.SetTextures(stillAtlas);
            Shaders.SetAnimatedTextures(Resources.Atlas.GetAtlas(0));

            RenderDistance = Options.VideoOptions.RenderDistance;

            Options.VideoOptions.RenderDistance.Bind(
                (value, newValue) =>
            {
                RenderDistance = newValue;
            });

            Chunks            = new ConcurrentDictionary <ChunkCoordinates, ChunkColumn>();
            CancellationToken = new CancellationTokenSource();

            BlockLightCalculations = new BlockLightCalculations((World)world);
            SkyLightCalculator     = new SkyLightCalculations();

            Func <ChunkCoordinates, ChunkCoordinates, int> orderingTool = (a, b) =>
            {
                var pos       = new ChunkCoordinates(World.Camera.Position);
                var aDistance = a.DistanceTo(pos);
                var bDistance = b.DistanceTo(pos);

                if (aDistance < bDistance)
                {
                    return(-1);
                }

                if (bDistance > aDistance)
                {
                    return(1);
                }

                return(0);
            };

            UpdateQueue       = new FancyQueue <ChunkCoordinates>();
            UpdateBorderQueue = new FancyQueue <ChunkCoordinates>();
            FastUpdateQueue   = new FancyQueue <ChunkCoordinates>();
        }
Пример #8
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates, bool cacheOnly = false)
        {
            if (Locked || cacheOnly)
            {
                _chunkCache.TryGetValue(chunkCoordinates, out ChunkColumn chunk);
                return(chunk);
            }

            // Warning: The following code MAY execute the GetChunk 2 times for the same coordinate
            // if called in rapid succession. However, for the scenario of the provider, this is highly unlikely.
            return(_chunkCache.GetOrAdd(chunkCoordinates, coordinates => GetChunk(coordinates, MissingChunkProvider)));
        }
Пример #9
0
        private void GenerateChunks(Level level, int r)
        {
            var cX = (int)level.SpawnPoint.X >> 4;
            var cZ = (int)level.SpawnPoint.Z >> 4;

            var x  = 0;
            var y  = 0;
            var t  = r;
            var dx = 0;
            var dy = -1;

            for (var i = 0; i < (r * r); i++)
            {
                if ((-r / 2 <= x) && (x <= r / 2) && (-r / 2 <= y) && (y <= r / 2))
                {
                    //Log.InfoFormat("Generating Chunk {0},{1}", x, y);
                    var coords = new ChunkCoordinates(cX + x, cZ + y);
                    //ThreadPool.QueueUserWorkItem(c => level.GetChunk((ChunkCoordinates) c), coords);

                    var chunk = level.GetChunk(coords);
                    RenderChunk(chunk);
                    (level.WorldProvider as ICachingWorldProvider)?.ClearCachedChunks();
                    //Thread.Sleep(50);
                }

                if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
                {
                    t  = dx;
                    dx = -dy;
                    dy = t;
                }

                x += dx;
                y += dy;
            }


            /*
             * for (int dx = -r; dx <= r; dx++)
             * {
             *  for (int dz = -r; dz <= r; dz++)
             *  {
             *
             *      var coords = new ChunkCoordinates(dx, dz);
             *      //ThreadPool.QueueUserWorkItem(c => level.GetChunk((ChunkCoordinates) c), coords);
             *
             *      var chunk = level.GetChunk(coords);
             *      RenderChunk(chunk);
             *      (level.WorldProvider as ICachingWorldProvider)?.ClearCachedChunks();
             *
             *  }
             * }*/
        }
Пример #10
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            //	Stopwatch sw = Stopwatch.StartNew();
            ChunkColumn chunk = new ChunkColumn
            {
                x = chunkCoordinates.X,
                z = chunkCoordinates.Z
            };

            Decorators.ChunkDecorator[] chunkDecorators = new ChunkDecorator[]
            {
                new WaterDecorator(),
                //new OreDecorator(),
                new FoliageDecorator(),
            };

            var biomes = CalculateBiomes(chunk.x, chunk.z);

            foreach (var i in chunkDecorators)
            {
                i.SetSeed(Seed);
            }

            var heightMap    = GenerateHeightMap(biomes, chunk.x, chunk.z);
            var thresholdMap = GetThresholdMap(chunk.x, chunk.z, biomes);

            CreateTerrainShape(chunk, heightMap, thresholdMap, biomes);
            DecorateChunk(chunk, heightMap, thresholdMap, biomes, chunkDecorators);

            //chunk.isDirty = true;
            //chunk.NeedSave = true;

            /*for (int x = 0; x < 16; x++)
             * {
             *      for (int z = 0; z < 16; z++)
             *      {
             *              for (int y = 0; y < 256; y++)
             *              {
             *                      chunk.SetSkyLight(x, y, z, 255);
             *              }
             *      }
             * }*/
            //	sw.Stop();

            //	if (sw.ElapsedMilliseconds > previousTime)
            //{
            //	Debug.WriteLine("Chunk gen took " + sw.ElapsedMilliseconds + " ms");
            //previousTime = sw.ElapsedMilliseconds;
            //}

            return(chunk);
        }
Пример #11
0
        public int MakeAirChunksAroundWorldToCompensateForBadRendering()
        {
            int       createdChunks = 0;
            Stopwatch sw            = new Stopwatch();

            sw.Start();

            foreach (KeyValuePair <ChunkCoordinates, ChunkColumn> valuePair in _chunkCache)
            {
                ChunkCoordinates chunkCoordinates = valuePair.Key;
                ChunkColumn      chunkColumn      = valuePair.Value;

                if (chunkColumn != null && !chunkColumn.isAllAir)
                {
                    for (int startX = chunkCoordinates.X - 1; startX <= chunkCoordinates.X + 1; startX++)
                    {
                        for (int startZ = chunkCoordinates.Z - 1; startZ <= chunkCoordinates.Z + 1; startZ++)
                        {
                            ChunkCoordinates surroundingChunkCoordinates = new ChunkCoordinates(startX, startZ);

                            if (surroundingChunkCoordinates.Equals(chunkCoordinates))
                            {
                                continue;
                            }

                            ChunkColumn surroundingChunkColumn;

                            _chunkCache.TryGetValue(surroundingChunkCoordinates, out surroundingChunkColumn);

                            if (surroundingChunkColumn == null)
                            {
                                ChunkColumn airColumn = new ChunkColumn
                                {
                                    x        = startX,
                                    z        = startZ,
                                    isAllAir = true
                                };

                                airColumn.GetBatch();

                                _chunkCache[surroundingChunkCoordinates] = airColumn;
                                createdChunks++;
                            }
                        }
                    }
                }
            }

            sw.Stop();
            Log.Info("Created " + createdChunks + " air chunks in " + sw.ElapsedMilliseconds + "ms");
            return(createdChunks);
        }
Пример #12
0
        private async Task <ChunkColumn> GenerateChunk(ChunkCoordinates chunkCoordinates)
        {
            ChunkColumn chunk = new ChunkColumn();

            chunk.X = chunkCoordinates.X;
            chunk.Z = chunkCoordinates.Z;

            Decorators.ChunkDecorator[] chunkDecorators = new ChunkDecorator[]
            {
                new WaterDecorator(),
                //new OreDecorator(),
                new FoliageDecorator(),
            };

            foreach (var i in chunkDecorators)
            {
                i.SetSeed(Seed);
            }

            var res = await GenerateNeeded(chunkCoordinates);

            var heightMap    = res.heightMap;
            var thresholdMap = res.thresholdMap;
            var biomes       = res.biomes;

            var blocks = await CreateTerrainShape(heightMap, thresholdMap);

            int[] metadata = new int[16 * 16 * 256];

            DecorateChunk(chunk.X, chunk.Z, blocks, metadata, heightMap, thresholdMap, biomes, chunkDecorators);

            for (int x = 0; x < 16; x++)
            {
                for (int z = 0; z < 16; z++)
                {
                    var height = heightMap[(x << 4) + z];
                    var biome  = biomes[(x << 4) + z];

                    chunk.biomeId[(x << 4) + z] = (byte)biome.Id;
                    chunk.height[(x << 4) + z]  = (short)height;

                    for (int y = 0; y < 256; y++)
                    {
                        var idx = GetIndex(x, y, z);
                        chunk.SetBlock(x, y, z, blocks[idx]);
                        // chunk.SetMetadata(x,y,z, (byte) metadata[idx]);
                    }
                }
            }

            return(chunk);
        }
Пример #13
0
        private AnvilRegion GenerateRegion(ChunkCoordinates coords)
        {
            int x            = coords.X >> 5;
            int z            = coords.Z >> 5;
            var regionCoords = new ChunkCoordinates(x, z);

            //Debug.WriteLine($"Generating AnvilRegion {x},{z}");

            var region = new AnvilRegion(this, x, z);

            _regionCache[regionCoords] = region;
            return(region);
        }
Пример #14
0
        private void GenerateChunks(int rX, int rZ)
        {
            var tot = rX * rZ;

            ThreadPool.QueueUserWorkItem(delegate
            {
                Monitor.Enter(_busy);

                try
                {
                    Busy();

                    _cancelProgress = false;
                    ShowProgress(tot);
                    var i = 0;

                    var hX = (int)Math.Floor(rX / 2f);
                    var hZ = (int)Math.Floor(rZ / 2f);

                    var chunks = _validChunks.ToArray();

                    for (int x = -hX; x <= hX; x++)
                    {
                        for (int z = -hZ; z <= hZ; z++)
                        {
                            if (_cancelProgress)
                            {
                                HideProgress();
                                return;
                            }

                            var co = new ChunkCoordinates(x, z);

                            if (!chunks.Contains(co))
                            {
                                UpdateProgress(i, "Generating Chunks");
                                _level.GenerateChunk(co);
                            }

                            i++;
                        }
                    }
                }
                finally
                {
                    Monitor.Exit(_busy);
                    HideProgress();
                    Busy(false);
                }
            });
        }
Пример #15
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            ChunkColumn c = new ChunkColumn()
            {
                X = chunkCoordinates.X,
                Z = chunkCoordinates.Z
            };

            /*   for (int x = 0; x < ChunkColumn.ChunkWidth; x++)
             * {
             *     for (int z = 0; z < ChunkColumn.ChunkDepth; z++)
             *     {
             *         for (int y = 0; y < ChunkColumn.ChunkHeight; y++)
             *         {
             *             if (c.X == 0 && c.Z == 0)
             *             {
             *                 IBlockState block;
             *                 switch (y >> 4)
             *                 {
             *                     case 0:
             *                         block = _dirt;
             *                         break;
             *                     case 1:
             *                         block = _stone;
             *                         break;
             *                     case 2:
             *                         block = _cobble;
             *                         break;
             *                     case 3:
             *                         block = _grass;
             *                         break;
             *                     //case 4:
             *                     //    break;
             *                     default:
             *                         continue;
             *                 }
             *
             *                 c.SetBlock(x, y, z, block);
             *             }
             *             else
             *             {
             *                 //c.SetBlockState(x, y, z, _air);
             *             }
             *
             *             c.SetSkyLight(x,y,z, 15);
             *         }
             *         c.SetHeight(x,z, 0);
             *     }
             * }*/
            return(c);
        }
Пример #16
0
        private void LevelManagerOnLevelCreated(object sender, LevelEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(o =>
            {
                var level = e.Level;

                var maxPoints = ChunkRadius * ChunkRadius;

                int di             = 1;
                int dj             = 0;
                int segment_length = 1;

                int i = 0;
                int j = 0;
                int segment_passed = 0;

                for (int k = 0; k < maxPoints; ++k)
                {
                    i += di;
                    j += dj;
                    ++segment_passed;

                    {
                        var coords = new ChunkCoordinates(i, j);
                        //ThreadPool.QueueUserWorkItem(c => level.GetChunk((ChunkCoordinates) c), coords);

                        level.GetChunk(coords);

                        if (k % ChunkSaveInterval == 0)
                        {
                            level.WorldProvider.SaveChunks();
                            Log.InfoFormat("Saving Level... {2:F1}% ({0}/{1})", k, maxPoints, (k / (float)maxPoints) * 100);
                        }
                    }

                    if (segment_passed == segment_length)
                    {
                        segment_passed = 0;

                        int buffer = di;
                        di        -= dj;
                        dj         = buffer;

                        if (dj == 0)
                        {
                            ++segment_length;
                        }
                    }
                }
            });
        }
Пример #17
0
        private bool IsWithinView(ChunkCoordinates chunk, ICamera camera)
        {
            var frustum  = camera.BoundingFrustum;
            var chunkPos = new Vector3(chunk.X * ChunkColumn.ChunkWidth, 0, chunk.Z * ChunkColumn.ChunkDepth);

            if (chunk.DistanceTo(new ChunkCoordinates(camera.Position)) > RenderDistance)
            {
                return(false);
            }

            return(frustum.Intersects(new Microsoft.Xna.Framework.BoundingBox(chunkPos,
                                                                              chunkPos + new Vector3(ChunkColumn.ChunkWidth, MathF.Max(camera.Position.Y + 10f, 256f),
                                                                                                     ChunkColumn.ChunkDepth))));
        }
Пример #18
0
        private IEnumerable <ChunkColumn> GenerateChunks(ChunkCoordinates center, int renderDistance)
        {
            var oldChunks = _loadedChunks.ToArray();

            double radiusSquared = Math.Pow(renderDistance, 2);

            List <ChunkCoordinates> newChunkCoordinates = new List <ChunkCoordinates>();

            List <ChunkCoordinates> results = new List <ChunkCoordinates>();

            for (int y = center.Z - renderDistance; y <= center.Z + renderDistance; y++)
            {
                for (int x = center.X - renderDistance; x <= center.X + renderDistance; x++)
                {
                    var cc = new ChunkCoordinates(x, y);

                    newChunkCoordinates.Add(cc);

                    if (!_loadedChunks.Contains(cc))
                    {
                        ChunkColumn chunk =
                            _generator.GenerateChunkColumn(cc);

                        if (chunk == null)
                        {
                            continue;
                        }

                        _loadedChunks.Add(cc);

                        yield return(chunk);
                    }
                }
            }

            foreach (var chunk in oldChunks)
            {
                if (!newChunkCoordinates.Contains(chunk) && chunk != center)
                {
                    //UnloadChunk(chunk.X, chunk.Z);
                    ChunkUnloadEvent unloadEvent = new ChunkUnloadEvent(chunk);
                    EventDispatcher.DispatchEvent(unloadEvent);

                    if (!unloadEvent.IsCancelled)
                    {
                        _loadedChunks.Remove(chunk);
                    }
                }
            }
        }
        public Chunk AllocateChunk(int X, int Y)
        {
            ChunkCoordinates chunkCoords = new ChunkCoordinates(X, Y);

            byte[] blocks = new byte[32768];
            Chunk  chunk  = new Chunk(blocks, X, Y);

            for (int i = 0; i < chunk.SkylightMap.data.Length; i++)
            {
                chunk.SkylightMap.data[i] = 255;
            }
            Chunks.Add(chunkCoords, chunk);
            return(chunk);
        }
Пример #20
0
        public int PruneAir()
        {
            int       prunedChunks = 0;
            Stopwatch sw           = new Stopwatch();

            sw.Start();

            foreach (KeyValuePair <ChunkCoordinates, ChunkColumn> valuePair in _chunkCache)
            {
                ChunkCoordinates chunkCoordinates = valuePair.Key;
                ChunkColumn      chunkColumn      = valuePair.Value;

                if (chunkColumn != null && chunkColumn.isAllAir)
                {
                    bool surroundingIsAir = true;

                    for (int startX = chunkCoordinates.X - 1; startX <= chunkCoordinates.X + 1; startX++)
                    {
                        for (int startZ = chunkCoordinates.Z - 1; startZ <= chunkCoordinates.Z + 1; startZ++)
                        {
                            ChunkCoordinates surroundingChunkCoordinates = new ChunkCoordinates(startX, startZ);

                            if (!surroundingChunkCoordinates.Equals(chunkCoordinates))
                            {
                                ChunkColumn surroundingChunkColumn;

                                _chunkCache.TryGetValue(surroundingChunkCoordinates, out surroundingChunkColumn);

                                if (surroundingChunkColumn != null && !surroundingChunkColumn.isAllAir)
                                {
                                    surroundingIsAir = false;
                                    break;
                                }
                            }
                        }
                    }

                    if (surroundingIsAir)
                    {
                        _chunkCache[chunkCoordinates] = null;
                        prunedChunks++;
                    }
                }
            }

            sw.Stop();
            Log.Info("Pruned " + prunedChunks + " in " + sw.ElapsedMilliseconds + "ms");
            return(prunedChunks);
        }
Пример #21
0
        private IEnumerable <ChunkColumn> GenerateChunks(ChunkCoordinates center, int renderDistance)
        {
            var oldChunks = _loadedChunks.ToArray();

            List <ChunkCoordinates> newChunkCoordinates = new List <ChunkCoordinates>();

            int minZ = Math.Min(center.Z - renderDistance, center.Z + renderDistance);
            int maxZ = Math.Max(center.Z - renderDistance, center.Z + renderDistance);

            int minX = Math.Min(center.X - renderDistance, center.X + renderDistance);
            int maxX = Math.Max(center.X - renderDistance, center.X + renderDistance);

            for (int x = minX; x <= maxX; x++)
            {
                for (int z = minZ; z <= maxZ; z++)
                {
                    var cc = new ChunkCoordinates(x, z);
                    newChunkCoordinates.Add(cc);

                    if (!_loadedChunks.Contains(cc))
                    {
                        _loadedChunks.Add(cc);

                        ChunkColumn chunk =
                            _generator.GenerateChunkColumn(cc);

                        if (chunk == null)
                        {
                            continue;
                        }

                        base.World.ChunkManager.AddChunk(chunk, cc, false);
                        LoadEntities(chunk);

                        yield return(chunk);
                    }
                }
            }

            foreach (var chunk in oldChunks)
            {
                if (!newChunkCoordinates.Contains(chunk) && chunk != center)
                {
                    //World.UnloadChunk(chunk);
                    World.ChunkManager.RemoveChunk(chunk, false);
                    _loadedChunks.Remove(chunk);
                }
            }
        }
Пример #22
0
        public override void HandleMcpeClientCacheMissResponse(McpeClientCacheMissResponse message)
        {
            foreach (KeyValuePair <ulong, byte[]> kv in message.blobs)
            {
                ulong  hash = kv.Key;
                byte[] data = kv.Value;

                Client.BlobCache.TryAdd(hash, data);

                var chunks = _futureChunks.Where(c => c.Key.SubChunks.Contains(hash) || c.Key.Biome == hash);
                foreach (KeyValuePair <CachedChunk, object> kvp in chunks)
                {
                    CachedChunk chunk = kvp.Key;

                    if (chunk.Biome == hash)
                    {
                        chunk.Chunk.biomeId = data;
                        chunk.Biome         = 0;
                    }
                    else
                    {
                        for (int i = 0; i < chunk.SubChunks.Length; i++)
                        {
                            ulong subChunkHash = chunk.SubChunks[i];
                            if (subChunkHash == hash)
                            {
                                // parse data
                                chunk.Chunk[i]     = ClientUtils.DecodeChunkColumn(1, data, BlockPalette, _internalStates)[0];
                                chunk.SubChunks[i] = 0;
                            }
                        }
                    }
                    if (chunk.Biome == 0 && chunk.SubChunks.All(c => c == 0))
                    {
                        _futureChunks.TryRemove(chunk, out _);

                        var coordinates = new ChunkCoordinates(chunk.Chunk.X, chunk.Chunk.Z);
                        foreach (KeyValuePair <BlockCoordinates, NbtCompound> bePair in _futureBlockEntities.Where(be => (ChunkCoordinates)be.Key == coordinates))
                        {
                            chunk.Chunk.BlockEntities.Add(bePair);
                            _futureBlockEntities.TryRemove(bePair.Key, out _);
                        }

                        chunk.Chunk.RecalcHeight();
                        Client.Chunks[coordinates] = chunk.Chunk;
                    }
                }
            }
        }
Пример #23
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            ChunkColumn cachedChunk;
            if (_chunkCache.TryGetValue(chunkCoordinates, out cachedChunk)) return cachedChunk;

            ChunkColumn chunk = new ChunkColumn();
            chunk.x = chunkCoordinates.X;
            chunk.z = chunkCoordinates.Z;

            PopulateChunk(chunk);

            _chunkCache[chunkCoordinates] = chunk;

            return chunk;
        }
Пример #24
0
 public bool isSameChunk(ChunkCoordinates otherChunkCoordinates)
 {
     if (otherChunkCoordinates == null)
     {
         return(false);
     }
     else if (otherChunkCoordinates.x == x && otherChunkCoordinates.z == z)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Пример #25
0
        internal void DeleteChunk(ChunkCoordinates coords)
        {
            lock (_cacheSync)
            {
                AnvilChunk chunk;
                if (_chunkCache.TryRemove(coords, out chunk))
                {
                }

                NbtFile nbtFile;
                if (_containingChunks.TryRemove(coords, out nbtFile))
                {
                }
            }
        }
Пример #26
0
        public void LoadAnvilChunkLoadTest()
        {
            int width = 32;
            int depth = 32;

            string basePath = @"D:\Development\Worlds\KingsLanding";
            int    regionX  = 4;
            int    regionZ  = 25;
            //string basePath = @"D:\Temp\TestSave130";
            //int regionX = 0;
            //int regionZ = 0;

            int cx = (width * regionX) + 3;
            int cz = (depth * regionZ) + 0;

            ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);

            int rx = coordinates.X >> 5;
            int rz = coordinates.Z >> 5;

            Assert.AreEqual(regionX, rx);
            Assert.AreEqual(regionZ, rz);

            //IWorldGenerator generator = new AirWorldGenerator();
            IWorldGenerator generator = null;

            Stopwatch sw = new Stopwatch();

            sw.Start();

            AnvilWorldProvider wp = new AnvilWorldProvider(basePath);

            int         iterations = 1000;
            ChunkColumn chunk      = null;

            for (int i = 0; i < iterations; i++)
            {
                chunk = wp.GetChunk(coordinates, basePath, generator);
            }

            long ticks = sw.ElapsedTicks;
            long ms    = sw.ElapsedMilliseconds;

            Console.WriteLine($"Read {iterations} chunk-columns in {ticks}ns ({ms}ms) at a rate of {ticks/iterations}ticks/col. 1ms={TimeSpan.TicksPerMillisecond}");

            Assert.NotNull(chunk);
            Assert.Less(ticks / iterations, 100);
        }
Пример #27
0
        public void SaveAnvilChunkTest()
        {
            int width = 32;
            int depth = 32;

            int regionX = 5;
            int regionZ = 24;

            AnvilWorldProvider anvil = new AnvilWorldProvider(@"D:\Development\Worlds\KingsLanding\");

            anvil.Initialize();
            Stopwatch sw = new Stopwatch();

            sw.Start();
            for (int x = 0; x < 32; x++)
            {
                for (int z = 0; z < 32; z++)
                {
                    int cx = (width * regionX) + x;
                    int cz = (depth * regionZ) + z;

                    ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
                    ChunkColumn      chunk       = anvil.GenerateChunkColumn(coordinates, false);
                    Assert.NotNull(chunk);
                }
            }

            Console.WriteLine("Read {0} chunks in {1}ms", anvil.NumberOfCachedChunks(), sw.ElapsedMilliseconds);

            sw.Restart();

            anvil.SaveChunks();

            Console.WriteLine("Saved {0} chunks in {1}ms", anvil.NumberOfCachedChunks(), sw.ElapsedMilliseconds);


            for (int x = 0; x < 32; x++)
            {
                for (int z = 0; z < 32; z++)
                {
                    int cx = (width * regionX) + x;
                    int cz = (depth * regionZ) + z;

                    ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
                    anvil.GenerateChunkColumn(coordinates, false);
                }
            }
        }
Пример #28
0
        private void Test(World level, BlockCoordinates sourceBlock, BlockCoordinates target, ConcurrentQueue <BlockCoordinates> lightBfsQueue, int lightLevel)
        {
            var chunkCoord = new ChunkCoordinates(sourceBlock);
            //Interlocked.Add(ref touches, 1);

            bool isOtherChunk  = false;
            var  newChunkCoord = (ChunkCoordinates)target;

            if (chunkCoord.X != newChunkCoord.X || chunkCoord.Z != newChunkCoord.Z)
            {
                //chunk = GetChunk(level, newCoord);
                lightBfsQueue =
                    ChunkQueues.GetOrAdd(newChunkCoord, coordinates => new ConcurrentQueue <BlockCoordinates>());

                isOtherChunk = true;
            }

            if (isOtherChunk && !World.TryGetBlockLight(target, out _))
            {
                lightBfsQueue.Enqueue(target);

                /*Queue.Enqueue((newCoord, () =>
                 * {
                 *      if (ChunkQueues.TryGetValue((ChunkCoordinates) newCoord, out var queue))
                 *      {
                 *              if (!level.TryGetBlockLight(coord, out var ll))
                 *              {
                 *                      return false;
                 *              }
                 *              //var cc = GetChunk(level, newCoord);
                 *              //if (cc == null)
                 *              //	return false;
                 *              //var ll = level.GetBlockLight(coord);
                 *
                 *              DoPass(level, newCoord, queue, ll);
                 *
                 *              Enqueue(coord);
                 *              Enqueue(newCoord);
                 *              return true;
                 *      }
                 *      return false;
                 * }));*/

                return;
            }

            DoPass(level, target, lightBfsQueue, lightLevel);
        }
Пример #29
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates, bool cacheOnly = false)
        {
            ChunkColumn cachedChunk;
            if (_chunkCache.TryGetValue(chunkCoordinates, out cachedChunk)) return cachedChunk;

            if (cacheOnly)
            {
                return null;
            }

            ChunkColumn chunk = Generator.GenerateChunkColumn(chunkCoordinates);
            
           _chunkCache[chunkCoordinates] = chunk;

            return chunk;
        }
Пример #30
0
        public ChunkColumn GetChunk(ChunkCoordinates coordinates, bool cacheOnly = false)
        {
            if (coordinates == _coord)
            {
                return(_chunk);
            }

            if (_coord != ChunkCoordinates.None)
            {
                if (coordinates != _coord)
                {
                    if (coordinates != _coord + ChunkCoordinates.Backward)
                    {
                        if (coordinates != _coord + ChunkCoordinates.Forward)
                        {
                            if (coordinates != _coord + ChunkCoordinates.Left)
                            {
                                if (coordinates != _coord + ChunkCoordinates.Right)
                                {
                                    if (coordinates != _coord + ChunkCoordinates.Backward + ChunkCoordinates.Left)
                                    {
                                        if (coordinates != _coord + ChunkCoordinates.Backward + ChunkCoordinates.Right)
                                        {
                                            if (coordinates != _coord + ChunkCoordinates.Forward + ChunkCoordinates.Left)
                                            {
                                                if (coordinates != _coord + ChunkCoordinates.Forward + ChunkCoordinates.Right)
                                                {
                                                    return(null);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (_worldProvider.TryGetChunk(coordinates, out ChunkColumn column))
            {
                return((ChunkColumn)column);
            }

            return(null);
            //return _worldProvider.GenerateChunkColumn(coordinates, true);
        }
Пример #31
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            ChunkColumn column = new ChunkColumn();

            column.X = chunkCoordinates.X;
            column.Z = chunkCoordinates.Z;

            for (int x = 0; x < 16; x++)
            {
                for (int z = 0; z < 16; z++)
                {
                    column.SetBlockState(x, 0, z, Bedrock);
                    if (column.X == 1 && column.Z == 1)
                    {
                        for (int y = 1; y < 2; y++)
                        {
                            column.SetBlockState(x, y, z, Water.WithProperty("level", "8"));
                        }
                        column.SetBlockState(x, 3, z, Water.WithProperty("level", "3"));
                    }
                    else
                    {
                        column.SetBlockState(x, 1, z, Dirt);
                        column.SetBlockState(x, 2, z, Dirt);
                        column.SetBlockState(x, 3, z, Grass);

                        if (x == 8 && z == 8)
                        {
                            column.SetBlockState(x, 5, z, Slab.WithProperty("type", "bottom"));
                        }
                        else if (x == 8 && z == 7)
                        {
                            column.SetBlockState(x, 5, z, Slab.WithProperty("type", "top"));
                        }
                    }

                    column.SetSkyLight(x, 0, z, 15);
                    column.SetSkyLight(x, 1, z, 15);
                    column.SetSkyLight(x, 2, z, 15);
                    column.SetSkyLight(x, 3, z, 15);
                    column.SetSkyLight(x, 4, z, 15);
                }
            }

            return(column);
        }
Пример #32
0
		public void SaveAnvilChunkTest()
		{
			int width = 32;
			int depth = 32;

			int regionX = 5;
			int regionZ = 24;

			AnvilWorldProvider anvil = new AnvilWorldProvider(@"D:\Development\Worlds\KingsLanding\");
			anvil.Initialize();
			Stopwatch sw = new Stopwatch();
			sw.Start();
			for (int x = 0; x < 32; x++)
			{
				for (int z = 0; z < 32; z++)
				{
					int cx = (width*regionX) + x;
					int cz = (depth*regionZ) + z;

					ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
					ChunkColumn chunk = anvil.GenerateChunkColumn(coordinates);
					Assert.NotNull(chunk);
				}
			}
			Console.WriteLine("Read {0} chunks in {1}ms", anvil.NumberOfCachedChunks(), sw.ElapsedMilliseconds);

			sw.Restart();

			anvil.SaveChunks();

			Console.WriteLine("Saved {0} chunks in {1}ms", anvil.NumberOfCachedChunks(), sw.ElapsedMilliseconds);


			for (int x = 0; x < 32; x++)
			{
				for (int z = 0; z < 32; z++)
				{
					int cx = (width*regionX) + x;
					int cz = (depth*regionZ) + z;

					ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
					anvil.GenerateChunkColumn(coordinates);
				}
			}
		}
Пример #33
0
        private void ForcedSendChunksForKnownPosition(PlayerLocation position)
        {
            var chunkPosition = new ChunkCoordinates(position);
            _currentChunkPosition = chunkPosition;

            foreach (McpeBatch chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
            {
                SendPackage(chunk, true);
            }
        }
Пример #34
0
        public static void SendChunk(ChunkCoordinates position)
        {
            ChunkColumn targetchunk = Level[0]._worldProvider.GenerateChunkColumn(position);
            PcChunkColumn converted = new PcChunkColumn {X = position.X, Z = position.Z};
            converted.Pe2Pc(targetchunk);

            foreach (var player in PcPlayers)
            {
                //new BlockChange(player.Wrapper, new MSGBuffer(player.Wrapper)) {BlockID = data.block, MetaData = data.meta, Location = new Vector3(data.x, data.y, data.z)}.Write();
                new ChunkData(player.Wrapper) { Chunk = converted, Quee = false}.Write();
            }
        }
Пример #35
0
		public void LoadAnvilChunkLoadTest()
		{
			int width = 32;
			int depth = 32;

			int cx = (width*4) + 3;
			int cz = (depth*25) + 0;

			ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);

			int rx = coordinates.X >> 5;
			int rz = coordinates.Z >> 5;

			Assert.AreEqual(4, rx);
			Assert.AreEqual(25, rz);

			string basePath = @"D:\Downloads\KingsLanding1";
			var generator = new FlatlandWorldProvider();

			Stopwatch sw = new Stopwatch();
			sw.Start();

			int iterations = 1024;
			for (int i = 0; i < iterations; i++)
			{
				AnvilWorldProvider.GetChunk(coordinates, basePath, generator, 30);
			}

			long ticks = sw.ElapsedTicks;
			long ms = sw.ElapsedMilliseconds;

			//Assert.Less(ticks/iterations, 100);

			Console.WriteLine("Read {0} chunk-columns in {1}ns ({3}ms) at a rate of {2}ns/col", iterations, ticks, ticks / iterations, ms);
		}
Пример #36
0
		public void LoadFullAnvilRegionLoadTest()
		{
			int width = 32;
			int depth = 32;

			int regionX = 5;
			int regionZ = 24;

			string basePath = @"D:\Downloads\KingsLanding1";
			var generator = new FlatlandWorldProvider();

			Stopwatch sw = new Stopwatch();
			sw.Start();
			int noChunksRead = 0;
			for (int x = 0; x < 32; x++)
			{
				for (int z = 0; z < 32; z++)
				{
					noChunksRead++;
					int cx = (width*regionX) + x;
					int cz = (depth*regionZ) + z;

					ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
					ChunkColumn chunk = AnvilWorldProvider.GetChunk(coordinates, basePath, generator, 30);
					Assert.NotNull(chunk);
				}
			}
			Console.WriteLine("Read {0} chunks in {1}ms", noChunksRead, sw.ElapsedMilliseconds);
		}
Пример #37
0
		public void ChunkLoadTest()
		{
			{
				var chunkPosition = new ChunkCoordinates(0, 0);

				Dictionary<Tuple<int, int>, double> newOrders = new Dictionary<Tuple<int, int>, double>();
				double viewDistance = 250;
				double radiusSquared = viewDistance/Math.PI;
				double radius = Math.Ceiling(Math.Sqrt(radiusSquared));
				int centerX = chunkPosition.X;
				int centerZ = chunkPosition.Z;

				Stopwatch sw = new Stopwatch();
				sw.Start();

				for (double x = -radius; x <= radius; x++)
				{
					for (double z = -radius; z <= radius; z++)
					{
						double distance = (x*x) + (z*z);
						if (distance > radiusSquared)
						{
							continue;
						}

						int chunkX = (int) (x + centerX);
						int chunkZ = (int) (z + centerZ);
						Tuple<int, int> index = new Tuple<int, int>(chunkX, chunkZ);
						newOrders[index] = distance;
					}
				}
			}
			{
				var chunkPosition = new ChunkCoordinates(0, 0);

				// A = pi r^2
				// sqrt(A/pi) = r
				Dictionary<Tuple<int, int>, double> newOrders = new Dictionary<Tuple<int, int>, double>();
				double radius = 9;
				double radiusSqr = radius*radius;
				int centerX = chunkPosition.X;
				int centerZ = chunkPosition.Z;

				Stopwatch sw = new Stopwatch();
				sw.Start();

				for (double x = -radius; x <= radius; x++)
				{
					for (double z = -radius; z <= radius; z++)
					{
						double distanceSqr = (x*x) + (z*z);

						if (distanceSqr > radiusSqr) continue;

						int chunkX = (int) (x + centerX);
						int chunkZ = (int) (z + centerZ);
						Tuple<int, int> index = new Tuple<int, int>(chunkX, chunkZ);
						newOrders[index] = distanceSqr;
					}
				}
			}
		}
Пример #38
0
		public void SaveOneAnvilChunkTest()
		{
			int width = 32;
			int depth = 32;

			int cx = (width*4) + 3;
			int cz = (depth*25) + 0;

			AnvilWorldProvider anvil = new AnvilWorldProvider(@"D:\Development\Worlds\KingsLanding\");
			anvil.Initialize();

			ChunkCoordinates coordinates = new ChunkCoordinates(cx, cz);
			ChunkColumn chunk = anvil.GenerateChunkColumn(coordinates);
			Assert.NotNull(chunk);

			Stopwatch sw = new Stopwatch();
			sw.Start();

			anvil.SaveChunks();

			Assert.Less(sw.ElapsedMilliseconds, 1);
		}
Пример #39
0
        /// <summary>
        ///     Sends the chunks for known position.
        /// </summary>
        private void SendChunksForKnownPosition()
        {
            if (IsBot) return;

            var chunkPosition = new ChunkCoordinates(KnownPosition);
            if (IsSpawned && _currentChunkPosition == chunkPosition) return;

            _currentChunkPosition = chunkPosition;

            ThreadPool.QueueUserWorkItem(delegate(object state)
            {
                int packetCount = 0;

                if (!IsBot)
                {
                    while (Rtt < 0)
                    {
                        Thread.Yield();
                    }
                }

                MemoryStream stream = new MemoryStream();
                foreach (var chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
                {
                    McpeFullChunkData fullChunkData = McpeFullChunkData.CreateObject();
                    fullChunkData.chunkX = chunk.x;
                    fullChunkData.chunkZ = chunk.z;
                    fullChunkData.chunkData = chunk.GetBytes();
                    fullChunkData.chunkDataLength = fullChunkData.chunkData.Length;
                    byte[] bytes = fullChunkData.Encode();
                    fullChunkData.PutPool();

                    //if (!IsSpawned)
                    {
                        McpeBatch batch = McpeBatch.CreateObject();
                        byte[] buffer = CompressBytes(bytes, CompressionLevel.Optimal);
                        batch.payloadSize = buffer.Length;
                        batch.payload = buffer;
                        SendPackage(batch, sendDirect: true);
                    }
                    //else
                    //{
                    //	stream.Write(bytes, 0, bytes.Length);
                    //}

                    // This is to slow down chunk-sending not to overrun old devices.
                    // The timeout should be configurable and enable/disable.
                    //if (Math.Floor(Rtt/10d) > 0)
                    //{
                    //	Thread.Sleep(Math.Min(Math.Max((int) Math.Floor(Rtt/10d), 12) + 10, 40));
                    //}

                    if (!IsSpawned)
                    {
                        if (packetCount++ == 56)
                        {
                            InitializePlayer();
                        }
                    }
                }

                //if (IsSpawned)
                //{
                //	McpeBatch batch = McpeBatch.CreateObject();
                //	byte[] buffer = CompressBytes(stream.ToArray(), CompressionLevel.Fastest);
                //	batch.payloadSize = buffer.Length;
                //	batch.payload = buffer;
                //	SendPackage(batch, sendDirect: true);
                //}
            });
        }
Пример #40
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            lock (_chunkCache)
            {
                ChunkColumn cachedChunk;
                if (_chunkCache.TryGetValue(chunkCoordinates, out cachedChunk))
                {
                    return cachedChunk;
                }

                ChunkColumn chunk = new ChunkColumn();
                chunk.x = chunkCoordinates.X;
                chunk.z = chunkCoordinates.Z;

                int h = PopulateChunk(chunk);

                chunk.SetBlock(0, h + 1, 0, 7);
                chunk.SetBlock(1, h + 1, 0, 41);
                chunk.SetBlock(2, h + 1, 0, 41);
                chunk.SetBlock(3, h + 1, 0, 41);
                chunk.SetBlock(3, h + 1, 0, 41);

                //chunk.SetBlock(6, h + 1, 6, 57);

                chunk.SetBlock(6, h, 9, 63);
                chunk.SetMetadata(6, h, 9, 12);
                var blockEntity = GetBlockEntity((chunkCoordinates.X*16) + 6, h, (chunkCoordinates.Z*16) + 9);
                chunk.SetBlockEntity(blockEntity.Coordinates, blockEntity.GetCompound());

                if (chunkCoordinates.X == 1 && chunkCoordinates.Z == 1)
                {
                    for (int x = 0; x < 10; x++)
                    {
                        for (int z = 0; z < 10; z++)
                        {
                            for (int y = h - 2; y < h; y++)
                            {
                                chunk.SetBlock(x, y, z, 8);
                            }
                        }
                    }
                }

                if (chunkCoordinates.X == 3 && chunkCoordinates.Z == 1)
                {
                    for (int x = 0; x < 10; x++)
                    {
                        for (int z = 0; z < 10; z++)
                        {
                            for (int y = h - 1; y < h; y++)
                            {
                                chunk.SetBlock(x, y, z, 10);
                            }
                        }
                    }
                }

                for (int x = 0; x < 16; x++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        for (int y = 127; y != 0; y--)
                        {
                            if (chunk.GetBlock(x, y, z) == 0x00)
                            {
                                chunk.SetSkylight(x, y, z, 0xff);
                            }
                            else
                            {
                                chunk.SetSkylight(x, y, z, 0x00);
                            }
                        }
                    }
                }

                _chunkCache[chunkCoordinates] = chunk;

                return chunk;
            }
        }
Пример #41
0
		private void ForcedSendChunks()
		{
			if (!Monitor.TryEnter(_sendChunkSync)) return;
			try
			{
				var chunkPosition = new ChunkCoordinates(KnownPosition);

				_currentChunkPosition = chunkPosition;

				if (Level == null) return;

				foreach (McpeBatch chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
				{
					if (chunk == null) continue;

					SendPackage(chunk, true);
				}
			}
			finally
			{
				Monitor.Exit(_sendChunkSync);
			}
		}
Пример #42
0
		private void SendChunksForKnownPosition()
		{
			if (!Monitor.TryEnter(_sendChunkSync)) return;

			try
			{
				var chunkPosition = new ChunkCoordinates(KnownPosition);
				if (IsSpawned && _currentChunkPosition == chunkPosition) return;

				if (IsSpawned && _currentChunkPosition.DistanceTo(chunkPosition) < 5)
				{
					return;
				}

				_currentChunkPosition = chunkPosition;

				int packetCount = 0;

				if (Level == null) return;

				foreach (McpeBatch chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
				{
					if (chunk != null) SendPackage(chunk);

					if (!IsSpawned)
					{
						if (packetCount++ == 56)
						{
							InitializePlayer();
						}
					}
				}
			}
			finally
			{
				Monitor.Exit(_sendChunkSync);
			}
		}
Пример #43
0
		private void ForcedSendChunk(PlayerLocation position)
		{
			lock (_sendChunkSync)
			{
				var chunkPosition = new ChunkCoordinates(position);

				McpeBatch chunk = Level.GenerateChunk(chunkPosition);
				var key = new Tuple<int, int>(chunkPosition.X, chunkPosition.Z);
				if (!_chunksUsed.ContainsKey(key))
				{
					_chunksUsed.Add(key, chunk);
				}

				if (chunk != null)
				{
					SendPackage(chunk, true);
				}
			}
		}
Пример #44
0
        public static void SaveChunk(ChunkColumn chunk, string basePath, int yoffset)
        {
            var coordinates = new ChunkCoordinates(chunk.x, chunk.z);

            int width = 32;
            int depth = 32;

            int rx = coordinates.X >> 5;
            int rz = coordinates.Z >> 5;

            string filePath = Path.Combine(basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz));

            if (!File.Exists(filePath))
            {
                // Make sure directory exist
                Directory.CreateDirectory(Path.Combine(basePath, "region"));

                // Create empty region file
                using (var regionFile = File.Open(filePath, FileMode.CreateNew))
                {
                    byte[] buffer = new byte[8192];
                    regionFile.Write(buffer, 0, buffer.Length);
                }

                return;
            }

            using (var regionFile = File.Open(filePath, FileMode.Open))
            {
                byte[] buffer = new byte[8192];
                regionFile.Read(buffer, 0, buffer.Length);

                int xi = (coordinates.X%width);
                if (xi < 0) xi += 32;
                int zi = (coordinates.Z%depth);
                if (zi < 0) zi += 32;
                int tableOffset = (xi + zi*width)*4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                byte[] offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                int offset = BitConverter.ToInt32(offsetBuffer, 0) << 4;

                int length = regionFile.ReadByte();

                if (offset == 0 || length == 0)
                {
                    regionFile.Seek(0, SeekOrigin.End);
                    offset = (int) regionFile.Position;

                    regionFile.Seek(tableOffset, SeekOrigin.Begin);

                    byte[] bytes = BitConverter.GetBytes(offset >> 4);
                    Array.Reverse(bytes);
                    regionFile.Write(bytes, 0, 3);
                    regionFile.WriteByte(1);
                }

                // Write NBT
                NbtFile nbt = CreateNbtFromChunkColumn(chunk, yoffset);
                byte[] nbtBuf = nbt.SaveToBuffer(NbtCompression.ZLib);

                int lenght = nbtBuf.Length;
                byte[] lenghtBytes = BitConverter.GetBytes(lenght + 1);
                Array.Reverse(lenghtBytes);

                regionFile.Seek(offset, SeekOrigin.Begin);
                regionFile.Write(lenghtBytes, 0, 4); // Lenght
                regionFile.WriteByte(0x02); // Compression mode

                regionFile.Write(nbtBuf, 0, nbtBuf.Length);

                int reminder;
                Math.DivRem(lenght + 4, 4096, out reminder);

                byte[] padding = new byte[4096 - reminder];
                if (padding.Length > 0) regionFile.Write(padding, 0, padding.Length);
            }
        }
Пример #45
0
        public ChunkColumn GenerateChunkColumn(ChunkCoordinates chunkCoordinates)
        {
            lock (_chunkCache)
            {
                ChunkColumn cachedChunk;
                if (_chunkCache.TryGetValue(chunkCoordinates, out cachedChunk)) return cachedChunk;

                ChunkColumn chunk = GetChunk(chunkCoordinates, _basePath, _flatland, _waterOffsetY);

                _chunkCache[chunkCoordinates] = chunk;

                return chunk;
            }
        }
Пример #46
0
        public static ChunkColumn GetChunk(ChunkCoordinates coordinates, string basePath, IWorldProvider generator, int yoffset)
        {
            int width = 32;
            int depth = 32;

            int rx = coordinates.X >> 5;
            int rz = coordinates.Z >> 5;

            string filePath = Path.Combine(basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz));

            if (!File.Exists(filePath)) return generator.GenerateChunkColumn(coordinates);

            using (var regionFile = File.OpenRead(filePath))
            {
                byte[] buffer = new byte[8192];

                regionFile.Read(buffer, 0, 8192);

                int xi = (coordinates.X%width);
                if (xi < 0) xi += 32;
                int zi = (coordinates.Z%depth);
                if (zi < 0) zi += 32;
                int tableOffset = (xi + zi*width)*4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                byte[] offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                int offset = BitConverter.ToInt32(offsetBuffer, 0) << 4;

                int length = regionFile.ReadByte();

                if (offset == 0 || length == 0)
                {
                    return generator.GenerateChunkColumn(coordinates);
                }

                regionFile.Seek(offset, SeekOrigin.Begin);
                byte[] waste = new byte[4];
                regionFile.Read(waste, 0, 4);
                int compressionMode = regionFile.ReadByte();

                var nbt = new NbtFile();
                nbt.LoadFromStream(regionFile, NbtCompression.ZLib);

                NbtTag dataTag = nbt.RootTag["Level"];

                NbtList sections = dataTag["Sections"] as NbtList;

                ChunkColumn chunk = new ChunkColumn
                {
                    x = coordinates.X,
                    z = coordinates.Z,
                    biomeId = dataTag["Biomes"].ByteArrayValue
                };

                for (int i = 0; i < chunk.biomeId.Length; i++)
                {
                    if (chunk.biomeId[i] > 22) chunk.biomeId[i] = 0;
                }
                if (chunk.biomeId.Length > 256) throw new Exception();

                // This will turn into a full chunk column
                foreach (NbtTag sectionTag in sections)
                {
                    int sy = sectionTag["Y"].ByteValue*16;
                    byte[] blocks = sectionTag["Blocks"].ByteArrayValue;
                    byte[] data = sectionTag["Data"].ByteArrayValue;
                    NbtTag addTag = sectionTag["Add"];
                    byte[] adddata = new byte[2048];
                    if (addTag != null) adddata = addTag.ByteArrayValue;
                    byte[] blockLight = sectionTag["BlockLight"].ByteArrayValue;
                    byte[] skyLight = sectionTag["SkyLight"].ByteArrayValue;

                    for (int x = 0; x < 16; x++)
                    {
                        for (int z = 0; z < 16; z++)
                        {
                            for (int y = 0; y < 16; y++)
                            {
                                int yi = sy + y - yoffset;
                                if (yi < 0 || yi >= 128) continue;

                                int anvilIndex = y*16*16 + z*16 + x;
                                int blockId = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8);

                                // Anvil to PE friendly converstion
                                if (blockId == 125) blockId = 5;
                                else if (blockId == 126) blockId = 158;
                                else if (blockId == 75) blockId = 50;
                                else if (blockId == 76) blockId = 50;
                                else if (blockId == 123) blockId = 89;
                                else if (blockId == 124) blockId = 89;
                                else if (blockId == 152) blockId = 73;
                                else if (_ignore.BinarySearch(blockId) >= 0) blockId = 0;
                                else if (_gaps.BinarySearch(blockId) >= 0)
                                {
                                    Debug.WriteLine("Missing material: " + blockId);
                                    blockId = 133;
                                }

                                if (blockId > 255) blockId = 41;

                                if (yi == 127 && blockId != 0) blockId = 30;
                                if (yi == 0 && (blockId == 8 || blockId == 9 /*|| blockId == 0*/)) blockId = 7;

                                //if (blockId != 0) blockId = 41;

                                chunk.SetBlock(x, yi, z, (byte) blockId);
                                chunk.SetMetadata(x, yi, z, Nibble4(data, anvilIndex));
                                chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex));
                                chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex));
                            }
                        }
                    }
                }

                NbtList entities = dataTag["Entities"] as NbtList;
                NbtList blockEntities = dataTag["TileEntities"] as NbtList;
                if (blockEntities != null)
                {
                    foreach (var nbtTag in blockEntities)
                    {
                        var blockEntityTag = (NbtCompound) nbtTag;
                        string entityId = blockEntityTag["id"].StringValue;
                        int x = blockEntityTag["x"].IntValue;
                        int y = blockEntityTag["y"].IntValue - yoffset;
                        int z = blockEntityTag["z"].IntValue;
                        blockEntityTag["y"] = new NbtInt("y", y);

                        BlockEntity blockEntity = BlockEntityFactory.GetBlockEntityById(entityId);
                        if (blockEntity != null)
                        {
                            blockEntityTag.Name = string.Empty;
                            chunk.SetBlockEntity(new BlockCoordinates(x, y, z), blockEntityTag);
                        }
                    }
                }

                NbtList tileTicks = dataTag["TileTicks"] as NbtList;

                chunk.isDirty = false;
                return chunk;
            }
        }
Пример #47
0
        private void SendChunksForKnownPosition()
        {
            if (!Monitor.TryEnter(_sendChunkSync)) return;

            try
            {
                var chunkPosition = new ChunkCoordinates(KnownPosition);
                if (IsSpawned && _currentChunkPosition == chunkPosition) return;

                //if (_currentChunkPosition.DistanceTo(chunkPosition) < 4)
                //{
                //	Log.DebugFormat("Denied chunk, too little distance.");
                //	return;
                //}

                _currentChunkPosition = chunkPosition;

                int packetCount = 0;

                foreach (McpeBatch chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
                {
                    SendPackage(chunk, sendDirect: true);

                    if (!IsSpawned)
                    {
                        if (packetCount++ == 56)
                        {
                            InitializePlayer();
                        }
                    }
                }
            }
            finally
            {
                Monitor.Exit(_sendChunkSync);
            }
        }