Added FlatRegionApplicator for FlatRegionFunctions.

This commit is contained in:
sk89q 2014-03-01 12:37:18 -08:00
parent 504c7a5ff1
commit c87b1acbad
6 changed files with 241 additions and 48 deletions

View File

@ -2752,14 +2752,16 @@ public class EditSession {
* @param treeGenerator the tree generator * @param treeGenerator the tree generator
* @return number of trees created * @return number of trees created
* @throws MaxChangedBlocksException * @throws MaxChangedBlocksException
* @deprecated Use {@link com.sk89q.worldedit.generator.ForestGenerator} with a
* {@link com.sk89q.worldedit.operation.FlatRegionApplicator}
*/ */
@Deprecated
public int makeForest(Iterable<Vector2D> it, int upperY, int lowerY, public int makeForest(Iterable<Vector2D> it, int upperY, int lowerY,
double density, TreeGenerator treeGenerator) double density, TreeGenerator treeGenerator)
throws WorldEditException { throws WorldEditException {
ForestGenerator generator = new ForestGenerator(this, treeGenerator); ForestGenerator generator = new ForestGenerator(this, treeGenerator);
generator.setLowerY(lowerY); generator.setRange(lowerY, upperY);
generator.setUpperY(upperY);
generator.setDensity(density); generator.setDensity(density);
int affected = 0; int affected = 0;

View File

@ -30,7 +30,10 @@ import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.filtering.GaussianKernel; import com.sk89q.worldedit.filtering.GaussianKernel;
import com.sk89q.worldedit.filtering.HeightMapFilter; import com.sk89q.worldedit.filtering.HeightMapFilter;
import com.sk89q.worldedit.generator.FloraPlacer; import com.sk89q.worldedit.generator.FloraPlacer;
import com.sk89q.worldedit.generator.ForestGenerator;
import com.sk89q.worldedit.masks.Mask; import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.operation.FlatRegionApplicator;
import com.sk89q.worldedit.operation.OperationHelper;
import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern; import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.regions.*;
@ -538,20 +541,15 @@ public class RegionCommands {
} }
Region region = session.getSelection(player.getWorld()); Region region = session.getSelection(player.getWorld());
FlatRegion flatRegion;
if (region instanceof FlatRegion) { ForestGenerator function = new ForestGenerator(editSession, new TreeGenerator(type));
flatRegion = (FlatRegion) region; function.setRange(region);
} else { function.setDensity(density);
player.print("(The given region is not a 'flat region', so a cuboid region will be used instead.)");
flatRegion = CuboidRegion.makeCuboid(region);
}
int upperY = flatRegion.getMaximumY() + 1; // Increase by 1 to have trees generate above the selection 1 block FlatRegionApplicator operation = new FlatRegionApplicator(region, function);
int lowerY = flatRegion.getMinimumY(); OperationHelper.complete(operation);
int affected = editSession.makeForest(flatRegion.asFlatRegion(), upperY, lowerY, density, new TreeGenerator(type)); player.print(operation.getAffected() + " trees created.");
player.print(affected + " trees created.");
} }
@Command( @Command(
@ -567,28 +565,15 @@ public class RegionCommands {
double density = args.argsLength() > 0 ? args.getDouble(0) / 100 : 0.1; double density = args.argsLength() > 0 ? args.getDouble(0) / 100 : 0.1;
Region region = session.getSelection(player.getWorld()); Region region = session.getSelection(player.getWorld());
FlatRegion flatRegion;
if (region instanceof FlatRegion) { FloraPlacer function = new FloraPlacer(editSession);
flatRegion = (FlatRegion) region; function.setRange(region);
} else { function.setDensity(density);
player.print("(The given region is not a 'flat region', so a cuboid region will be used instead.)");
flatRegion = CuboidRegion.makeCuboid(region);
}
FloraPlacer generator = new FloraPlacer(editSession); FlatRegionApplicator operation = new FlatRegionApplicator(region, function);
generator.setLowerY(flatRegion.getMinimumY()); OperationHelper.complete(operation);
generator.setUpperY(flatRegion.getMaximumY());
generator.setDensity(density);
int affected = 0;
for (Vector2D pt : flatRegion.asFlatRegion()) { player.print(operation.getAffected() + " flora created.");
if (generator.apply(pt)) {
affected++;
}
}
player.print(affected + " flora created.");
} }
} }

View File

@ -0,0 +1,75 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.operation;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;
/**
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
*/
public class FlatRegionApplicator implements Operation {
private final Region region;
private final FlatRegionFunction function;
private int affected = 0;
public FlatRegionApplicator(Region region, FlatRegionFunction function) {
this.region = region;
this.function = function;
}
/**
* Get the number of affected objects.
*
* @return the number of affected
*/
public int getAffected() {
return affected;
}
@Override
public Operation resume() throws WorldEditException {
FlatRegion flatRegion;
if (region instanceof FlatRegion) {
flatRegion = (FlatRegion) region;
} else {
flatRegion = CuboidRegion.makeCuboid(region);
}
for (Vector2D pt : flatRegion.asFlatRegion()) {
if (function.apply(pt)) {
affected++;
}
}
return null;
}
@Override
public void cancel() {
}
}

