public override bool TryPlaceBlock(IWorldAccessor world, IPlayer byPlayer, ItemStack itemstack, BlockSelection blockSel) { if (!world.TestPlayerAccessBlock(byPlayer, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak)) { byPlayer.InventoryManager.ActiveHotbarSlot.MarkDirty(); return(false); } BlockPos abovePos = blockSel.Position.AddCopy(0, 1, 0); IBlockAccessor ba = world.BlockAccessor; if (ba.GetBlockId(abovePos) == 0 && IsSuitablePosition(world, blockSel.Position)) { BlockFacing[] horVer = SuggestedHVOrientation(byPlayer, blockSel); string knobOrientation = GetSuggestedKnobOrientation(ba, blockSel.Position, horVer[0]); AssetLocation downBlockCode = CodeWithParts(horVer[0].Code, "down", "closed", knobOrientation); Block downBlock = ba.GetBlock(downBlockCode); AssetLocation upBlockCode = CodeWithParts(horVer[0].Code, "up", "closed", knobOrientation); Block upBlock = ba.GetBlock(upBlockCode); ba.SetBlock(downBlock.BlockId, blockSel.Position); ba.SetBlock(upBlock.BlockId, abovePos); return(true); } return(false); }
bool CanTorchStay(IBlockAccessor blockAccessor, BlockPos pos) { BlockFacing facing = BlockFacing.FromCode(LastCodePart()); Block block = blockAccessor.GetBlock(blockAccessor.GetBlockId(pos.AddCopy(facing.GetOpposite()))); return(block.CanAttachBlockAt(blockAccessor, this, pos, facing)); }
private void tryPlaceDecoUp(BlockPos blockPos, IBlockAccessor blockAccessor, LCGRandom worldgenRand) { if (blockAccessor.GetBlockId(blockPos) != 0) { return; } int tries = 7; while (tries-- > 0) { blockPos.Y++; Block block = blockAccessor.GetBlock(blockPos); if (block.IsLiquid()) { return; } if (block.SideSolid[BlockFacing.DOWN.Index]) { blockPos.Y--; Block placeblock = DecoBlocksCeiling[worldgenRand.NextInt(DecoBlocksCeiling.Length)]; blockAccessor.SetBlock(placeblock.BlockId, blockPos); return; } } }
public override bool TryPlaceBlock(IWorldAccessor world, IPlayer byPlayer, ItemStack itemstack, BlockSelection blockSel, ref string failureCode) { BlockPos abovePos = blockSel.Position.AddCopy(0, 1, 0); IBlockAccessor ba = world.BlockAccessor; if (ba.GetBlockId(abovePos) == 0 && CanPlaceBlock(world, byPlayer, blockSel, ref failureCode)) { BlockFacing[] horVer = SuggestedHVOrientation(byPlayer, blockSel); string knobOrientation = GetSuggestedKnobOrientation(ba, blockSel.Position, horVer[0]); AssetLocation downBlockCode = CodeWithVariants(new Dictionary <string, string>() { { "horizontalorientation", horVer[0].Code }, { "part", "down" }, { "state", "closed" }, { "knobOrientation", knobOrientation } }); Block downBlock = ba.GetBlock(downBlockCode); AssetLocation upBlockCode = downBlock.CodeWithVariant("part", "up"); Block upBlock = ba.GetBlock(upBlockCode); ba.SetBlock(downBlock.BlockId, blockSel.Position); ba.SetBlock(upBlock.BlockId, abovePos); return(true); } return(false); }
private void tryPlaceDecoDown(BlockPos blockPos, IBlockAccessor blockAccessor, Random worldGenRand) { if (blockAccessor.GetBlockId(blockPos) != 0) { return; } int tries = 7; while (tries-- > 0) { blockPos.Y--; Block block = blockAccessor.GetBlock(blockPos); if (block.IsLiquid()) { return; } if (block.SideSolid[BlockFacing.DOWN.Index]) { blockPos.Y++; blockAccessor.SetBlock(DecoBlocksFloor[worldGenRand.Next(DecoBlocksFloor.Length)].BlockId, blockPos); return; } } }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand) { if (blockAccessor.GetBlockId(pos) != 0) { return(false); } int surfaceY = blockAccessor.GetTerrainMapheightAt(pos); if (surfaceY - pos.Y < 30 || pos.Y < 25) { return(false); } BlockPos cavepos = getSemiLargeCavePos(blockAccessor, pos); if (cavepos == null) { return(false); } int dy = 0; while (dy < 15 && !blockAccessor.GetBlock(cavepos.X, cavepos.Y + dy, cavepos.Z).SideSolid[BlockFacing.UP.Index]) { dy++; } if (dy >= 15) { return(false); } blockAccessor.SetBlock(this.BlockId, cavepos.AddCopy(0, dy, 0)); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, cavepos.AddCopy(0, dy, 0)); } BlockPos tmppos = new BlockPos(); int tries = 55 + worldGenRand.NextInt(55); while (tries-- > 0) { int offX = worldGenRand.NextInt(15) - 7; int offY = worldGenRand.NextInt(15) - 7; int offZ = worldGenRand.NextInt(15) - 7; if (worldGenRand.NextDouble() < 0.4) { tryPlaceDecoUp(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand); } else { tryPlaceDecoDown(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand); } } return(true); }
private void ExportArea(string filename, BlockPos start, BlockPos end) { int exported = 0; IBlockAccessor blockAcccessor = api.WorldManager.GetBlockAccessor(false, false, false); BlockPos startPos = new BlockPos(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y), Math.Min(start.Z, end.Z)); BlockPos finalPos = new BlockPos(Math.Max(start.X, end.X), Math.Max(start.Y, end.Y), Math.Max(start.Z, end.Z)); BlockSchematic blockdata = new BlockSchematic(); for (int x = startPos.X; x < finalPos.X; x++) { for (int y = startPos.Y; y < finalPos.Y; y++) { for (int z = startPos.Z; z < finalPos.Z; z++) { BlockPos pos = new BlockPos(x, y, z); ushort blockid = blockAcccessor.GetBlockId(pos); if (blockid == 0) { continue; } blockdata.BlocksUnpacked[pos] = blockid; exported++; } } } blockdata.Pack(blockAcccessor, startPos); string outfilepath = Path.Combine(exportFolderPath, filename); if (!outfilepath.EndsWith(".json")) { outfilepath += ".json"; } try { using (TextWriter textWriter = new StreamWriter(outfilepath)) { textWriter.Write(JsonConvert.SerializeObject(blockdata, Formatting.None)); textWriter.Close(); } } catch (IOException e) { Good("Failed exporting: " + e.Message); return; } Good(exported + " blocks exported."); }
private BlockPos getSemiLargeCavePos(IBlockAccessor blockAccessor, BlockPos pos) { BlockPos outpos = pos.Copy(); int maxY = pos.Y; int minY = pos.Y; int minX = pos.X; int maxX = pos.X; int minZ = pos.Z; int maxZ = pos.Z; while (pos.Y - minY < 12 && blockAccessor.GetBlockId(pos.X, minY - 1, pos.Z) == 0) { minY--; } while (maxY - pos.Y < 12 && blockAccessor.GetBlockId(pos.X, maxY + 1, pos.Z) == 0) { maxY++; } outpos.Y = (maxY + minY) / 2; if (maxY - minY < 4 || maxY - minY >= 10) { return(null); } while (pos.X - minX < 12 && blockAccessor.GetBlockId(minX - 1, pos.Y, pos.Z) == 0) { minX--; } while (maxX - pos.X < 12 && blockAccessor.GetBlockId(maxX + 1, pos.Y, pos.Z) == 0) { maxX++; } if (maxX - minX < 3) { return(null); } outpos.X = (maxX + minX) / 2; while (pos.Z - minZ < 12 && blockAccessor.GetBlockId(pos.X, pos.Y, minZ - 1) == 0) { minZ--; } while (maxZ - pos.Z < 12 && blockAccessor.GetBlockId(pos.X, pos.Y, maxZ + 1) == 0) { maxZ++; } if (maxZ - minZ < 3) { return(null); } outpos.Z = (maxZ + minZ) / 2; return(outpos); }
bool TryAttachTo(IBlockAccessor blockAccessor, BlockPos blockpos, BlockFacing onBlockFace) { BlockPos attachingBlockPos = blockpos.AddCopy(onBlockFace.Opposite); Block block = blockAccessor.GetBlock(blockAccessor.GetBlockId(attachingBlockPos)); if (block.CanAttachBlockAt(blockAccessor, this, attachingBlockPos, onBlockFace)) { int blockId = blockAccessor.GetBlock(CodeWithParts(onBlockFace.Code)).BlockId; blockAccessor.SetBlock(blockId, blockpos); return(true); } return(false); }
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling) { IPlayer byPlayer = null; if (byEntity is EntityPlayer) { byPlayer = byEntity.World.PlayerByUid(((EntityPlayer)byEntity).PlayerUID); } IClientPlayer spry = byPlayer as IClientPlayer; IWorldAccessor world = byEntity.World; IBlockAccessor bacc = world.BlockAccessor; List <BlockPos> plist = new List <BlockPos>(); if (bacc.GetBlockId(blockSel.Position + blockSel.Face.Normali.AsBlockPos) == 0) { Debug.WriteLine("airblock good to place thing here"); Dictionary <string, string> rplace = new Dictionary <string, string>(); rplace.Add("rock", "clay"); rplace.Add("size", "oogle"); Debug.WriteLine(CodeWithVariants(rplace)); } plist.Add(blockSel.Position + blockSel.Face.Normali.AsBlockPos); byEntity.World.HighlightBlocks(byPlayer, 0, plist); if (spry == null) { Debug.WriteLine("spry is null"); return; } spry.ShowChatNotification(slot.Itemstack.Attributes.GetInt("stonestored").ToString()); base.OnHeldInteractStart(slot, byEntity, blockSel, entitySel, firstEvent, ref handling); }
void TestTree(IServerPlayer player, CmdArgs arguments) { if (arguments.Length < 2) { player.SendMessage(groupId, "/wgen tree {treeWorldPropertyCode} [0.1 - 3] [aheadoffset]", EnumChatType.CommandError); return; } float size = 1f; int aheadoffset = 0; if (arguments.Length > 2) { float.TryParse(arguments[2], out size); } if (arguments.Length > 3) { int.TryParse(arguments[3], out aheadoffset); } BlockPos pos = player.Entity.Pos.HorizontalAheadCopy(aheadoffset).AsBlockPos; IBlockAccessor blockAccessor = api.WorldManager.GetBlockAccessorBulkUpdate(true, true); while (blockAccessor.GetBlockId(pos) == 0 && pos.Y > 1) { pos.Down(); } treeGenerators.ReloadTreeGenerators(); treeGenerators.RunGenerator(new AssetLocation(arguments[1]), blockAccessor, pos, size); blockAccessor.Commit(); player.SendMessage(groupId, arguments[1] + " size " + size + " generated.", EnumChatType.CommandError); }
private void growBranch(Random rand, int depth, BlockPos pos, float dx, float dy, float dz, float angleVerStart, float angleHorStart, float curWidth, float dieAt, float trunkWidthLoss, bool wideTrunk) { if (depth > 30) { Console.WriteLine("TreeGen.growBranch() aborted, too many branches!"); return; } TreeGenBranch branch = branchesByDepth[Math.Min(depth, branchesByDepth.Count - 1)]; short[] outline = forestFloor.GetOutline(); float widthloss = depth == 0 ? trunkWidthLoss : branch.WidthLoss(rand); float widthlossCurve = branch.widthlossCurve; float branchspacing = branch.branchSpacing.nextFloat(1, rand); float branchstart = branch.branchStart.nextFloat(1, rand); float branchQuantityStart = branch.branchQuantity.nextFloat(1, rand); float branchWidthMulitplierStart = branch.branchWidthMultiplier.nextFloat(1, rand); float reldistance, lastreldistance = 0; float totaldistance = curWidth / widthloss; int iteration = 0; float sequencesPerIteration = 1f / (curWidth / widthloss); float ddrag, angleVer, angleHor; // we want to place around the trunk/branch => offset the coordinates when growing stuff from the base float trunkOffsetX, trunkOffsetZ; BlockPos currentPos = new BlockPos(); float branchQuantity, branchWidth; float sinAngleVer, cosAnglerHor, sinAngleHor; float currentSequence; LCGRandom lcgrand = lcgrandTL.Value; while (curWidth > 0 && iteration++ < 5000) { curWidth -= widthloss; if (widthlossCurve + curWidth / 20 < 1f) { widthloss *= (widthlossCurve + curWidth / 20); } currentSequence = sequencesPerIteration * (iteration - 1); if (curWidth < dieAt) { break; } angleVer = branch.angleVertEvolve.nextFloat(angleVerStart, currentSequence); angleHor = branch.angleHoriEvolve.nextFloat(angleHorStart, currentSequence); sinAngleVer = GameMath.FastSin(angleVer); cosAnglerHor = GameMath.FastCos(angleHor); sinAngleHor = GameMath.FastSin(angleHor); trunkOffsetX = Math.Max(-0.5f, Math.Min(0.5f, 0.7f * sinAngleVer * cosAnglerHor)); trunkOffsetZ = Math.Max(-0.5f, Math.Min(0.5f, 0.7f * sinAngleVer * sinAngleHor)); ddrag = branch.gravityDrag * (float)Math.Sqrt(dx * dx + dz * dz); dx += sinAngleVer * cosAnglerHor / Math.Max(1, Math.Abs(ddrag)); dy += Math.Min(1, Math.Max(-1, GameMath.FastCos(angleVer) - ddrag)); dz += sinAngleVer * sinAngleHor / Math.Max(1, Math.Abs(ddrag)); int blockId = branch.getBlockId(curWidth, config.treeBlocks, this); if (blockId == 0) { return; } currentPos.Set(pos.X + dx, pos.Y + dy, pos.Z + dz); PlaceResumeState state = getPlaceResumeState(currentPos, blockId, wideTrunk); if (state == PlaceResumeState.CanPlace) { api.SetBlock(blockId, currentPos); // Update the canopy outline of the tree for this block position int idz = (int)(dz + 16); int idx = (int)(dx + 16); if (idz > 1 && idz < 31 && idx > 1 && idx < 31) { int canopyIndex = idz * 33 + idx; outline[canopyIndex - 68]++; outline[canopyIndex - 67]++; //bias canopy shading towards the North (- z direction) for sun effects outline[canopyIndex - 66]++; outline[canopyIndex - 65]++; outline[canopyIndex - 64]++; outline[canopyIndex - 35]++; outline[canopyIndex - 34] += 2; outline[canopyIndex - 33] += 2; outline[canopyIndex - 32] += 2; outline[canopyIndex - 31]++; outline[canopyIndex - 2]++; outline[canopyIndex - 1] += 2; outline[canopyIndex + 0] += 3; outline[canopyIndex + 1] += 2; outline[canopyIndex + 2]++; outline[canopyIndex + 33]++; } if (vineGrowthChance > 0 && rand.NextDouble() < vineGrowthChance && config.treeBlocks.vinesBlock != null) { BlockFacing facing = BlockFacing.HORIZONTALS[rand.Next(4)]; BlockPos vinePos = currentPos.AddCopy(facing); float cnt = 1 + rand.Next(11) * (vineGrowthChance + 0.2f); while (api.GetBlockId(vinePos) == 0 && cnt-- > 0) { Block block = config.treeBlocks.vinesBlock; if (cnt <= 0 && config.treeBlocks.vinesEndBlock != null) { block = config.treeBlocks.vinesEndBlock; } block.TryPlaceBlockForWorldGen(api, vinePos, facing, lcgrand); vinePos.Down(); } } } else { if (state == PlaceResumeState.Stop) { return; } } reldistance = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz) / totaldistance; if (reldistance < branchstart) { continue; } if (reldistance > lastreldistance + branchspacing * (1f - reldistance)) { branchspacing = branch.branchSpacing.nextFloat(1, rand); lastreldistance = reldistance; if (branch.branchQuantityEvolve != null) { branchQuantity = branch.branchQuantityEvolve.nextFloat(branchQuantityStart, currentSequence); } else { branchQuantity = branch.branchQuantity.nextFloat(1, rand); } float prevHorAngle = 0f; float horAngle; float minHorangleDist = Math.Min(GameMath.PI / 5, branch.branchHorizontalAngle.var / 5); bool first = true; while (branchQuantity-- > 0) { if (branchQuantity < 1 && rand.NextDouble() < branchQuantity) { break; } curWidth *= branch.branchWidthLossMul; horAngle = angleHor + branch.branchHorizontalAngle.nextFloat(1, rand); int tries = 10; while (!first && Math.Abs(horAngle - prevHorAngle) < minHorangleDist && tries-- > 0) { float newAngle = angleHor + branch.branchHorizontalAngle.nextFloat(1, rand); if (Math.Abs(horAngle - prevHorAngle) < Math.Abs(newAngle - prevHorAngle)) { horAngle = newAngle; } } if (branch.branchWidthMultiplierEvolve != null) { branchWidth = curWidth * branch.branchWidthMultiplierEvolve.nextFloat(branchWidthMulitplierStart, currentSequence); } else { branchWidth = branch.branchWidthMultiplier.nextFloat(curWidth, rand); } growBranch( rand, depth + 1, pos, dx + trunkOffsetX, dy, dz + trunkOffsetZ, branch.branchVerticalAngle.nextFloat(1, rand), horAngle, branchWidth, Math.Max(0, branch.dieAt.nextFloat(1, rand)), trunkWidthLoss, false ); first = false; prevHorAngle = angleHor + horAngle; } } } }
private void growBranch(int depth, BlockPos pos, float dx, float dy, float dz, float angleVerStart, float angleHorStart, float curWidth, float dieAt) { if (depth > 30) { Console.WriteLine("TreeGen.growBranch() aborted, too many branches!"); return; } TreeGenBranch branch = branchesByDepth[Math.Min(depth, branchesByDepth.Count - 1)]; float branchspacing = branch.branchSpacing.nextFloat(); float branchstart = branch.branchStart.nextFloat(); float branchQuantityStart = branch.branchQuantity.nextFloat(); float branchWidthMulitplierStart = branch.branchWidthMultiplier.nextFloat(); float reldistance = 0, lastreldistance = 0; float totaldistance = curWidth / branch.widthloss; int iteration = 0; float sequencesPerIteration = 1f / (curWidth / branch.widthloss); float ddrag = 0, angleVer = 0, angleHor = 0; // we want to place around the trunk/branch => offset the coordinates when growing stuff from the base float trunkOffsetX = 0, trunkOffsetZ = 0, trunkOffsetY = 0; BlockPos currentPos; float branchQuantity, branchWidth; float sinAngleVer, cosAnglerHor, sinAngleHor; float currentSequence; while (curWidth > 0 && iteration++ < 5000) { curWidth -= branch.widthloss; currentSequence = sequencesPerIteration * (iteration - 1); if (curWidth < dieAt) { break; } angleVer = branch.angleVertEvolve.nextFloat(angleVerStart, currentSequence); angleHor = branch.angleHoriEvolve.nextFloat(angleHorStart, currentSequence); sinAngleVer = GameMath.FastSin(angleVer); cosAnglerHor = GameMath.FastCos(angleHor); sinAngleHor = GameMath.FastSin(angleHor); trunkOffsetX = Math.Max(-0.5f, Math.Min(0.5f, 0.7f * sinAngleVer * cosAnglerHor)); trunkOffsetY = Math.Max(-0.5f, Math.Min(0.5f, 0.7f * cosAnglerHor)) + 0.5f; trunkOffsetZ = Math.Max(-0.5f, Math.Min(0.5f, 0.7f * sinAngleVer * sinAngleHor)); ddrag = branch.gravityDrag * GameMath.FastSqrt(dx * dx + dz * dz); dx += sinAngleVer * cosAnglerHor / Math.Max(1, Math.Abs(ddrag)); dy += Math.Min(1, Math.Max(-1, GameMath.FastCos(angleVer) - ddrag)); dz += sinAngleVer * sinAngleHor / Math.Max(1, Math.Abs(ddrag)); ushort blockId = getBlockId(curWidth); if (blockId == 0) { return; } currentPos = pos.AddCopy(dx, dy, dz); if (canPlace(currentPos, blockId)) { api.SetBlock(blockId, currentPos); if (vineGrowthChance > 0 && rand.NextDouble() < vineGrowthChance && config.treeBlocks.vinesBlock != null) { BlockFacing facing = BlockFacing.HORIZONTALS[rand.Next(4)]; BlockPos vinePos = currentPos.AddCopy(facing); float cnt = 1 + rand.Next(11) * (vineGrowthChance + 0.2f); while (api.GetBlockId(vinePos) == 0 && cnt-- > 0) { Block block = config.treeBlocks.vinesBlock; if (cnt <= 0 && config.treeBlocks.vinesEndBlock != null) { block = config.treeBlocks.vinesEndBlock; } block.TryPlaceBlockForWorldGen(api, vinePos, facing); vinePos.Down(); } } } reldistance = GameMath.FastSqrt(dx * dx + dy * dy + dz * dz) / totaldistance; if (reldistance < branchstart) { continue; } if (reldistance > lastreldistance + branchspacing * (1f - reldistance)) { branchspacing = branch.branchSpacing.nextFloat(); lastreldistance = reldistance; if (branch.branchQuantityEvolve != null) { branchQuantity = branch.branchQuantityEvolve.nextFloat(branchQuantityStart, currentSequence); } else { branchQuantity = branch.branchQuantity.nextFloat(); } float prevHorAngle = 0f; float horAngle; float minHorangleDist = Math.Min(GameMath.PI / 10, branch.branchHorizontalAngle.var / 5); bool first = true; while (branchQuantity-- > 0) { if (branchQuantity < 1 && rand.NextDouble() < branchQuantity) { break; } curWidth *= branch.branchWidthLossMul; horAngle = branch.branchHorizontalAngle.nextFloat(); int tries = 5; while (!first && Math.Abs(horAngle - prevHorAngle) < minHorangleDist && tries-- > 0) { horAngle = branch.branchHorizontalAngle.nextFloat(); } if (branch.branchWidthMultiplierEvolve != null) { branchWidth = curWidth * branch.branchWidthMultiplierEvolve.nextFloat(branchWidthMulitplierStart, currentSequence); } else { branchWidth = branch.branchWidthMultiplier.nextFloat(curWidth); } growBranch( depth + 1, pos, dx + trunkOffsetX, dy, dz + trunkOffsetZ, branch.branchVerticalAngle.nextFloat(), angleHor + branch.branchHorizontalAngle.nextFloat(), branchWidth, Math.Max(0, branch.dieAt.nextFloat()) ); first = false; prevHorAngle = horAngle; } } } }
private void ApplyErode(WorldEdit worldEdit, IBlockAccessor blockAccessor, BlockPos pos, Block blockToPlace, ItemStack withItemStack) { int radInt = (int)Math.Ceiling(BrushRadius); float radSq = BrushRadius * BrushRadius; int blurRad = KernelRadius; int quantitySamples = (2 * blurRad + 1) * (2 * blurRad + 1); BlockPos dpos; Block prevBlock = blockAccessRev.GetBlock(0); bool useSelected = UseSelectedBlock; int mapSizeY = worldEdit.sapi.WorldManager.MapSizeY; for (int dx = -radInt; dx <= radInt; dx++) { for (int dz = -radInt; dz <= radInt; dz++) { if (dx * dx + dz * dz > radSq) { continue; } double avgHeight = 0; // Todo: More efficient implementation. This ones super lame. for (int lx = -blurRad; lx <= blurRad; lx++) { for (int lz = -blurRad; lz <= blurRad; lz++) { dpos = pos.AddCopy(dx + lx, 0, dz + lz); while (dpos.Y < mapSizeY && blockAccessor.GetBlockId(dpos) != 0) { dpos.Up(); } while (dpos.Y > 0 && blockAccessor.GetBlockId(dpos.X, dpos.Y, dpos.Z) == 0) { dpos.Down(); } avgHeight += dpos.Y * kernel[lx + blurRad, lz + blurRad]; } } dpos = pos.AddCopy(dx, 0, dz); while (dpos.Y < mapSizeY && blockAccessor.GetBlockId(dpos) != 0) { dpos.Up(); } while (dpos.Y > 0 && (prevBlock = blockAccessor.GetBlock(dpos.X, dpos.Y, dpos.Z)).BlockId == 0) { dpos.Down(); } if (Math.Abs(dpos.Y - avgHeight) < 0.36) { continue; } if (dpos.Y > avgHeight) { blockAccessor.SetBlock(0, dpos); } else { if (useSelected) { blockAccessRev.SetBlock(blockToPlace.BlockId, dpos.Up(), withItemStack); } else { blockAccessRev.SetBlock(prevBlock.BlockId, dpos.Up()); } } } } }