diff --git a/leaf-archived-patches/work/server/0110-Cache-ItemStack-max-stack-size.patch b/leaf-archived-patches/removed/hardfork/server/0110-Cache-ItemStack-max-stack-size.patch similarity index 97% rename from leaf-archived-patches/work/server/0110-Cache-ItemStack-max-stack-size.patch rename to leaf-archived-patches/removed/hardfork/server/0110-Cache-ItemStack-max-stack-size.patch index 55d9d72f..093e5879 100644 --- a/leaf-archived-patches/work/server/0110-Cache-ItemStack-max-stack-size.patch +++ b/leaf-archived-patches/removed/hardfork/server/0110-Cache-ItemStack-max-stack-size.patch @@ -3,7 +3,7 @@ From: Taiyou06 Date: Fri, 7 Feb 2025 21:41:51 +0100 Subject: [PATCH] Cache ItemStack max stack size -TODO: check this, fix get max stack size +Abandoned plan, maybe research deeper in this part in the future, maybe not diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java index fd7c1e800cbd4919a1a47f6c468c8776535bd028..fdd7e89bacc98e23f067ba17d0bd93ee84a388cb 100644 diff --git a/leaf-archived-patches/work/server/0042-Optimize-Minecart-collisions.patch b/leaf-archived-patches/work/server/0042-Optimize-Minecart-collisions.patch index 6a9bc4c4..d583555e 100644 --- a/leaf-archived-patches/work/server/0042-Optimize-Minecart-collisions.patch +++ b/leaf-archived-patches/work/server/0042-Optimize-Minecart-collisions.patch @@ -3,6 +3,8 @@ From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Sat, 6 Apr 2024 22:57:41 -0400 Subject: [PATCH] Optimize Minecart collisions +TODO: need to re-design + Co-authored-by: MrHua269 Skip tick collisions to to prevent lag causing by massive stacked Minecart diff --git a/leaf-server/minecraft-patches/features/0191-aaa.patch b/leaf-server/minecraft-patches/features/0191-aaa.patch new file mode 100644 index 00000000..7431d1c6 --- /dev/null +++ b/leaf-server/minecraft-patches/features/0191-aaa.patch @@ -0,0 +1,285 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Fri, 6 Jun 2025 19:05:40 +0800 +Subject: [PATCH] aaa + + +diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java +index 8e693028ef9e512094dbb97d6088d95ead03487d..dc5900903589bc806b89df45ea4de361eed6a9ca 100644 +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -1948,7 +1948,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + this.awardStat(Stats.SWIM_ONE_CM, rounded); + this.causeFoodExhaustion(this.level().spigotConfig.swimMultiplier * (float) rounded * 0.01F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent // Spigot + } +- } else if (this.isEyeInFluid(FluidTags.WATER)) { ++ } else if (this.isEyeInFluid(1)) { + int rounded = Math.round((float)Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); + if (rounded > 0) { + this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, rounded); +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 9f581d5bdc3f658694bbd8c80abbce4e27e568d3..2c0417d14d276864c1a74f5264751105dde2f34f 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -17,6 +17,7 @@ import it.unimi.dsi.fastutil.objects.ReferenceArraySet; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.HashSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Objects; +@@ -265,6 +266,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + private static final int FLUID_WATER = 1; // Leaf - Optimize isEyeInFluid + private static final int FLUID_LAVA = 2; // Leaf - Optimize isEyeInFluid + private int fluidCache = 0; // Leaf - Optimize isEyeInFluid ++ private int fluidOnEyesCache = 0; + public int invulnerableTime; + protected boolean firstTick = true; + protected final SynchedEntityData entityData; +@@ -1985,8 +1987,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + + private void updateFluidOnEyes() { +- this.wasEyeInWater = this.isEyeInFluid(FluidTags.WATER); +- if (org.dreeam.leaf.config.modules.opt.EyeFluidCache.enabled) fluidCache = 0; else this.fluidOnEyes.clear(); // Leaf - Optimize isEyeInFluid ++ this.wasEyeInWater = this.isEyeInFluid(1); ++ this.fluidOnEyesCache = 0; + + double eyeY = this.getEyeY(); + if (!( +@@ -1999,18 +2001,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + FluidState fluidState = this.level().getFluidState(blockPos); + double d = blockPos.getY() + fluidState.getHeight(this.level(), blockPos); + if (d > eyeY) { +- // Leaf start - Optimize isEyeInFluid +- if (org.dreeam.leaf.config.modules.opt.EyeFluidCache.enabled) { +- if (fluidState.is(FluidTags.WATER)) { +- setFluidStatus(FluidTags.WATER, true); +- } +- if (fluidState.is(FluidTags.LAVA)) { +- setFluidStatus(FluidTags.LAVA, true); +- } ++ TagKey[] tagArray = fluidState.getTagsArray(); ++ if (tagArray.length == 0) { ++ this.fluidOnEyesCache = 0; + } else { +- this.fluidOnEyes.addAll(fluidState.getTagsAsSet()); // Leaf - Remove stream in updateFluidOnEyes ++ for (int i = 0; i < tagArray.length; i++) { ++ TagKey tag = tagArray[i]; ++ if (tag == FluidTags.WATER || tag == FluidTags.LAVA) { ++ this.fluidOnEyesCache++; ++ } ++ } + } +- // Leaf end - Optimize isEyeInFluid + } + } + } +@@ -2108,6 +2109,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + fluidCache = isInFluid ? (fluidCache | bit) : (fluidCache & ~bit); + } ++ ++ public boolean isEyeInFluid(int fluidBit) { ++ return fluidOnEyesCache >= fluidBit; ++ } + // Leaf end - Optimize isEyeInFluid + + public boolean isInLava() { +@@ -4442,7 +4447,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + @Nullable + public Entity getFirstPassenger() { +- return this.passengers.isEmpty() ? null : this.passengers.get(0); ++ return this.passengers.isEmpty() ? null : this.passengers.getFirst(); + } + + public boolean hasPassenger(Entity entity) { +diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java +index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..bd2c7fae6858ba446760f7e18390090434b660e0 100644 +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -133,7 +133,7 @@ public class ExperienceOrb extends Entity { + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +- if (this.isEyeInFluid(FluidTags.WATER)) { ++ if (this.isEyeInFluid(1)) { + this.setUnderwaterMovement(); + } else { + this.applyGravity(); +diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java +index 156d0c14eedf2f79e4276cc4065e19a43699b965..6072d713d08ea3172eee039b35d1c122813cffa3 100644 +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -483,7 +483,7 @@ public abstract class LivingEntity extends Entity implements Attackable, net.caf + } + } + +- if (this.isEyeInFluid(FluidTags.WATER) ++ if (this.isEyeInFluid(1) + && !this.level().getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { + boolean flag1 = !this.canBreatheUnderwater() + && !MobEffectUtil.hasWaterBreathing(this) +diff --git a/net/minecraft/world/entity/animal/AbstractFish.java b/net/minecraft/world/entity/animal/AbstractFish.java +index 28ae152125ed83d8917674b6068f227f87890f30..4b0a8743172b790fb42b47ecef33e52d0cb3c194 100644 +--- a/net/minecraft/world/entity/animal/AbstractFish.java ++++ b/net/minecraft/world/entity/animal/AbstractFish.java +@@ -179,7 +179,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { + + @Override + public void vanillaTick() { // Purpur - Ridables +- if (this.fish.isEyeInFluid(FluidTags.WATER)) { ++ if (this.fish.isEyeInFluid(1)) { + this.fish.setDeltaMovement(this.fish.getDeltaMovement().add(0.0, 0.005, 0.0)); + } + +diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index 56dc7011ed07f0bd5870fbadde2b5c0c630c5edd..8d02515297ead6073d5eb60d58ff040cd101f3d8 100644 +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -71,6 +71,7 @@ import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec2; +@@ -1202,13 +1203,16 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + double d1 = this.getBoundingBox().minY; + double d2 = this.getZ() + direction.z; + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- ++ net.minecraft.world.level.chunk.ChunkAccess chunk = this.level().getChunkIfLoadedImmediately((int) d >> 4, (int) d2 >> 4); ++ if (chunk == null) { ++ return null; ++ } + for (Pose pose : passenger.getDismountPoses()) { + mutableBlockPos.set(d, d1, d2); + double d3 = this.getBoundingBox().maxY + 0.75; + + do { +- double blockFloorHeight = this.level().getBlockFloorHeight(mutableBlockPos); ++ double blockFloorHeight = ((LevelChunk) chunk).getBlockFloorHeight(mutableBlockPos); + if (mutableBlockPos.getY() + blockFloorHeight > d3) { + break; + } +diff --git a/net/minecraft/world/entity/animal/horse/SkeletonHorse.java b/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +index d5ee5b816efc1b3b17b94227f8ea05ab7a2ccad7..93702017d2769d8207864725e73c86cf54cda8ff 100644 +--- a/net/minecraft/world/entity/animal/horse/SkeletonHorse.java ++++ b/net/minecraft/world/entity/animal/horse/SkeletonHorse.java +@@ -108,7 +108,7 @@ public class SkeletonHorse extends AbstractHorse { + + @Override + protected SoundEvent getAmbientSound() { +- return this.isEyeInFluid(FluidTags.WATER) ? SoundEvents.SKELETON_HORSE_AMBIENT_WATER : SoundEvents.SKELETON_HORSE_AMBIENT; ++ return this.isEyeInFluid(1) ? SoundEvents.SKELETON_HORSE_AMBIENT_WATER : SoundEvents.SKELETON_HORSE_AMBIENT; + } + + @Override +diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java +index f4fa19c6352e44a624e81dc201b1d7d710c2d9d2..3b070af23802dcba9a356ea22e2898ab6099b86b 100644 +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -405,7 +405,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { + + @Override + protected boolean canAddPassenger(Entity passenger) { +- return !this.isVehicle() && !this.isEyeInFluid(FluidTags.LAVA); ++ return !this.isVehicle() && !this.isEyeInFluid(2); + } + + @Override +diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java +index e4353c64732067198f082cdd266c1f1ee1fe4f4e..2a4a1d6a94e7712f6c861fe70f65a0a76014ad0b 100644 +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -178,7 +178,7 @@ public class Witch extends Raider implements RangedAttackMob { + } + } else { + Holder holder = null; +- if (this.random.nextFloat() < 0.15F && this.isEyeInFluid(FluidTags.WATER) && !this.hasEffect(MobEffects.WATER_BREATHING)) { ++ if (this.random.nextFloat() < 0.15F && this.isEyeInFluid(1) && !this.hasEffect(MobEffects.WATER_BREATHING)) { + holder = Potions.WATER_BREATHING; + } else if (this.random.nextFloat() < 0.15F + && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) +diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java +index 9c83f1406c0aaad36383a23cebf270b8dc6ced33..2a16248539718d3945d3b2b4d2da161f632831ff 100644 +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -283,7 +283,7 @@ public class Zombie extends Monster { + this.doUnderWaterConversion(); + } + } else if (this.convertsInWater()) { +- if (this.isEyeInFluid(FluidTags.WATER)) { ++ if (this.isEyeInFluid(1)) { + this.inWaterTime++; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); +diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java +index 76d85632e1364e71a2aa15dbef41c62422ffd7af..335f99ecd313b4e1ad5b997a84b65331a2253574 100644 +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -374,7 +374,7 @@ public abstract class Player extends LivingEntity { + this.lastItemInMainHand = mainHandItem.copy(); + } + +- if (!this.isEyeInFluid(FluidTags.WATER) && this.isEquipped(Items.TURTLE_HELMET)) { ++ if (!this.isEyeInFluid(1) && this.isEquipped(Items.TURTLE_HELMET)) { + this.turtleHelmetTick(); + } + +@@ -414,7 +414,7 @@ public abstract class Player extends LivingEntity { + } + + protected boolean updateIsUnderwater() { +- this.wasUnderwater = this.isEyeInFluid(FluidTags.WATER); ++ this.wasUnderwater = this.isEyeInFluid(1); + return this.wasUnderwater; + } + +@@ -851,7 +851,7 @@ public abstract class Player extends LivingEntity { + } + + destroySpeed *= (float)this.getAttributeValue(Attributes.BLOCK_BREAK_SPEED); +- if (this.isEyeInFluid(FluidTags.WATER)) { ++ if (this.isEyeInFluid(1)) { + destroySpeed *= (float)this.getAttribute(Attributes.SUBMERGED_MINING_SPEED).getValue(); + } + +diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java +index b1b312e45ed4514eaa6fb3941af64b641220c5bd..636b5dfe1761f4d13b6af7b11f610ff5c18b36d6 100644 +--- a/net/minecraft/world/entity/vehicle/AbstractBoat.java ++++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java +@@ -847,7 +847,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { + + @Override + protected boolean canAddPassenger(Entity passenger) { +- return this.getPassengers().size() < this.getMaxPassengers() && !this.isEyeInFluid(FluidTags.WATER); ++ return this.getPassengers().size() < this.getMaxPassengers() && !this.isEyeInFluid(1); + } + + protected int getMaxPassengers() { +diff --git a/net/minecraft/world/level/material/FluidState.java b/net/minecraft/world/level/material/FluidState.java +index 06581fe010ca722d62d0b6d3c44d845f9db0231f..38600ed61757da54295e712a37a3bba3c71fe0a1 100644 +--- a/net/minecraft/world/level/material/FluidState.java ++++ b/net/minecraft/world/level/material/FluidState.java +@@ -160,8 +160,14 @@ public final class FluidState extends StateHolder implements + } + + // Leaf start - Remove stream in updateFluidOnEyes +- public java.util.Set> getTagsAsSet() { +- return this.owner.builtInRegistryHolder().tagsAsSet(); ++ public TagKey[] getTagsArray() { ++ java.util.Set> tags = this.owner.builtInRegistryHolder().tagsAsSet(); ++ TagKey[] array = new TagKey[tags.size()]; ++ int i = 0; ++ for (TagKey tag : tags) { ++ array[i++] = tag; ++ } ++ return array; + } + // Leaf end - Remove stream in updateFluidOnEyes + } diff --git a/leaf-server/paper-patches/features/0042-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch b/leaf-server/paper-patches/features/0042-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch index 77da8702..ea542d1d 100644 --- a/leaf-server/paper-patches/features/0042-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch +++ b/leaf-server/paper-patches/features/0042-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch @@ -1,12 +1,21 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Taiyou06 -Date: Fri, 6 Jun 2025 10:47:32 +0200 +From: Spottedleaf +Date: Thu, 5 Jun 2025 14:55:57 -0700 Subject: [PATCH] Paper: Update CraftWorld#getForceLoadedChunks to avoid using getChunkAt +Original license: GPLv3 +Original project: https://github.com/PaperMC/Paper + +https://github.com/PaperMC/Paper/commit/774c40e71297c6e6d7d417639e1ce61cc79cc5ba + +Usual methods of adding force loaded chunks sync load them, so +they should be loaded already. This should avoid the more expensive +getChunkAt and more importantly allow this function to properly work +on Folia due to avoiding thread checks. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 236be1bb296d0f080d2a8c739d2678655e81e174..e5ed5bae80aad4ddbea9fca0c0fe00cf95bb6f47 100644 +index 236be1bb296d0f080d2a8c739d2678655e81e174..64d95bc035fbafa660e7f3d7393da4bf8839b2f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -657,7 +657,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @@ -14,7 +23,7 @@ index 236be1bb296d0f080d2a8c739d2678655e81e174..e5ed5bae80aad4ddbea9fca0c0fe00cf for (long coord : this.getHandle().getForcedChunks()) { - chunks.add(this.getChunkAt(ChunkPos.getX(coord), ChunkPos.getZ(coord))); -+ chunks.add(new CraftChunk(this.getHandle(), ChunkPos.getX(coord), ChunkPos.getZ(coord))); ++ chunks.add(new CraftChunk(this.getHandle(), ChunkPos.getX(coord), ChunkPos.getZ(coord))); // Paper - Update CraftWorld#getForceLoadedChunks to avoid using getChunkAt } return Collections.unmodifiableCollection(chunks);