예제 #1
0
 private sbyte GetSkyLight(Chunk chunk, int x, int y, int z)
 {
     if (x < 0)
     {
         x = Chunk.Width + x;
         chunk = GetChunkWithoutGeneration(chunk.AbsolutePosition + Vector3.Left);
         if (chunk == null) return -1;
     }
     if (x >= Chunk.Width)
     {
         x -= Chunk.Width;
         chunk = GetChunkWithoutGeneration(chunk.AbsolutePosition + Vector3.Right);
         if (chunk == null) return -1;
     }
     if (z < 0)
     {
         z = Chunk.Depth + z;
         chunk = GetChunkWithoutGeneration(chunk.AbsolutePosition + Vector3.Backwards);
         if (chunk == null) return -1;
     }
     if (z >= Chunk.Depth)
     {
         z -= Chunk.Depth;
         chunk = GetChunkWithoutGeneration(chunk.AbsolutePosition + Vector3.Forwards);
         if (chunk == null) return -1;
     }
     return (sbyte)chunk.GetSkyLight(x, y, z);
 }
예제 #2
0
 public void LightChunk(Chunk chunk)
 {
     chunk.ClearLight();
     chunk.CalculateInitialSkylight();
     for (int y = 0; y < Chunk.Height; y++)
     {
         for (int x = 0; x < Chunk.Width; x++)
         {
             for (int z = 0; z < Chunk.Depth; z++)
             {
                 CalculateSkyLight(chunk, x, y, z);
             }
         }
     }
     //for (int y = 0; y < Chunk.Height; y++)
     //{
     //    for (int x = Chunk.Width - 1; x >= Chunk.Width; x--)
     //    {
     //        for (int z = Chunk.Depth - 1; z >= 0; z--)
     //        {
     //            CalculateSkyLight(chunk, x, y, z);
     //        }
     //    }
     //}
 }
예제 #3
0
 public static void MapChunkBulk(MinecraftClient client, IPacket _packet)
 {
     var packet = (MapChunkBulkPacket)_packet;
     var metadataStrem = new MemoryStream(packet.ChunkMetadata);
     var minecraftStream = new MinecraftStream(metadataStrem);
     var data = ZlibStream.UncompressBuffer(packet.ChunkData);
     int chunkLength = BlockDataLength + (NibbleDataLength * 2) + (Chunk.Width * Chunk.Depth);
     if (packet.LightIncluded)
         chunkLength += NibbleDataLength;
     for (int i = 0; i < packet.ChunkCount; i++)
     {
         int x = minecraftStream.ReadInt32();
         int z = minecraftStream.ReadInt32();
         ushort primaryBitMap = minecraftStream.ReadUInt16();
         ushort addBitMap = minecraftStream.ReadUInt16(); // TODO
         int offset = i * chunkLength;
         // Read chunk data
         var chunk = new Chunk(World.GetRelativeChunkPosition(new Vector3(x, 0, z)));
         var sectionCount = 0;
         // Get the total sections included in the packet
         for (int y = 0; y < 16; y++)
         {
             if ((primaryBitMap & (1 << y)) > 0)
                 sectionCount++;
         }
         // Run through the sections
         // TODO: Support block IDs >255
         for (int y = 0; y < 16; y++)
         {
             if ((primaryBitMap & (1 << y)) > 0)
             {
                 // Add this section
                 Array.Copy(data, offset + (y * BlockDataLength), chunk.Sections[y].Blocks, 0, BlockDataLength);
                 Array.Copy(data, offset + (y * BlockDataLength + (BlockDataLength * sectionCount)),
                     chunk.Sections[y].Metadata.Data, 0, NibbleDataLength);
                 Array.Copy(data, offset + (y * BlockDataLength + (BlockDataLength * sectionCount + NibbleDataLength)),
                     chunk.Sections[y].BlockLight.Data, 0, NibbleDataLength);
                 if (packet.LightIncluded)
                 {
                     Array.Copy(data, offset + (y * BlockDataLength + (BlockDataLength * sectionCount + (NibbleDataLength * 2))),
                         chunk.Sections[y].SkyLight.Data, 0, NibbleDataLength);
                 }
             }
         }
         Array.Copy(data, offset + chunkLength - chunk.Biomes.Length, chunk.Biomes, 0, chunk.Biomes.Length);
         client.World.SetChunk(new Vector3(x, 0, z), chunk);
         client.OnChunkRecieved(new ChunkRecievedEventArgs(new Vector3(x, 0, z), new ReadOnlyChunk(chunk)));
     }
 }
