From 6390e1f180a1d3e56e76525931415a753990ccc2 Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 11 Jan 2011 10:21:26 -0800 Subject: [PATCH] Added the tree generator for CraftBukkit. Build process is now a bit difficult. --- build.xml | 2 + src/HMWorld.java | 79 ------------ src/com/sk89q/worldedit/LocalWorld.java | 69 ++++++++++- .../sk89q/worldedit/bukkit/BukkitWorld.java | 51 +++++--- .../bukkit/CraftBukkitInterface.java | 115 ++++++++++++++++++ .../worldedit/bukkit/WorldSetBlockProxy.java | 92 ++++++++++++++ 6 files changed, 307 insertions(+), 101 deletions(-) create mode 100644 src/com/sk89q/worldedit/bukkit/CraftBukkitInterface.java create mode 100644 src/com/sk89q/worldedit/bukkit/WorldSetBlockProxy.java diff --git a/build.xml b/build.xml index 22a38cc5c..d4b553704 100644 --- a/build.xml +++ b/build.xml @@ -20,6 +20,8 @@ + + diff --git a/src/HMWorld.java b/src/HMWorld.java index 63d8390cd..edc9f01a6 100644 --- a/src/HMWorld.java +++ b/src/HMWorld.java @@ -17,7 +17,6 @@ * along with this program. If not, see . */ -import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import com.sk89q.worldedit.EditSession; @@ -35,10 +34,6 @@ public class HMWorld extends LocalWorld { * Logger. */ private final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); - /** - * Random generator. - */ - private Random random = new Random(); /** * Set block type. @@ -304,21 +299,6 @@ public class HMWorld extends LocalWorld { } } - /** - * Drop an item. - * - * @param pt - * @param type - * @param count - * @param times - */ - public void dropItem(Vector pt, int type, int count, int times) { - for (int i = 0; i < times; i++) { - etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), - type, count); - } - } - /** * Drop an item. * @@ -344,65 +324,6 @@ public class HMWorld extends LocalWorld { etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type, 1); } - - /** - * Simulate a block being mined. - * - * @param pt - */ - public void simulateBlockMine(Vector pt) { - int type = getBlockType(pt); - //setBlockType(pt, 0); - - if (type == 1) { dropItem(pt, 4); } // Stone - else if (type == 2) { dropItem(pt, 3); } // Grass - else if (type == 7) { } // Bedrock - else if (type == 8) { } // Water - else if (type == 9) { } // Water - else if (type == 10) { } // Lava - else if (type == 11) { } // Lava - else if (type == 13) { // Gravel - dropItem(pt, type); - - if (random.nextDouble() >= 0.9) { - dropItem(pt, 318); - } - } - else if (type == 16) { dropItem(pt, 263); } // Coal ore - else if (type == 18) { // Leaves - if (random.nextDouble() > 0.95) { - dropItem(pt, 6); - } - } - else if (type == 20) { } // Glass - else if (type == 43) { dropItem(pt, 44); } // Double step - else if (type == 47) { } // Bookshelves - else if (type == 51) { } // Fire - else if (type == 52) { } // Mob spawner - else if (type == 53) { dropItem(pt, 5); } // Wooden stairs - else if (type == 55) { dropItem(pt, 331); } // Redstone wire - else if (type == 56) { dropItem(pt, 264); } // Diamond ore - else if (type == 59) { dropItem(pt, 295); } // Crops - else if (type == 60) { dropItem(pt, 3); } // Soil - else if (type == 62) { dropItem(pt, 61); } // Furnace - else if (type == 63) { dropItem(pt, 323); } // Sign post - else if (type == 64) { dropItem(pt, 324); } // Wood door - else if (type == 67) { dropItem(pt, 4); } // Cobblestone stairs - else if (type == 68) { dropItem(pt, 323); } // Wall sign - else if (type == 71) { dropItem(pt, 330); } // Iron door - else if (type == 73) { dropItem(pt, 331, 1, 4); } // Redstone ore - else if (type == 74) { dropItem(pt, 331, 1, 4); } // Glowing redstone ore - else if (type == 75) { dropItem(pt, 76); } // Redstone torch - else if (type == 78) { } // Snow - else if (type == 79) { } // Ice - else if (type == 82) { dropItem(pt, 337, 1, 4); } // Clay - else if (type == 83) { dropItem(pt, 338); } // Reed - else if (type == 89) { dropItem(pt, 348); } // Lightstone - else if (type == 90) { } // Portal - else if (type != 0) { - dropItem(pt, type); - } - } /** * Kill mobs in an area. diff --git a/src/com/sk89q/worldedit/LocalWorld.java b/src/com/sk89q/worldedit/LocalWorld.java index ad0d4e2be..54a1cc993 100644 --- a/src/com/sk89q/worldedit/LocalWorld.java +++ b/src/com/sk89q/worldedit/LocalWorld.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit; +import java.util.Random; import com.sk89q.worldedit.blocks.BaseItemStack; /** @@ -27,6 +28,11 @@ import com.sk89q.worldedit.blocks.BaseItemStack; * @author sk89q */ public abstract class LocalWorld { + /** + * Random generator. + */ + protected Random random = new Random(); + /** * Set block type. * @@ -138,14 +144,17 @@ public abstract class LocalWorld { /** * Drop an item. - * + * * @param pt * @param type * @param count * @param times */ - public abstract void dropItem(Vector pt, int type, - int count, int times); + public void dropItem(Vector pt, int type, int count, int times) { + for (int i = 0; i < times; i++) { + dropItem(pt, type, count); + } + } /** * Drop an item. @@ -173,7 +182,59 @@ public abstract class LocalWorld { * * @param pt */ - public abstract void simulateBlockMine(Vector pt); + public void simulateBlockMine(Vector pt) { + int type = getBlockType(pt); + //setBlockType(pt, 0); + + if (type == 1) { dropItem(pt, 4); } // Stone + else if (type == 2) { dropItem(pt, 3); } // Grass + else if (type == 7) { } // Bedrock + else if (type == 8) { } // Water + else if (type == 9) { } // Water + else if (type == 10) { } // Lava + else if (type == 11) { } // Lava + else if (type == 13) { // Gravel + dropItem(pt, type); + + if (random.nextDouble() >= 0.9) { + dropItem(pt, 318); + } + } + else if (type == 16) { dropItem(pt, 263); } // Coal ore + else if (type == 18) { // Leaves + if (random.nextDouble() > 0.95) { + dropItem(pt, 6); + } + } + else if (type == 20) { } // Glass + else if (type == 43) { dropItem(pt, 44); } // Double step + else if (type == 47) { } // Bookshelves + else if (type == 51) { } // Fire + else if (type == 52) { } // Mob spawner + else if (type == 53) { dropItem(pt, 5); } // Wooden stairs + else if (type == 55) { dropItem(pt, 331); } // Redstone wire + else if (type == 56) { dropItem(pt, 264); } // Diamond ore + else if (type == 59) { dropItem(pt, 295); } // Crops + else if (type == 60) { dropItem(pt, 3); } // Soil + else if (type == 62) { dropItem(pt, 61); } // Furnace + else if (type == 63) { dropItem(pt, 323); } // Sign post + else if (type == 64) { dropItem(pt, 324); } // Wood door + else if (type == 67) { dropItem(pt, 4); } // Cobblestone stairs + else if (type == 68) { dropItem(pt, 323); } // Wall sign + else if (type == 71) { dropItem(pt, 330); } // Iron door + else if (type == 73) { dropItem(pt, 331, 1, 4); } // Redstone ore + else if (type == 74) { dropItem(pt, 331, 1, 4); } // Glowing redstone ore + else if (type == 75) { dropItem(pt, 76); } // Redstone torch + else if (type == 78) { } // Snow + else if (type == 79) { } // Ice + else if (type == 82) { dropItem(pt, 337, 1, 4); } // Clay + else if (type == 83) { dropItem(pt, 338); } // Reed + else if (type == 89) { dropItem(pt, 348); } // Lightstone + else if (type == 90) { } // Portal + else if (type != 0) { + dropItem(pt, type); + } + } /** * Kill mobs in an area. diff --git a/src/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/com/sk89q/worldedit/bukkit/BukkitWorld.java index fe62042dd..04be96f16 100644 --- a/src/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -19,6 +19,10 @@ package com.sk89q.worldedit.bukkit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.bukkit.ItemStack; +import org.bukkit.Location; import org.bukkit.World; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalWorld; @@ -26,6 +30,11 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseItemStack; public class BukkitWorld extends LocalWorld { + /** + * Logger. + */ + private final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); + private World world; public BukkitWorld(World world) { @@ -100,37 +109,39 @@ public class BukkitWorld extends LocalWorld { @Override public boolean generateTree(EditSession editSession, Vector pt) { - // TODO Auto-generated method stub - return false; + try { + return CraftBukkitInterface.generateTree(editSession, pt); + } 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; + } } @Override public boolean generateBigTree(EditSession editSession, Vector pt) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void dropItem(Vector pt, int type, int count, int times) { - // TODO Auto-generated method stub - + try { + return CraftBukkitInterface.generateBigTree(editSession, pt); + } 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; + } } @Override public void dropItem(Vector pt, int type, int count) { - // TODO Auto-generated method stub + ItemStack item = new ItemStack(type, count); + world.dropItemNaturally(toLocation(pt), item); } @Override public void dropItem(Vector pt, int type) { - // TODO Auto-generated method stub - - } - - @Override - public void simulateBlockMine(Vector pt) { - // TODO Auto-generated method stub + ItemStack item = new ItemStack(type, 1); + world.dropItemNaturally(toLocation(pt), item); } @@ -139,6 +150,10 @@ public class BukkitWorld extends LocalWorld { // TODO Auto-generated method stub return 0; } + + private Location toLocation(Vector pt) { + return new Location(world, pt.getX(), pt.getY(), pt.getZ()); + } @Override public boolean equals(Object other) { diff --git a/src/com/sk89q/worldedit/bukkit/CraftBukkitInterface.java b/src/com/sk89q/worldedit/bukkit/CraftBukkitInterface.java new file mode 100644 index 000000000..c26e6f8c4 --- /dev/null +++ b/src/com/sk89q/worldedit/bukkit/CraftBukkitInterface.java @@ -0,0 +1,115 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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.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 + * @param clazz + * @return + * @throws Throwable + */ + @SuppressWarnings("rawtypes") + private static T createNoConstructor(Class 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; + } + } +} diff --git a/src/com/sk89q/worldedit/bukkit/WorldSetBlockProxy.java b/src/com/sk89q/worldedit/bukkit/WorldSetBlockProxy.java new file mode 100644 index 000000000..2f2617840 --- /dev/null +++ b/src/com/sk89q/worldedit/bukkit/WorldSetBlockProxy.java @@ -0,0 +1,92 @@ +package com.sk89q.worldedit.bukkit; +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +import net.minecraft.server.World; +import com.sk89q.worldedit.EditSession; +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 WorldSetBlockProxy extends World { + /** + * Edit session. + */ + private EditSession editSession; + + /** + * Constructor that should NOT be called. + * + * @param editSession + */ + public WorldSetBlockProxy(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; + } +}