Merge remote-tracking branch 'upstream/main'

# Conflicts:
#	coreSubProjects
This commit is contained in:
Steveplays28
2023-09-12 17:35:49 +02:00
12 changed files with 368 additions and 39 deletions
@@ -66,9 +66,9 @@ public class BiomeWrapper implements IBiomeWrapper
private static final Logger LOGGER = LogManager.getLogger();
#if PRE_MC_1_18_2
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public static final ConcurrentMap<Biome, BiomeWrapper> WRAPPER_BY_BIOME = new ConcurrentHashMap<>();
#else
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> WRAPPER_BY_BIOME = new ConcurrentHashMap<>();
#endif
public static final String EMPTY_STRING = "EMPTY";
@@ -100,7 +100,17 @@ public class BiomeWrapper implements IBiomeWrapper
return EMPTY_WRAPPER;
}
return biomeWrapperMap.computeIfAbsent(biome, newBiome -> new BiomeWrapper(newBiome, levelWrapper));
if (WRAPPER_BY_BIOME.containsKey(biome))
{
return WRAPPER_BY_BIOME.get(biome);
}
else
{
BiomeWrapper newWrapper = new BiomeWrapper(biome, levelWrapper);
WRAPPER_BY_BIOME.put(biome, newWrapper);
return newWrapper;
}
}
private BiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
@@ -91,7 +91,17 @@ public class BlockStateWrapper implements IBlockStateWrapper
return AIR;
}
return WRAPPER_BY_BLOCK_STATE.computeIfAbsent(blockState, newBlockState -> new BlockStateWrapper(newBlockState, levelWrapper));
if (WRAPPER_BY_BLOCK_STATE.containsKey(blockState))
{
return WRAPPER_BY_BLOCK_STATE.get(blockState);
}
else
{
BlockStateWrapper newWrapper = new BlockStateWrapper(blockState, levelWrapper);
WRAPPER_BY_BLOCK_STATE.put(blockState, newWrapper);
return newWrapper;
}
}
private BlockStateWrapper(BlockState blockState, ILevelWrapper levelWrapper)
@@ -0,0 +1,216 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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;
public ChunkLightStorage(int minY, int maxY)
{
this.minY = minY;
this.maxY = maxY;
}
public int get(int x, int y, int z)
{
if (y < this.minY)
{
return 0;
}
if (y >= this.maxY)
{
return 15;
}
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<long[]> 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); }
}
}
@@ -61,7 +61,10 @@ 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 = false;
private static final boolean RUN_RELATIVE_POS_INDEX_VALIDATION = false;
/** 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<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos());
private final ChunkAccess chunk;
@@ -73,8 +76,8 @@ public class ChunkWrapper implements IChunkWrapper
/** only used when connected to a dedicated server */
private boolean isMcClientLightingCorrect = false;
private final byte[] blockLightArray;
private final byte[] skyLightArray;
private ChunkLightStorage blockLightStorage;
private ChunkLightStorage skyLightStorage;
private ArrayList<DhBlockPos> blockLightPosList = null;
@@ -112,9 +115,7 @@ public class ChunkWrapper implements IChunkWrapper
this.useDhLighting = isDhGeneratedChunk;
// FIXME +1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the relative position validator
this.blockLightArray = new byte[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH * (this.getHeight() + 1)];
this.skyLightArray = new byte[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH * (this.getHeight() + 1)];
chunksNeedingClientLightUpdating.add(this);
}
@@ -146,6 +147,21 @@ public class ChunkWrapper implements IChunkWrapper
@Override
public int getMaxBuildHeight() { return this.chunk.getMaxBuildHeight(); }
@Override
public int getMinFilledHeight()
{
LevelChunkSection[] sections = this.chunk.getSections();
for (int index = 0; index < sections.length; index++)
{
if (!sections[index].hasOnlyAir())
{
// convert from an index to a block coordinate
return this.chunk.getSectionYFromSectionIndex(index) * 16;
}
}
return Integer.MAX_VALUE;
}
@Override
public int getSolidHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel); }
@@ -242,34 +258,45 @@ public class ChunkWrapper implements IChunkWrapper
public int getDhBlockLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
int index = this.relativeBlockPosToIndex(relX, y, relZ);
return this.blockLightArray[index];
return this.getBlockLightStorage().get(relX, y, relZ);
}
@Override
public void setDhBlockLight(int relX, int y, int relZ, int lightValue)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
int index = this.relativeBlockPosToIndex(relX, y, relZ);
this.blockLightArray[index] = (byte) lightValue;
this.getBlockLightStorage().set(relX, y, relZ, lightValue);
}
private ChunkLightStorage getBlockLightStorage()
{
if (this.blockLightStorage == null)
{
this.blockLightStorage = new ChunkLightStorage(this.getMinBuildHeight(), this.getMaxBuildHeight());
}
return this.blockLightStorage;
}
@Override
public int getDhSkyLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
int index = this.relativeBlockPosToIndex(relX, y, relZ);
return this.skyLightArray[index];
return this.getSkyLightStorage().get(relX, y, relZ);
}
@Override
public void setDhSkyLight(int relX, int y, int relZ, int lightValue)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
int index = this.relativeBlockPosToIndex(relX, y, relZ);
this.skyLightArray[index] = (byte) lightValue;
this.getSkyLightStorage().set(relX, y, relZ, lightValue);
}
private ChunkLightStorage getSkyLightStorage()
{
if (this.skyLightStorage == null)
{
this.skyLightStorage = new ChunkLightStorage(this.getMinBuildHeight(), this.getMaxBuildHeight());
}
return this.skyLightStorage;
}
@@ -282,8 +309,7 @@ public class ChunkWrapper implements IChunkWrapper
if (this.useDhLighting)
{
// DH lighting method
int index = this.relativeBlockPosToIndex(relX, y, relZ);
return this.blockLightArray[index];
return this.getBlockLightStorage().get(relX, y, relZ);
}
else
{
@@ -303,8 +329,7 @@ public class ChunkWrapper implements IChunkWrapper
if (this.useDhLighting)
{
// DH lighting method
int index = this.relativeBlockPosToIndex(relX, y, relZ);
return this.skyLightArray[index];
return this.getSkyLightStorage().get(relX, y, relZ);
}
else
{
@@ -314,7 +339,7 @@ public class ChunkWrapper implements IChunkWrapper
}
@Override
public List<DhBlockPos> getBlockLightPosList()
public ArrayList<DhBlockPos> getBlockLightPosList()
{
// only populate the list once
if (this.blockLightPosList == null)
@@ -372,7 +397,13 @@ public class ChunkWrapper implements IChunkWrapper
@Override
public IBlockStateWrapper getBlockState(int relX, int relY, int relZ)
{
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(new BlockPos(relX, relY, relZ)), this.wrappedLevel);
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
@@ -442,7 +473,10 @@ public class ChunkWrapper implements IChunkWrapper
private void throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(int x, int y, int z) throws IndexOutOfBoundsException
{
if (RUN_RELATIVE_POS_INDEX_VALIDATION)
{
return;
}
// FIXME +1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the constructor
int minHeight = this.getMinBuildHeight();
@@ -103,6 +103,15 @@ public class FabricMain
{
ModAccessorInjector.INSTANCE.bind(IBCLibAccessor.class, new BCLibAccessor());
}
#if MC_1_16_5 || MC_1_18_2 || MC_1_19_2 || MC_1_19_4 || MC_1_20_1
// 1.17.1 won't support this since there isn't a matching Iris version
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("iris"))
{
ModAccessorInjector.INSTANCE.bind(IIrisAccessor.class, new IrisAccessor());
}
#endif
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
@@ -0,0 +1,50 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
#if MC_1_16_5 || MC_1_18_2 || MC_1_19_2 || MC_1_19_4 || MC_1_20_1
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
import net.coderbot.iris.Iris;
import net.irisshaders.iris.api.v0.IrisApi;
public class IrisAccessor implements IIrisAccessor
{
@Override
public String getModName()
{
//return "Iris-Fabric";
return Iris.MODID;
}
@Override
public boolean isShaderPackInUse()
{
return IrisApi.getInstance().isShaderPackInUse();
}
@Override
public boolean isRenderingShadowPass()
{
return IrisApi.getInstance().isRenderingShadowPass();
}
}
#endif
+2 -2
View File
@@ -15,7 +15,7 @@ fabric_api_version=0.42.0+1.16
phosphor_version_fabric=
lithium_version=mc1.16.5-0.6.6
sodium_version=mc1.16.5-0.2.0
iris_version=1.16.x-v1.2.5
iris_version=1.4.4+1.16.5
bclib_version=
immersive_portals_version=
canvas_version=
@@ -30,7 +30,7 @@ fabric_api_version=0.42.0+1.16
enable_phosphor=0
enable_lithium=0
enable_sodium=1
enable_iris=0
enable_iris=1
# not available via github, use curse.maven if necessary
enable_bclib=0
enable_immersive_portals=0
+2 -2
View File
@@ -16,7 +16,7 @@ fabric_api_version=0.76.0+1.18.2
phosphor_version_fabric=3573395
lithium_version=mc1.18.2-0.10.3
sodium_version=mc1.18.2-0.4.1
iris_version=1.18.x-v1.6.4
iris_version=1.6.6+1.18.2
bclib_version=1.4.6
immersive_portals_version=v1.4.11-1.18
canvas_version=mc118:1.0.2616
@@ -31,7 +31,7 @@ fabric_api_version=0.76.0+1.18.2
enable_phosphor=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
+2 -2
View File
@@ -15,7 +15,7 @@ fabric_api_version=0.76.0+1.19.2
phosphor_version_fabric=
lithium_version=
sodium_version=mc1.19.2-0.4.4
iris_version=1.6.4+1.19.2
iris_version=1.6.6+1.19.2
bclib_version=2.1.6
immersive_portals_version=
canvas_version=mc119-1.0.2480
@@ -30,7 +30,7 @@ fabric_api_version=0.76.0+1.19.2
enable_phosphor=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
+2 -2
View File
@@ -15,7 +15,7 @@ fabric_api_version=0.83.0+1.19.4
phosphor_version_fabric=
lithium_version=
sodium_version=mc1.19.4-0.4.10
iris_version=1.6.4+1.19.4
iris_version=1.6.6+1.19.4
bclib_version=2.3.3
immersive_portals_version=
canvas_version=
@@ -30,7 +30,7 @@ fabric_api_version=0.83.0+1.19.4
enable_phosphor=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
+2 -2
View File
@@ -15,7 +15,7 @@ fabric_api_version=0.85.0+1.20.1
phosphor_version_fabric=
lithium_version=
sodium_version=mc1.20.1-0.5.1
iris_version=1.6.4+1.20.1
iris_version=1.6.8+1.20.1
bclib_version=3.0.12
immersive_portals_version=
canvas_version=
@@ -30,7 +30,7 @@ fabric_api_version=0.85.0+1.20.1
enable_phosphor=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0