diff --git a/luminol-server/minecraft-patches/features/0043-Leaf-Smart-sort-entities-in-NearestLivingEntitySenso.patch b/luminol-server/minecraft-patches/features/0043-Leaf-Smart-sort-entities-in-NearestLivingEntitySenso.patch new file mode 100644 index 0000000..638a4d6 --- /dev/null +++ b/luminol-server/minecraft-patches/features/0043-Leaf-Smart-sort-entities-in-NearestLivingEntitySenso.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Fri, 21 Mar 2025 21:14:02 +0800 +Subject: [PATCH] Leaf Smart sort entities in NearestLivingEntitySensor + + +diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..83af90c7a2e425b775abd7907895d211ced07955 100644 +--- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -13,18 +13,102 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; + import net.minecraft.world.phys.AABB; + + public class NearestLivingEntitySensor extends Sensor { ++ ++ // Leaf start - Optimized entity sorting with buffer reuse ++ private static final int SMALL_ARRAY_THRESHOLD = 2; ++ private LivingEntity[] entityBuffer = new LivingEntity[0]; ++ private long[] bitsBuffer = new long[0]; ++ + @Override + protected void doTick(ServerLevel level, T entity) { +- double attributeValue = entity.getAttributeValue(Attributes.FOLLOW_RANGE); +- AABB aabb = entity.getBoundingBox().inflate(attributeValue, attributeValue, attributeValue); +- List entitiesOfClass = level.getEntitiesOfClass( +- LivingEntity.class, aabb, matchableEntity -> matchableEntity != entity && matchableEntity.isAlive() ++ double range = entity.getAttributeValue(Attributes.FOLLOW_RANGE); ++ double rangeSqr = range * range; ++ AABB aabb = entity.getBoundingBox().inflate(range, range, range); ++ ++ List entities = level.getEntitiesOfClass( ++ LivingEntity.class, aabb, e -> e != entity && e.isAlive() && entity.distanceToSqr(e) <= rangeSqr + ); +- entitiesOfClass.sort(Comparator.comparingDouble(entity::distanceToSqr)); ++ ++ LivingEntity[] sorted = smartSort(entities, entity); ++ List sortedList = java.util.Arrays.asList(sorted); ++ + Brain brain = entity.getBrain(); +- brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, entitiesOfClass); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, new NearestVisibleLivingEntities(level, entity, entitiesOfClass)); ++ brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, sortedList); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, ++ new NearestVisibleLivingEntities(level, entity, sortedList)); ++ } ++ ++ private LivingEntity[] smartSort(List entities, T reference) { ++ int size = entities.size(); ++ if (size <= 1) return entities.toArray(new LivingEntity[0]); ++ ++ if (entityBuffer.length < size) { ++ entityBuffer = new LivingEntity[size]; ++ bitsBuffer = new long[size]; ++ } ++ ++ for (int i = 0; i < size; i++) { ++ LivingEntity e = entities.get(i); ++ entityBuffer[i] = e; ++ bitsBuffer[i] = Double.doubleToRawLongBits(reference.distanceToSqr(e)); ++ } ++ ++ fastRadixSort(entityBuffer, bitsBuffer, 0, size - 1, 62); ++ ++ return java.util.Arrays.copyOf(entityBuffer, size); ++ } ++ ++ private void fastRadixSort(LivingEntity[] ents, long[] bits, int low, int high, int bit) { ++ if (bit < 0 || low >= high) return; ++ ++ if (high - low <= SMALL_ARRAY_THRESHOLD) { ++ insertionSort(ents, bits, low, high); ++ return; ++ } ++ ++ int i = low, j = high; ++ final long mask = 1L << bit; ++ ++ while (i <= j) { ++ while (i <= j && (bits[i] & mask) == 0) i++; ++ while (i <= j && (bits[j] & mask) != 0) j--; ++ ++ if (i < j) { ++ swap(ents, bits, i++, j--); ++ } ++ } ++ ++ if (low < j) fastRadixSort(ents, bits, low, j, bit - 1); ++ if (i < high) fastRadixSort(ents, bits, i, high, bit - 1); ++ } ++ ++ private void insertionSort(LivingEntity[] ents, long[] bits, int low, int high) { ++ for (int i = low + 1; i <= high; i++) { ++ int j = i; ++ LivingEntity e = ents[j]; ++ long b = bits[j]; ++ ++ while (j > low && bits[j - 1] > b) { ++ ents[j] = ents[j - 1]; ++ bits[j] = bits[j - 1]; ++ j--; ++ } ++ ++ ents[j] = e; ++ bits[j] = b; ++ } ++ } ++ ++ private void swap(LivingEntity[] ents, long[] bits, int a, int b) { ++ LivingEntity te = ents[a]; ++ ents[a] = ents[b]; ++ ents[b] = te; ++ ++ long tb = bits[a]; ++ bits[a] = bits[b]; ++ bits[b] = tb; + } ++ // Leaf end - Optimized entity sorting with buffer reuse + + @Override + public Set> requires() { diff --git a/luminol-server/minecraft-patches/features/0043-Tick-regions-api.patch b/luminol-server/minecraft-patches/features/0044-Tick-regions-api.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0043-Tick-regions-api.patch rename to luminol-server/minecraft-patches/features/0044-Tick-regions-api.patch diff --git a/luminol-server/minecraft-patches/features/0044-Add-missing-teleportation-apis-for-folia.patch b/luminol-server/minecraft-patches/features/0045-Add-missing-teleportation-apis-for-folia.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0044-Add-missing-teleportation-apis-for-folia.patch rename to luminol-server/minecraft-patches/features/0045-Add-missing-teleportation-apis-for-folia.patch diff --git a/luminol-server/minecraft-patches/features/0045-Leaves-Revert-raid-changes.patch b/luminol-server/minecraft-patches/features/0046-Leaves-Revert-raid-changes.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0045-Leaves-Revert-raid-changes.patch rename to luminol-server/minecraft-patches/features/0046-Leaves-Revert-raid-changes.patch diff --git a/luminol-server/minecraft-patches/features/0046-Leaves-Disable-moved-wrongly-threshold.patch b/luminol-server/minecraft-patches/features/0047-Leaves-Disable-moved-wrongly-threshold.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0046-Leaves-Disable-moved-wrongly-threshold.patch rename to luminol-server/minecraft-patches/features/0047-Leaves-Disable-moved-wrongly-threshold.patch diff --git a/luminol-server/minecraft-patches/features/0047-Leaves-Fix-Incorrect-Collision-Behavior-for-Block-Sh.patch b/luminol-server/minecraft-patches/features/0048-Leaves-Fix-Incorrect-Collision-Behavior-for-Block-Sh.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0047-Leaves-Fix-Incorrect-Collision-Behavior-for-Block-Sh.patch rename to luminol-server/minecraft-patches/features/0048-Leaves-Fix-Incorrect-Collision-Behavior-for-Block-Sh.patch diff --git a/luminol-server/minecraft-patches/features/0048-Raytracing-tracker-experiment.patch b/luminol-server/minecraft-patches/features/0049-Raytracing-tracker-experiment.patch similarity index 100% rename from luminol-server/minecraft-patches/features/0048-Raytracing-tracker-experiment.patch rename to luminol-server/minecraft-patches/features/0049-Raytracing-tracker-experiment.patch