Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f69800dfe3 | |||
| cc251e46b0 | |||
| 7aa0bfefec | |||
| 9bdad5e4f1 | |||
| baebb7323d | |||
| 8a3175f345 | |||
| dc58efb301 | |||
| c9ac4b2ada | |||
| 6e1ec476ed | |||
| d1aa5a524b | |||
| 5c661a3a76 | |||
| d29e9085a1 | |||
| d392de3c0d | |||
| 7209193f8f | |||
| ed4f644a3f | |||
| 34038684a7 | |||
| 6fe6694c82 | |||
| 8e52f1aca5 | |||
| 5ce3dda2d5 | |||
| f4f81f4d7f | |||
| 7c37a5c370 | |||
| b495ac4799 | |||
| 2ddeaf50eb | |||
| 3721ebea6e | |||
| 98f8a87362 | |||
| 10a743ddef | |||
| 95c896f964 | |||
| 040bc16874 | |||
| 35d3fdb473 | |||
| 549f7510f7 | |||
| fab64d8477 | |||
| 4a6a35f617 | |||
| 2b519a826f | |||
| 445c01b5ae |
+1
-2
@@ -5,7 +5,6 @@ root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
@@ -688,7 +687,7 @@ ij_markdown_wrap_text_inside_blockquotes = true
|
||||
ij_toml_keep_indents_on_empty_lines = false
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
ij_yaml_align_values_properties = do_not_align
|
||||
ij_yaml_autoinsert_sequence_marker = true
|
||||
ij_yaml_block_mapping_on_new_line = false
|
||||
|
||||
@@ -29,7 +29,6 @@ buildAllJars/
|
||||
relocate_natives/.venv/
|
||||
relocate_natives/__pycache__/
|
||||
relocate_natives/apple-codesign/
|
||||
relocate_natives/cache/
|
||||
|
||||
# file from notepad++
|
||||
*.bak
|
||||
|
||||
+1
-4
@@ -17,9 +17,6 @@ variables:
|
||||
# These can be extended so code is a bit less duplicated
|
||||
.build_java:
|
||||
#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:
|
||||
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
||||
policy: pull-push
|
||||
@@ -44,7 +41,7 @@ build:
|
||||
- ./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 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 ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./build/merged/* . || true
|
||||
artifacts:
|
||||
name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||
paths:
|
||||
|
||||
+9
-76
@@ -13,7 +13,7 @@ plugins {
|
||||
id "com.github.johnrengelman.shadow" version '8.1.1' apply false
|
||||
|
||||
// Plugin to create merged jars
|
||||
id "io.github.pacifistmc.forgix" version "1.2.9"
|
||||
id "io.github.pacifistmc.forgix" version "1.3.4"
|
||||
|
||||
// Manifold preprocessor
|
||||
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
||||
@@ -67,63 +67,16 @@ project.gradle.ext.getProperties().each { prop ->
|
||||
// Sets up manifold stuff
|
||||
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
|
||||
|
||||
|
||||
|
||||
|
||||
// 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")
|
||||
// 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 {
|
||||
private boolean enabled = false
|
||||
private final HashMap<String, String> replacements = new HashMap()
|
||||
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||
private var nativeRelocator
|
||||
|
||||
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) {
|
||||
if (replacement.length() > target.length()) {
|
||||
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||
@@ -132,22 +85,15 @@ class NativeTransformer implements Transformer {
|
||||
replacements.put(target, replacement)
|
||||
}
|
||||
|
||||
void before(Closure closure) {
|
||||
if (enabled)
|
||||
closure.run()
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||
return enabled && replacements.keySet().stream().anyMatch {
|
||||
return replacements.keySet().stream().anyMatch {
|
||||
element.name.startsWith(it as String)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(@Nonnull TransformerContext context) {
|
||||
println("Transforming $context.path...")
|
||||
byte[] content = context.is.readAllBytes()
|
||||
|
||||
if (nativeRelocator == null) {
|
||||
@@ -395,16 +341,13 @@ subprojects { p ->
|
||||
// Sqlite Database
|
||||
// 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
|
||||
relocate "org.sqlite", "dh_sqlite", {
|
||||
exclude "org/sqlite/native/**"
|
||||
}
|
||||
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||
|
||||
transform(NativeTransformer) {
|
||||
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_1sqlite"
|
||||
}
|
||||
@@ -582,8 +525,9 @@ allprojects { p ->
|
||||
apply plugin: "java"
|
||||
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
|
||||
version = project.name + "-" + rootProject.versionStr
|
||||
version = (project == rootProject ? "" : project.name + "-") + rootProject.versionStr
|
||||
group = rootProject.maven_group
|
||||
|
||||
// this is the text that appears at the top of the overview (home) page
|
||||
@@ -748,14 +692,3 @@ allprojects { p ->
|
||||
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)
|
||||
|
||||
@@ -12,14 +12,15 @@ class NativeRelocator
|
||||
/**
|
||||
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||
* 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.cacheRoot = this.rootDirectory.resolve("cache");
|
||||
|
||||
}
|
||||
|
||||
private void prepare() throws Exception
|
||||
{
|
||||
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
||||
{
|
||||
return;
|
||||
@@ -196,6 +197,9 @@ class NativeRelocator
|
||||
return Files.readAllBytes(outputFilePath);
|
||||
}
|
||||
|
||||
System.out.println("Relocating to " + outputPath + "...");
|
||||
this.prepare();
|
||||
|
||||
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||
{
|
||||
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
||||
|
||||
+23
-4
@@ -1,6 +1,7 @@
|
||||
package com.seibel.distanthorizons.common;
|
||||
|
||||
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.network.event.internal.IncompatibleMessageInternalEvent;
|
||||
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);
|
||||
#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
|
||||
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
|
||||
@@ -41,7 +52,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
@Override
|
||||
public abstract void sendToServer(AbstractNetworkMessage message);
|
||||
|
||||
public static AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||
public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||
{
|
||||
AbstractNetworkMessage message = null;
|
||||
|
||||
@@ -49,7 +60,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
{
|
||||
in.markReaderIndex();
|
||||
|
||||
int protocolVersion = in.readShort();
|
||||
int protocolVersion = this.forgeByteInProtocolVersion ? in.readByte() : in.readShort();
|
||||
if (protocolVersion != ModInfo.PROTOCOL_VERSION)
|
||||
{
|
||||
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
|
||||
Objects.requireNonNull(message);
|
||||
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
||||
|
||||
if (this.forgeByteInProtocolVersion)
|
||||
{
|
||||
out.writeByte(ModInfo.PROTOCOL_VERSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.seibel.distanthorizons.common;
|
||||
|
||||
#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.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
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 static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE);
|
||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -23,11 +26,11 @@ public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) impl
|
||||
@NotNull
|
||||
@Override
|
||||
public CommonPacketPayload decode(@NotNull FriendlyByteBuf in)
|
||||
{ return new CommonPacketPayload(AbstractPluginPacketSender.decodeMessage(in)); }
|
||||
{ return new CommonPacketPayload(PACKET_SENDER.decodeMessage(in)); }
|
||||
|
||||
@Override
|
||||
public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload)
|
||||
{ AbstractPluginPacketSender.encodeMessage(out, payload.message()); }
|
||||
{ PACKET_SENDER.encodeMessage(out, payload.message()); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
+82
-59
@@ -47,6 +47,7 @@ import net.minecraft.core.registries.Registries;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
#endif
|
||||
@@ -130,14 +131,6 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
//LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
|
||||
}
|
||||
|
||||
/** should only be used to create {@link BiomeWrapper#EMPTY_WRAPPER} */
|
||||
private BiomeWrapper()
|
||||
{
|
||||
this.biome = null;
|
||||
this.serialString = EMPTY_BIOME_STRING;
|
||||
this.hashCode = Objects.hash(this.serialString);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
@@ -286,64 +279,16 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
BiomeWrapper foundWrapper = EMPTY_WRAPPER;
|
||||
try
|
||||
{
|
||||
// parse the resource location
|
||||
int separatorIndex = resourceLocationString.indexOf(":");
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
try
|
||||
{
|
||||
#if MC_VER < MC_1_21_1
|
||||
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#else
|
||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "].");
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
Level level = (Level) levelWrapper.getWrappedMcObject();
|
||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||
|
||||
boolean success;
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#elif MC_VER < MC_1_21_3
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#else
|
||||
Holder<Biome> biome;
|
||||
Optional<Holder.Reference<Biome>> optionalBiomeHolder = registryAccess.lookupOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
if (optionalBiomeHolder.isPresent())
|
||||
{
|
||||
Biome unwrappedBiome = optionalBiomeHolder.get().value();
|
||||
success = (unwrappedBiome != null);
|
||||
biome = new Holder.Direct<>(unwrappedBiome);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
biome = null;
|
||||
}
|
||||
#endif
|
||||
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess);
|
||||
|
||||
|
||||
|
||||
if (!success)
|
||||
if (!deserializeResult.success)
|
||||
{
|
||||
if (!brokenResourceLocationStrings.contains(resourceLocationString))
|
||||
{
|
||||
@@ -354,7 +299,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
}
|
||||
|
||||
|
||||
foundWrapper = (BiomeWrapper) getBiomeWrapper(biome, levelWrapper);
|
||||
foundWrapper = (BiomeWrapper) getBiomeWrapper(deserializeResult.biome, levelWrapper);
|
||||
return foundWrapper;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -368,4 +313,82 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException
|
||||
{
|
||||
// parse the resource location
|
||||
int separatorIndex = resourceLocationString.indexOf(":");
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
try
|
||||
{
|
||||
#if MC_VER < MC_1_21_1
|
||||
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#else
|
||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "].");
|
||||
}
|
||||
|
||||
|
||||
boolean success;
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#elif MC_VER < MC_1_21_3
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#else
|
||||
Holder<Biome> biome;
|
||||
Optional<Holder.Reference<Biome>> optionalBiomeHolder = registryAccess.lookupOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
if (optionalBiomeHolder.isPresent())
|
||||
{
|
||||
Biome unwrappedBiome = optionalBiomeHolder.get().value();
|
||||
success = (unwrappedBiome != null);
|
||||
biome = new Holder.Direct<>(unwrappedBiome);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
biome = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new BiomeDeserializeResult(success, biome);
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
public static class BiomeDeserializeResult
|
||||
{
|
||||
public final boolean success;
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
public final Biome biome;
|
||||
#else
|
||||
public final Holder<Biome> biome;
|
||||
#endif
|
||||
|
||||
public BiomeDeserializeResult(boolean success, #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome)
|
||||
{
|
||||
this.success = success;
|
||||
this.biome = biome;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -91,7 +91,7 @@ public class ClientBlockStateColorCache
|
||||
private static final RandomSource RANDOM = RandomSource.create();
|
||||
#endif
|
||||
|
||||
private final IClientLevelWrapper levelWrapper;
|
||||
private final IClientLevelWrapper clientLevelWrapper;
|
||||
private final BlockState blockState;
|
||||
private final LevelReader level;
|
||||
|
||||
@@ -174,7 +174,7 @@ public class ClientBlockStateColorCache
|
||||
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper samplingLevel)
|
||||
{
|
||||
this.blockState = blockState;
|
||||
this.levelWrapper = samplingLevel;
|
||||
this.clientLevelWrapper = samplingLevel;
|
||||
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
||||
this.resolveColors();
|
||||
}
|
||||
@@ -471,7 +471,7 @@ public class ClientBlockStateColorCache
|
||||
try
|
||||
{
|
||||
tintColor = Minecraft.getInstance().getBlockColors()
|
||||
.getColor(this.blockState, new TintWithoutLevelOverrider(biome, this.levelWrapper), McObjectConverter.Convert(pos), this.tintIndex);
|
||||
.getColor(this.blockState, new TintWithoutLevelOverrider(biome, this.clientLevelWrapper), McObjectConverter.Convert(pos), this.tintIndex);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
|
||||
+120
-39
@@ -20,13 +20,13 @@
|
||||
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.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.*;
|
||||
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.state.BlockState;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
@@ -39,55 +39,54 @@ import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
||||
{
|
||||
/**
|
||||
* This will only ever be null if there was an issue with {@link IClientLevelWrapper#getPlainsBiomeWrapper()}
|
||||
* but {@link Nullable} is there just in case.
|
||||
*/
|
||||
@Nullable
|
||||
private final Biome biome;
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
public static final ConcurrentMap<String, Biome> BIOME_BY_RESOURCE_STRING = new ConcurrentHashMap<>();
|
||||
#else
|
||||
public static final ConcurrentMap<String, Holder<Biome>> BIOME_BY_RESOURCE_STRING = new ConcurrentHashMap<>();
|
||||
#endif
|
||||
|
||||
|
||||
@NotNull
|
||||
private final BiomeWrapper biomeWrapper;
|
||||
|
||||
|
||||
|
||||
public TintWithoutLevelOverrider(BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||
{
|
||||
// try to get the wrapped biome
|
||||
Biome unwrappedBiome = null;
|
||||
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());
|
||||
if (plainsBiomeWrapper != null)
|
||||
{
|
||||
unwrappedBiome = unwrap(plainsBiomeWrapper.biome);
|
||||
}
|
||||
}
|
||||
|
||||
this.biome = unwrappedBiome;
|
||||
}
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public TintWithoutLevelOverrider(@NotNull BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||
{ this.biomeWrapper = biomeWrapper; }
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||
{
|
||||
if (this.biome != null)
|
||||
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||
{
|
||||
String biomeString = this.biomeWrapper.getSerialString();
|
||||
if (biomeString == null
|
||||
|| biomeString.isEmpty()
|
||||
|| biomeString.equals(BiomeWrapper.EMPTY_BIOME_STRING))
|
||||
{
|
||||
return colorResolver.getColor(this.biome, blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// hopefully unneeded debug color
|
||||
return ColorUtil.CYAN;
|
||||
// default to "plains" for empty/invalid biomes
|
||||
biomeString = "minecraft:plains";
|
||||
}
|
||||
|
||||
|
||||
return colorResolver.getColor(unwrap(getClientBiome(biomeString)), blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
|
||||
private static Biome unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
@@ -97,6 +96,88 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* <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>
|
||||
*/
|
||||
private static #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif getClientBiome(String biomeResourceString)
|
||||
{
|
||||
// cache the client biomes so we don't have to re-parse the resource location every time
|
||||
return BIOME_BY_RESOURCE_STRING.compute(biomeResourceString,
|
||||
(resourceString, existingBiome) ->
|
||||
{
|
||||
if (existingBiome != null)
|
||||
{
|
||||
return existingBiome;
|
||||
}
|
||||
|
||||
ClientLevel clientLevel = Minecraft.getInstance().level;
|
||||
if (clientLevel == null)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
throw new IllegalStateException("Attempted to get client biome when no client level was loaded.");
|
||||
}
|
||||
|
||||
BiomeWrapper.BiomeDeserializeResult result;
|
||||
try
|
||||
{
|
||||
result = BiomeWrapper.deserializeBiome(resourceString, clientLevel.registryAccess());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warn("Unable to deserialize client biome ["+resourceString+"], using fallback...");
|
||||
|
||||
try
|
||||
{
|
||||
result = BiomeWrapper.deserializeBiome("minecraft:plains", clientLevel.registryAccess());
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// should never happen, if it does this log will explode, but just in case
|
||||
LOGGER.error("Unable to deserialize fallback client biome [minecraft:plains], returning NULL.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.success)
|
||||
{
|
||||
existingBiome = result.biome;
|
||||
}
|
||||
|
||||
return existingBiome;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
|
||||
+7
-4
@@ -42,6 +42,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
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.ChunkSource;
|
||||
|
||||
@@ -115,10 +116,12 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
@Override
|
||||
public String getWorldFolderName()
|
||||
{
|
||||
#if MC_VER >= MC_1_17_1
|
||||
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
|
||||
#else // <= 1.16.5
|
||||
return this.level.getServer().getWorldScreenshotFile().getParentFile().getName();
|
||||
// Need specifically overworld since it's the only dimension that is stored in a server root folder
|
||||
|
||||
#if MC_VER >= MC_1_21_3
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+122
-97
@@ -179,20 +179,24 @@ public class ChunkLoader
|
||||
|
||||
//================== Read params for making the LevelChunk ==================
|
||||
|
||||
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
|
||||
UpgradeData upgradeData = UpgradeData.EMPTY;
|
||||
// commented out 2025-06-04 as a test to see if the upgrade data
|
||||
// is actually necessary for DH or if it can be ignored
|
||||
// (if it can't be ignored we'll need to handle null responses from tagGetCompoundTag())
|
||||
//
|
||||
//#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");
|
||||
@@ -242,7 +246,7 @@ public class ChunkLoader
|
||||
// Set some states after object creation
|
||||
chunk.setLightCorrect(isLightOn);
|
||||
readHeightmaps(chunk, chunkData);
|
||||
readPostPocessings(chunk, chunkData);
|
||||
//readPostPocessings(chunk, chunkData);
|
||||
return chunk;
|
||||
}
|
||||
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
||||
@@ -285,48 +289,54 @@ public class ChunkLoader
|
||||
for (int j = 0; j < tagSections.size(); ++j)
|
||||
{
|
||||
CompoundTag tagSection = tagGetCompoundTag(tagSections, j);
|
||||
int sectionYPos = tagGetByte(tagSection, "Y");
|
||||
if (tagSection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final int sectionYPos = tagGetByte(tagSection, "Y");
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||
{
|
||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
||||
tagSection.getLongArray("BlockStates"));
|
||||
levelChunkSection.recalcBlockCounts();
|
||||
if (!levelChunkSection.isEmpty())
|
||||
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
||||
= levelChunkSection;
|
||||
}
|
||||
#else
|
||||
#if MC_VER < MC_1_18_2
|
||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||
{
|
||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
||||
tagSection.getLongArray("BlockStates"));
|
||||
levelChunkSection.recalcBlockCounts();
|
||||
if (!levelChunkSection.isEmpty())
|
||||
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
||||
= levelChunkSection;
|
||||
}
|
||||
#else
|
||||
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||
if (sectionId >= 0 && sectionId < chunkSections.length)
|
||||
{
|
||||
PalettedContainer<BlockState> blockStateContainer;
|
||||
#if MC_VER < MC_1_18_2
|
||||
PalettedContainer<Biome> biomeContainer;
|
||||
#else
|
||||
#if MC_VER < MC_1_18_2
|
||||
PalettedContainer<Biome> biomeContainer;
|
||||
#else
|
||||
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 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
|
||||
#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
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -334,31 +344,31 @@ public class ChunkLoader
|
||||
}
|
||||
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#else
|
||||
#if MC_VER < MC_1_18_2
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#else
|
||||
|
||||
|
||||
boolean containsBiomes;
|
||||
#if MC_VER < MC_1_21_5
|
||||
containsBiomes = tagSection.contains("biomes", 10);
|
||||
#else
|
||||
containsBiomes = tagSection.contains("biomes");
|
||||
#endif
|
||||
#if MC_VER < MC_1_21_5
|
||||
containsBiomes = tagSection.contains("biomes", 10);
|
||||
#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
|
||||
#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))
|
||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -371,15 +381,15 @@ public class ChunkLoader
|
||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||
#else
|
||||
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -391,10 +401,14 @@ public class ChunkLoader
|
||||
#else ChunkType #endif
|
||||
readChunkType(CompoundTag tagLevel)
|
||||
{
|
||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagGetString(tagLevel,"Status"));
|
||||
if (chunkStatus != null)
|
||||
String statusString = tagGetString(tagLevel,"Status");
|
||||
if (statusString != null)
|
||||
{
|
||||
return chunkStatus.getChunkType();
|
||||
ChunkStatus chunkStatus = ChunkStatus.byName(statusString);
|
||||
if (chunkStatus != null)
|
||||
{
|
||||
return chunkStatus.getChunkType();
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_20_4
|
||||
@@ -406,43 +420,52 @@ public class ChunkLoader
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
CompoundTag tagHeightmaps = tagGetCompoundTag(chunkData, "Heightmaps");
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
if (tagHeightmaps != null)
|
||||
{
|
||||
String heightmap = type.getSerializationKey();
|
||||
#if MC_VER < MC_1_21_5
|
||||
if (tagHeightmaps.contains(heightmap, 12))
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
{
|
||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||
}
|
||||
#else
|
||||
if (tagHeightmaps.contains(heightmap))
|
||||
{
|
||||
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmap);
|
||||
if (optionalHeightmap.isPresent())
|
||||
String heightmap = type.getSerializationKey();
|
||||
#if MC_VER < MC_1_21_5
|
||||
if (tagHeightmaps.contains(heightmap, 12))
|
||||
{
|
||||
chunk.setHeightmap(type, optionalHeightmap.get());
|
||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||
}
|
||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
ListTag tagPostProcessings = tagGetListTag(chunkData,"PostProcessing", 9);
|
||||
for (int i = 0; i < tagPostProcessings.size(); ++i)
|
||||
{
|
||||
ListTag listTag3 = tagGetListTag(tagPostProcessings, i);
|
||||
for (int j = 0; j < listTag3.size(); ++j)
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
||||
#else
|
||||
chunk.addPackedPostProcess(ShortList.of(tagGetShort(listTag3, j)), i);
|
||||
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());
|
||||
}
|
||||
}
|
||||
// commented out as a test as of 2025-06-04 to see if this is actually necessary for DH
|
||||
// DH probably doesn't need any chunk post-processing data
|
||||
//private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||
//{
|
||||
// ListTag tagPostProcessings = tagGetListTag(chunkData,"PostProcessing", 9);
|
||||
// if (tagPostProcessings != null)
|
||||
// {
|
||||
// for (int i = 0; i < tagPostProcessings.size(); ++i)
|
||||
// {
|
||||
// ListTag listTag3 = tagGetListTag(tagPostProcessings, i);
|
||||
// for (int j = 0; j < listTag3.size(); ++j)
|
||||
// {
|
||||
// #if MC_VER < MC_1_21_3
|
||||
// chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
||||
// #else
|
||||
// chunk.addPackedPostProcess(ShortList.of(tagGetShort(listTag3, j)), i);
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
#if MC_VER >= MC_1_18_2
|
||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||
{
|
||||
@@ -728,6 +751,7 @@ public class ChunkLoader
|
||||
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static String tagGetString(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
@@ -738,6 +762,7 @@ public class ChunkLoader
|
||||
}
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static byte[] tagGetByteArray(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
|
||||
+1
-1
Submodule coreSubProjects updated: 3ed50e5134...9cb627eaac
@@ -33,6 +33,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
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.world.IClientLevelWrapper;
|
||||
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 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();
|
||||
|
||||
// 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
|
||||
ClientPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (client, handler, buffer, packetSender) ->
|
||||
{
|
||||
// Forge packet ID
|
||||
buffer.readByte();
|
||||
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
|
||||
AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
|
||||
if (message != null)
|
||||
{
|
||||
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||
|
||||
@@ -90,8 +90,8 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
||||
{
|
||||
ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor());
|
||||
|
||||
// If sodium is installed Indium is also necessary in order to use the Fabric rendering API
|
||||
if (!modChecker.isModLoaded("indium"))
|
||||
// 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") && SodiumAccessor.isSodiumV5OrLess)
|
||||
{
|
||||
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
||||
LOGGER.fatal(indiumMissingMessage);
|
||||
|
||||
+2
-6
@@ -22,9 +22,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
|
||||
ClientPlayNetworking.send(new CommonPacketPayload(message));
|
||||
#else // < 1.20.6
|
||||
FriendlyByteBuf buffer = PacketByteBufs.create();
|
||||
// Forge packet ID
|
||||
buffer.writeByte(0);
|
||||
AbstractPluginPacketSender.encodeMessage(buffer, message);
|
||||
this.encodeMessage(buffer, message);
|
||||
ClientPlayNetworking.send(WRAPPER_PACKET_RESOURCE, buffer);
|
||||
#endif
|
||||
}
|
||||
@@ -36,9 +34,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
|
||||
ServerPlayNetworking.send(serverPlayer, new CommonPacketPayload(message));
|
||||
#else // < 1.20.6
|
||||
FriendlyByteBuf buffer = PacketByteBufs.create();
|
||||
// Forge packet ID
|
||||
buffer.writeByte(0);
|
||||
AbstractPluginPacketSender.encodeMessage(buffer, message);
|
||||
this.encodeMessage(buffer, message);
|
||||
ServerPlayNetworking.send(serverPlayer, WRAPPER_PACKET_RESOURCE, buffer);
|
||||
#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.worldGeneration.BatchGenerationEnvironment;
|
||||
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.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
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;
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
|
||||
#endif
|
||||
|
||||
import java.util.function.Supplier;
|
||||
@@ -48,6 +50,8 @@ import java.util.function.Supplier;
|
||||
public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
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 final boolean isDedicatedServer;
|
||||
@@ -192,9 +196,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
||||
#else
|
||||
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
|
||||
{
|
||||
// Forge packet ID
|
||||
buffer.readByte();
|
||||
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
|
||||
AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
|
||||
if (message != null)
|
||||
{
|
||||
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
|
||||
|
||||
+12
-2
@@ -43,11 +43,22 @@ import net.minecraft.world.phys.AABB;
|
||||
|
||||
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
|
||||
private static MethodHandle setFogOcclusionMethod;
|
||||
private static Object sodiumPerformanceOptions;
|
||||
#endif
|
||||
|
||||
static {
|
||||
isSodiumV5OrLess = !classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
@@ -72,8 +83,7 @@ public class SodiumAccessor implements ISodiumAccessor
|
||||
{
|
||||
if (sodiumPerformanceOptions == null)
|
||||
{
|
||||
boolean sodiumV6 = classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||
if (!sodiumV6)
|
||||
if (isSodiumV5OrLess)
|
||||
{
|
||||
// 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.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
@@ -79,6 +80,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
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();
|
||||
|
||||
|
||||
@@ -96,7 +98,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
// 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);
|
||||
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||
|
||||
@@ -45,16 +45,18 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
|
||||
);
|
||||
#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
|
||||
PLUGIN_CHANNEL.messageBuilder(MessageWrapper.class, 0)
|
||||
.encoder((wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message))
|
||||
.decoder(in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)))
|
||||
.encoder((wrapper, out) -> this.encodeMessage(out, wrapper.message))
|
||||
.decoder(in -> new MessageWrapper(this.decodeMessage(in)))
|
||||
.consumerNetworkThread((wrapper, context) ->
|
||||
{
|
||||
if (wrapper.message != null)
|
||||
@@ -73,8 +75,8 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
|
||||
.add();
|
||||
#else // < 1.20.2
|
||||
PLUGIN_CHANNEL.registerMessage(0, MessageWrapper.class,
|
||||
(wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message),
|
||||
in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)),
|
||||
(wrapper, out) -> this.encodeMessage(out, wrapper.message),
|
||||
in -> new MessageWrapper(this.decodeMessage(in)),
|
||||
(wrapper, context) ->
|
||||
{
|
||||
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.worldGeneration.BatchGenerationEnvironment;
|
||||
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.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -51,6 +53,8 @@ import java.util.function.Supplier;
|
||||
|
||||
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
|
||||
private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); }
|
||||
#else
|
||||
@@ -68,7 +72,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
if (this.isDedicated)
|
||||
{
|
||||
ForgePluginPacketSender.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
|
||||
PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -5,7 +5,7 @@ org.gradle.caching=true
|
||||
|
||||
# Mod Info
|
||||
mod_name=DistantHorizons
|
||||
mod_version=2.3.2-b
|
||||
mod_version=2.3.3-b-dev
|
||||
api_version=4.0.0
|
||||
maven_group=com.seibel.distanthorizons
|
||||
mod_readable_name=Distant Horizons
|
||||
@@ -23,6 +23,7 @@ manifold_version=2024.1.37
|
||||
nightconfig_version=3.6.6
|
||||
lz4_version=1.8.0
|
||||
xz_version=1.9
|
||||
# Before updating, read relocate_natives/README.md
|
||||
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
|
||||
fastutil_version=8.2.1
|
||||
|
||||
@@ -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
|
||||
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.
@@ -24,6 +24,7 @@ fabric_api_version=0.42.0+1.16
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "*" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ fabric_api_version=0.46.1+1.17
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "*" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ fabric_api_version=0.76.0+1.18.2
|
||||
immersive_portals_version=v1.4.11-1.18
|
||||
canvas_version=mc118:1.0.2616
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "*" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ fabric_api_version=0.76.1+1.19.2
|
||||
immersive_portals_version=
|
||||
canvas_version=mc119-1.0.2480
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "*" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ fabric_api_version=0.87.1+1.19.4
|
||||
bclib_version=2.3.3
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "*" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ fabric_api_version=0.90.4+1.20.1
|
||||
bclib_version=3.0.13
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "<=1.7.4" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ fabric_api_version=0.90.4+1.20.2
|
||||
bclib_version=3.0.13
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "<=1.7.4" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ fabric_api_version=0.91.2+1.20.4
|
||||
bclib_version=
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "<=1.7.4" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ fabric_api_version=0.97.8+1.20.6
|
||||
bclib_version=
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "<=1.7.4" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ fabric_api_version=0.115.0+1.21.1
|
||||
bclib_version=
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
# iris - needs 1.7.4+ to support the DH API
|
||||
fabric_incompatibility_list={ "iris": "<=1.7.4" }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ fabric_api_version=0.110.5+1.21.4
|
||||
bclib_version=
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
|
||||
fabric_incompatibility_list={ }
|
||||
fabric_recommend_list={}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ fabric_api_version=0.119.5+1.21.5
|
||||
immersive_portals_version=
|
||||
canvas_version=
|
||||
|
||||
# some versions of 1.8.11 nightly builds may not work, but the ones after 2025-03-30 should
|
||||
# Iris - 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={}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user