diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index a80fdeede..8d92f7b62 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.expression.Expression; import com.sk89q.worldedit.expression.ExpressionException; import com.sk89q.worldedit.expression.runtime.RValue; +import com.sk89q.worldedit.generator.ForestGenerator; import com.sk89q.worldedit.interpolation.Interpolation; import com.sk89q.worldedit.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.interpolation.Node; @@ -2753,38 +2754,16 @@ public class EditSession { * @throws MaxChangedBlocksException */ public int makeForest(Iterable it, int upperY, int lowerY, - double density, TreeGenerator treeGenerator) throws MaxChangedBlocksException { - if (upperY < lowerY) { - throw new IllegalArgumentException("upperY must be greater than or equal to lowerY"); - } + double density, TreeGenerator treeGenerator) + throws WorldEditException { + ForestGenerator generator = new ForestGenerator(this, treeGenerator, lowerY, upperY); + generator.setDensity(density); int affected = 0; for (Vector2D pt : it) { - // Don't want to be in the ground - if (!getBlock(pt.toVector(upperY)).isAir()) { - continue; - } - - // The gods don't want a tree here - if (Math.random() >= density) { - continue; - } // def 0.05 - - for (int y = upperY; y >= lowerY; --y) { - // Check if we hit the ground - Vector testPt = pt.toVector(y); - int t = getBlock(testPt).getType(); - - if (t == BlockID.GRASS || t == BlockID.DIRT) { - treeGenerator.generate(this, testPt.add(0, 1, 0)); - ++affected; - break; - } else if (t == BlockID.SNOW) { - setBlock(testPt, new BaseBlock(BlockID.AIR)); - } else if (t != BlockID.AIR) { // Trees won't grow on this! - break; - } + if (generator.apply(pt)) { + affected++; } } diff --git a/src/main/java/com/sk89q/worldedit/generator/ForestGenerator.java b/src/main/java/com/sk89q/worldedit/generator/ForestGenerator.java new file mode 100644 index 000000000..0d0222cb0 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/generator/ForestGenerator.java @@ -0,0 +1,96 @@ +/* + * 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.generator; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.operation.GroundFindingFunction; +import com.sk89q.worldedit.util.TreeGenerator; + +/** + * Generates forests by searching for the ground starting from the given upper Y + * coordinate for every column given. + */ +public class ForestGenerator extends GroundFindingFunction { + + private final TreeGenerator treeGenerator; + private final EditSession editSession; + private double density; + + /** + * Create a new instance. + * + * @param editSession the edit session + * @param treeGenerator a tree generator + * @param lowerY the lower Y boundary to end the ground search from + * @param upperY the upper Y boundary to start the ground search at + */ + public ForestGenerator(EditSession editSession, TreeGenerator treeGenerator, int lowerY, int upperY) { + super(editSession, lowerY, upperY); + this.editSession = editSession; + this.treeGenerator = treeGenerator; + } + + /** + * Set the density (0 <= density <= 1) which indicates the percentage chance + * that a tree will spawn in each column. + * + * @return the density + */ + public double getDensity() { + return density; + } + + /** + * Get the density (0 <= density <= 1) which indicates the percentage chance + * that a tree will spawn in each column. + * + * @param density the density + */ + public void setDensity(double density) { + this.density = density; + } + + @Override + protected boolean shouldContinue(Vector2D pt) { + return Math.random() < density; + } + + @Override + protected boolean apply(Vector pt, BaseBlock block) throws MaxChangedBlocksException { + int t = block.getType(); + + if (t == BlockID.GRASS || t == BlockID.DIRT) { + treeGenerator.generate(editSession, pt.add(0, 1, 0)); + return true; + } else if (t == BlockID.SNOW) { + editSession.setBlock(pt, new BaseBlock(BlockID.AIR)); + return false; + } else { // Trees won't grow on this! + return false; + } + } + + +}