AutoBow - PlayerInteractEvent

Discussion in 'Plugin Development' started by ShadowLAX, Jul 24, 2013.

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

    ShadowLAX

    Hi all, I'm trying to make an AutoBow, and I know it has to do with the PlayerInteractEvent, I just don't know what I'm doing wrong. I have already registered my event class in the main, so that isnt the problem.

    Code:java
    1. @EventHandler
    2. public void onBowUse(PlayerInteractEvent e) {
    3. Player player = e.getPlayer();
    4. ItemStack bow = new ItemStack(Material.BOW);
    5. String name = player.getName();
    6. if (player.getItemInHand() == bow) {
    7. player.launchProjectile(Arrow.class);


    Thanks!
     
  2. Offline

    MuisYa

    Code:
    if (player.getItemInHand() == bow) {
    This 'if statement' will never pass because:

    Object 1 is the item in the players hand,
    Object 2 is a new 'bow'.

    As you can see, 'Object 1' can be the same material as 'Object 2' but they're not the same objects. So if you compare these 'objects' they will never be the same.
    You can fix this by instead of comparing the objects: compare the materials.

    Code:
    if (player.getItemInHand().getType() == Material.BOW) {
     
  3. Offline

    ShadowLAX

    Notorious-Riddler There are no errors in console.
    Code:java
    1. package me.shadowlax.testproject;
    2.  
    3. import org.bukkit.Material;
    4. import org.bukkit.entity.Arrow;
    5. import org.bukkit.entity.Player;
    6. import org.bukkit.event.EventHandler;
    7. import org.bukkit.event.Listener;
    8. import org.bukkit.event.player.PlayerInteractEvent;
    9. import org.bukkit.inventory.ItemStack;
    10.  
    11. public class EventListener implements Listener {
    12.  
    13. @EventHandler
    14. public void onAuto(PlayerInteractEvent e) {
    15. Player player = e.getPlayer();
    16. ItemStack bow = new ItemStack(Material.BOW);
    17. if (player.getItemInHand() == bow) {
    18. player.launchProjectile(Arrow.class);
    19. }
    20.  
    21. }
    22. };


    Oh, I tried that already but I guess I forgot to put the .getType() :oops:

    I will try this out, thanks!

    MuisYa This somewhat works, It works when i right click it, but I want it so when I pull it back all the way it still fires.

    Is there anyway to make it constantly shoot when the bow is pulled all the way back?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  4. make it loop to make it constantly shoot

    Example ill make the bow shoot 10 arrows

    Code:java
    1. int i;
    2. for(i=0;i < 10;i++){
    3.  
    4. player.launchProjectile(Arrow.class);
    5.  
    6. }
     
  5. Offline

    ShadowLAX

    Notorious-Riddler I did this, and now its acting like a shotgun type bow, not a machine gun type bow. :|
     
  6. you would have to make a delay in between im not speed feading you i was just giving you an idea
     
  7. Offline

    ShadowLAX

    Notorious-Riddler oh, ok.

    How would I set a delay for the arrows?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  8. Offline

    Chinwe

    Use a BukkitRunnable:
    Code:
    new BukkitRunnable()
    {
        int count = 10;
        public void run()
        {
            // shoot arrow
            count--;
            if (count == 0)
                cancel();
        }
    }.runTaskTimer(plugin, delay, interval);
     
  9. Offline

    ShadowLAX

    Chinwe ok, this makes sense. Can you help me with this question too?

    I want to bow to start autofiring when the bow is pulled al the way back, like a regular bow. Is there anyway to do this?
     
  10. Offline

    Chinwe

    The pulling back animation is clientside, but you could try delaying the autofiring by however many ticks it takes for the bow to be pulled back fully?
    As for detecting when they let it go - this is competely off the top of my head, no idea if it could work - checking their walk speed, as drawing back bows slow you down? You might want to experiment with that a bit :3
     
  11. Offline

    ShadowLAX

    Chinwe So, to delay it until the animation is done, just use another runnable? as for the let go detection, I would use the... PlayerMoveEvent?
     
  12. Offline

    Chinwe

    ShadowLAX Yep, though instead of .runTaskTimer(), use .runTaskLater(plugin, delay); for a one time delayed task.

    If all else fails you couuuld use PlayerMoveEvent, though that could be too intensive for little gain: I was more thinking of player.getWalkSpeed() - you could test if this works by using a temporary runnable to print out .getWalkSpeed() every few ticks and pull back a bow
     
  13. Offline

    ShadowLAX

    Chinwe do you know the normal walk speed?
     
  14. Offline

    Chinwe

  15. Offline

    ShadowLAX

    Chinwe Um, im getting an error in console:
    16:08:10 [SEVERE] Could not pass event PlayerInteractEvent to FunBow v0.1
    org.bukkit.event.EventException
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:427)
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:477)
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:462)
    at org.bukkit.craftbukkit.v1_6_R2.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:192)
    at org.bukkit.craftbukkit.v1_6_R2.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:162)
    at net.minecraft.server.v1_6_R2.PlayerConnection.a(PlayerConnection.java:610)
    at net.minecraft.server.v1_6_R2.Packet15Place.handle(SourceFile:58)
    at net.minecraft.server.v1_6_R2.NetworkManager.b(NetworkManager.java:296)
    at net.minecraft.server.v1_6_R2.PlayerConnection.e(PlayerConnection.java:118)
    at net.minecraft.server.v1_6_R2.ServerConnection.b(SourceFile:37)
    at net.minecraft.server.v1_6_R2.DedicatedServerConnection.b(SourceFile:30)
    at net.minecraft.server.v1_6_R2.MinecraftServer.t(MinecraftServer.java:590)
    at net.minecraft.server.v1_6_R2.DedicatedServer.t(DedicatedServer.java:226)
    at net.minecraft.server.v1_6_R2.MinecraftServer.s(MinecraftServer.java:486)
    at net.minecraft.server.v1_6_R2.MinecraftServer.run(MinecraftServer.java:419)
    at net.minecraft.server.v1_6_R2.ThreadServerApplication.run(SourceFile:582)
    Caused by: java.lang.IllegalArgumentException: Plugin cannot be null
    at org.apache.commons.lang.Validate.notNull(Validate.java:203)
    at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.validate(CraftScheduler.java:391)
    at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.runTaskTimer(CraftScheduler.java:120)
    at org.bukkit.scheduler.BukkitRunnable.runTaskTimer(BukkitRunnable.java:98)
    at me.shadowlax.funbow.FunBowListener.onAuto(FunBowListener.java:73)
    at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:425)
    ... 16 more

    Plugin cannot be null, and yet I defined my main class by using public Main plugin;
    and in the bukkit runnable I used plugin as the plugin args.
     
  16. Offline

    jdawgerj515

    New Code?
     
  17. Offline

    ShadowLAX

    jdawgerj515
    Code:java
    1. public class FunBowListener implements Listener {
    2.  
    3. public Main main;
    4.  
    5. @EventHandler
    6. public void onAuto(PlayerInteractEvent e) {
    7. final Player player = e.getPlayer();
    8. String name = player.getName();
    9. if (player.getItemInHand().getType() == Material.BOW) {
    10. if (Main.Auto.contains(name) && e.getAction() == Action.RIGHT_CLICK_AIR) {
    11. player.playSound(player.getLocation(), Sound.CREEPER_HISS, 20, 1);
    12. Bukkit.getScheduler().scheduleSyncRepeatingTask(main, new BukkitRunnable() {
    13. public void run() {
    14. int count = 10;
    15. player.launchProjectile(Arrow.class);
    16. count--;
    17. if (count == 0 || player.getWalkSpeed() <= 0.2) {
    18. cancel();
    19. }
    20. }
    21. }, 40L, 20L);
    22. }
    23. }
    24. }
     
  18. Offline

    jdawgerj515

    Make an instance to Main and call it something like plugin and change this:
    Code:
    Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new BukkitRunnable() {
    
    EDIT: Basically get rid of line 3: public Main main;
    And put: public Main plugin;
    And make a constructer like this:
    Code:
    public FunBowListener(Main instance)
    {
        plugin = instance;
    }
    EDIT:
    Forget what I said about changing main to plugin, that doesn't matter, just do everything else and I think that should fix the problem
     
  19. Offline

    ShadowLAX

    jdawgerj515 Thanks, This worked! :D I tried this out, and it started firing, but it wouldn't stop xD Any idea how to stop it? :p
     
  20. Offline

    jdawgerj515

    Try something along the lines of this:
    Code:
    while (event.getAction().equals(Action.RIGHT_CLICK_AIR) || event.getAction().equals(Action.RIGHT_CLICK_BLOCK))
    {
    //Shoot Arrow
    }
    That may be completely wrong but use that logic.

    EDIT: And next time, keep this in consideration: Always analyze the issue before you ask a question on here. If it wont stop shooting an arrow that obviously means that it is an infinite loop so you need to set it so that it only shoots when a certain condition is set. I hope that helps you understand better.
     
  21. Offline

    ShadowLAX

    jdawgerj515 I knew it was an infinite loop, I just didn't understand why it was. My code looked like it owuld only shoot 10 times before it stopped, but it kept going.
     
  22. Offline

    jdawgerj515

    Wait, oh ya thats right you are using a scheduler for some reason to schedule it to shoot arrows every however many seconds? I am guessing this is to set the amount of time between each arrow launch? Well put the while loop statement around the scheduler. I think that should still work with the scheduler.
     
  23. Offline

    ShadowLAX

    jdawgerj515 There is an error in console now, and I know why it isn't stopping.

    Error:
    Code:
    21:23:19 [WARNING] [FunBow] Task #39 for FunBow v0.1 generated an exception
    java.lang.IllegalStateException: Not scheduled yet
        at org.bukkit.scheduler.BukkitRunnable.getTaskId(BukkitRunnable.java:129)
        at org.bukkit.scheduler.BukkitRunnable.cancel(BukkitRunnable.java:18)
        at me.shadowlax.funbow.FunBowListener$1.run(FunBowListener.java:73)
        at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftTask.run(CraftTask.java:53)
        at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:345)
        at net.minecraft.server.v1_6_R2.MinecraftServer.t(MinecraftServer.java:522)
        at net.minecraft.server.v1_6_R2.DedicatedServer.t(DedicatedServer.java:226)
        at net.minecraft.server.v1_6_R2.MinecraftServer.s(MinecraftServer.java:486)
        at net.minecraft.server.v1_6_R2.MinecraftServer.run(MinecraftServer.java:419)
        at net.minecraft.server.v1_6_R2.ThreadServerApplication.run(SourceFile:582)
    
    this is line 73:
    Code:
    cancel();
    rest of my code:
    Code:
    @EventHandler
        public void onAuto(PlayerInteractEvent e) {
            final Player player = e.getPlayer();
            String name = player.getName();
            if (player.getItemInHand().getType() == Material.BOW) {
                if (Main.Auto.contains(name) && e.getAction() == Action.RIGHT_CLICK_AIR) {
                    player.playSound(player.getLocation(), Sound.CREEPER_HISS, 20, 1);
                    Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new BukkitRunnable() {
                                int count = 10;
                                public void run() {
                                    player.launchProjectile(Arrow.class);
                                    count--;
                                    if (count >= 0 || player.getWalkSpeed() >= 0.2) {
                                        cancel();
                                        count = 10;
                                    }
                                }
                            }, 30L, 5L);
                }
            }
    The Cancel() method doesn't seem to be working...
     
  24. Offline

    HepoSys

    I would not suggest using while loops for this, tried it in many different ways. It just lags up the server until it crashes.
     
  25. Offline

    ShadowLAX

    Yeah, I tried a while loop. For some reason though, console keeps saying that It generated an exception.

    Code:
    [WARNING] [FunBow] Task #2 for FunBow v0.1 generated an exception
    java.lang.IllegalStateException: Not scheduled yet
        at org.bukkit.scheduler.BukkitRunnable.getTaskId(BukkitRunnable.java:129)
        at org.bukkit.scheduler.BukkitRunnable.cancel(BukkitRunnable.java:18)
        at me.shadowlax.funbow.FunBowListener$1.run(FunBowListener.java:73)
        at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftTask.run(CraftTask.java:53)
        at org.bukkit.craftbukkit.v1_6_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:345)
        at net.minecraft.server.v1_6_R2.MinecraftServer.t(MinecraftServer.java:522)
        at net.minecraft.server.v1_6_R2.DedicatedServer.t(DedicatedServer.java:226)
        at net.minecraft.server.v1_6_R2.MinecraftServer.s(MinecraftServer.java:486)
        at net.minecraft.server.v1_6_R2.MinecraftServer.run(MinecraftServer.java:419)
        at net.minecraft.server.v1_6_R2.ThreadServerApplication.run(SourceFile:582)
    
    I dont get why though :| my code is in my above post.

    I can't seem to be able to cancel the task... cancel() is not working.. :| Someone help please? :(

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  26. Offline

    Chinwe

    This :<

    I think infinite loop because you hold down right click to fire bow - holding it down to autobow will keep firing the event - you could try having a HashMap with <String, BukkitTask> that stores player names and a bukkittask to prevent multiple tasks ->
    Code:
    HashMap<String, BukkitTask> map = new HashMap<String, BukkitTask>();
     
    public void onInteract (PlayerInteractEvent event)
    {
        // do all your checks
        if (map.get(player.getName() != null)
        {
            // start new timer
            BukkitTask task = new BukkitRunnable()
            { // timer stuff here \\}
           
            // save to map
            map.put(player.getName(), task);
     
     
            // Whenever you're cancelling it
            map.put(player.getName(), null);
        }
     
    }
     
  27. Offline

    ShadowLAX

    Chinwe Shouldn't I check to see if it is null in the hasmap, because that would mean that they aren't in it, and how would I cancel the repeatng task? >.< I'm kind of a noob with Runnables... :(
     
  28. Offline

    Chinwe

    Use cancel(); as before, it shouldn't give that "Plugin cannot be null" error if you're initializing 'plugin' like @jdawgerj515 said : unfortunately I'm going on holiday for two weeks now and can't help until then: hopefully someone else who understands BukkitRunnables can help you now, sorry :'(
     
  29. Offline

    ShadowLAX

    Chinwe oh man, Well thanks for your help! I really appreciate it dude :)

    Anyone who understands how runnables work: Does the cancel(); method go inside the run() method, or outside of it?

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

    HepoSys

    I do not know how Runnables work, when doing things like this I have things like RunTick() in Minecraft, Too bad this doesn't have it. But Runnables are the same concept as a while statement with a delay in-between. If you found how how to do that, it would be easy, since you can just have a the while be like:
    Code:java
    1. while(player.getItemInHand().getType() == Material.Bow && isBowPulled()){ shoot arrow }
    2.  

    But instead you might need to do something like this:
    Code:java
    1. while(Bow in Hand && is pulled back){
    2. if(delayran){
    3. shoot arrow
    4. }
    5. }

    But that doesn't work and it lags too much.
     
Thread Status:
Not open for further replies.

Share This Page