Solved Efficiency question

Discussion in 'Spigot Plugin Development' started by Dramatically, Jan 17, 2020.

  1. I have some code and another developer is saying there is a better faster and less laggy method:

    Code (Text):

    private void home(Player player, WitherSkull witherSkull) {
            double vel = plugin.getConfig().getDouble("global-options.projectile-speed");
            witherSkull.setVelocity( witherSkull.getVelocity().add(player.getEyeLocation().getDirection().toBlockVector().multiply( .7 * vel ) ).normalize().multiply( vel ) );

            Location origin = witherSkull.getLocation();
            BukkitTask task = Bukkit.getScheduler().runTaskTimer(plugin, new BukkitRunnable() {
                        @Override
                        public void run() {
                            if (witherSkull.isDead()) {
                                playerLastWitherSkull.get(player.getUniqueId()).cancel();
                                playerLastWitherSkull.remove(player.getUniqueId());
                            }

                            if (!witherSkull.isDead() && witherSkull.getLocation().distance(origin) >= plugin.getConfig().getInt("global-options.maximum-distance")) {
                                util.detonate(witherSkull);
                                Bukkit.getPluginManager().callEvent(new ProjectileHitEvent(witherSkull));
                                playerLastWitherSkull.get(player.getUniqueId()).cancel();
                                playerLastWitherSkull.remove(player.getUniqueId());
                            }
                            witherSkull.setDirection(player.getEyeLocation().getDirection().multiply( .7 * vel ).normalize().multiply( vel ) );
                        }
            }, 0L, 0L);
            playerLastWitherSkull.put(player.getUniqueId(), task);
        }
     
    The dev said that it would be better to check for entitydeathevent rather than checking if it’s died or not. Is that more efficient or just the same?
     
  2. I mean... an EntityDeathEvent gets triggered once. And only once. Your runnable runs every time? I don't even know what the behaviour is of a runnable that has a 0 tick delay...
    So hell yea, listening for the death event is way more efficient
     
  3. Yes using the EntityDeathEvent would be more efficient than a BukkitRunnable running every tick. Even if the WitherSkull is dead though, the BukkitRunnable never cancels. If it runs after the skull has died, you'll get an NPE because of this line:
    Code (Java):
    playerLastWitherSkull.get(player.getUniqueId()).cancel();
    This would be because the skull was already dead in the last iteration and the player was removed from your Map.
    BukkitRunnables on a timer will only fire as often as once per tick, so 0 ticks would default to 1 tick anyways.
     
    #3 Escad, Jan 17, 2020
    Last edited: Jan 17, 2020
  4. I get no errors and works fine
     
  5. That's the whole point of entity death event
     
  6. Well, when you remove the player from the map then try to get them from the map again and run a method on them, that's exactly how you get an NPE.. But regardless of errors, you want the most efficient method, don't you? Just switch to Listeners. If you need to constantly change the velocity of your wither skulls, you'll probably still want the BukkitRunnable somewhere though.
     
  7. But you asked how your code could be more efficient, did you not? What is the point of doing that if you’re just going to say that it works fine as is if there’s a better way to do it?
     
  8. Alright Ill switch to listeners.