From dfd8a7ad14f436ea9c4704a758305e7145923c2d Mon Sep 17 00:00:00 2001 From: MXU Date: Sun, 29 Jun 2025 16:00:59 +0100 Subject: [PATCH 1/7] Fix phantom going at high speed when ridden (#1680) --- .../minecraft-patches/features/0001-Ridables.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index c0b8f4757..6184b7034 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -42,7 +42,7 @@ index 83eff33884bffddfafc85eeb4a2900104a396e2e..3c7159d0981c948e71a5612ba4083acc @Override public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 63ef4690ff76df961fcc51dabd0f4f3d7de09fe9..7adb3d1f75896f1e31747e3356b124948a1c77c0 100644 +index f292626a6ab2ae3f71f76aebdd2b4cf576183331..cb83141c70f28569d91df6553ae368bfacb9a0e2 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -861,6 +861,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -3813,7 +3813,7 @@ index 889c31cc9257fbbd5df8325ccee9ce39b026ec4b..4a1299d6cee2807522de0c2d0d4745c5 @Override diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index 2abb55d84507fd29817760cb0068dd083f7f1c37..855ec37a7e4110e37823ecf62f67f5cb3714f4bf 100644 +index 2abb55d84507fd29817760cb0068dd083f7f1c37..3b343c29b86292f5965a84bd180a7866e76bcac1 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java @@ -62,6 +62,52 @@ public class Phantom extends Mob implements Enemy { @@ -3907,7 +3907,7 @@ index 2abb55d84507fd29817760cb0068dd083f7f1c37..855ec37a7e4110e37823ecf62f67f5cb + this.setSpeed(speed); + Vec3 mot = this.getDeltaMovement(); + this.move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed)); -+ this.setDeltaMovement(mot.scale(0.9D)); ++ this.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO); + } + // Purpur end - Ridables } From 04a9045d98ac48d82941210d0391d0f2a05ef10b Mon Sep 17 00:00:00 2001 From: MXU Date: Mon, 30 Jun 2025 03:05:11 +0100 Subject: [PATCH 2/7] Fix phantom high speed by modifying the speed: Part 2 (#1682) Co-authored-by: granny --- .../features/0001-Ridables.patch | 37 ++++++++++++++++--- .../0008-Implement-elytra-settings.patch | 6 +-- ...018-API-for-any-mob-to-burn-daylight.patch | 4 +- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index 6184b7034..83b3841d2 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -177,7 +177,7 @@ index f0c452ddc4b299a930de261722cc41a89aa78eeb..8e8ddab59de508c84c4182e105a11554 protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..d272f5e789cb6c03ede0bece14fc3fe976a02ff3 100644 +index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..388d2e87696d9d3ec265355ec3602a03aa3151bb 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -238,9 +238,9 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -210,7 +210,34 @@ index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..d272f5e789cb6c03ede0bece14fc3fe9 @Override protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { -@@ -3629,8 +3630,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3026,6 +3027,26 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); + } else { ++ // Purpur start - Ridables ++ if (this.getRider() != null && this.isControllable()) { ++ float f = 0.91F; ++ if (this.onGround()) { ++ f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F; ++ } ++ ++ float f1 = 0.16277137F / (f * f * f); ++ f = 0.91F; ++ if (this.onGround()) { ++ f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F; ++ } ++ ++ this.moveRelative(this.onGround() ? 0.1F * f1 : 0.02F, relative); ++ this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(f)); ++ return; ++ } ++ // Purpur end - Ridables ++ + this.moveRelative(amount, relative); + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.91F)); +@@ -3629,8 +3650,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.pushEntities(); profilerFiller.pop(); // Paper start - Add EntityMoveEvent @@ -223,7 +250,7 @@ index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..d272f5e789cb6c03ede0bece14fc3fe9 Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); -@@ -3640,6 +3643,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3640,6 +3663,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); } } @@ -3813,7 +3840,7 @@ index 889c31cc9257fbbd5df8325ccee9ce39b026ec4b..4a1299d6cee2807522de0c2d0d4745c5 @Override diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index 2abb55d84507fd29817760cb0068dd083f7f1c37..3b343c29b86292f5965a84bd180a7866e76bcac1 100644 +index 2abb55d84507fd29817760cb0068dd083f7f1c37..855ec37a7e4110e37823ecf62f67f5cb3714f4bf 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java @@ -62,6 +62,52 @@ public class Phantom extends Mob implements Enemy { @@ -3907,7 +3934,7 @@ index 2abb55d84507fd29817760cb0068dd083f7f1c37..3b343c29b86292f5965a84bd180a7866 + this.setSpeed(speed); + Vec3 mot = this.getDeltaMovement(); + this.move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed)); -+ this.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO); ++ this.setDeltaMovement(mot.scale(0.9D)); + } + // Purpur end - Ridables } diff --git a/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch b/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch index 436e1a581..d278d0f03 100644 --- a/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch +++ b/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement elytra settings diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index ae0c2f41c522656bde37d4f31699ee6172b5a79d..4f149e5e17d2d2f2964e2f6626e20f52121e72d9 100644 +index bc26752293f8edd7d40bfc161b235c2a6eaf2c29..de3bb90db932cc452a81b0a2b267f00a51f0e47b 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3699,7 +3699,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3719,7 +3719,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin .filter(equipmentSlot1 -> canGlideUsing(this.getItemBySlot(equipmentSlot1), equipmentSlot1)) .toList(); EquipmentSlot equipmentSlot = Util.getRandom(list, this.random); @@ -51,7 +51,7 @@ index 83cfe63b0245f79d0873477ab3aae75f690ecb68..f32370217735b5e9556a0df7652682d8 itemInHand.shrink(1); // Moved up from below } else { diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 52aaa325476af53eca97fc14ad5f82fbb9193c80..d512ee6b1039b80b908816b625ef1aa9cd50461c 100644 +index 7041e93158ffab707f14ff6e48c3977bebf275a9..b95acf4c688a9113a34e9be2639536245c66c83e 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java @@ -700,6 +700,14 @@ public final class ItemStack implements DataComponentHolder { diff --git a/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch b/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch index 82914d436..41688c08f 100644 --- a/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch +++ b/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch @@ -35,7 +35,7 @@ index 34e0fbef06b0c7aededf27fe9dc64f3f6f33e3ae..ce3e5ec505ac37c820436bcf7c7d6452 this.type = entityType; this.level = level; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 70808e9f092953a3edf7001b318c91228844f73c..98096df5f83196a6fee8d26637a1816807952f3f 100644 +index 78875973599112f8b5602bec78ce075aac0df94c..c935fe512480fe927d72570674579a5685bde366 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -286,6 +286,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -62,7 +62,7 @@ index 70808e9f092953a3edf7001b318c91228844f73c..98096df5f83196a6fee8d26637a18168 this.lastHurtByPlayer = EntityReference.read(input, "last_hurt_by_player"); this.lastHurtByPlayerMemoryTime = input.getIntOr("last_hurt_by_player_memory_time", 0); this.lastHurtByMob = EntityReference.read(input, "last_hurt_by_mob"); -@@ -3666,6 +3669,32 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3686,6 +3689,32 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) { this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F); } From 175bb181af6e564c5843e84f177b22830240010d Mon Sep 17 00:00:00 2001 From: granny Date: Sun, 29 Jun 2025 23:28:54 -0700 Subject: [PATCH 3/7] [ci skip] micro opt when applying block friction on flying ridable mobs --- .../features/0001-Ridables.patch | 23 ++++++++----------- .../0008-Implement-elytra-settings.patch | 4 ++-- ...018-API-for-any-mob-to-burn-daylight.patch | 4 ++-- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index 83b3841d2..b2f08a475 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -177,7 +177,7 @@ index f0c452ddc4b299a930de261722cc41a89aa78eeb..8e8ddab59de508c84c4182e105a11554 protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..388d2e87696d9d3ec265355ec3602a03aa3151bb 100644 +index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..4f67ae2491d053d3d7261440c029da512dc1002b 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -238,9 +238,9 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -210,26 +210,21 @@ index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..388d2e87696d9d3ec265355ec3602a03 @Override protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { -@@ -3026,6 +3027,26 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3026,6 +3027,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.move(MoverType.SELF, this.getDeltaMovement()); this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); } else { + // Purpur start - Ridables + if (this.getRider() != null && this.isControllable()) { -+ float f = 0.91F; ++ float friction = 0.91F; + if (this.onGround()) { -+ f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F; ++ friction = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F; + } + -+ float f1 = 0.16277137F / (f * f * f); -+ f = 0.91F; -+ if (this.onGround()) { -+ f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.91F; -+ } -+ -+ this.moveRelative(this.onGround() ? 0.1F * f1 : 0.02F, relative); ++ float frictionCompensation = 0.16277137F / (friction * friction * friction); ++ this.moveRelative(this.onGround() ? 0.1F * frictionCompensation : 0.02F, relative); + this.move(MoverType.SELF, this.getDeltaMovement()); -+ this.setDeltaMovement(this.getDeltaMovement().scale(f)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(friction)); + return; + } + // Purpur end - Ridables @@ -237,7 +232,7 @@ index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..388d2e87696d9d3ec265355ec3602a03 this.moveRelative(amount, relative); this.move(MoverType.SELF, this.getDeltaMovement()); this.setDeltaMovement(this.getDeltaMovement().scale(0.91F)); -@@ -3629,8 +3650,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3629,8 +3645,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.pushEntities(); profilerFiller.pop(); // Paper start - Add EntityMoveEvent @@ -250,7 +245,7 @@ index 96e47e6145a4cce8c154a05f9b155c1ba74bfa6a..388d2e87696d9d3ec265355ec3602a03 Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); -@@ -3640,6 +3663,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3640,6 +3658,21 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.absSnapTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); } } diff --git a/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch b/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch index d278d0f03..2cbb5abfe 100644 --- a/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch +++ b/purpur-server/minecraft-patches/features/0008-Implement-elytra-settings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement elytra settings diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index bc26752293f8edd7d40bfc161b235c2a6eaf2c29..de3bb90db932cc452a81b0a2b267f00a51f0e47b 100644 +index 7d0a8048cea101be9747a2b89713288f53ce6637..49089d7235857e2d788002c1bc6d0fe5979e7ec0 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3719,7 +3719,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3714,7 +3714,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin .filter(equipmentSlot1 -> canGlideUsing(this.getItemBySlot(equipmentSlot1), equipmentSlot1)) .toList(); EquipmentSlot equipmentSlot = Util.getRandom(list, this.random); diff --git a/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch b/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch index 41688c08f..f820794fb 100644 --- a/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch +++ b/purpur-server/minecraft-patches/features/0018-API-for-any-mob-to-burn-daylight.patch @@ -35,7 +35,7 @@ index 34e0fbef06b0c7aededf27fe9dc64f3f6f33e3ae..ce3e5ec505ac37c820436bcf7c7d6452 this.type = entityType; this.level = level; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 78875973599112f8b5602bec78ce075aac0df94c..c935fe512480fe927d72570674579a5685bde366 100644 +index eeb8e244f57a5c36b99c13dd20cc635694d83f34..70fa06167ad67bd201d37b1666960c9b69743c76 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -286,6 +286,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -62,7 +62,7 @@ index 78875973599112f8b5602bec78ce075aac0df94c..c935fe512480fe927d72570674579a56 this.lastHurtByPlayer = EntityReference.read(input, "last_hurt_by_player"); this.lastHurtByPlayerMemoryTime = input.getIntOr("last_hurt_by_player_memory_time", 0); this.lastHurtByMob = EntityReference.read(input, "last_hurt_by_mob"); -@@ -3686,6 +3689,32 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3681,6 +3684,32 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) { this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F); } From d0b705e49c19d6073e62919ed38c07b8a2c9a34b Mon Sep 17 00:00:00 2001 From: granny Date: Sun, 29 Jun 2025 23:38:10 -0700 Subject: [PATCH 4/7] Updated Upstream (Paper) Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@57c202e0 Allow adventure nbt codec to parse all tags --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 17b7957db..a513a92b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group = org.purpurmc.purpur version = 1.21.6-R0.1-SNAPSHOT mcVersion = 1.21.6 -paperCommit = bd79e20c6627faadad184bd2e6dbea31b35d32d0 +paperCommit = 57c202e01516b653aea9c7e050eaded1448863e5 org.gradle.configuration-cache = true org.gradle.caching = true From 3658291d2999f9946551066af952b929eaca4d2a Mon Sep 17 00:00:00 2001 From: MXU Date: Mon, 30 Jun 2025 18:11:04 +0100 Subject: [PATCH 5/7] Fix llama not moving when ridden, Fixes #1507 (#1684) Co-authored-by: granny --- .../features/0001-Ridables.patch | 17 ++++++++++++----- ...02-Configurable-entity-base-attributes.patch | 8 ++++---- ...ake-entity-breeding-times-configurable.patch | 6 +++--- ...-Toggle-for-water-sensitive-mob-damage.patch | 6 +++--- .../0020-Mobs-always-drop-experience.patch | 6 +++--- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index b2f08a475..dde8fdd6d 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -2384,10 +2384,10 @@ index 2a1d720557c0bd4895a32723e34512c0a557e4f2..f1cb2e315e1d86f9fcd87db11d3ee7a8 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 5e3382351b1b5728750534f64babc85c4da3ac54..da6450f7573ca9797577d5afae2bb1365d112177 100644 +index 5e3382351b1b5728750534f64babc85c4da3ac54..f7c6b2188ed3801417c7497dbc36749def3e5057 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -84,7 +84,51 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -84,7 +84,58 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { super(entityType, level); this.getNavigation().setRequiredPathLength(40.0F); this.maxDomestication = 30; // Paper - Missing entity API; configure max temper instead of a hardcoded value @@ -2433,13 +2433,20 @@ index 5e3382351b1b5728750534f64babc85c4da3ac54..da6450f7573ca9797577d5afae2bb136 + + @Override + public boolean isSaddled() { -+ return super.isSaddled() || (isTamed()); ++ return super.isWearingBodyArmor() || this.isTamed(); ++ } ++ ++ @Nullable ++ @Override ++ public LivingEntity getControllingPassenger() { ++ Entity firstPassenger = this.getFirstPassenger(); ++ return !this.isNoAi() && firstPassenger instanceof net.minecraft.world.entity.Mob mob && firstPassenger.canControlVehicle() ? mob : null; } + // Purpur end - Ridables public boolean isTraderLlama() { return false; -@@ -127,6 +171,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -127,6 +178,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); @@ -2447,7 +2454,7 @@ index 5e3382351b1b5728750534f64babc85c4da3ac54..da6450f7573ca9797577d5afae2bb136 this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2)); this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.1F)); this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25, 40, 20.0F)); -@@ -137,6 +182,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -137,6 +189,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7)); this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 6.0F)); this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); diff --git a/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch b/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch index e4676be04..cc1c04af7 100644 --- a/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch +++ b/purpur-server/minecraft-patches/features/0002-Configurable-entity-base-attributes.patch @@ -23,7 +23,7 @@ index 8e8ddab59de508c84c4182e105a11554387dcce0..1896f91e10a5e17332836d5354813a18 protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index d272f5e789cb6c03ede0bece14fc3fe976a02ff3..41b6b18130d89b3c3c31bbb2d184fa735a8cd99c 100644 +index 4f67ae2491d053d3d7261440c029da512dc1002b..7d0a8048cea101be9747a2b89713288f53ce6637 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -291,6 +291,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -712,10 +712,10 @@ index f1cb2e315e1d86f9fcd87db11d3ee7a81cfe12f6..53c0eac62018a0d88e30b8c13de94216 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index da6450f7573ca9797577d5afae2bb1365d112177..6fe6507edbf4c3c2795b8fe000d230d5fe6a2486 100644 +index f7c6b2188ed3801417c7497dbc36749def3e5057..3bc0f670a84216e5a62d1e3a9fb26bd85a0cd79a 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -130,6 +130,23 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -137,6 +137,23 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { } // Purpur end - Ridables @@ -1222,7 +1222,7 @@ index 0335e85f196363c06597812149e9a93cba57fa9e..5b0794bd87423715cada1f860b4141fd EntityType entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random ) { diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java -index 304a1ce41071e5597859b1235fa014f966ff5cfb..c45786fa6b9c7834b73fa0266ad4f37dfdfb8937 100644 +index bb2649001f0b31676a51378745818d5c5b15c443..6311261d71aa062ba497a73cd22cb5dbdf2a4cdb 100644 --- a/net/minecraft/world/entity/monster/Illusioner.java +++ b/net/minecraft/world/entity/monster/Illusioner.java @@ -74,6 +74,16 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { diff --git a/purpur-server/minecraft-patches/features/0012-Make-entity-breeding-times-configurable.patch b/purpur-server/minecraft-patches/features/0012-Make-entity-breeding-times-configurable.patch index ba379b430..90d9febea 100644 --- a/purpur-server/minecraft-patches/features/0012-Make-entity-breeding-times-configurable.patch +++ b/purpur-server/minecraft-patches/features/0012-Make-entity-breeding-times-configurable.patch @@ -150,7 +150,7 @@ index 869a0154c81593db8933f9daa6a7d3a9d02facc5..37b6bfa8dc1fd4ed0006f6531d2056bc this.partner.resetLove(); serverLevel.addFreshEntityWithPassengers(fox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason diff --git a/net/minecraft/world/entity/animal/HappyGhast.java b/net/minecraft/world/entity/animal/HappyGhast.java -index 801fc7e1a6ec56a6cde5b787daebe3c8c008cc93..50a64a312cb6af0f39117993553b66de1f095150 100644 +index 6c80c12313147fb022d1bb0c8694fcf85174ae7c..136b918f053cacbc4fa60b0ed434619c5e07adf5 100644 --- a/net/minecraft/world/entity/animal/HappyGhast.java +++ b/net/minecraft/world/entity/animal/HappyGhast.java @@ -140,6 +140,13 @@ public class HappyGhast extends Animal { @@ -451,10 +451,10 @@ index 53c0eac62018a0d88e30b8c13de94216ff829cd8..3678c767818abb9e4180c2ade378ca09 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 6fe6507edbf4c3c2795b8fe000d230d5fe6a2486..9cfc31b9acca44c56b78ba6d935bcb6c1d6c5697 100644 +index 3bc0f670a84216e5a62d1e3a9fb26bd85a0cd79a..45d0977b5016a8728b11ec13c528b160598c80e2 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -147,6 +147,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -154,6 +154,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { } // Purpur end - Configurable entity base attributes diff --git a/purpur-server/minecraft-patches/features/0017-Toggle-for-water-sensitive-mob-damage.patch b/purpur-server/minecraft-patches/features/0017-Toggle-for-water-sensitive-mob-damage.patch index 00d5670f6..053c5c78e 100644 --- a/purpur-server/minecraft-patches/features/0017-Toggle-for-water-sensitive-mob-damage.patch +++ b/purpur-server/minecraft-patches/features/0017-Toggle-for-water-sensitive-mob-damage.patch @@ -513,10 +513,10 @@ index 3678c767818abb9e4180c2ade378ca09761ad784..2928159447a87ea8cc945e73e2e81ad1 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 9cfc31b9acca44c56b78ba6d935bcb6c1d6c5697..017482c8818a854b23237e27e3304498d800569d 100644 +index 45d0977b5016a8728b11ec13c528b160598c80e2..ea25c48cb60aff6fbc82a364789beff92b054a88 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -154,6 +154,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -161,6 +161,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { } // Purpur end - Make entity breeding times configurable @@ -899,7 +899,7 @@ index 75cb1db5584c04e442583ab2f50a26132ed48bfb..9baec22561093d64157d93449e84c23b EntityType entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random ) { diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java -index c45786fa6b9c7834b73fa0266ad4f37dfdfb8937..b2e59058c71eb0b05670be8dcddfff073ae2d0db 100644 +index 6311261d71aa062ba497a73cd22cb5dbdf2a4cdb..4b68c0e999c37b3a3b62b522e2fcc805d2483943 100644 --- a/net/minecraft/world/entity/monster/Illusioner.java +++ b/net/minecraft/world/entity/monster/Illusioner.java @@ -84,6 +84,13 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { diff --git a/purpur-server/minecraft-patches/features/0020-Mobs-always-drop-experience.patch b/purpur-server/minecraft-patches/features/0020-Mobs-always-drop-experience.patch index cb13ab943..6a84db38f 100644 --- a/purpur-server/minecraft-patches/features/0020-Mobs-always-drop-experience.patch +++ b/purpur-server/minecraft-patches/features/0020-Mobs-always-drop-experience.patch @@ -509,10 +509,10 @@ index 2928159447a87ea8cc945e73e2e81ad1dbe13680..f1080a40f759b30b921b88b4f6edd35f protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(generateMaxHealth(random::nextInt)); diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java -index 017482c8818a854b23237e27e3304498d800569d..1bef43f42aee02a0a00556318607072ce9814860 100644 +index ea25c48cb60aff6fbc82a364789beff92b054a88..455a84ffa16152137409777e1fddbab5a21bd57d 100644 --- a/net/minecraft/world/entity/animal/horse/Llama.java +++ b/net/minecraft/world/entity/animal/horse/Llama.java -@@ -161,6 +161,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { +@@ -168,6 +168,13 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { } // Purpur end - Toggle for water sensitive mob damage @@ -869,7 +869,7 @@ index 3f331215ef49c52fa3a53bcf744159d2221111f5..a4ce65911a5d778f60bcedb3acd9fe59 EntityType entityType, ServerLevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random ) { diff --git a/net/minecraft/world/entity/monster/Illusioner.java b/net/minecraft/world/entity/monster/Illusioner.java -index b2e59058c71eb0b05670be8dcddfff073ae2d0db..93eaafe260312f26840a2afee8375b8a95d97ba2 100644 +index 4b68c0e999c37b3a3b62b522e2fcc805d2483943..2ea8c8480dcc15eb5b4bc9686554ec912ef1f3f4 100644 --- a/net/minecraft/world/entity/monster/Illusioner.java +++ b/net/minecraft/world/entity/monster/Illusioner.java @@ -91,6 +91,13 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { From 051566db7f9df74c78c5ee9f9641033ffc79a5a0 Mon Sep 17 00:00:00 2001 From: granny Date: Mon, 30 Jun 2025 10:47:48 -0700 Subject: [PATCH 6/7] check for purpur.debug.f3n on new serverbound change gamemode packet, closes #1683 --- .../network/ServerGamePacketListenerImpl.java.patch | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index f3c9a2115..093d93a7b 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -222,3 +222,12 @@ packet.dispatch( new ServerboundInteractPacket.Handler() { private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction entityInteraction, PlayerInteractEntityEvent event) { // CraftBukkit +@@ -3538,7 +_,7 @@ + @Override + public void handleChangeGameMode(ServerboundChangeGameModePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); +- if (!this.player.hasPermissions(2)) { ++ if (!this.player.hasPermissions(2) && !player.getBukkitEntity().hasPermission("purpur.debug.f3n")) { // Purpur - Add permission for F3+N debug + LOGGER.warn( + "Player {} tried to change game mode to {} without required permissions", + this.player.getGameProfile().getName(), From a112b6aca718e4500a6d48ca9d7158faf0f4adf9 Mon Sep 17 00:00:00 2001 From: granny Date: Mon, 30 Jun 2025 11:58:16 -0700 Subject: [PATCH 7/7] Final 1.21.6 Upstream (Paper) Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@4d854e66 Disable MC-163962 fix by default --- gradle.properties | 2 +- .../minecraft/world/item/trading/MerchantOffer.java.patch | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index a513a92b4..6fed0df2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group = org.purpurmc.purpur version = 1.21.6-R0.1-SNAPSHOT mcVersion = 1.21.6 -paperCommit = 57c202e01516b653aea9c7e050eaded1448863e5 +paperCommit = 4d854e66b80dad9898d71a0f0b1f83cd39b97119 org.gradle.configuration-cache = true org.gradle.caching = true diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/trading/MerchantOffer.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/trading/MerchantOffer.java.patch index 6a3b114a8..d173c48d1 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/trading/MerchantOffer.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/trading/MerchantOffer.java.patch @@ -1,16 +1,17 @@ --- a/net/minecraft/world/item/trading/MerchantOffer.java +++ b/net/minecraft/world/item/trading/MerchantOffer.java -@@ -143,7 +_,12 @@ +@@ -143,8 +_,13 @@ } public void updateDemand() { -- this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - Fix MC-163962 + // Purpur start - Configurable minimum demand for trades + this.updateDemand(0); + } + public void updateDemand(int minimumDemand) { -+ this.demand = Math.max(minimumDemand, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - Fix MC-163962 + // Purpur end - Configurable minimum demand for trades + this.demand = this.demand + this.uses - (this.maxUses - this.uses); +- if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.preventNegativeVillagerDemand) this.demand = Math.max(0, this.demand); // Paper - Fix MC-163962 ++ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.preventNegativeVillagerDemand) this.demand = Math.max(minimumDemand, this.demand); // Paper - Fix MC-163962 // Purpur - Configurable minimum demand for trades } public ItemStack assemble() {