diff --git a/divinemc-server/minecraft-patches/features/0075-Pufferfish-Cache-climbing-check-for-activation.patch b/divinemc-server/minecraft-patches/features/0075-Pufferfish-Cache-climbing-check-for-activation.patch new file mode 100644 index 0000000..5950e66 --- /dev/null +++ b/divinemc-server/minecraft-patches/features/0075-Pufferfish-Cache-climbing-check-for-activation.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Tue, 14 Oct 2025 01:35:26 +0300 +Subject: [PATCH] Pufferfish: Cache climbing check for activation + +This patch is based on the following patch: +"Cache climbing check for activation" +By: Paul Sauve +As part of: Pufferfish (https://github.com/pufferfish-gg/Pufferfish) +Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) + +diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java +index 226088405c019922085285ba5d04d7c131470c69..61bf86a1380060ff118c31b5070b28705a897529 100644 +--- a/io/papermc/paper/entity/activation/ActivationRange.java ++++ b/io/papermc/paper/entity/activation/ActivationRange.java +@@ -238,7 +238,7 @@ public final class ActivationRange { + } + // special cases. + if (entity instanceof final LivingEntity living) { +- if (living.onClimbable() || living.jumping || living.hurtTime > 0 || !living.activeEffects.isEmpty() || living.isFreezing()) { ++ if (living.onClimbableCached() || living.jumping || living.hurtTime > 0 || !living.activeEffects.isEmpty() || living.isFreezing()) { // DivineMC - Pufferfish: Cache climbing check for activation + return 1; + } + if (entity instanceof final Mob mob && mob.getTarget() != null) { +diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java +index 85e287bc66c4e2be6f703c3206fe53bba3d15a6d..fe7232b25458f363dfc43dd1eccab5b95212fc10 100644 +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -2236,6 +2236,20 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + return this.lastClimbablePos; + } + ++ // DivineMC start - Pufferfish: Cache climbing check for activation ++ private boolean cachedOnClimbable = false; ++ private BlockPos lastClimbingPosition = null; ++ ++ public boolean onClimbableCached() { ++ if (!this.blockPosition().equals(this.lastClimbingPosition)) { ++ this.cachedOnClimbable = this.onClimbable(); ++ this.lastClimbingPosition = this.blockPosition(); ++ } ++ ++ return this.cachedOnClimbable; ++ } ++ // DivineMC end - Pufferfish: Cache climbing check for activation ++ + public boolean onClimbable() { + if (this.isSpectator()) { + return false; diff --git a/divinemc-server/minecraft-patches/features/0076-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch b/divinemc-server/minecraft-patches/features/0076-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch new file mode 100644 index 0000000..6807ecf --- /dev/null +++ b/divinemc-server/minecraft-patches/features/0076-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Tue, 14 Oct 2025 01:42:43 +0300 +Subject: [PATCH] Pufferfish: Make EntityCollisionContext a live representation + +This patch is based on the following patch: +"Make EntityCollisionContext a live representation" +By: Paul Sauve +As part of: Airplane (https://github.com/TECHNOVE/Airplane) +Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) + +diff --git a/net/minecraft/world/phys/shapes/EntityCollisionContext.java b/net/minecraft/world/phys/shapes/EntityCollisionContext.java +index a2467db9f096368810e3c1ab8ddabf610fa38379..953c28670cecd6a8ceae1c9c3a490df99acd1a73 100644 +--- a/net/minecraft/world/phys/shapes/EntityCollisionContext.java ++++ b/net/minecraft/world/phys/shapes/EntityCollisionContext.java +@@ -12,40 +12,35 @@ import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; + + public class EntityCollisionContext implements CollisionContext { +- private final boolean descending; +- private final double entityBottom; ++ // DivineMC start - Pufferfish: Make EntityCollisionContext a live representation + private final boolean placement; +- private final ItemStack heldItem; + private final boolean alwaysCollideWithFluid; ++ // DivineMC end - Pufferfish: Make EntityCollisionContext a live representation + @Nullable + private final Entity entity; + + protected EntityCollisionContext( + boolean descending, boolean placement, double entityBottom, ItemStack heldItem, boolean alwaysCollideWithFluid, @Nullable Entity entity + ) { +- this.descending = descending; ++ // DivineMC start - Pufferfish: Make EntityCollisionContext a live representation + this.placement = placement; +- this.entityBottom = entityBottom; +- this.heldItem = heldItem; + this.alwaysCollideWithFluid = alwaysCollideWithFluid; ++ // DivineMC end - Pufferfish: Make EntityCollisionContext a live representation + this.entity = entity; + } + + @Deprecated + protected EntityCollisionContext(Entity entity, boolean canStandOnFluid, boolean placement) { +- this( +- entity.isDescending(), +- placement, +- entity.getY(), +- entity instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY, +- canStandOnFluid, +- entity +- ); ++ // DivineMC start - Pufferfish: Make EntityCollisionContext a live representation ++ this.placement = placement; ++ this.alwaysCollideWithFluid = canStandOnFluid; ++ this.entity = entity; ++ // DivineMC end - Pufferfish: Make EntityCollisionContext a live representation + } + + @Override + public boolean isHoldingItem(Item item) { +- return this.heldItem.is(item); ++ return this.entity instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem().is(item) : ItemStack.EMPTY.is(item); // DivineMC - Pufferfish: Make EntityCollisionContext a live representation + } + + @Override +@@ -65,12 +60,12 @@ public class EntityCollisionContext implements CollisionContext { + + @Override + public boolean isDescending() { +- return this.descending; ++ return this.entity != null && this.entity.isDescending(); // DivineMC - Pufferfish: Make EntityCollisionContext a live representation + } + + @Override + public boolean isAbove(VoxelShape shape, BlockPos pos, boolean canAscend) { +- return this.entityBottom > pos.getY() + shape.max(Direction.Axis.Y) - 1.0E-5F; ++ return (this.entity == null ? -Double.MAX_VALUE : entity.getY()) > (double) pos.getY() + shape.max(Direction.Axis.Y) - (double) 1.0E-5F; // DivineMC - Pufferfish: Make EntityCollisionContext a live representation + } + + @Nullable diff --git a/divinemc-server/minecraft-patches/features/0077-Pufferfish-Better-checking-for-useless-move-packets.patch b/divinemc-server/minecraft-patches/features/0077-Pufferfish-Better-checking-for-useless-move-packets.patch new file mode 100644 index 0000000..749ef6e --- /dev/null +++ b/divinemc-server/minecraft-patches/features/0077-Pufferfish-Better-checking-for-useless-move-packets.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Tue, 14 Oct 2025 01:50:40 +0300 +Subject: [PATCH] Pufferfish: Better checking for useless move packets + +This patch is based on the following patch: +"Better checking for useless move packets" +By: Paul Sauve +As part of: Airplane (https://github.com/TECHNOVE/Airplane) +Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) + +diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java +index cfa2c3aa357a0dbb7edf7f0c8cebea5ed2f31cbc..d8ac41bacbb2303eacac6d96dd829865346f5b3b 100644 +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -181,18 +181,24 @@ public class ServerEntity { + packet = ClientboundEntityPositionSyncPacket.of(this.entity); + flag3 = true; + flag4 = true; +- } else if ((!flag2 || !flag) && !(this.entity instanceof AbstractArrow)) { +- if (flag2) { +- packet = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short)l, (short)l1, (short)l2, this.entity.onGround()); +- flag3 = true; +- } else if (flag) { +- packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), b, b1, this.entity.onGround()); +- flag4 = true; +- } + } else { +- packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)l, (short)l1, (short)l2, b, b1, this.entity.onGround()); +- flag3 = true; +- flag4 = true; ++ // DivineMC start - Pufferfish: Better checking for useless move packets ++ if (flag2 || flag || this.entity instanceof AbstractArrow) { ++ if ((!flag2 || !flag) && !(this.entity instanceof AbstractArrow)) { ++ if (flag2) { ++ packet = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) l, (short) l1, (short) l2, this.entity.onGround()); ++ flag3 = true; ++ } else if (flag) { ++ packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), b, b1, this.entity.onGround()); ++ flag4 = true; ++ } ++ } else { ++ packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short) l, (short) l1, (short) l2, b, b1, this.entity.onGround()); ++ flag3 = true; ++ flag4 = true; ++ } ++ } ++ // DivineMC end - Pufferfish: Better checking for useless move packets + } + + if (this.entity.hasImpulse || this.trackDelta || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) { diff --git a/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch b/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch index e079576..b4268e5 100644 --- a/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch +++ b/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch @@ -1,5 +1,13 @@ --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java +@@ -756,6 +_,7 @@ + + super.remove(reason, eventCause); // CraftBukkit + this.brain.clearMemories(); ++ this.combatTracker.resetCombatState(); // DivineMC - Fix MC-298464 (by HaHaWTH) + } + + @Override @@ -1431,7 +_,7 @@ player.setRealHealth(health); } diff --git a/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java.patch b/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java.patch new file mode 100644 index 0000000..581e3b5 --- /dev/null +++ b/divinemc-server/minecraft-patches/sources/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -119,6 +_,7 @@ + for (int i4 = 0; i4 <= i3; i4 = i4 > 0 ? -i4 : 1 - i4) { + for (int i5 = i4 < i3 && i4 > -i3 ? i3 : 0; i5 <= i3; i5 = i5 > 0 ? -i5 : 1 - i5) { + mutableBlockPos.setWithOffset(blockPos, i4, i2 - 1, i5); ++ if (!this.mob.level().hasChunkAt(mutableBlockPos)) continue; // DivineMC - Pufferfish: Block goal does not load chunks + if (this.mob.isWithinHome(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) { + this.blockPos = mutableBlockPos; + this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper