Help Using WorldEdit API

Discussion in 'Plugin Development' started by bgsteiner, Dec 24, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    bgsteiner

    Hi i'v been looking for some help with using the WorldEdit API in a private plugin I'm making for a server. I haven't received much help form the irc they have.

    All I need right now is how to interact with the count function. All i need is on request to be able to query the block count of a specific block from a selected region them my plugin will handle some calculation data and complete its task.

    I have looked through he source code and the javadocs and I couldn't find the method I need to call the only one I could find was the command reference which cant be called from my plugin because it doesn't return the data I can work with.

    Before I get insults from people saying I'm a lazy noob and to go kill myself... I have been developing commissioned plugins for 2 years now and have taken college courses on java development.

    All I need is a little help please don't hurt me internet.
     
  2. Offline

    Rprrr

    bgsteiner
    WorldEdit is all broken at the moment.
    API would be .. worthless. :p Better write something yourself.. loop through a cuboid or so.
     
  3. Offline

    bgsteiner

    not really helpful plus im building on a stable version
     
  4. Offline

    fireblast709

    if it is a cuboid, WorldEdit just loops over all the blocks and checks if it is the type you want. If it is, it just increments a value and later returns this
     
  5. Offline

    bgsteiner

    even if i write my own i need to be able to get the region selected

    I know its Christmas but can anyone please help here

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 30, 2016
  6. Offline

    Gildan27

    @bgsteiner
    I'm not sure if this is exactly what you need, but I have done something like this and have shared below.

    Hopefully there's enough code here to do what you want... If it isn't helpful, let me know exactly what you're trying to do and I can probably help. I have done a lot with WorldEdit's API.

    The reason I ask for clarification, is because you could also invoke WorldEdit's count function, but you indicate that's not what you need, even though that sounds like it's exactly what you need, so any clarification you have would be good. My WorldEditHelper's replace function below illustrates invoking one of WorldEdit's commands without using their API. So any clarification on what you're trying to do would be helpful.

    At present, there is no way to call the count functions in WorldEdit. The methods are private and there is no way to call them. If you want to use WorldEdit to perform the count, you will either need to invoke the command manually or extend their EditSession object and add the functionality yourself. This is what I did (code below).

    As others have said, depending on what you're doing, it might be easier just to get the selection and count them yourself (example of getting selections is below)

    That didn't work for me. What I needed to do is given a WorldEdit replacement, I wanted to know how many blocks would be replaced if the replace was allowed, supporting //replace stone (replaces all non-air blocks with stone). I wanted to use WorldEdit for this because they take care of parsing out all the block names and all that.

    I'm not sure if this is your exact situation, but I share my code in case it will be useful to what you are doing.

    If you're just needing to know how many of a block type is in a selection, you might just do it yourself. But I wanted to use WorldEdit because I wanted to know, given a replacement, how many blocks would be affected. The same code can count the number of blocks in a selection of a certain type, if you change what you pass to it.

    I have created a class called WorldEditHelper (the code is towards the end), where I put all my WorldEdit stuff. Here's an example of getting the selection with my WorldEditHelper class:

    Code:
    WorldEditHelper worldEditHelper = new WorldEditHelper(plugin, player);
    Selection selection = worldEditHelper.getSelection();
    try {
    Location min = selection.getMinimumPoint();
    Location max = selection.getMaximumPoint();
    } catch(Exception e) {
    //Nothing was selected
    return true;
    }
    
    Below is the code for my plugin's /replace command. It works a bit like WorldEdit's //replace command, like so:
    /replace wool:green stone <--gets a quote for replacing all green wool with stone
    /replace wool:green stone yes <--replaces all green wool with stone
    /replace stone yes <--replaces all non-air blocks with stone

    To get the quote, one must count the number of blocks that will be replaced.

    This works by calling the getReplaceInformation method. It will take the string "/replace grass stone" and will return the number of grass blocks. It will also take "/replace stone" and will return the number of non-air blocks (as that is what would be replaced by that command). You can modify this according to your needs. Everything is done through WorldEdit.

    This code is missing its superclass and some plugin-specific stuff, but you can still see what it's doing...

    Code:
    WorldEditHelper worldEditHelper = new WorldEditHelper(plugin, player);
    Selection selection = worldEditHelper.getSelection();
     
    String arguments = "";
    for(String arg : args) arguments = arguments + arg + " ";
    String commandArgs = arguments.trim();
    if(commandArgs.equals("yes") || commandArgs.equals("")) return false;
     
    int area = -1;
    int maxArea = Integer.parseInt(plugin.getConfig().getString("max_replace_size"));
     
    try {
    area = selection.getArea();
    } catch(Exception e) {
    sendErrorMessage("You have not selected anything.");
    return true;
    }
     
    if(area > maxArea) {
    sendErrorMessage("The selected area is too large (" + area + " blocks). Make sure the selected area is less than " + maxArea + " blocks and try again.");
    return true;
    }
     
    String pay = "no";
    commandArgs = "/replace " + commandArgs;
     
    if(commandArgs.endsWith("yes")) {
    pay = "yes";
    commandArgs = commandArgs.substring(0, commandArgs.length() - 4);
    }
     
    int numBlocks = 0;
    try {
    numBlocks = worldEditHelper.getReplaceInformation(commandArgs); //Num blocks will be a count of the number of blocks that would be replaced by this operation
    } catch (DisallowedItemException e) {
    sendErrorMessage("It is not allowed to use this command with at least one of the specified items.");
    return true;
    } catch (UnknownItemException e) {
    sendErrorMessage("At least one of the items specified could not be found.");
    return true;
    } catch (IncompleteRegionException e) {
    sendErrorMessage("There is a problem with your selection. Please make a new selection, and try again.");
    return true;
    }
     
    if(pay.equals("yes") && numBlocks > 0) {
    try {
    worldEditHelper.replace(commandArgs);
    } catch (CommandException e) {
    sendErrorMessage(e.getMessage());
    e.printStackTrace();
    } catch (WorldEditException e) {
    sendErrorMessage(e.getMessage());
    e.printStackTrace();
    }
    }
     
    //Removed plugin-specific stuff here
     
    
    Here is WorldEditHelper (some of this code is from WorldEdit):

    Code:
    public class WorldEditHelper {
    private WorldEditPlugin worldEditPlugin;
    private WorldEdit worldEdit;
    @SuppressWarnings("unused")
    private JavaPlugin plugin;
    private LocalPlayer localPlayer;
    private Player player;
     
    public WorldEditHelper(JavaPlugin plugin, Player player) {
    this.worldEditPlugin = (WorldEditPlugin) Bukkit.getServer().getPluginManager().getPlugin("WorldEdit");
    this.worldEdit = worldEditPlugin.getWorldEdit();
    this.plugin = plugin;
    this.localPlayer = worldEditPlugin.wrapPlayer(player);
    this.player = player;
    }
     
    public Selection getSelection() {
    return worldEditPlugin.getSelection(player);
    }
     
    public void replace(String args) throws CommandException, WorldEditException {
    CommandContext commandContext = null;
     
    commandContext = new CommandContext(args);
     
    LocalSession localSession = worldEdit.getSession(localPlayer);
    LocalWorld localWorld = localSession.getSelectionWorld();
    EditSession editSession = new EditSession(localWorld, -1);
     
    new RegionCommands(worldEdit).replace(commandContext, localSession, localPlayer, editSession); //Invoke WorldEdit's replace command to avoid using their API
     
    }
     
    public int getReplaceInformation(String args) throws DisallowedItemException, UnknownItemException, IncompleteRegionException {
    CommandContext commandContext = null;
    try {
    commandContext = new CommandContext(args);
    } catch (CommandException e) {
    e.printStackTrace();
    }
     
    LocalSession localSession = worldEdit.getSession(localPlayer);
    LocalWorld localWorld = localSession.getSelectionWorld();
    ExtendedEditSession editSession = new ExtendedEditSession(localWorld, -1);
     
            Set<BaseBlock> from;
            Pattern to;
     
            int affected = 0;
     
            if (commandContext.argsLength() == 1) {
                from = null;
                to = worldEdit.getBlockPattern(localPlayer, commandContext.getString(0));
     
            } else {
                from = worldEdit.getBlocks(localPlayer, commandContext.getString(0), true, !commandContext.hasFlag('f'));
                to = worldEdit.getBlockPattern(localPlayer, commandContext.getString(1));
            }
     
            editSession.getBlockChangeCount(); //TODO: I don't think this needs to be here, don't have time to test right now. This was probably from a previous test.
     
    if (to instanceof SingleBlockPattern) {
                affected = editSession.getAffectedBlocks(localSession.getSelection(localPlayer.getWorld()), from, ((SingleBlockPattern) to).getBlock());
            } else {
                affected = editSession.getAffectedBlocks(localSession.getSelection(localPlayer.getWorld()), from, to);
            }
     
    return affected;
     
    }
    
    Here is ExtendedEditSession (almost all from WorldEdit):

    Code:
    public class ExtendedEditSession extends EditSession {
     
    public ExtendedEditSession(LocalWorld world, int maxBlocks) {
    super(world, maxBlocks);
    }
     
    public ExtendedEditSession(LocalWorld world, int maxBlocks, BlockBag blockBag) {
    super(world, maxBlocks, blockBag);
    }
     
        /**
        * Counts all the blocks of a type inside a region that will be replaced with another block type.
        *
        * @param region
        * @param fromBlockTypes -1 for non-air
        * @param toBlock
        * @return number of blocks affected
        */
        public int getAffectedBlocks(Region region, Set<BaseBlock> fromBlockTypes, BaseBlock toBlock) {
            Set<BaseBlock> definiteBlockTypes = new HashSet<BaseBlock>();
            Set<Integer> fuzzyBlockTypes = new HashSet<Integer>();
     
            if (fromBlockTypes != null) {
                for (BaseBlock block : fromBlockTypes) {
                    if (block.getData() == -1) {
                        fuzzyBlockTypes.add(block.getType());
                    } else {
                        definiteBlockTypes.add(block);
                    }
                }
            }
     
            int affected = 0;
     
            if (region instanceof CuboidRegion) {
                // Doing this for speed
                Vector min = region.getMinimumPoint();
                Vector max = region.getMaximumPoint();
     
                int minX = min.getBlockX();
                int minY = min.getBlockY();
                int minZ = min.getBlockZ();
                int maxX = max.getBlockX();
                int maxY = max.getBlockY();
                int maxZ = max.getBlockZ();
     
                for (int x = minX; x <= maxX; ++x) {
                    for (int y = minY; y <= maxY; ++y) {
                        for (int z = minZ; z <= maxZ; ++z) {
                            Vector pt = new Vector(x, y, z);
                            BaseBlock curBlockType = getBlock(pt);
     
                            if (fromBlockTypes == null) {
                                //replace <to-block>
                                if (curBlockType.isAir()) {
                                    continue;
                                }
                            } else {
                                //replace <from-block> <to-block>
                                if (!definiteBlockTypes.contains(curBlockType) && !fuzzyBlockTypes.contains(curBlockType.getType())) {
                                    continue;
                                }
                            }
     
                            ++affected;
       
                        }
                    }
                }
            } else {
                for (Vector pt : region) {
                    BaseBlock curBlockType = getBlock(pt);
     
                    if (fromBlockTypes == null) {
                        //replace <to-block>
                        if (curBlockType.isAir()) {
                            continue;
                        }
                    } else {
                        //replace <from-block> <to-block>
                        if (!definiteBlockTypes.contains(curBlockType) && !fuzzyBlockTypes.contains(curBlockType.getType())) {
                            continue;
                        }
                    }
     
                    ++affected;
     
                }
            }
     
            return affected;
        }
     
        /**
        * Counts all the blocks of a type inside a region that will be replaced with another block type.
        *
        * @param region
        * @param fromBlockTypes -1 for non-air
        * @param pattern
        * @return number of blocks affected
        */
        public int getAffectedBlocks(Region region, Set<BaseBlock> fromBlockTypes, Pattern pattern) {
            Set<BaseBlock> definiteBlockTypes = new HashSet<BaseBlock>();
            Set<Integer> fuzzyBlockTypes = new HashSet<Integer>();
            if (fromBlockTypes != null) {
                for (BaseBlock block : fromBlockTypes) {
                    if (block.getData() == -1) {
                        fuzzyBlockTypes.add(block.getType());
                    } else {
                        definiteBlockTypes.add(block);
                    }
                }
            }
     
            int affected = 0;
     
            if (region instanceof CuboidRegion) {
                // Doing this for speed
                Vector min = region.getMinimumPoint();
                Vector max = region.getMaximumPoint();
     
                int minX = min.getBlockX();
                int minY = min.getBlockY();
                int minZ = min.getBlockZ();
                int maxX = max.getBlockX();
                int maxY = max.getBlockY();
                int maxZ = max.getBlockZ();
     
                for (int x = minX; x <= maxX; ++x) {
                    for (int y = minY; y <= maxY; ++y) {
                        for (int z = minZ; z <= maxZ; ++z) {
                            Vector pt = new Vector(x, y, z);
                            BaseBlock curBlockType = getBlock(pt);
     
                            if (fromBlockTypes == null) {
                                //replace <to-block>
                                if (curBlockType.isAir()) {
                                    continue;
                                }
                            } else {
                                //replace <from-block> <to-block>
                                if (!definiteBlockTypes.contains(curBlockType) && !fuzzyBlockTypes.contains(curBlockType.getType())) {
                                    continue;
                                }
                            }
     
                            ++affected;
       
                        }
                    }
                }
            } else {
                for (Vector pt : region) {
                    BaseBlock curBlockType = getBlock(pt);
     
                    if (fromBlockTypes == null) {
                        //replace <to-block>
                        if (curBlockType.isAir()) {
                            continue;
                        }
                    } else {
                        //replace <from-block> <to-block>
                        if (!definiteBlockTypes.contains(curBlockType) && !fuzzyBlockTypes.contains(curBlockType.getType())) {
                            continue;
                        }
                    }
     
                    ++affected;
     
                }
            }
     
            return affected;
        }
     
    }
    
     
  7. Offline

    chriztopia

    I use worldguard to do this but I am sure worldedit will return the same results.

    Code:
    public static Selection getWorldEditSelection(Player ply) {
    Plugin we = Bukkit.getPluginManager().getPlugin("WorldEdit");
    if(we != null && we instanceof WorldEditPlugin) {
    return ((WorldEditPlugin) we).getSelection(ply);
    }
    return null;
    }
    //---------------------------
    //will return well what it says. Area is what ur probly looking for.
    int area = getWorldEditSelection(player).getArea();
    int height = getWorldEditSelection(player).getHeight();
    int length = getWorldEditSelection(player).getLength();
    int width = getWorldEditSelection(player).getWidth();
    //--------------------------
    if by chance you use worldguard there is a volume option. I use the worldguard part in my plugin to do price per block. http://dev.bukkit.org/server-mods/buyland/
     
  8. Offline

    bgsteiner

    Im creating an automation system to verify that the minimum number of blocks for a certain id in a given cuboid selection are their instead of having to test the count of each block type.
     
Thread Status:
Not open for further replies.

Share This Page