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