private void GenerateChunk(IWorld world, ChunkColumnCompactStorage chunk, int x, int z, GeneratorSettings settings) { // 按照flat模式每层的设置给chunk赋值 for (int y = 0; y < settings.FlatBlockId.Length; ++y) { var section = chunk.Sections[y / 16]; var state = settings.FlatBlockId[y]; if (state != null) { for (int j = 0; j < 16; ++j) { for (int k = 0; k < 16; ++k) { section.Data[j, y % 16, k] = new BlockState { Id = state.Value.Id, MetaValue = state.Value.MetaValue } } ; } } for (int i = 0; i < section.SkyLight.Storage.Length; i++) { section.SkyLight.Storage[i] = 0xFF; } } // todo biomes }
// 添加其他东西 public override void Decorate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random rand, BlockWorldPos pos) { GenCacti(world, grainFactory, chunk, rand, pos); // TODO 生成仙人掌和枯木 base.Decorate(world, grainFactory, chunk, rand, pos); }
public bool CanCactiGrow(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos, int height) { bool result = true; // 检查所有方块可替换 for (int y = pos.Y; y <= pos.Y + 1 + height; ++y) { int xzSize = 1; // 检查这个平面所有方块可替换 for (int x = pos.X - xzSize; x <= pos.X + xzSize && result; ++x) { for (int z = pos.Z - xzSize; z <= pos.Z + xzSize && result; ++z) { if (y >= 0 && y < 256) { BlockChunkPos chunkPos = new BlockWorldPos(x, y, z).ToBlockChunkPos(); BlockState state = chunk[chunkPos.X, chunkPos.Y, chunkPos.Z]; if (!state.IsAir()) { result = false; } } else { result = false; } } } } return(result); }
public void GenTrees(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockWorldPos pos) { int treesPerChunk = _treesPerChunk; if (random.NextDouble() < _extraTreeChance) { ++treesPerChunk; } for (int num = 0; num < treesPerChunk; ++num) { int x = random.Next(12) + 2; int z = random.Next(12) + 2; TreeGenerator treeGenerator = new TreeGenerator(5, false, GetRandomTree(random)); // 获得地表面高度 int h = 0; for (int y = 255; y >= 0; --y) { if (!chunk[x, y, z].IsAir()) { h = y + 1; break; } } treeGenerator.Generate(world, grainFactory, chunk, this, random, new BlockWorldPos(pos.X + x, h, pos.Z + z)); } }
private Task DispatchPacket(ChunkData packet) { var column = new ChunkColumnCompactStorage(packet.Biomes); var mask = packet.PrimaryBitMask; int index = 0; int srcIndex = 0; while (index < ChunkConstants.SectionsPerChunk) { if ((mask & 1) == 1) { var src = packet.Data[srcIndex]; column.Sections[index] = new ChunkSectionCompactStorage( new ChunkSectionCompactStorage.DataArray(src.DataArray), new ChunkSectionCompactStorage.NibbleArray(src.BlockLight), src.SkyLight != null ? new ChunkSectionCompactStorage.NibbleArray(src.SkyLight) : null); srcIndex++; } mask >>= 1; index++; } System.Diagnostics.Debug.Assert(packet.PrimaryBitMask == column.SectionBitMask, "PrimaryBitMask must be equal."); _chunkLoader.LoadTerrain(packet.ChunkX, packet.ChunkZ, column); return(Task.CompletedTask); }
public async Task Populate(IWorld world, int x, int z, GeneratorSettings settings) { var chunkColumnKey = world.MakeAddressByPartitionKey(new ChunkWorldPos { X = x, Z = z }); ChunkColumnCompactStorage chunkColumn = await GrainFactory.GetGrain <IChunkColumn>(chunkColumnKey).GetStateUnsafe(); Biome chunkBiome = Biome.GetBiome(chunkColumn.Biomes[7 * 16 + 7], settings); if (chunkBiome.GetBiomeId() == BiomeId.Plains) { var decorator = GrainFactory.GetGrain <IBiomePlainsDecorator>((long)BiomeId.Plains); await decorator.Decorate(world, new ChunkWorldPos(x, z), settings); // decorator.SpawnMob(world, chunk, new ChunkWorldPos(x, z), new BlockWorldPos { X = blockX, Z = blockZ }); } else if (chunkBiome.GetBiomeId() == BiomeId.Forest) { var decorator = GrainFactory.GetGrain <IBiomeForestDecorator>((long)BiomeId.Forest); await decorator.Decorate(world, new ChunkWorldPos(x, z), settings); } else if (chunkBiome.GetBiomeId() == BiomeId.Taiga) { var decorator = GrainFactory.GetGrain <IBiomeTaigaDecorator>((long)BiomeId.Taiga); await decorator.Decorate(world, new ChunkWorldPos(x, z), settings); } else if (chunkBiome.GetBiomeId() == BiomeId.Savanna) { var decorator = GrainFactory.GetGrain <IBiomeSavannaDecorator>((long)BiomeId.Savanna); await decorator.Decorate(world, new ChunkWorldPos(x, z), settings); } }
public async Task Populate(IWorld world, int x, int z, GeneratorSettings settings) { var chunkColumnKey = world.MakeAddressByPartitionKey(new ChunkWorldPos { X = x, Z = z }); ChunkColumnCompactStorage chunkColumn = await GrainFactory.GetGrain <IChunkColumn>(chunkColumnKey).GetState(); PopulateChunk(world, chunkColumn, x, z, settings); }
public void LoadFromChunkData(int chunkX, int chunkZ, ChunkColumnCompactStorage column, NeighborColumns neighborColumns) { for (int i = 0; i < 16; i++) { var src = column.Sections[i]; if (src != null) { InstantiateSection(i, src, column, neighborColumns); } } }
public void LoadTerrain(int chunkX, int chunkZ, ChunkColumnCompactStorage column) { var key = new Vector2Int(chunkX, chunkZ); _sections.Add(key, column); var updater = InstantiateUpdater(chunkX, chunkZ); _updater.Add(key, updater); updater?.LoadFromChunkData(chunkX, chunkZ, column, FindNeighborColumns(key)); UpdateNeighborChunks(key); }
public bool CanFlowerGrow(PlantsType type, ChunkColumnCompactStorage chunk, BlockChunkPos pos) { if (chunk[pos.X, pos.Y - 1, pos.Z] == BlockStates.GrassBlock() || chunk[pos.X, pos.Y - 1, pos.Z] == BlockStates.Dirt()) { return(true); } else { return(false); } }
public Task <ChunkColumnCompactStorage> Generate(IWorld world, int x, int z, GeneratorSettings settings) { var chunkColumn = new ChunkColumnCompactStorage(); for (int i = 0; i < chunkColumn.Sections.Length; ++i) { chunkColumn.Sections[i] = new ChunkSectionCompactStorage(true); } GenerateChunk(world, chunkColumn, x, z, settings); PopulateChunk(world, chunkColumn, x, z, settings); return(Task.FromResult(chunkColumn)); }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); int x = chunkPos.X; int y = chunkPos.Y; int z = chunkPos.Z; // TODO use block accessor if (chunk[x, y, z].IsAir() && chunk[x, y - 1, z] == BlockStates.GrassBlock()) { chunk[x, y, z] = BlockStates.Grass(GrassType.TallGrass); } }
// 添加其他东西 public override void Decorate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random rand, BlockWorldPos pos) { float grassColor = (_grassColorNoise.Noise((pos.X + 8) / 200.0F, 0.0F, (pos.Z + 8) / 200.0F) - 0.5F) * 2; if (grassColor < -0.8F) { _flowersPerChunk = 15; _grassPerChunk = 5 * 7; GenDoubleFlowers(world, grainFactory, chunk, rand, pos); } else { _flowersPerChunk = 4; _grassPerChunk = 10 * 7; } GenGrass(world, grainFactory, chunk, rand, pos); GenFlowers(world, grainFactory, chunk, rand, pos); GenDoubleGrass(world, grainFactory, chunk, rand, pos); int treesPerChunk = _treesPerChunk; if (rand.NextDouble() < _extraTreeChance) { ++treesPerChunk; } for (int num = 0; num < treesPerChunk; ++num) { int x = rand.Next(12) + 2; int z = rand.Next(12) + 2; TreeGenerator treeGenerator = new TreeGenerator(5, false, GetRandomTree(rand)); // 获得地表面高度 int h = 0; for (int y = 255; y >= 0; --y) { if (!chunk[x, y, z].IsAir()) { h = y + 1; break; } } treeGenerator.Generate(world, grainFactory, chunk, this, rand, new BlockWorldPos(pos.X + x, h, pos.Z + z)); } base.Decorate(world, grainFactory, chunk, rand, pos); }
// 添加生物群系特有的生物 public override void SpawnMob(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random rand, BlockWorldPos pos) { ChunkWorldPos chunkPos = pos.ToChunkWorldPos(); int seed = chunkPos.Z * 16384 + chunkPos.X; Random r = new Random(seed); foreach (MobType eachType in _passiveMobList) { if (r.Next(32) == 0) { PassiveMobSpawner spawner = new PassiveMobSpawner(eachType, 15); spawner.Spawn(world, grainFactory, chunk, rand, new BlockWorldPos(pos.X, pos.Y, pos.Z)); } } }
// ��������һЩ���飬Biome������Ҫ���ɿ��� public virtual void Decorate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random rand, BlockWorldPos pos) { GenerateOre(_dirtGen, world, grainFactory, chunk, rand, pos, _genSettings.DirtCount, _genSettings.DirtMaxHeight, _genSettings.DirtMinHeight); GenerateOre(_gravelOreGen, world, grainFactory, chunk, rand, pos, _genSettings.GravelCount, _genSettings.GravelMaxHeight, _genSettings.GravelMinHeight); GenerateOre(_graniteGen, world, grainFactory, chunk, rand, pos, _genSettings.GraniteCount, _genSettings.GraniteMaxHeight, _genSettings.GraniteMinHeight); GenerateOre(_dioriteGen, world, grainFactory, chunk, rand, pos, _genSettings.DioriteCount, _genSettings.DioriteMaxHeight, _genSettings.DioriteMinHeight); GenerateOre(_andesiteGen, world, grainFactory, chunk, rand, pos, _genSettings.AndesiteCount, _genSettings.AndesiteMaxHeight, _genSettings.AndesiteMinHeight); GenerateOre(_coalGen, world, grainFactory, chunk, rand, pos, _genSettings.CoalCount, _genSettings.CoalMaxHeight, _genSettings.CoalMinHeight); GenerateOre(_ironGen, world, grainFactory, chunk, rand, pos, _genSettings.IronCount, _genSettings.IronMaxHeight, _genSettings.IronMinHeight); GenerateOre(_goldGen, world, grainFactory, chunk, rand, pos, _genSettings.GoldCount, _genSettings.GoldMaxHeight, _genSettings.GoldMinHeight); GenerateOre(_redstoneGen, world, grainFactory, chunk, rand, pos, _genSettings.RedstoneCount, _genSettings.RedstoneMaxHeight, _genSettings.RedstoneMinHeight); GenerateOre(_diamondGen, world, grainFactory, chunk, rand, pos, _genSettings.DiamondCount, _genSettings.DiamondMaxHeight, _genSettings.DiamondMinHeight); GenerateOre(_lapisGen, world, grainFactory, chunk, rand, pos, _genSettings.LapisCount, _genSettings.LapisCenterHeight + _genSettings.LapisSpread, _genSettings.LapisCenterHeight - _genSettings.LapisSpread); }
public bool CanTreeGrow(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos, int height) { bool result = true; // 检查所有方块可替换 for (int y = pos.Y; y <= pos.Y + 1 + height; ++y) { int xzSize = 1; // 底端 if (y == pos.Y) { xzSize = 0; } // 顶端 if (y >= pos.Y + height - 1) { xzSize = 2; } // 检查这个平面所有方块可替换 for (int x = pos.X - xzSize; x <= pos.X + xzSize && result; ++x) { for (int z = pos.Z - xzSize; z <= pos.Z + xzSize && result; ++z) { if (y >= 0 && y < 256) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); BlockState state = chunk[chunkPos.X, chunkPos.Y, chunkPos.Z]; if (!state.IsAir() && state.IsSameId(BlockStates.Leaves()) && state.IsSameId(BlockStates.Leaves2())) { result = false; } } else { result = false; } } } } return(result); }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int num = random.Next(_flowersMaxNum); for (int i = 0; i < num; ++i) { BlockWorldPos blockpos = BlockWorldPos.Add(pos, random.Next(8), random.Next(4), random.Next(8)); BlockChunkPos chunkpos = blockpos.ToBlockChunkPos(); if (chunk[chunkpos.X, chunkpos.Y, chunkpos.Z].IsAir() && blockpos.Y < 254 && CanFlowerGrow(_flowerType, chunk, chunkpos)) { chunk[chunkpos.X, chunkpos.Y, chunkpos.Z] = BlockStates.LargeFlowers(LargeFlowerType.Sunflower); chunk[chunkpos.X, chunkpos.Y + 1, chunkpos.Z] = BlockStates.LargeFlowers(LargeFlowerType.TopHalfFlag); } } }
private void GenDoubleGrass(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockWorldPos pos) { DoubleGrassGenerator generator = new DoubleGrassGenerator(PlantsType.DoubleTallgrass); for (int grassNum = 0; grassNum < 2; ++grassNum) { int x = random.Next(16); int z = random.Next(16); for (int y = 255; y >= 1; --y) { if (!chunk[x, y, z].IsAir()) { generator.Generate(world, grainFactory, chunk, this, random, new BlockWorldPos(pos.X + x, y + 1, pos.Z + z)); break; } } } }
private void GenFlowers(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockWorldPos pos) { int flowersMaxNum = random.Next(_flowersPerChunk); FlowersGenerator generator = new FlowersGenerator(); for (int flowersNum = 0; flowersNum < flowersMaxNum; ++flowersNum) { int x = random.Next(16); int z = random.Next(16); for (int y = 255; y >= 1; --y) { if (!chunk[x, y, z].IsAir()) { generator.Generate(world, grainFactory, chunk, this, random, new BlockWorldPos(pos.X + x, y + 1, pos.Z + z)); break; } } } }
public async void Spawn(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockWorldPos pos) { int num = random.Next(_groupMaxNum); for (int n = 0; n < num; ++n) { int x = random.Next(16); int z = random.Next(16); int height; for (height = 255; height >= 0; height--) { if (chunk[x, height, z] != BlockStates.Air()) { break; } } BlockWorldPos standPos = new BlockWorldPos(pos.X + x, height + 1, pos.Z + z); if (CanMobStand(world, grainFactory, chunk, random, standPos.ToBlockChunkPos())) { // 添加一个生物 /* * var eid = await world.NewEntityId(); * var entity = grainFactory.GetGrain<IPassiveMob>(world.MakeEntityKey(eid)); * await world.AttachEntity(entity); * * await entity.Spawn(Guid.NewGuid(), new Vector3(pos.X + x + 0.5F, height + 1, pos.Z + z + 0.5F), _mobType); * await entity.OnCreated(); */ IMob entity = grainFactory.GetGrain <IMob>(Guid.NewGuid()); await entity.Tell(new SpawnMob { World = world, EntityId = await world.NewEntityId(), Position = new EntityWorldPos(pos.X + x + 0.5F, height + 1, pos.Z + z + 0.5F), MobType = _mobType, }); } } }
public bool CanMobStand(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockChunkPos pos) { // TODO 以后结合boundbox判断 if (pos.Y <= 0 || pos.Y >= 255) { return(false); } BlockChunkPos downPos = new BlockChunkPos(pos.X, pos.Y - 1, pos.Z); if (chunk[pos.X, pos.Y - 1, pos.Z].IsLightOpacity() == 0) { if (chunk[pos.X, pos.Y, pos.Z] == BlockStates.Air() && chunk[pos.X, pos.Y + 1, pos.Z] == BlockStates.Air()) { return(true); } } return(false); }
private NeighborSections FindNeighborSections(ChunkColumnCompactStorage column, NeighborColumns neighborColumns, int y) { ChunkSectionCompactStorage TryGetSection(int sectionY) { if (sectionY < 0 || sectionY >= ChunkConstants.SectionsPerChunk) { return(null); } return(column.Sections[sectionY]); } return(new NeighborSections { Left = neighborColumns.Left?.Sections[y], Right = neighborColumns.Right?.Sections[y], Bottom = TryGetSection(y - 1), Top = TryGetSection(y + 1), Front = neighborColumns.Front?.Sections[y], Back = neighborColumns.Back?.Sections[y], }); }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int height = random.Next(3) + _minCactiHeight; BlockChunkPos chunkPos = pos.ToBlockChunkPos(); // 不超出世界边界 if (pos.Y >= 1 && pos.Y + height + 1 <= 256) { if (CanCactiGrow(world, grainFactory, chunk, biome, random, pos, height)) { BlockState state = chunk[chunkPos.X, chunkPos.Y - 1, chunkPos.Z]; if (CanSustainCacti(state)) { for (int y = 0; y < height; ++y) { chunk[chunkPos.X, chunkPos.Y + y, chunkPos.Z] = BlockStates.Cactus(CactusType.Interval15); } } } } }
private void GenCacti(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Random random, BlockWorldPos pos) { int cactiMaxNum = random.Next(_cactiPerChunk); if (random.Next(64) == 0) { CactiGenerator generator = new CactiGenerator(); for (int cactiNum = 0; cactiNum < cactiMaxNum; ++cactiNum) { int x = random.Next(14) + 1; int z = random.Next(14) + 1; for (int y = 255; y >= 1; --y) { if (!chunk[x, y, z].IsAir()) { generator.Generate(world, grainFactory, chunk, this, random, new BlockWorldPos(pos.X + x, y + 1, pos.Z + z)); break; } } } } }
public Task ChunkData(Dimension dimension, int chunkX, int chunkZ, ChunkColumnCompactStorage chunkColumn) { return(Sink.SendPacket(new ChunkData { ChunkX = chunkX, ChunkZ = chunkZ, GroundUpContinuous = chunkColumn.Biomes != null, Biomes = chunkColumn.Biomes, PrimaryBitMask = chunkColumn.SectionBitMask, NumberOfBlockEntities = 0, Data = (from c in chunkColumn.Sections where c != null select new Protocol.Play.ChunkSection { PaletteLength = 0, BitsPerBlock = c.BitsPerBlock, SkyLight = c.SkyLight.Storage, BlockLight = c.BlockLight.Storage, DataArray = c.Data.Storage }).ToArray() })); }
public Task ChunkData(Dimension dimension, int chunkX, int chunkZ, ChunkColumnCompactStorage chunkColumn) { return(SendPacket(new ChunkData { ChunkX = chunkX, ChunkZ = chunkZ, FullChunk = chunkColumn.Biomes != null, PrimaryBitMask = chunkColumn.SectionBitMask, Heightmaps = chunkColumn.Heightmaps, Biomes = chunkColumn.Biomes, Data = (from c in chunkColumn.Sections where c != null select new Protocol.Play.ChunkSection { BlockCount = c.NonAirBlockCount, BitsPerBlock = c.BitsPerBlock, PaletteLength = 0, DataArray = c.Data.Storage }).ToArray(), NumberOfBlockEntities = 0, BlockEntities = new Nbt.Tags.NbtCompound[0], // TODO : read real block entities })); }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { BlockChunkPos chunkPos = pos.ToBlockChunkPos(); int x = chunkPos.X; int y = chunkPos.Y; int z = chunkPos.Z; // TODO use block accessor if (chunk[x, y, z].IsAir() && chunk[x, y - 1, z] == BlockStates.GrassBlock()) { var flowerType = biome.GetRandomFlower(random); switch (flowerType) { case PlantsType.Poppy: chunk[x, y, z] = BlockStates.Poppy(); break; case PlantsType.Dandelion: chunk[x, y, z] = BlockStates.Dandelion(); break; } } }
// protected virtual BlockState TryGetBlock(ChunkColumnStorage chunk, ChunkWorldPos chunkWorldPos, BlockWorldPos pos) // { // if (pos.ToChunkWorldPos() == chunkWorldPos) // { // BlockChunkPos blockChunkPos = pos.ToBlockChunkPos(); // return chunk[blockChunkPos.X, blockChunkPos.Y, blockChunkPos.Z]; // } // return BlockState; // } public virtual void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { }
public void PopulateChunk(IWorld world, ChunkColumnCompactStorage chunk, int x, int z, GeneratorSettings settings) { }
public override void Generate(IWorld world, IGrainFactory grainFactory, ChunkColumnCompactStorage chunk, Biome biome, Random random, BlockWorldPos pos) { int height = random.Next(5) + 7; int heightLeaves = height - random.Next(2) - 3; int k = height - heightLeaves; int l = 1 + random.Next(k + 1); if (pos.Y >= 1 && pos.Y + height + 1 <= 256) { bool flag = true; for (int y = pos.Y; y <= pos.Y + 1 + height && flag; ++y) { int xzWidth = 1; if (y - pos.Y < heightLeaves) { xzWidth = 0; } else { xzWidth = l; } for (int x = pos.X - xzWidth; x <= pos.X + xzWidth && flag; ++x) { for (int z = pos.Z - xzWidth; z <= pos.Z + xzWidth && flag; ++z) { if (y >= 0 && y < 256) { BlockChunkPos chunkpos = new BlockWorldPos(x, y, z).ToBlockChunkPos(); BlockState block = chunk[chunkpos.X, chunkpos.Y, chunkpos.Z]; if (!(block.IsAir() || block.IsLeaves() || block.IsSameId(BlockStates.Vines()))) { flag = false; } } else { flag = false; } } } } if (!flag) { // return false; } else { BlockChunkPos down = new BlockWorldPos(pos.X, pos.Y - 1, pos.Z).ToBlockChunkPos(); BlockState state = chunk[down.X, down.Y, down.Z]; bool isSoil = CanSustainTree(PlantsType.Spruce, state); if (isSoil && pos.Y < 256 - height - 1) { int xzWidth = 0; for (int y = pos.Y + height; y >= pos.Y + heightLeaves; --y) { for (int x = pos.X - xzWidth; x <= pos.X + xzWidth; ++x) { int deltaX = x - pos.X; for (int z = pos.Z - xzWidth; z <= pos.Z + xzWidth; ++z) { int deltaZ = z - pos.Z; if (Math.Abs(deltaX) != xzWidth || Math.Abs(deltaZ) != xzWidth || xzWidth <= 0) { BlockChunkPos blockpos = new BlockWorldPos(x, y, z).ToBlockChunkPos(); state = chunk[blockpos.X, blockpos.Y, blockpos.Z]; if (state.IsAir() || state.IsLeaves() || state.IsSameId(BlockStates.Vines())) { chunk[blockpos.X, blockpos.Y, blockpos.Z] = _leaves; } } } } if (xzWidth >= 1 && y == pos.Y + heightLeaves + 1) { --xzWidth; } else if (xzWidth < l) { ++xzWidth; } } for (int y = 0; y < height - 1; ++y) { BlockChunkPos upN = new BlockWorldPos(pos.X, pos.Y + y, pos.Z).ToBlockChunkPos(); state = chunk[upN.X, upN.Y, upN.Z]; if (state.IsAir() || state.IsLeaves()) { chunk[upN.X, upN.Y, upN.Z] = _wood; } } // return true; } else { // return false; } } } else { // return false; } }