Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c37a5c370 | |||
| b495ac4799 | |||
| 3721ebea6e | |||
| 98f8a87362 | |||
| 10a743ddef | |||
| 95c896f964 | |||
| 040bc16874 | |||
| 35d3fdb473 | |||
| 549f7510f7 | |||
| fab64d8477 | |||
| 4a6a35f617 | |||
| 2b519a826f | |||
| 445c01b5ae | |||
| 0f08bd540e | |||
| 77088465f9 | |||
| affe014433 | |||
| 4c06bf6dbd | |||
| dcab616385 | |||
| 89b7d08e9b | |||
| 724e318221 | |||
| a40d62d46a | |||
| 2f6b4c079b | |||
| 951e3c0271 | |||
| 84825c2d09 | |||
| ec627e2eba | |||
| 06bc9a349f | |||
| ff6c4e227b | |||
| a4d46ffe94 | |||
| bd5c140782 | |||
| 229c3f7c91 | |||
| 693369bc08 | |||
| d109fe6c43 | |||
| 3c9d3707cf | |||
| 6e53564835 | |||
| 2480fe0d86 | |||
| 691c9d3f45 | |||
| 3faf25636d | |||
| ab3bfbefb4 | |||
| 890e802de4 | |||
| c13bc0cd6e | |||
| 7143b7de08 | |||
| d136d782f5 | |||
| 29a160316c | |||
| 1f6f64d322 | |||
| 37c0af529d | |||
| 1341ea3f3d | |||
| c0bb120669 | |||
| f8887e403f | |||
| 949ee423c8 | |||
| b19ed3f30c | |||
| 2d085e1074 | |||
| 6ba0490cf7 | |||
| b6a0878241 | |||
| 50f5371084 | |||
| df74b8d243 | |||
| a36cd0763b |
@@ -29,7 +29,6 @@ buildAllJars/
|
|||||||
relocate_natives/.venv/
|
relocate_natives/.venv/
|
||||||
relocate_natives/__pycache__/
|
relocate_natives/__pycache__/
|
||||||
relocate_natives/apple-codesign/
|
relocate_natives/apple-codesign/
|
||||||
relocate_natives/cache/
|
|
||||||
|
|
||||||
# file from notepad++
|
# file from notepad++
|
||||||
*.bak
|
*.bak
|
||||||
|
|||||||
+1
-4
@@ -17,9 +17,6 @@ variables:
|
|||||||
# These can be extended so code is a bit less duplicated
|
# These can be extended so code is a bit less duplicated
|
||||||
.build_java:
|
.build_java:
|
||||||
#image: eclipse-temurin:17
|
#image: eclipse-temurin:17
|
||||||
before_script:
|
|
||||||
- apt-get update
|
|
||||||
- apt-get install python3 python3-pip python-is-python3 python3-venv -y --no-install-recommends
|
|
||||||
cache:
|
cache:
|
||||||
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
||||||
policy: pull-push
|
policy: pull-push
|
||||||
@@ -38,7 +35,7 @@ build:
|
|||||||
stage: build
|
stage: build
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
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", "1.21.1", "1.21.3", "1.21.4"]
|
- 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.1", "1.21.3", "1.21.4", "1.21.5"]
|
||||||
script:
|
script:
|
||||||
# this both runs the unit tests and assembles the code
|
# 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/;
|
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||||
|
|||||||
+7
-29
@@ -19,7 +19,7 @@ plugins {
|
|||||||
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
||||||
|
|
||||||
// Architectury is used here only as a replacement for forge's own loom
|
// Architectury is used here only as a replacement for forge's own loom
|
||||||
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
|
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,24 +106,12 @@ forgix {
|
|||||||
|
|
||||||
|
|
||||||
class NativeTransformer implements Transformer {
|
class NativeTransformer implements Transformer {
|
||||||
private boolean enabled = false
|
|
||||||
private final HashMap<String, String> replacements = new HashMap()
|
private final HashMap<String, String> replacements = new HashMap()
|
||||||
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||||
private var nativeRelocator
|
private var nativeRelocator
|
||||||
|
|
||||||
public File rootDir
|
public File rootDir
|
||||||
|
|
||||||
NativeTransformer() {
|
|
||||||
try {
|
|
||||||
int exitCode = Runtime.getRuntime().exec(new String[]{"python", "--version"}).waitFor()
|
|
||||||
if (exitCode == 0) {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
println(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void relocateNative(String target, String replacement) {
|
void relocateNative(String target, String replacement) {
|
||||||
if (replacement.length() > target.length()) {
|
if (replacement.length() > target.length()) {
|
||||||
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||||
@@ -132,22 +120,15 @@ class NativeTransformer implements Transformer {
|
|||||||
replacements.put(target, replacement)
|
replacements.put(target, replacement)
|
||||||
}
|
}
|
||||||
|
|
||||||
void before(Closure closure) {
|
|
||||||
if (enabled)
|
|
||||||
closure.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||||
return enabled && replacements.keySet().stream().anyMatch {
|
return replacements.keySet().stream().anyMatch {
|
||||||
element.name.startsWith(it as String)
|
element.name.startsWith(it as String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void transform(@Nonnull TransformerContext context) {
|
void transform(@Nonnull TransformerContext context) {
|
||||||
println("Transforming $context.path...")
|
|
||||||
byte[] content = context.is.readAllBytes()
|
byte[] content = context.is.readAllBytes()
|
||||||
|
|
||||||
if (nativeRelocator == null) {
|
if (nativeRelocator == null) {
|
||||||
@@ -395,16 +376,13 @@ subprojects { p ->
|
|||||||
// Sqlite Database
|
// Sqlite Database
|
||||||
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
||||||
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
||||||
|
relocate "org.sqlite", "dh_sqlite", {
|
||||||
|
exclude "org/sqlite/native/**"
|
||||||
|
}
|
||||||
|
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||||
|
|
||||||
transform(NativeTransformer) {
|
transform(NativeTransformer) {
|
||||||
rootDir = project.rootDir
|
rootDir = project.rootDir
|
||||||
|
|
||||||
before {
|
|
||||||
relocate "org.sqlite", "dh_sqlite", {
|
|
||||||
exclude "org/sqlite/native/**"
|
|
||||||
}
|
|
||||||
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
|
||||||
}
|
|
||||||
|
|
||||||
relocateNative "org/sqlite", "dh_sqlite"
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
relocateNative "org_sqlite", "dh_1sqlite"
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ for %%f in (versionProperties\*) do (
|
|||||||
|
|
||||||
@rem Clean out the folders, build it, and merge it
|
@rem Clean out the folders, build it, and merge it
|
||||||
echo ==================== Cleaning workspace to build !version! ====================
|
echo ==================== Cleaning workspace to build !version! ====================
|
||||||
call .\gradlew.bat clean -PmcVer="!version!"
|
call .\gradlew.bat clean
|
||||||
echo ==================== Building !version! ====================
|
echo ==================== Building !version! ====================
|
||||||
call .\gradlew.bat build -PmcVer="!version!"
|
call .\gradlew.bat build -PmcVer="!version!"
|
||||||
echo ==================== Merging !version! ====================
|
echo ==================== Merging !version! ====================
|
||||||
|
|||||||
@@ -12,14 +12,15 @@ class NativeRelocator
|
|||||||
/**
|
/**
|
||||||
* Initializes the NativeRelocator by preparing the environment if necessary.
|
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||||
* Executes the appropriate preparation script based on the OS.
|
* Executes the appropriate preparation script based on the OS.
|
||||||
*
|
|
||||||
* @throws Exception if the preparation script fails or an unsupported OS is detected.
|
|
||||||
*/
|
*/
|
||||||
NativeRelocator(Path rootDirectory) throws Exception
|
NativeRelocator(Path rootDirectory)
|
||||||
{
|
{
|
||||||
this.rootDirectory = rootDirectory;
|
this.rootDirectory = rootDirectory;
|
||||||
this.cacheRoot = this.rootDirectory.resolve("cache");
|
this.cacheRoot = this.rootDirectory.resolve("cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepare() throws Exception
|
||||||
|
{
|
||||||
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -31,7 +32,7 @@ class NativeRelocator
|
|||||||
String os = System.getProperty("os.name").toLowerCase();
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
if (os.contains("win"))
|
if (os.contains("win"))
|
||||||
{
|
{
|
||||||
processBuilder.command("powershell", "./prepare.ps1");
|
processBuilder.command("powershell", "-ExecutionPolicy", "Bypass", "./prepare.ps1");
|
||||||
}
|
}
|
||||||
else if (os.contains("nix") || os.contains("nux") || os.contains("mac"))
|
else if (os.contains("nix") || os.contains("nux") || os.contains("mac"))
|
||||||
{
|
{
|
||||||
@@ -196,6 +197,9 @@ class NativeRelocator
|
|||||||
return Files.readAllBytes(outputFilePath);
|
return Files.readAllBytes(outputFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("Relocating to " + outputPath + "...");
|
||||||
|
this.prepare();
|
||||||
|
|
||||||
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||||
{
|
{
|
||||||
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
||||||
|
|||||||
+37
-5
@@ -20,8 +20,6 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers;
|
package com.seibel.distanthorizons.common.wrappers;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
import net.minecraft.SharedConstants;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author James Seibel
|
* @author James Seibel
|
||||||
@@ -41,11 +39,45 @@ public class VersionConstants implements IVersionConstants
|
|||||||
@Override
|
@Override
|
||||||
public String getMinecraftVersion()
|
public String getMinecraftVersion()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_19_2
|
// these values are hard-coded to prevent an issue with Forge (specifically 1.18.2) where
|
||||||
return Minecraft.getInstance().getGame().getVersion().getId();
|
// it can't load client classes when running as a dedicated server,
|
||||||
|
// which was how we were dynamically accessing the MC version string
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_16_5
|
||||||
|
return "1.16.5";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_17_1
|
||||||
|
return "1.17.1";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_18_2
|
||||||
|
return "1.18.2";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_19_2
|
||||||
|
return "1.19.2";
|
||||||
|
#elif MC_VER == MC_1_19_4
|
||||||
|
return "1.19.4";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_20_1
|
||||||
|
return "1.20.1";
|
||||||
|
#elif MC_VER == MC_1_20_2
|
||||||
|
return "1.20.2";
|
||||||
|
#elif MC_VER == MC_1_20_4
|
||||||
|
return "1.20.4";
|
||||||
|
#elif MC_VER == MC_1_20_6
|
||||||
|
return "1.20.6";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_21_1
|
||||||
|
return "1.21.1";
|
||||||
|
#elif MC_VER == MC_1_21_3
|
||||||
|
return "1.21.3";
|
||||||
|
#elif MC_VER == MC_1_21_4
|
||||||
|
return "1.21.4";
|
||||||
|
#elif MC_VER == MC_1_21_5
|
||||||
|
return "1.21.5";
|
||||||
#else
|
#else
|
||||||
return SharedConstants.getCurrentVersion().getId();
|
ERROR MC version constant missing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+77
-29
@@ -97,16 +97,14 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
/** technically final, but since it requires a method call to generate it can't be marked as such */
|
/** technically final, but since it requires a method call to generate it can't be marked as such */
|
||||||
private String serialString;
|
private String serialString;
|
||||||
private final int hashCode;
|
private final int hashCode;
|
||||||
/**
|
/** Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE} */
|
||||||
* Cached opacity value, -1 if not populated. <br>
|
private final int opacity;
|
||||||
* Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE}
|
|
||||||
*/
|
|
||||||
private int opacity = -1;
|
|
||||||
/** used by the Iris shader mod to determine how each LOD should be rendered */
|
/** used by the Iris shader mod to determine how each LOD should be rendered */
|
||||||
private byte blockMaterialId = 0;
|
private byte blockMaterialId = 0;
|
||||||
|
|
||||||
private final boolean isBeaconBlock;
|
private final boolean isBeaconBlock;
|
||||||
private final boolean isBeaconBaseBlock;
|
private final boolean isBeaconBaseBlock;
|
||||||
|
private final boolean allowsBeaconBeamPassage;
|
||||||
/** null if this block can't tint beacons */
|
/** null if this block can't tint beacons */
|
||||||
private final Color beaconTintColor;
|
private final Color beaconTintColor;
|
||||||
private final Color mapColor;
|
private final Color mapColor;
|
||||||
@@ -163,9 +161,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
this.serialString = this.serialize(levelWrapper);
|
this.serialString = this.serialize(levelWrapper);
|
||||||
this.hashCode = Objects.hash(this.serialString);
|
this.hashCode = Objects.hash(this.serialString);
|
||||||
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
||||||
|
this.opacity = this.calculateOpacity();
|
||||||
|
|
||||||
|
String lowercaseSerial = this.serialString.toLowerCase();
|
||||||
|
|
||||||
|
|
||||||
// beacon blocks
|
// beacon blocks
|
||||||
String lowercaseSerial = this.serialString.toLowerCase();
|
|
||||||
boolean isBeaconBaseBlock = false;
|
boolean isBeaconBaseBlock = false;
|
||||||
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -201,6 +202,39 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
this.beaconTintColor = beaconTintColor;
|
this.beaconTintColor = beaconTintColor;
|
||||||
|
|
||||||
|
|
||||||
|
// allow/deny beacon beam passage
|
||||||
|
boolean allowsBeaconBeamPassage;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
// get block properties (defaults to the values used by air)
|
||||||
|
boolean canOcclude = this.getCanOcclude();
|
||||||
|
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||||
|
|
||||||
|
if (lowercaseSerial.contains("minecraft:bedrock"))
|
||||||
|
{
|
||||||
|
// bedrock is a special case fully opaque block that does allow beacons through
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
else if (propagatesSkyLightDown || !canOcclude)
|
||||||
|
{
|
||||||
|
// stairs, cake, fences, etc.
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non-opaque blocks (glass, mob spawners, etc.)
|
||||||
|
// all allow beacons through
|
||||||
|
allowsBeaconBeamPassage = (this.opacity != LodUtil.BLOCK_FULLY_OPAQUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// air allows beacons through
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
this.allowsBeaconBeamPassage = allowsBeaconBeamPassage;
|
||||||
|
|
||||||
|
|
||||||
int mcColor = 0;
|
int mcColor = 0;
|
||||||
if (this.blockState != null)
|
if (this.blockState != null)
|
||||||
{
|
{
|
||||||
@@ -344,28 +378,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
//=================//
|
//=================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOpacity()
|
public int getOpacity() { return this.opacity; }
|
||||||
|
private int calculateOpacity()
|
||||||
{
|
{
|
||||||
// use the cached opacity value if possible
|
// get block properties (defaults to the values used by air)
|
||||||
if (this.opacity != -1)
|
boolean canOcclude = this.getCanOcclude();
|
||||||
{
|
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||||
return this.opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// get block properties (default to the values used by air)
|
|
||||||
boolean canOcclude = false;
|
|
||||||
boolean propagatesSkyLightDown = true;
|
|
||||||
if (this.blockState != null)
|
|
||||||
{
|
|
||||||
canOcclude = this.blockState.canOcclude();
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
|
||||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
|
||||||
#else
|
|
||||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -398,9 +416,37 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.opacity = opacity;
|
return opacity;
|
||||||
return this.opacity;
|
|
||||||
}
|
}
|
||||||
|
private boolean getCanOcclude()
|
||||||
|
{
|
||||||
|
// defaults to the value used by air
|
||||||
|
boolean canOcclude = false;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
canOcclude = this.blockState.canOcclude();
|
||||||
|
}
|
||||||
|
|
||||||
|
return canOcclude;
|
||||||
|
}
|
||||||
|
private boolean getPropagatesSkyLightDown()
|
||||||
|
{
|
||||||
|
// defaults to the value used by air
|
||||||
|
boolean propagatesSkyLightDown = true;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||||
|
#else
|
||||||
|
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return propagatesSkyLightDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
||||||
@@ -473,6 +519,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
||||||
@Override
|
@Override
|
||||||
public boolean isBeaconTintBlock() { return this.beaconTintColor != null; }
|
public boolean isBeaconTintBlock() { return this.beaconTintColor != null; }
|
||||||
|
@Override
|
||||||
|
public boolean allowsBeaconBeamPassage() { return this.allowsBeaconBeamPassage; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color getMapColor() { return this.mapColor; }
|
public Color getMapColor() { return this.mapColor; }
|
||||||
|
|||||||
+73
-16
@@ -40,11 +40,18 @@ import java.util.Random;
|
|||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.renderer.block.model.BlockModelPart;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This stores and calculates the colors
|
* This stores and calculates the colors
|
||||||
* the given {@link BlockState} should have based
|
* the given {@link BlockState} should have based
|
||||||
@@ -196,9 +203,7 @@ public class ClientBlockStateColorCache
|
|||||||
List<BakedQuad> quads = null;
|
List<BakedQuad> quads = null;
|
||||||
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
||||||
{
|
{
|
||||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
quads = this.getQuadsForDirection(direction);
|
||||||
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
|
||||||
|
|
||||||
if (quads != null && !quads.isEmpty()
|
if (quads != null && !quads.isEmpty()
|
||||||
&& !(
|
&& !(
|
||||||
this.blockState.getBlock() instanceof RotatedPillarBlock
|
this.blockState.getBlock() instanceof RotatedPillarBlock
|
||||||
@@ -212,19 +217,37 @@ public class ClientBlockStateColorCache
|
|||||||
|
|
||||||
if (quads == null || quads.isEmpty())
|
if (quads == null || quads.isEmpty())
|
||||||
{
|
{
|
||||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
quads = this.getUnculledQuads();
|
||||||
getBlockModel(this.blockState).getQuads(this.blockState, null, RANDOM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quads != null && !quads.isEmpty())
|
if (quads != null
|
||||||
|
&& !quads.isEmpty()
|
||||||
|
&& quads.get(0) != null)
|
||||||
{
|
{
|
||||||
this.needPostTinting = quads.get(0).isTinted();
|
BakedQuad firstQuad = quads.get(0);
|
||||||
this.needShade = quads.get(0).isShade();
|
|
||||||
this.tintIndex = quads.get(0).getTintIndex();
|
this.needPostTinting = firstQuad.isTinted();
|
||||||
|
#if MC_VER <= MC_1_21_4
|
||||||
|
this.needShade = firstQuad.isShade();
|
||||||
|
this.tintIndex = firstQuad.getTintIndex();
|
||||||
|
#else
|
||||||
|
this.needShade = firstQuad.shade();
|
||||||
|
this.tintIndex = firstQuad.tintIndex();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_17_1
|
||||||
this.baseColor = calculateColorFromTexture(
|
this.baseColor = calculateColorFromTexture(
|
||||||
#if MC_VER < MC_1_17_1 quads.get(0).sprite,
|
firstQuad.sprite,
|
||||||
#else quads.get(0).getSprite(), #endif
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
#elif MC_VER < MC_1_21_5
|
||||||
|
this.baseColor = calculateColorFromTexture(
|
||||||
|
firstQuad.getSprite(),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
#else
|
||||||
|
this.baseColor = calculateColorFromTexture(
|
||||||
|
firstQuad.sprite(),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -232,8 +255,7 @@ public class ClientBlockStateColorCache
|
|||||||
this.needPostTinting = false;
|
this.needPostTinting = false;
|
||||||
this.needShade = false;
|
this.needShade = false;
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
this.baseColor = this.getParticleIconColor();
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -242,8 +264,7 @@ public class ClientBlockStateColorCache
|
|||||||
this.needPostTinting = true;
|
this.needPostTinting = true;
|
||||||
this.needShade = false;
|
this.needShade = false;
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
this.baseColor = this.getParticleIconColor();
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isColorResolved = true;
|
this.isColorResolved = true;
|
||||||
@@ -253,6 +274,35 @@ public class ClientBlockStateColorCache
|
|||||||
RESOLVE_LOCK.unlock();
|
RESOLVE_LOCK.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); }
|
||||||
|
@Nullable
|
||||||
|
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
|
||||||
|
{
|
||||||
|
List<BakedQuad> quads = null;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||||
|
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
||||||
|
#else
|
||||||
|
List<BlockModelPart> blockModelPartList = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||||
|
getBlockModel(this.blockState).collectParts(RANDOM);
|
||||||
|
|
||||||
|
quads = new ArrayList<>();
|
||||||
|
if (blockModelPartList != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < blockModelPartList.size(); i++)
|
||||||
|
{
|
||||||
|
// if direction is null this will return the unculled quads
|
||||||
|
quads.addAll(blockModelPartList.get(i).getQuads(direction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return quads;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Perhaps make this not just use the first frame?
|
//TODO: Perhaps make this not just use the first frame?
|
||||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
||||||
{
|
{
|
||||||
@@ -383,6 +433,13 @@ public class ClientBlockStateColorCache
|
|||||||
return (bias + (scale * t)) >>> 16;
|
return (bias + (scale * t)) >>> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getParticleIconColor()
|
||||||
|
{
|
||||||
|
return calculateColorFromTexture(
|
||||||
|
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============//
|
//===============//
|
||||||
|
|||||||
+49
-24
@@ -19,19 +19,16 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.*;
|
import net.minecraft.world.level.*;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.biome.Biomes;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -46,46 +43,74 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
|||||||
* but {@link Nullable} is there just in case.
|
* but {@link Nullable} is there just in case.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Biome biome;
|
#if MC_VER >= MC_1_18_2
|
||||||
|
public final Holder<Biome> biome;
|
||||||
|
#else
|
||||||
|
public final Biome biome;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the TintWithoutLevelOverrider, storing the provided Biome Holder for late-binding access.
|
||||||
|
*
|
||||||
|
* <p>Previously, this class might have immediately unwrapped the Holder like this:</p>
|
||||||
|
* <pre>{@code
|
||||||
|
* // Inside constructor (OLD WAY - PROBLEMATIC):
|
||||||
|
* Holder<Biome> biomeHolder = getTheHolderFromSomewhere();
|
||||||
|
* this.biome = biomeHolder.value(); // <-- PROBLEM HERE
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>This approach is problematic because the {@link net.minecraft.core.Holder} system,
|
||||||
|
* particularly {@code Holder.Reference}, is designed for <strong>late binding</strong>. Here's why storing
|
||||||
|
* the Holder itself is now necessary:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>A {@code Holder.Reference<Biome>} might be created initially just with a
|
||||||
|
* {@link net.minecraft.resources.ResourceKey} (like {@code minecraft:plains}), but its actual
|
||||||
|
* {@link net.minecraft.core.Holder#value() value()} (the {@code Biome} object itself) might be {@code null}
|
||||||
|
* at construction time.</li>
|
||||||
|
* <li>Later, during game loading, registry population, or potentially due to modifications by other mods
|
||||||
|
* (e.g., Polytone), the system calls internal binding methods (like {@code bindValue(Biome)})
|
||||||
|
* on the {@code Holder} instance. This sets or <strong>updates</strong> the internal reference to the
|
||||||
|
* actual {@code Biome} object.</li>
|
||||||
|
* <li>Crucially, the binding process might assign a completely <strong>new</strong> {@code Biome} object
|
||||||
|
* instance to the {@code Holder} reference, replacing any previous one.</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* <p>If we unwrapped the {@code Holder} using {@code .value()} within the constructor (the old way),
|
||||||
|
* our class's internal {@code biome} field would permanently store a reference to whatever {@code Biome}
|
||||||
|
* object the {@code Holder} pointed to *at that exact moment*. It would have no link back to the
|
||||||
|
* {@code Holder} and would be unaware if the {@code Holder} was later updated to point to a different
|
||||||
|
* (or the initially missing) {@code Biome} object. This would lead to using stale or even {@code null} data.</p>
|
||||||
|
*
|
||||||
|
* <p>By storing the {@code Holder<Biome>} itself, this class can call {@link net.minecraft.core.Holder#value()}
|
||||||
|
* whenever the biome information is needed, ensuring it always retrieves the most current {@code Biome}
|
||||||
|
* instance associated with the holder at that time.</p>
|
||||||
|
*/
|
||||||
public TintWithoutLevelOverrider(BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
public TintWithoutLevelOverrider(BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||||
{
|
{
|
||||||
// try to get the wrapped biome
|
#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome = biomeWrapper.biome;
|
||||||
Biome unwrappedBiome = null;
|
if (biome == null) // We are looking at the empty biome wrapper
|
||||||
if (biomeWrapper.biome != null)
|
|
||||||
{
|
{
|
||||||
unwrappedBiome = unwrap(biomeWrapper.biome);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(unwrappedBiome == null)
|
|
||||||
{
|
|
||||||
// we are looking at the empty biome wrapper, try using plains as a backup
|
|
||||||
BiomeWrapper plainsBiomeWrapper = ((BiomeWrapper) clientLevelWrapper.getPlainsBiomeWrapper());
|
BiomeWrapper plainsBiomeWrapper = ((BiomeWrapper) clientLevelWrapper.getPlainsBiomeWrapper());
|
||||||
if (plainsBiomeWrapper != null)
|
if (plainsBiomeWrapper != null)
|
||||||
{
|
{
|
||||||
unwrappedBiome = unwrap(plainsBiomeWrapper.biome);
|
biome = plainsBiomeWrapper.biome;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.biome = unwrappedBiome;
|
this.biome = biome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||||
{
|
{
|
||||||
if (this.biome != null)
|
if (this.biome == null)
|
||||||
{
|
|
||||||
return colorResolver.getColor(this.biome, blockPos.getX(), blockPos.getZ());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// hopefully unneeded debug color
|
// hopefully unneeded debug color
|
||||||
return ColorUtil.CYAN;
|
return ColorUtil.CYAN;
|
||||||
}
|
}
|
||||||
|
return colorResolver.getColor(unwrap(biome), blockPos.getX(), blockPos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Biome unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
private static Biome unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||||
|
|||||||
+17
-2
@@ -19,7 +19,11 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#elif MC_VER == MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.opengl.GlStateManager;
|
||||||
|
#endif
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
@@ -148,7 +152,10 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
public void glBlendFunc(int sfactor, int dfactor)
|
public void glBlendFunc(int sfactor, int dfactor)
|
||||||
{
|
{
|
||||||
GL32.glBlendFunc(sfactor, dfactor);
|
GL32.glBlendFunc(sfactor, dfactor);
|
||||||
GlStateManager._blendFunc(sfactor, dfactor);
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
GlStateManager._blendFunc(sfactor, dfactor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/** @see GL32#glBlendFuncSeparate */
|
/** @see GL32#glBlendFuncSeparate */
|
||||||
@Override
|
@Override
|
||||||
@@ -180,7 +187,15 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
/** @see GL32#glDeleteBuffers(int) */
|
/** @see GL32#glDeleteBuffers(int) */
|
||||||
@Override
|
@Override
|
||||||
public void glDeleteBuffers(int buffer)
|
public void glDeleteBuffers(int buffer)
|
||||||
{ GlStateManager._glDeleteBuffers(buffer); }
|
{
|
||||||
|
GL32.glDeleteBuffers(buffer);
|
||||||
|
|
||||||
|
// MC's implementation has a bug where it will throw:
|
||||||
|
// GL_INVALID_OPERATION in glBufferData(immutable)
|
||||||
|
// when attempting to delete Storage Buffers
|
||||||
|
// So we need to manually delete the buffers ourselves
|
||||||
|
//GlStateManager._glDeleteBuffers(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// culling //
|
// culling //
|
||||||
|
|||||||
+95
-4
@@ -71,6 +71,10 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton that contains everything
|
* A singleton that contains everything
|
||||||
@@ -102,8 +106,15 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
*/
|
*/
|
||||||
public int finalLevelFrameBufferId = -1;
|
public int finalLevelFrameBufferId = -1;
|
||||||
|
|
||||||
|
public boolean colorTextureCastFailLogged = false;
|
||||||
|
public boolean depthTextureCastFailLogged = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3f getLookAtVector()
|
public Vec3f getLookAtVector()
|
||||||
{
|
{
|
||||||
@@ -250,6 +261,26 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
|
|
||||||
private RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
private RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mcRendersToFrameBuffer()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean runningLegacyOpenGL()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_16_5
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBuffer()
|
public int getTargetFrameBuffer()
|
||||||
{
|
{
|
||||||
@@ -259,27 +290,87 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
return this.finalLevelFrameBufferId;
|
return this.finalLevelFrameBufferId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
return this.getRenderTarget().frameBufferId;
|
return this.getRenderTarget().frameBufferId;
|
||||||
|
#else
|
||||||
|
// MC renders to a texture and then directly to the default FBO now
|
||||||
|
// we need to draw to their texture instead of the FBO
|
||||||
|
return 0; // 0 is the ID for the default frame buffer
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearTargetFrameBuffer() { this.finalLevelFrameBufferId = -1; }
|
public void clearTargetFrameBuffer() { this.finalLevelFrameBufferId = -1; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDepthTextureId() { return this.getRenderTarget().getDepthTextureId(); }
|
public int getDepthTextureId()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return this.getRenderTarget().getDepthTextureId();
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GlTexture glTexture = (GlTexture) this.getRenderTarget().getDepthTexture();
|
||||||
|
if (glTexture == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glTexture.glId();
|
||||||
|
}
|
||||||
|
catch (ClassCastException e)
|
||||||
|
{
|
||||||
|
// only log this error once per session
|
||||||
|
if (!this.depthTextureCastFailLogged)
|
||||||
|
{
|
||||||
|
this.depthTextureCastFailLogged = true;
|
||||||
|
LOGGER.error("Unable to cast render Target depth texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public int getColorTextureId() { return this.getRenderTarget().getColorTextureId(); }
|
public int getColorTextureId()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return this.getRenderTarget().getColorTextureId();
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GlTexture glTexture = (GlTexture) this.getRenderTarget().getColorTexture();
|
||||||
|
if (glTexture == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glTexture.glId();
|
||||||
|
}
|
||||||
|
catch (ClassCastException e)
|
||||||
|
{
|
||||||
|
// only log this error once per session
|
||||||
|
if (!this.colorTextureCastFailLogged)
|
||||||
|
{
|
||||||
|
this.colorTextureCastFailLogged = true;
|
||||||
|
LOGGER.error("Unable to cast render Target color texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportWidth()
|
public int getTargetFrameBufferViewportWidth()
|
||||||
{
|
{
|
||||||
return getRenderTarget().viewWidth;
|
return this.getRenderTarget().viewWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportHeight()
|
public int getTargetFrameBufferViewportHeight()
|
||||||
{
|
{
|
||||||
return getRenderTarget().viewHeight;
|
return this.getRenderTarget().viewHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+18
-1
@@ -21,8 +21,10 @@ package com.seibel.distanthorizons.common.wrappers.misc;
|
|||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -30,6 +32,7 @@ import java.nio.ByteBuffer;
|
|||||||
public class LightMapWrapper implements ILightMapWrapper
|
public class LightMapWrapper implements ILightMapWrapper
|
||||||
{
|
{
|
||||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||||
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
private int textureId = 0;
|
private int textureId = 0;
|
||||||
|
|
||||||
@@ -49,6 +52,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
|
|
||||||
public void uploadLightmap(NativeImage image)
|
public void uploadLightmap(NativeImage image)
|
||||||
{
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
int currentTexture = GLMC.getActiveTexture();
|
int currentTexture = GLMC.getActiveTexture();
|
||||||
if (this.textureId == 0)
|
if (this.textureId == 0)
|
||||||
{
|
{
|
||||||
@@ -59,14 +63,27 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
GLMC.glBindTexture(this.textureId);
|
GLMC.glBindTexture(this.textureId);
|
||||||
}
|
}
|
||||||
image.upload(0, 0, 0, false);
|
image.upload(0, 0, 0, false);
|
||||||
GLMC.glBindTexture(currentTexture);
|
|
||||||
|
// getActiveTexture() may return textures that aren't valid and attempting to bind them will
|
||||||
|
// throw a GL error in MC 1.21.1
|
||||||
|
if (GL32.glIsTexture(currentTexture))
|
||||||
|
{
|
||||||
|
GLMC.glBindTexture(currentTexture);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
private void createLightmap(NativeImage image)
|
private void createLightmap(NativeImage image)
|
||||||
{
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
this.textureId = GLMC.glGenTextures();
|
this.textureId = GLMC.glGenTextures();
|
||||||
GLMC.glBindTexture(this.textureId);
|
GLMC.glBindTexture(this.textureId);
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
||||||
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||||
|
#else
|
||||||
|
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLightmapId(int minecraftLightmapTetxureId)
|
public void setLightmapId(int minecraftLightmapTetxureId)
|
||||||
|
|||||||
+28
-7
@@ -25,7 +25,6 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkSource;
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -33,6 +32,10 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
@@ -42,6 +45,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
#else
|
#else
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
#endif
|
#endif
|
||||||
@@ -49,7 +53,12 @@ import com.seibel.distanthorizons.core.util.ColorUtil;
|
|||||||
public class ClientLevelWrapper implements IClientLevelWrapper
|
public class ClientLevelWrapper implements IClientLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
||||||
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); // TODO can leak
|
/**
|
||||||
|
* weak references are to prevent rare issues
|
||||||
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
|
* and/or for servers were the level object isn't consistent
|
||||||
|
*/
|
||||||
|
private static final Map<ClientLevel, WeakReference<ClientLevelWrapper>> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
||||||
|
|
||||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||||
@@ -72,9 +81,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============//
|
//==================//
|
||||||
// wrapper logic //
|
// instance methods //
|
||||||
//===============//
|
//==================//
|
||||||
|
|
||||||
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
|
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
|
||||||
|
|
||||||
@@ -96,7 +105,19 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new);
|
return LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.compute(level, (newLevel, levelRef) ->
|
||||||
|
{
|
||||||
|
if (levelRef != null)
|
||||||
|
{
|
||||||
|
ClientLevelWrapper oldLevelWrapper = levelRef.get();
|
||||||
|
if (oldLevelWrapper != null)
|
||||||
|
{
|
||||||
|
return levelRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WeakReference<>(new ClientLevelWrapper(newLevel));
|
||||||
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -265,7 +286,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
@Override
|
@Override
|
||||||
public void onUnload()
|
public void onUnload()
|
||||||
{
|
{
|
||||||
LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level);
|
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.remove(this.level);
|
||||||
this.parentDhLevel = null;
|
this.parentDhLevel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
-6
@@ -20,6 +20,10 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.world;
|
package com.seibel.distanthorizons.common.wrappers.world;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||||
@@ -57,7 +61,11 @@ import org.apache.logging.log4j.Logger;
|
|||||||
public class ServerLevelWrapper implements IServerLevelWrapper
|
public class ServerLevelWrapper implements IServerLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper> LEVEL_WRAPPER_BY_SERVER_LEVEL = new ConcurrentHashMap<>();
|
/**
|
||||||
|
* weak references are to prevent rare issues
|
||||||
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
|
*/
|
||||||
|
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
|
|
||||||
private final ServerLevel level;
|
private final ServerLevel level;
|
||||||
@Deprecated // TODO circular references are bad
|
@Deprecated // TODO circular references are bad
|
||||||
@@ -70,15 +78,29 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
public static ServerLevelWrapper getWrapper(ServerLevel level)
|
public static ServerLevelWrapper getWrapper(ServerLevel level)
|
||||||
{ return LEVEL_WRAPPER_BY_SERVER_LEVEL.computeIfAbsent(level, ServerLevelWrapper::new); }
|
{
|
||||||
|
return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) ->
|
||||||
|
{
|
||||||
|
if (levelRef != null)
|
||||||
|
{
|
||||||
|
ServerLevelWrapper oldLevelWrapper = levelRef.get();
|
||||||
|
if (oldLevelWrapper != null)
|
||||||
|
{
|
||||||
|
return levelRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WeakReference<>(new ServerLevelWrapper(newLevel));
|
||||||
|
}).get();
|
||||||
|
}
|
||||||
|
|
||||||
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========//
|
//==================//
|
||||||
// methods //
|
// instance methods //
|
||||||
//=========//
|
//==================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getMcSaveFolder()
|
public File getMcSaveFolder()
|
||||||
@@ -93,6 +115,8 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
@Override
|
@Override
|
||||||
public String getWorldFolderName()
|
public String getWorldFolderName()
|
||||||
{
|
{
|
||||||
|
// TODO can we just replace this with getMcSaveFolder()? Why are we using the screenshot file anyway?
|
||||||
|
// this can have issues when the screenshot file is null/missing
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER >= MC_1_17_1
|
||||||
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
|
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
|
||||||
#else // <= 1.16.5
|
#else // <= 1.16.5
|
||||||
@@ -179,7 +203,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
public ServerLevel getWrappedMcObject() { return this.level; }
|
public ServerLevel getWrappedMcObject() { return this.level; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); }
|
public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+12
@@ -113,7 +113,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
||||||
() -> Config.Common.Logging.logWorldGenLoadEvent.get());
|
() -> Config.Common.Logging.logWorldGenLoadEvent.get());
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
|
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
|
||||||
|
#else
|
||||||
|
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING);
|
||||||
|
#endif
|
||||||
|
|
||||||
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
|
||||||
@@ -878,7 +882,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
chunkLevel = generateUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
chunkLevel = generateUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||||
|
#else
|
||||||
|
level.getChunkSource().addTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||||
|
#endif
|
||||||
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap); // probably not the most optimal to run updates here, but fast enough
|
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap); // probably not the most optimal to run updates here, but fast enough
|
||||||
ChunkHolder holder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
ChunkHolder holder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
||||||
if (holder == null)
|
if (holder == null)
|
||||||
@@ -915,7 +923,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
chunkLevel = chunkWasGeneratedUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
chunkLevel = chunkWasGeneratedUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||||
|
#else
|
||||||
|
level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// mitigate OOM issues in vanilla chunk system: see https://github.com/pop4959/Chunky/pull/383
|
// mitigate OOM issues in vanilla chunk system: see https://github.com/pop4959/Chunky/pull/383
|
||||||
level.getChunkSource().chunkMap.tick(() -> false);
|
level.getChunkSource().chunkMap.tick(() -> false);
|
||||||
|
|||||||
+328
-108
@@ -29,7 +29,9 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.shorts.ShortList;
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||||||
@@ -84,11 +86,13 @@ import net.minecraft.world.level.chunk.status.ChunkType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|
||||||
public class ChunkLoader
|
public class ChunkLoader
|
||||||
{
|
{
|
||||||
private static boolean zeroChunkPosErrorLogged = false;
|
private static final AtomicBoolean ZERO_CHUNK_POS_ERROR_LOGGED_REF = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||||
@@ -120,19 +124,16 @@ public class ChunkLoader
|
|||||||
CompoundTag tagLevel = chunkData;
|
CompoundTag tagLevel = chunkData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
|
int chunkX = tagGetInt(tagLevel,"xPos");
|
||||||
|
int chunkZ = tagGetInt(tagLevel, "zPos");
|
||||||
|
ChunkPos actualPos = new ChunkPos(chunkX, chunkZ);
|
||||||
|
|
||||||
if (!Objects.equals(chunkPos, actualPos))
|
if (!Objects.equals(chunkPos, actualPos))
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_18_2
|
if (chunkX == 0 && chunkZ == 0)
|
||||||
if (actualPos.equals(ChunkPos.ZERO))
|
|
||||||
#else
|
|
||||||
if (actualPos.equals(ChunkPos.INVALID_CHUNK_POS))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (!zeroChunkPosErrorLogged)
|
if (!ZERO_CHUNK_POS_ERROR_LOGGED_REF.getAndSet(true))
|
||||||
{
|
{
|
||||||
zeroChunkPosErrorLogged = true;
|
|
||||||
|
|
||||||
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
||||||
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
||||||
"This might happen if the world was created using an external program. \n" +
|
"This might happen if the world was created using an external program. \n" +
|
||||||
@@ -174,14 +175,27 @@ public class ChunkLoader
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
long inhabitedTime = tagGetLong(tagLevel, "InhabitedTime");
|
||||||
|
|
||||||
//================== Read params for making the LevelChunk ==================
|
//================== Read params for making the LevelChunk ==================
|
||||||
UpgradeData upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
|
||||||
? new UpgradeData(tagLevel.getCompound(TAG_UPGRADE_DATA)#if MC_VER >= MC_1_17_1 , level #endif )
|
|
||||||
: UpgradeData.EMPTY;
|
|
||||||
|
|
||||||
boolean isLightOn = tagLevel.getBoolean("isLightOn");
|
UpgradeData upgradeData;
|
||||||
|
#if MC_VER < MC_1_17_1
|
||||||
|
upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
||||||
|
? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA))
|
||||||
|
: UpgradeData.EMPTY;
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
|
upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
||||||
|
? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
||||||
|
: UpgradeData.EMPTY;
|
||||||
|
#else
|
||||||
|
upgradeData = tagLevel.contains(TAG_UPGRADE_DATA)
|
||||||
|
? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
||||||
|
: UpgradeData.EMPTY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
boolean isLightOn = tagGetBoolean(tagLevel, "isLightOn");
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
||||||
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
||||||
@@ -198,17 +212,21 @@ public class ChunkLoader
|
|||||||
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
||||||
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
||||||
#else
|
#else
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
#else
|
#elif MC_VER < MC_1_21_4
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||||
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||||
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
#endif
|
#else
|
||||||
|
// do we need the ticks for what we're doing?
|
||||||
|
LevelChunkTicks<Block> blockTicks = new LevelChunkTicks<>();
|
||||||
|
LevelChunkTicks<Fluid> fluidTicks = new LevelChunkTicks<>();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
||||||
@@ -218,7 +236,6 @@ public class ChunkLoader
|
|||||||
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null);
|
fluidTicks, inhabitedTime, levelChunkSections, null);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
||||||
#endif
|
#endif
|
||||||
@@ -252,18 +269,23 @@ public class ChunkLoader
|
|||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
||||||
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
||||||
|
|
||||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
ListTag tagSections = tagGetListTag(chunkData, "Sections", 10);
|
||||||
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
if (tagSections == null || tagSections.isEmpty())
|
||||||
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);
|
tagSections = tagGetListTag(chunkData, "sections", 10);
|
||||||
int sectionYPos = tagSection.getByte("Y");
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (tagSections != null)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < tagSections.size(); ++j)
|
||||||
|
{
|
||||||
|
CompoundTag tagSection = tagGetCompoundTag(tagSections, j);
|
||||||
|
int sectionYPos = tagGetByte(tagSection, "Y");
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||||
@@ -277,65 +299,89 @@ public class ChunkLoader
|
|||||||
= levelChunkSection;
|
= levelChunkSection;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||||
if (sectionId >= 0 && sectionId < chunkSections.length)
|
if (sectionId >= 0 && sectionId < chunkSections.length)
|
||||||
{
|
{
|
||||||
PalettedContainer<BlockState> blockStateContainer;
|
PalettedContainer<BlockState> blockStateContainer;
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
PalettedContainer<Biome> biomeContainer;
|
PalettedContainer<Biome> biomeContainer;
|
||||||
#else
|
#else
|
||||||
PalettedContainer<Holder<Biome>> biomeContainer;
|
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
boolean containsBlockStates;
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
containsBlockStates = tagSection.contains("block_states", 10);
|
||||||
|
#else
|
||||||
|
containsBlockStates = tagSection.contains("block_states");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (containsBlockStates)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||||
|
#else
|
||||||
|
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blockStateContainer = new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
blockStateContainer = tagSection.contains("block_states", 10)
|
|
||||||
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states"))
|
|
||||||
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
.getOrThrow(false, (message) -> logWarningOnce(message))
|
|
||||||
#else
|
|
||||||
.getOrThrow((message) -> logErrorAndReturnException(message))
|
|
||||||
#endif
|
|
||||||
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
biomeContainer = tagSection.contains("biomes", 10)
|
biomeContainer = tagSection.contains("biomes", 10)
|
||||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
||||||
if (tagSection.contains("biomes", 10))
|
boolean containsBiomes;
|
||||||
{
|
#if MC_VER < MC_1_21_5
|
||||||
biomeContainer =
|
containsBiomes = tagSection.contains("biomes", 10);
|
||||||
biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes"))
|
#else
|
||||||
|
containsBiomes = tagSection.contains("biomes");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (containsBiomes)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||||
|
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||||
|
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||||
|
#else
|
||||||
|
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||||
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||||
#if MC_VER < MC_1_20_6
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
.getOrThrow(false, (message) -> logWarningOnce(message));
|
#endif
|
||||||
#else
|
}
|
||||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
else
|
||||||
#endif
|
{
|
||||||
}
|
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
||||||
else
|
|
||||||
{
|
|
||||||
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
biomes.getHolderOrThrow(Biomes.PLAINS),
|
biomes.getHolderOrThrow(Biomes.PLAINS),
|
||||||
#else
|
#else
|
||||||
biomes.getOrThrow(Biomes.PLAINS),
|
biomes.getOrThrow(Biomes.PLAINS),
|
||||||
#endif
|
#endif
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_1
|
#if MC_VER < MC_1_20_1
|
||||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||||
#else
|
#else
|
||||||
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return chunkSections;
|
return chunkSections;
|
||||||
}
|
}
|
||||||
@@ -345,39 +391,54 @@ public class ChunkLoader
|
|||||||
#else ChunkType #endif
|
#else ChunkType #endif
|
||||||
readChunkType(CompoundTag tagLevel)
|
readChunkType(CompoundTag tagLevel)
|
||||||
{
|
{
|
||||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
ChunkStatus chunkStatus = ChunkStatus.byName(tagGetString(tagLevel,"Status"));
|
||||||
if (chunkStatus != null)
|
if (chunkStatus != null)
|
||||||
{
|
{
|
||||||
return chunkStatus.getChunkType();
|
return chunkStatus.getChunkType();
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
#if MC_VER <= MC_1_20_4
|
||||||
#if MC_VER <= MC_1_20_4 ChunkStatus.ChunkType.PROTOCHUNK;
|
return ChunkStatus.ChunkType.PROTOCHUNK;
|
||||||
#else ChunkType.PROTOCHUNK; #endif
|
#else
|
||||||
|
return ChunkType.PROTOCHUNK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
CompoundTag tagHeightmaps = tagGetCompoundTag(chunkData, "Heightmaps");
|
||||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||||
{
|
{
|
||||||
String heightmap = type.getSerializationKey();
|
String heightmap = type.getSerializationKey();
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
if (tagHeightmaps.contains(heightmap, 12))
|
if (tagHeightmaps.contains(heightmap, 12))
|
||||||
|
{
|
||||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (tagHeightmaps.contains(heightmap))
|
||||||
|
{
|
||||||
|
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmap);
|
||||||
|
if (optionalHeightmap.isPresent())
|
||||||
|
{
|
||||||
|
chunk.setHeightmap(type, optionalHeightmap.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||||
}
|
}
|
||||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
ListTag tagPostProcessings = tagGetListTag(chunkData,"PostProcessing", 9);
|
||||||
for (int i = 0; i < tagPostProcessings.size(); ++i)
|
for (int i = 0; i < tagPostProcessings.size(); ++i)
|
||||||
{
|
{
|
||||||
ListTag listTag3 = tagPostProcessings.getList(i);
|
ListTag listTag3 = tagGetListTag(tagPostProcessings, i);
|
||||||
for (int j = 0; j < listTag3.size(); ++j)
|
for (int j = 0; j < listTag3.size(); ++j)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
||||||
#else
|
#else
|
||||||
chunk.addPackedPostProcess(ShortList.of(listTag3.getShort(j)), i);
|
chunk.addPackedPostProcess(ShortList.of(tagGetShort(listTag3, j)), i);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,16 +447,38 @@ public class ChunkLoader
|
|||||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
BlendingData blendingData = null;
|
BlendingData blendingData = null;
|
||||||
if (chunkData.contains("blending_data", 10))
|
|
||||||
|
|
||||||
|
boolean containsBlendingData;
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
containsBlendingData = chunkData.contains("blending_data", 10);
|
||||||
|
#else
|
||||||
|
containsBlendingData = chunkData.contains("blending_data");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (containsBlendingData)
|
||||||
{
|
{
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
try
|
||||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null);
|
{
|
||||||
#else
|
#if MC_VER < MC_1_21_3
|
||||||
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null));
|
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null);
|
||||||
#endif
|
#else
|
||||||
|
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message == null || message.trim().isEmpty())
|
||||||
|
{
|
||||||
|
message = "Failed to parse blending data";
|
||||||
|
}
|
||||||
|
|
||||||
|
logParsingWarningOnce(message, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return blendingData;
|
return blendingData;
|
||||||
}
|
}
|
||||||
@@ -472,33 +555,37 @@ public class ChunkLoader
|
|||||||
|
|
||||||
|
|
||||||
// if null all lights = 0
|
// if null all lights = 0
|
||||||
byte[] blockLightNibbleArray = chunkSectionCompoundTag.getByteArray("BlockLight");
|
byte[] blockLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "BlockLight");
|
||||||
byte[] skyLightNibbleArray = chunkSectionCompoundTag.getByteArray("SkyLight");
|
byte[] skyLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "SkyLight");
|
||||||
|
|
||||||
// if any sky light was found then all lights above will be max brightness
|
if (blockLightNibbleArray != null
|
||||||
if (skyLightNibbleArray.length != 0)
|
&& skyLightNibbleArray != null)
|
||||||
{
|
{
|
||||||
foundSkyLight = true;
|
// if any sky light was found then all lights above will be max brightness
|
||||||
}
|
if (skyLightNibbleArray.length != 0)
|
||||||
|
|
||||||
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
|
foundSkyLight = true;
|
||||||
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
}
|
||||||
|
|
||||||
|
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||||
|
{
|
||||||
|
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||||
{
|
{
|
||||||
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
// chunk sections are also 16 blocks tall
|
||||||
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||||
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
|
||||||
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
|
||||||
{
|
{
|
||||||
skyLight = LodUtil.MAX_MC_LIGHT;
|
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.getInclusiveMinBuildHeight(chunk);
|
||||||
|
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||||
|
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
|
||||||
blockLightStorage.set(relX, y, relZ, blockLight);
|
|
||||||
skyLightStorage.set(relX, y, relZ, skyLight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,9 +634,14 @@ public class ChunkLoader
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logWarningOnce(String message) { logWarningOnce(message, null); }
|
private static void logParsingWarningOnce(String message) { logParsingWarningOnce(message, null); }
|
||||||
private static void logWarningOnce(String message, Exception e)
|
private static void logParsingWarningOnce(String message, Exception e)
|
||||||
{
|
{
|
||||||
|
if (message == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
{
|
{
|
||||||
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||||
@@ -576,6 +668,134 @@ public class ChunkLoader
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//====================//
|
||||||
|
// tag helper methods //
|
||||||
|
//====================//
|
||||||
|
|
||||||
|
// TODO move into separate file (this file is getting long)
|
||||||
|
// these tag helpers are to simplify tag accessing between MC versions
|
||||||
|
|
||||||
|
/** defaults to "false" if the tag isn't present */
|
||||||
|
private static boolean tagGetBoolean(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getBoolean(key);
|
||||||
|
#else
|
||||||
|
return tag.getBoolean(key).orElse(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static byte tagGetByte(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByte(key);
|
||||||
|
#else
|
||||||
|
return tag.getByte(key).orElse((byte)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static short tagGetShort(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getShort(index);
|
||||||
|
#else
|
||||||
|
return tag.getShort(index).orElse((short)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static int tagGetInt(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getInt(key).orElse(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static long tagGetLong(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getLong(key).orElse(0L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
private static String tagGetString(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getString(key);
|
||||||
|
#else
|
||||||
|
return tag.getString(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
private static byte[] tagGetByteArray(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByteArray(key);
|
||||||
|
#else
|
||||||
|
return tag.getByteArray(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static CompoundTag tagGetCompoundTag(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(key);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static CompoundTag tagGetCompoundTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(index);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(index).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* defaults to null if the tag isn't present
|
||||||
|
* @param elementType unused after MC 1.21.5
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private static ListTag tagGetListTag(CompoundTag tag, String key, int elementType)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(key, elementType);
|
||||||
|
#else
|
||||||
|
return tag.getList(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static ListTag tagGetListTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(index);
|
||||||
|
#else
|
||||||
|
return tag.getList(index).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// helper classes //
|
// helper classes //
|
||||||
|
|||||||
+8
@@ -229,8 +229,16 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
{
|
{
|
||||||
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
||||||
if (chunkAccess instanceof LevelChunk)
|
if (chunkAccess instanceof LevelChunk)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
|
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
|
||||||
|
#else
|
||||||
|
chunkAccess.setBlockState(blockPos, blockState, /*flags*/0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is for post ticking for water on gen and stuff like that. Not enabled
|
// This is for post ticking for water on gen and stuff like that. Not enabled
|
||||||
// for now.
|
// for now.
|
||||||
// if (blockState.hasPostProcess(this, blockPos))
|
// if (blockState.hasPostProcess(this, blockPos))
|
||||||
|
|||||||
+1
-1
Submodule coreSubProjects updated: e701c0e5ea...09174c2d2a
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "fabric-loom" version "1.8-SNAPSHOT"
|
id "fabric-loom" version "1.10-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
{
|
{
|
||||||
ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor());
|
ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor());
|
||||||
|
|
||||||
// If sodium is installed Indium is also necessary in order to use the Fabric rendering API
|
// If sodium is installed Indium is also necessary for versions 0.5 and less in order to use the Fabric rendering API
|
||||||
if (!modChecker.isModLoaded("indium"))
|
if (!modChecker.isModLoaded("indium") && SodiumAccessor.isSodiumV5OrLess)
|
||||||
{
|
{
|
||||||
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
||||||
LOGGER.fatal(indiumMissingMessage);
|
LOGGER.fatal(indiumMissingMessage);
|
||||||
|
|||||||
+21
-5
@@ -34,21 +34,34 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@Mixin(LightTexture.class)
|
@Mixin(LightTexture.class)
|
||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
private NativeImage lightPixels;
|
private NativeImage lightPixels;
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
private TextureTarget target;
|
private TextureTarget target;
|
||||||
|
#else
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private GpuTexture texture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
@@ -63,8 +76,11 @@ public class MixinLightTexture
|
|||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||||
|
#else
|
||||||
|
GlTexture glTexture = (GlTexture) this.texture;
|
||||||
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(glTexture.glId(), clientLevel);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
@@ -1,12 +1,15 @@
|
|||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#endif
|
||||||
import com.mojang.blaze3d.platform.TextureUtil;
|
import com.mojang.blaze3d.platform.TextureUtil;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets Minecraft's LOD Bias (looks similar to mipmaps)
|
* Sets Minecraft's LOD Bias (looks similar to mipmaps)
|
||||||
*
|
*
|
||||||
@@ -15,6 +18,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
@Mixin(TextureUtil.class)
|
@Mixin(TextureUtil.class)
|
||||||
public class MixinTextureUtil
|
public class MixinTextureUtil
|
||||||
{
|
{
|
||||||
|
// TODO fix for MC 1.21.5+
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
|
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
|
||||||
private static void setLodBias(int target, int pname, float param)
|
private static void setLodBias(int target, int pname, float param)
|
||||||
@@ -27,5 +33,6 @@ public class MixinTextureUtil
|
|||||||
GlStateManager._texParameter(target, pname, biasValue);
|
GlStateManager._texParameter(target, pname, biasValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -43,11 +43,22 @@ import net.minecraft.world.phys.AABB;
|
|||||||
|
|
||||||
public class SodiumAccessor implements ISodiumAccessor
|
public class SodiumAccessor implements ISodiumAccessor
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* True if sodium 0.5 or less is present. <br>
|
||||||
|
* This field is public because it's also used to check if we need Indium to be present. <br>
|
||||||
|
* We need Indium if Sodium 0.5 or less is present.
|
||||||
|
*/
|
||||||
|
public static final boolean isSodiumV5OrLess;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER >= MC_1_20_1
|
||||||
private static MethodHandle setFogOcclusionMethod;
|
private static MethodHandle setFogOcclusionMethod;
|
||||||
private static Object sodiumPerformanceOptions;
|
private static Object sodiumPerformanceOptions;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static {
|
||||||
|
isSodiumV5OrLess = !classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//======================//
|
//======================//
|
||||||
@@ -72,8 +83,7 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
{
|
{
|
||||||
if (sodiumPerformanceOptions == null)
|
if (sodiumPerformanceOptions == null)
|
||||||
{
|
{
|
||||||
boolean sodiumV6 = classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
if (isSodiumV5OrLess)
|
||||||
if (!sodiumV6)
|
|
||||||
{
|
{
|
||||||
// sodium 0.5
|
// sodium 0.5
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,16 @@ import com.seibel.distanthorizons.common.util.ProxyUtil;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
@@ -52,6 +55,7 @@ import net.minecraft.world.level.chunk.ChunkAccess;
|
|||||||
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
@@ -90,7 +94,13 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
public void registerEvents()
|
public void registerEvents()
|
||||||
{
|
{
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
ForgePluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived);
|
|
||||||
|
// handles singleplayer, LAN, and connecting to a server
|
||||||
|
ForgePluginPacketSender.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||||
|
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -78,10 +78,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public ForgeServerProxy(boolean isDedicated)
|
public ForgeServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; }
|
||||||
{
|
|
||||||
this.isDedicated = isDedicated;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -5,7 +5,7 @@ org.gradle.caching=true
|
|||||||
|
|
||||||
# Mod Info
|
# Mod Info
|
||||||
mod_name=DistantHorizons
|
mod_name=DistantHorizons
|
||||||
mod_version=2.3.0-b
|
mod_version=2.3.3-b-dev
|
||||||
api_version=4.0.0
|
api_version=4.0.0
|
||||||
maven_group=com.seibel.distanthorizons
|
maven_group=com.seibel.distanthorizons
|
||||||
mod_readable_name=Distant Horizons
|
mod_readable_name=Distant Horizons
|
||||||
@@ -23,9 +23,9 @@ manifold_version=2024.1.37
|
|||||||
nightconfig_version=3.6.6
|
nightconfig_version=3.6.6
|
||||||
lz4_version=1.8.0
|
lz4_version=1.8.0
|
||||||
xz_version=1.9
|
xz_version=1.9
|
||||||
|
# Before updating, read relocate_natives/README.md
|
||||||
sqlite_jdbc_version=3.47.2.0
|
sqlite_jdbc_version=3.47.2.0
|
||||||
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
||||||
# (at least until we can fix the gradle script so core and main can use/shade different fastutil versions)
|
|
||||||
fastutil_version=8.2.1
|
fastutil_version=8.2.1
|
||||||
#svgSalamander_version=1.1.3
|
#svgSalamander_version=1.1.3
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ versionStr=
|
|||||||
|
|
||||||
# This defines what MC version Intellij will use for the preprocessor
|
# This defines what MC version Intellij will use for the preprocessor
|
||||||
# and what version is used automatically by build and run commands
|
# and what version is used automatically by build and run commands
|
||||||
mcVer=1.21.4
|
mcVer=1.21.5
|
||||||
|
|
||||||
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
||||||
#minecraftMemoryJavaArg="-Xmx4G"
|
#minecraftMemoryJavaArg="-Xmx4G"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
|||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
@@ -51,6 +53,7 @@ import java.util.function.Consumer;
|
|||||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||||
#else
|
#else
|
||||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,11 +67,16 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
{
|
{
|
||||||
public NeoforgeMain(IEventBus eventBus)
|
public NeoforgeMain(IEventBus eventBus)
|
||||||
{
|
{
|
||||||
eventBus.addListener((FMLClientSetupEvent e) -> {
|
// handles singleplayer, LAN, and connecting to a server
|
||||||
|
eventBus.addListener((FMLClientSetupEvent e) ->
|
||||||
|
{
|
||||||
this.onInitializeClient();
|
this.onInitializeClient();
|
||||||
eventBus.addListener(this::registerNetworkingClient);
|
eventBus.addListener(this::registerNetworkingClientServer);
|
||||||
});
|
});
|
||||||
eventBus.addListener((FMLDedicatedServerSetupEvent e) -> {
|
|
||||||
|
// handles dedicated servers
|
||||||
|
eventBus.addListener((FMLDedicatedServerSetupEvent e) ->
|
||||||
|
{
|
||||||
this.onInitializeServer();
|
this.onInitializeServer();
|
||||||
eventBus.addListener(this::registerNetworkingServer);
|
eventBus.addListener(this::registerNetworkingServer);
|
||||||
});
|
});
|
||||||
@@ -79,13 +87,22 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
//============//
|
//============//
|
||||||
// networking //
|
// networking //
|
||||||
//============//
|
//============//
|
||||||
public void registerNetworkingClient(RegisterPayloadHandlersEvent event)
|
|
||||||
{ NeoforgePluginPacketSender.setPacketHandler(event, ClientApi.INSTANCE::pluginMessageReceived); }
|
public void registerNetworkingClientServer(RegisterPayloadHandlersEvent event)
|
||||||
|
{
|
||||||
|
NeoforgePluginPacketSender.setPacketHandler(event, (IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||||
|
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||||
|
});
|
||||||
|
}
|
||||||
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
|
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
|
||||||
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
|
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IEventProxy createServerProxy(boolean isDedicated) { return new NeoforgeServerProxy(isDedicated); }
|
protected IEventProxy createServerProxy(boolean isDedicated) { return new NeoforgeServerProxy(isDedicated); }
|
||||||
|
|
||||||
|
|||||||
+28
-22
@@ -19,17 +19,12 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -37,30 +32,33 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
@Mixin(LightTexture.class)
|
@Mixin(LightTexture.class)
|
||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private NativeImage lightPixels;
|
private NativeImage lightPixels;
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
|
@Shadow
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Final
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
private TextureTarget target;
|
||||||
{
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
|
||||||
if (mc == null || mc.getWrappedClientLevel() == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private GpuTexture texture;
|
||||||
|
#endif
|
||||||
|
|
||||||
@Shadow @Final private TextureTarget target;
|
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
@@ -70,9 +68,17 @@ public class MixinLightTexture
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||||
|
#else
|
||||||
|
GlTexture glTexture = (GlTexture) this.texture;
|
||||||
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(glTexture.glId(), clientLevel);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -1,6 +1,8 @@
|
|||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#endif
|
||||||
import com.mojang.blaze3d.platform.TextureUtil;
|
import com.mojang.blaze3d.platform.TextureUtil;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -15,6 +17,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
@Mixin(TextureUtil.class)
|
@Mixin(TextureUtil.class)
|
||||||
public class MixinTextureUtil
|
public class MixinTextureUtil
|
||||||
{
|
{
|
||||||
|
// TODO fix for MC 1.21.5+
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
|
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
|
||||||
private static void setLodBias(int target, int pname, float param)
|
private static void setLodBias(int target, int pname, float param)
|
||||||
@@ -27,5 +32,6 @@ public class MixinTextureUtil
|
|||||||
GlStateManager._texParameter(target, pname, biasValue);
|
GlStateManager._texParameter(target, pname, biasValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
This directory contains the native files of libraries that were modified for relocation. They will be copied from here during the normal build steps.
|
||||||
|
|
||||||
|
Before adding/updating a library, make sure you have Python 3.8+ installed and check the instructions below.
|
||||||
|
|
||||||
|
How to add a library's natives:
|
||||||
|
|
||||||
|
1. In `build.gradle`:
|
||||||
|
|
||||||
|
- Make sure the target package is the same length or shorter (untested) than the source package. Underscores in native methods will take 2 characters so account for that as well.
|
||||||
|
- Exclude the native files and add them as `relocateNative` (see example).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
relocate "org.sqlite", "dh_sqlite", {
|
||||||
|
exclude "org/sqlite/native/**"
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
// NativeTransformer configuration
|
||||||
|
rootDir = project.rootDir
|
||||||
|
|
||||||
|
// Replace native strings, e.g. used in calls back to Java
|
||||||
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
|
// Rename native methods used when calling from Java
|
||||||
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
How to update a library's natives:
|
||||||
|
|
||||||
|
1. Delete the library's folder in cache/.
|
||||||
|
2. It will repopulate during the next build.
|
||||||
|
|
||||||
|
Why does this step exist?
|
||||||
|
|
||||||
|
- Native files are not handled by the shadow plugin correctly.
|
||||||
|
- I preferred it as a more streamlined approach, although a bit hacky.
|
||||||
|
- Possible alternatives:
|
||||||
|
- Use edited libraries' source code: although more straightforward, it requires maintaining and updating the repositories for the libraries being added
|
||||||
|
- Interfacing with the necessary libraries directly: an absolute mess for technical reasons
|
||||||
|
|
||||||
|
What are libraries used?
|
||||||
|
|
||||||
|
- LIEF: for fixing binaries after replacing strings
|
||||||
|
- apple-codesign: for re-signing Mac binaries, since their signatures get invalidated after previous steps
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,56 @@
|
|||||||
|
# 1.21.4 version
|
||||||
|
java_version=21
|
||||||
|
minecraft_version=1.21.5
|
||||||
|
parchment_version=1.21:2024.07.28
|
||||||
|
compatible_minecraft_versions=["1.21.5"]
|
||||||
|
accessWidenerVersion=1_21_4
|
||||||
|
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.16.10
|
||||||
|
fabric_api_version=0.119.5+1.21.5
|
||||||
|
modmenu_version=14.0.0-rc.2
|
||||||
|
starlight_version_fabric=
|
||||||
|
phosphor_version_fabric=
|
||||||
|
lithium_version=
|
||||||
|
sodium_version=mc1.21.5-0.6.11-fabric
|
||||||
|
iris_version=1.8.10+1.21.5-fabric
|
||||||
|
bclib_version=
|
||||||
|
immersive_portals_version=
|
||||||
|
canvas_version=
|
||||||
|
|
||||||
|
# some versions of 1.8.11 nightly builds may not work, but the ones after 2025-03-30 should
|
||||||
|
fabric_incompatibility_list={ "iris": "<=1.8.10" }
|
||||||
|
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=
|
||||||
|
neoforge_version=21.5.0-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
|
||||||
Reference in New Issue
Block a user