예제 #4
0
 private void CalculateSkyLight(Chunk chunk, int x, int y, int z)
 {
     byte self = chunk.GetSkyLight(x, y, z);
     // We use sbytes here so we can use -1 as the light value of an ungenerated block
     sbyte left = GetSkyLight(chunk, x - 1, y, z);
     sbyte right = GetSkyLight(chunk, x + 1, y, z);
     sbyte forwards = GetSkyLight(chunk, x, y, z + 1);
     sbyte backwards = GetSkyLight(chunk, z, y, z - 1);
     if (left > self)
         self = (byte)(left - 1);
     if (right > self)
         self = (byte)(right - 1);
     if (forwards > self)
         self = (byte)(forwards - 1);
     if (backwards > self)
         self = (byte)(backwards - 1);
     chunk.SetSkyLight(x, y, z, self);
 }
예제 #5
0
        private static void AddChunk(MinecraftClient client, int x, int z, ushort primaryBitMap, ushort addBitMap, bool lightIncluded, bool groundUp, byte[] data)
        {
            var position = new Vector3(x, 0, z);
            var relativePosition = World.GetRelativeChunkPosition(position);
            var chunk = new Chunk(relativePosition);
            var sectionCount = GetSectionCount(primaryBitMap);

            // Run through the sections
            // TODO: Support block IDs >255
            for (int y = 0; y < 16; y++)
            {
                if ((primaryBitMap & (1 << y)) > 0)
                {
                    // Add this section

                    // Blocks
                    Array.Copy(data, y * BlockDataLength, chunk.Sections[y].Blocks, 0, BlockDataLength);

                    // Metadata
                    Array.Copy(data, (BlockDataLength * sectionCount) + (y * NibbleDataLength),
                        chunk.Sections[y].Metadata.Data, 0, NibbleDataLength);

                    // Light
                    Array.Copy(data, ((BlockDataLength + NibbleDataLength) * sectionCount) + (y * NibbleDataLength),
                        chunk.Sections[y].BlockLight.Data, 0, NibbleDataLength);

                    // Sky light
                    if (lightIncluded)
                        Array.Copy(data, ((BlockDataLength + NibbleDataLength + NibbleDataLength) * sectionCount) + (y * NibbleDataLength),
                            chunk.Sections[y].SkyLight.Data, 0, NibbleDataLength);
                }
            }

            // biomes
            if (groundUp)
                Array.Copy(data, data.Length - chunk.Biomes.Length, chunk.Biomes, 0, chunk.Biomes.Length);

            client.World.SetChunk(position, chunk);
            client.OnChunkRecieved(new ChunkRecievedEventArgs(position, new ReadOnlyChunk(chunk)));
        }
예제 #6
0
 public static void ChunkData(MinecraftClient client, IPacket _packet)
 {
     var packet = (ChunkDataPacket)_packet;
     if (packet.Data == ChunkRemovalSequence)
     {
         client.World.RemoveChunk(packet.X, packet.Z);
         return;
     }
     var chunk = new Chunk(World.GetRelativeChunkPosition(new Vector3(packet.X, 0, packet.Z)));
     var data = ZlibStream.UncompressBuffer(packet.Data);
     var sectionCount = 0;
     // Get the total sections included in the packet
     for (int y = 0; y < 16; y++)
     {
         if ((packet.PrimaryBitMap & (1 << y)) > 0)
             sectionCount++;
     }
     // Run through the sections
     // TODO: Support block IDs >255
     for (int y = 0; y < 16; y++)
     {
         if ((packet.PrimaryBitMap & (1 << y)) > 0)
         {
             // Add this section
             Array.Copy(data, y * BlockDataLength, chunk.Sections[y].Blocks, 0, BlockDataLength);
             Array.Copy(data, y * BlockDataLength + (BlockDataLength * sectionCount),
                 chunk.Sections[y].Metadata.Data, 0, NibbleDataLength);
             Array.Copy(data, y * BlockDataLength + (BlockDataLength * sectionCount + NibbleDataLength),
                 chunk.Sections[y].BlockLight.Data, 0, NibbleDataLength);
             Array.Copy(data, y * BlockDataLength + (BlockDataLength * sectionCount + (NibbleDataLength * 2)),
                 chunk.Sections[y].SkyLight.Data, 0, NibbleDataLength);
         }
     }
     if (packet.GroundUpContinuous)
         Array.Copy(data, data.Length - chunk.Biomes.Length, chunk.Biomes, 0, chunk.Biomes.Length);
     client.World.SetChunk(new Vector3(packet.X, 0, packet.Z), chunk);
     client.OnChunkRecieved(new ChunkRecievedEventArgs(new Vector3(packet.X, 0, packet.Z), new ReadOnlyChunk(chunk)));
 }
