Added more tree generators, removed CraftBukkit/MC dependency (yay!).

This commit is contained in:
sk89q 2011-01-30 14:54:42 -08:00
parent 68b12f4c7d
commit 10b48e9344
14 changed files with 430 additions and 472 deletions

View File

@ -11,8 +11,6 @@
<fileset dir="${lib.dir}" id="libs"> <fileset dir="${lib.dir}" id="libs">
<include name="truezip.jar" /> <include name="truezip.jar" />
<include name="minecraft_server_cb.jar" />
<include name="CraftBukkit.jar" />
<include name="Bukkit.jar" /> <include name="Bukkit.jar" />
<include name="GroupUsers.jar" /> <include name="GroupUsers.jar" />
<include name="Permissions.jar" /> <include name="Permissions.jar" />

View File

@ -71,10 +71,7 @@ commands:
usage: /<command> <block> <radius> [raised?] usage: /<command> <block> <radius> [raised?]
forestgen: forestgen:
description: Generate a forest description: Generate a forest
usage: /<command> [size] [density] usage: /<command> [size] [type] [density]
pinegen:
description: Generate a pine forest
usage: /<command> [size] [density]
pumpkins: pumpkins:
description: Generate pumpkin patches description: Generate pumpkin patches
usage: /<command> [size] usage: /<command> [size]
@ -197,12 +194,6 @@ commands:
none: none:
description: Turn off all superpickaxe alternate modes description: Turn off all superpickaxe alternate modes
usage: /<command> usage: /<command>
bigtree:
description: Big tree generator tool
usage: /<command>
pinetree:
description: Pine tree generator tool
usage: /<command>
repl: repl:
description: Block replacer tool description: Block replacer tool
usage: /<command> <block> usage: /<command> <block>
@ -226,7 +217,7 @@ commands:
usage: /<command> usage: /<command>
tree: tree:
description: Tree generator tool description: Tree generator tool
usage: /<command> usage: /<command> [type]
/fillr: /fillr:
description: Fill a hole recursively description: Fill a hole recursively
usage: /<command> <block> <radius> [depth] usage: /<command> <block> <radius> [depth]

View File

