diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 04c44defc..cd7778c4f 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -32,24 +32,19 @@ import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.RegionMaskingFilter; import com.sk89q.worldedit.function.block.BlockCount; import com.sk89q.worldedit.function.block.BlockReplace; +import com.sk89q.worldedit.function.block.Naturalizer; import com.sk89q.worldedit.function.generator.ForestGenerator; import com.sk89q.worldedit.function.generator.GardenPatchGenerator; import com.sk89q.worldedit.function.operation.OperationHelper; import com.sk89q.worldedit.function.util.RegionOffset; -import com.sk89q.worldedit.function.visitor.DownwardVisitor; -import com.sk89q.worldedit.function.visitor.FlatRegionVisitor; -import com.sk89q.worldedit.function.visitor.RecursiveVisitor; -import com.sk89q.worldedit.function.visitor.RegionVisitor; +import com.sk89q.worldedit.function.visitor.*; import com.sk89q.worldedit.interpolation.Interpolation; import com.sk89q.worldedit.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.interpolation.Node; import com.sk89q.worldedit.masks.*; import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.patterns.SingleBlockPattern; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.EllipsoidRegion; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.regions.RegionOperationException; +import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.regions.search.GroundSearch; import com.sk89q.worldedit.regions.search.MaskingGroundSearch; import com.sk89q.worldedit.shape.ArbitraryBiomeShape; @@ -63,6 +58,8 @@ import java.util.*; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.regions.Regions.maximumBlockY; +import static com.sk89q.worldedit.regions.Regions.minimumBlockY; /** * This class can wrap all block editing operations into one "edit session" that @@ -236,9 +233,9 @@ public class EditSession { } } } - + boolean result; - + if (type == 0) { if (fastMode) { result = world.setBlockTypeFast(pt, 0); @@ -248,7 +245,7 @@ public class EditSession { } else { result = world.setBlock(pt, block, !fastMode); } - + return result; } @@ -1175,73 +1172,18 @@ public class EditSession { * Turns the first 3 layers into dirt/grass and the bottom layers * into rock, like a natural Minecraft mountain. * - * @param region + * @param region the region to affect * @return number of blocks affected - * @throws MaxChangedBlocksException + * @throws MaxChangedBlocksException thrown if too many blocks are changed */ - public int naturalizeCuboidBlocks(Region region) - throws MaxChangedBlocksException { - Vector min = region.getMinimumPoint(); - Vector max = region.getMaximumPoint(); + public int naturalizeCuboidBlocks(Region region) throws MaxChangedBlocksException { + checkNotNull(region); - int upperY = Math.min(world.getMaxY(), max.getBlockY() + 1); - int lowerY = Math.max(0, min.getBlockY() - 1); - - int affected = 0; - - int minX = min.getBlockX(); - int minZ = min.getBlockZ(); - int maxX = max.getBlockX(); - int maxZ = max.getBlockZ(); - - BaseBlock grass = new BaseBlock(BlockID.GRASS); - BaseBlock dirt = new BaseBlock(BlockID.DIRT); - BaseBlock stone = new BaseBlock(BlockID.STONE); - - for (int x = minX; x <= maxX; ++x) { - for (int z = minZ; z <= maxZ; ++z) { - int level = -1; - - for (int y = upperY; y >= lowerY; --y) { - Vector pt = new Vector(x, y, z); - //Vector above = new Vector(x, y + 1, z); - int blockType = getBlockType(pt); - - boolean isTransformable = - blockType == BlockID.GRASS - || blockType == BlockID.DIRT - || blockType == BlockID.STONE; - - // Still searching for the top block - if (level == -1) { - if (!isTransformable) { - continue; // Not transforming this column yet - } - - level = 0; - } - - if (level >= 0) { - if (isTransformable) { - if (level == 0) { - setBlock(pt, grass); - affected++; - } else if (level <= 2) { - setBlock(pt, dirt); - affected++; - } else { - setBlock(pt, stone); - affected++; - } - } - - level++; - } - } - } - } - - return affected; + Naturalizer naturalizer = new Naturalizer(this); + FlatRegion flatRegion = Regions.asFlatRegion(region); + LayerVisitor visitor = new LayerVisitor(flatRegion, minimumBlockY(region), maximumBlockY(region), naturalizer); + OperationHelper.completeLegacy(visitor); + return naturalizer.getAffected(); } /** diff --git a/src/main/java/com/sk89q/worldedit/function/block/Naturalizer.java b/src/main/java/com/sk89q/worldedit/function/block/Naturalizer.java new file mode 100644 index 000000000..b2143319b --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/function/block/Naturalizer.java @@ -0,0 +1,91 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function.block; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.function.LayerFunction; +import com.sk89q.worldedit.masks.BlockMask; +import com.sk89q.worldedit.masks.Mask; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Makes a layer of grass on top, three layers of dirt below, and smooth stone + * only below that for all layers that originally consist of grass, dirt, + * or smooth stone. + */ +public class Naturalizer implements LayerFunction { + + private final EditSession editSession; + private final BaseBlock grass = new BaseBlock(BlockID.GRASS); + private final BaseBlock dirt = new BaseBlock(BlockID.DIRT); + private final BaseBlock stone = new BaseBlock(BlockID.STONE); + private final Mask mask = new BlockMask(grass, dirt, stone); + private int affected = 0; + + /** + * Make a new naturalizer. + * + * @param editSession an edit session + */ + public Naturalizer(EditSession editSession) { + checkNotNull(editSession); + this.editSession = editSession; + } + + /** + * Get the number of affected objects. + * + * @return the number of affected + */ + public int getAffected() { + return affected; + } + + @Override + public boolean isGround(Vector position) { + return mask.matches(editSession, position); + } + + @Override + public boolean apply(Vector position, int depth) throws WorldEditException { + if (mask.matches(editSession, position)) { + affected++; + switch (depth) { + case 0: + editSession.setBlock(position, grass); + break; + case 1: + case 2: + case 3: + editSession.setBlock(position, dirt); + break; + default: + editSession.setBlock(position, stone); + } + } + + return true; + } +}