예제 #7
0
파일: Region.cs 프로젝트: pdelvo/Craft.Net
 /// <summary>
 /// Sets the chunk at the specified local position to the given value.
 /// </summary>
 public void SetChunk(Vector3 position, Chunk chunk)
 {
     if (!Chunks.ContainsKey(position))
         Chunks.Add(position, chunk);
     Chunks[position] = chunk;
 }
예제 #8
0
        private Vector3 FindBlockPosition(Vector3 position, out Chunk chunk)
        {
            var x = (int)position.X;
            var y = (int)position.Y;
            var z = (int)position.Z;

            if (y < 0 || y >= Chunk.Height)
                throw new ArgumentOutOfRangeException("position", "Position is out of range");

            int chunkX = x / (Chunk.Width) - ((x < 0) ? 1 : 0);
            int chunkZ = z / (Chunk.Depth) - ((z < 0) ? 1 : 0);

            chunk = GetChunk(new Vector3(chunkX, 0, chunkZ));
            return new Vector3((x - chunkX * Chunk.Width) % Chunk.Width, y, (z - chunkZ * Chunk.Depth) % Chunk.Depth);
        }
예제 #9
0
        /// <summary>
        /// Sets the chunk at the given position to the chunk provided.
        /// </summary>
        public void SetChunk(Vector3 position, Chunk chunk)
        {
            //In chunks
            var x = (int)position.X;
            var z = (int)position.Z;

            //In regions
            int regionX = x/Region.Width - ((x < 0) ? 1 : 0);
            int regionZ = z/Region.Depth - ((z < 0) ? 1 : 0);

            var region = CreateOrLoadRegion(new Vector3(regionX, 0, regionZ));
            region.SetChunk(new Vector3(x - regionX * 32, 0, z - regionZ * 32), chunk);
        }
예제 #10
0
 public static Chunk FromNbt(Vector3 position, NbtFile nbt)
 {
     Chunk chunk = new Chunk(position);
     // Load data
     var root = nbt.RootTag.Get<NbtCompound>("Level");
     chunk.Biomes = root.Get<NbtByteArray>("Biomes").Value;
     chunk.HeightMap = root.Get<NbtIntArray>("HeightMap").Value;
     var sections = root.Get<NbtList>("Sections");
     foreach (var sectionTag in sections) // TODO: This might not work properly
     {
         // Load data
         var compound = (NbtCompound)sectionTag;
         byte y = compound.Get<NbtByte>("Y").Value;
         var section = new Section(y);
         section.Blocks = compound.Get<NbtByteArray>("Blocks").Value;
         section.BlockLight.Data = compound.Get<NbtByteArray>("BlockLight").Value;
         section.SkyLight.Data = compound.Get<NbtByteArray>("SkyLight").Value;
         section.Metadata.Data = compound.Get<NbtByteArray>("Data").Value;
         // Process section
         section.ProcessSection();
         chunk.Sections[y] = section;
     }
     var tileEntities = root.Get<NbtList>("TileEntities");
     if (tileEntities != null)
     {
         foreach (var tag in tileEntities)
         {
             Vector3 tilePosition;
             var entity = TileEntity.FromNbt(tag as NbtCompound, out tilePosition);
             if (entity != null)
                 chunk.TileEntities.Add(tilePosition, entity);
         }
     }
     return chunk;
 }
