From ea14971545abf281c8b604c03a44d30ee92d4182 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Sat, 14 Dec 2024 18:12:30 +0100 Subject: [PATCH] More entity classes --- .../world/entity/EntityType.java.patch | 155 +++++++++++++++ .../world/entity/Leashable.java.patch | 98 ++++++++++ .../world/entity/EntityType.java.patch | 179 ------------------ .../world/entity/Leashable.java.patch | 157 --------------- 4 files changed, 253 insertions(+), 336 deletions(-) create mode 100644 paper-server/patches/sources/net/minecraft/world/entity/EntityType.java.patch create mode 100644 paper-server/patches/sources/net/minecraft/world/entity/Leashable.java.patch delete mode 100644 paper-server/patches/unapplied/net/minecraft/world/entity/EntityType.java.patch delete mode 100644 paper-server/patches/unapplied/net/minecraft/world/entity/Leashable.java.patch diff --git a/paper-server/patches/sources/net/minecraft/world/entity/EntityType.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/EntityType.java.patch new file mode 100644 index 0000000000..df8e7e81b0 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/entity/EntityType.java.patch @@ -0,0 +1,155 @@ +--- a/net/minecraft/world/entity/EntityType.java ++++ b/net/minecraft/world/entity/EntityType.java +@@ -176,6 +_,7 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.CreatureSpawnEvent; + import org.slf4j.Logger; + + public class EntityType implements FeatureElement, EntityTypeTest { +@@ -215,7 +_,7 @@ + .fireImmune() + .sized(6.0F, 0.5F) + .clientTrackingRange(10) +- .updateInterval(Integer.MAX_VALUE) ++ .updateInterval(10) // CraftBukkit - SPIGOT-3729: track area effect clouds + ); + public static final EntityType ARMADILLO = register( + "armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10) +@@ -1132,6 +_,22 @@ + boolean shouldOffsetY, + boolean shouldOffsetYMore + ) { ++ // CraftBukkit start ++ return this.spawn(level, spawnedFrom, player, pos, reason, shouldOffsetY, shouldOffsetYMore, reason == EntitySpawnReason.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs ++ } ++ ++ @Nullable ++ public T spawn( ++ ServerLevel level, ++ @Nullable ItemStack spawnedFrom, ++ @Nullable Player player, ++ BlockPos pos, ++ EntitySpawnReason reason, ++ boolean shouldOffsetY, ++ boolean shouldOffsetYMore, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason createSpawnReason ++ ) { ++ // CraftBukkit end + Consumer consumer; + if (spawnedFrom != null) { + consumer = createDefaultStackConfig(level, spawnedFrom, player); +@@ -1139,7 +_,7 @@ + consumer = entity -> {}; + } + +- return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore); ++ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, createSpawnReason); // CraftBukkit + } + + public static Consumer createDefaultStackConfig(Level level, ItemStack spawnedFrom, @Nullable Player player) { +@@ -1159,19 +_,54 @@ + Consumer consumer, Level level, ItemStack spawnedFrom, @Nullable Player player + ) { + CustomData customData = spawnedFrom.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); +- return !customData.isEmpty() ? consumer.andThen(entity -> updateCustomEntityTag(level, player, entity, customData)) : consumer; ++ // CraftBukkit start - SPIGOT-5665 ++ return !customData.isEmpty() ? consumer.andThen(entity -> { ++ try { ++ updateCustomEntityTag(level, player, entity, customData); ++ } catch (Throwable t) { ++ EntityType.LOGGER.warn("Error loading spawn egg NBT", t); ++ } ++ }) : consumer; ++ // CraftBukkit end + } + + @Nullable + public T spawn(ServerLevel level, BlockPos pos, EntitySpawnReason reason) { +- return this.spawn(level, null, pos, reason, false, false); ++ // CraftBukkit start ++ return this.spawn(level, pos, reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ @Nullable ++ public T spawn(ServerLevel level, BlockPos pos, EntitySpawnReason reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) { ++ return this.spawn(level, null, pos, reason, false, false, creatureSpawnReason); ++ // CraftBukkit End + } + + @Nullable + public T spawn(ServerLevel level, @Nullable Consumer consumer, BlockPos pos, EntitySpawnReason reason, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ @Nullable ++ public T spawn(ServerLevel level, @Nullable Consumer consumer, BlockPos pos, EntitySpawnReason reason, boolean shouldOffsetY, boolean shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason creatureSpawnReason) { ++ // CraftBukkit end ++ // Paper start - PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ io.papermc.paper.util.MCUtil.toLocation(level, pos), ++ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this), ++ creatureSpawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ // Paper end - PreCreatureSpawnEvent + T entity = this.create(level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore); + if (entity != null) { +- level.addFreshEntityWithPassengers(entity); ++ // CraftBukkit start ++ level.addFreshEntityWithPassengers(entity, creatureSpawnReason); ++ if (entity.isRemoved()) { ++ return null; // Don't return an entity when CreatureSpawnEvent is canceled ++ } ++ // CraftBukkit end + if (entity instanceof Mob mob) { + mob.playAmbientSound(); + } +@@ -1225,6 +_,15 @@ + EntityType entityType = customData.parseEntityType(server.registryAccess(), Registries.ENTITY_TYPE); + if (entity.getType() == entityType) { + if (level.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && server.getPlayerList().isOp(player.getGameProfile())) { ++ // Paper start - filter out protected tags ++ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) { ++ customData = customData.update((compound) -> { ++ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : level.paperConfig().entities.spawning.filteredEntityTagNbtPaths) { ++ tag.remove(compound); ++ } ++ }); ++ } ++ // Paper end - filter out protected tags + customData.loadInto(entity); + } + } +@@ -1296,9 +_,19 @@ + } + + public static Optional create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) { ++ // Paper start - Don't fire sync event during generation ++ return create(tag, level, spawnReason, false); ++ } ++ public static Optional create(CompoundTag tag, Level level, EntitySpawnReason spawnReason, boolean generation) { ++ // Paper end - Don't fire sync event during generation + return Util.ifElse( + by(tag).map(entityType -> entityType.create(level, spawnReason)), +- entity -> entity.load(tag), ++ // Paper start - Don't fire sync event during generation ++ entity -> { ++ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation ++ entity.load(tag); ++ }, ++ // Paper end - Don't fire sync event during generation + () -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id")) + ); + } +@@ -1325,7 +_,7 @@ + } + + public static Optional> by(CompoundTag tag) { +- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(tag.getString("id"))); ++ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(tag.getString("id"))); // Paper - Validate ResourceLocation + } + + @Nullable diff --git a/paper-server/patches/sources/net/minecraft/world/entity/Leashable.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/Leashable.java.patch new file mode 100644 index 0000000000..691174efb1 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/entity/Leashable.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/entity/Leashable.java ++++ b/net/minecraft/world/entity/Leashable.java +@@ -56,7 +_,13 @@ + @Nullable + private static Leashable.LeashData readLeashDataInternal(CompoundTag tag) { + if (tag.contains("leash", 10)) { +- return new Leashable.LeashData(Either.left(tag.getCompound("leash").getUUID("UUID"))); ++ // Paper start ++ final CompoundTag leashTag = tag.getCompound("leash"); ++ if (!leashTag.hasUUID("UUID")) { ++ return null; ++ } ++ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID"))); ++ // Paper end + } else { + if (tag.contains("leash", 11)) { + Either either = NbtUtils.readBlockPos(tag, "leash").>map(Either::right).orElse(null); +@@ -72,6 +_,11 @@ + default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) { + if (leashData != null) { + Either either = leashData.delayedLeashInfo; ++ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin ++ if (leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) { ++ return; ++ } ++ // CraftBukkit end + if (leashData.leashHolder instanceof LeashFenceKnotEntity leashFenceKnotEntity) { + either = Either.right(leashFenceKnotEntity.getPos()); + } else if (leashData.leashHolder != null) { +@@ -104,7 +_,9 @@ + } + + if (entity.tickCount > 100) { ++ entity.forceDrops = true; // CraftBukkit + entity.spawnAtLocation(serverLevel, Items.LEAD); ++ entity.forceDrops = false; // CraftBukkit + entity.setLeashData(null); + } + } +@@ -128,7 +_,9 @@ + entity.onLeashRemoved(); + if (entity.level() instanceof ServerLevel serverLevel) { + if (dropItem) { ++ entity.forceDrops = true; // CraftBukkit + entity.spawnAtLocation(serverLevel, Items.LEAD); ++ entity.forceDrops = false; // CraftBukkit + } + + if (broadcastPacket) { +@@ -146,7 +_,15 @@ + + if (leashData != null && leashData.leashHolder != null) { + if (!entity.isAlive() || !leashData.leashHolder.isAlive()) { +- if (level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { ++ // Paper start - Expand EntityUnleashEvent ++ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent( ++ entity.getBukkitEntity(), ++ !entity.isAlive() ? org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.HOLDER_GONE, ++ level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS) && !entity.pluginRemoved ++ ); ++ event.callEvent(); ++ if (event.isDropLeash()) { // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin ++ // Paper end - Expand EntityUnleashEvent + entity.dropLeash(); + } else { + entity.removeLeash(); +@@ -160,7 +_,7 @@ + return; + } + +- if (f > 10.0) { ++ if (f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance + entity.leashTooFarBehaviour(); + } else if (f > 6.0) { + entity.elasticRangeLeashBehaviour(leashHolder, f); +@@ -177,7 +_,21 @@ + } + + default void leashTooFarBehaviour() { +- this.dropLeash(); ++ // CraftBukkit start ++ boolean dropLeash = true; // Paper ++ if (this instanceof Entity entity) { ++ // Paper start - Expand EntityUnleashEvent ++ final org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(entity.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ if (!event.callEvent()) return; ++ dropLeash = event.isDropLeash(); ++ } ++ // CraftBukkit end ++ if (dropLeash) { ++ this.dropLeash(); ++ } else { ++ this.removeLeash(); ++ } ++ // Paper end - Expand EntityUnleashEvent + } + + default void closeRangeLeashBehaviour(Entity entity) { diff --git a/paper-server/patches/unapplied/net/minecraft/world/entity/EntityType.java.patch b/paper-server/patches/unapplied/net/minecraft/world/entity/EntityType.java.patch deleted file mode 100644 index 1ff8d4806a..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/entity/EntityType.java.patch +++ /dev/null @@ -1,179 +0,0 @@ ---- a/net/minecraft/world/entity/EntityType.java -+++ b/net/minecraft/world/entity/EntityType.java -@@ -176,6 +176,7 @@ - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -+import org.bukkit.event.entity.CreatureSpawnEvent; - import org.slf4j.Logger; - - public class EntityType implements FeatureElement, EntityTypeTest { -@@ -191,7 +192,7 @@ - return Items.ACACIA_CHEST_BOAT; - }), MobCategory.MISC).noLootTable().sized(1.375F, 0.5625F).eyeHeight(0.5625F).clientTrackingRange(10)); - public static final EntityType ALLAY = EntityType.register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).eyeHeight(0.36F).ridingOffset(0.04F).clientTrackingRange(8).updateInterval(2)); -- public static final EntityType AREA_EFFECT_CLOUD = EntityType.register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); -+ public static final EntityType AREA_EFFECT_CLOUD = EntityType.register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).noLootTable().fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds - public static final EntityType ARMADILLO = EntityType.register("armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10)); - public static final EntityType ARMOR_STAND = EntityType.register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).eyeHeight(1.7775F).clientTrackingRange(10)); - public static final EntityType ARROW = EntityType.register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).noLootTable().sized(0.5F, 0.5F).eyeHeight(0.13F).clientTrackingRange(4).updateInterval(20)); -@@ -399,7 +400,7 @@ - return ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.withDefaultNamespace(id)); - } - -- private static EntityType register(String id, EntityType.Builder type) { -+ private static EntityType register(String id, EntityType.Builder type) { // CraftBukkit - decompile error - return EntityType.register(EntityType.vanillaEntityId(id), type); - } - -@@ -431,16 +432,23 @@ - - @Nullable - public T spawn(ServerLevel world, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EntitySpawnReason spawnReason, boolean alignPosition, boolean invertY) { -- Consumer consumer; -+ // CraftBukkit start -+ return this.spawn(world, stack, player, pos, spawnReason, alignPosition, invertY, spawnReason == EntitySpawnReason.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs -+ } - -- if (stack != null) { -- consumer = EntityType.createDefaultStackConfig(world, stack, player); -+ @Nullable -+ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // CraftBukkit end -+ Consumer consumer; // CraftBukkit - decompile error -+ -+ if (itemstack != null) { -+ consumer = EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman); - } else { - consumer = (entity) -> { - }; - } - -- return this.spawn(world, consumer, pos, spawnReason, alignPosition, invertY); -+ return this.spawn(worldserver, consumer, blockposition, entityspawnreason, flag, flag1, spawnReason); // CraftBukkit - } - - public static Consumer createDefaultStackConfig(Level world, ItemStack stack, @Nullable Player player) { -@@ -464,21 +472,50 @@ - CustomData customdata = (CustomData) stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); - - return !customdata.isEmpty() ? chained.andThen((entity) -> { -- EntityType.updateCustomEntityTag(world, player, entity, customdata); -+ try { EntityType.updateCustomEntityTag(world, player, entity, customdata); } catch (Throwable t) { EntityType.LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 - }) : chained; - } - - @Nullable - public T spawn(ServerLevel world, BlockPos pos, EntitySpawnReason reason) { -- return this.spawn(world, (Consumer) null, pos, reason, false, false); -+ // CraftBukkit start -+ return this.spawn(world, pos, reason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); - } - - @Nullable -+ public T spawn(ServerLevel worldserver, BlockPos blockposition, EntitySpawnReason entityspawnreason, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ return this.spawn(worldserver, (Consumer) null, blockposition, entityspawnreason, false, false, spawnReason); // CraftBukkit - decompile error -+ // CraftBukkit end -+ } -+ -+ @Nullable - public T spawn(ServerLevel world, @Nullable Consumer afterConsumer, BlockPos pos, EntitySpawnReason reason, boolean alignPosition, boolean invertY) { -- T t0 = this.create(world, afterConsumer, pos, reason, alignPosition, invertY); -+ // CraftBukkit start -+ return this.spawn(world, afterConsumer, pos, reason, alignPosition, invertY, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); -+ } -+ -+ @Nullable -+ public T spawn(ServerLevel worldserver, @Nullable Consumer consumer, BlockPos blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // CraftBukkit end -+ // Paper start - PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ io.papermc.paper.util.MCUtil.toLocation(worldserver, blockposition), -+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this), -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ // Paper end - PreCreatureSpawnEvent -+ T t0 = this.create(worldserver, consumer, blockposition, entityspawnreason, flag, flag1); - - if (t0 != null) { -- world.addFreshEntityWithPassengers(t0); -+ // CraftBukkit start -+ worldserver.addFreshEntityWithPassengers(t0, spawnReason); -+ if (t0.isRemoved()) { -+ return null; // Don't return an entity when CreatureSpawnEvent is canceled -+ } -+ // CraftBukkit end - if (t0 instanceof Mob) { - Mob entityinsentient = (Mob) t0; - -@@ -542,6 +579,15 @@ - - if (entity.getType() == entitytypes) { - if (world.isClientSide || !entity.getType().onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) { -+ // Paper start - filter out protected tags -+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) { -+ nbt = nbt.update((compound) -> { -+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : world.paperConfig().entities.spawning.filteredEntityTagNbtPaths) { -+ tag.remove(compound); -+ } -+ }); -+ } -+ // Paper end - filter out protected tags - nbt.loadInto(entity); - } - } -@@ -613,9 +659,15 @@ - } - - public static Optional create(CompoundTag nbt, Level world, EntitySpawnReason reason) { -+ // Paper start - Don't fire sync event during generation -+ return create(nbt, world, reason, false); -+ } -+ public static Optional create(CompoundTag nbt, Level world, EntitySpawnReason reason, boolean generation) { -+ // Paper end - Don't fire sync event during generation - return Util.ifElse(EntityType.by(nbt).map((entitytypes) -> { - return entitytypes.create(world, reason); - }), (entity) -> { -+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation - entity.load(nbt); - }, () -> { - EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id")); -@@ -638,7 +690,7 @@ - } - - public static Optional> by(CompoundTag nbt) { -- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(nbt.getString("id"))); -+ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(nbt.getString("id"))); // Paper - Validate ResourceLocation - } - - @Nullable -@@ -657,7 +709,7 @@ - } - - return entity; -- }).orElse((Object) null); -+ }).orElse(null); // CraftBukkit - decompile error - } - - public static Stream loadEntitiesRecursive(final List entityNbtList, final Level world, final EntitySpawnReason reason) { -@@ -718,7 +770,7 @@ - - @Nullable - public T tryCast(Entity obj) { -- return obj.getType() == this ? obj : null; -+ return obj.getType() == this ? (T) obj : null; // CraftBukkit - decompile error - } - - @Override -@@ -791,7 +843,7 @@ - this.canSpawnFarFromPlayer = spawnGroup == MobCategory.CREATURE || spawnGroup == MobCategory.MISC; - } - -- public static EntityType.Builder of(EntityType.EntityFactory factory, MobCategory spawnGroup) { -+ public static EntityType.Builder of(EntityType.EntityFactory factory, MobCategory spawnGroup) { // CraftBukkit - decompile error - return new EntityType.Builder<>(factory, spawnGroup); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/entity/Leashable.java.patch b/paper-server/patches/unapplied/net/minecraft/world/entity/Leashable.java.patch deleted file mode 100644 index aa36549d47..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/entity/Leashable.java.patch +++ /dev/null @@ -1,157 +0,0 @@ ---- a/net/minecraft/world/entity/Leashable.java -+++ b/net/minecraft/world/entity/Leashable.java -@@ -15,6 +15,10 @@ - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.ItemLike; - import net.minecraft.world.level.Level; -+// CraftBukkit start -+import org.bukkit.event.entity.EntityUnleashEvent; -+import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+// CraftBukkit end - - public interface Leashable { - -@@ -45,7 +49,7 @@ - - default void setDelayedLeashHolderId(int unresolvedLeashHolderId) { - this.setLeashData(new Leashable.LeashData(unresolvedLeashHolderId)); -- Leashable.dropLeash((Entity) this, false, false); -+ Leashable.dropLeash((Entity & Leashable) this, false, false); // CraftBukkit - decompile error - } - - default void readLeashData(CompoundTag nbt) { -@@ -61,10 +65,16 @@ - @Nullable - private static Leashable.LeashData readLeashDataInternal(CompoundTag nbt) { - if (nbt.contains("leash", 10)) { -- return new Leashable.LeashData(Either.left(nbt.getCompound("leash").getUUID("UUID"))); -+ // Paper start -+ final CompoundTag leashTag = nbt.getCompound("leash"); -+ if (!leashTag.hasUUID("UUID")) { -+ return null; -+ } -+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID"))); -+ // Paper end - } else { - if (nbt.contains("leash", 11)) { -- Either either = (Either) NbtUtils.readBlockPos(nbt, "leash").map(Either::right).orElse((Object) null); -+ Either either = (Either) NbtUtils.readBlockPos(nbt, "leash").map(Either::right).orElse(null); // CraftBukkit - decompile error - - if (either != null) { - return new Leashable.LeashData(either); -@@ -79,6 +89,11 @@ - if (leashData != null) { - Either either = leashData.delayedLeashInfo; - Entity entity = leashData.leashHolder; -+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin -+ if (entity != null && entity.pluginRemoved) { -+ return; -+ } -+ // CraftBukkit end - - if (entity instanceof LeashFenceKnotEntity) { - LeashFenceKnotEntity entityleash = (LeashFenceKnotEntity) entity; -@@ -121,7 +136,9 @@ - } - - if (entity.tickCount > 100) { -+ entity.forceDrops = true; // CraftBukkit - entity.spawnAtLocation(worldserver, (ItemLike) Items.LEAD); -+ entity.forceDrops = false; // CraftBukkit - ((Leashable) entity).setLeashData((Leashable.LeashData) null); - } - } -@@ -130,11 +147,11 @@ - } - - default void dropLeash() { -- Leashable.dropLeash((Entity) this, true, true); -+ Leashable.dropLeash((Entity & Leashable) this, true, true); // CraftBukkit - decompile error - } - - default void removeLeash() { -- Leashable.dropLeash((Entity) this, true, false); -+ Leashable.dropLeash((Entity & Leashable) this, true, false); // CraftBukkit - decompile error - } - - default void onLeashRemoved() {} -@@ -151,7 +168,9 @@ - ServerLevel worldserver = (ServerLevel) world; - - if (dropItem) { -+ entity.forceDrops = true; // CraftBukkit - entity.spawnAtLocation(worldserver, (ItemLike) Items.LEAD); -+ entity.forceDrops = false; // CraftBukkit - } - - if (sendPacket) { -@@ -171,7 +190,11 @@ - - if (leashable_a != null && leashable_a.leashHolder != null) { - if (!entity.isAlive() || !leashable_a.leashHolder.isAlive()) { -- if (world.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { -+ // Paper start - Expand EntityUnleashEvent -+ final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), (!entity.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, world.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS) && !entity.pluginRemoved); -+ event.callEvent(); -+ if (event.isDropLeash()) { // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin -+ // Paper end - Expand EntityUnleashEvent - ((Leashable) entity).dropLeash(); - } else { - ((Leashable) entity).removeLeash(); -@@ -187,7 +210,7 @@ - return; - } - -- if ((double) f > 10.0D) { -+ if ((double) f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance - ((Leashable) entity).leashTooFarBehaviour(); - } else if ((double) f > 6.0D) { - ((Leashable) entity).elasticRangeLeashBehaviour(entity1, f); -@@ -205,13 +228,27 @@ - } - - default void leashTooFarBehaviour() { -- this.dropLeash(); -+ // CraftBukkit start -+ boolean dropLeash = true; // Paper -+ if (this instanceof Entity entity) { -+ // Paper start - Expand EntityUnleashEvent -+ final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ if (!event.callEvent()) return; -+ dropLeash = event.isDropLeash(); -+ } -+ // CraftBukkit end -+ if (dropLeash) { -+ this.dropLeash(); -+ } else { -+ this.removeLeash(); -+ } -+ // Paper end - Expand EntityUnleashEvent - } - - default void closeRangeLeashBehaviour(Entity entity) {} - - default void elasticRangeLeashBehaviour(Entity leashHolder, float distance) { -- Leashable.legacyElasticRangeLeashBehaviour((Entity) this, leashHolder, distance); -+ Leashable.legacyElasticRangeLeashBehaviour((Entity & Leashable) this, leashHolder, distance); // CraftBukkit - decompile error - } - - private static void legacyElasticRangeLeashBehaviour(E entity, Entity leashHolder, float distance) { -@@ -223,7 +260,7 @@ - } - - default void setLeashedTo(Entity leashHolder, boolean sendPacket) { -- this.setLeashedTo((Entity) this, leashHolder, sendPacket); -+ Leashable.setLeashedTo((Entity & Leashable) this, leashHolder, sendPacket); // CraftBukkit - decompile error - } - - private static void setLeashedTo(E entity, Entity leashHolder, boolean sendPacket) { -@@ -254,7 +291,7 @@ - - @Nullable - default Entity getLeashHolder() { -- return Leashable.getLeashHolder((Entity) this); -+ return Leashable.getLeashHolder((Entity & Leashable) this); // CraftBukkit - decompile error - } - - @Nullable