diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2fdac9f35..2d272f373 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,7 +35,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/; diff --git a/build.gradle b/build.gradle index 4e397f3a6..8152a1476 100644 --- a/build.gradle +++ b/build.gradle @@ -218,9 +218,6 @@ subprojects { p -> // Netty implementation("io.netty:netty-buffer:${rootProject.netty_version}") - implementation("io.netty:netty-codec:${rootProject.netty_version}") - implementation("io.netty:netty-transport:${rootProject.netty_version}") - implementation("io.netty:netty-handler:${rootProject.netty_version}") // Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java b/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java index 2102af207..d1d74c950 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java @@ -21,8 +21,13 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender private static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(), () -> Config.Client.Advanced.Logging.logNetworkEvent.get()); - public static final ResourceLocation PLUGIN_CHANNEL_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.PLUGIN_CHANNEL_PATH); + #if MC_VER >= MC_1_21 + public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); + #elif MC_VER >= MC_1_20_6 public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); + #else + public static final ResourceLocation PLUGIN_CHANNEL_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.PLUGIN_CHANNEL_PATH); + #endif @Override 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 eed5f64e7..2d5ded61e 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 @@ -185,7 +185,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(), @@ -233,7 +233,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)); @@ -256,7 +256,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 @@ -277,7 +277,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)); @@ -304,7 +304,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 9959c01c8..528bd11f7 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 @@ -379,7 +379,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/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 bfa549f62..144949d0a 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 @@ -29,11 +29,11 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.world.EWorldEnvironment; 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; @@ -85,9 +85,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()); @@ -111,6 +108,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). @@ -151,30 +150,34 @@ public class ChunkWrapper implements IChunkWrapper //=========// - // methods // + // getters // //=========// @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() @@ -266,7 +269,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) { @@ -290,11 +292,35 @@ 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; } 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 @@ -304,8 +330,11 @@ public class ChunkWrapper implements IChunkWrapper @Override public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); } - @Override - public long getLongChunkPos() { return this.chunk.getPos().toLong(); } + + + //==========// + // lighting // + //==========// @Override public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; } @@ -313,8 +342,6 @@ public class ChunkWrapper implements IChunkWrapper @Override public void setUseDhLighting(boolean useDhLighting) { this.useDhLighting = useDhLighting; } - - @Override public boolean isLightCorrect() { @@ -367,13 +394,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 @@ -393,13 +418,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 @@ -469,55 +492,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; - } - - public LevelReader getColorResolver() { return this.lightSource; } - - @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 @@ -577,64 +551,57 @@ public class ChunkWrapper implements IChunkWrapper - //================// - // helper methods // - //================// + //===============// + // other 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 + @Override + public boolean doNearbyChunksExist() { - if (!RUN_RELATIVE_POS_INDEX_VALIDATION) + if (this.lightSource instanceof DhLitWorldGenRegion) { - return; + return true; } - - // 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) + for (int dx = -1; dx <= 1; dx++) { - 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); + 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; + } + } } - } - - - /** - * 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); + 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; + //} + +} \ No newline at end of file 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 8c1b5af0b..d9020200f 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,10 +12,7 @@ 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() { @@ -23,7 +20,12 @@ public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper { throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!"); } + + #if MC_VER < MC_1_21 return this.dedicatedServer.getServerDirectory(); + #else + return this.dedicatedServer.getServerDirectory().toFile(); + #endif } } \ No newline at end of file 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..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.getFrameTime()); + 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/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..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 @@ -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; @@ -109,8 +110,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 +293,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv + //=================// + // synchronization // + //=================// public T joinSync(CompletableFuture future) { @@ -368,31 +370,197 @@ 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) + + //==================// + // world generation // + //==================// + + public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException + { + EVENT_LOGGER.debug("Lod Generate Event: " + genEvent.minPos); + + ArrayGridList chunkWrapperList; + DhLitWorldGenRegion region; + DummyLightEngine dummyLightEngine; + LightGetterAdaptor adaptor; + + int borderSize = MaxBorderNeeded; + int refSize = genEvent.size + borderSize * 2; + int refPosX = genEvent.minPos.x - borderSize; + int refPosZ = genEvent.minPos.z - borderSize; + + try + { + ArrayGridList totalChunks; + + adaptor = new LightGetterAdaptor(this.params.level); + 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); + DhChunkPos dhChunkPos = new DhChunkPos(x, z); + ChunkAccess newChunk = null; + try + { + // 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 loadChunkError) + { + // Continue... + } + + if (newChunk == null) + { + 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 newChunk; + }; + 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( + centerX, centerZ, + centerChunk, + this.params.level, dummyLightEngine, totalChunks, + ChunkStatus.STRUCTURE_STARTS, radius, emptyChunkGeneratorFunc); + adaptor.setRegion(region); + 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) + { + // 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"); + } + catch (StepStructureStart.StructStartCorruptedException f) + { + genEvent.threadedParam.markAsInvalid(); + throw (RuntimeException) f.getCause(); + } + + ArrayGridList finalGenChunks = GetCutoutFrom(chunkWrapperList, borderSize); + for (int offsetY = 0; offsetY < finalGenChunks.gridSize; offsetY++) + { + for (int offsetX = 0; offsetX < finalGenChunks.gridSize; offsetX++) + { + ChunkWrapper wrappedChunk = finalGenChunks.get(offsetX, offsetY); + ChunkAccess target = wrappedChunk.getChunk(); + if (target instanceof LevelChunk) + { + #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 + ((LevelChunk) target).setLoaded(true); + #else + ((LevelChunk) target).loaded = true; + #endif + } + + if (!wrappedChunk.isLightCorrect()) + { + throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false"); + } + + boolean isFull = ChunkWrapper.getStatus(target) == ChunkStatus.FULL || target instanceof LevelChunk; + #if MC_VER >= MC_1_18_2 + boolean isPartial = target.isOldNoiseGeneration(); + #endif + if (isFull) + { + LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos()); + genEvent.resultConsumer.accept(wrappedChunk); + } + #if MC_VER >= MC_1_18_2 + else if (isPartial) + { + LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos()); + genEvent.resultConsumer.accept(wrappedChunk); + } + #endif + else if (ChunkWrapper.getStatus(target) == ChunkStatus.EMPTY) + { + genEvent.resultConsumer.accept(wrappedChunk); + } + else + { + genEvent.resultConsumer.accept(wrappedChunk); + } + } + } + + genEvent.timer.complete(); + genEvent.refreshTimeout(); + if (PREF_LOGGER.canMaybeLog()) + { + genEvent.threadedParam.perf.recordEvent(genEvent.timer); + PREF_LOGGER.infoInc("{}", genEvent.timer); + } + } + private CompoundTag getChunkNbtData(ChunkPos chunkPos) { ServerLevel level = this.params.level; - - - //====================// - // get the chunk data // - //====================// - CompoundTag chunkData = null; try { @@ -425,15 +593,15 @@ 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) { - return EmptyChunk(level, chunkPos); + return CreateEmptyChunk(level, chunkPos); } else { @@ -445,154 +613,28 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv 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); + "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); + return CreateEmptyChunk(level, chunkPos); } } } - - private static ArrayGridList GetCutoutFrom(ArrayGridList total, int border) + private static ProtoChunk CreateEmptyChunk(ServerLevel level, ChunkPos chunkPos) { - return new ArrayGridList<>(total, border, total.gridSize - border); - } - - private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) - { - return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step)); - } - - public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException - { - EVENT_LOGGER.debug("Lod Generate Event: " + genEvent.minPos); - - ArrayGridList chunkWrapperList; - DhLitWorldGenRegion region; - DummyLightEngine lightEngine; - LightGetterAdaptor adaptor; - - int borderSize = MaxBorderNeeded; - int refSize = genEvent.size + borderSize * 2; - int refPosX = genEvent.minPos.x - borderSize; - int refPosZ = genEvent.minPos.z - borderSize; - - try - { - ArrayGridList totalChunks; - - adaptor = new LightGetterAdaptor(this.params.level); - lightEngine = new DummyLightEngine(adaptor); - - EmptyChunkGenerator generator = (int x, int z) -> - { - ChunkPos chunkPos = new ChunkPos(x, z); - ChunkAccess target = null; - try - { - target = this.loadOrMakeChunk(chunkPos); - } - catch (RuntimeException e2) - { - // Continue... - } - - if (target == 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 - ); - } - return target; - }; - - totalChunks = new ArrayGridList<>(refSize, (x, z) -> generator.generate(x + refPosX, z + refPosZ)); - - genEvent.refreshTimeout(); - region = new DhLitWorldGenRegion(params.level, lightEngine, totalChunks, - ChunkStatus.STRUCTURE_STARTS, refSize / 2, generator); - adaptor.setRegion(region); - genEvent.threadedParam.makeStructFeat(region, params); - - - 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())); - } - }); - - this.generateDirect(genEvent, chunkWrapperList, borderSize, genEvent.targetGenerationStep, region); - genEvent.timer.nextEvent("cleanup"); - } - catch (StepStructureStart.StructStartCorruptedException f) - { - genEvent.threadedParam.markAsInvalid(); - throw (RuntimeException) f.getCause(); - } - - ArrayGridList finalGenChunks = GetCutoutFrom(chunkWrapperList, borderSize); - for (int offsetY = 0; offsetY < finalGenChunks.gridSize; offsetY++) - { - for (int offsetX = 0; offsetX < finalGenChunks.gridSize; offsetX++) - { - ChunkWrapper wrappedChunk = finalGenChunks.get(offsetX, offsetY); - ChunkAccess target = wrappedChunk.getChunk(); - if (target instanceof LevelChunk) - { - #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 - ((LevelChunk) target).setLoaded(true); - #else - ((LevelChunk) target).loaded = true; - #endif - } - - if (!wrappedChunk.isLightCorrect()) - { - throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false"); - } - - boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk; - #if MC_VER >= MC_1_18_2 - boolean isPartial = target.isOldNoiseGeneration(); - #endif - if (isFull) - { - LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos()); - genEvent.resultConsumer.accept(wrappedChunk); - } - #if MC_VER >= MC_1_18_2 - else if (isPartial) - { - LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos()); - genEvent.resultConsumer.accept(wrappedChunk); - } - #endif - else if (target.getStatus() == ChunkStatus.EMPTY) - { - genEvent.resultConsumer.accept(wrappedChunk); - } - else - { - genEvent.resultConsumer.accept(wrappedChunk); - } - } - } - - genEvent.timer.complete(); - genEvent.refreshTimeout(); - if (PREF_LOGGER.canMaybeLog()) - { - genEvent.threadedParam.perf.recordEvent(genEvent.timer); - PREF_LOGGER.infoInc("{}", genEvent.timer); - } + 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( @@ -694,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); } @@ -715,19 +757,19 @@ 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(); } } + 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 +818,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 +837,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/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index 9a5eb9c68..fac555faa 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.*; @@ -79,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; @@ -100,138 +109,13 @@ 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 boolean lightingSectionErrorLogged = false; - 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 - } + //============// + // read chunk // + //============// public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData) { @@ -349,11 +233,290 @@ 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 + #elif MC_VER < MC_1_21 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_4 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 + + + + //=====================// + // 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) { 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/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 4f66f315c..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 @@ -20,9 +20,10 @@ 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; @@ -59,7 +60,13 @@ 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; +import net.minecraft.world.level.chunk.status.*; +#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 @@ -71,7 +78,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; @@ -112,11 +119,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.EmptyChunkGenerator generator) + BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator) { - super(serverLevel, chunkList #if MC_VER >= MC_1_17_1 , chunkStatus, writeRadius #endif ); + #if MC_VER == MC_1_16_5 + 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 +305,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 d2f497269..4d6e11fde 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit d2f49726934698f5a9b7d44f16df5ad3c058a9bb +Subproject commit 4d6e11fdebba2f3893be9aabf6af038988130e5e 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 e4ec2bb0a..316a42151 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java @@ -213,7 +213,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/FabricMain.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java index 90d3f151e..03e664e41 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java @@ -58,7 +58,11 @@ import java.util.function.Consumer; */ public class FabricMain extends AbstractModInitializer implements ClientModInitializer, DedicatedServerModInitializer { + #if MC_VER >= MC_1_21 + private static final ResourceLocation INITIAL_PHASE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH); + #else private static final ResourceLocation INITIAL_PHASE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH); + #endif private static final Logger LOGGER = DhLoggerBuilder.getLogger(); @@ -153,4 +157,4 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti } } -} +} \ No newline at end of file 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/MixinMinecraft.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinMinecraft.java index a259a2b11..14d991433 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinMinecraft.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinMinecraft.java @@ -126,19 +126,15 @@ public abstract class MixinMinecraft @Inject(at = @At("HEAD"), method = "updateLevelInEngines") public void updateLevelInEngines(ClientLevel level, CallbackInfo ci) { - // Only for multiplayer clients - if (!this.isLocalServer()) + if (this.lastLevel != null && level != this.lastLevel) { - if (this.lastLevel != null && level != this.lastLevel) - { - ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel)); - } - if (level != null) - { - ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level)); - } - this.lastLevel = level; + ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel)); } + if (level != null) + { + ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level)); + } + this.lastLevel = level; } @Inject(at = @At("HEAD"), method = "close()V") 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 01ed2b1c3..90feb59eb 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 @@ -48,7 +48,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" \ No newline at end of file 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 e48186cbd..598a15cc5 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java @@ -136,7 +136,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"); 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 new file mode 100644 index 000000000..5c9c7af29 --- /dev/null +++ b/versionProperties/1.21.properties @@ -0,0 +1,56 @@ +# 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 + +# Netty +netty_version=4.1.97.Final + +# 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=21.0.4-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 \ No newline at end of file