diff --git a/leaf-server/minecraft-patches/features/0281-Lithium-combined-heightmap-update.patch b/leaf-server/minecraft-patches/features/0281-Lithium-combined-heightmap-update.patch new file mode 100644 index 00000000..e652d7a5 --- /dev/null +++ b/leaf-server/minecraft-patches/features/0281-Lithium-combined-heightmap-update.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Wed, 30 Jul 2025 23:18:41 +0200 +Subject: [PATCH] Lithium: combined heightmap update + +This patch is based on the following mixins: +* "net/caffeinemc/mods/lithium/mixin/world/combined_heightmap_update/LevelChunkMixin" + +By: 2No2Name <2No2Name@web.de> +As part of: Lithium (https://github.com/CaffeineMC/lithium) +Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html) + +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index c3ecdd80efad340c9fa0ea6913db9a3362b53ad4..e429932a044647f931443c6761d1b39e4eb7665c 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -426,10 +426,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + } + // Leaf end - optimize random tick + Block block = state.getBlock(); +- this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(i, y, i2, state); ++ // Leaf start - Lithium - combined heightmap update ++ Heightmap heightmap0 = this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING); ++ Heightmap heightmap1 = this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES); ++ Heightmap heightmap2 = this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR); ++ Heightmap heightmap3 = this.heightmaps.get(Heightmap.Types.WORLD_SURFACE); ++ net.caffeinemc.mods.lithium.common.world.chunk.heightmap.CombinedHeightmapUpdate.updateHeightmaps(heightmap0, heightmap1, heightmap2, heightmap3, this, i, y, i2, state); ++ // Leaf end - Lithium - combined heightmap update + boolean hasOnlyAir1 = section.hasOnlyAir(); + if (hasOnlyAir != hasOnlyAir1) { + this.level.getChunkSource().getLightEngine().updateSectionStatus(pos, hasOnlyAir1); +diff --git a/net/minecraft/world/level/levelgen/Heightmap.java b/net/minecraft/world/level/levelgen/Heightmap.java +index f7b8637680e654dc0b3e8850d65081a1c565bb69..94ac77e269d84ede7f16e7595feedb103f8a1f35 100644 +--- a/net/minecraft/world/level/levelgen/Heightmap.java ++++ b/net/minecraft/world/level/levelgen/Heightmap.java +@@ -40,6 +40,12 @@ public class Heightmap { + this.data = new SimpleBitStorage(i, 256); + } + ++ // Leaf start - Lithium - combined heightmap update ++ public final Predicate isOpaque() { ++ return this.isOpaque; ++ } ++ // Leaf end - Lithium - combined heightmap update ++ + public static void primeHeightmaps(ChunkAccess chunk, Set types) { + if (!types.isEmpty()) { + int size = types.size(); +@@ -119,7 +125,7 @@ public class Heightmap { + return this.data.get(index) + this.chunk.getMinY(); + } + +- private void setHeight(int x, int z, int value) { ++ public void setHeight(int x, int z, int value) { + this.data.set(getIndex(x, z), value - this.chunk.getMinY()); + } + diff --git a/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/heightmap/CombinedHeightmapUpdate.java b/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/heightmap/CombinedHeightmapUpdate.java new file mode 100644 index 00000000..5cd1b1d9 --- /dev/null +++ b/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/heightmap/CombinedHeightmapUpdate.java @@ -0,0 +1,138 @@ +package net.caffeinemc.mods.lithium.common.world.chunk.heightmap; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.levelgen.Heightmap; + +import java.util.Objects; +import java.util.function.Predicate; + +public final class CombinedHeightmapUpdate { + public static void updateHeightmaps(Heightmap heightmap0, Heightmap heightmap1, Heightmap heightmap2, Heightmap heightmap3, LevelChunk worldChunk, final int x, final int y, final int z, BlockState state) { + final int height0 = heightmap0.getFirstAvailable(x, z); + final int height1 = heightmap1.getFirstAvailable(x, z); + final int height2 = heightmap2.getFirstAvailable(x, z); + final int height3 = heightmap3.getFirstAvailable(x, z); + int heightmapsToUpdate = 4; + if (y + 2 <= height0) { + heightmap0 = null; + heightmapsToUpdate--; + } + if (y + 2 <= height1) { + heightmap1 = null; + heightmapsToUpdate--; + } + if (y + 2 <= height2) { + heightmap2 = null; + heightmapsToUpdate--; + } + if (y + 2 <= height3) { + heightmap3 = null; + heightmapsToUpdate--; + } + + if (heightmapsToUpdate == 0) { + return; + } + + Predicate blockPredicate0 = heightmap0 == null ? null : Objects.requireNonNull(heightmap0.isOpaque()); + Predicate blockPredicate1 = heightmap1 == null ? null : Objects.requireNonNull(heightmap1.isOpaque()); + Predicate blockPredicate2 = heightmap2 == null ? null : Objects.requireNonNull(heightmap2.isOpaque()); + Predicate blockPredicate3 = heightmap3 == null ? null : Objects.requireNonNull(heightmap3.isOpaque()); + + if (heightmap0 != null) { + if (blockPredicate0.test(state)) { + if (y >= height0) { + heightmap0.setHeight(x, z, y + 1); + } + heightmap0 = null; + heightmapsToUpdate--; + } else if (height0 != y + 1) { + heightmap0 = null; + heightmapsToUpdate--; + } + } + if (heightmap1 != null) { + if (blockPredicate1.test(state)) { + if (y >= height1) { + heightmap1.setHeight(x, z, y + 1); + } + heightmap1 = null; + heightmapsToUpdate--; + } else if (height1 != y + 1) { + heightmap1 = null; + heightmapsToUpdate--; + } + } + if (heightmap2 != null) { + if (blockPredicate2.test(state)) { + if (y >= height2) { + heightmap2.setHeight(x, z, y + 1); + } + heightmap2 = null; + heightmapsToUpdate--; + } else if (height2 != y + 1) { + heightmap2 = null; + heightmapsToUpdate--; + } + } + if (heightmap3 != null) { + if (blockPredicate3.test(state)) { + if (y >= height3) { + heightmap3.setHeight(x, z, y + 1); + } + heightmap3 = null; + heightmapsToUpdate--; + } else if (height3 != y + 1) { + heightmap3 = null; + heightmapsToUpdate--; + } + } + + + if (heightmapsToUpdate == 0) { + return; + } + + BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos(); + int bottomY = worldChunk.getMinY(); + + for (int searchY = y - 1; searchY >= bottomY && heightmapsToUpdate > 0; --searchY) { + mutable.set(x, searchY, z); + BlockState blockState = worldChunk.getBlockState(mutable); + if (heightmap0 != null && blockPredicate0.test(blockState)) { + heightmap0.setHeight(x, z, searchY + 1); + heightmap0 = null; + heightmapsToUpdate--; + } + if (heightmap1 != null && blockPredicate1.test(blockState)) { + heightmap1.setHeight(x, z, searchY + 1); + heightmap1 = null; + heightmapsToUpdate--; + } + if (heightmap2 != null && blockPredicate2.test(blockState)) { + heightmap2.setHeight(x, z, searchY + 1); + heightmap2 = null; + heightmapsToUpdate--; + } + if (heightmap3 != null && blockPredicate3.test(blockState)) { + heightmap3.setHeight(x, z, searchY + 1); + heightmap3 = null; + heightmapsToUpdate--; + } + } + if (heightmap0 != null) { + heightmap0.setHeight(x, z, bottomY); + } + if (heightmap1 != null) { + heightmap1.setHeight(x, z, bottomY); + } + if (heightmap2 != null) { + heightmap2.setHeight(x, z, bottomY); + } + if (heightmap3 != null) { + heightmap3.setHeight(x, z, bottomY); + } + } +}