From 0f2ff2037573d54015fbfe4d0fadc8c1f2b24585 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 10 Jun 2024 21:17:57 -0500 Subject: [PATCH 01/17] Re-arange ChunkLoader --- .../mimicObject/ChunkLoader.java | 266 +++++++++--------- 1 file changed, 135 insertions(+), 131 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index 5c6ef0fa1..b82370dfb 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -100,138 +100,7 @@ public class ChunkLoader private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks"; private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER; - #if MC_VER >= MC_1_18_2 - private static BlendingData readBlendingData(CompoundTag chunkData) - { - BlendingData blendingData = null; - if (chunkData.contains("blending_data", 10)) - { - @SuppressWarnings({"unchecked", "rawtypes"}) - Dynamic blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data")); - blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null); - } - return blendingData; - } - #endif - private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData) - { - #if MC_VER >= MC_1_18_2 - #if MC_VER < MC_1_19_4 - Registry biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); - #else - Registry biomes = level.registryAccess().registryOrThrow(Registries.BIOME); - #endif - #if MC_VER < MC_1_18_2 - Codec> biomeCodec = PalettedContainer.codec( - biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS)); - #elif MC_VER < MC_1_19_2 - Codec>> biomeCodec = PalettedContainer.codec( - biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS)); - #else - Codec>> biomeCodec = PalettedContainer.codecRW( - biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS)); - #endif - #endif - int i = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif - LevelChunkSection[] chunkSections = new LevelChunkSection[i]; - - boolean isLightOn = chunkData.getBoolean("isLightOn"); - boolean hasSkyLight = level.dimensionType().hasSkyLight(); - ListTag tagSections = chunkData.getList("Sections", 10); - if (tagSections.isEmpty()) tagSections = chunkData.getList("sections", 10); - - for (int j = 0; j < tagSections.size(); ++j) - { - CompoundTag tagSection = tagSections.getCompound(j); - int sectionYPos = tagSection.getByte("Y"); - - #if MC_VER < MC_1_18_2 - if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12)) - { - LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4); - levelChunkSection.getStates().read(tagSection.getList("Palette", 10), - tagSection.getLongArray("BlockStates")); - levelChunkSection.recalcBlockCounts(); - if (!levelChunkSection.isEmpty()) - chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ] - = levelChunkSection; - } - #else - int sectionId = level.getSectionIndexFromSectionY(sectionYPos); - if (sectionId >= 0 && sectionId < chunkSections.length) - { - PalettedContainer blockStateContainer; - #if MC_VER < MC_1_18_2 - PalettedContainer biomeContainer; - #else - PalettedContainer> biomeContainer; - #endif - - blockStateContainer = tagSection.contains("block_states", 10) - ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)) - #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif - : new PalettedContainer(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); - - #if MC_VER < MC_1_18_2 - biomeContainer = tagSection.contains("biomes", 10) - ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error) - : new PalettedContainer(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); - #else - - biomeContainer = tagSection.contains("biomes", 10) - ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)) - #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif - : new PalettedContainer>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); - #endif - - #if MC_VER < MC_1_20_1 - chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer); - #else - chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer); - #endif - } - #endif - - } - return chunkSections; - } - - private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) - { - CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps"); - for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter()) - { - String heightmap = type.getSerializationKey(); - if (tagHeightmaps.contains(heightmap, 12)) - chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap)); - } - Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter()); - } - - private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData) - { - ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9); - for (int n = 0; n < tagPostProcessings.size(); ++n) - { - ListTag listTag3 = tagPostProcessings.getList(n); - for (int o = 0; o < listTag3.size(); ++o) - { - chunk.addPackedPostProcess(listTag3.getShort(o), n); - } - } - } - - public static #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType #else ChunkType #endif readChunkType(CompoundTag tagLevel) - { - ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status")); - if (chunkStatus != null) - { - return chunkStatus.getChunkType(); - } - - return #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK; #else ChunkType.PROTOCHUNK; #endif - } public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData) { @@ -349,6 +218,141 @@ public class ChunkLoader readPostPocessings(chunk, chunkData); return chunk; } + private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData) + { + #if MC_VER >= MC_1_18_2 + #if MC_VER < MC_1_19_4 + Registry biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); + #else + Registry biomes = level.registryAccess().registryOrThrow(Registries.BIOME); + #endif + #if MC_VER < MC_1_18_2 + Codec> biomeCodec = PalettedContainer.codec( + biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS)); + #elif MC_VER < MC_1_19_2 + Codec>> biomeCodec = PalettedContainer.codec( + biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS)); + #else + Codec>> biomeCodec = PalettedContainer.codecRW( + biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS)); + #endif + #endif + int i = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif + LevelChunkSection[] chunkSections = new LevelChunkSection[i]; + + boolean isLightOn = chunkData.getBoolean("isLightOn"); + boolean hasSkyLight = level.dimensionType().hasSkyLight(); + ListTag tagSections = chunkData.getList("Sections", 10); + if (tagSections.isEmpty()) tagSections = chunkData.getList("sections", 10); + + for (int j = 0; j < tagSections.size(); ++j) + { + CompoundTag tagSection = tagSections.getCompound(j); + int sectionYPos = tagSection.getByte("Y"); + + #if MC_VER < MC_1_18_2 + if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12)) + { + LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4); + levelChunkSection.getStates().read(tagSection.getList("Palette", 10), + tagSection.getLongArray("BlockStates")); + levelChunkSection.recalcBlockCounts(); + if (!levelChunkSection.isEmpty()) + chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ] + = levelChunkSection; + } + #else + int sectionId = level.getSectionIndexFromSectionY(sectionYPos); + if (sectionId >= 0 && sectionId < chunkSections.length) + { + PalettedContainer blockStateContainer; + #if MC_VER < MC_1_18_2 + PalettedContainer biomeContainer; + #else + PalettedContainer> biomeContainer; + #endif + + blockStateContainer = tagSection.contains("block_states", 10) + ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)) + #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif + : new PalettedContainer(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); + + #if MC_VER < MC_1_18_2 + biomeContainer = tagSection.contains("biomes", 10) + ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error) + : new PalettedContainer(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + #else + + biomeContainer = tagSection.contains("biomes", 10) + ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)) + #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif + : new PalettedContainer>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + #endif + + #if MC_VER < MC_1_20_1 + chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer); + #else + chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer); + #endif + } + #endif + + } + return chunkSections; + } + private static #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType #else ChunkType #endif readChunkType(CompoundTag tagLevel) + { + ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status")); + if (chunkStatus != null) + { + return chunkStatus.getChunkType(); + } + + return #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK; #else ChunkType.PROTOCHUNK; #endif + } + private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) + { + CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps"); + for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter()) + { + String heightmap = type.getSerializationKey(); + if (tagHeightmaps.contains(heightmap, 12)) + chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap)); + } + Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter()); + } + private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData) + { + ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9); + for (int n = 0; n < tagPostProcessings.size(); ++n) + { + ListTag listTag3 = tagPostProcessings.getList(n); + for (int o = 0; o < listTag3.size(); ++o) + { + chunk.addPackedPostProcess(listTag3.getShort(o), n); + } + } + } + #if MC_VER >= MC_1_18_2 + private static BlendingData readBlendingData(CompoundTag chunkData) + { + BlendingData blendingData = null; + if (chunkData.contains("blending_data", 10)) + { + @SuppressWarnings({"unchecked", "rawtypes"}) + Dynamic blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data")); + blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null); + } + return blendingData; + } + #endif + + + + public static LevelChunk readLight(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData) + { + return null; + } private static void logErrors(ChunkPos chunkPos, int i, String string) { From 7293677ddb026046b64ad05776a172c70058eb00 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 10 Jun 2024 21:32:14 -0500 Subject: [PATCH 02/17] Batch Generation Environment refactoring --- .../BatchGenerationEnvironment.java | 220 +++++++++--------- .../mimicObject/DhLitWorldGenRegion.java | 4 +- 2 files changed, 116 insertions(+), 108 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index 59ffa4c5f..36cb6f1e7 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -109,8 +109,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"), () -> Config.Client.Advanced.Logging.logWorldGenLoadEvent.get()); - //TODO: Make actual proper support for StarLight - public static class PerfCalculator { private static final String[] TIME_NAMES = { @@ -294,6 +292,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv + //=================// + // synchronization // + //=================// public T joinSync(CompletableFuture future) { @@ -368,103 +369,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv } } - private static ProtoChunk EmptyChunk(ServerLevel level, ChunkPos chunkPos) - { - return new ProtoChunk(chunkPos, UpgradeData.EMPTY - #if MC_VER >= MC_1_17_1 , level #endif - #if MC_VER >= MC_1_18_2 , level.registryAccess().registryOrThrow( - #if MC_VER < MC_1_19_4 - Registry.BIOME_REGISTRY - #else - Registries.BIOME - #endif - ), null #endif - ); - - } - public ChunkAccess loadOrMakeChunk(ChunkPos chunkPos) - { - ServerLevel level = this.params.level; - - - - //====================// - // get the chunk data // - //====================// - - CompoundTag chunkData = null; - try - { - IOWorker ioWorker = level.getChunkSource().chunkMap.worker; - - #if MC_VER <= MC_1_18_2 - chunkData = ioWorker.load(chunkPos); - #else - - // timeout should prevent locking up the thread if the ioWorker dies or has issues - int maxGetTimeInSec = Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get(); - CompletableFuture> future = ioWorker.loadAsync(chunkPos); - try - { - Optional data = future.get(maxGetTimeInSec, TimeUnit.SECONDS); - if (data.isPresent()) - { - chunkData = data.get(); - } - } - catch (Exception e) - { - LOAD_LOGGER.warn("Unable to get chunk at pos ["+chunkPos+"] after ["+maxGetTimeInSec+"] milliseconds.", e); - future.cancel(true); - } - #endif - } - catch (Exception e) - { - LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e); - } - - - - //========================// - // convert the chunk data // - //========================// - - if (chunkData == null) - { - return EmptyChunk(level, chunkPos); - } - else - { - try - { - LOAD_LOGGER.info("DistantHorizons: Loading chunk [" + chunkPos + "] from disk."); - return ChunkLoader.read(level, chunkPos, chunkData); - } - catch (Exception e) - { - LOAD_LOGGER.error( - "DistantHorizons: couldn't load or make chunk at ["+chunkPos+"]." + - "Please try optimizing your world to fix this issue. \n" + - "World optimization can be done from the singleplayer world selection screen.\n" + - "Error: ["+e.getMessage()+"]." - , e); - - return EmptyChunk(level, chunkPos); - } - } - } - private static ArrayGridList GetCutoutFrom(ArrayGridList total, int border) - { - return new ArrayGridList<>(total, border, total.gridSize - border); - } - - private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) - { - return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step)); - } + //==================// + // world generation // + //==================// public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException { @@ -487,7 +396,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv adaptor = new LightGetterAdaptor(this.params.level); lightEngine = new DummyLightEngine(adaptor); - EmptyChunkGenerator generator = (int x, int z) -> + IEmptyChunkGeneratorFunc emptyChunkGeneratorFunc = (int x, int z) -> { ChunkPos chunkPos = new ChunkPos(x, z); ChunkAccess target = null; @@ -509,12 +418,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv } return target; }; - - totalChunks = new ArrayGridList<>(refSize, (x, z) -> generator.generate(x + refPosX, z + refPosZ)); + totalChunks = new ArrayGridList<>(refSize, (x, z) -> emptyChunkGeneratorFunc.generate(x + refPosX, z + refPosZ)); genEvent.refreshTimeout(); region = new DhLitWorldGenRegion(params.level, lightEngine, totalChunks, - ChunkStatus.STRUCTURE_STARTS, refSize / 2, generator); + ChunkStatus.STRUCTURE_STARTS, refSize / 2, emptyChunkGeneratorFunc); adaptor.setRegion(region); genEvent.threadedParam.makeStructFeat(region, params); @@ -594,6 +502,91 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv PREF_LOGGER.infoInc("{}", genEvent.timer); } } + private ChunkAccess loadOrMakeChunk(ChunkPos chunkPos) + { + ServerLevel level = this.params.level; + + + + //====================// + // get the chunk data // + //====================// + + CompoundTag chunkData = null; + try + { + IOWorker ioWorker = level.getChunkSource().chunkMap.worker; + + #if MC_VER <= MC_1_18_2 + chunkData = ioWorker.load(chunkPos); + #else + + // timeout should prevent locking up the thread if the ioWorker dies or has issues + int maxGetTimeInSec = Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get(); + CompletableFuture> future = ioWorker.loadAsync(chunkPos); + try + { + Optional data = future.get(maxGetTimeInSec, TimeUnit.SECONDS); + if (data.isPresent()) + { + chunkData = data.get(); + } + } + catch (Exception e) + { + LOAD_LOGGER.warn("Unable to get chunk at pos ["+chunkPos+"] after ["+maxGetTimeInSec+"] milliseconds.", e); + future.cancel(true); + } + #endif + } + catch (Exception e) + { + LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e); + } + + + + //========================// + // convert the chunk data // + //========================// + + if (chunkData == null) + { + return CreateEmptyChunk(level, chunkPos); + } + else + { + try + { + LOAD_LOGGER.info("DistantHorizons: Loading chunk [" + chunkPos + "] from disk."); + return ChunkLoader.read(level, chunkPos, chunkData); + } + catch (Exception e) + { + LOAD_LOGGER.error( + "DistantHorizons: couldn't load or make chunk at ["+chunkPos+"]." + + "Please try optimizing your world to fix this issue. \n" + + "World optimization can be done from the singleplayer world selection screen.\n" + + "Error: ["+e.getMessage()+"]." + , e); + + return CreateEmptyChunk(level, chunkPos); + } + } + } + private static ProtoChunk CreateEmptyChunk(ServerLevel level, ChunkPos chunkPos) + { + return new ProtoChunk(chunkPos, UpgradeData.EMPTY + #if MC_VER >= MC_1_17_1 , level #endif + #if MC_VER >= MC_1_18_2 , level.registryAccess().registryOrThrow( + #if MC_VER < MC_1_19_4 + Registry.BIOME_REGISTRY + #else + Registries.BIOME + #endif + ), null #endif + ); + } public void generateDirect( GenerationEvent genEvent, ArrayGridList chunksToGenerate, int border, @@ -722,12 +715,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv genEvent.refreshTimeout(); } } + private static ArrayGridList GetCutoutFrom(ArrayGridList total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); } + private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step)); } - public interface EmptyChunkGenerator - { - ChunkAccess generate(int x, int z); - - } @Override public int getEventCount() { return this.generationEventList.size(); } @@ -776,6 +766,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv return genEvent.future; } + + + //================// + // helper methods // + //================// + /** * Called before code that may run for an extended period of time.
* This is necessary to allow canceling world gen since waiting @@ -789,4 +785,16 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv } } + + + //================// + // helper classes // + //================// + + @FunctionalInterface + public interface IEmptyChunkGeneratorFunc + { + ChunkAccess generate(int x, int z); + } + } \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java index 4f66f315c..8ee62a90f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java @@ -71,7 +71,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion public final DummyLightEngine lightEngine; - public final BatchGenerationEnvironment.EmptyChunkGenerator generator; + public final BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator; public final int writeRadius; public final int size; @@ -114,7 +114,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion public DhLitWorldGenRegion( ServerLevel serverLevel, DummyLightEngine lightEngine, List chunkList, ChunkStatus chunkStatus, int writeRadius, - BatchGenerationEnvironment.EmptyChunkGenerator generator) + BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator) { super(serverLevel, chunkList #if MC_VER >= MC_1_17_1 , chunkStatus, writeRadius #endif ); this.firstPos = chunkList.get(0).getPos(); From cc4a69c10cb02f1eb1ed95bec0633e3a3927b451 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 11 Jun 2024 18:35:02 -0500 Subject: [PATCH 03/17] Move shared ChunkWrapper code form Main to Core --- .../wrappers/chunk/ChunkLightStorage.java | 239 ------------------ .../common/wrappers/chunk/ChunkWrapper.java | 98 +------ coreSubProjects | 2 +- 3 files changed, 15 insertions(+), 324 deletions(-) delete mode 100644 common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkLightStorage.java diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkLightStorage.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkLightStorage.java deleted file mode 100644 index 405c0fb95..000000000 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkLightStorage.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * This file is part of the Distant Horizons mod - * licensed under the GNU LGPL v3 License. - * - * Copyright (C) 2020-2023 James Seibel - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.seibel.distanthorizons.common.wrappers.chunk; - -import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Compact, efficient storage for light levels. - * all blocks only take up 4 bits in total, - * and if a 16x16x16 area is detected to have the same light level in all positions, - * then we store a single byte for that light level, instead of 2 kilobytes. - * - * @author Builderb0y -*/ -public class ChunkLightStorage -{ - /** the minimum Y level in the chunk which this storage is storing light levels for (inclusive). */ - public int minY; - /** the maximum Y level in the chunk which this storage is storing light levels for (exclusive). */ - public int maxY; - - /** the data stored in this storage, split up into 16x16x16 areas. */ - public LightSection[] lightSections; - - /** - * If the get method is called on a Y position above what's stored - * this value will be returned.

