[SPIGOT-6227] EntityDeathEvent and EntityDamageEvent not called when entity falls in the void Created: 07/Nov/20 Updated: 12/Nov/20 Resolved: 09/Nov/20 |
|
| Status: | Resolved |
| Project: | Spigot |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Minor |
| Reporter: | Frank van der Heijden | Assignee: | Unassigned |
| Resolution: | Cannot Reproduce | Votes: | 0 |
| Labels: | None | ||
| Environment: |
Empty spigot server. |
||
| Version: | 37d799b-3eb7236 1.16.4 |
| Guidelines Read: | Yes |
| Description |
|
EntityDeathEvent and EntityDamageEvent are not called when entity falls in the void, however, if you jump together with the entity into the void – the two events are called. It seems like spigot is just magically removing the entity below a certain y-level without calling any event when no player is nearby. With the same setup on a PaperMC server, their event `com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent` does fire when the entity is removed. |
| Comments |
| Comment by Airtheon Thesalion [ 12/Nov/20 ] |
|
So I looked into this and actually it has to do with how Minecraft handles hostile mob existence ranges. How to test this? Experiment 1:
Now I could NOT have died, but maybe spigot just unregisters entities that take damage? Well let's try another experiment for that. Experiment 2:
Okay so now we know that it has nothing to do with damage, just with distance. The next step is to see if the limit applies to special mobs, even if they are hostile. Experiment 3:
So all in all, there is nothing wrong with the EntityDeathEvent and EntityDamageEvent. This is just a side effect of Minecraft's optimization, where hostile mobs are unregistered when there are now players around them. And yes you are reading that right, this has nothing to do with Spigot whatsoever, try it in a singleplayer Minecraft world and the creeper will have despawned as well. |
| Comment by Frank van der Heijden [ 09/Nov/20 ] |
|
To illustrate the behaviour I meant I made a recording: https://frankheijden.stackstorage.com/s/A6RwvMLfQzUhouay The plugin visible in-game is practically the same as the plugin @md_5 described above: public class Spigot6227 extends JavaPlugin implements Listener { @Override public void onEnable() { super.onEnable(); getServer().getPluginManager().registerEvents(this, this); } @EventHandler public void onEntityDamage(EntityDamageEvent event) { getServer().broadcastMessage(event.getEntityType().name() + ": " + event.getCause().name()); } @EventHandler public void onEntityDeath(EntityDeathEvent event) { getServer().broadcastMessage(event.getEntityType().name() + ": Death"); } } I think this has to do with the entity tracking range of spigot, but I still find it weird that it doesn't call the EntityDeathEvent, even though the entity technically died (but not with a player nearby). |
| Comment by md_5 [ 09/Nov/20 ] |
@EventHandler
public void event(EntityDeathEvent event)
{
getServer().broadcastMessage( ReflectionToStringBuilder.toString( event ) );
}
@EventHandler
public void event(EntityDamageEvent event)
{
getServer().broadcastMessage( ReflectionToStringBuilder.toString( event ) );
}
[18:24:07] [Server thread/INFO]: org.bukkit.event.entity.EntityDamageByBlockEvent@1ecf1ed2[damager=<null>,modifiers={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},modifierFunctions={BASE=Functions.constant(-0.0), ARMOR=net.minecraft.server.EntityLiving$3@4cf4c8ec, RESISTANCE=net.minecraft.server.EntityLiving$4@12c6d11e, MAGIC=net.minecraft.server.EntityLiving$5@2e163a8c, ABSORPTION=net.minecraft.server.EntityLiving$6@48c99812},originals={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},cancelled=false,cause=VOID,entity=CraftCow,name=<null>,async=false]
[18:24:08] [Server thread/INFO]: org.bukkit.event.entity.EntityDamageByBlockEvent@22108a4f[damager=<null>,modifiers={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},modifierFunctions={BASE=Functions.constant(-0.0), ARMOR=net.minecraft.server.EntityLiving$3@67ae132, RESISTANCE=net.minecraft.server.EntityLiving$4@19a7792b, MAGIC=net.minecraft.server.EntityLiving$5@1daa7b05, ABSORPTION=net.minecraft.server.EntityLiving$6@3b4ec80d},originals={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},cancelled=false,cause=VOID,entity=CraftCow,name=<null>,async=false]
[18:24:08] [Server thread/INFO]: org.bukkit.event.entity.EntityDamageByBlockEvent@48a09f70[damager=<null>,modifiers={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},modifierFunctions={BASE=Functions.constant(-0.0), ARMOR=net.minecraft.server.EntityLiving$3@69cb732, RESISTANCE=net.minecraft.server.EntityLiving$4@4b5f194c, MAGIC=net.minecraft.server.EntityLiving$5@4756e0e5, ABSORPTION=net.minecraft.server.EntityLiving$6@b41bc60},originals={BASE=4.0, ARMOR=-0.0, RESISTANCE=-0.0, MAGIC=-0.0, ABSORPTION=-0.0},cancelled=false,cause=VOID,entity=CraftCow,name=<null>,async=false]
[18:24:08] [Server thread/INFO]: org.bukkit.event.entity.EntityDeathEvent@6887af1d[drops=[ItemStack{LEATHER x 2}, ItemStack{BEEF x 3}],dropExp=0,entity=CraftCow,name=<null>,async=false]
As you can see both events are called correctly. |
| Comment by Frank van der Heijden [ 08/Nov/20 ] |
|
Yup! This means that the entity magically disappears (as the PaperMC EntityRemoveFromWorldEvent does catch it as being unregistered), but without calling an EntityDeathEvent nor the damage chain before dying. The EntityDamageEvent and EntityDeathEvent aren't called for both the Spigot and Paper server setups. |
| Comment by Airtheon Thesalion [ 08/Nov/20 ] |
|
Actually PaperMC's `com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent` is fundamentally different. It is called from WorldServer whenever an entity is unregistered, instead of when an entity dies or takes damages. The reason this is so different is that after an entity death, it can be revived, but an unregistered entity cannot be reregistered. Also EntityDeathEvent and EntityDamageEvent are Paper events as well. Are they fired on the PaperMC setup? |