@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.Random;
import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.regions.*;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.bags.*; import com.sk89q.worldedit.bags.*;
import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.blocks.*;
import com.sk89q.worldedit.patterns.*; import com.sk89q.worldedit.patterns.*;
@ -1788,7 +1789,7 @@ public class EditSession {
* 0-1 chance * 0-1 chance
* @return whether a block was changed * @return whether a block was changed
*/ */
private boolean setChanceBlockIfAir(Vector pos, BaseBlock block, double c) public boolean setChanceBlockIfAir(Vector pos, BaseBlock block, double c)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
if (Math.random() <= c) { if (Math.random() <= c) {
return setBlockIfAir(pos, block); return setBlockIfAir(pos, block);
@ -1915,11 +1916,11 @@ public class EditSession {
* @param basePos * @param basePos
* @param size * @param size
* @param density * @param density
* @param pineTree * @param treeGenerator
* @return number of trees created * @return number of trees created
*/ */
public int makeForest(Vector basePos, int size, double density, public int makeForest(Vector basePos, int size, double density,
boolean pineTree) throws MaxChangedBlocksException { TreeGenerator treeGenerator) throws MaxChangedBlocksException {
int affected = 0; int affected = 0;
for (int x = basePos.getBlockX() - size; x <= basePos.getBlockX() for (int x = basePos.getBlockX() - size; x <= basePos.getBlockX()
@ -1938,11 +1939,7 @@ public class EditSession {
// Check if we hit the ground // Check if we hit the ground
int t = getBlock(new Vector(x, y, z)).getType(); int t = getBlock(new Vector(x, y, z)).getType();
if (t == 2 || t == 3) { if (t == 2 || t == 3) {
if (pineTree) { treeGenerator.generate(this, new Vector(x, y + 1, z));
makePineTree(new Vector(x, y + 1, z));
} else {
world.generateBigTree(this, new Vector(x, y, z));
}
affected++; affected++;
break; break;
} else if (t != 0) { // Trees won't grow on this! } else if (t != 0) { // Trees won't grow on this!
@ -1955,64 +1952,6 @@ public class EditSession {
return affected; return affected;
} }
/**
* Makes a terrible looking pine tree.
*
* @param basePos
*/
public void makePineTree(Vector basePos) throws MaxChangedBlocksException {
int trunkHeight = (int) Math.floor(Math.random() * 2) + 3;
int height = (int) Math.floor(Math.random() * 5) + 8;
BaseBlock logBlock = new BaseBlock(17);
BaseBlock leavesBlock = new BaseBlock(18);
// Create trunk
for (int i = 0; i < trunkHeight; i++) {
if (!setBlockIfAir(basePos.add(0, i, 0), logBlock)) {
return;
}
}
// Move up
basePos = basePos.add(0, trunkHeight, 0);
// Create tree + leaves
for (int i = 0; i < height; i++) {
setBlockIfAir(basePos.add(0, i, 0), logBlock);
// Less leaves at these levels
double chance = ((i == 0 || i == height - 1) ? 0.6 : 1);
// Inner leaves
setChanceBlockIfAir(basePos.add(-1, i, 0), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(1, i, 0), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(0, i, -1), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(0, i, 1), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(1, i, 1), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(-1, i, 1), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(1, i, -1), leavesBlock, chance);
setChanceBlockIfAir(basePos.add(-1, i, -1), leavesBlock, chance);
if (!(i == 0 || i == height - 1)) {
for (int j = -2; j <= 2; j++) {
setChanceBlockIfAir(basePos.add(-2, i, j), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
setChanceBlockIfAir(basePos.add(2, i, j), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
setChanceBlockIfAir(basePos.add(j, i, -2), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
setChanceBlockIfAir(basePos.add(j, i, 2), leavesBlock, 0.6);
}
}
}
setBlockIfAir(basePos.add(0, height, 0), leavesBlock);
}
/** /**
* Count the number of blocks of a list of types in a region. * Count the number of blocks of a list of types in a region.
* *
@ -2183,4 +2122,13 @@ public class EditSession {
public void setBlockBag(BlockBag blockBag) { public void setBlockBag(BlockBag blockBag) {
this.blockBag = blockBag; this.blockBag = blockBag;
} }
/**
* Get the world.
*
* @return
*/
public LocalWorld getWorld() {
return world;
}
} }

View File

@ -99,7 +99,8 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @return * @return
*/ */
public abstract boolean generateTree(EditSession editSession, Vector pt); public abstract boolean generateTree(EditSession editSession, Vector pt)
throws MaxChangedBlocksException;
/** /**
* Generate a big tree at a location. * Generate a big tree at a location.
@ -107,7 +108,35 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @return * @return
*/ */
public abstract boolean generateBigTree(EditSession editSession, Vector pt); public abstract boolean generateBigTree(EditSession editSession, Vector pt)
throws MaxChangedBlocksException;
/**
* Generate a birch tree at a location.
*
* @param pt
* @return
*/
public abstract boolean generateBirchTree(EditSession editSession, Vector pt)
throws MaxChangedBlocksException;
/**
* Generate a redwood tree at a location.
*
* @param pt
* @return
*/
public abstract boolean generateRedwoodTree(EditSession editSession, Vector pt)
throws MaxChangedBlocksException;
/**
* Generate a tall redwood tree at a location.
*
* @param pt
* @return
*/
public abstract boolean generateTallRedwoodTree(EditSession editSession, Vector pt)
throws MaxChangedBlocksException;
/** /**
* Drop an item. * Drop an item.

View File

@ -24,6 +24,7 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -31,6 +32,10 @@ public class BukkitUtil {
private BukkitUtil() { private BukkitUtil() {
} }
public static Location toLocation(World world, Vector loc) {
return new Location(world, loc.getX(), loc.getY(), loc.getZ());
}
public static BlockVector toVector(Block block) { public static BlockVector toVector(Block block) {
return new BlockVector(block.getX(), block.getY(), block.getZ()); return new BlockVector(block.getX(), block.getY(), block.getZ());
} }

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.Furnace; import org.bukkit.block.Furnace;
@ -31,6 +29,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.TreeType;
import org.bukkit.World; import org.bukkit.World;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
@ -38,11 +37,6 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.blocks.*;
public class BukkitWorld extends LocalWorld { public class BukkitWorld extends LocalWorld {
/**
* Logger.
*/
private final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
private World world; private World world;
/** /**
@ -254,14 +248,8 @@ public class BukkitWorld extends LocalWorld {
*/ */
@Override @Override
public boolean generateTree(EditSession editSession, Vector pt) { public boolean generateTree(EditSession editSession, Vector pt) {
try { return world.generateTree(BukkitUtil.toLocation(world, pt), TreeType.TREE,
return CraftBukkitInterface.generateTree(editSession, pt); new EditSessionBlockChangeDegate(editSession));
} catch (Throwable t) {
logger.log(Level.SEVERE,
"Failed to create tree (do you need to update WorldEdit " +
"due to a Minecraft update?)", t);
return false;
}
} }
/** /**
@ -272,14 +260,44 @@ public class BukkitWorld extends LocalWorld {
*/ */
@Override @Override
public boolean generateBigTree(EditSession editSession, Vector pt) { public boolean generateBigTree(EditSession editSession, Vector pt) {
try { return world.generateTree(BukkitUtil.toLocation(world, pt), TreeType.BIG_TREE,
return CraftBukkitInterface.generateBigTree(editSession, pt); new EditSessionBlockChangeDegate(editSession));
} catch (Throwable t) {
logger.log(Level.SEVERE,
"Failed to create tree (do you need to update WorldEdit " +
"due to a Minecraft update?)", t);
return false;
} }
/**
* Generate a birch tree at a location.
*
* @param pt
* @return
*/
@Override
public boolean generateBirchTree(EditSession editSession, Vector pt) {
return world.generateTree(BukkitUtil.toLocation(world, pt), TreeType.BIRCH,
new EditSessionBlockChangeDegate(editSession));
}
/**
* Generate a redwood tree at a location.
*
* @param pt
* @return
*/
@Override
public boolean generateRedwoodTree(EditSession editSession, Vector pt) {
return world.generateTree(BukkitUtil.toLocation(world, pt), TreeType.REDWOOD,
new EditSessionBlockChangeDegate(editSession));
}
/**
* Generate a redwood tree at a location.
*
* @param pt
* @return
*/
@Override
public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) {
return world.generateTree(BukkitUtil.toLocation(world, pt), TreeType.TALL_REDWOOD,
new EditSessionBlockChangeDegate(editSession));
} }
/** /**

View File

@ -1,115 +0,0 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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.bukkit;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Random;
import java.lang.reflect.*;
import net.minecraft.server.WorldGenBigTree;
import net.minecraft.server.WorldGenTrees;
import net.minecraft.server.WorldGenerator;
import sun.reflect.ReflectionFactory;
import com.sk89q.worldedit.*;
/**
*
* @author sk89q
*/
public class CraftBukkitInterface {
/**
* Logger.
*/
private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
/**
* Random generator.
*/
private static Random random = new Random();
/**
* Proxy for the tree generator.
*/
private static WorldSetBlockProxy proxy;
/**
* Perform world generation at a location.
*
* @param pt
* @return
*/
private static boolean performWorldGen(EditSession editSession, Vector pt,
WorldGenerator worldGen) {
if (proxy == null) {
try {
proxy = createNoConstructor(WorldSetBlockProxy.class);
} catch (Throwable t) {
logger.log(Level.WARNING, "setBlock() proxy class failed to construct",
t);
return false;
}
}
proxy.setEditSession(editSession);
WorldGenerator gen = worldGen;
return gen.a(proxy, random,
pt.getBlockX(), pt.getBlockY() + 1, pt.getBlockZ());
}
/**
* Generate a tree at a location.
*
* @param pt
* @return
*/
public static boolean generateTree(EditSession editSession, Vector pt) {
return performWorldGen(editSession, pt, new WorldGenTrees());
}
/**
* Generate a big tree at a location.
*
* @param pt
* @return
*/
public static boolean generateBigTree(EditSession editSession, Vector pt) {
return performWorldGen(editSession, pt, new WorldGenBigTree());
}
/**
* Instantiate a class without calling its constructor.
*
* @param <T>
* @param clazz
* @return
* @throws Throwable
*/
@SuppressWarnings("rawtypes")
private static <T> T createNoConstructor(Class<T> clazz) throws Throwable {
try {
ReflectionFactory factory = ReflectionFactory.getReflectionFactory();
Constructor objectConstructor = Object.class.getDeclaredConstructor();
Constructor c = factory.newConstructorForSerialization(
clazz, objectConstructor
);
return clazz.cast(c.newInstance());
} catch (Throwable e) {
throw e;
}
}
}

View File

@ -1,4 +1,3 @@
package com.sk89q.worldedit.bukkit;
// $Id$ // $Id$
/* /*
* WorldEdit * WorldEdit
@ -18,7 +17,9 @@ package com.sk89q.worldedit.bukkit;
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import net.minecraft.server.World; package com.sk89q.worldedit.bukkit;
import org.bukkit.BlockChangeDelegate;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
@ -29,64 +30,30 @@ import com.sk89q.worldedit.blocks.BaseBlock;
* *
* @author sk89q * @author sk89q
*/ */
public class WorldSetBlockProxy extends World { public class EditSessionBlockChangeDegate implements BlockChangeDelegate {
/**
* Edit session.
*/
private EditSession editSession; private EditSession editSession;
/** public EditSessionBlockChangeDegate(EditSession editSession) {
* Constructor that should NOT be called. this.editSession = editSession;
*
* @param editSession
*/
public WorldSetBlockProxy(EditSession editSession) {
super(null, "", (long)0, null);
throw new IllegalStateException("MinecraftSetBlockProxy constructor called (BAD)");
} }
/** public boolean setTypeId(int x, int y, int z, int typeId) {
* Called to set a block.
*
* @param x
* @param y
* @param z
* @param blockType
* @return
*/
@Override
public boolean b(int x, int y, int z, int blockType) {
try { try {
return editSession.setBlock(new Vector(x, y, z), new BaseBlock(blockType)); return editSession.setBlock(new Vector(x, y, z), new BaseBlock(typeId));
} catch (MaxChangedBlocksException ex) { } catch (MaxChangedBlocksException ex) {
return false; return false;
} }
} }
/** public boolean setTypeIdAndData(int x, int y, int z, int typeId, int data) {
* Called to get a block. try {
* return editSession.setBlock(new Vector(x, y, z), new BaseBlock(typeId, data));
* @param x } catch (MaxChangedBlocksException ex) {
* @param y return false;
* @param z }
* @return }
*/
@Override public int getTypeId(int x, int y, int z) {
public int a(int x, int y, int z) {
return editSession.getBlock(new Vector(x, y, z)).getType(); return editSession.getBlock(new Vector(x, y, z)).getType();
} }
/**
* @return
*/
public EditSession getEditSession() {
return editSession;
}
/**
* @param editSession
*/
public void setEditSession(EditSession editSession) {
this.editSession = editSession;
}
} }

View File

@ -23,6 +23,7 @@ import com.sk89q.util.commands.Command;
import com.sk89q.util.commands.CommandContext; import com.sk89q.util.commands.CommandContext;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.util.TreeGenerator;
/** /**
* Generation commands. * Generation commands.
@ -132,7 +133,7 @@ public class GenerationCommands {
@Command( @Command(
aliases = {"forestgen"}, aliases = {"forestgen"},
usage = "[size] [density] ", usage = "[size] [type] [density]",
desc = "Generate a forest", desc = "Generate a forest",
min = 0, min = 0,
max = 2 max = 2
@ -143,31 +144,20 @@ public class GenerationCommands {
throws WorldEditException { throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 10; int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 10;
double density = args.argsLength() > 1 ? Double.parseDouble(args.getString(1)) / 100 : 0.05; TreeGenerator.TreeType type = args.argsLength() > 1 ?
type = TreeGenerator.lookup(args.getString(1))
: TreeGenerator.TreeType.TREE;
double density = args.argsLength() > 2 ? args.getDouble(2) / 100 : 0.05;
int affected = editSession.makeForest(player.getPosition(), if (type == null) {
size, density, false); player.printError("Tree type '" + args.getString(1) + "' is unknown.");
player.print(affected + " trees created."); return;
} else {
} }
@Command(
aliases = {"pinegen"},
usage = "[size] [density]",
desc = "Generate a pine forest",
min = 0,
max = 2
)
@CommandPermissions({"worldedit.generation.forest"})
public static void pineGen(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 10;
double density = args.argsLength() > 1 ? Double.parseDouble(args.getString(1)) / 100 : 0.05;
int affected = editSession.makeForest(player.getPosition(), int affected = editSession.makeForest(player.getPosition(),
size, density, true); size, density, new TreeGenerator(type));
player.print(affected + " pine trees created."); player.print(affected + " trees created.");
} }
@Command( @Command(

View File

@ -24,6 +24,7 @@ import com.sk89q.util.commands.CommandContext;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.superpickaxe.*; import com.sk89q.worldedit.superpickaxe.*;
import com.sk89q.worldedit.util.TreeGenerator;
/** /**
* Super pickaxe commands. * Super pickaxe commands.
@ -152,55 +153,30 @@ public class SuperPickaxeCommands {
@Command( @Command(
aliases = {"tree"}, aliases = {"tree"},
usage = "", usage = "[type]",
desc = "Tree generator tool", desc = "Tree generator tool",
min = 0, min = 0,
max = 0 max = 1
) )
@CommandPermissions({"worldedit.superpickaxe.tree"}) @CommandPermissions({"worldedit.superpickaxe.tree"})
public static void tree(CommandContext args, WorldEdit we, public static void tree(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession) LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException { throws WorldEditException {
TreeGenerator.TreeType type = args.argsLength() > 0 ?
type = TreeGenerator.lookup(args.getString(0))
: TreeGenerator.TreeType.TREE;
if (type == null) {
player.printError("Tree type '" + args.getString(0) + "' is unknown.");
return;
}
session.setArmSwingMode(null); session.setArmSwingMode(null);
session.setRightClickMode(new TreePlanter()); session.setRightClickMode(new TreePlanter(new TreeGenerator(type)));
player.print("Tree tool equipped. Right click grass with a pickaxe."); player.print("Tree tool equipped. Right click grass with a pickaxe.");
} }
@Command(
aliases = {"bigtree"},
usage = "",
desc = "Big tree generator tool",
min = 0,
max = 0
)
@CommandPermissions({"worldedit.superpickaxe.tree.big"})
public static void bigTree(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
session.setArmSwingMode(null);
session.setRightClickMode(new BigTreePlanter());
player.print("Big tree tool equipped. Right click grass with a pickaxe.");
}
@Command(
aliases = {"pinetree"},
usage = "",
desc = "Pine tree generator tool",
min = 0,
max = 0
)
@CommandPermissions({"worldedit.superpickaxe.tree.pine"})
public static void pineTree(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
session.setArmSwingMode(null);
session.setRightClickMode(new PineTreePlanter());
player.print("Pine tree tool equipped. Right click a block with a pickaxe.");
}
@Command( @Command(
aliases = {"repl"}, aliases = {"repl"},
usage = "<block>", usage = "<block>",

View File

@ -1,49 +0,0 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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.superpickaxe;
import com.sk89q.worldedit.*;
/**
* Plants a big tree.
*
* @author sk89q
*/
public class BigTreePlanter implements SuperPickaxeMode {
@Override
public boolean act(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
EditSession editSession =
new EditSession(server, world, session.getBlockChangeLimit());
try {
if (!world.generateBigTree(editSession, clicked)) {
player.printError("Notch won't let you put a tree there.");
}
} finally {
session.remember(editSession);
}
return true;
}
}

View File

@ -1,49 +0,0 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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.superpickaxe;
import com.sk89q.worldedit.*;
/**
* Plants a pine tree.
*
* @author sk89q
*/
public class PineTreePlanter implements SuperPickaxeMode {
@Override
public boolean act(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) {
LocalWorld world = clicked.getWorld();
EditSession editSession =
new EditSession(server, world, session.getBlockChangeLimit());
try {
editSession.makePineTree(clicked.add(0, 1, 0));
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
}
return true;
}
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.superpickaxe; package com.sk89q.worldedit.superpickaxe;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.*;
import com.sk89q.worldedit.util.TreeGenerator;
/** /**
* Plants a tree. * Plants a tree.
@ -27,6 +28,12 @@ import com.sk89q.worldedit.*;
* @author sk89q * @author sk89q
*/ */
public class TreePlanter implements SuperPickaxeMode { public class TreePlanter implements SuperPickaxeMode {
private TreeGenerator gen;
public TreePlanter(TreeGenerator gen) {
this.gen = gen;
}
@Override @Override
public boolean act(ServerInterface server, LocalConfiguration config, public boolean act(ServerInterface server, LocalConfiguration config,
LocalPlayer player, LocalSession session, WorldVector clicked) { LocalPlayer player, LocalSession session, WorldVector clicked) {
@ -36,9 +43,11 @@ public class TreePlanter implements SuperPickaxeMode {
new EditSession(server, world, session.getBlockChangeLimit()); new EditSession(server, world, session.getBlockChangeLimit());
try { try {
if (!world.generateTree(editSession, clicked)) { if (!gen.generate(editSession, clicked.add(0, 1, 0))) {
player.printError("Notch won't let you put a tree there."); player.printError("A tree can't go there.");
} }
} catch (MaxChangedBlocksException e) {
player.printError("Max. blocks changed reached.");
} finally { } finally {
session.remember(editSession); session.remember(editSession);
} }

View File

@ -0,0 +1,240 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
*
* 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.util;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
/**
* Tree generator.
*
* @author sk89q
*/
public class TreeGenerator {
public enum TreeType {
TREE("Regular tree", new String[] {"tree", "regular"}),
BIG_TREE("Big tree", new String[] {"big", "bigtree"}),
REDWOOD("Redwood", new String[] {"redwood", "sequoia", "sequoioideae"}),
TALL_REDWOOD("Tall redwood", new String[] {"tallredwood", "tallsequoia", "tallsequoioideae"}),
BIRCH("Birch", new String[] {"birch", "white", "whitebark"}),
PINE("Pine", new String[] {"pine"}),
RANDOM_REDWOOD("Random redwood", new String[] {"randredwood", "randomredwood", "anyredwood"}),
RANDOM("Random", new String[] {"rand", "random"});
/**
* Stores a map of the names for fast access.
*/
private static final Map<String,TreeType> lookup = new HashMap<String,TreeType>();
private final String name;
private final String[] lookupKeys;
static {
for (TreeType type : EnumSet.allOf(TreeType.class)) {
for (String key : type.lookupKeys) {
lookup.put(key, type);
}
}
}
TreeType(String name, String lookupKey) {
this.name = name;
this.lookupKeys = new String[]{ lookupKey };
}
TreeType(String name, String[] lookupKeys) {
this.name = name;
this.lookupKeys = lookupKeys;
}
/**
* Get user-friendly tree type name.
*
* @return
*/
public String getName() {
return name;
}
/**
* Return type from name. May return null.
*
* @param name
* @return
*/
public static TreeType lookup(String name) {
return lookup.get(name.toLowerCase());
}
};
private static Random rand = new Random();
private TreeType type;
/**
* Construct the tree generator with a tree type.
*
* @param type
*/
public TreeGenerator(TreeType type) {
this.type = type;
}
/**
* Generate a tree.
*
* @param world
* @param editSession
* @param pos
* @return
* @throws MaxChangedBlocksException
*/
public boolean generate(EditSession editSession, Vector pos)
throws MaxChangedBlocksException {
return generate(type, editSession, pos);
}
/**
* Generate a tree.
*
* @param world
* @param editSession
* @param pos
* @return
* @throws MaxChangedBlocksException
*/
private boolean generate(TreeType type, EditSession editSession, Vector pos)
throws MaxChangedBlocksException {
LocalWorld world = editSession.getWorld();
TreeType[] choices;
TreeType realType;
switch (type) {
case TREE:
return world.generateTree(editSession, pos);
case BIG_TREE:
return world.generateBigTree(editSession, pos);
case BIRCH:
return world.generateBirchTree(editSession, pos);
case REDWOOD:
return world.generateRedwoodTree(editSession, pos);
case TALL_REDWOOD:
return world.generateTallRedwoodTree(editSession, pos);
case PINE:
makePineTree(editSession, pos);
return true;
case RANDOM_REDWOOD:
choices =
new TreeType[] {
TreeType.REDWOOD, TreeType.TALL_REDWOOD
};
realType = choices[rand.nextInt(choices.length)];
return generate(realType, editSession, pos);
case RANDOM:
choices =
new TreeType[] {
TreeType.TREE, TreeType.BIG_TREE, TreeType.BIRCH,
TreeType.REDWOOD, TreeType.TALL_REDWOOD, TreeType.PINE
};
realType = choices[rand.nextInt(choices.length)];
return generate(realType, editSession, pos);
}
return false;
}
/**
* Makes a terrible looking pine tree.
*
* @param basePos
*/
private static void makePineTree(EditSession editSession, Vector basePos)
throws MaxChangedBlocksException {
int trunkHeight = (int) Math.floor(Math.random() * 2) + 3;
int height = (int) Math.floor(Math.random() * 5) + 8;
BaseBlock logBlock = new BaseBlock(17);
BaseBlock leavesBlock = new BaseBlock(18);
// Create trunk
for (int i = 0; i < trunkHeight; i++) {
if (!editSession.setBlockIfAir(basePos.add(0, i, 0), logBlock)) {
return;
}
}
// Move up
basePos = basePos.add(0, trunkHeight, 0);
// Create tree + leaves
for (int i = 0; i < height; i++) {
editSession.setBlockIfAir(basePos.add(0, i, 0), logBlock);
// Less leaves at these levels
double chance = ((i == 0 || i == height - 1) ? 0.6 : 1);
// Inner leaves
editSession.setChanceBlockIfAir(basePos.add(-1, i, 0), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(1, i, 0), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(0, i, -1), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(0, i, 1), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(1, i, 1), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(-1, i, 1), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(1, i, -1), leavesBlock, chance);
editSession.setChanceBlockIfAir(basePos.add(-1, i, -1), leavesBlock, chance);
if (!(i == 0 || i == height - 1)) {
for (int j = -2; j <= 2; j++) {
editSession.setChanceBlockIfAir(basePos.add(-2, i, j), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
editSession.setChanceBlockIfAir(basePos.add(2, i, j), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
editSession.setChanceBlockIfAir(basePos.add(j, i, -2), leavesBlock, 0.6);
}
for (int j = -2; j <= 2; j++) {
editSession.setChanceBlockIfAir(basePos.add(j, i, 2), leavesBlock, 0.6);
}
}
}
editSession.setBlockIfAir(basePos.add(0, height, 0), leavesBlock);
}
/**
* Looks up a tree type. May return null if a tree type by that
* name is not found.
*
* @param type
* @return
*/
public static TreeType lookup(String type) {
return TreeType.lookup(type);
}
}