Getting a selection from event handler

Discussion in 'Plugin Development' started by Chinwe, Nov 3, 2013.

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

    Chinwe

    I have a Wizard class, that will listen to PlayerInteractEvent to get the two corners of a region which will be used for a command. The code is something like this:
    Code:
    // in onCommand
    Wizard w = new Wizard(p, "trigger region");
    w.addStep(Step.CUBOID_SELECTION);
    Cuboid selected = w.initiate();
    // continue with more wizards/selections
    I then listen for their selecting of the cuboid:
    Code:
    @EventHandler
    public void onSelection(PlayerInteractEvent event)
    {
        // do some checks
        event.setCancelled(true);
     
        aw.cuboid[aw.cuboidSelection] = event.getClickedBlock().getLocation();
        aw.cuboidSelection = aw.cuboidSelection == 0 ? 1 : -1;
     
        message("&bPoint " + (aw.cuboidSelection == 1 ? "1" : "2") + " selected at &3" + Utils.formatLocation(event.getClickedBlock().getLocation()));
    if (aw.cuboidSelection == -1)
    {
            Cuboid c = new Cuboid(aw.cuboid[0], aw.cuboid[1]);
            // now what ?
    


    I would like to somehow return this Cuboid from the listener to the command handler - how could I do this? Would it have something to do with running the command in another thread, which then waits until both points have been selected?

    I would be grateful if you could help with this, as I can't get my head around it :oops:
     
  2. Offline

    Chinwe

    Shameless bump :oops:
     
  3. Offline

    clienthax

    Why not use the worldedit api to get the area?

    Code:java
    1. WorldEditPlugin worldEditPlugin = null;
    2. worldEditPlugin = (WorldEditPlugin) this.mainPlugin.getServer().getPluginManager().getPlugin("WorldEdit");
    3. Selection sel = worldEditPlugin.getSelection(plr);
    4.  
    5. if (sel instanceof Polygonal2DSelection) {
    6. Polygonal2DSelection polySel = (Polygonal2DSelection) sel;
    7. int minY = polySel.getNativeMinimumPoint().getBlockY();
    8. int maxY = polySel.getNativeMaximumPoint().getBlockY();
    9. }
    10. else if (sel instanceof CuboidSelection) {
    11. BlockVector min = sel.getNativeMinimumPoint().toBlockVector();
    12. BlockVector max = sel.getNativeMaximumPoint().toBlockVector();
    13. }
     
  4. Offline

    xTrollxDudex

    Chinwe
    What do you want to hand over to the command? The region?
     
  5. Offline

    Noxyro

    I think not everyone wants to implement WorldEdit in his plugin.


    Chinwe: Why don't you just save the first position of the selection and the second position of the selection together with two booleans wich signal if a position is already set or not. Then just check with these two booleans in your PlayerInteractEvent if you have to save Pos 1 or Pos 2 at the current event.

    Edit: Oh didn't read the topic correctly.

    If you want to hand over the cuboid to the command handler you have to create a static function or a method inside your command handler wich accepts the data from the listener.
    Something like: newCuboid(Cuboid cubuoid) {...}
     
  6. Offline

    Chinwe

    clienthax
    I'd rather not have any dependencies (even though most servers would have WorldEdit)

    xTrollxDudex
    Yeh, the Cuboid object, which then continues the command, without having to have several methods for each command, such as:
    Send "Please select a region", create a Wizard and return ----> Wizard gets the selection, and calls another method that carries on, possibly asking for another selection and returns etc..
     
  7. Offline

    calebbfmv

    What I have done is save the 2 cuboid on player click events, left and right click separately, saving the World,X, Y, Z to a flat file, or MySQL, then on command, get the locations, then do what I need to do with them.

    Short answer, save them to a file, get the file, create the cuboid on command.
     
  8. Offline

    Chinwe

    calebbfmv
    I need them to select the cuboid while running the command, rather than loading a preselected one from a file :oops:
     
  9. Offline

    calebbfmv

    Chinwe
    Look at what I said, listen to PlayerIneractEvent,2 of them, one for right click, one for left click, store the XYZ and world in a file, then on command, create 2 new locations, then create the cuboid from the Locations:
    Code:
    
            File playerFile = new File(plugin.getDataFolder()
                    .getAbsolutePath()
                    + File.separatorChar
                    + "graveyard"
                    + File.separatorChar
                    + "graveyards"
                    + ".yml");
            YamlConfiguration p = YamlConfiguration
                    .loadConfiguration(playerFile);
            World world = Bukkit.getWorld(p.getString(
                    "graveyard.Rworld").toString());
            Location locc1 = new Location(world, p.getInt("graveyard.Rx"), p.getInt("graveyard.Ry"), p.getInt("graveyard.Rz"));
    
            World lWorld = Bukkit.getWorld(p.getString("graveyard.lworld").toString());
    
            Location Llocc1 = new Location(lWorld, p.getInt("graveyard.Lx"), p.getInt("graveyard.Ly"), p.getInt("graveyard.Lz"));
                Cuboid cuboid = new Cuboid(Llocc1, locc1);
    
     
  10. Offline

    Chinwe

    calebbfmv
    Ah ok I see what you mean, storing the Cuboid in a file in order to access it? I'll be able to access it through the Wizard object, it's just pausing the command process while the player selects it which is the problem :oops:
     
  11. Offline

    calebbfmv

    Huh? I don't understand your problem. When the player selects, just store. Then on command, just get the locs, nothing more, nothing less.
     
  12. Offline

    Chinwe

    calebbfmv
    The selection process takes place during the command, and should continue after they have selected it, such as onCommand sends a message "Please select a region" -> they select it -> now enter something into chat -> now select another region -> etc
     
  13. Offline

    calebbfmv

    Why would you want to do that?
    Here is how though:
    Create an arraylist and a method to get the containment of the list.
    Then on command, add them, then on the listener check if the arraylist contains the player, if so continue, ect.
     
  14. Offline

    xTrollxDudex

    Chinwe
    You should pass the cuboid object to the command as son as the two points are selected.
     
  15. Offline

    FinalFred

    If you're serious about "during" the command (I don't see why that's necessary) then you have to pause the thread that's handling the command (I hope that's not the main thread!).

    Then either have a 2 element list/array or 2 variables somewhere in memory that both the command thread and the main thread can access. Public, static fields are a quick and dirty way if you're not overly concerned with style. If you're going with that approach, I recommend placing the static fields in the command handler's class.

    After the user selects both cubes (check this during the interaction event handling), unpause the command thread (called an interrupt) and let the command keep processing.



    That said, why can't you just do whatever it was you were going to do in the interaction event? That seems like a much cleaner way of doing things in my opinion. If you're only worried about organization, make a static method in the command class that actually does the processing, or have some reference to the command class instance.
     
  16. Offline

    afistofirony

    Chinwe As for actually implementing your "step-by-step" system, you could try something like this:

    Code:
    public class CommandClass implements CommandExecutor {
     
        HashMap<String, Integer> steps = new HashMap<String, Integer>();
     
        public boolean onCommand (CommandSender sender, Command command, String label, String[] args) {
            // arbitrary checks for player (declared (Player) sender as player), permission, etc skipped here
            try {
                if (!steps.containsKey(player.getName())
                    steps.put(player.getName(), 0);
                int step = steps.get(player.getName());
                switch (step) {
                      case 0: // do stuff for each step here
                }
     
                steps.put(player.getName(), step + 1);
               // NOTE: We want to throw exceptions (or just return true) because otherwise the step count is incremented
               // even if execution failed.
            } catch (final Exception e) { 
                sender.sendMessage(ChatColor.RED + e.getMessage());
            }
        }
     
    }
    I should also point out that you can always invoke your method manually from your listener(s), so you can theoretically make your interaction listener execute the command if the selection is ready. However, you'd need to have a copy of the command executor (the same one used by Bukkit) available so your HashMap's values would match up:

    Code:
    public static PluginClass instance;
    public static CommandClass commandInstance;
     
    public void onEnable() {
    instance = this;
    // ...
    commandInstance = new CommandClass();
    getCommand("example").setExecutor(commandInstance);
    // ...
    }
     
    public static Command getCommand(String value) { // You may need to check if this works.
        return instance.getCommand(value);
    }
     
    // and in your listeners...
    PluginClass.commandInstance.onCommand(event.getPlayer(), PluginClass.getCommand("example"), "example",
    new String[]{});
     
Thread Status:
Not open for further replies.

Share This Page