예제 #11
0
        public ChunkDataPacket(ref Chunk chunk)
        {
            X = (int)chunk.AbsolutePosition.X;
            Z = (int)chunk.AbsolutePosition.Z;

            byte[] blockData;
            byte[] metadata;
            byte[] blockLight;
            byte[] skyLight;

            ushort mask = 1, chunkY = 0;
            bool nonAir = true;

            // First pass calculates number of sections to send
            int totalSections = 0;
            for (int i = 15; i >= 0; i--)
            {
                Section s = chunk.Sections[chunkY++];

                if (s.IsAir)
                    nonAir = false;
                if (nonAir)
                    totalSections++;
                mask <<= 1;
            }

            mask = 1;
            chunkY = 0;
            nonAir = true;
            blockData = new byte[totalSections * BlockDataLength];
            metadata = new byte[totalSections * NibbleDataLength];
            blockLight = new byte[totalSections * NibbleDataLength];
            skyLight = new byte[totalSections * NibbleDataLength];

            // Second pass produces the arrays
            for (int i = 15; i >= 0; i--)
            {
                Section s = chunk.Sections[chunkY++];

                if (s.IsAir)
                    nonAir = false;
                if (nonAir)
                {
                    Array.Copy(s.Blocks, 0, blockData, (chunkY - 1) * BlockDataLength, BlockDataLength);
                    Array.Copy(s.Metadata.Data, 0, metadata, (chunkY - 1) * NibbleDataLength, NibbleDataLength);
                    Array.Copy(s.BlockLight.Data, 0, blockLight, (chunkY - 1) * NibbleDataLength, NibbleDataLength);
                    Array.Copy(s.SkyLight.Data, 0, skyLight, (chunkY - 1) * NibbleDataLength, NibbleDataLength);

                    PrimaryBitMap |= mask;
                }

                mask <<= 1;
            }

            // Create the final array
            // TODO: Merge this into the other loop, reduce objects
            byte[] data = new byte[blockData.Length + metadata.Length +
                blockLight.Length + skyLight.Length + chunk.Biomes.Length];
            int index = 0;
            Array.Copy(blockData, 0, data, index, blockData.Length); index += blockData.Length;
            Array.Copy(metadata, 0, data, index, metadata.Length); index += metadata.Length;
            Array.Copy(blockLight, 0, data, index, blockLight.Length); index += blockLight.Length;
            Array.Copy(skyLight, 0, data, index, skyLight.Length); index += skyLight.Length;
            Array.Copy(chunk.Biomes, 0, data, index, chunk.Biomes.Length);

            // Compress the array
            var result = ZlibStream.CompressBuffer(data);
            CompressedData = result;

            GroundUpContiguous = true;
        }
예제 #12
0
        private Vector3 FindBlockPosition(Vector3 position, out Chunk chunk)
        {
            var x = Math.Floor(position.X);
            var y = Math.Floor(position.Y);
            var z = Math.Floor(position.Z);

            if (y < 0 || y >= Chunk.Height)
                throw new ArgumentOutOfRangeException("position", "Position is out of range");

            var chunkX = Math.Floor(x / (Chunk.Width));
            var chunkZ = Math.Floor(z / (Chunk.Depth));

            chunk = GetChunk(new Vector3(chunkX, 0, chunkZ));
            return new Vector3((x - chunkX * Chunk.Width) % Chunk.Width, y, (z - chunkZ * Chunk.Depth) % Chunk.Depth);
        }
예제 #13
0
파일: Chunk.cs 프로젝트: pdelvo/Craft.Net
 public static Chunk FromNbt(Vector3 position, NbtFile nbt)
 {
     Chunk chunk = new Chunk(position);
     // Load data
     var root = nbt.RootTag.Get<NbtCompound>("Level");
     chunk.Biomes = root.Get<NbtByteArray>("Biomes").Value;
     chunk.HeightMap = root.Get<NbtIntArray>("HeightMap").Value;
     var sections = root.Get<NbtList>("Sections");
     foreach (var sectionTag in sections.Tags)
     {
         // Load data
         var compound = (NbtCompound)sectionTag;
         byte y = compound.Get<NbtByte>("Y").Value;
         var section = new Section(y);
         section.Blocks = compound.Get<NbtByteArray>("Blocks").Value;
         section.BlockLight.Data = compound.Get<NbtByteArray>("BlockLight").Value;
         section.SkyLight.Data = compound.Get<NbtByteArray>("SkyLight").Value;
         section.Metadata.Data = compound.Get<NbtByteArray>("Data").Value;
         // Process section
         section.ProcessSection();
         chunk.Sections[y] = section;
     }
     return chunk;
 }
예제 #14
0
 internal ReadOnlyChunk(Chunk chunk)
 {
     Chunk = chunk;
 }
예제 #15
0
 internal void SetChunk(Vector3 position, Chunk chunk)
 {
     World.SetChunk(position, chunk);
 }