Fixes and changes to forest/forestgen.

* Sync up implementations of the two commands.
* Fix generating trees in spots with replaceable blocks.
* Make message when you mistype tree-type arg more correct.

Fixes WORLDEDIT-3869.
This commit is contained in:
wizjany 2019-03-20 21:05:11 -04:00
parent 1934006d14
commit 9b473cecbd
5 changed files with 38 additions and 49 deletions

View File

@ -44,6 +44,7 @@ import com.sk89q.worldedit.function.block.BlockDistributionCounter;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.Counter;
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.mask.BlockMask;
import com.sk89q.worldedit.function.mask.BlockStateMask;
@ -1832,38 +1833,25 @@ public class EditSession implements Extent, AutoCloseable {
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int makeForest(BlockVector3 basePosition, int size, double density, TreeGenerator.TreeType treeType) throws MaxChangedBlocksException {
int affected = 0;
for (int x = basePosition.getBlockX() - size; x <= basePosition.getBlockX()
+ size; ++x) {
for (int z = basePosition.getBlockZ() - size; z <= basePosition.getBlockZ()
+ size; ++z) {
// Don't want to be in the ground
if (!getBlock(BlockVector3.at(x, basePosition.getBlockY(), z)).getBlockType().getMaterial().isAir()) {
continue;
}
// The gods don't want a tree here
if (Math.random() >= density) {
continue;
} // def 0.05
for (int y = basePosition.getBlockY(); y >= basePosition.getBlockY() - 10; --y) {
// Check if we hit the ground
BlockType t = getBlock(BlockVector3.at(x, y, z)).getBlockType();
if (t == BlockTypes.GRASS_BLOCK || t == BlockTypes.DIRT) {
treeType.generate(this, BlockVector3.at(x, y + 1, z));
++affected;
break;
} else if (t == BlockTypes.SNOW) {
setBlock(BlockVector3.at(x, y, z), BlockTypes.AIR.getDefaultState());
} else if (!t.getMaterial().isAir()) { // Trees won't grow on this!
break;
}
}
}
return makeForest(CuboidRegion.fromCenter(basePosition, size), density, treeType);
}
return affected;
/**
* Makes a forest.
*
* @param region the region to generate trees in
* @param density between 0 and 1, inclusive
* @param treeType the tree type
* @return number of trees created
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int makeForest(Region region, double density, TreeGenerator.TreeType treeType) throws MaxChangedBlocksException {
ForestGenerator generator = new ForestGenerator(this, treeType);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(this), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
return ground.getAffected();
}
/**

View File

@ -197,7 +197,8 @@ public class GenerationCommands {
)
@CommandPermissions("worldedit.generation.forest")
@Logging(POSITION)
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException {
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size,
@Optional("tree") TreeType type, @Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type);
player.print(affected + " trees created.");

View File

@ -445,14 +445,8 @@ public class RegionCommands {
@Logging(REGION)
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type,
@Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
ForestGenerator generator = new ForestGenerator(editSession, type);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
player.print(ground.getAffected() + " trees created.");
int affected = editSession.makeForest(region, density / 100, type);
player.print(affected + " trees created.");
}
@Command(

View File

@ -54,15 +54,19 @@ public class ForestGenerator implements RegionFunction {
BlockType t = block.getBlockType();
if (t == BlockTypes.GRASS_BLOCK || t == BlockTypes.DIRT) {
treeType.generate(editSession, position.add(0, 1, 0));
return true;
} else if (t == BlockTypes.GRASS || t == BlockTypes.DEAD_BUSH || t == BlockTypes.POPPY || t == BlockTypes.DANDELION) { // TODO: This list needs to be moved
return treeType.generate(editSession, position.add(0, 1, 0));
} else if (t.getMaterial().isReplacedDuringPlacement()) {
// since the implementation's tree generators generally don't generate in non-air spots,
// we trick editsession history here in the first call
editSession.setBlock(position, BlockTypes.AIR.getDefaultState());
treeType.generate(editSession, position);
return true;
} else if (t == BlockTypes.SNOW) {
editSession.setBlock(position, BlockTypes.AIR.getDefaultState());
return false;
// and then trick the generator here by directly setting into the world
editSession.getWorld().setBlock(position, BlockTypes.AIR.getDefaultState());
// so that now the generator can generate the tree
boolean success = treeType.generate(editSession, position);
if (!success) {
editSession.setBlock(position, block); // restore on failure
}
return success;
} else { // Trees won't grow on this!
return false;
}

View File

@ -52,6 +52,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import sun.reflect.generics.tree.Tree;
import java.util.Arrays;
import java.util.Collection;
@ -290,7 +291,8 @@ public class WorldEditBinding extends BindingHelper {
return type;
} else {
throw new ParameterException(
String.format("Can't recognize tree type '%s' -- choose from: %s", input, Arrays.toString(TreeType.values())));
String.format("Can't recognize tree type '%s' -- choose from: %s", input,
TreeType.getPrimaryAliases()));
}
} else {
return TreeType.TREE;