From b57e8086a35903bd7ea42495311b1bef93d0580e Mon Sep 17 00:00:00 2001 From: Martix Date: Tue, 10 Nov 2026 17:25:52 +0100 Subject: [PATCH 1/6] Bug fix --- .../utils/world/BlockIterator.java | 83 +++++++++++-------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index 59a796b708b..9f496dd5862 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -16,6 +16,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; +import java.util.Iterator; import java.util.List; import java.util.function.BiConsumer; @@ -24,12 +25,15 @@ public class BlockIterator { private static final Pool callbackPool = new Pool<>(Callback::new); private static final List callbacks = new ReferenceArrayList<>(); + private static final List pendingCallbacks = new ReferenceArrayList<>(); + private static final List completedCallbacks = new ReferenceArrayList<>(); private static final List afterCallbacks = new ReferenceArrayList<>(); private static final BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); private static int hRadius, vRadius; + private static boolean processing; private static boolean disableCurrent; private BlockIterator() { @@ -44,55 +48,68 @@ public static void init() { private static void onTick(TickEvent.Pre event) { if (!Utils.canUpdate()) return; - int px = mc.player.getBlockX(); - int py = mc.player.getBlockY(); - int pz = mc.player.getBlockZ(); - - for (int x = px - hRadius; x <= px + hRadius; x++) { - for (int z = pz - hRadius; z <= pz + hRadius; z++) { - for (int y = Math.max(mc.level.getMinY(), py - vRadius); y <= py + vRadius; y++) { - if (y > mc.level.getHeight()) break; - - blockPos.set(x, y, z); - BlockState blockState = mc.level.getBlockState(blockPos); - - int dx = Math.abs(x - px); - int dy = Math.abs(y - py); - int dz = Math.abs(z - pz); - - callbacks.removeIf(callback -> { - if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { - disableCurrent = false; - callback.function.accept(blockPos, blockState); - return disableCurrent; + int px = mc.player.getBlockX(), py = mc.player.getBlockY(), pz = mc.player.getBlockZ(); + int scanHRadius = hRadius, scanVRadius = vRadius; + hRadius = 0; + vRadius = 0; + processing = true; + + try { + for (int x = px - scanHRadius; x <= px + scanHRadius; x++) { + for (int z = pz - scanHRadius; z <= pz + scanHRadius; z++) { + for (int y = Math.max(mc.level.getMinY(), py - scanVRadius); y <= py + scanVRadius; y++) { + if (y > mc.level.getMaxY()) break; + + blockPos.set(x, y, z); + BlockState blockState = mc.level.getBlockState(blockPos); + + int dx = Math.abs(x - px); + int dy = Math.abs(y - py); + int dz = Math.abs(z - pz); + + Iterator iterator = callbacks.iterator(); + while (iterator.hasNext()) { + Callback callback = iterator.next(); + + if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { + disableCurrent = false; + callback.function.accept(blockPos, blockState); + + if (disableCurrent) { + iterator.remove(); + completedCallbacks.add(callback); + } + } } - return false; - }); + } } } + } finally { + processing = false; + callbackPool.freeAll(callbacks); + callbackPool.freeAll(completedCallbacks); + callbacks.clear(); + completedCallbacks.clear(); + callbacks.addAll(pendingCallbacks); + pendingCallbacks.clear(); } - hRadius = 0; - vRadius = 0; - - callbackPool.freeAll(callbacks); - callbacks.clear(); - for (Runnable callback : afterCallbacks) callback.run(); afterCallbacks.clear(); } public static void register(int horizontalRadius, int verticalRadius, BiConsumer function) { - hRadius = Math.max(hRadius, horizontalRadius); - vRadius = Math.max(vRadius, verticalRadius); - Callback callback = callbackPool.get(); callback.function = function; callback.hRadius = horizontalRadius; callback.vRadius = verticalRadius; - callbacks.add(callback); + hRadius = Math.max(hRadius, horizontalRadius); + vRadius = Math.max(vRadius, verticalRadius); + + if (processing) pendingCallbacks.add(callback); + else callbacks.add(callback); } public static void disableCurrent() { From 40f1f677841bd93a3d1b8cab07edea29e76b34a7 Mon Sep 17 00:00:00 2001 From: Martix Date: Tue, 10 Nov 2026 17:35:49 +0100 Subject: [PATCH 2/6] Fix BlockIterator callback lifecycle --- .../utils/world/BlockIterator.java | 78 +++++++++++-------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index 9f496dd5862..fb6fbbb5569 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -55,47 +55,59 @@ private static void onTick(TickEvent.Pre event) { processing = true; try { - for (int x = px - scanHRadius; x <= px + scanHRadius; x++) { - for (int z = pz - scanHRadius; z <= pz + scanHRadius; z++) { - for (int y = Math.max(mc.level.getMinY(), py - scanVRadius); y <= py + scanVRadius; y++) { - if (y > mc.level.getMaxY()) break; - - blockPos.set(x, y, z); - BlockState blockState = mc.level.getBlockState(blockPos); - - int dx = Math.abs(x - px); - int dy = Math.abs(y - py); - int dz = Math.abs(z - pz); - - Iterator iterator = callbacks.iterator(); - while (iterator.hasNext()) { - Callback callback = iterator.next(); - - if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { - disableCurrent = false; - callback.function.accept(blockPos, blockState); - - if (disableCurrent) { - iterator.remove(); - completedCallbacks.add(callback); + try { + scan: + for (int x = px - scanHRadius; x <= px + scanHRadius; x++) { + for (int z = pz - scanHRadius; z <= pz + scanHRadius; z++) { + for (int y = Math.max(mc.level.getMinY(), py - scanVRadius); y <= py + scanVRadius; y++) { + if (callbacks.isEmpty()) break scan; + if (y > mc.level.getMaxY()) break; + + blockPos.set(x, y, z); + BlockState blockState = mc.level.getBlockState(blockPos); + + int dx = Math.abs(x - px); + int dy = Math.abs(y - py); + int dz = Math.abs(z - pz); + + Iterator iterator = callbacks.iterator(); + while (iterator.hasNext()) { + Callback callback = iterator.next(); + + if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { + disableCurrent = false; + callback.function.accept(blockPos, blockState); + + if (disableCurrent) { + iterator.remove(); + completedCallbacks.add(callback); + } } } } } } + } finally { + processing = false; + callbackPool.freeAll(callbacks); + callbackPool.freeAll(completedCallbacks); + callbacks.clear(); + completedCallbacks.clear(); + callbacks.addAll(pendingCallbacks); + pendingCallbacks.clear(); } } finally { - processing = false; - callbackPool.freeAll(callbacks); - callbackPool.freeAll(completedCallbacks); - callbacks.clear(); - completedCallbacks.clear(); - callbacks.addAll(pendingCallbacks); - pendingCallbacks.clear(); + List callbacksToRun = new ReferenceArrayList<>(afterCallbacks); + afterCallbacks.clear(); + + for (Runnable callback : callbacksToRun) { + try { + callback.run(); + } catch (RuntimeException e) { + MeteorClient.LOG.error("Error while executing a BlockIterator after callback.", e); + } + } } - - for (Runnable callback : afterCallbacks) callback.run(); - afterCallbacks.clear(); } public static void register(int horizontalRadius, int verticalRadius, BiConsumer function) { From 970334ee86f65acc01998b538ea91e4e5d865dcd Mon Sep 17 00:00:00 2001 From: Martix Date: Tue, 10 Nov 2026 17:54:49 +0100 Subject: [PATCH 3/6] Change comparison operator for block height check --- .../meteorclient/utils/world/BlockIterator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index fb6fbbb5569..dd086e77810 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -61,7 +61,7 @@ private static void onTick(TickEvent.Pre event) { for (int z = pz - scanHRadius; z <= pz + scanHRadius; z++) { for (int y = Math.max(mc.level.getMinY(), py - scanVRadius); y <= py + scanVRadius; y++) { if (callbacks.isEmpty()) break scan; - if (y > mc.level.getMaxY()) break; + if (y >= mc.level.getMaxY()) break; blockPos.set(x, y, z); BlockState blockState = mc.level.getBlockState(blockPos); From 961949dda48c6371347b489e843d2b6c205ecf51 Mon Sep 17 00:00:00 2001 From: Martix Date: Tue, 10 Nov 2026 23:43:17 +0100 Subject: [PATCH 4/6] Simplify BlockIterator callback lifecycle --- .../utils/world/BlockIterator.java | 107 ++++++++---------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index dd086e77810..3c196cbf64c 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -25,15 +25,12 @@ public class BlockIterator { private static final Pool callbackPool = new Pool<>(Callback::new); private static final List callbacks = new ReferenceArrayList<>(); - private static final List pendingCallbacks = new ReferenceArrayList<>(); - private static final List completedCallbacks = new ReferenceArrayList<>(); private static final List afterCallbacks = new ReferenceArrayList<>(); private static final BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); private static int hRadius, vRadius; - private static boolean processing; private static boolean disableCurrent; private BlockIterator() { @@ -48,80 +45,70 @@ public static void init() { private static void onTick(TickEvent.Pre event) { if (!Utils.canUpdate()) return; - int px = mc.player.getBlockX(), py = mc.player.getBlockY(), pz = mc.player.getBlockZ(); - int scanHRadius = hRadius, scanVRadius = vRadius; - hRadius = 0; - vRadius = 0; - processing = true; + int px = mc.player.getBlockX(); + int py = mc.player.getBlockY(); + int pz = mc.player.getBlockZ(); try { - try { - scan: - for (int x = px - scanHRadius; x <= px + scanHRadius; x++) { - for (int z = pz - scanHRadius; z <= pz + scanHRadius; z++) { - for (int y = Math.max(mc.level.getMinY(), py - scanVRadius); y <= py + scanVRadius; y++) { - if (callbacks.isEmpty()) break scan; - if (y >= mc.level.getMaxY()) break; - - blockPos.set(x, y, z); - BlockState blockState = mc.level.getBlockState(blockPos); - - int dx = Math.abs(x - px); - int dy = Math.abs(y - py); - int dz = Math.abs(z - pz); - - Iterator iterator = callbacks.iterator(); - while (iterator.hasNext()) { - Callback callback = iterator.next(); - - if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { - disableCurrent = false; - callback.function.accept(blockPos, blockState); - - if (disableCurrent) { - iterator.remove(); - completedCallbacks.add(callback); - } - } + scan(px, py, pz); + } finally { + hRadius = 0; + vRadius = 0; + + callbackPool.freeAll(callbacks); + callbacks.clear(); + } + + List callbacksToRun = new ReferenceArrayList<>(afterCallbacks); + afterCallbacks.clear(); + + for (Runnable callback : callbacksToRun) callback.run(); + } + + private static void scan(int px, int py, int pz) { + for (int x = px - hRadius; x <= px + hRadius; x++) { + for (int z = pz - hRadius; z <= pz + hRadius; z++) { + for (int y = Math.max(mc.level.getMinY(), py - vRadius); y <= py + vRadius; y++) { + if (callbacks.isEmpty()) return; + if (y >= mc.level.getMaxY()) break; + + blockPos.set(x, y, z); + BlockState blockState = mc.level.getBlockState(blockPos); + + int dx = Math.abs(x - px); + int dy = Math.abs(y - py); + int dz = Math.abs(z - pz); + + Iterator iterator = callbacks.iterator(); + while (iterator.hasNext()) { + Callback callback = iterator.next(); + + if (dx <= callback.hRadius && dy <= callback.vRadius && dz <= callback.hRadius) { + disableCurrent = false; + callback.function.accept(blockPos, blockState); + + if (disableCurrent) { + iterator.remove(); + callbackPool.free(callback); } } } } - } finally { - processing = false; - callbackPool.freeAll(callbacks); - callbackPool.freeAll(completedCallbacks); - callbacks.clear(); - completedCallbacks.clear(); - callbacks.addAll(pendingCallbacks); - pendingCallbacks.clear(); - } - } finally { - List callbacksToRun = new ReferenceArrayList<>(afterCallbacks); - afterCallbacks.clear(); - - for (Runnable callback : callbacksToRun) { - try { - callback.run(); - } catch (RuntimeException e) { - MeteorClient.LOG.error("Error while executing a BlockIterator after callback.", e); - } } } } public static void register(int horizontalRadius, int verticalRadius, BiConsumer function) { + hRadius = Math.max(hRadius, horizontalRadius); + vRadius = Math.max(vRadius, verticalRadius); + Callback callback = callbackPool.get(); callback.function = function; callback.hRadius = horizontalRadius; callback.vRadius = verticalRadius; - hRadius = Math.max(hRadius, horizontalRadius); - vRadius = Math.max(vRadius, verticalRadius); - - if (processing) pendingCallbacks.add(callback); - else callbacks.add(callback); + callbacks.add(callback); } public static void disableCurrent() { From d08ab8a2e5119c62a81b66b805815c578f6324cb Mon Sep 17 00:00:00 2001 From: Martix Date: Wed, 11 Nov 2026 00:04:01 +0100 Subject: [PATCH 5/6] Clear deferred callbacks when block scan fails --- .../meteorclient/utils/world/BlockIterator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index 3c196cbf64c..3e6649fb8e9 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -49,14 +49,19 @@ private static void onTick(TickEvent.Pre event) { int py = mc.player.getBlockY(); int pz = mc.player.getBlockZ(); + boolean scanCompleted = false; + try { scan(px, py, pz); + scanCompleted = true; } finally { hRadius = 0; vRadius = 0; callbackPool.freeAll(callbacks); callbacks.clear(); + + if (!scanCompleted) afterCallbacks.clear(); } List callbacksToRun = new ReferenceArrayList<>(afterCallbacks); From 0b51228bd1981b8d15624abf1654dcbab63ea452 Mon Sep 17 00:00:00 2001 From: Martix Date: Wed, 11 Nov 2026 14:03:06 +0100 Subject: [PATCH 6/6] Simplify BlockIterator callback cleanup --- .../utils/world/BlockIterator.java | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java index 3e6649fb8e9..cc71feb711c 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockIterator.java @@ -49,25 +49,16 @@ private static void onTick(TickEvent.Pre event) { int py = mc.player.getBlockY(); int pz = mc.player.getBlockZ(); - boolean scanCompleted = false; + scan(px, py, pz); - try { - scan(px, py, pz); - scanCompleted = true; - } finally { - hRadius = 0; - vRadius = 0; + hRadius = 0; + vRadius = 0; - callbackPool.freeAll(callbacks); - callbacks.clear(); + callbackPool.freeAll(callbacks); + callbacks.clear(); - if (!scanCompleted) afterCallbacks.clear(); - } - - List callbacksToRun = new ReferenceArrayList<>(afterCallbacks); + for (Runnable callback : afterCallbacks) callback.run(); afterCallbacks.clear(); - - for (Runnable callback : callbacksToRun) callback.run(); } private static void scan(int px, int py, int pz) {