Solved Cancelling *all* enderman teleporting

Discussion in 'Plugin Development' started by Hedgehogs4Me, Jun 4, 2013.

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

    Hedgehogs4Me

    So I'm running a server where endermen teleporting can be a problem, and I need to stop it entirely. I've cancelled the event, but there's a problem!

    They still teleport when shot with an arrow, splashed with a potion, or lit on fire.

    Is there any way to prevent this? I'm willing to go to rather extreme lengths.
     
  2. Offline

    Nitnelave

    Have a look at the bukkit source to see how it is implemented. It may not even be possible (meaning you may have to open a ticket and/or provide a fix). But maybe cancelling the damageEvent and implementing your own might do the trick.
     
  3. Offline

    Hedgehogs4Me

    I don't think endermen even get damage from arrows or potions, meaning that I can't just cancel the damage event. I don't know how I'd even get close to making my own event. I'm looking at this code and it looks like it's missing the part that actually makes it work. I'm confused and I don't understand it at all.

    EDIT: I could do something proving the following unlikely things are true:
    1) Entity.teleport() doesn't trigger EntityTeleportEvent (so that I can still block regular teleportation), and
    2) Even though they dodge getting any damage, shooting an enderman with an arrow or splashing a potion on it still triggers EntityDamageEvent.

    Sounds extremely unlikely (so much so that I kind of don't even want to test it), but here's my code in case anyone has any suggestions that could make this sort of thing work.

    Code:
            private class ReturnThatEnderman extends BukkitRunnable{
                private Enderman Enderpal;
                private Location Enderloc;
             
                public ReturnThatEnderman(Enderman Enderpal, Location Enderloc){
                    this.Enderpal = Enderpal;
                    this.Enderloc = Enderloc;
                }
                public void run(){
                    Enderpal.teleport(Enderloc);
                }
            }
         
            @EventHandler
            public void onEntityDamage(EntityDamageEvent event){
                if(event.getEntityType()==EntityType.ENDERMAN){
                    Enderman Enderpal = (Enderman)event.getEntity();
                    Location Enderloc = Enderpal.getLocation();
                    if(event.getCause()==DamageCause.FIRE||event.getCause()==DamageCause.FIRE_TICK){
                        Enderpal.setFireTicks(0);
                    }
                    ReturnThatEnderman Enderwait = new ReturnThatEnderman(Enderpal, Enderloc);
                    Enderwait.runTaskLater(ArenaFixes.this, 1);
                }
            }
    ReturnThatEnderman is inside FixerListener is inside ArenaFixes. Yay for not wanting to use more than one class file.
     
  4. Offline

    Nitnelave

    Alas by looking at the source I see a direct connection from the arrow reaching the Enderman to the Enderman teleporting, so the only way to prevent the enderman from teleporting is to create your own Endermanm and override the damageEntity or the j() method (that teleports the enderman).
     
  5. Offline

    Hedgehogs4Me

    Oh goodness. How can I do this? Is it complicated enough that should just make a plugin request?
     
  6. Offline

    Nitnelave

    It's not that complicated. But you'll neeed to have a look at the source code for the EntityEnderman class to know what each method (kind of ) does and how it does it. Or at least for damageEntity and j().
    You need to create your own custom enderman that extends EntityEnderman, and then you listen for all enderman spawning, you cancel them and spawn you custom enderman instead.
     
  7. Offline

    Hedgehogs4Me

    I'm totally puzzled. I've never done anything like this before in my life. Something like this?

    Code:
    public class FixedEnderman extends EntityEnderman{
        @Override
        protected boolean j(double d0, double d1, double d2){
            return false;
        }
    }
     
    @EventHandler
    public void onMobSpawn(CreatureSpawnEvent event){
        if(event.getEntityType()==EntityType.ENDERMAN){
            Location Enderloc = event.getEntity().getLocation();
            FixedEnderman Enderpal = new FixedEnderman;
            Enderloc.getWorld().spawn(Enderpal, Enderloc);
            event.setCancelled(true);
        }
    }
    Follow-up question: I'm using this for MobArena, and it records all mobs so it can delete them when the arena session is over. Will it still be able to find and delete these guys, recognizing them as endermen? Or do I have to hook MA and listen for when an arena ends?
     
  8. Offline

    Nitnelave

    Your guys are Endermen, so thry will be recognized as such.

    I don't have the code right here, so I can't tell you if what you did will zork, you just havr to try. One thing, though : don't put the onMobSpawn in the Enderman class, but rather in a separate Listener class (don't forget to implement Listener and to register events).

    And you forgot the parenthesis in your call to the FixesEnderman constructor'
     
    Hedgehogs4Me likes this.
  9. Offline

    Hedgehogs4Me

    I can't seem to figure out how to get it spawned. I've tried and tried, and I eventually came up with this:
    Code:
    @EventHandler
    public void onCreatureSpawn(CreatureSpawnEvent event){
        if(event.getEntityType()==EntityType.ENDERMAN){
            Location Enderloc = event.getEntity().getLocation();
            Enderloc.getWorld().spawn(Enderloc,FixedEnderman.class);
            event.setCancelled(true);
        }
    }
    with a shamelessly copied and pasted FixedEnderman class:
    Code:
    public class FixedEnderman extends EntityEnderman{
        public FixedEnderman(World world) {
            super(world);
            this.texture = "/mob/enderman.png";
            this.bI = 0.2F;
            this.a(0.6F, 2.9F);
            this.Y = 1.0F;
        }
     
        @Override
        protected boolean j(double d0, double d1, double d2){
            return false;
        }
    }
    and it's exactly one error away from being at least compilable. I can't make any claims about it being correct at this point.
    Enderloc.getWorld().spawn(Enderloc,FixedEnderman.class); gives me the following error:
    Obviously I can't just make it extend Entity, since it already extends EntityEnderman. To be honest, I really have no idea what this means. Am I even going about this in a somewhat vaguely correct manner?
    I feel so stupid.
     
  10. Offline

    Nitnelave

    Don't extend EntityEnderman, but rather CraftEnderman, maybe (if it exists) or explicitly implement the Enderman interface (or look for a similar enderman class implementing the Enderman interface).
     
  11. Offline

    Hedgehogs4Me

    CraftEnderman seems to exist, but I'm completely lost already. I didn't even know there was an org.bukkit.craftbukkit. Maybe I should just request this plugin instead of trying to write it myself, since it seems like I'd have to be walked through this like a chimp trying to do calculus. Unless I'm just missing some super obvious way of doing it, that is.
     
  12. Offline

    Nitnelave

    No, it should be alright, I think.
    CraftBukkit is the backend of Bukkit, so not the official API, but the implementation behind. Developers are not supposed to use it (plugin using it break with every major update as a dissuasive measure), but it's still the only way to do some things, including what you're trying to do, and it is quite common to use it anyway.

    If you need help, I'm here, don't hesitate to ask.
     
  13. Offline

    CoderCloud

    Here is a usefull thread about custom mob behavior. I think you just have to overide the right method and extend the EntityEnderman.
     
    Hedgehogs4Me likes this.
  14. Offline

    Hedgehogs4Me

    CoderCloud Thanks, that actually works! I had to change a few things to make it not throw any errors, and there were a few deprecated things that I fixed, but now it seems to be working fine.

    Interestingly enough, they still seem to dodge arrows and potions, but they come right back. I wonder if I can totally stop it dodging arrows and make it not react to sunlight. This is going to be fun!

    Thanks again to both of you!
     
  15. Did you figure it out?
     
  16. Offline

    SnowGears

    Did you ever figure this out?
     
  17. Offline

    AndyMcB1

    Could you check everytime an enderman moves and check the velocity? I know it's a very bad way of doing it, but would it work?
     
Thread Status:
Not open for further replies.

Share This Page