- * - * This needs to be manually defined since sky and block lights behave differently - * for values both above and below what's defined. - */ - public int aboveMaxYValue; - /** @see ChunkLightStorage#aboveMaxYValue */ - public int belowMinYValue; - - - - //=============// - // constructor // - //=============// - - public ChunkLightStorage(int minY, int maxY, int aboveMaxYValue, int belowMinYValue) - { - this.minY = minY; - this.maxY = maxY; - - this.aboveMaxYValue = aboveMaxYValue; - this.belowMinYValue = belowMinYValue; - } - - - - //=====================// - // getters and setters // - //=====================// - - public int get(int x, int y, int z) - { - if (y < this.minY) - { - return this.belowMinYValue; - } - else if (y >= this.maxY) - { - return this.aboveMaxYValue; - } - - - if (this.lightSections != null) - { - LightSection lightSection = this.lightSections[BitShiftUtil.divideByPowerOfTwo(y - this.minY, 4)]; - if (lightSection != null) - { - return lightSection.get(x, y, z); - } - } - - return 0; - } - - public void set(int x, int y, int z, int lightLevel) - { - if (y < this.minY || y >= this.maxY) - { - return; - } - - //populate array if it doesn't exist. - if (this.lightSections == null) - { - this.lightSections = new LightSection[BitShiftUtil.divideByPowerOfTwo(this.maxY - this.minY, 4)]; - } - - int index = (y - this.minY) >> 4; - LightSection lightSection = this.lightSections[index]; - - //populate lightSection in array if it doesn't exist. - if (lightSection == null) - { - lightSection = new LightSection(0); - this.lightSections[index] = lightSection; - } - lightSection.set(x, y, z, lightLevel); - } - - - - //================// - // helper classes // - //================// - - public static class LightSection - { - public byte constantValue; - public long[] data; - public short[] counts; - - public LightSection(int initialValue) - { - this.constantValue = (byte) (initialValue); - this.counts = new short[16]; - this.counts[initialValue] = 16 * 16 * 16; - } - - public int get(int x, int y, int z) - { - if (this.constantValue >= 0) - { - return this.constantValue; - } - - x &= 15; - y &= 15; - z &= 15; - long bits = this.data[(z << 4) | x]; - return ((int) (bits >>> (y << 2))) & 15; - } - - public void set(int x, int y, int z, int lightLevel) - { - int oldLightLevel = -1; - if (this.constantValue >= 0) - { - oldLightLevel = this.constantValue; - - //if the light level didn't change, then there's nothing to do. - if (oldLightLevel == lightLevel) return; - - //if we are a constant value and need to change something, - //then that means we need to convert to a non-constant value. - this.data = DataRecycler.get(); - - //repeat oldLightLevel 16 times as a bit pattern. - long payload = oldLightLevel; - payload |= payload << 4; - payload |= payload << 8; - payload |= payload << 16; - payload |= payload << 32; - - //fill our data with our constant value. - Arrays.fill(this.data, payload); - - //we are no longer a constant value. - this.constantValue = -1; - } - - x &= 15; - y &= 15; - z &= 15; - int index = (z << 4) | x; - long bits = this.data[index]; - //if we weren't a constant value before, now's the time to initialize oldLightLevel. - if (oldLightLevel < 0) - { - oldLightLevel = ((int) (bits >>> (y << 2))) & 15; - } - //clear the 4 bits that correspond to the light level at x, y, z... - bits &= ~(15L << (y << 2)); - //...and then re-populate those bits with the new light level. - bits |= ((long) (lightLevel)) << (y << 2); - //store the updated bits in our data. - this.data[index] = bits; - - //we have one less of the old light level... - this.counts[oldLightLevel]--; - //...and one more of the new level. - //if the number associated with the new level is now 4096 (AKA 16 ^ 3), - //then this implies every position in this section has the same light level, - //and therefore we can convert back to a constant value. - if (++this.counts[lightLevel] == 4096) - { - this.constantValue = (byte) (lightLevel); - DataRecycler.reclaim(this.data); - this.data = null; - } - } - - } - - static class DataRecycler - { - private static final ArrayList recycled = new ArrayList<>(256); - - static synchronized long[] get() - { - if (recycled.isEmpty()) - { - return new long[256]; - } - else - { - return recycled.remove(recycled.size() - 1); - } - } - - static synchronized void reclaim(long[] data) { if (recycled.size() < 256) recycled.add(data); } - } - -} \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index ee6c373df..321d02050 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -25,13 +25,12 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.Dh import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import com.seibel.distanthorizons.coreapi.ModInfo; import net.minecraft.client.multiplayer.ClientChunkCache; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; @@ -83,9 +82,6 @@ public class ChunkWrapper implements IChunkWrapper { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - /** useful for debugging, but can slow down chunk operations quite a bit due to being called every time. */ - private static final boolean RUN_RELATIVE_POS_INDEX_VALIDATION = ModInfo.IS_DEV_BUILD; - /** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */ private static final ThreadLocal MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos()); @@ -152,26 +148,30 @@ public class ChunkWrapper implements IChunkWrapper //=========// @Override - public int getHeight() + public int getHeight() { return getHeight(this.chunk); } + public static int getHeight(ChunkAccess chunk) { #if MC_VER < MC_1_17_1 return 255; #else - return this.chunk.getHeight(); + return chunk.getHeight(); #endif } @Override - public int getMinBuildHeight() + public int getMinBuildHeight() { return getMinBuildHeight(this.chunk); } + public static int getMinBuildHeight(ChunkAccess chunk) { #if MC_VER < MC_1_17_1 return 0; #else - return this.chunk.getMinBuildHeight(); + return chunk.getMinBuildHeight(); #endif } + @Override - public int getMaxBuildHeight() { return this.chunk.getMaxBuildHeight(); } + public int getMaxBuildHeight() { return getMaxBuildHeight(this.chunk); } + public static int getMaxBuildHeight(ChunkAccess chunk) { return chunk.getMaxBuildHeight(); } @Override public int getMinNonEmptyHeight() @@ -301,9 +301,6 @@ public class ChunkWrapper implements IChunkWrapper @Override public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); } - @Override - public long getLongChunkPos() { return this.chunk.getPos().toLong(); } - @Override public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; } @@ -364,13 +361,11 @@ public class ChunkWrapper implements IChunkWrapper { if (this.blockLightStorage == null) { - this.blockLightStorage = new ChunkLightStorage( - this.getMinBuildHeight(), this.getMaxBuildHeight(), - // positions above and below the handled area should be unlit - LodUtil.MIN_MC_LIGHT, LodUtil.MIN_MC_LIGHT); + this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(this); } return this.blockLightStorage; } + public void setBlockLightStorage(ChunkLightStorage lightStorage) { this.blockLightStorage = lightStorage; } @Override @@ -390,13 +385,11 @@ public class ChunkWrapper implements IChunkWrapper { if (this.skyLightStorage == null) { - this.skyLightStorage = new ChunkLightStorage( - this.getMinBuildHeight(), this.getMaxBuildHeight(), - // positions above should be lit but positions below should be unlit - LodUtil.MAX_MC_LIGHT, LodUtil.MIN_MC_LIGHT); + this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(this); } return this.skyLightStorage; } + public void setSkyLightStorage(ChunkLightStorage lightStorage) { this.skyLightStorage = lightStorage; } @Override @@ -492,8 +485,6 @@ public class ChunkWrapper implements IChunkWrapper return true; } - public LevelReader getColorResolver() { return this.lightSource; } - @Override public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); } @@ -573,65 +564,4 @@ public class ChunkWrapper implements IChunkWrapper #endif - - //================// - // helper methods // - //================// - - /** used to prevent accidentally attempting to get/set values outside this chunk's boundaries */ - private void throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(int x, int y, int z) throws IndexOutOfBoundsException - { - if (!RUN_RELATIVE_POS_INDEX_VALIDATION) - { - return; - } - - - // FIXME +1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the constructor - int minHeight = this.getMinBuildHeight(); - int maxHeight = this.getMaxBuildHeight() + 1; - - if (x < 0 || x >= LodUtil.CHUNK_WIDTH - || z < 0 || z >= LodUtil.CHUNK_WIDTH - || y < minHeight || y > maxHeight) - { - String errorMessage = "Relative position [" + x + "," + y + "," + z + "] out of bounds. \n" + - "X/Z must be between 0 and 15 (inclusive) \n" + - "Y must be between [" + minHeight + "] and [" + maxHeight + "] (inclusive)."; - throw new IndexOutOfBoundsException(errorMessage); - } - } - - - /** - * Converts a 3D position into a 1D array index.

