public void generate(Chunk chunk, Random rnd) { CachedChunk3x3 cc3x3 = CachedChunk3x3.getNewRegion(chunk.world, chunk); int x, z; Block groundBlock; BlockPos pos, pos1; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { x = i * 5 + rnd.Next(0, 4); z = j * 5 + rnd.Next(0, 4); if (rnd.Next(0, 2) != 0) { for (int y = 0; y < Chunk.SIZE; y++) { pos = new BlockPos(x, y, z); pos1 = pos.move(Direction.DOWN); groundBlock = cc3x3.getBlock(pos1.x, pos1.y, pos1.z); if (cc3x3.getBlock(pos.x, pos.y, pos.z) == Block.air && (groundBlock == Block.dirt || groundBlock == Block.grass)) { this.makeTree(cc3x3, rnd, pos); } } } } } }
public void updateLighting(int newLight, int startX, int startY, int startZ) { Chunk c = this.world.getChunk(startX, startY, startZ); this.region = CachedChunk3x3.getNewRegion(this.world, c); this.orginX = c.worldPos.x; this.orginY = c.worldPos.y; this.orginZ = c.worldPos.z; /* * * // Make x, y, and z local within the chunk * x -= c.worldPos.x; * y -= c.worldPos.y; * z -= c.worldPos.z; * * // Populate the lookup table. * int i, j, k; * for (i = 0; i <= 29; i++) { * for (j = 0; j <= 29; j++) { * for (k = 0; k <= 29; k++) { * this.lightLookup[(j * Chunk.SIZE * Chunk.SIZE) + (k * Chunk.SIZE) + i] = * (byte)this.region.getLight(x + i - 14, y + j - 14, z + k - 14); * } * } * } */ int x, y, z, neighborLevel, lightLevel; LightRemovalNode node; this.removalQueue.Enqueue(new LightRemovalNode(startX, startY, startZ, this.getLight(startX, startY, startZ))); this.world.setLight(startX, startY, startZ, 0); while (this.removalQueue.Count > 0) { node = this.removalQueue.Dequeue(); x = node.x; y = node.y; z = node.z; lightLevel = node.lightLevel; int ox = x - this.orginX; int oy = y - this.orginY; int oz = z - this.orginZ; // -X neighborLevel = this.getLight(x - 1, y, z); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox - 1, oy, oz, 0); this.removalQueue.Enqueue(new LightRemovalNode(x - 1, y, z, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x - 1, y, z)); } // +X neighborLevel = this.getLight(x + 1, y, z); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox + 1, oy, oz, 0); this.removalQueue.Enqueue(new LightRemovalNode(x + 1, y, z, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x + 1, y, z)); } // -Y neighborLevel = this.getLight(x, y - 1, z); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox, oy - 1, oz, 0); this.removalQueue.Enqueue(new LightRemovalNode(x, y - 1, z, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x, y - 1, z)); } // +Y neighborLevel = this.getLight(x, y + 1, z); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox, oy + 1, oz, 0); this.removalQueue.Enqueue(new LightRemovalNode(x, y + 1, z, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x, y + 1, z)); } // -Z neighborLevel = this.getLight(x, y, z - 1); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox, oy, oz - 1, 0); this.removalQueue.Enqueue(new LightRemovalNode(x, y, z - 1, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x, y, z - 1)); } // +Z neighborLevel = this.getLight(x, y, z + 1); if (neighborLevel != 0 && neighborLevel < lightLevel) { this.region.setLight(ox, oy, oz + 1, 0); this.removalQueue.Enqueue(new LightRemovalNode(x, y, z + 1, neighborLevel)); } else if (neighborLevel >= lightLevel) { this.queue.Enqueue(new BlockPos(x, y, z + 1)); } } this.setLight(startX, startY, startZ, newLight); this.queue.Enqueue(new BlockPos(startX, startY, startZ)); BlockPos pos; while (this.queue.Count > 0) { pos = this.queue.Dequeue(); x = pos.x; y = pos.y; z = pos.z; lightLevel = this.getLight(x, y, z); if (!this.getBlock(x - 1, y, z).isSolid&& this.getLight(x - 1, y, z) + 2 <= lightLevel) { this.setLight(x - 1, y, z, lightLevel - 1); this.queue.Enqueue(new BlockPos(x - 1, y, z)); } if (!this.getBlock(x + 1, y, z).isSolid&& this.getLight(x + 1, y, z) + 2 <= lightLevel) { this.setLight(x + 1, y, z, lightLevel - 1); this.queue.Enqueue(new BlockPos(x + 1, y, z)); } if (!this.getBlock(x, y - 1, z).isSolid&& this.getLight(x, y - 1, z) + 2 <= lightLevel) { this.setLight(x, y - 1, z, lightLevel - 1); this.queue.Enqueue(new BlockPos(x, y - 1, z)); } if (!this.getBlock(x, y + 1, z).isSolid&& this.getLight(x, y + 1, z) + 2 <= lightLevel) { this.setLight(x, y + 1, z, lightLevel - 1); this.queue.Enqueue(new BlockPos(x, y + 1, z)); } if (!this.getBlock(x, y, z - 1).isSolid&& this.getLight(x, y, z - 1) + 2 <= lightLevel) { this.setLight(x, y, z - 1, lightLevel - 1); this.queue.Enqueue(new BlockPos(x, y, z - 1)); } if (!this.getBlock(x, y, z + 1).isSolid&& this.getLight(x, y, z + 1) + 2 <= lightLevel) { this.setLight(x, y, z + 1, lightLevel - 1); this.queue.Enqueue(new BlockPos(x, y, z + 1)); } } this.removalQueue.Clear(); this.queue.Clear(); }
/// <summary> /// Bakes the block meshes and light levels into the chunk. /// </summary> public void renderChunk() { CachedChunk3x3 cachedRegion = CachedChunk3x3.getNewRegion(this.world, this); if (!cachedRegion.allChunksLoaded()) { // Waiting for the lazy chunk loading to finish... return; } this.isDirty = false; MeshBuilder meshBuilder = RenderManager.getMeshBuilder(); Block currentBlock, neighborBlock; bool isSolid; Block[] surroundingBlocks = new Block[6]; BlockPos dirPos; int x, y, z, i, facesCulled, x1, y1, z1, renderFaceMask, x2, y2, z2; Direction direction; // Bake blocks into mesh. for (x = 0; x < Chunk.SIZE; x++) { for (y = 0; y < Chunk.SIZE; y++) { for (z = 0; z < Chunk.SIZE; z++) { currentBlock = this.getBlock(x, y, z); if (currentBlock.renderer != null && currentBlock.renderer.bakeIntoChunks) { renderFaceMask = 0; // Find the surrounding blocks and faces to cull. facesCulled = 0; for (i = 0; i < 6; i++) { direction = Direction.all[i]; dirPos = direction.blockPos; x1 = x + dirPos.x; y1 = y + dirPos.y; z1 = z + dirPos.z; if (x1 < 0 || y1 < 0 || z1 < 0 || x1 >= Chunk.SIZE || y1 >= Chunk.SIZE || z1 >= Chunk.SIZE) { neighborBlock = cachedRegion.getBlock(x1, y1, z1); } else { neighborBlock = this.getBlock(x1, y1, z1); } isSolid = neighborBlock.isSolid; if (!isSolid) { renderFaceMask |= direction.renderMask; } if (currentBlock.renderer.lookupAdjacentBlocks) { surroundingBlocks[i] = neighborBlock; } if (isSolid) { facesCulled++; } } // If at least one face is visible, render the block. if (facesCulled != 6) { // Populate the meshData with light levels. if (currentBlock.renderer.lookupAdjacentLight) { for (x2 = -1; x2 <= 1; x2++) { for (y2 = -1; y2 <= 1; y2++) { for (z2 = -1; z2 <= 1; z2++) { x1 = x + x2; y1 = y + y2; z1 = z + z2; meshBuilder.setLightLevel(x2, y2, z2, x1 < 0 || y1 < 0 || z1 < 0 || x1 >= Chunk.SIZE || y1 >= Chunk.SIZE || z1 >= Chunk.SIZE ? cachedRegion.getLight(x1, y1, z1) : this.getLight(x1, y1, z1)); } } } } else { meshBuilder.setLightLevel(0, 0, 0, this.getLight(x, y, z)); } // Render the block. currentBlock.renderer.renderBlock(currentBlock, this.getMeta(x, y, z), meshBuilder, x, y, z, renderFaceMask, surroundingBlocks); } } } } } // Set light UVs for tile entities that don't bake into the chunk. Material[] materials; Color lightColor; foreach (TileEntityBase te in this.tileEntityDict.Values) { if (te is TileEntityGameObject) { x = te.posX - this.worldPos.x; y = te.posY - this.worldPos.y; z = te.posZ - this.worldPos.z; materials = ((TileEntityGameObject)te).modelMaterials; lightColor = RenderManager.instance.lightColors.getColorFromBrightness(this.getLight(x, y, z)); for (i = 0; i < materials.Length; i++) { materials[i].SetColor(LightColors.SERIALIZED_LightColor, lightColor); } } } this.filter.mesh = meshBuilder.getGraphicMesh(); this.blockCollider.sharedMesh = meshBuilder.getColliderMesh(); }
protected abstract void makeTree(CachedChunk3x3 region, Random rnd, BlockPos pos);
protected override void makeTree(CachedChunk3x3 region, Random rnd, BlockPos pos) { int height = pos.y + 4 + rnd.Next(3); // Make sure the area is clear. /* * for (int y = pos.y; y < height; y++) { * int i = y <= 2 ? 0 : 2; * for (int x = pos.x - i; x <= pos.x + i; x++) { * for (int z = pos.z - i; z <= pos.z + i; z++) { * if(!(this.isReplacable(world.getBlock(x, y, z)))) { * return; * } * } * } * } */ // Generate tree for (int y = pos.y; y <= height; y++) { if (y == height - 3 || y == height - 2) { for (int x = pos.x - 2; x <= pos.x + 2; x++) { for (int z = pos.z - 2; z <= pos.z + 2; z++) { if (Math.Abs(x) == 2 && Math.Abs(z) == 2 && rnd.Next(2) == 0) { continue; } region.setBlock(x, y, z, Block.leaves); } } } else if (y == height - 1) { for (int x = pos.x - 1; x <= pos.x + 1; x++) { for (int z = pos.z - 1; z <= pos.z + 1; z++) { region.setBlock(x, y, z, Block.leaves); } } } else if (y == height) { region.setBlock(pos.x + 1, y, pos.z, Block.leaves); region.setBlock(pos.x - 1, y, pos.z, Block.leaves); region.setBlock(pos.x, y, pos.z + 1, Block.leaves); region.setBlock(pos.x, y, pos.z - 1, Block.leaves); region.setBlock(pos.x, y, pos.z, Block.leaves); } if (y != height) { region.setBlock(pos.x, y, pos.z, Block.wood, 1); } } }