Changed /forestgen to use Notch's tree generation code and made /pinegen to use the old generator. Both commands now support a density argument.

This commit is contained in:
sk89q 2010-11-06 21:03:34 -07:00
parent 57906fba32
commit b609114a8a
4 changed files with 241 additions and 69 deletions

View File

@ -1275,67 +1275,6 @@ public class EditSession {
return false;
}
/**
* Makes a terrible looking pine tree.
*
* @param basePos
*/
private 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);
int pos2[] = {-2, 2};
// 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);
}
/**
* Makes a pumpkin patch.
*
@ -1436,14 +1375,16 @@ public class EditSession {
}
/**
* Makes a terrible looking pine forest.
* Makes a forest.
*
* @param basePos
* @param size
* @param density
* @param pineTree
* @return number of trees created
*/
public int makePineTreeForest(Vector basePos, int size)
throws MaxChangedBlocksException {
public int makeForest(Vector basePos, int size, double density,
boolean pineTree) throws MaxChangedBlocksException {
int affected = 0;
for (int x = basePos.getBlockX() - size; x <= basePos.getBlockX() + size; x++) {
@ -1452,13 +1393,17 @@ public class EditSession {
if (!getBlock(new Vector(x, basePos.getBlockY(), z)).isAir())
continue;
// The gods don't want a tree here
if (Math.random() < 0.95) { continue; }
if (Math.random() >= density) { continue; } // def 0.05
for (int y = basePos.getBlockY(); y >= basePos.getBlockY() - 10; y--) {
// Check if we hit the ground
int t = getBlock(new Vector(x, y, z)).getID();
if (t == 2 || t == 3) {
makePineTree(new Vector(x, y + 1, z));
if (pineTree) {
makePineTree(new Vector(x, y + 1, z));
} else {
ServerInterface.generateTree(this, new Vector(x, y + 1, z));
}
affected++;
break;
} else if (t != 0) { // Trees won't grow on this!
@ -1470,4 +1415,65 @@ public class EditSession {
return affected;
}
/**
* Makes a terrible looking pine tree.
*
* @param basePos
*/
private 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);
int pos2[] = {-2, 2};
// 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);
}
}

View File

@ -0,0 +1,89 @@
// $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/>.
*/
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.blocks.BaseBlock;
/**
* Proxy class to catch calls to set blocks.
*
* @author sk89q
*/
public class MinecraftSetBlockProxy extends el {
/**
* Edit session.
*/
private EditSession editSession;
/**
* Constructor that should NOT be called.
*
* @param editSession
*/
public MinecraftSetBlockProxy(EditSession editSession) {
super(null, "", (long)0, null);
throw new IllegalStateException("MinecraftSetBlockProxy constructor called (BAD)");
}
/**
* Called to set a block.
*
* @param x
* @param y
* @param z
* @param blockType
* @return
*/
@Override
public boolean a(int x, int y, int z, int blockType) {
try {
return editSession.setBlock(new Vector(x, y, z), new BaseBlock(blockType));
} catch (MaxChangedBlocksException ex) {
return false;
}
}
/**
* Called to get a block.
*
* @param x
* @param y
* @param z
* @return
*/
@Override
public int a(int x, int y, int z) {
return editSession.getBlock(new Vector(x, y, z)).getID();
}
/**
* @return
*/
public EditSession getEditSession() {
return editSession;
}
/**
* @param editSession
*/
public void setEditSession(EditSession editSession) {
this.editSession = editSession;
}
}

View File

@ -19,14 +19,32 @@
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseItem;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.lang.reflect.Constructor;
import sun.reflect.ReflectionFactory;
/**
*
* @author sk89q
*/
public class ServerInterface {
/**
* 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 MinecraftSetBlockProxy proxy;
/**
* Set block type.
*
@ -165,4 +183,48 @@ public class ServerInterface {
chest.update();
return true;
}
/**
* Generate a tree at a location.
*
* @param pt
* @return
*/
public static boolean generateTree(EditSession editSession, Vector pt) {
if (proxy == null) {
try {
proxy = createNoConstructor(MinecraftSetBlockProxy.class);
} catch (Throwable t) {
logger.log(Level.WARNING, "setBlock() proxy class failed to construct",
t);
return false;
}
}
proxy.setEditSession(editSession);
bg treeGen = new gy();
return treeGen.a(proxy, random,
pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());
}
/**
* Instantiate a class without calling its constructor.
*
* @param <T>
* @param clazz
* @return
* @throws Throwable
*/
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

@ -159,7 +159,8 @@ public class WorldEditListener extends PluginListener {
commands.put("/fixwater", "[Radius] - Level nearby pools of water");
commands.put("/fixlava", "[Radius] - Level nearby pools of lava");
commands.put("/ex", "[Size] - Extinguish fires");
commands.put("/forestgen", "<Size> - Make an ugly pine tree forest");
commands.put("/forestgen", "<Size> <Density> - Make Notch tree forest");
commands.put("/pinegen", "<Size> <Density> - Make an ugly pine tree forest");
commands.put("/pumpkins", "<Size> - Make a pumpkin forest");
commands.put("/unstuck", "Go up to the first free spot");
commands.put("/ascend", "Go up one level");
@ -892,12 +893,26 @@ public class WorldEditListener extends PluginListener {
return true;
// Make pine tree forest
// Make tree forest
} else if (split[0].equalsIgnoreCase("/forestgen")) {
checkArgs(split, 0, 2, split[0]);
int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10;
double density = split.length > 2 ? Double.parseDouble(split[2]) / 100 : 0.05;
int affected = editSession.makeForest(player.getPosition(),
size, density, false);
player.print(affected + " trees created.");
return true;
// Make pine tree forest
} else if (split[0].equalsIgnoreCase("/pinegen")) {
checkArgs(split, 0, 1, split[0]);
int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10;
double density = split.length > 2 ? Double.parseDouble(split[2]) / 100 : 0.05;
int affected = editSession.makePineTreeForest(player.getPosition(), size);
int affected = editSession.makeForest(player.getPosition(),
size, density, true);
player.print(affected + " pine trees created.");
return true;