From 04356668a5de8625d1103a6204881e427e50c2f5 Mon Sep 17 00:00:00 2001 From: toprakdevx Date: Wed, 29 Jul 2026 18:29:15 +0300 Subject: [PATCH 1/9] Add EntityCollectionUtil with thread-local reusable lists --- .../util/entity/EntityCollectionUtil.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java diff --git a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java new file mode 100644 index 00000000..c92e64b0 --- /dev/null +++ b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java @@ -0,0 +1,34 @@ +package org.galemc.gale.util.entity; + +import java.util.ArrayList; +import java.util.List; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.VoxelShape; + +public final class EntityCollectionUtil { + + private static final ThreadLocal> ENTITY_LIST = ThreadLocal.withInitial(ArrayList::new); + private static final ThreadLocal> VOXEL_SHAPE_LIST = ThreadLocal.withInitial(ArrayList::new); + private static final ThreadLocal> AABB_LIST = ThreadLocal.withInitial(ArrayList::new); + + private EntityCollectionUtil() {} + + public static List getEntityList() { + List list = ENTITY_LIST.get(); + list.clear(); + return list; + } + + public static List getVoxelShapeList() { + List list = VOXEL_SHAPE_LIST.get(); + list.clear(); + return list; + } + + public static List getAABBList() { + List list = AABB_LIST.get(); + list.clear(); + return list; + } +} From ce4d0c7555a431fb70a90d5b655e0076da010ee9 Mon Sep 17 00:00:00 2001 From: toprakdevx Date: Wed, 29 Jul 2026 21:16:39 +0300 Subject: [PATCH 2/9] Add EntityCollectionUtil utility class --- .../galemc/gale/util/entity/EntityCollectionUtil.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java index c92e64b0..3525335d 100644 --- a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java +++ b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java @@ -8,9 +8,12 @@ public final class EntityCollectionUtil { - private static final ThreadLocal> ENTITY_LIST = ThreadLocal.withInitial(ArrayList::new); - private static final ThreadLocal> VOXEL_SHAPE_LIST = ThreadLocal.withInitial(ArrayList::new); - private static final ThreadLocal> AABB_LIST = ThreadLocal.withInitial(ArrayList::new); + private static final int EXPECTED_ENTITIES = 64; + private static final int EXPECTED_COLLISIONS = 32; + + private static final ThreadLocal> ENTITY_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_ENTITIES)); + private static final ThreadLocal> VOXEL_SHAPE_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_COLLISIONS)); + private static final ThreadLocal> AABB_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_COLLISIONS)); private EntityCollectionUtil() {} From b131dd0dcac9da913d6460547dfe364f1e9aff99 Mon Sep 17 00:00:00 2001 From: toprakdevx Date: Wed, 29 Jul 2026 21:22:53 +0300 Subject: [PATCH 3/9] remove ThreadLocal, server-thread-only --- .../util/entity/EntityCollectionUtil.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java index 3525335d..97cff6a9 100644 --- a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java +++ b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java @@ -11,27 +11,24 @@ public final class EntityCollectionUtil { private static final int EXPECTED_ENTITIES = 64; private static final int EXPECTED_COLLISIONS = 32; - private static final ThreadLocal> ENTITY_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_ENTITIES)); - private static final ThreadLocal> VOXEL_SHAPE_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_COLLISIONS)); - private static final ThreadLocal> AABB_LIST = ThreadLocal.withInitial(() -> new ArrayList<>(EXPECTED_COLLISIONS)); + private static final List ENTITY_LIST = new ArrayList<>(EXPECTED_ENTITIES); + private static final List VOXEL_SHAPE_LIST = new ArrayList<>(EXPECTED_COLLISIONS); + private static final List AABB_LIST = new ArrayList<>(EXPECTED_COLLISIONS); private EntityCollectionUtil() {} public static List getEntityList() { - List list = ENTITY_LIST.get(); - list.clear(); - return list; + ENTITY_LIST.clear(); + return ENTITY_LIST; } public static List getVoxelShapeList() { - List list = VOXEL_SHAPE_LIST.get(); - list.clear(); - return list; + VOXEL_SHAPE_LIST.clear(); + return VOXEL_SHAPE_LIST; } public static List getAABBList() { - List list = AABB_LIST.get(); - list.clear(); - return list; + AABB_LIST.clear(); + return AABB_LIST; } } From 8f894724e76b53e27d35b16311e0eac63757dd9b Mon Sep 17 00:00:00 2001 From: toprakdevx Date: Thu, 30 Jul 2026 03:10:15 +0300 Subject: [PATCH 4/9] remove unused lists, add Level.java patch --- .../net/minecraft/world/level/Level.java.patch | 13 +++++++++++++ .../gale/util/entity/EntityCollectionUtil.java | 15 --------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index 96f847f7..2fb1112f 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -288,6 +288,19 @@ this.tickingBlockEntities = true; if (!this.pendingBlockEntityTickers.isEmpty()) { this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); +@@ -1515,4 +_,14 @@ + } + ++ // Gale start - use thread-local reusable list ++ @Override ++ public List getEntities(@Nullable Entity except, AABB area) { ++ List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); ++ ((ServerLevel)this).getEntityLookup().getEntities(except, area, list, EntitySelector.NO_SPECTATORS); ++ return list; ++ } ++ // Gale end - use thread-local reusable list + @Override + public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { @@ -2127,6 +_,13 @@ public BiomeManager getBiomeManager() { return this.biomeManager; diff --git a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java index 97cff6a9..29b1fafa 100644 --- a/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java +++ b/gale-server/src/main/java/org/galemc/gale/util/entity/EntityCollectionUtil.java @@ -3,17 +3,12 @@ import java.util.ArrayList; import java.util.List; import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.VoxelShape; public final class EntityCollectionUtil { private static final int EXPECTED_ENTITIES = 64; - private static final int EXPECTED_COLLISIONS = 32; private static final List ENTITY_LIST = new ArrayList<>(EXPECTED_ENTITIES); - private static final List VOXEL_SHAPE_LIST = new ArrayList<>(EXPECTED_COLLISIONS); - private static final List AABB_LIST = new ArrayList<>(EXPECTED_COLLISIONS); private EntityCollectionUtil() {} @@ -21,14 +16,4 @@ public static List getEntityList() { ENTITY_LIST.clear(); return ENTITY_LIST; } - - public static List getVoxelShapeList() { - VOXEL_SHAPE_LIST.clear(); - return VOXEL_SHAPE_LIST; - } - - public static List getAABBList() { - AABB_LIST.clear(); - return AABB_LIST; - } } From 19434811a61e84b51f5b2bac610ce203c269b269 Mon Sep 17 00:00:00 2001 From: Toprak Date: Thu, 30 Jul 2026 12:18:36 +0300 Subject: [PATCH 5/9] Fix Level.java.patch: remove broken hunk, add EntityCollectionUtil override anchored on isDebug() --- .../minecraft/world/level/Level.java.patch | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index 2fb1112f..3bf72e7a 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -288,20 +288,7 @@ this.tickingBlockEntities = true; if (!this.pendingBlockEntityTickers.isEmpty()) { this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); -@@ -1515,4 +_,14 @@ - } - -+ // Gale start - use thread-local reusable list -+ @Override -+ public List getEntities(@Nullable Entity except, AABB area) { -+ List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); -+ ((ServerLevel)this).getEntityLookup().getEntities(except, area, list, EntitySelector.NO_SPECTATORS); -+ return list; -+ } -+ // Gale end - use thread-local reusable list - @Override - public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { -@@ -2127,6 +_,13 @@ +@@ -2127,6 +_,22 @@ public BiomeManager getBiomeManager() { return this.biomeManager; } @@ -313,5 +300,14 @@ + } + // Gale end - Cache - BiomeManager.getBiome() ++ // Gale start - use reusable entity list ++ @Override ++ public List getEntities(@Nullable Entity except, AABB area) { ++ List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); ++ ((ServerLevel)this).getEntityLookup().getEntities(except, area, list, EntitySelector.NO_SPECTATORS); ++ return list; ++ } ++ // Gale end - use reusable entity list public final boolean isDebug() { return this.isDebug; + From 7c620135d47d626543baf7c73402c95e82b5b378 Mon Sep 17 00:00:00 2001 From: Toprak Date: Thu, 30 Jul 2026 12:26:33 +0300 Subject: [PATCH 6/9] fix: restore getEntities(Entity, AABB) override that was dropped from patch --- .../sources/net/minecraft/world/level/Level.java.patch | 1 - 1 file changed, 1 deletion(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index 3bf72e7a..4666a584 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -310,4 +310,3 @@ + // Gale end - use reusable entity list public final boolean isDebug() { return this.isDebug; - From 5f714ae4bb9a48ed3d8c987249db013a7eaed6b8 Mon Sep 17 00:00:00 2001 From: Toprak Date: Thu, 30 Jul 2026 13:14:58 +0300 Subject: [PATCH 7/9] fix: replace getEntityLookup() with Level.getEntities() LevelEntityGetter API + add missing EntityCollectionUtil.getEntityList() call --- .../sources/net/minecraft/world/level/Level.java.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index 4666a584..a12304ec 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -304,7 +304,7 @@ + @Override + public List getEntities(@Nullable Entity except, AABB area) { + List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); -+ ((ServerLevel)this).getEntityLookup().getEntities(except, area, list, EntitySelector.NO_SPECTATORS); ++ this.getEntities().getEntities(net.minecraft.world.level.entity.EntityTypeTest.forClass(Entity.class), area, EntitySelector.NO_SPECTATORS, list, Integer.MAX_VALUE); + return list; + } + // Gale end - use reusable entity list From a04586767d7c752ed4392ff0d7fce9d8e837c000 Mon Sep 17 00:00:00 2001 From: Toprak Date: Thu, 30 Jul 2026 13:19:55 +0300 Subject: [PATCH 8/9] fix: use LevelEntityGetter.get(...) not getEntities(...) --- .../sources/net/minecraft/world/level/Level.java.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index a12304ec..5e7a5e68 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -304,7 +304,7 @@ + @Override + public List getEntities(@Nullable Entity except, AABB area) { + List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); -+ this.getEntities().getEntities(net.minecraft.world.level.entity.EntityTypeTest.forClass(Entity.class), area, EntitySelector.NO_SPECTATORS, list, Integer.MAX_VALUE); ++ this.getEntities().get(net.minecraft.world.level.entity.EntityTypeTest.forClass(Entity.class), area, EntitySelector.NO_SPECTATORS, list, Integer.MAX_VALUE); + return list; + } + // Gale end - use reusable entity list From cdbeb64b4b193444ec0f5117c8da29a6dc1ff472 Mon Sep 17 00:00:00 2001 From: Toprak Date: Thu, 30 Jul 2026 13:23:43 +0300 Subject: [PATCH 9/9] fix build --- .../sources/net/minecraft/world/level/Level.java.patch | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index 5e7a5e68..855578f8 100644 --- a/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/gale-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -304,7 +304,12 @@ + @Override + public List getEntities(@Nullable Entity except, AABB area) { + List list = org.galemc.gale.util.entity.EntityCollectionUtil.getEntityList(); -+ this.getEntities().get(net.minecraft.world.level.entity.EntityTypeTest.forClass(Entity.class), area, EntitySelector.NO_SPECTATORS, list, Integer.MAX_VALUE); ++ this.getEntities().get(net.minecraft.world.level.entity.EntityTypeTest.forClass(Entity.class), area, (net.minecraft.util.AbortableIterationConsumer) entity -> { ++ if (entity != except && !entity.isSpectator()) { ++ list.add(entity); ++ } ++ return net.minecraft.util.AbortableIterationConsumer.Continuation.CONTINUE; ++ }); + return list; + } + // Gale end - use reusable entity list