private static void AddChunk(MinecraftClient client, int x, int z, ushort primaryBitMap, ushort addBitMap, bool lightIncluded, bool groundUp, byte[] data) { var coordinates = new Coordinates2D(x, z); var relativePosition = GetRelativeChunkPosition(coordinates); 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) { // 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); } } } if (groundUp) Array.Copy(data, data.Length - chunk.Biomes.Length, chunk.Biomes, 0, chunk.Biomes.Length); client.World.SetChunk(coordinates, chunk); //client.OnChunkRecieved(new ChunkRecievedEventArgs(position, new ReadOnlyChunk(chunk))); }
public void SetChunk(Coordinates2D coordinates, Chunk chunk) { int regionX = coordinates.X / Region.Width - ((coordinates.X < 0) ? 1 : 0); int regionZ = coordinates.Z / Region.Depth - ((coordinates.Z < 0) ? 1 : 0); var region = LoadOrGenerateRegion(new Coordinates2D(regionX, regionZ)); lock (region) { chunk.IsModified = true; region.SetChunk(new Coordinates2D(coordinates.X - regionX * 32, coordinates.Z - regionZ * 32), chunk); } }
public Chunk GenerateChunk(Coordinates2D position) { var chunk = new Chunk(position); int y = 0; for (int i = 0; i < Layers.Count; i++) { int height = y + Layers[i].Height; while (y < height) { for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { chunk.SetBlockId(new Coordinates3D(x, y, z), Layers[i].BlockId); chunk.SetMetadata(new Coordinates3D(x, y, z), Layers[i].Metadata); } } y++; } } for (int i = 0; i < chunk.Biomes.Length; i++) chunk.Biomes[i] = (byte)Biome; return chunk; }
public Coordinates3D FindBlockPosition(Coordinates3D coordinates, out Chunk chunk) { if (coordinates.Y < 0 || coordinates.Y >= Chunk.Height) throw new ArgumentOutOfRangeException("coordinates", "Coordinates are out of range"); var chunkX = (int)Math.Floor((double)coordinates.X / Chunk.Width); var chunkZ = (int)Math.Floor((double)coordinates.Z / Chunk.Depth); chunk = GetChunk(new Coordinates2D(chunkX, chunkZ)); return new Coordinates3D( (coordinates.X - chunkX * Chunk.Width) % Chunk.Width, coordinates.Y, (coordinates.Z - chunkZ * Chunk.Depth) % Chunk.Depth); }
internal ReadOnlyChunk(Chunk chunk) { Chunk = chunk; }
internal void SetChunk(Coordinates2D coordinates, Chunk chunk) { World.SetChunk(coordinates, chunk); }
/// <summary> /// Sets the chunk at the specified local position to the given value. /// </summary> public void SetChunk(Coordinates2D position, Chunk chunk) { if (!Chunks.ContainsKey(position)) Chunks.Add(position, chunk); chunk.IsModified = true; chunk.X = position.X; chunk.Z = position.Z; chunk.LastAccessed = DateTime.Now; Chunks[position] = chunk; }
/// <summary> /// Generates a chunk by getting an array of heights then placing blocks of varying types up to that height /// then it adds trees (leaves first then trunk) /// /// </summary> /// <returns>The chunk.</returns> /// <param name="position">Position.</param> public Chunk GenerateChunk(Coordinates2D position) { // TODO: Add Ores // TODO: Add Caves int trees = new Random().Next(0, 10); int[,] heights = new int[16, 16]; int[,] treeBasePositions = new int[trees, 2]; for (int t = 0; t < trees; t++) { treeBasePositions[t, 0] = new Random().Next(1, 16); treeBasePositions[t, 1] = new Random().Next(1, 16); } //Make a new Chunk var chunk = new Chunk(position); //Loop through all the blocks in the chunk for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { int height = GetHeight(chunk.X * Chunk.Width + x, chunk.Z * Chunk.Depth + z); for (int y = 0; y < height; y++) { if (y == 0) // if at the bottom then set block to bedrock chunk.SetBlockId(new Coordinates3D(x, y, z), 7); else if (y < height - 1) // if not at the top set the block to dirt or stone depending on height { if (!(y < (height / 4) * 3)) chunk.SetBlockId(new Coordinates3D(x, y, z), 3); else chunk.SetBlockId(new Coordinates3D(x, y, z), 1); } else if (y < waterLevel) // if below the water set to sand or clay { if (new Random().Next(1, 40) < 5 && y < waterLevel - 4) chunk.SetBlockId(new Coordinates3D(x, y, z), 82); else chunk.SetBlockId(new Coordinates3D(x, y, z), 12); } else { // otherwise set the block to grass or gravel rarely chunk.SetBlockId(new Coordinates3D(x, y, z), 2); } chunk.SetBiome((byte)x, (byte)z, Biome.ExtremeHills); if (y < waterLevel + 17) chunk.SetBiome((byte)x, (byte)z, Biome.ExtremeHillsEdge); if (y < waterLevel + 10) chunk.SetBiome((byte)x, (byte)z, Biome.Beach); } heights[x, z] = height; //create beaches and place water if (height <= waterLevel) { for (int w = 0; w < waterLevel - 3; w++) { if (chunk.GetBlockId(new Coordinates3D(x, w, z)) == 0) { chunk.SetBlockId(new Coordinates3D(x, w, z), 8); } } } // Generate colour of the wood and leaves int woodColor = new Random().Next(1, 3); if (woodColor == 1) woodColor = 0; // Generate trees for (int pos = 0; pos < trees; pos++) { int random = new Random().Next(3, 4); int treeBase = heights[treeBasePositions[pos, 0], treeBasePositions[pos, 1]];//chunk.GetHeight((byte)treeBasePositions[pos, 0], (byte)treeBasePositions[pos, 1]); if (treeBasePositions[pos, 0] < 14 && treeBasePositions[pos, 0] > 4 && treeBasePositions[pos, 1] < 14 && treeBasePositions[pos, 1] > 4) { if (treeBase < waterLevel + 10) break; int leafwidth = 4; for (int layer = 0; layer <= height; layer++) { for (int w = 0; w <= leafwidth; w++) { for (int l = 0; l <= leafwidth; l++) { chunk.SetBlockId(new Coordinates3D(treeBasePositions[pos, 0] - (leafwidth / 2) + w, treeBase + layer + random, treeBasePositions[pos, 1] - (leafwidth / 2) + l), 18); chunk.SetMetadata(new Coordinates3D(treeBasePositions[pos, 0] - (leafwidth / 2) + w, treeBase + layer + random, treeBasePositions[pos, 1] - (leafwidth / 2) + l), (byte)woodColor); } } leafwidth -= 1; } for (int t = 0; t <= (random + 2); t++) { chunk.SetBlockId(new Coordinates3D(treeBasePositions[pos, 0], treeBase + t, treeBasePositions[pos, 1]), 17); chunk.SetMetadata(new Coordinates3D(treeBasePositions[pos, 0], treeBase + t, treeBasePositions[pos, 1]), (byte)woodColor); } } } } } return chunk; }
public static ChunkDataPacket CreatePacket(Chunk chunk) { var X = chunk.X; var Z = chunk.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; chunkY = 0; nonAir = true; blockData = new byte[totalSections * BlockDataLength]; metadata = new byte[totalSections * NibbleDataLength]; blockLight = new byte[totalSections * NibbleDataLength]; skyLight = new byte[totalSections * NibbleDataLength]; ushort PrimaryBitMap = 0, AddBitMap = 0; // 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); var GroundUpContiguous = true; return new ChunkDataPacket(X, Z, GroundUpContiguous, PrimaryBitMap, AddBitMap, result); }