diff --git a/patches/api/0033-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/api/0033-Entity-AddTo-RemoveFrom-World-Events.patch index c3c7770fe1e0f..b869330d3cc32 100644 --- a/patches/api/0033-Entity-AddTo-RemoveFrom-World-Events.patch +++ b/patches/api/0033-Entity-AddTo-RemoveFrom-World-Events.patch @@ -53,16 +53,18 @@ index 0000000000000000000000000000000000000000..982a0abd9a90fcb99f8d7c60a89021a5 +} diff --git a/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..b58e2e7b8707c6221773b8f023f58a4eb9c7d4b9 +index 0000000000000000000000000000000000000000..52e756c7ef85992b8ad3b5fe060a9ea7081d295d --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/event/entity/EntityRemoveFromWorldEvent.java -@@ -0,0 +1,40 @@ +@@ -0,0 +1,115 @@ +package com.destroystokyo.paper.event.entity; + +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** @@ -70,11 +72,16 @@ index 0000000000000000000000000000000000000000..b58e2e7b8707c6221773b8f023f58a4e + * Note: The entity is updated prior to this event being called, as such, the entity's world may not be equal to {@link #getWorld()}. + */ +public class EntityRemoveFromWorldEvent extends EntityEvent { -+ @NotNull private final World world; + -+ public EntityRemoveFromWorldEvent(@NotNull Entity entity, @NotNull World world) { ++ private final World world; ++ private final RemovalReason removalReason; ++ ++ @ApiStatus.Internal ++ public EntityRemoveFromWorldEvent(@NotNull Entity entity, @NotNull World world, @NotNull RemovalReason removalReason) { + super(entity); ++ + this.world = world; ++ this.removalReason = removalReason; + } + + /** @@ -85,6 +92,15 @@ index 0000000000000000000000000000000000000000..b58e2e7b8707c6221773b8f023f58a4e + return world; + } + ++ /** ++ * Gets the reason the entity is being removed from the world. ++ * @return the removal reason ++ */ ++ @NotNull ++ public RemovalReason getRemovalReason() { ++ return removalReason; ++ } ++ + private static final HandlerList handlers = new HandlerList(); + + @NotNull @@ -96,4 +112,63 @@ index 0000000000000000000000000000000000000000..b58e2e7b8707c6221773b8f023f58a4e + public static HandlerList getHandlerList() { + return handlers; + } ++ ++ public enum RemovalReason { ++ ++ /** ++ * When an entity is removed after being killed. ++ */ ++ KILLED(true, false), ++ /** ++ * When an entity is removed after being discarded, such as from despawning. ++ */ ++ DISCARDED(true, false), ++ /** ++ * When an entity is removed after its containing chunk unloads. ++ */ ++ UNLOADED_TO_CHUNK(false, true), ++ /** ++ * When a player and its vehicle/passengers are removed after a player quits. ++ */ ++ UNLOADED_WITH_PLAYER(false, false), ++ /** ++ * When an entity is removed after moving to another world. ++ */ ++ CHANGED_DIMENSION(false, false), ++ /** ++ * Used when the cause of a removal is unknown. ++ */ ++ UNKNOWN(false, false); ++ ++ private final boolean destroy; ++ private final boolean save; ++ ++ RemovalReason(boolean destroy, boolean save) { ++ this.destroy = destroy; ++ this.save = save; ++ } ++ ++ /** ++ * Whether the entity instance being removed will be destroyed. ++ * ++ * @return whether the entity will be destroyed ++ */ ++ public boolean willDestroy() { ++ return this.destroy; ++ } ++ ++ /** ++ * Whether the entity instance being removed will be saved. This does not account for the value of ++ * {@link Entity#isPersistent}. Entities removed with {@link RemovalReason#UNLOADED_WITH_PLAYER} are saved ++ * prior to the event firing, and thus should be modified prior to this using another event, such as ++ * with {@link PlayerQuitEvent}. ++ * ++ * @return whether the entity will be saved ++ */ ++ public boolean willSave() { ++ return this.save; ++ } ++ ++ } ++ +} diff --git a/patches/server/0076-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server/0076-Entity-AddTo-RemoveFrom-World-Events.patch index 61e1e7d0aef4b..2c855d7526359 100644 --- a/patches/server/0076-Entity-AddTo-RemoveFrom-World-Events.patch +++ b/patches/server/0076-Entity-AddTo-RemoveFrom-World-Events.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Entity AddTo/RemoveFrom World Events diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index b4fdcfa28347beafe75339782d6e0cd7fc0b6256..f5c271c604dc74d9d82b44591ffc09e04567e3ab 100644 +index 5975cc2fa72609ea5f3e6f99155d6e5bc321a321..38d27d84c985724d1f58bbb7c8f19842cf397074 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -2161,6 +2161,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -16,11 +16,17 @@ index b4fdcfa28347beafe75339782d6e0cd7fc0b6256..f5c271c604dc74d9d82b44591ffc09e0 } public void onTrackingEnd(Entity entity) { -@@ -2236,6 +2237,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2236,6 +2237,13 @@ public class ServerLevel extends Level implements WorldGenLevel { } } // CraftBukkit end -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity(), ServerLevel.this.getWorld()).callEvent(); // Paper - fire while valid ++ // Paper start - fire while valid ++ com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent.RemovalReason removalReason = com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent.RemovalReason.UNKNOWN; ++ Entity.RemovalReason reason = entity.getRemovalReason(); ++ if (reason != null) removalReason = com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent.RemovalReason.values()[reason.ordinal()]; ++ else if (entity.chunkStatus == FullChunkStatus.INACCESSIBLE) removalReason = com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent.RemovalReason.UNLOADED_TO_CHUNK; ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity(), ServerLevel.this.getWorld(), removalReason).callEvent(); ++ // Paper end } public void onSectionChange(Entity entity) { diff --git a/patches/server/0819-check-global-player-list-where-appropriate.patch b/patches/server/0819-check-global-player-list-where-appropriate.patch index 0045fbf607110..cb5914bd3979a 100644 --- a/patches/server/0819-check-global-player-list-where-appropriate.patch +++ b/patches/server/0819-check-global-player-list-where-appropriate.patch @@ -7,10 +7,10 @@ Makes certain entities check all players when searching for a player instead of just checking players in their world. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index e7ed2d1160d412790b23550f9ae967179b7a61f4..711712f144d7b0e26d1248f53bf7ac3963c5df4a 100644 +index 0d5a80327fbe45d5c7eb364d2a1ac9de811d6388..97df66e61249df54d276d8e0ab7fb74421405236 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2385,4 +2385,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2391,4 +2391,12 @@ public class ServerLevel extends Level implements WorldGenLevel { entity.updateDynamicGameEventListener(DynamicGameEventListener::move); } }