Compare commits

...

29 Commits

Author SHA1 Message Date
Ran 8e7f82d3e0 Update Forgix 2025-05-08 12:44:29 +10:00
Ran 931aa2974e Better CI formatting 2025-05-06 14:00:27 +10:00
Ran 1f77a12fe3 attempt #3 on fixing the CI 2025-05-06 13:14:34 +10:00
Ran dcf546a163 attempt #2 on fixing the CI 2025-05-06 12:37:46 +10:00
Ran 81f050dc8b try to fix CI 2025-05-06 11:33:49 +10:00
Ran 9cd1ada37f multiversion test 2025-05-06 11:27:16 +10:00
s809 d29e9085a1 Fix getWorldFolderName crash 2025-05-03 13:44:54 +05:00
Ran d392de3c0d Update Forgix
fixes a critical bug
2025-05-03 17:40:58 +10:00
Ran 7209193f8f Fix gradle versioning 2025-05-03 11:21:17 +10:00
s809 ed4f644a3f Bump protocol version 2025-05-03 00:08:12 +05:00
Ran 34038684a7 Fix gradle versioning for core application 2025-05-02 12:45:18 +10:00
s809 6fe6694c82 Merge branch 'feature/adaptive-data-rate' 2025-04-27 21:57:47 +05:00
s809 8e52f1aca5 Merge branch 'refactor/remove-python-dependency' 2025-04-27 21:48:53 +05:00
s809 5ce3dda2d5 Clear up the comment a bit 2025-04-27 21:48:28 +05:00
s809 f4f81f4d7f Account for forge byte when encoding protocol version instead of shifting the entire packet on pre-1.20.6 2025-04-27 21:40:50 +05:00
s809 7c37a5c370 Run prepare only when needed 2025-04-27 00:40:12 +05:00
s809 b495ac4799 remove python dependency for building with correct sqlite natives 2025-04-27 00:13:24 +05:00
s809 2ddeaf50eb test builds 2025-04-21 00:00:01 +05:00
Ran 3721ebea6e Improve LodDataBuilder.java
- Use bitwise modulo
- Don't compute certain things 256 times when they can be computed once.
- Removed expressions that are always false
- Improved comments
2025-04-11 11:24:17 +10:00
Ran 98f8a87362 Improve LodDataBuilder.java
- Use bitwise modulo
- Don't compute certain things 256 times when they can be computed once.
- Removed expressions that are always false
- Improved comments
2025-04-11 11:20:05 +10:00
Ran 10a743ddef Don't check for Indium for Sodium version >= 0.6 2025-04-07 23:53:02 +10:00
James Seibel 95c896f964 maybe break n-sized rendering but fix LOD loading getting stuck 2025-04-07 06:56:58 -05:00
James Seibel 040bc16874 re-add comment to getWorldFolderName() 2025-04-07 06:55:45 -05:00
James Seibel 35d3fdb473 Revert "bandaid fix for Forge 1.20.1 UI crashing"
This reverts commit 2b519a826f.
2025-04-07 06:55:01 -05:00
Ran 549f7510f7 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintWithoutLevelOverrider.java
2025-04-07 13:52:25 +10:00
Ran fab64d8477 Fix white foliage issue 2025-04-07 13:52:02 +10:00
Ran 4a6a35f617 Fix white foliage issue 2025-04-07 13:47:42 +10:00
James Seibel 2b519a826f bandaid fix for Forge 1.20.1 UI crashing 2025-04-05 09:19:36 -05:00
James Seibel 445c01b5ae up version number 2.3.2 -> 2.3.3 2025-04-05 09:11:45 -05:00
44 changed files with 231 additions and 152 deletions
-1
View File
@@ -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
+29 -8
View File
@@ -6,6 +6,7 @@ image: eclipse-temurin:21
# TODO: Make stages depend on what is in versionProperties # TODO: Make stages depend on what is in versionProperties
stages: stages:
- build - build
- multiversion
- api - api
- pages - pages
@@ -17,9 +18,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
@@ -41,23 +39,46 @@ build:
- 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"] - 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 build -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/; - ./gradlew build -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
- ./gradlew mergeJars -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/; - ./gradlew mergeJars -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./Merged/* . || true - cp ./build/forgix/* . || true
- mkdir -p ./builds
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./builds || true
# When the archive is created, the merged jar will be the main jar and a subfolder named "builds" will contain the other jars
artifacts: artifacts:
name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}" name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths: paths:
- ./*.jar - ./*.jar
- ./builds/*.jar
exclude: exclude:
- ./*-all.jar - ./builds/*-all.jar
- ./*-dev.jar - ./builds/*-dev.jar
- ./*-sources.jar - ./builds/*-sources.jar
expire_in: 14 days expire_in: 14 days
when: always when: always
extends: .build_java extends: .build_java
multiversion:
stage: multiversion
needs: [build]
script:
# Create a semicolon-separated list of jar paths
- MC_VER_PATHS=$(find . -maxdepth 1 -name "*.jar" -type f | tr '\n' ';')
# Run the mergeVersions task
- ./gradlew mergeVersions -PmergeVersions="${MC_VER_PATHS}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
# Clean up existing jars and make sure only the multiversion jar remains which will be uploaded
- rm -f ./*.jar
- cp ./build/forgix/multiversion/* .
artifacts:
name: "NightlyBuild_Multiversion-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
- ./*.jar
expire_in: 30 days
when: always
extends: .build_java
api: api:
stage: api stage: api
needs: [] needs: []
+14 -73
View File
@@ -13,7 +13,7 @@ plugins {
id "com.github.johnrengelman.shadow" version '8.1.1' apply false id "com.github.johnrengelman.shadow" version '8.1.1' apply false
// Plugin to create merged jars // Plugin to create merged jars
id "io.github.pacifistmc.forgix" version "1.2.9" id "io.github.pacifistmc.forgix" version "2.0.0-SNAPSHOT.2"
// Manifold preprocessor // Manifold preprocessor
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha" id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
@@ -22,6 +22,14 @@ plugins {
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
} }
// Sets up Forgix for multiversion merging
forgix {
if (project.hasProperty('mergeVersions')) { // This is set using -PmergeVersions by the GitLab CI
multiversion {
inputJars = project.files(project.property('mergeVersions').toString().split(';'))
}
}
}
/** /**
* Creates the list of preprocessors to use. * Creates the list of preprocessors to use.
@@ -67,63 +75,16 @@ project.gradle.ext.getProperties().each { prop ->
// Sets up manifold stuff // Sets up manifold stuff
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex) writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
// Sets up the version string (the name we use for our jar) // Sets up the version string (the name we use for our jar)
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm") rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
// Forgix settings (used for merging jars)
forgix {
String loaderHyphenSeparatedList = ((String)gradle.builds_for).replaceAll(",", "-");
group = "com.seibel.distanthorizons"
mergedJarName = "DistantHorizons-${loaderHyphenSeparatedList}-${rootProject.versionStr}.jar"
if (findProject(":forge"))
forge {
jarLocation = "build/libs/DistantHorizons-forge-${rootProject.versionStr}.jar"
}
if (findProject(":neoforge"))
custom {
projectName = "neoforge"
jarLocation = "build/libs/DistantHorizons-neoforge-${rootProject.versionStr}.jar"
}
if (findProject(":fabric"))
fabric {
jarLocation = "build/libs/DistantHorizons-fabric-${rootProject.versionStr}.jar"
}
if (findProject(":quilt"))
quilt {
jarLocation = "build/libs/DistantHorizons-quilt-${rootProject.versionStr}.jar"
}
removeDuplicate "com.seibel.distanthorizons"
}
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 +93,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 +349,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
transform(NativeTransformer) {
rootDir = project.rootDir
before {
relocate "org.sqlite", "dh_sqlite", { relocate "org.sqlite", "dh_sqlite", {
exclude "org/sqlite/native/**" exclude "org/sqlite/native/**"
} }
relocate "jdbc:sqlite", "jdbc:dh_sqlite" relocate "jdbc:sqlite", "jdbc:dh_sqlite"
}
transform(NativeTransformer) {
rootDir = project.rootDir
relocateNative "org/sqlite", "dh_sqlite" relocateNative "org/sqlite", "dh_sqlite"
relocateNative "org_sqlite", "dh_1sqlite" relocateNative "org_sqlite", "dh_1sqlite"
} }
@@ -582,8 +533,9 @@ allprojects { p ->
apply plugin: "java" apply plugin: "java"
apply plugin: "maven-publish" apply plugin: "maven-publish"
// Sets the name of the jar, the version will contain the name of the project if it isn't the root project
archivesBaseName = rootProject.mod_name archivesBaseName = rootProject.mod_name
version = project.name + "-" + rootProject.versionStr version = (project == rootProject ? "" : project.name + "-") + rootProject.versionStr
group = rootProject.maven_group group = rootProject.maven_group
// this is the text that appears at the top of the overview (home) page // this is the text that appears at the top of the overview (home) page
@@ -748,14 +700,3 @@ allprojects { p ->
withSourcesJar() withSourcesJar()
} }
} }
// Delete the merged folder when running clean
task cleanMergedJars() {
def mergedFolder = file("Merged")
if (mergedFolder.exists()) {
delete(mergedFolder)
}
}
// add cleanMergedJars to the end of the "clean" task
tasks["clean"].finalizedBy(cleanMergedJars)
+7 -3
View File
@@ -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;
@@ -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());
@@ -1,6 +1,7 @@
package com.seibel.distanthorizons.common; package com.seibel.distanthorizons.common;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent; import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent; import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
@@ -30,6 +31,16 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
#endif #endif
// "Forge byte" is an unused packet ID. We have our own system which works with all mod loaders,
// so we're just accounting for it by reading the protocol version as a byte instead of a short in Forge, to keep cross-loader compatibility
private final boolean forgeByteInProtocolVersion;
public AbstractPluginPacketSender() { this(false); }
public AbstractPluginPacketSender(boolean forgeByteInProtocolVersion)
{
this.forgeByteInProtocolVersion = forgeByteInProtocolVersion;
}
@Override @Override
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message) public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
@@ -41,7 +52,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
@Override @Override
public abstract void sendToServer(AbstractNetworkMessage message); public abstract void sendToServer(AbstractNetworkMessage message);
public static AbstractNetworkMessage decodeMessage(FriendlyByteBuf in) public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
{ {
AbstractNetworkMessage message = null; AbstractNetworkMessage message = null;
@@ -49,7 +60,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
{ {
in.markReaderIndex(); in.markReaderIndex();
int protocolVersion = in.readShort(); int protocolVersion = this.forgeByteInProtocolVersion ? in.readByte() : in.readShort();
if (protocolVersion != ModInfo.PROTOCOL_VERSION) if (protocolVersion != ModInfo.PROTOCOL_VERSION)
{ {
return new IncompatibleMessageInternalEvent(protocolVersion); return new IncompatibleMessageInternalEvent(protocolVersion);
@@ -82,11 +93,19 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
} }
} }
public static void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message) public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
{ {
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild // This is intentionally unhandled, because errors related to this are unlikely to appear in wild
Objects.requireNonNull(message); Objects.requireNonNull(message);
if (this.forgeByteInProtocolVersion)
{
out.writeByte(ModInfo.PROTOCOL_VERSION);
}
else
{
out.writeShort(ModInfo.PROTOCOL_VERSION); out.writeShort(ModInfo.PROTOCOL_VERSION);
}
try try
{ {
@@ -2,7 +2,9 @@ package com.seibel.distanthorizons.common;
#if MC_VER >= MC_1_20_6 #if MC_VER >= MC_1_20_6
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage; import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
@@ -12,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) implements CustomPacketPayload public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) implements CustomPacketPayload
{ {
public static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE); public static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE);
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
@NotNull @NotNull
@Override @Override
@@ -23,11 +26,11 @@ public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) impl
@NotNull @NotNull
@Override @Override
public CommonPacketPayload decode(@NotNull FriendlyByteBuf in) public CommonPacketPayload decode(@NotNull FriendlyByteBuf in)
{ return new CommonPacketPayload(AbstractPluginPacketSender.decodeMessage(in)); } { return new CommonPacketPayload(PACKET_SENDER.decodeMessage(in)); }
@Override @Override
public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload) public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload)
{ AbstractPluginPacketSender.encodeMessage(out, payload.message()); } { PACKET_SENDER.encodeMessage(out, payload.message()); }
} }
@@ -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,30 +43,61 @@ 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;
} }
@@ -77,15 +105,12 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
@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)
@@ -42,6 +42,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
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;
@@ -115,10 +116,12 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override @Override
public String getWorldFolderName() public String getWorldFolderName()
{ {
#if MC_VER >= MC_1_17_1 // Need specifically overworld since it's the only dimension that is stored in a server root folder
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
#else // <= 1.16.5 #if MC_VER >= MC_1_21_3
return this.level.getServer().getWorldScreenshotFile().getParentFile().getName(); return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString();
#else // <= 1.21.3
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName();
#endif #endif
} }
@@ -33,6 +33,7 @@ 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.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
@@ -82,6 +83,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
{ {
private final ClientApi clientApi = ClientApi.INSTANCE; private final ClientApi clientApi = ClientApi.INSTANCE;
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi // TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi
@@ -316,9 +318,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
#else #else
ClientPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (client, handler, buffer, packetSender) -> ClientPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (client, handler, buffer, packetSender) ->
{ {
// Forge packet ID AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null) if (message != null)
{ {
ClientApi.INSTANCE.pluginMessageReceived(message); ClientApi.INSTANCE.pluginMessageReceived(message);
@@ -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);
@@ -22,9 +22,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
ClientPlayNetworking.send(new CommonPacketPayload(message)); ClientPlayNetworking.send(new CommonPacketPayload(message));
#else // < 1.20.6 #else // < 1.20.6
FriendlyByteBuf buffer = PacketByteBufs.create(); FriendlyByteBuf buffer = PacketByteBufs.create();
// Forge packet ID this.encodeMessage(buffer, message);
buffer.writeByte(0);
AbstractPluginPacketSender.encodeMessage(buffer, message);
ClientPlayNetworking.send(WRAPPER_PACKET_RESOURCE, buffer); ClientPlayNetworking.send(WRAPPER_PACKET_RESOURCE, buffer);
#endif #endif
} }
@@ -36,9 +34,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
ServerPlayNetworking.send(serverPlayer, new CommonPacketPayload(message)); ServerPlayNetworking.send(serverPlayer, new CommonPacketPayload(message));
#else // < 1.20.6 #else // < 1.20.6
FriendlyByteBuf buffer = PacketByteBufs.create(); FriendlyByteBuf buffer = PacketByteBufs.create();
// Forge packet ID this.encodeMessage(buffer, message);
buffer.writeByte(0);
AbstractPluginPacketSender.encodeMessage(buffer, message);
ServerPlayNetworking.send(serverPlayer, WRAPPER_PACKET_RESOURCE, buffer); ServerPlayNetworking.send(serverPlayer, WRAPPER_PACKET_RESOURCE, buffer);
#endif #endif
} }
@@ -9,7 +9,10 @@ import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
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.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
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 com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent; import com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent;
@@ -32,7 +35,6 @@ import com.seibel.distanthorizons.common.CommonPacketPayload;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
#else #else
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage; import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
#endif #endif
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -48,6 +50,8 @@ import java.util.function.Supplier;
public class FabricServerProxy implements AbstractModInitializer.IEventProxy public class FabricServerProxy implements AbstractModInitializer.IEventProxy
{ {
private static final ServerApi SERVER_API = ServerApi.INSTANCE; private static final ServerApi SERVER_API = ServerApi.INSTANCE;
@SuppressWarnings("unused")
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicatedServer; private final boolean isDedicatedServer;
@@ -192,9 +196,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
#else #else
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) -> ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
{ {
// Forge packet ID AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null) if (message != null)
{ {
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message); ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
@@ -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
@@ -33,6 +33,7 @@ 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.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; 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;
@@ -79,6 +80,7 @@ import java.util.concurrent.ThreadPoolExecutor;
public class ForgeClientProxy implements AbstractModInitializer.IEventProxy public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
{ {
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -96,7 +98,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
// handles singleplayer, LAN, and connecting to a server // handles singleplayer, LAN, and connecting to a server
ForgePluginPacketSender.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) -> PACKET_SENDER.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
{ {
ClientApi.INSTANCE.pluginMessageReceived(message); ClientApi.INSTANCE.pluginMessageReceived(message);
ServerApi.INSTANCE.pluginMessageReceived(player, message); ServerApi.INSTANCE.pluginMessageReceived(player, message);
@@ -45,16 +45,18 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
); );
#endif #endif
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer) public ForgePluginPacketSender() { super(true); }
public void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
{ {
setPacketHandler((player, message) -> consumer.accept(message)); this.setPacketHandler((player, message) -> consumer.accept(message));
} }
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer) public void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
{ {
#if MC_VER >= MC_1_20_2 #if MC_VER >= MC_1_20_2
PLUGIN_CHANNEL.messageBuilder(MessageWrapper.class, 0) PLUGIN_CHANNEL.messageBuilder(MessageWrapper.class, 0)
.encoder((wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message)) .encoder((wrapper, out) -> this.encodeMessage(out, wrapper.message))
.decoder(in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in))) .decoder(in -> new MessageWrapper(this.decodeMessage(in)))
.consumerNetworkThread((wrapper, context) -> .consumerNetworkThread((wrapper, context) ->
{ {
if (wrapper.message != null) if (wrapper.message != null)
@@ -73,8 +75,8 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
.add(); .add();
#else // < 1.20.2 #else // < 1.20.2
PLUGIN_CHANNEL.registerMessage(0, MessageWrapper.class, PLUGIN_CHANNEL.registerMessage(0, MessageWrapper.class,
(wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message), (wrapper, out) -> this.encodeMessage(out, wrapper.message),
in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)), in -> new MessageWrapper(this.decodeMessage(in)),
(wrapper, context) -> (wrapper, context) ->
{ {
if (wrapper.message != null) if (wrapper.message != null)
@@ -7,7 +7,9 @@ import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
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.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -51,6 +53,8 @@ import java.util.function.Supplier;
public class ForgeServerProxy implements AbstractModInitializer.IEventProxy public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
{ {
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); } private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); }
#else #else
@@ -68,7 +72,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
if (this.isDedicated) if (this.isDedicated)
{ {
ForgePluginPacketSender.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived); PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
} }
} }
+3 -1
View File
@@ -5,7 +5,7 @@ org.gradle.caching=true
# Mod Info # Mod Info
mod_name=DistantHorizons mod_name=DistantHorizons
mod_version=2.3.2-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,6 +23,7 @@ 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
fastutil_version=8.2.1 fastutil_version=8.2.1
@@ -47,6 +48,7 @@ infoBuildSource=User
# Internal Properties (These are set at runtime for Forgix to merge jar's) # Internal Properties (These are set at runtime for Forgix to merge jar's)
versionStr= versionStr=
mergeVersions=
# 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
+46
View File
@@ -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 be mapped to `_1` 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
+1 -1
View File
@@ -58,7 +58,7 @@ If you still need help with compiling, please read the Readme.md
/** Loads the VersionProperties fiel for the currently selected Minecraft version. */ /** Loads the VersionProperties field for the currently selected Minecraft version. */
def loadProperties() { def loadProperties() {
def defaultMcVersion = "1.20.1" // 1.20.1 is our current most stable version so we use that if no version was defined def defaultMcVersion = "1.20.1" // 1.20.1 is our current most stable version so we use that if no version was defined