From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:36:25 +0800 Subject: [PATCH] Optimize world generation chunk and block access This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java index 877498729c66de9aa6a27c9148f7494d7895615c..28386146cada17442d3b3f1517512b95ddcc6a9f 100644 --- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java +++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java @@ -83,6 +83,10 @@ public class WorldGenRegion implements WorldGenLevel { private Supplier currentlyGenerating; private final AtomicLong subTickCount = new AtomicLong(); private static final ResourceLocation WORLDGEN_REGION_RANDOM = new ResourceLocation("worldgen_region_random"); + // Leaves start - optimize world generation chunk and block access + private ChunkAccess[] chunksArr; + private int minChunkX, minChunkZ; + // Leaves end - optimize world generation chunk and block access public WorldGenRegion(ServerLevel world, List chunks, ChunkStatus status, int placementRadius) { this.generatingStatus = status; @@ -105,6 +109,11 @@ public class WorldGenRegion implements WorldGenLevel { this.lastPos = ((ChunkAccess) chunks.get(chunks.size() - 1)).getPos(); this.structureManager = world.structureManager().forWorldGenRegion(this); } + // Leaves start - optimize world generation chunk and block access + this.minChunkX = this.firstPos.x; + this.minChunkZ = this.firstPos.z; + this.chunksArr = chunks.toArray(new ChunkAccess[0]); + // Leaves end - optimize world generation chunk and block access } public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { @@ -122,8 +131,29 @@ public class WorldGenRegion implements WorldGenLevel { @Override public ChunkAccess getChunk(int chunkX, int chunkZ) { - return this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY); + // Leaves start - optimize world generation chunk and block access + if (!top.leavesmc.leaves.LeavesConfig.optimizeWorldGenerationAccess) { + return this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY); + } else { + int x = chunkX - this.minChunkX; + int z = chunkZ - this.minChunkZ; + int w = this.size; + + if (x >= 0 && z >= 0 && x < w && z < w) { + return this.chunksArr[x + z * w]; + } else { + throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ)); + } + } + // Leaves end - optimize world generation chunk and block access + } + + // Leaves start - optimize world generation chunk and block access + public ChunkAccess getChunk(BlockPos pos) { + // Skip checking chunk.getStatus().isAtLeast(ChunkStatus.EMPTY) here, because it is always true + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); } + // Leaves end - optimize world generation chunk and block access @Nullable @Override @@ -182,7 +212,21 @@ public class WorldGenRegion implements WorldGenLevel { @Override public BlockState getBlockState(BlockPos pos) { - return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); + // Leaves start - optimize world generation chunk and block access + if (!top.leavesmc.leaves.LeavesConfig.optimizeWorldGenerationAccess) { + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); + } else { + int x = SectionPos.blockToSectionCoord(pos.getX()) - this.minChunkX; + int z = SectionPos.blockToSectionCoord(pos.getZ()) - this.minChunkZ; + int w = this.size; + + if (x >= 0 && z >= 0 && x < w && z < w) { + return this.chunksArr[x + z * w].getBlockState(pos); + } else { + throw new NullPointerException("No chunk exists at " + new ChunkPos(pos)); + } + } + // Leaves end - optimize world generation chunk and block access } @Override diff --git a/src/main/java/top/leavesmc/leaves/lithium/common/util/Pos.java b/src/main/java/top/leavesmc/leaves/lithium/common/util/Pos.java new file mode 100644 index 0000000000000000000000000000000000000000..f1650846d080ab743aa324a3fe94447e2b3d7ece --- /dev/null +++ b/src/main/java/top/leavesmc/leaves/lithium/common/util/Pos.java @@ -0,0 +1,104 @@ + +package top.leavesmc.leaves.lithium.common.util; + +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.LevelHeightAccessor; + +public class Pos { + + public static class BlockCoord { + public static int getYSize(LevelHeightAccessor view) { + return view.getHeight(); + } + + public static int getMinY(LevelHeightAccessor view) { + return view.getMinBuildHeight(); + } + + public static int getMaxYInclusive(LevelHeightAccessor view) { + return view.getMaxBuildHeight() - 1; + } + + public static int getMaxYExclusive(LevelHeightAccessor view) { + return view.getMaxBuildHeight(); + } + + public static int getMaxInSectionCoord(int sectionCoord) { + return 15 + getMinInSectionCoord(sectionCoord); + } + + public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex) { + return getMaxInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex)); + } + + public static int getMinInSectionCoord(int sectionCoord) { + return SectionPos.sectionToBlockCoord(sectionCoord); + } + + public static int getMinYInSectionIndex(LevelHeightAccessor view, int sectionIndex) { + return getMinInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex)); + } + } + + public static class ChunkCoord { + public static int fromBlockCoord(int blockCoord) { + return SectionPos.blockToSectionCoord(blockCoord); + } + + public static int fromBlockSize(int i) { + return i >> 4; //same method as fromBlockCoord, just be clear about coord/size semantic difference + } + } + + public static class SectionYCoord { + public static int getNumYSections(LevelHeightAccessor view) { + return view.getSectionsCount(); + } + + public static int getMinYSection(LevelHeightAccessor view) { + return view.getMinSection(); + } + + public static int getMaxYSectionInclusive(LevelHeightAccessor view) { + return view.getMaxSection() - 1; + } + + public static int getMaxYSectionExclusive(LevelHeightAccessor view) { + return view.getMaxSection(); + } + + public static int fromSectionIndex(LevelHeightAccessor view, int sectionCoord) { + return sectionCoord + SectionYCoord.getMinYSection(view); + } + + public static int fromBlockCoord(int blockCoord) { + return SectionPos.blockToSectionCoord(blockCoord); + } + } + + public static class SectionYIndex { + public static int getNumYSections(LevelHeightAccessor view) { + return view.getSectionsCount(); + } + + public static int getMinYSectionIndex(LevelHeightAccessor view) { + return 0; + } + + public static int getMaxYSectionIndexInclusive(LevelHeightAccessor view) { + return view.getSectionsCount() - 1; + } + + public static int getMaxYSectionIndexExclusive(LevelHeightAccessor view) { + return view.getSectionsCount(); + } + + public static int fromSectionCoord(LevelHeightAccessor view, int sectionCoord) { + return sectionCoord - SectionYCoord.getMinYSection(view); + } + + public static int fromBlockCoord(LevelHeightAccessor view, int blockCoord) { + return fromSectionCoord(view, SectionPos.blockToSectionCoord(blockCoord)); + } + } +}