- * - * Source:
- * stackoverflow - */ - public int relativeBlockPosToIndex(int xRel, int y, int zRel) - { - int yRel = y - this.getMinBuildHeight(); - return (zRel * LodUtil.CHUNK_WIDTH * this.getHeight()) + (yRel * LodUtil.CHUNK_WIDTH) + xRel; - } - - /** - * Converts a 3D position into a 1D array index.

- * - * Source:
- * stackoverflow - */ - public DhBlockPos indexToRelativeBlockPos(int index) - { - final int zRel = index / (LodUtil.CHUNK_WIDTH * this.getHeight()); - index -= (zRel * LodUtil.CHUNK_WIDTH * this.getHeight()); - - final int y = index / LodUtil.CHUNK_WIDTH; - final int yRel = y + this.getMinBuildHeight(); - - final int xRel = index % LodUtil.CHUNK_WIDTH; - return new DhBlockPos(xRel, yRel, zRel); - } - - } diff --git a/coreSubProjects b/coreSubProjects index e011ce3ee..97b86d69c 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit e011ce3ee065fa195a694495ec54d5f446520879 +Subproject commit 97b86d69c4031bf575280e8b3e30b8e3470598d9 From 96b4c1a9e8aa5ec0b208780c21a4587b6fab28c3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 11 Jun 2024 20:22:13 -0500 Subject: [PATCH 04/17] Use existing lighting for pre-generated chunks --- .../BatchGenerationEnvironment.java | 97 ++++++++---- .../mimicObject/ChunkLoader.java | 144 +++++++++++++++++- coreSubProjects | 2 +- 3 files changed, 214 insertions(+), 29 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index 36cb6f1e7..4f459eeb9 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -35,6 +35,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.objects.EventTimer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.gridList.ArrayGridList; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvironmentWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -381,7 +382,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv ArrayGridList chunkWrapperList; DhLitWorldGenRegion region; - DummyLightEngine lightEngine; + DummyLightEngine dummyLightEngine; LightGetterAdaptor adaptor; int borderSize = MaxBorderNeeded; @@ -394,49 +395,94 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv ArrayGridList totalChunks; adaptor = new LightGetterAdaptor(this.params.level); - lightEngine = new DummyLightEngine(adaptor); + dummyLightEngine = new DummyLightEngine(adaptor); + + + //=============================// + // try getting existing chunks // + //=============================// + + HashMap chunkSkyLightingByDhPos = new HashMap<>(); + HashMap chunkBlockLightingByDhPos = new HashMap<>(); IEmptyChunkGeneratorFunc emptyChunkGeneratorFunc = (int x, int z) -> { ChunkPos chunkPos = new ChunkPos(x, z); - ChunkAccess target = null; + DhChunkPos dhChunkPos = new DhChunkPos(x, z); + ChunkAccess newChunk = null; try { - target = this.loadOrMakeChunk(chunkPos); + // get the chunk + CompoundTag chunkData = this.getChunkNbtData(chunkPos); + newChunk = this.loadOrMakeChunk(chunkPos, chunkData); + + // get chunk lighting + ChunkLoader.CombinedChunkLightStorage combinedLights = ChunkLoader.readLight(newChunk, chunkData); + if (combinedLights != null) + { + chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage); + chunkBlockLightingByDhPos.put(dhChunkPos, combinedLights.blockLightStorage); + } } - catch (RuntimeException e2) + catch (RuntimeException loadChunkError) { // Continue... } - if (target == null) + if (newChunk == null) { - target = new ProtoChunk(chunkPos, UpgradeData.EMPTY - #if MC_VER >= MC_1_17_1 , params.level #endif - #if MC_VER >= MC_1_18_2 , params.biomes, null #endif + newChunk = new ProtoChunk(chunkPos, UpgradeData.EMPTY + #if MC_VER >= MC_1_17_1 , this.params.level #endif + #if MC_VER >= MC_1_18_2 , this.params.biomes, null #endif ); } - return target; + return newChunk; }; totalChunks = new ArrayGridList<>(refSize, (x, z) -> emptyChunkGeneratorFunc.generate(x + refPosX, z + refPosZ)); genEvent.refreshTimeout(); - region = new DhLitWorldGenRegion(params.level, lightEngine, totalChunks, + region = new DhLitWorldGenRegion(this.params.level, dummyLightEngine, totalChunks, ChunkStatus.STRUCTURE_STARTS, refSize / 2, emptyChunkGeneratorFunc); adaptor.setRegion(region); - genEvent.threadedParam.makeStructFeat(region, params); + genEvent.threadedParam.makeStructFeat(region, this.params); + + //=======================// + // create chunk wrappers // + //=======================// + chunkWrapperList = new ArrayGridList<>(totalChunks.gridSize); totalChunks.forEachPos((x, z) -> { ChunkAccess chunk = totalChunks.get(x, z); if (chunk != null) { - chunkWrapperList.set(x, z, new ChunkWrapper(chunk, region, serverlevel.getLevelWrapper())); + // wrap the chunk + ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, region, this.serverlevel.getLevelWrapper()); + chunkWrapperList.set(x, z, chunkWrapper); + + // try getting the chunk lighting + if (chunkBlockLightingByDhPos.containsKey(chunkWrapper.getChunkPos())) + { + chunkWrapper.setBlockLightStorage(chunkBlockLightingByDhPos.get(chunkWrapper.getChunkPos())); + chunkWrapper.setSkyLightStorage(chunkSkyLightingByDhPos.get(chunkWrapper.getChunkPos())); + chunkWrapper.setUseDhLighting(true); + chunkWrapper.setIsDhLightCorrect(true); + } + else + { + int k = 0; + } } }); + + + //=================// + // generate chunks // + //=================// + this.generateDirect(genEvent, chunkWrapperList, borderSize, genEvent.targetGenerationStep, region); genEvent.timer.nextEvent("cleanup"); } @@ -502,16 +548,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv PREF_LOGGER.infoInc("{}", genEvent.timer); } } - private ChunkAccess loadOrMakeChunk(ChunkPos chunkPos) + private CompoundTag getChunkNbtData(ChunkPos chunkPos) { ServerLevel level = this.params.level; - - - //====================// - // get the chunk data // - //====================// - CompoundTag chunkData = null; try { @@ -544,11 +584,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e); } - - - //========================// - // convert the chunk data // - //========================// + return chunkData; + } + private ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, CompoundTag chunkData) + { + ServerLevel level = this.params.level; if (chunkData == null) { @@ -708,8 +748,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv // if this isn't done everything else afterward may fail Heightmap.primeHeightmaps(((ChunkWrapper)centerChunk).getChunk(), ChunkStatus.FEATURES.heightmapsAfter()); - // populate the lighting - DhLightingEngine.INSTANCE.lightChunk(centerChunk, iChunkWrapperList, maxSkyLight); + // pre-generated chunks should have lighting but new ones won't + if (!centerChunk.isLightCorrect()) + { + DhLightingEngine.INSTANCE.lightChunk(centerChunk, iChunkWrapperList, maxSkyLight); + } } genEvent.refreshTimeout(); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index b82370dfb..1a7ce278b 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -22,9 +22,14 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; import com.google.common.collect.Maps; import com.mojang.serialization.Codec; import com.mojang.serialization.Dynamic; +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; @@ -44,6 +49,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.*; @@ -100,8 +106,14 @@ public class ChunkLoader private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks"; private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER; + private static boolean lightingSectionErrorLogged = false; + + //============// + // read chunk // + //============// + public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData) { #if MC_VER < MC_1_18_2 @@ -349,9 +361,121 @@ public class ChunkLoader - public static LevelChunk readLight(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData) + //=====================// + // read chunk lighting // + //=====================// + + /** + * https://minecraft.wiki/w/Chunk_format + */ + public static CombinedChunkLightStorage readLight(ChunkAccess chunk, CompoundTag chunkData) { + #if MC_VER <= MC_1_17_1 + // MC 1.16 and 1.17 doesn't have the necessary NBT info return null; + #else + + CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getMinBuildHeight(chunk), ChunkWrapper.getMaxBuildHeight(chunk)); + ChunkLightStorage blockLightStorage = combinedStorage.blockLightStorage; + ChunkLightStorage skyLightStorage = combinedStorage.skyLightStorage; + + boolean foundSkyLight = false; + + + + //===================// + // get NBT tags info // + //===================// + + Tag chunkSectionTags = chunkData.get("sections"); + if (chunkSectionTags == null) + { + if (!lightingSectionErrorLogged) + { + lightingSectionErrorLogged = true; + LOGGER.error("No sections found for chunk at pos ["+chunk.getPos()+"] chunk data may be out of date."); + } + return null; + } + else if (!(chunkSectionTags instanceof ListTag)) + { + if (!lightingSectionErrorLogged) + { + lightingSectionErrorLogged = true; + LOGGER.error("Chunk section tag list have unexpected type ["+chunkSectionTags.getClass().getName()+"], expected ["+ListTag.class.getName()+"]."); + } + return null; + } + ListTag chunkSectionListTag = (ListTag) chunkSectionTags; + + + + //===================// + // get lighting info // + //===================// + + for (int sectionIndex = 0; sectionIndex < chunkSectionListTag.size(); sectionIndex++) + { + Tag chunkSectionTag = chunkSectionListTag.get(sectionIndex); + if (!(chunkSectionTag instanceof CompoundTag)) + { + if (!lightingSectionErrorLogged) + { + lightingSectionErrorLogged = true; + LOGGER.error("Chunk section tag has an unexpected type ["+chunkSectionTag.getClass().getName()+"], expected ["+CompoundTag.class.getName()+"]."); + } + return null; + } + CompoundTag chunkSectionCompoundTag = (CompoundTag) chunkSectionTag; + + + // if null all lights = 0 + byte[] blockLightNibbleArray = chunkSectionCompoundTag.getByteArray("BlockLight"); + byte[] skyLightNibbleArray = chunkSectionCompoundTag.getByteArray("SkyLight"); + + // if any sky light was found then all lights above will be max brightness + if (skyLightNibbleArray.length != 0) + { + foundSkyLight = true; + } + + for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++) + { + for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++) + { + // chunk sections are also 16 blocks tall + for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++) + { + int blockPosIndex = relY*16*16 + relZ*16 + relX; + byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex); + byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex); + if (skyLightNibbleArray.length == 0 && foundSkyLight) + { + skyLight = LodUtil.MAX_MC_LIGHT; + } + + int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getMinBuildHeight(chunk); + blockLightStorage.set(relX, y, relZ, blockLight); + skyLightStorage.set(relX, y, relZ, skyLight); + } + } + } + } + + return combinedStorage; + #endif + } + /** source: https://minecraft.wiki/w/Chunk_format#Block_Format */ + private static byte getNibbleAtIndex(byte[] arr, int index) + { + if (index % 2 == 0) + { + return (byte)(arr[index/2] & 0x0F); + } + else + { + return (byte)((arr[index/2]>>4) & 0x0F); + } } private static void logErrors(ChunkPos chunkPos, int i, String string) @@ -359,5 +483,23 @@ public class ChunkLoader LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string); } + + + //================// + // helper classes // + //================// + + public static class CombinedChunkLightStorage + { + public ChunkLightStorage blockLightStorage; + public ChunkLightStorage skyLightStorage; + + public CombinedChunkLightStorage(int minY, int maxY) + { + this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(minY, maxY); + this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(minY, maxY); + } + } + } diff --git a/coreSubProjects b/coreSubProjects index 97b86d69c..af9b55ad6 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 97b86d69c4031bf575280e8b3e30b8e3470598d9 +Subproject commit af9b55ad6cd1446dd96c3a5e5c9968e560b36cb7 From 48e29784380be8c571a63a0a1dbebbc229b33955 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 13 Jun 2024 07:15:11 -0500 Subject: [PATCH 05/17] Fixes #713 (Forge/Neo level unload events not being called) --- .../java/com/seibel/distanthorizons/forge/ForgeClientProxy.java | 2 +- .../seibel/distanthorizons/neoforge/NeoforgeClientProxy.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java index e97d9b9f5..036bc979b 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java @@ -144,7 +144,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy #if MC_VER < MC_1_19_2 public void clientLevelUnloadEvent(WorldEvent.Unload event) #else - public void clientLevelUnloadEvent(LevelEvent.Load event) + public void clientLevelUnloadEvent(LevelEvent.Unload event) #endif { LOGGER.info("level unload"); diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java index 8a086c0b1..cc53ba527 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java @@ -140,7 +140,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper); } @SubscribeEvent - public void clientLevelUnloadEvent(LevelEvent.Load event) + public void clientLevelUnloadEvent(LevelEvent.Unload event) { LOGGER.info("level unload"); From 94ad118c5df77b8a1a7b360c90e8c387b9858512 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 13 Jun 2024 07:30:42 -0500 Subject: [PATCH 06/17] Minor memory optimization thanks to littlewolf --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index af9b55ad6..54c2213eb 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit af9b55ad6cd1446dd96c3a5e5c9968e560b36cb7 +Subproject commit 54c2213eb61879492ac29b1bf4646fcc6020af55 From a12092c1a1a1dc077d684730c395779653a30c96 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 14 Jun 2024 07:36:25 -0500 Subject: [PATCH 07/17] Add fabric 1.21 support --- .../common/wrappers/WrapperFactory.java | 12 ++--- .../common/wrappers/block/BiomeWrapper.java | 4 ++ .../wrappers/block/BlockStateWrapper.java | 4 ++ .../common/wrappers/chunk/ChunkWrapper.java | 10 ++++ .../common/wrappers/gui/ClassicConfigGUI.java | 8 ++- .../wrappers/gui/updater/UpdateModScreen.java | 16 +++++- .../MinecraftDedicatedServerWrapper.java | 16 +++--- .../minecraft/MinecraftRenderWrapper.java | 2 +- .../BatchGenerationEnvironment.java | 19 +++++-- .../mimicObject/ChunkLoader.java | 17 ++++-- .../mimicObject/DhGenerationChunkHolder.java | 23 ++++++++ .../mimicObject/DhLitWorldGenRegion.java | 32 +++++++++-- .../worldGeneration/step/StepBiomes.java | 26 ++++++--- .../worldGeneration/step/StepFeatures.java | 12 ++--- .../worldGeneration/step/StepNoise.java | 23 +++++--- .../step/StepStructureReference.java | 12 +++-- .../step/StepStructureStart.java | 6 ++- .../worldGeneration/step/StepSurface.java | 13 +++-- coreSubProjects | 2 +- .../fabric/FabricClientProxy.java | 7 ++- .../mixins/client/MixinLevelRenderer.java | 7 ++- .../mixins/client/MixinOptionsScreen.java | 23 +++++--- .../wrappers/modAccessor/BCLibAccessor.java | 5 +- gradle.properties | 4 +- versionProperties/1.21.properties | 54 +++++++++++++++++++ 25 files changed, 290 insertions(+), 67 deletions(-) create mode 100644 common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhGenerationChunkHolder.java create mode 100644 versionProperties/1.21.properties diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java index 7b885fc5f..115243c1d 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java @@ -130,7 +130,7 @@ public class WrapperFactory implements IWrapperFactory } } - #if MC_VER <= MC_1_20_6 + #if MC_VER <= MC_1_21 else if (objectArray.length == 2) { // correct number of parameters from the API @@ -195,7 +195,7 @@ public class WrapperFactory implements IWrapperFactory { String[] expectedClassNames; - #if MC_VER <= MC_1_20_6 + #if MC_VER <= MC_1_21 expectedClassNames = new String[] { ChunkAccess.class.getName(), @@ -243,7 +243,7 @@ public class WrapperFactory implements IWrapperFactory Biome biome = (Biome) objectArray[0]; return BiomeWrapper.getBiomeWrapper(biome, coreLevelWrapper); - #elif MC_VER <= MC_1_20_6 + #elif MC_VER <= MC_1_21 if (!(objectArray[0] instanceof Holder) || !(((Holder) objectArray[0]).value() instanceof Biome)) { throw new ClassCastException(createBiomeWrapperErrorMessage(objectArray)); @@ -266,7 +266,7 @@ public class WrapperFactory implements IWrapperFactory #if MC_VER < MC_1_18_2 expectedClassNames = new String[] { Biome.class.getName() }; - #elif MC_VER <= MC_1_20_6 + #elif MC_VER <= MC_1_21 expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" }; #else // See preprocessor comment in createChunkWrapper() for full documentation @@ -287,7 +287,7 @@ public class WrapperFactory implements IWrapperFactory - #if MC_VER <= MC_1_20_6 + #if MC_VER <= MC_1_21 if (objectArray.length != 1) { throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray)); @@ -314,7 +314,7 @@ public class WrapperFactory implements IWrapperFactory #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 expectedClassNames = new String[] { Biome.class.getName() }; - #elif MC_VER <= MC_1_20_6 + #elif MC_VER <= MC_1_21 expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" }; #else // See preprocessor comment in createChunkWrapper() for full documentation diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java index f7282de12..5f1b205b0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java @@ -293,7 +293,11 @@ public class BiomeWrapper implements IBiomeWrapper ResourceLocation resourceLocation; try { + #if MC_VER < MC_1_21 resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1)); + #else + resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1)); + #endif } catch (Exception e) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java index 4a40c6e1f..52b30b922 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java @@ -380,7 +380,11 @@ public class BlockStateWrapper implements IBlockStateWrapper ResourceLocation resourceLocation; try { + #if MC_VER < MC_1_21 resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1)); + #else + resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1)); + #endif } catch (Exception e) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index 321d02050..07f65dfca 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -292,6 +292,16 @@ public class ChunkWrapper implements IChunkWrapper public ChunkAccess getChunk() { return this.chunk; } + public ChunkStatus getStatus() { return getStatus(this.getChunk()); } + public static ChunkStatus getStatus(ChunkAccess chunk) + { + #if MC_VER < MC_1_21 + return chunk.getStatus(); + #else + return chunk.getPersistedStatus(); + #endif + } + @Override public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); } @Override diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java index 228c4a218..ffb8d9412 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java @@ -255,7 +255,13 @@ public class ClassicConfigGUI // texture UV Offset 0, 0, // Some textuary stuff - 0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20, + 0, + #if MC_VER < MC_1_21 + new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), + #else + ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), + #endif + 20, 20, // Create the button and tell it where to go (buttonWidget) -> { ChangelogScreen changelogScreen = new ChangelogScreen(this); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java index 01ac2bb2f..f4d52e9d6 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java @@ -75,7 +75,13 @@ public class UpdateModScreen extends DhScreen // Offset 0, 0, // Some textuary stuff - 0, new ResourceLocation(ModInfo.ID, "logo.png"), 130, 65, + 0, + #if MC_VER < MC_1_21 + new ResourceLocation(ModInfo.ID, "logo.png"), + #else + ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"), + #endif + 130, 65, // Create the button and tell it where to go // For now it goes to the client option by default (buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti) @@ -100,7 +106,13 @@ public class UpdateModScreen extends DhScreen // Offset 0, 0, // Some textuary stuff - 0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20, + 0, + #if MC_VER < MC_1_21 + new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), + #else + ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), + #endif + 20, 20, // Create the button and tell it where to go (buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti) // Add a title to the button diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftDedicatedServerWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftDedicatedServerWrapper.java index af701e598..bf09dc1bd 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftDedicatedServerWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftDedicatedServerWrapper.java @@ -12,16 +12,20 @@ public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper private MinecraftDedicatedServerWrapper() { } public DedicatedServer dedicatedServer = null; @Override - public boolean isDedicatedServer() - { - return true; - } + public boolean isDedicatedServer() { return true; } @Override public File getInstallationDirectory() { - if (dedicatedServer == null) + if (this.dedicatedServer == null) + { throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!"); - return dedicatedServer.getServerDirectory(); + } + + #if MC_VER < MC_1_21 + return this.dedicatedServer.getServerDirectory(); + #else + return this.dedicatedServer.getServerDirectory().toFile(); + #endif } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java index a4651ae75..eba3ef2e9 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java @@ -215,7 +215,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper #if MC_VER < MC_1_17_1 Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), MC.getFrameTime()); #else - Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime()); + Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getTimer().getRealtimeDeltaTicks()); #endif return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index 4f459eeb9..a3cf7bc3e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -440,9 +440,18 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv }; totalChunks = new ArrayGridList<>(refSize, (x, z) -> emptyChunkGeneratorFunc.generate(x + refPosX, z + refPosZ)); + int radius = refSize / 2; + int centerX = refPosX + radius; + int centerZ = refPosZ + radius; + + ChunkAccess centerChunk = totalChunks.stream().filter(chunk -> chunk.getPos().x == centerX && chunk.getPos().z == centerZ).findFirst().get(); + genEvent.refreshTimeout(); - region = new DhLitWorldGenRegion(this.params.level, dummyLightEngine, totalChunks, - ChunkStatus.STRUCTURE_STARTS, refSize / 2, emptyChunkGeneratorFunc); + region = new DhLitWorldGenRegion( + centerX, centerZ, + centerChunk, + this.params.level, dummyLightEngine, totalChunks, + ChunkStatus.STRUCTURE_STARTS, radius, emptyChunkGeneratorFunc); adaptor.setRegion(region); genEvent.threadedParam.makeStructFeat(region, this.params); @@ -513,7 +522,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false"); } - boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk; + boolean isFull = ChunkWrapper.getStatus(target) == ChunkStatus.FULL || target instanceof LevelChunk; #if MC_VER >= MC_1_18_2 boolean isPartial = target.isOldNoiseGeneration(); #endif @@ -529,7 +538,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv genEvent.resultConsumer.accept(wrappedChunk); } #endif - else if (target.getStatus() == ChunkStatus.EMPTY) + else if (ChunkWrapper.getStatus(target) == ChunkStatus.EMPTY) { genEvent.resultConsumer.accept(wrappedChunk); } @@ -727,7 +736,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv for (int i = 0; i < chunksToGenerate.size(); i++) // regular for loop since enhanced for loops increase GC pressure slightly { ChunkWrapper chunkWrapper = chunksToGenerate.get(i); - if (chunkWrapper.getChunk().getStatus() != ChunkStatus.EMPTY) + if (chunkWrapper.getStatus() != ChunkStatus.EMPTY) { iChunkWrapperList.add(chunkWrapper); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index 1a7ce278b..f69efe3b8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -85,6 +85,9 @@ import net.minecraft.world.level.material.Fluids; #if MC_VER == MC_1_20_6 import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkType; +#elif MC_VER == MC_1_21 +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkType; #endif import net.minecraft.world.level.material.Fluid; @@ -286,7 +289,11 @@ public class ChunkLoader blockStateContainer = tagSection.contains("block_states", 10) ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)) - #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif + #if MC_VER < MC_1_20_6 + .getOrThrow(false, LOGGER::error) + #else + .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) + #endif : new PalettedContainer(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); #if MC_VER < MC_1_18_2 @@ -297,7 +304,11 @@ public class ChunkLoader biomeContainer = tagSection.contains("biomes", 10) ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)) - #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) #endif + #if MC_VER < MC_1_20_6 + .getOrThrow(false, LOGGER::error) + #else + .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) + #endif : new PalettedContainer>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); #endif @@ -312,7 +323,7 @@ public class ChunkLoader } return chunkSections; } - private static #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType #else ChunkType #endif readChunkType(CompoundTag tagLevel) + private static #if MC_VER < MC_1_21 ChunkType #else ChunkType #endif readChunkType(CompoundTag tagLevel) { ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status")); if (chunkStatus != null) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhGenerationChunkHolder.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhGenerationChunkHolder.java new file mode 100644 index 000000000..519938ce8 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhGenerationChunkHolder.java @@ -0,0 +1,23 @@ +package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; + +#if MC_VER >= MC_1_21 + +import net.minecraft.server.level.GenerationChunkHolder; +import net.minecraft.world.level.ChunkPos; + +public class DhGenerationChunkHolder extends GenerationChunkHolder +{ + + public DhGenerationChunkHolder(ChunkPos pos) + { + super(pos); + } + + @Override + public int getTicketLevel() { return 0; } + @Override + public int getQueueLevel() { return 0; } + +} + +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java index 8ee62a90f..ce4fd28a2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java @@ -20,14 +20,17 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; import java.lang.invoke.MethodHandles; +import java.util.EnumSet; import java.util.List; import java.util.concurrent.locks.ReentrantLock; +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.util.LodUtil; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.SpawnerBlock; +import net.minecraft.world.level.chunk.status.*; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,7 +62,12 @@ import net.minecraft.world.level.lighting.LevelLightEngine; #if MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; #else -import net.minecraft.world.level.chunk.status.ChunkStatus; +#endif + +#if MC_VER == MC_1_21 +import net.minecraft.util.StaticCache2D; +import com.google.common.collect.ImmutableList; +import net.minecraft.server.level.GenerationChunkHolder; #endif @@ -112,11 +120,29 @@ public class DhLitWorldGenRegion extends WorldGenRegion public DhLitWorldGenRegion( + int centerChunkX, int centerChunkZ, + ChunkAccess centerChunk, ServerLevel serverLevel, DummyLightEngine lightEngine, List chunkList, ChunkStatus chunkStatus, int writeRadius, BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator) { - super(serverLevel, chunkList #if MC_VER >= MC_1_17_1 , chunkStatus, writeRadius #endif ); + #if MC_VER == MC_1_16 + super(serverLevel, chunkList); + #elif MC_VER < MC_1_21 + super(serverLevel, chunkList, chunkStatus, writeRadius); + #else + super(serverLevel, + StaticCache2D.create( + centerChunkX, centerChunkZ, + writeRadius * 2, (x,z) -> new DhGenerationChunkHolder(new ChunkPos(x, z))), + new ChunkStep(chunkStatus, + // reverse is needed because MC uses the index of the chunkStatus to determine how many items are in the list instead of the actual list count + new ChunkDependencies(ImmutableList.copyOf(ChunkStatus.getStatusList()).reverse()), + new ChunkDependencies(ImmutableList.copyOf(ChunkStatus.getStatusList()).reverse()), + writeRadius, (WorldGenContext var1, ChunkStep var2, StaticCache2D var3, ChunkAccess var4) -> null), + centerChunk); + + #endif this.firstPos = chunkList.get(0).getPos(); this.generator = generator; this.lightEngine = lightEngine; @@ -280,7 +306,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion private ChunkAccess getChunkAccess(int chunkX, int chunkZ, ChunkStatus chunkStatus, boolean returnNonNull) { ChunkAccess chunk = this.superHasChunk(chunkX, chunkZ) ? this.superGetChunk(chunkX, chunkZ) : null; - if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) + if (chunk != null && ChunkWrapper.getStatus(chunk).isOrAfter(chunkStatus)) { return chunk; } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java index d52fdc447..7fdce78f0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java @@ -56,29 +56,39 @@ public final class StepBiomes List chunkWrappers) { - ArrayList chunksToDo = new ArrayList(); + ArrayList chunksToDo = new ArrayList<>(); for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunk.getStatus().isOrAfter(STATUS)) continue; - ((ProtoChunk) chunk).setStatus(STATUS); - chunksToDo.add(chunk); + if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + { + #if MC_VER < MC_1_21 + ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif + + chunksToDo.add(chunk); + } } for (ChunkAccess chunk : chunksToDo) { // System.out.println("StepBiomes: "+chunk.getPos()); #if MC_VER < MC_1_18_2 - environment.params.generator.createBiomes(environment.params.biomes, chunk); + this.environment.params.generator.createBiomes(this.environment.params.biomes, chunk); #elif MC_VER < MC_1_19_2 - chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, Blender.of(worldGenRegion), + chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, Blender.of(worldGenRegion), tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #elif MC_VER < MC_1_19_4 - chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, environment.params.randomState, Blender.of(worldGenRegion), + chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion), + tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); + #elif MC_VER < MC_1_21 + chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion), tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #else - chunk = environment.joinSync(environment.params.generator.createBiomes(Runnable::run, environment.params.randomState, Blender.of(worldGenRegion), + chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.randomState, Blender.of(worldGenRegion), tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java index 4f6618e1f..5ae538825 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java @@ -59,14 +59,14 @@ public final class StepFeatures for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunk.getStatus().isOrAfter(STATUS)) - { - continue; - } - - if (chunk instanceof ProtoChunk) + if (!chunkWrapper.getStatus().isOrAfter(STATUS) + && chunk instanceof ProtoChunk) { + #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java index a99958aac..47b524cd5 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java @@ -58,13 +58,21 @@ public final class StepNoise List chunkWrappers) { - ArrayList chunksToDo = new ArrayList(); + ArrayList chunksToDo = new ArrayList<>(); for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunk.getStatus().isOrAfter(STATUS)) continue; + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + continue; + } + + #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif chunksToDo.add(chunk); } @@ -72,15 +80,18 @@ public final class StepNoise { // System.out.println("StepNoise: "+chunk.getPos()); #if MC_VER < MC_1_17_1 - environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk); + this.environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk); #elif MC_VER < MC_1_18_2 - chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, + chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #elif MC_VER < MC_1_19_2 - chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), + chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), + tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); + #elif MC_VER < MC_1_21 + chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), this.environment.params.randomState, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #else - chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), environment.params.randomState, + chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Blender.of(worldGenRegion), this.environment.params.randomState, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk)); #endif UncheckedInterruptedException.throwIfInterrupted(); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java index 3894c522d..e90819967 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java @@ -59,9 +59,15 @@ public final class StepStructureReference for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunk.getStatus().isOrAfter(STATUS)) continue; - ((ProtoChunk) chunk).setStatus(STATUS); - chunksToDo.add(chunk); + if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + { + #if MC_VER < MC_1_21 + ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif + chunksToDo.add(chunk); + } } for (ChunkAccess chunk : chunksToDo) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java index 24e9c90b5..8c53a0c12 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java @@ -76,9 +76,13 @@ public final class StepStructureStart for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunk.getStatus().isOrAfter(STATUS)) + if (!chunkWrapper.getStatus().isOrAfter(STATUS)) { + #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif chunksToDo.add(chunk); } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java index 384611a2f..0e61d70a2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java @@ -58,9 +58,16 @@ public final class StepSurface for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (chunk.getStatus().isOrAfter(STATUS)) continue; - ((ProtoChunk) chunk).setStatus(STATUS); - chunksToDo.add(chunk); + if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + { + #if MC_VER < MC_1_21 + ((ProtoChunk) chunk).setStatus(STATUS); + #else + ((ProtoChunk) chunk).setPersistedStatus(STATUS); + #endif + + chunksToDo.add(chunk); + } } for (ChunkAccess chunk : chunksToDo) diff --git a/coreSubProjects b/coreSubProjects index 54c2213eb..7b153a8aa 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 54c2213eb61879492ac29b1bf4646fcc6020af55 +Subproject commit 7b153a8aadc703209b58b8760d1dd879fdfbca4e diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java index cb2153586..71e35cd76 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java @@ -208,7 +208,12 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()), modelViewMatrix, projectionMatrix, - renderContext.tickDelta()); + #if MC_VER < MC_1_21 + renderContext.tickDelta() + #else + renderContext.tickCounter().getGameTimeDeltaTicks() + #endif + ); }); // Debug keyboard event diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java index 34767a843..12bbb0421 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java @@ -120,7 +120,12 @@ public class MixinLevelRenderer ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, - Minecraft.getInstance().getFrameTime()); + #if MC_VER < MC_1_21 + Minecraft.getInstance().getFrameTime() + #else + Minecraft.getInstance().getTimer().getRealtimeDeltaTicks() + #endif + ); } // FIXME completely disables rendering when sodium is installed diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinOptionsScreen.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinOptionsScreen.java index 7c4116b6d..d638536f7 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinOptionsScreen.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinOptionsScreen.java @@ -23,16 +23,13 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.config.Config; -import net.minecraft.client.gui.screens.OptionsScreen; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; #if MC_VER < MC_1_19_2 import net.minecraft.network.chat.TranslatableComponent; #endif import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -41,11 +38,20 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; -#if MC_VER == MC_1_20_6 +#if MC_VER >= MC_1_20_6 import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Shadow; #endif +#if MC_VER < MC_1_21 +import net.minecraft.client.gui.screens.OptionsScreen; +#else +import net.minecraft.client.gui.screens.options.OptionsScreen; +#endif + + /** * Adds a button to the menu to goto the config * @@ -57,13 +63,18 @@ public class MixinOptionsScreen extends Screen { /** Texture used for the config opening button */ @Unique - private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png"); + private static final ResourceLocation ICON_TEXTURE = + #if MC_VER < MC_1_21 + new ResourceLocation(ModInfo.ID, "textures/gui/button.png"); + #else + ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png"); + #endif @Unique private TexturedButtonWidget optionsButton = null; - #if MC_VER == MC_1_20_6 + #if MC_VER >= MC_1_20_6 @Shadow @Final protected HeaderAndFooterLayout layout; diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/BCLibAccessor.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/BCLibAccessor.java index ed9c55488..06efa7741 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/BCLibAccessor.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/BCLibAccessor.java @@ -5,7 +5,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IBCLibAcces #elif MC_VER == MC_1_18_2 import ru.bclib.config.ClientConfig; import ru.bclib.config.Configs; -#else +#elif MC_VER < MC_1_21 import org.betterx.bclib.config.ClientConfig; import org.betterx.bclib.config.Configs; #endif @@ -17,7 +17,8 @@ public class BCLibAccessor implements IBCLibAccessor public void setRenderCustomFog(boolean newValue) { - #if !(MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 || MC_VER == MC_1_20_4 || MC_VER == MC_1_20_6) // These versions either don't have BCLib, or the implementation is different + // only some MC versions have BCLib and require this fix + #if (MC_VER > MC_1_17_1 && MC_VER < MC_1_20_4) // Change the value of CUSTOM_FOG_RENDERING in the bclib client config // This disabled fog from rendering within bclib diff --git a/gradle.properties b/gradle.properties index b66ef5dbd..6da075fb9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ mod_issues=https://gitlab.com/jeseibel/distant-horizons/-/issues mod_discord=https://discord.gg/xAB8G4cENx # Global Plugin Versions -manifold_version=2024.1.15 +manifold_version=2023.1.17 # 2023.1.17 can be used if there are mystery Java compiler issues nightconfig_version=3.6.6 lz4_version=1.8.0 @@ -49,7 +49,7 @@ versionStr= # This defines what MC version Intellij will use for the preprocessor # and what version is used automatically by build and run commands -mcVer=1.20.6 +mcVer=1.21 # Defines the maximum amount of memory Minecraft is allowed when run in a development environment #minecraftMemoryJavaArg="-Xmx4G" diff --git a/versionProperties/1.21.properties b/versionProperties/1.21.properties new file mode 100644 index 000000000..e16886c23 --- /dev/null +++ b/versionProperties/1.21.properties @@ -0,0 +1,54 @@ +# 1.21 version +java_version=21 +minecraft_version=1.21 +parchment_version=1.20.6:2024.05.01 +compatible_minecraft_versions=["1.21.0"] +accessWidenerVersion=1_20_6 +builds_for=fabric +# neoforge +# forge is broken due to gradle/build script issues + +# Fabric loader +fabric_loader_version=0.15.11 +fabric_api_version=0.100.1+1.21 + # Fabric mod versions + modmenu_version=11.0.0-beta.1 + starlight_version_fabric= + phosphor_version_fabric= + lithium_version= + sodium_version=mc1.21-0.5.9 + iris_version=1.7.1+1.21 + bclib_version= + immersive_portals_version= + canvas_version= + + fabric_incompatibility_list={ "iris": "<=1.6.20" } + fabric_recommend_list={} + + # Fabric mod run + # 0 = Don't enable and don't run + # 1 = Can be referenced in code but doesn't run + # 2 = Can be referenced in code and runs in client + enable_starlight=0 + enable_phosphor=0 + enable_sodium=1 + enable_lithium=0 + enable_iris=1 + enable_bclib=0 + enable_immersive_portals=0 + enable_canvas=0 + +# (Neo)Forge loader +forge_version=50.0.19 +neoforge_version=20.6.70-beta + # (Neo)Forge mod versions + starlight_version_forge= + terraforged_version= + + # (Neo)Forge mod run + # 0 = Don't enable and don't run + # 1 = Can be referenced in code but doesn't run + # 2 = Can be referenced in code and runs in client + enable_starlight_forge=0 + enable_terraforged=0 + enable_terrafirmacraft=0 From 601d4e6e3a611874fdfd2492d2c1a216c0c28de5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 14 Jun 2024 07:40:29 -0500 Subject: [PATCH 08/17] Fix CI not picking up 1.21 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d84d24eea..181343627 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,7 +30,7 @@ build: stage: build parallel: matrix: - - MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6"] + - MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21"] script: # this both runs the unit tests and assembles the code - ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/; From f4e71f701278d87d70cdb51e5fcc326050ded204 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 14 Jun 2024 19:05:45 -0500 Subject: [PATCH 09/17] Add NeoForge 1.21 --- .../minecraft/MinecraftRenderWrapper.java | 15 +++++++++--- gradle.properties | 2 +- .../mixins/client/MixinLevelRenderer.java | 12 +++++++--- .../mixins/client/MixinOptionsScreen.java | 24 +++++++++++++------ versionProperties/1.21.properties | 5 ++-- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java index eba3ef2e9..e0ffe856e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java @@ -212,15 +212,24 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper { if (MC.level.dimensionType().hasSkyLight()) { - #if MC_VER < MC_1_17_1 - Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), MC.getFrameTime()); + float frameTime; + #if MC_VER < MC_1_21 + frameTime = MC.getFrameTime(); #else - Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getTimer().getRealtimeDeltaTicks()); + frameTime = MC.getTimer().getRealtimeDeltaTicks(); + #endif + + #if MC_VER < MC_1_17_1 + Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime); + #else + Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime); #endif return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z); } else + { return new Color(0, 0, 0); + } } @Override diff --git a/gradle.properties b/gradle.properties index 6da075fb9..b8928e5de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,7 +49,7 @@ versionStr= # This defines what MC version Intellij will use for the preprocessor # and what version is used automatically by build and run commands -mcVer=1.21 +mcVer=1.20.6 # Defines the maximum amount of memory Minecraft is allowed when run in a development environment #minecraftMemoryJavaArg="-Xmx4G" diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java index 95e5e9bff..8c3c0506c 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java @@ -98,7 +98,6 @@ public class MixinLevelRenderer private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback) #endif { - // get MC's model view and projection matrices #if MC_VER == MC_1_16_5 // get the matrices from the OpenGL fixed pipeline float[] mcProjMatrixRaw = new float[16]; @@ -120,15 +119,21 @@ public class MixinLevelRenderer #endif + float frameTime; + #if MC_VER < MC_1_21 + frameTime = Minecraft.getInstance().getFrameTime(); + #else + frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks(); + #endif // only render before solid blocks if (renderType.equals(RenderType.solid())) { - ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, Minecraft.getInstance().getFrameTime()); + ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime); } else if (renderType.equals(RenderType.translucent())) { - ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, Minecraft.getInstance().getFrameTime()); + ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime); } if (Config.Client.Advanced.Debugging.lodOnlyMode.get()) @@ -154,4 +159,5 @@ public class MixinLevelRenderer ChunkWrapper.syncedUpdateClientLightStatus(); } + } diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinOptionsScreen.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinOptionsScreen.java index 983b446dd..b1a661e78 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinOptionsScreen.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinOptionsScreen.java @@ -23,16 +23,13 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.config.Config; -import net.minecraft.client.gui.screens.OptionsScreen; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; #if MC_VER < MC_1_19_2 import net.minecraft.network.chat.TranslatableComponent; #endif import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -41,11 +38,20 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; -#if MC_VER == MC_1_20_6 +#if MC_VER >= MC_1_20_6 import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Shadow; #endif +#if MC_VER < MC_1_21 +import net.minecraft.client.gui.screens.OptionsScreen; +#else +import net.minecraft.client.gui.screens.options.OptionsScreen; +#endif + + /** * Adds a button to the menu to goto the config * @@ -57,13 +63,18 @@ public class MixinOptionsScreen extends Screen { /** Texture used for the config opening button */ @Unique - private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png"); + private static final ResourceLocation ICON_TEXTURE = + #if MC_VER < MC_1_21 + new ResourceLocation(ModInfo.ID, "textures/gui/button.png"); + #else + ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png"); + #endif @Unique private TexturedButtonWidget optionsButton = null; - #if MC_VER == MC_1_20_6 + #if MC_VER >= MC_1_20_6 @Shadow @Final protected HeaderAndFooterLayout layout; @@ -93,7 +104,6 @@ public class MixinOptionsScreen extends Screen // add the button to the correct location in the UI // TODO is there a better way to do this instead of using access transformers to inject into the exact UI elements? - // TODO is there a way we can put the button on the left side of the FOV bar like before? LinearLayout layout = (LinearLayout) this.layout.headerFrame.children.get(0).child; // determine how wide the other option buttons are so we can put our botton to the left of them all diff --git a/versionProperties/1.21.properties b/versionProperties/1.21.properties index e16886c23..4e9ded570 100644 --- a/versionProperties/1.21.properties +++ b/versionProperties/1.21.properties @@ -4,8 +4,7 @@ minecraft_version=1.21 parchment_version=1.20.6:2024.05.01 compatible_minecraft_versions=["1.21.0"] accessWidenerVersion=1_20_6 -builds_for=fabric -# neoforge +builds_for=fabric,neoforge # forge is broken due to gradle/build script issues # Fabric loader @@ -40,7 +39,7 @@ fabric_api_version=0.100.1+1.21 # (Neo)Forge loader forge_version=50.0.19 -neoforge_version=20.6.70-beta +neoforge_version=21.0.4-beta # (Neo)Forge mod versions starlight_version_forge= terraforged_version= From 5570f3a313c1059ef8fbcf1d73c90453160b7e25 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 14 Jun 2024 19:31:21 -0500 Subject: [PATCH 10/17] Fix some compiling issues --- .../worldGeneration/mimicObject/ChunkLoader.java | 11 +++++++++-- .../mimicObject/DhLitWorldGenRegion.java | 3 +-- gradle.properties | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index f69efe3b8..e89c5ee48 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -323,7 +323,11 @@ public class ChunkLoader } return chunkSections; } - private static #if MC_VER < MC_1_21 ChunkType #else ChunkType #endif readChunkType(CompoundTag tagLevel) + private static + #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType + #elif MC_VER < MC_1_21 ChunkType + #else ChunkType #endif + readChunkType(CompoundTag tagLevel) { ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status")); if (chunkStatus != null) @@ -331,7 +335,10 @@ public class ChunkLoader return chunkStatus.getChunkType(); } - return #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK; #else ChunkType.PROTOCHUNK; #endif + return + #if MC_VER <= MC_1_20_6 ChunkType.PROTOCHUNK; + #elif MC_VER < MC_1_21 ChunkStatus.ChunkType.PROTOCHUNK; + #else ChunkType.PROTOCHUNK; #endif } private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java index ce4fd28a2..ed585da95 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java @@ -23,14 +23,12 @@ import java.lang.invoke.MethodHandles; import java.util.EnumSet; import java.util.List; import java.util.concurrent.locks.ReentrantLock; - import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.util.LodUtil; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.SpawnerBlock; -import net.minecraft.world.level.chunk.status.*; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,6 +60,7 @@ import net.minecraft.world.level.lighting.LevelLightEngine; #if MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; #else +import net.minecraft.world.level.chunk.status.*; #endif #if MC_VER == MC_1_21 diff --git a/gradle.properties b/gradle.properties index b8928e5de..6da075fb9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,7 +49,7 @@ versionStr= # This defines what MC version Intellij will use for the preprocessor # and what version is used automatically by build and run commands -mcVer=1.20.6 +mcVer=1.21 # Defines the maximum amount of memory Minecraft is allowed when run in a development environment #minecraftMemoryJavaArg="-Xmx4G" From 7e45051ffdf8ed56514d1cbcf223a24aa58b83e6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 14 Jun 2024 22:21:52 -0500 Subject: [PATCH 11/17] Fix more MC version compiles --- .../wrappers/worldGeneration/mimicObject/ChunkLoader.java | 3 +-- .../worldGeneration/mimicObject/DhLitWorldGenRegion.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index e89c5ee48..5699051cb 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -336,8 +336,7 @@ public class ChunkLoader } return - #if MC_VER <= MC_1_20_6 ChunkType.PROTOCHUNK; - #elif MC_VER < MC_1_21 ChunkStatus.ChunkType.PROTOCHUNK; + #if MC_VER <= MC_1_20_4 ChunkStatus.ChunkType.PROTOCHUNK; #else ChunkType.PROTOCHUNK; #endif } private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java index ed585da95..30632bef1 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java @@ -125,7 +125,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion List chunkList, ChunkStatus chunkStatus, int writeRadius, BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator) { - #if MC_VER == MC_1_16 + #if MC_VER == MC_1_16_5 super(serverLevel, chunkList); #elif MC_VER < MC_1_21 super(serverLevel, chunkList, chunkStatus, writeRadius); From 84bd876c7197b1f553cb25da2e4198355d613b81 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 15 Jun 2024 08:11:26 -0500 Subject: [PATCH 12/17] Refactor ChunkWrapper --- .../common/wrappers/chunk/ChunkWrapper.java | 128 +++++++++++------- coreSubProjects | 2 +- 2 files changed, 78 insertions(+), 52 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index 07f65dfca..407da88f4 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -105,6 +105,8 @@ public class ChunkWrapper implements IChunkWrapper private int minNonEmptyHeight = Integer.MIN_VALUE; private int maxNonEmptyHeight = Integer.MAX_VALUE; + private int blockBiomeHashCode = 0; + /** * Due to vanilla `isClientLightReady()` not being designed for use by a non-render thread, it may return 'true' * before the light engine has ticked, (right after all light changes is marked by the engine to be processed). @@ -144,7 +146,7 @@ public class ChunkWrapper implements IChunkWrapper //=========// - // methods // + // getters // //=========// @Override @@ -263,7 +265,6 @@ public class ChunkWrapper implements IChunkWrapper public int getLightBlockingHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); } - @Override public IBiomeWrapper getBiome(int relX, int relY, int relZ) { @@ -287,6 +288,20 @@ public class ChunkWrapper implements IChunkWrapper #endif } + @Override + public IBlockStateWrapper getBlockState(int relX, int relY, int relZ) + { + this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ); + + BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get(); + + blockPos.setX(relX); + blockPos.setY(relY); + blockPos.setZ(relZ); + + return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel); + } + @Override public DhChunkPos getChunkPos() { return this.chunkPos; } @@ -311,14 +326,18 @@ public class ChunkWrapper implements IChunkWrapper @Override public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); } + + + //==========// + // lighting // + //==========// + @Override public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; } @Override public void setUseDhLighting(boolean useDhLighting) { this.useDhLighting = useDhLighting; } - - @Override public boolean isLightCorrect() { @@ -469,53 +488,6 @@ public class ChunkWrapper implements IChunkWrapper return this.blockLightPosList; } - @Override - public boolean doNearbyChunksExist() - { - if (this.lightSource instanceof DhLitWorldGenRegion) - { - return true; - } - - for (int dx = -1; dx <= 1; dx++) - { - for (int dz = -1; dz <= 1; dz++) - { - if (dx == 0 && dz == 0) - { - continue; - } - else if (this.lightSource.getChunk(dx + this.chunk.getPos().x, dz + this.chunk.getPos().z, ChunkStatus.BIOMES, false) == null) - { - return false; - } - } - } - - return true; - } - - @Override - public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); } - - @Override - public IBlockStateWrapper getBlockState(int relX, int relY, int relZ) - { - this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ); - - BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get(); - - blockPos.setX(relX); - blockPos.setY(relY); - blockPos.setZ(relZ); - - return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel); - } - - @Override - public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; } - - public static void syncedUpdateClientLightStatus() { #if MC_VER < MC_1_18_2 @@ -574,4 +546,58 @@ public class ChunkWrapper implements IChunkWrapper #endif + + //===============// + // other methods // + //===============// + + @Override + public boolean doNearbyChunksExist() + { + if (this.lightSource instanceof DhLitWorldGenRegion) + { + return true; + } + + for (int dx = -1; dx <= 1; dx++) + { + for (int dz = -1; dz <= 1; dz++) + { + if (dx == 0 && dz == 0) + { + continue; + } + else if (this.lightSource.getChunk(dx + this.chunk.getPos().x, dz + this.chunk.getPos().z, ChunkStatus.BIOMES, false) == null) + { + return false; + } + } + } + + return true; + } + + @Override + public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; } + + + + //================// + // base overrides // + //================// + + @Override + public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); } + + //@Override + //public int hashCode() + //{ + // if (this.blockBiomeHashCode == 0) + // { + // this.blockBiomeHashCode = this.getBlockBiomeHashCode(); + // } + // + // return this.blockBiomeHashCode; + //} + } diff --git a/coreSubProjects b/coreSubProjects index 7b153a8aa..385e3dc96 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 7b153a8aadc703209b58b8760d1dd879fdfbca4e +Subproject commit 385e3dc964fc985b01b68dfc4c852ac4946a9cd3 From 389b09a5cd6ede0fc87ae5b49d90e61d9234cb87 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 15 Jun 2024 09:42:49 -0500 Subject: [PATCH 13/17] Prevent creating LODs for already processed chunks --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 385e3dc96..81d1ed419 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 385e3dc964fc985b01b68dfc4c852ac4946a9cd3 +Subproject commit 81d1ed419e5ee583271579c355e43d750586f5f8 From 272841aae9ece7d4e281133c1ce6570a3d3658ed Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 15 Jun 2024 11:05:10 -0500 Subject: [PATCH 14/17] Add a startup low memory warning --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 81d1ed419..6542e9e88 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 81d1ed419e5ee583271579c355e43d750586f5f8 +Subproject commit 6542e9e88986942928fba562b45bc77040dbfd37 From 34db7c9dac0a19abc1a685775e2e85c31fbff3cc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 15 Jun 2024 11:26:05 -0500 Subject: [PATCH 15/17] Lower the default CPU presets --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 6542e9e88..4da48c4c5 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 6542e9e88986942928fba562b45bc77040dbfd37 +Subproject commit 4da48c4c55ac2957e483f3f05cd65f4aff938a39 From e7d7033548dc00dab581d7e13ee89a67c65e3865 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 15 Jun 2024 19:20:25 -0500 Subject: [PATCH 16/17] Improve F3 menu logic and visuals --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 4da48c4c5..67819b30e 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 4da48c4c55ac2957e483f3f05cd65f4aff938a39 +Subproject commit 67819b30ebb869d23a974258ace542837fb32b5b From cd74117de3529c9528e80f5112daa8b7ee74fa47 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 17 Jun 2024 07:42:35 -0500 Subject: [PATCH 17/17] Fix file handler tooltip --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 67819b30e..7f50de17c 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 67819b30ebb869d23a974258ace542837fb32b5b +Subproject commit 7f50de17c03a0e0cf4ac25fb1de62129adfdbab1