View File

@ -19,9 +19,13 @@
package com.sk89q.worldedit.operation; package com.sk89q.worldedit.operation;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.regions.Region;
/** /**
* An abstract implementation of {@link com.sk89q.worldedit.operation.FlatRegionFunction} * An abstract implementation of {@link com.sk89q.worldedit.operation.FlatRegionFunction}
@ -68,16 +72,6 @@ public abstract class GroundFindingFunction implements FlatRegionFunction {
return upperY; return upperY;
} }
/**
* Set the upper Y coordinate to start the ground search from.
*
* @param upperY the upper Y coordinate
*/
public void setUpperY(int upperY) {
this.upperY = upperY;
checkYBounds();
}
/** /**
* Get the lower Y coordinate to end the ground search at. * Get the lower Y coordinate to end the ground search at.
* *
@ -88,19 +82,43 @@ public abstract class GroundFindingFunction implements FlatRegionFunction {
} }
/** /**
* Set the lower Y coordinate to end the ground search at. * Set the range of Y coordinates to perform a search for ground within.
* *
* @return lowerY the lower Y coordinate * @param lowerY the lower Y coordinate
* @param upperY the upper Y coordinate (upperY >= lowerY)
*/ */
public void setLowerY(int lowerY) { public void setRange(int lowerY, int upperY) {
this.lowerY = lowerY; this.lowerY = lowerY;
this.upperY = upperY;
checkYBounds(); checkYBounds();
} }
/**
* Set the range of Y coordinates to perform a search for ground within from
* the minimum and maximum Y of the given region.
*
* @param region the region
*/
public void setRange(Region region) {
setRange(region.getMinimumPoint().getBlockY(), region.getMaximumPoint().getBlockY());
}
/**
* Increase the upper Y by the given amount.
*
* @param y the amount to increase the upper Y by
*/
public void raiseCeiling(int y) {
if (y <= 0) {
throw new IllegalArgumentException("Can't raise by a negative");
}
upperY += y;
}
@Override @Override
public final boolean apply(Vector2D pt) throws WorldEditException { public final boolean apply(Vector2D pt) throws WorldEditException {
// Don't want to be in the ground // Don't want to be in the ground
if (!editSession.getBlock(pt.toVector(upperY)).isAir()) { if (!editSession.getBlock(pt.toVector(upperY + 1)).isAir()) {
return false; return false;
} }
@ -108,7 +126,7 @@ public abstract class GroundFindingFunction implements FlatRegionFunction {
return false; return false;
} }
for (int y = upperY; y >= lowerY; --y) { for (int y = upperY + 1; y >= lowerY; --y) {
Vector testPt = pt.toVector(y); Vector testPt = pt.toVector(y);
BaseBlock block = editSession.getBlock(testPt); BaseBlock block = editSession.getBlock(testPt);

View File

@ -0,0 +1,49 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.operation;
import com.sk89q.worldedit.WorldEditException;
/**
* An task that may be split into multiple steps to be run sequentially immediately
* or at a varying or fixed interval. Operations should attempt to break apart tasks
* into smaller tasks that can be completed in quicker successions.
*/
public interface Operation {
/**
* Complete the next step. If this method returns true, then the method may be
* called again in the future, or possibly never. If this method returns false,
* then this method should not be called again.
*
* @return another operation to run that operation again, or null to stop
* @throws WorldEditException an error
*/
Operation resume() throws WorldEditException;
/**
* Abort the current task. After the this method is called, {@link #resume()} should
* not be called at any point in the future. This method should not be called after
* successful completion of the operation. This method must be called if
* the operation is interrupted before completion.
*/
void cancel();
}

View File

@ -0,0 +1,64 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.operation;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
/**
* Operation helper methods.
*/
public final class OperationHelper {
private OperationHelper() {
}
/**
* Complete a given operation synchronously until it completes.
*
* @param op operation to execute
* @throws WorldEditException WorldEdit exception
*/
public static void complete(Operation op) throws WorldEditException {
while (op != null) {
op = op.resume();
}
}
/**
* Complete a given operation synchronously until it completes. Catch all
* errors that is not {@link MaxChangedBlocksException} for legacy reasons.
*
* @param op operation to execute
* @throws MaxChangedBlocksException thrown when too many blocks have been changed
*/
public static void completeLegacy(Operation op) throws MaxChangedBlocksException {
while (op != null) {
try {
op = op.resume();
} catch (MaxChangedBlocksException e) {
throw e;
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
}
}