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); }
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); // } // } //} }
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))); } }
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); }
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))); }
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))); }
/// <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; }
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); }
/// <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); }
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; }
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; }
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); }
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; }
internal ReadOnlyChunk(Chunk chunk) { Chunk = chunk; }
internal void SetChunk(Vector3 position, Chunk chunk) { World.SetChunk(position, chunk); }