Compare commits
228 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d09ddf57d3 | |||
| 486edac1d8 | |||
| 3b3731a137 | |||
| 563ec70154 | |||
| 175f5ed6d6 | |||
| 1e63607233 | |||
| 4dd8be23fa | |||
| 7fac5b4c6e | |||
| f2ec1ecf3f | |||
| 2674e6b2e9 | |||
| bcbe3f0fb7 | |||
| f85108ed11 | |||
| 2bc5169ce5 | |||
| 1edd809708 | |||
| 475111b38b | |||
| b44a967e56 | |||
| acea685e75 | |||
| 20f15a6b39 | |||
| debf52418c | |||
| cf71491381 | |||
| 0a4a8466cf | |||
| 31fac60d34 | |||
| c335020c2f | |||
| 4db4f2fbc6 | |||
| f9f4a208e7 | |||
| b5fa5936b3 | |||
| 6ceabe7895 | |||
| ec3d8afbfc | |||
| e9a0c6d097 | |||
| 0238568370 | |||
| 74be00e025 | |||
| c10af6dd04 | |||
| 85ee5ac833 | |||
| 21877d67a5 | |||
| ae33a79d6e | |||
| 9204b357d8 | |||
| 78b1b74036 | |||
| 864c5b5f86 | |||
| b271c8e119 | |||
| 79bdae5b8b | |||
| d5dc9f6b79 | |||
| a50f13caa0 | |||
| 75b3649a97 | |||
| 69adb54b91 | |||
| 458c1ae7e0 | |||
| a647551d26 | |||
| 3a45bdd2a2 | |||
| 4806cd2445 | |||
| af7f90f128 | |||
| f72ad60f58 | |||
| 6015afbf4c | |||
| 0369ae63f3 | |||
| 278d5063fb | |||
| a64e72034e | |||
| fcdb56660c | |||
| 0c26261cd5 | |||
| b50525fff9 | |||
| 92e403823b | |||
| e02f56f4ef | |||
| aa4681e044 | |||
| 1c9130c3f1 | |||
| c3597cd843 | |||
| d4a52ac5a3 | |||
| 1b9d14e7b4 | |||
| 0ea27b676e | |||
| cd73608b07 | |||
| 03fc22f611 | |||
| 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 | |||
| 0f08bd540e | |||
| 77088465f9 | |||
| affe014433 | |||
| 4c06bf6dbd | |||
| dcab616385 | |||
| 89b7d08e9b | |||
| 724e318221 | |||
| a40d62d46a | |||
| 2f6b4c079b | |||
| 951e3c0271 | |||
| 84825c2d09 | |||
| ec627e2eba | |||
| 06bc9a349f | |||
| ff6c4e227b | |||
| a4d46ffe94 | |||
| bd5c140782 | |||
| 229c3f7c91 | |||
| 693369bc08 | |||
| d109fe6c43 | |||
| 3c9d3707cf | |||
| 6e53564835 | |||
| 2480fe0d86 | |||
| 691c9d3f45 | |||
| 3faf25636d | |||
| ab3bfbefb4 | |||
| 890e802de4 | |||
| c13bc0cd6e | |||
| 7143b7de08 | |||
| d136d782f5 | |||
| 29a160316c | |||
| 1f6f64d322 | |||
| 37c0af529d | |||
| 1341ea3f3d | |||
| c0bb120669 | |||
| f8887e403f | |||
| 949ee423c8 | |||
| b19ed3f30c | |||
| 2d085e1074 | |||
| 6ba0490cf7 | |||
| b6a0878241 | |||
| 50f5371084 | |||
| df74b8d243 | |||
| fce2868c62 | |||
| a36cd0763b | |||
| 0fba015f54 | |||
| f251c90472 | |||
| 492a051a3b | |||
| 0aa4743c1b | |||
| 85f16944b2 | |||
| dddb0be2ac | |||
| 4a3effa2f5 | |||
| a0a9151bfd | |||
| aa3d15f38f | |||
| adcb2a3a05 | |||
| 78f2cb24cc | |||
| 67945509ed | |||
| c653e526a5 | |||
| 49b50c4c88 | |||
| 7449f46c5e | |||
| 069fc39aad | |||
| 4979ccf3e2 | |||
| dd7f9c20b6 | |||
| e96f9de1f0 | |||
| c902e1957f | |||
| d40afb7a2a | |||
| 01474d72e3 | |||
| 7c5af1836b | |||
| a9bf6ae7e4 | |||
| aef3162246 | |||
| 97ce869076 | |||
| 91b3c83ffd | |||
| 1522df19cb | |||
| 3845564128 | |||
| 23ef7cf27a | |||
| bec28a5694 | |||
| 8f20f103ad | |||
| 246e77cc56 | |||
| 87fa29c77a | |||
| 5010256ce6 | |||
| a66ad19343 | |||
| 913a458a1a | |||
| 093d3a801e | |||
| 61ccf7bf60 | |||
| f948072253 | |||
| b748f27a1c | |||
| 4dd4bb9ef0 | |||
| 5051bde3b0 | |||
| 42cf639acc | |||
| 9e6953a596 | |||
| 7f4f8a40eb | |||
| 89ca535a6f | |||
| 145182502e | |||
| d61dfc9e03 | |||
| 611d7d87ae | |||
| 2f6a2d99ab | |||
| d88ca0c98d | |||
| 0f64df7be0 | |||
| 23a1f0b025 | |||
| 4a72e02550 | |||
| 521bcdcc0f | |||
| 4eb20d5ce8 | |||
| 3ad68aaf42 | |||
| 2a9a03771e | |||
| 8f7823a4d2 | |||
| cc4b965966 | |||
| a6418de927 | |||
| 5303415d05 | |||
| 836515934f | |||
| 228dc46d6b | |||
| a91f9670dc | |||
| 81313252f2 | |||
| f65d411978 | |||
| 8c8a5ffeaf | |||
| 68793fbe8d | |||
| d8401a8f49 | |||
| 07ff00f7c9 | |||
| fadaff1113 | |||
| ff6bf7b4c9 | |||
| 082b1224a8 | |||
| bc475373fc | |||
| 498e958eca | |||
| 82e0cfe0b4 | |||
| 31d89e3349 | |||
| a3775c1f88 | |||
| 834269da67 | |||
| a9bebf03d5 | |||
| 939f6304bf | |||
| a0b5cc7a5c |
+1
-2
@@ -5,7 +5,6 @@ root = true
|
|||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = crlf
|
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = false
|
insert_final_newline = false
|
||||||
@@ -688,7 +687,7 @@ ij_markdown_wrap_text_inside_blockquotes = true
|
|||||||
ij_toml_keep_indents_on_empty_lines = false
|
ij_toml_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
[{*.yaml,*.yml}]
|
[{*.yaml,*.yml}]
|
||||||
indent_size = 2
|
indent_size = 4
|
||||||
ij_yaml_align_values_properties = do_not_align
|
ij_yaml_align_values_properties = do_not_align
|
||||||
ij_yaml_autoinsert_sequence_marker = true
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
ij_yaml_block_mapping_on_new_line = false
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ Merged/
|
|||||||
# Folder created by the buildAll scripts
|
# Folder created by the buildAll scripts
|
||||||
buildAllJars/
|
buildAllJars/
|
||||||
|
|
||||||
|
relocate_natives/.venv/
|
||||||
|
relocate_natives/__pycache__/
|
||||||
|
relocate_natives/apple-codesign/
|
||||||
|
|
||||||
# file from notepad++
|
# file from notepad++
|
||||||
*.bak
|
*.bak
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -35,13 +35,13 @@ build:
|
|||||||
stage: build
|
stage: build
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4"]
|
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.8"]
|
||||||
script:
|
script:
|
||||||
# this both runs the unit tests and assembles the code
|
# this both runs the unit tests and assembles the code
|
||||||
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||||
- ./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 ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./build/merged/* . || true
|
||||||
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:
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ Or click the checkbox once the issue has been created.
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
1. [ ] Check the FAQ to see if your issue has already been reported and has a solution:
|
1. [ ] Check the FAQ to see if your issue has already been reported and has a solution:
|
||||||
[Problems-and-solutions](https://gitlab.com/jeseibel/distant-horizons/-/wikis/2-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions)
|
[Problems-and-solutions](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions)
|
||||||
|
|
||||||
2. [ ] Make sure you are not using any mods on the incompatible list:
|
2. [ ] Make sure you are not using any mods on the incompatible list:
|
||||||
[Mod support FAQ](https://gitlab.com/jeseibel/distant-horizons/-/wikis/2-frequently-asked-questions/4-mod-support/Mod-Support)
|
[Mod support FAQ](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/4-mod-support/Mod-Support)
|
||||||
|
|
||||||
3. [ ] Check the existing issues to verify that your bug hasn't already been submitted:
|
3. [ ] Check the existing issues to verify that your bug hasn't already been submitted:
|
||||||
[Issues](https://gitlab.com/jeseibel/distant-horizons/-/issues/)
|
[Issues](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues)
|
||||||
|
|
||||||
4. [ ] Upload Minecraft's crash report and/or log. \
|
4. [ ] Upload Minecraft's crash report and/or log. \
|
||||||
Minecraft crash reports are located in: `.minecraft/crash-reports` \
|
Minecraft crash reports are located in: `.minecraft/crash-reports` \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
- [ ] Check the existing [feature requests](https://gitlab.com/jeseibel/distant-horizons/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=Feature) to verify that your feature hasn't already been suggested.
|
- [ ] Check the existing [feature requests](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues?sort=updated_desc&state=opened&label_name%5B%5D=Feature) to verify that your feature hasn't already been suggested.
|
||||||
|
|
||||||
1. **Describe the feature**:
|
1. **Describe the feature**:
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
1. Check the existing [improvement requests](https://gitlab.com/jeseibel/distant-horizons/-/issues/?sort=updated_desc&state=all&label_name%5B%5D=Improvement) to verify that your improvement hasn't already been suggested.
|
1. Check the existing [improvement requests](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues?sort=updated_desc&state=all&label_name%5B%5D=Improvement) to verify that your improvement hasn't already been suggested.
|
||||||
|
|
||||||
2. **Describe the improvement**:
|
2. **Describe the improvement**:
|
||||||
|
|||||||
+81
-62
@@ -1,3 +1,11 @@
|
|||||||
|
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
|
||||||
|
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
|
||||||
|
import org.apache.tools.zip.ZipEntry
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull
|
||||||
|
import org.apache.tools.zip.ZipOutputStream
|
||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
|
|
||||||
@@ -5,13 +13,13 @@ 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 "1.3.4"
|
||||||
|
|
||||||
// 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"
|
||||||
|
|
||||||
// Architectury is used here only as a replacement for forge's own loom
|
// Architectury is used here only as a replacement for forge's own loom
|
||||||
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
|
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,41 +67,64 @@ 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"))
|
class NativeTransformer implements Transformer {
|
||||||
forge {
|
private final HashMap<String, String> replacements = new HashMap()
|
||||||
jarLocation = "build/libs/DistantHorizons-forge-${rootProject.versionStr}.jar"
|
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||||
}
|
private var nativeRelocator
|
||||||
|
|
||||||
if (findProject(":neoforge"))
|
public File rootDir
|
||||||
custom {
|
|
||||||
projectName = "neoforge"
|
void relocateNative(String target, String replacement) {
|
||||||
jarLocation = "build/libs/DistantHorizons-neoforge-${rootProject.versionStr}.jar"
|
if (replacement.length() > target.length()) {
|
||||||
|
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findProject(":fabric"))
|
replacements.put(target, replacement)
|
||||||
fabric {
|
}
|
||||||
jarLocation = "build/libs/DistantHorizons-fabric-${rootProject.versionStr}.jar"
|
|
||||||
|
@Override
|
||||||
|
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||||
|
return replacements.keySet().stream().anyMatch {
|
||||||
|
element.name.startsWith(it as String)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void transform(@Nonnull TransformerContext context) {
|
||||||
|
byte[] content = context.is.readAllBytes()
|
||||||
|
|
||||||
|
if (nativeRelocator == null) {
|
||||||
|
nativeRelocator = new NativeRelocator(rootDir.toPath().resolve("relocate_natives"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findProject(":quilt"))
|
try {
|
||||||
quilt {
|
Map.Entry<String, String> pathReplacement = replacements.entrySet().stream().filter {
|
||||||
jarLocation = "build/libs/DistantHorizons-quilt-${rootProject.versionStr}.jar"
|
context.path.startsWith(it.key as String)
|
||||||
}
|
}.findFirst().orElseThrow()
|
||||||
|
|
||||||
removeDuplicate "com.seibel.distanthorizons"
|
String path = context.path.replace(pathReplacement.key as String, pathReplacement.value as String)
|
||||||
|
content = nativeRelocator.processBinary(path, content, replacements)
|
||||||
|
|
||||||
|
rewrittenFiles.put(path, content)
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
throw new GradleException("Failed to relocate", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean hasTransformedResource() { return !rewrittenFiles.isEmpty() }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void modifyOutputStream(@Nonnull ZipOutputStream os, boolean preserveFileTimestamps) {
|
||||||
|
for (Map.Entry<String, byte[]> rewrittenFile : rewrittenFiles.entrySet()) {
|
||||||
|
os.putNextEntry(new ZipEntry(rewrittenFile.key))
|
||||||
|
os.write(rewrittenFile.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects { p ->
|
subprojects { p ->
|
||||||
@@ -214,7 +245,9 @@ subprojects { p ->
|
|||||||
// Note: MC 1.16 uses 8.2.1, and versions after use 8.5.12
|
// Note: MC 1.16 uses 8.2.1, and versions after use 8.5.12
|
||||||
// We cannot relocate this library since we call some MC classes that reference it
|
// We cannot relocate this library since we call some MC classes that reference it
|
||||||
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
|
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
|
||||||
|
|
||||||
|
//forgeShadowMe("com.github.luben:zstd-jni:1.5.7-3")
|
||||||
|
//forgeShadowMe("org.apache.commons:commons-compress:1.27.1")
|
||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
||||||
@@ -306,26 +339,20 @@ subprojects { p ->
|
|||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
relocate "org.slf4j", "${librariesLocation}.slf4j"
|
relocate "org.slf4j", "${librariesLocation}.slf4j"
|
||||||
|
|
||||||
// // Sqlite Database
|
// Sqlite Database
|
||||||
// // James can't determine how to relocate the library correctly so this is commented out
|
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
||||||
// relocate ("org.sqlite", "${librariesLocation}.sqlite") {
|
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
||||||
// exclude("org/sqlite/core/NativeDB/**")
|
relocate "org.sqlite", "dh_sqlite", {
|
||||||
//
|
exclude "org/sqlite/native/**"
|
||||||
// exclude("org/sqlite/native/FreeBSD/**")
|
}
|
||||||
// exclude("org/sqlite/native/Linux-Android/**")
|
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||||
// exclude("org/sqlite/native/Linux-Musl/**")
|
|
||||||
// exclude("org/sqlite/native/Linux/arm/**")
|
transform(NativeTransformer) {
|
||||||
// exclude("org/sqlite/native/Linux/aarch64/**")
|
rootDir = project.rootDir
|
||||||
// exclude("org/sqlite/native/Linux/armv6/**")
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
// exclude("org/sqlite/native/Linux/x86/**")
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
// exclude("org/sqlite/native/Linux/armv7/**")
|
}
|
||||||
// exclude("org/sqlite/native/Linux/ppc64/**")
|
|
||||||
// exclude("org/sqlite/native/Linux/riscv64/**")
|
|
||||||
// exclude("org/sqlite/native/Windows/armv7/**")
|
|
||||||
// exclude("org/sqlite/native/Windows/aarch64/**")
|
|
||||||
// exclude("org/sqlite/native/Windows/armv7/**")
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// JOML
|
// JOML
|
||||||
@@ -420,6 +447,8 @@ subprojects { p ->
|
|||||||
|
|
||||||
fabric_incompatibility_list : fabric_incompatibility_list,
|
fabric_incompatibility_list : fabric_incompatibility_list,
|
||||||
fabric_recommend_list : fabric_recommend_list,
|
fabric_recommend_list : fabric_recommend_list,
|
||||||
|
|
||||||
|
neoforge_version_range : neoforge_version_range,
|
||||||
]
|
]
|
||||||
|
|
||||||
// replace any properties in the sub-projects with the values defined here
|
// replace any properties in the sub-projects with the values defined here
|
||||||
@@ -500,8 +529,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
|
||||||
@@ -666,14 +696,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)
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ for d in versionProperties/*; do
|
|||||||
echo "==================== Merging $version ===================="
|
echo "==================== Merging $version ===================="
|
||||||
sh gradlew mergeJars -PmcVer=$version
|
sh gradlew mergeJars -PmcVer=$version
|
||||||
if [ $? != 0 ]; then continue; fi
|
if [ $? != 0 ]; then continue; fi
|
||||||
|
|
||||||
echo "==================== Moving jar ===================="
|
echo "==================== Moving jar ===================="
|
||||||
mv Merged/*.jar buildAllJars/
|
mv build/merged/*.jar buildAllJars/
|
||||||
done
|
done
|
||||||
|
|||||||
+7
-4
@@ -14,13 +14,16 @@ for %%f in (versionProperties\*) do (
|
|||||||
|
|
||||||
@rem Clean out the folders, build it, and merge it
|
@rem Clean out the folders, build it, and merge it
|
||||||
echo ==================== Cleaning workspace to build !version! ====================
|
echo ==================== Cleaning workspace to build !version! ====================
|
||||||
call .\gradlew.bat clean -PmcVer="!version!"
|
call .\gradlew.bat clean
|
||||||
echo ==================== Building !version! ====================
|
|
||||||
|
echo ==================== Building !version! ====================
|
||||||
call .\gradlew.bat build -PmcVer="!version!"
|
call .\gradlew.bat build -PmcVer="!version!"
|
||||||
echo ==================== Merging !version! ====================
|
|
||||||
|
echo ==================== Merging !version! ====================
|
||||||
call .\gradlew.bat mergeJars -PmcVer="!version!"
|
call .\gradlew.bat mergeJars -PmcVer="!version!"
|
||||||
|
|
||||||
echo ==================== Moving jar ====================
|
echo ==================== Moving jar ====================
|
||||||
move Merged\*.jar buildAllJars\
|
move build\merged\*.jar buildAllJars\
|
||||||
)
|
)
|
||||||
|
|
||||||
endlocal
|
endlocal
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
class NativeRelocator
|
||||||
|
{
|
||||||
|
private final Path rootDirectory;
|
||||||
|
private final Path cacheRoot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||||
|
* Executes the appropriate preparation script based on the OS.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
processBuilder.directory(this.rootDirectory.toFile());
|
||||||
|
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
if (os.contains("win"))
|
||||||
|
{
|
||||||
|
processBuilder.command("powershell", "-ExecutionPolicy", "Bypass", "./prepare.ps1");
|
||||||
|
}
|
||||||
|
else if (os.contains("nix") || os.contains("nux") || os.contains("mac"))
|
||||||
|
{
|
||||||
|
processBuilder.command("./prepare.sh");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Unsupported operating system: " + os);
|
||||||
|
}
|
||||||
|
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
CompletableFuture<Void> outputFuture = readOutputStreams(process);
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
outputFuture.get();
|
||||||
|
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Prepare failed: " + exitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and prints the output and error streams of a process asynchronously.
|
||||||
|
*
|
||||||
|
* @param process The process whose streams should be read.
|
||||||
|
* @return A CompletableFuture that completes once all output has been processed.
|
||||||
|
*/
|
||||||
|
private static CompletableFuture<Void> readOutputStreams(Process process)
|
||||||
|
{
|
||||||
|
return CompletableFuture.runAsync(() -> {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (process.isAlive() || process.getInputStream().available() > 0 || process.getErrorStream().available() > 0)
|
||||||
|
{
|
||||||
|
if (process.getInputStream().available() > 0)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[process.getInputStream().available()];
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
process.getInputStream().read(data);
|
||||||
|
System.out.write(data);
|
||||||
|
}
|
||||||
|
if (process.getErrorStream().available() > 0)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[process.getErrorStream().available()];
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
process.getErrorStream().read(data);
|
||||||
|
System.err.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection BusyWait
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable ignored)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces occurrences of a target string in a byte array, ensuring null termination.
|
||||||
|
*
|
||||||
|
* @param byteArray The byte array where replacements should occur.
|
||||||
|
* @param target The string to replace.
|
||||||
|
* @param replacement The replacement string (must not be longer than the target).
|
||||||
|
* @throws IllegalArgumentException if the replacement is longer than the target.
|
||||||
|
*/
|
||||||
|
private void replaceInNullTerminatedStrings(byte[] byteArray, String target, String replacement)
|
||||||
|
{
|
||||||
|
if (target.length() < replacement.length())
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Replacement must be the same length or shorter than the target.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] targetBytes = target.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
byte[] replacementBytes = replacement.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
|
byte nullByte = 0;
|
||||||
|
|
||||||
|
for (int endPos = 0; endPos < byteArray.length - targetBytes.length - 1; endPos++)
|
||||||
|
{
|
||||||
|
int startPos = endPos;
|
||||||
|
int targetPos = 0;
|
||||||
|
while (targetPos < targetBytes.length && byteArray[endPos] == targetBytes[targetPos])
|
||||||
|
{
|
||||||
|
targetPos++;
|
||||||
|
endPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetPos == targetBytes.length)
|
||||||
|
{
|
||||||
|
System.arraycopy(replacementBytes, 0, byteArray, startPos, replacementBytes.length);
|
||||||
|
|
||||||
|
startPos = startPos + replacementBytes.length;
|
||||||
|
while (byteArray[endPos] != nullByte)
|
||||||
|
{
|
||||||
|
byteArray[startPos] = byteArray[endPos];
|
||||||
|
endPos++;
|
||||||
|
startPos++;
|
||||||
|
}
|
||||||
|
byteArray[startPos] = nullByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs an external script to fix a modified binary and returns the processed content.
|
||||||
|
*
|
||||||
|
* @param outputFilePath Path to store the processed binary.
|
||||||
|
* @param content The original binary content.
|
||||||
|
* @return The modified binary content.
|
||||||
|
* @throws Exception if the process execution fails.
|
||||||
|
*/
|
||||||
|
public byte[] fixModifiedBinary(Path outputFilePath, byte[] content) throws Exception
|
||||||
|
{
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
processBuilder.directory(this.rootDirectory.toFile());
|
||||||
|
|
||||||
|
processBuilder.command(
|
||||||
|
this.rootDirectory.resolve(".venv/Scripts").toFile().exists()
|
||||||
|
? this.rootDirectory.resolve(".venv/Scripts/python.exe").toString()
|
||||||
|
: this.rootDirectory.resolve(".venv/bin/python").toString(),
|
||||||
|
"./fix_modified_binary.py",
|
||||||
|
outputFilePath.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
CompletableFuture<Void> outputFuture = readOutputStreams(process);
|
||||||
|
|
||||||
|
process.getOutputStream().write(content);
|
||||||
|
process.getOutputStream().close();
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
outputFuture.get();
|
||||||
|
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Process failed: " + exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Files.readAllBytes(outputFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a binary file, applying string replacements and fixing modifications.
|
||||||
|
*
|
||||||
|
* @param outputPath The output file path relative to the cache directory.
|
||||||
|
* @param content The binary content to process.
|
||||||
|
* @param replacements A map of string replacements to apply.
|
||||||
|
* @return The modified binary content.
|
||||||
|
* @throws Exception if processing fails.
|
||||||
|
*/
|
||||||
|
public byte[] processBinary(String outputPath, byte[] content, Map<String, String> replacements) throws Exception
|
||||||
|
{
|
||||||
|
Path outputFilePath = this.cacheRoot.resolve(outputPath);
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
outputFilePath.getParent().toFile().mkdirs();
|
||||||
|
|
||||||
|
if (outputFilePath.toFile().exists())
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.fixModifiedBinary(outputFilePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
-10
@@ -66,7 +66,7 @@ public abstract class AbstractModInitializer
|
|||||||
{
|
{
|
||||||
DependencySetup.createClientBindings();
|
DependencySetup.createClientBindings();
|
||||||
|
|
||||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client.");
|
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client, firing DhApiBeforeDhInitEvent...");
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||||
|
|
||||||
this.startup();
|
this.startup();
|
||||||
@@ -77,13 +77,12 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
this.initializeModCompat();
|
this.initializeModCompat();
|
||||||
|
|
||||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
|
||||||
|
|
||||||
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
||||||
this.initConfig();
|
this.initConfig();
|
||||||
logModIncompatibilityWarnings(); // needs to be called after config loading
|
logModIncompatibilityWarnings(); // needs to be called after config loading
|
||||||
|
|
||||||
|
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||||
|
|
||||||
this.subscribeClientStartedEvent(this::postInit);
|
this.subscribeClientStartedEvent(this::postInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +90,7 @@ public abstract class AbstractModInitializer
|
|||||||
{
|
{
|
||||||
DependencySetup.createServerBindings();
|
DependencySetup.createServerBindings();
|
||||||
|
|
||||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server.");
|
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server, firing DhApiBeforeDhInitEvent event...");
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||||
|
|
||||||
this.startup();
|
this.startup();
|
||||||
@@ -106,8 +105,7 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
this.initializeModCompat();
|
this.initializeModCompat();
|
||||||
|
|
||||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized.");
|
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
|
||||||
|
|
||||||
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer = new CommandInitializer(dispatcher); });
|
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer = new CommandInitializer(dispatcher); });
|
||||||
|
|
||||||
@@ -121,7 +119,7 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
this.checkForUpdates();
|
this.checkForUpdates();
|
||||||
|
|
||||||
LOGGER.info("Dedicated server initialized at " + server.getServerDirectory());
|
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,9 +181,12 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
private void postInit()
|
private void postInit()
|
||||||
{
|
{
|
||||||
LOGGER.info("Post-Initializing Mod");
|
LOGGER.info("Running Delayed setup...");
|
||||||
this.runDelayedSetup();
|
this.runDelayedSetup();
|
||||||
LOGGER.info("Mod Post-Initialized");
|
LOGGER.info("Delayed setup complete, firing DhApiAfterDhInitEvent event...");
|
||||||
|
|
||||||
|
// should be fired after all delayed setup so singletons and config can be accessed
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+23
-4
@@ -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);
|
||||||
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
|
||||||
|
if (this.forgeByteInProtocolVersion)
|
||||||
|
{
|
||||||
|
out.writeByte(ModInfo.PROTOCOL_VERSION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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()); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
|||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -40,6 +41,7 @@ public class ConfigCommand extends AbstractCommand
|
|||||||
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||||
{
|
{
|
||||||
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
|
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
|
||||||
|
HashSet<String> addedCommands = new HashSet<>();
|
||||||
|
|
||||||
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
|
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
|
||||||
{
|
{
|
||||||
@@ -56,6 +58,11 @@ public class ConfigCommand extends AbstractCommand
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!addedCommands.add(configEntry.getChatCommandName()))
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Duplicate command name: " + configEntry.getChatCommandName());
|
||||||
|
}
|
||||||
|
|
||||||
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getChatCommandName())
|
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getChatCommandName())
|
||||||
.executes(commandContext -> this.sendSuccessResponse(commandContext,
|
.executes(commandContext -> this.sendSuccessResponse(commandContext,
|
||||||
"\n" +
|
"\n" +
|
||||||
|
|||||||
+6
-2
@@ -49,7 +49,9 @@ public class McObjectConverter
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public static Mat4f Convert(
|
public static Mat4f Convert(
|
||||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||||
#else org.joml.Matrix4f #endif
|
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||||
|
#else org.joml.Matrix4fc
|
||||||
|
#endif
|
||||||
mcMatrix)
|
mcMatrix)
|
||||||
{
|
{
|
||||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||||
@@ -63,7 +65,9 @@ public class McObjectConverter
|
|||||||
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
|
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
|
||||||
private static void storeMatrix(
|
private static void storeMatrix(
|
||||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||||
#else org.joml.Matrix4f #endif
|
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||||
|
#else org.joml.Matrix4fc
|
||||||
|
#endif
|
||||||
matrix,
|
matrix,
|
||||||
FloatBuffer buffer)
|
FloatBuffer buffer)
|
||||||
{
|
{
|
||||||
|
|||||||
+41
-23
@@ -20,8 +20,6 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers;
|
package com.seibel.distanthorizons.common.wrappers;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
import net.minecraft.SharedConstants;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author James Seibel
|
* @author James Seibel
|
||||||
@@ -38,32 +36,52 @@ public class VersionConstants implements IVersionConstants
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMinimumWorldHeight()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWorldGenerationCountPerThread()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVanillaRenderedChunkSquare()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMinecraftVersion()
|
public String getMinecraftVersion()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_19_2
|
// these values are hard-coded to prevent an issue with Forge (specifically 1.18.2) where
|
||||||
return Minecraft.getInstance().getGame().getVersion().getId();
|
// it can't load client classes when running as a dedicated server,
|
||||||
|
// which was how we were dynamically accessing the MC version string
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_16_5
|
||||||
|
return "1.16.5";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_17_1
|
||||||
|
return "1.17.1";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_18_2
|
||||||
|
return "1.18.2";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_19_2
|
||||||
|
return "1.19.2";
|
||||||
|
#elif MC_VER == MC_1_19_4
|
||||||
|
return "1.19.4";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_20_1
|
||||||
|
return "1.20.1";
|
||||||
|
#elif MC_VER == MC_1_20_2
|
||||||
|
return "1.20.2";
|
||||||
|
#elif MC_VER == MC_1_20_4
|
||||||
|
return "1.20.4";
|
||||||
|
#elif MC_VER == MC_1_20_6
|
||||||
|
return "1.20.6";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_21_1
|
||||||
|
return "1.21.1";
|
||||||
|
#elif MC_VER == MC_1_21_3
|
||||||
|
return "1.21.3";
|
||||||
|
#elif MC_VER == MC_1_21_4
|
||||||
|
return "1.21.4";
|
||||||
|
#elif MC_VER == MC_1_21_5
|
||||||
|
return "1.21.5";
|
||||||
|
#elif MC_VER == MC_1_21_6
|
||||||
|
return "1.21.6";
|
||||||
|
#elif MC_VER == MC_1_21_8
|
||||||
|
return "1.21.8";
|
||||||
#else
|
#else
|
||||||
return SharedConstants.getCurrentVersion().getId();
|
ERROR MC version constant missing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+82
-59
@@ -47,6 +47,7 @@ import net.minecraft.core.registries.Registries;
|
|||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.biome.Biomes;
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
#endif
|
#endif
|
||||||
@@ -130,14 +131,6 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
//LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
|
//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;
|
BiomeWrapper foundWrapper = EMPTY_WRAPPER;
|
||||||
try
|
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
|
try
|
||||||
{
|
{
|
||||||
Level level = (Level) levelWrapper.getWrappedMcObject();
|
Level level = (Level) levelWrapper.getWrappedMcObject();
|
||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
|
|
||||||
boolean success;
|
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess);
|
||||||
#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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!success)
|
if (!deserializeResult.success)
|
||||||
{
|
{
|
||||||
if (!brokenResourceLocationStrings.contains(resourceLocationString))
|
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;
|
return foundWrapper;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-25
@@ -43,6 +43,8 @@ import java.util.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@@ -84,26 +86,25 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
|
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
|
||||||
|
|
||||||
/** keep track of broken blocks so we don't log every time */
|
/** keep track of broken blocks so we don't log every time */
|
||||||
private static final HashSet<ResourceLocation> BrokenResourceLocations = new HashSet<>();
|
private static final HashSet<ResourceLocation> BROKEN_RESOURCE_LOCATIONS = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// properties //
|
// properties //
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public final BlockState blockState;
|
public final BlockState blockState;
|
||||||
/** technically final, but since it requires a method call to generate it can't be marked as such */
|
/** technically final, but since it requires a method call to generate it can't be marked as such */
|
||||||
private String serialString;
|
private String serialString;
|
||||||
private final int hashCode;
|
private final int hashCode;
|
||||||
/**
|
/** Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE} */
|
||||||
* Cached opacity value, -1 if not populated. <br>
|
private final int opacity;
|
||||||
* Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE}
|
|
||||||
*/
|
|
||||||
private int opacity = -1;
|
|
||||||
/** used by the Iris shader mod to determine how each LOD should be rendered */
|
/** used by the Iris shader mod to determine how each LOD should be rendered */
|
||||||
private byte blockMaterialId = 0;
|
private byte blockMaterialId = 0;
|
||||||
|
|
||||||
private final boolean isBeaconBlock;
|
private final boolean isBeaconBlock;
|
||||||
private final boolean isBeaconBaseBlock;
|
private final boolean isBeaconBaseBlock;
|
||||||
|
private final boolean allowsBeaconBeamPassage;
|
||||||
/** null if this block can't tint beacons */
|
/** null if this block can't tint beacons */
|
||||||
private final Color beaconTintColor;
|
private final Color beaconTintColor;
|
||||||
private final Color mapColor;
|
private final Color mapColor;
|
||||||
@@ -160,9 +161,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
this.serialString = this.serialize(levelWrapper);
|
this.serialString = this.serialize(levelWrapper);
|
||||||
this.hashCode = Objects.hash(this.serialString);
|
this.hashCode = Objects.hash(this.serialString);
|
||||||
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
||||||
|
this.opacity = this.calculateOpacity();
|
||||||
|
|
||||||
|
String lowercaseSerial = this.serialString.toLowerCase();
|
||||||
|
|
||||||
|
|
||||||
// beacon blocks
|
// beacon blocks
|
||||||
String lowercaseSerial = this.serialString.toLowerCase();
|
|
||||||
boolean isBeaconBaseBlock = false;
|
boolean isBeaconBaseBlock = false;
|
||||||
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -198,6 +202,39 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
this.beaconTintColor = beaconTintColor;
|
this.beaconTintColor = beaconTintColor;
|
||||||
|
|
||||||
|
|
||||||
|
// allow/deny beacon beam passage
|
||||||
|
boolean allowsBeaconBeamPassage;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
// get block properties (defaults to the values used by air)
|
||||||
|
boolean canOcclude = this.getCanOcclude();
|
||||||
|
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||||
|
|
||||||
|
if (lowercaseSerial.contains("minecraft:bedrock"))
|
||||||
|
{
|
||||||
|
// bedrock is a special case fully opaque block that does allow beacons through
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
else if (propagatesSkyLightDown || !canOcclude)
|
||||||
|
{
|
||||||
|
// stairs, cake, fences, etc.
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non-opaque blocks (glass, mob spawners, etc.)
|
||||||
|
// all allow beacons through
|
||||||
|
allowsBeaconBeamPassage = (this.opacity != LodUtil.BLOCK_FULLY_OPAQUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// air allows beacons through
|
||||||
|
allowsBeaconBeamPassage = true;
|
||||||
|
}
|
||||||
|
this.allowsBeaconBeamPassage = allowsBeaconBeamPassage;
|
||||||
|
|
||||||
|
|
||||||
int mcColor = 0;
|
int mcColor = 0;
|
||||||
if (this.blockState != null)
|
if (this.blockState != null)
|
||||||
{
|
{
|
||||||
@@ -341,13 +378,13 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
//=================//
|
//=================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOpacity()
|
public int getOpacity() { return this.opacity; }
|
||||||
|
private int calculateOpacity()
|
||||||
{
|
{
|
||||||
// use the cached opacity value if possible
|
// get block properties (defaults to the values used by air)
|
||||||
if (this.opacity != -1)
|
boolean canOcclude = this.getCanOcclude();
|
||||||
{
|
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||||
return this.opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// this method isn't perfect, but works well enough for our use case
|
// this method isn't perfect, but works well enough for our use case
|
||||||
@@ -356,19 +393,20 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
{
|
{
|
||||||
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
||||||
}
|
}
|
||||||
else if (this.isLiquid() && !this.blockState.canOcclude())
|
else if (this.isLiquid() && !canOcclude)
|
||||||
{
|
{
|
||||||
// probably not a waterlogged block (which should block light entirely)
|
// probably not a waterlogged block (which should block light entirely)
|
||||||
|
|
||||||
// +1 to indicate that the block is translucent (in between transparent and opaque)
|
// +1 to indicate that the block is translucent (in between transparent and opaque)
|
||||||
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1;
|
||||||
}
|
}
|
||||||
#if MC_VER < MC_1_21_3
|
else if (propagatesSkyLightDown && !canOcclude)
|
||||||
else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))
|
|
||||||
#else
|
|
||||||
else if (this.blockState.propagatesSkylightDown())
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
|
// probably glass or some other fully transparent block
|
||||||
|
|
||||||
|
// !canOcclude is required to ignore stairs and slabs since
|
||||||
|
// propagateSkyLightDown is true for them, but they're solid and don't actually let light through
|
||||||
|
|
||||||
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -378,9 +416,37 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.opacity = opacity;
|
return opacity;
|
||||||
return this.opacity;
|
|
||||||
}
|
}
|
||||||
|
private boolean getCanOcclude()
|
||||||
|
{
|
||||||
|
// defaults to the value used by air
|
||||||
|
boolean canOcclude = false;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
canOcclude = this.blockState.canOcclude();
|
||||||
|
}
|
||||||
|
|
||||||
|
return canOcclude;
|
||||||
|
}
|
||||||
|
private boolean getPropagatesSkyLightDown()
|
||||||
|
{
|
||||||
|
// defaults to the value used by air
|
||||||
|
boolean propagatesSkyLightDown = true;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||||
|
#else
|
||||||
|
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return propagatesSkyLightDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
||||||
@@ -453,6 +519,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
||||||
@Override
|
@Override
|
||||||
public boolean isBeaconTintBlock() { return this.beaconTintColor != null; }
|
public boolean isBeaconTintBlock() { return this.beaconTintColor != null; }
|
||||||
|
@Override
|
||||||
|
public boolean allowsBeaconBeamPassage() { return this.allowsBeaconBeamPassage; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color getMapColor() { return this.mapColor; }
|
public Color getMapColor() { return this.mapColor; }
|
||||||
@@ -596,9 +664,9 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
if (block == null)
|
if (block == null)
|
||||||
{
|
{
|
||||||
// shouldn't normally happen, but here to make the compiler happy
|
// shouldn't normally happen, but here to make the compiler happy
|
||||||
if (!BrokenResourceLocations.contains(resourceLocation))
|
if (!BROKEN_RESOURCE_LOCATIONS.contains(resourceLocation))
|
||||||
{
|
{
|
||||||
BrokenResourceLocations.add(resourceLocation);
|
BROKEN_RESOURCE_LOCATIONS.add(resourceLocation);
|
||||||
LOGGER.warn("Unable to find BlockState with the resourceLocation [" + resourceLocation + "] and properties: [" + blockStatePropertiesString + "]. Air will be used instead, some data may be lost.");
|
LOGGER.warn("Unable to find BlockState with the resourceLocation [" + resourceLocation + "] and properties: [" + blockStatePropertiesString + "]. Air will be used instead, some data may be lost.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,9 +696,9 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
if (blockStatePropertiesString != null)
|
if (blockStatePropertiesString != null)
|
||||||
{
|
{
|
||||||
// we should have found a blockstate, but didn't
|
// we should have found a blockstate, but didn't
|
||||||
if (!BrokenResourceLocations.contains(resourceLocation))
|
if (!BROKEN_RESOURCE_LOCATIONS.contains(resourceLocation))
|
||||||
{
|
{
|
||||||
BrokenResourceLocations.add(resourceLocation);
|
BROKEN_RESOURCE_LOCATIONS.add(resourceLocation);
|
||||||
LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state.");
|
LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+76
-19
@@ -40,11 +40,18 @@ import java.util.Random;
|
|||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.renderer.block.model.BlockModelPart;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This stores and calculates the colors
|
* This stores and calculates the colors
|
||||||
* the given {@link BlockState} should have based
|
* the given {@link BlockState} should have based
|
||||||
@@ -84,7 +91,7 @@ public class ClientBlockStateColorCache
|
|||||||
private static final RandomSource RANDOM = RandomSource.create();
|
private static final RandomSource RANDOM = RandomSource.create();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private final IClientLevelWrapper levelWrapper;
|
private final IClientLevelWrapper clientLevelWrapper;
|
||||||
private final BlockState blockState;
|
private final BlockState blockState;
|
||||||
private final LevelReader level;
|
private final LevelReader level;
|
||||||
|
|
||||||
@@ -167,7 +174,7 @@ public class ClientBlockStateColorCache
|
|||||||
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper samplingLevel)
|
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper samplingLevel)
|
||||||
{
|
{
|
||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
this.levelWrapper = samplingLevel;
|
this.clientLevelWrapper = samplingLevel;
|
||||||
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
||||||
this.resolveColors();
|
this.resolveColors();
|
||||||
}
|
}
|
||||||
@@ -196,9 +203,7 @@ public class ClientBlockStateColorCache
|
|||||||
List<BakedQuad> quads = null;
|
List<BakedQuad> quads = null;
|
||||||
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
||||||
{
|
{
|
||||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
quads = this.getQuadsForDirection(direction);
|
||||||
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
|
||||||
|
|
||||||
if (quads != null && !quads.isEmpty()
|
if (quads != null && !quads.isEmpty()
|
||||||
&& !(
|
&& !(
|
||||||
this.blockState.getBlock() instanceof RotatedPillarBlock
|
this.blockState.getBlock() instanceof RotatedPillarBlock
|
||||||
@@ -212,19 +217,37 @@ public class ClientBlockStateColorCache
|
|||||||
|
|
||||||
if (quads == null || quads.isEmpty())
|
if (quads == null || quads.isEmpty())
|
||||||
{
|
{
|
||||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
quads = this.getUnculledQuads();
|
||||||
getBlockModel(this.blockState).getQuads(this.blockState, null, RANDOM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quads != null && !quads.isEmpty())
|
if (quads != null
|
||||||
|
&& !quads.isEmpty()
|
||||||
|
&& quads.get(0) != null)
|
||||||
{
|
{
|
||||||
this.needPostTinting = quads.get(0).isTinted();
|
BakedQuad firstQuad = quads.get(0);
|
||||||
this.needShade = quads.get(0).isShade();
|
|
||||||
this.tintIndex = quads.get(0).getTintIndex();
|
this.needPostTinting = firstQuad.isTinted();
|
||||||
|
#if MC_VER <= MC_1_21_4
|
||||||
|
this.needShade = firstQuad.isShade();
|
||||||
|
this.tintIndex = firstQuad.getTintIndex();
|
||||||
|
#else
|
||||||
|
this.needShade = firstQuad.shade();
|
||||||
|
this.tintIndex = firstQuad.tintIndex();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_17_1
|
||||||
this.baseColor = calculateColorFromTexture(
|
this.baseColor = calculateColorFromTexture(
|
||||||
#if MC_VER < MC_1_17_1 quads.get(0).sprite,
|
firstQuad.sprite,
|
||||||
#else quads.get(0).getSprite(), #endif
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
#elif MC_VER < MC_1_21_5
|
||||||
|
this.baseColor = calculateColorFromTexture(
|
||||||
|
firstQuad.getSprite(),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
#else
|
||||||
|
this.baseColor = calculateColorFromTexture(
|
||||||
|
firstQuad.sprite(),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -232,8 +255,7 @@ public class ClientBlockStateColorCache
|
|||||||
this.needPostTinting = false;
|
this.needPostTinting = false;
|
||||||
this.needShade = false;
|
this.needShade = false;
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
this.baseColor = this.getParticleIconColor();
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -242,8 +264,7 @@ public class ClientBlockStateColorCache
|
|||||||
this.needPostTinting = true;
|
this.needPostTinting = true;
|
||||||
this.needShade = false;
|
this.needShade = false;
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
this.baseColor = this.getParticleIconColor();
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isColorResolved = true;
|
this.isColorResolved = true;
|
||||||
@@ -253,6 +274,35 @@ public class ClientBlockStateColorCache
|
|||||||
RESOLVE_LOCK.unlock();
|
RESOLVE_LOCK.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); }
|
||||||
|
@Nullable
|
||||||
|
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
|
||||||
|
{
|
||||||
|
List<BakedQuad> quads = null;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||||
|
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
||||||
|
#else
|
||||||
|
List<BlockModelPart> blockModelPartList = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||||
|
getBlockModel(this.blockState).collectParts(RANDOM);
|
||||||
|
|
||||||
|
quads = new ArrayList<>();
|
||||||
|
if (blockModelPartList != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < blockModelPartList.size(); i++)
|
||||||
|
{
|
||||||
|
// if direction is null this will return the unculled quads
|
||||||
|
quads.addAll(blockModelPartList.get(i).getQuads(direction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return quads;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Perhaps make this not just use the first frame?
|
//TODO: Perhaps make this not just use the first frame?
|
||||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
||||||
{
|
{
|
||||||
@@ -383,6 +433,13 @@ public class ClientBlockStateColorCache
|
|||||||
return (bias + (scale * t)) >>> 16;
|
return (bias + (scale * t)) >>> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getParticleIconColor()
|
||||||
|
{
|
||||||
|
return calculateColorFromTexture(
|
||||||
|
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||||
|
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============//
|
//===============//
|
||||||
@@ -414,7 +471,7 @@ public class ClientBlockStateColorCache
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
tintColor = Minecraft.getInstance().getBlockColors()
|
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)
|
catch (UnsupportedOperationException e)
|
||||||
{
|
{
|
||||||
|
|||||||
+120
-39
@@ -20,13 +20,13 @@
|
|||||||
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.logging.DhLoggerBuilder;
|
||||||
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.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
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;
|
||||||
@@ -39,55 +39,54 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
||||||
{
|
{
|
||||||
/**
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
* This will only ever be null if there was an issue with {@link IClientLevelWrapper#getPlainsBiomeWrapper()}
|
|
||||||
* but {@link Nullable} is there just in case.
|
#if MC_VER < MC_1_18_2
|
||||||
*/
|
public static final ConcurrentMap<String, Biome> BIOME_BY_RESOURCE_STRING = new ConcurrentHashMap<>();
|
||||||
@Nullable
|
#else
|
||||||
private final Biome biome;
|
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)
|
//=============//
|
||||||
{
|
// constructor //
|
||||||
// try to get the wrapped biome
|
//=============//
|
||||||
Biome unwrappedBiome = null;
|
|
||||||
if (biomeWrapper.biome != null)
|
public TintWithoutLevelOverrider(@NotNull BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||||
{
|
{ this.biomeWrapper = biomeWrapper; }
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||||
{
|
{
|
||||||
if (this.biome != null)
|
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());
|
// default to "plains" for empty/invalid biomes
|
||||||
}
|
biomeString = "minecraft:plains";
|
||||||
else
|
|
||||||
{
|
|
||||||
// hopefully unneeded debug color
|
|
||||||
return ColorUtil.CYAN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
private static Biome unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
@@ -97,6 +96,88 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
|||||||
#endif
|
#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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
|
|||||||
+2
-2
@@ -278,14 +278,14 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
{
|
{
|
||||||
// is this block solid?
|
// is this block solid?
|
||||||
if (solidHeight == minInclusiveBuildHeight
|
if (solidHeight == minInclusiveBuildHeight
|
||||||
&& block.isSolid())
|
&& block.isSolid())
|
||||||
{
|
{
|
||||||
solidHeight = y;
|
solidHeight = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this block light blocking?
|
// is this block light blocking?
|
||||||
if (lightBlockingHeight == minInclusiveBuildHeight
|
if (lightBlockingHeight == minInclusiveBuildHeight
|
||||||
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
|
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
|
||||||
{
|
{
|
||||||
lightBlockingHeight = y;
|
lightBlockingHeight = y;
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-23
@@ -56,20 +56,20 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
||||||
|
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Based upon TinyConfig but is highly modified
|
* Based upon TinyConfig but is highly modified
|
||||||
* https://github.com/Minenash/TinyConfig
|
* https://github.com/Minenash/TinyConfig
|
||||||
*
|
*
|
||||||
|
* Note: floats don't work with this system, use doubles.
|
||||||
|
*
|
||||||
* Credits to Motschen
|
* Credits to Motschen
|
||||||
*
|
*
|
||||||
* @author coolGi
|
* @author coolGi
|
||||||
* @version 5-21-2022
|
* @version 5-21-2022
|
||||||
*/
|
*/
|
||||||
// FLOATS DONT WORK WITH THIS
|
|
||||||
|
|
||||||
/** This file is going to be removed sometime soon, please dont hook onto anything within this file until the new UI is compleated */
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ClassicConfigGUI
|
public class ClassicConfigGUI
|
||||||
{
|
{
|
||||||
@@ -178,7 +178,7 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(value.intValue());
|
((ConfigEntry) info).uiSetWithoutSaving(value != null ? value.intValue() : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ public class ClassicConfigGUI
|
|||||||
protected void init()
|
protected void init()
|
||||||
{
|
{
|
||||||
super.init();
|
super.init();
|
||||||
if (!reload)
|
if (!this.reload)
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ public class ClassicConfigGUI
|
|||||||
(buttonWidget) -> {
|
(buttonWidget) -> {
|
||||||
ChangelogScreen changelogScreen = new ChangelogScreen(this);
|
ChangelogScreen changelogScreen = new ChangelogScreen(this);
|
||||||
if (changelogScreen.usable)
|
if (changelogScreen.usable)
|
||||||
Objects.requireNonNull(minecraft).setScreen(changelogScreen);
|
Objects.requireNonNull(this.minecraft).setScreen(changelogScreen);
|
||||||
else
|
else
|
||||||
LOGGER.warn("Changelog was not able to open");
|
LOGGER.warn("Changelog was not able to open");
|
||||||
},
|
},
|
||||||
@@ -286,17 +286,17 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addBtn(MakeBtn(Translatable("distanthorizons.general.cancel"),
|
this.addBtn(MakeBtn(Translatable("distanthorizons.general.cancel"),
|
||||||
this.width / 2 - 154, this.height - 28,
|
this.width / 2 - 154, this.height - 28,
|
||||||
150, 20,
|
150, 20,
|
||||||
button ->
|
button ->
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
||||||
Objects.requireNonNull(minecraft).setScreen(parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
}));
|
}));
|
||||||
doneButton = addBtn(MakeBtn(Translatable("distanthorizons.general.done"), this.width / 2 + 4, this.height - 28, 150, 20, (button) -> {
|
this.doneButton = this.addBtn(MakeBtn(Translatable("distanthorizons.general.done"), this.width / 2 + 4, this.height - 28, 150, 20, (button) -> {
|
||||||
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
||||||
Objects.requireNonNull(minecraft).setScreen(parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.list = new ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, 32, 25);
|
this.list = new ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, 32, 25);
|
||||||
@@ -312,8 +312,8 @@ public class ClassicConfigGUI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (info.getCategory().matches(category) && info.getAppearance().showInGui)
|
if (info.getCategory().matches(this.category) && info.getAppearance().showInGui)
|
||||||
addMenuItem(info);
|
this.addMenuItem(info);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -336,7 +336,7 @@ public class ClassicConfigGUI
|
|||||||
private void addMenuItem(AbstractConfigType info)
|
private void addMenuItem(AbstractConfigType info)
|
||||||
{
|
{
|
||||||
initEntry(info, this.translationPrefix);
|
initEntry(info, this.translationPrefix);
|
||||||
Component name = Translatable(translationPrefix + info.getNameWCategory());
|
Component name = Translatable(this.translationPrefix + info.getNameWCategory());
|
||||||
|
|
||||||
|
|
||||||
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
|
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
|
||||||
@@ -345,7 +345,7 @@ public class ClassicConfigGUI
|
|||||||
((ConfigEntry) info).uiSetWithoutSaving(((ConfigEntry) info).getDefaultValue());
|
((ConfigEntry) info).uiSetWithoutSaving(((ConfigEntry) info).getDefaultValue());
|
||||||
((EntryInfo) info.guiValue).index = 0;
|
((EntryInfo) info.guiValue).index = 0;
|
||||||
this.reload = true;
|
this.reload = true;
|
||||||
Objects.requireNonNull(minecraft).setScreen(this);
|
Objects.requireNonNull(this.minecraft).setScreen(this);
|
||||||
};
|
};
|
||||||
int posX = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
|
int posX = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
|
||||||
int posZ = 0;
|
int posZ = 0;
|
||||||
@@ -359,17 +359,17 @@ public class ClassicConfigGUI
|
|||||||
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) ((EntryInfo) info.guiValue).widget;
|
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) ((EntryInfo) info.guiValue).widget;
|
||||||
if (info.getType().isEnum())
|
if (info.getType().isEnum())
|
||||||
{
|
{
|
||||||
widget.setValue(value -> Translatable(translationPrefix + "enum." + info.getType().getSimpleName() + "." + info.get().toString()));
|
widget.setValue(value -> Translatable(this.translationPrefix + "enum." + info.getType().getSimpleName() + "." + info.get().toString()));
|
||||||
}
|
}
|
||||||
this.list.addButton(MakeBtn(widget.getValue().apply(info.get()), this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen, 0, 150, 20, widget.getKey()), resetButton, null, name);
|
this.list.addButton(MakeBtn(widget.getValue().apply(info.get()), this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen, 0, 150, 20, widget.getKey()), resetButton, null, name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (((EntryInfo) info.guiValue).widget != null)
|
else if (((EntryInfo) info.guiValue).widget != null)
|
||||||
{
|
{
|
||||||
EditBox widget = new EditBox(font, this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen + 2, 0, 150 - 4, 20, null);
|
EditBox widget = new EditBox(this.font, this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen + 2, 0, 150 - 4, 20, Translatable(""));
|
||||||
widget.setMaxLength(150);
|
widget.setMaxLength(150);
|
||||||
widget.insertText(String.valueOf(info.get()));
|
widget.insertText(String.valueOf(info.get()));
|
||||||
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) ((EntryInfo) info.guiValue).widget).apply(widget, doneButton);
|
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) ((EntryInfo) info.guiValue).widget).apply(widget, this.doneButton);
|
||||||
widget.setFilter(processor);
|
widget.setFilter(processor);
|
||||||
this.list.addButton(widget, resetButton, null, name);
|
this.list.addButton(widget, resetButton, null, name);
|
||||||
return;
|
return;
|
||||||
@@ -379,7 +379,7 @@ public class ClassicConfigGUI
|
|||||||
{
|
{
|
||||||
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
|
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
|
||||||
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
||||||
Objects.requireNonNull(minecraft).setScreen(ClassicConfigGUI.getScreen(this.configBase, this, ((ConfigCategory) info).getDestination()));
|
Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this.configBase, this, ((ConfigCategory) info).getDestination()));
|
||||||
}));
|
}));
|
||||||
this.list.addButton(widget, null, null, null);
|
this.list.addButton(widget, null, null, null);
|
||||||
return;
|
return;
|
||||||
@@ -420,16 +420,34 @@ public class ClassicConfigGUI
|
|||||||
#endif
|
#endif
|
||||||
this.list.render(matrices, mouseX, mouseY, delta); // Render buttons
|
this.list.render(matrices, mouseX, mouseY, delta); // Render buttons
|
||||||
|
|
||||||
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
|
// Render title
|
||||||
|
this.DhDrawCenteredString(matrices, this.font, this.title, this.width / 2, 15,
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
0xFFFFFF // RGB white
|
||||||
|
#else
|
||||||
|
0xFFFFFFFF // ARGB white
|
||||||
|
#endif);
|
||||||
|
|
||||||
if (this.configBase.modID.equals("distanthorizons"))
|
if (this.configBase.modID.equals("distanthorizons"))
|
||||||
{
|
{
|
||||||
// Display version
|
// Display version
|
||||||
DhDrawString(matrices, font, TextOrLiteral(ModInfo.VERSION), 2, height - 10, 0xAAAAAA);
|
this.DhDrawString(matrices, this.font, TextOrLiteral(ModInfo.VERSION), 2, this.height - 10,
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
0xAAAAAA // RGB white
|
||||||
|
#else
|
||||||
|
0xFFAAAAAA // ARGB white
|
||||||
|
#endif);
|
||||||
|
|
||||||
// If the update is pending, display this message to inform the user that it will apply when the game restarts
|
// If the update is pending, display this message to inform the user that it will apply when the game restarts
|
||||||
if (SelfUpdater.deleteOldJarOnJvmShutdown)
|
if (SelfUpdater.deleteOldJarOnJvmShutdown)
|
||||||
DhDrawString(matrices, font, Translatable(configBase.modID + ".updater.waitingForClose"), 4, height - 38, 0xFFFFFF);
|
{
|
||||||
|
this.DhDrawString(matrices, this.font, Translatable(this.configBase.modID + ".updater.waitingForClose"), 4, this.height - 38,
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
0xFFFFFF // RGB white
|
||||||
|
#else
|
||||||
|
0xFFFFFFFF // ARGB white
|
||||||
|
#endif);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -659,8 +677,10 @@ public class ClassicConfigGUI
|
|||||||
if (text != null && (!text.getString().contains("spacer") || button != null))
|
if (text != null && (!text.getString().contains("spacer") || button != null))
|
||||||
#if MC_VER < MC_1_20_1
|
#if MC_VER < MC_1_20_1
|
||||||
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
|
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF);
|
||||||
#else
|
#else
|
||||||
matrices.drawString(textRenderer, text, 12, y + 5, 0xFFFFFF);
|
matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFFFF);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,27 @@ public class DhScreen extends Screen
|
|||||||
{
|
{
|
||||||
renderTooltip(guiStack, comp, x, y);
|
renderTooltip(guiStack, comp, x, y);
|
||||||
}
|
}
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||||
|
{
|
||||||
|
guiStack.drawCenteredString(font, text, x, y, color);
|
||||||
|
}
|
||||||
|
protected void DhDrawString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||||
|
{
|
||||||
|
guiStack.drawString(font, text, x, y, color);
|
||||||
|
}
|
||||||
|
//protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
||||||
|
//{
|
||||||
|
// guiStack.renderTooltip(font, text, x, y);
|
||||||
|
//}
|
||||||
|
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
|
||||||
|
{
|
||||||
|
guiStack.renderComponentTooltip(font, comp, x, y);
|
||||||
|
}
|
||||||
|
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
|
||||||
|
{
|
||||||
|
guiStack.renderTooltip(font, text, x, y);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||||
{
|
{
|
||||||
@@ -61,17 +82,20 @@ public class DhScreen extends Screen
|
|||||||
{
|
{
|
||||||
guiStack.drawString(font, text, x, y, color);
|
guiStack.drawString(font, text, x, y, color);
|
||||||
}
|
}
|
||||||
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
//protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
||||||
{
|
//{
|
||||||
guiStack.renderTooltip(font, text, x, y);
|
// //guiStack.renderTooltip(font, text, x, y);
|
||||||
}
|
//}
|
||||||
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
|
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
|
||||||
{
|
{
|
||||||
guiStack.renderComponentTooltip(font, comp, x, y);
|
guiStack.setComponentTooltipForNextFrame(font, comp, x, y);
|
||||||
}
|
}
|
||||||
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
|
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
|
||||||
{
|
{
|
||||||
guiStack.renderTooltip(font, text, x, y);
|
guiStack.setTooltipForNextFrame(font, text, x, y);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-2
@@ -39,9 +39,13 @@ import net.minecraft.client.renderer.GameRenderer;
|
|||||||
#elif MC_VER < MC_1_20_2
|
#elif MC_VER < MC_1_20_2
|
||||||
import net.minecraft.client.gui.components.ImageButton;
|
import net.minecraft.client.gui.components.ImageButton;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
#else
|
#else
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.RenderPipelines;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,9 +176,15 @@ public class TexturedButtonWidget extends Button
|
|||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
matrices.blitSprite(SPRITES.get(this.active, this.isHoveredOrFocused()), this.getX(), this.getY(), this.getWidth(), this.getHeight());
|
matrices.blitSprite(SPRITES.get(this.active, this.isHoveredOrFocused()), this.getX(), this.getY(), this.getWidth(), this.getHeight());
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
matrices.blitSprite(
|
||||||
|
RenderType::guiTextured,
|
||||||
|
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||||
|
this.getX(), this.getY(),
|
||||||
|
this.getWidth(), this.getHeight());
|
||||||
#else
|
#else
|
||||||
matrices.blitSprite(
|
matrices.blitSprite(
|
||||||
RenderType::guiTextured,
|
RenderPipelines.GUI_TEXTURED,
|
||||||
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||||
this.getX(), this.getY(),
|
this.getX(), this.getY(),
|
||||||
this.getWidth(), this.getHeight());
|
this.getWidth(), this.getHeight());
|
||||||
@@ -196,7 +206,7 @@ public class TexturedButtonWidget extends Button
|
|||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
matrices.blit(this.textureResourceLocation, this.getX(), this.getY(), this.u, this.v + (this.hoveredVOffset * i), this.width, this.height, this.textureWidth, this.textureHeight);
|
matrices.blit(this.textureResourceLocation, this.getX(), this.getY(), this.u, this.v + (this.hoveredVOffset * i), this.width, this.height, this.textureWidth, this.textureHeight);
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
matrices.blit(
|
matrices.blit(
|
||||||
RenderType::guiTextured,
|
RenderType::guiTextured,
|
||||||
this.textureResourceLocation,
|
this.textureResourceLocation,
|
||||||
@@ -204,6 +214,14 @@ public class TexturedButtonWidget extends Button
|
|||||||
this.u, this.v + (this.hoveredVOffset * i),
|
this.u, this.v + (this.hoveredVOffset * i),
|
||||||
this.width, this.height,
|
this.width, this.height,
|
||||||
this.textureWidth, this.textureHeight);
|
this.textureWidth, this.textureHeight);
|
||||||
|
#else
|
||||||
|
matrices.blit(
|
||||||
|
RenderPipelines.GUI_TEXTURED,
|
||||||
|
this.textureResourceLocation,
|
||||||
|
this.getX(), this.getY(),
|
||||||
|
this.u, this.v + (this.hoveredVOffset * i),
|
||||||
|
this.width, this.height,
|
||||||
|
this.textureWidth, this.textureHeight);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-6
@@ -169,8 +169,10 @@ public class UpdateModScreen extends DhScreen
|
|||||||
{
|
{
|
||||||
#if MC_VER < MC_1_20_2
|
#if MC_VER < MC_1_20_2
|
||||||
this.renderBackground(matrices); // Render background
|
this.renderBackground(matrices); // Render background
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||||
|
#else
|
||||||
|
// background blur is already being rendered, rendering again causes the game to crash
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: add the tooltips for the buttons
|
// TODO: add the tooltips for the buttons
|
||||||
@@ -178,16 +180,30 @@ public class UpdateModScreen extends DhScreen
|
|||||||
// TODO: Add tooltips
|
// TODO: Add tooltips
|
||||||
|
|
||||||
// Render the text's
|
// Render the text's
|
||||||
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text1"), this.width / 2, this.height / 2 - 35, 0xFFFFFF);
|
this.DhDrawCenteredString(matrices, this.font,
|
||||||
DhDrawCenteredString(matrices, this.font,
|
Translatable(ModInfo.ID + ".updater.text1"),
|
||||||
Translatable(ModInfo.ID + ".updater.text2", currentVer, nextVer),
|
this.width / 2, this.height / 2 - 35,
|
||||||
this.width / 2, this.height / 2 - 20, 0x52FD52);
|
#if MC_VER < MC_1_21_6
|
||||||
|
0xFFFFFF // RGB
|
||||||
|
#else
|
||||||
|
0xFFFFFFFF // ARGB
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
this.DhDrawCenteredString(matrices, this.font,
|
||||||
|
Translatable(ModInfo.ID + ".updater.text2", this.currentVer, this.nextVer),
|
||||||
|
this.width / 2, this.height / 2 - 20,
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
0x52FD52 // RGB
|
||||||
|
#else
|
||||||
|
0xFF52FD52 // ARGB
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClose()
|
public void onClose()
|
||||||
{
|
{
|
||||||
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+15
-3
@@ -214,17 +214,29 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
@Override
|
@Override
|
||||||
public DhBlockPos getPlayerBlockPos()
|
public DhBlockPos getPlayerBlockPos()
|
||||||
{
|
{
|
||||||
BlockPos playerPos = this.getPlayer().blockPosition();
|
LocalPlayer player = this.getPlayer();
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
return new DhBlockPos(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos playerPos = player.blockPosition();
|
||||||
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DhChunkPos getPlayerChunkPos()
|
public DhChunkPos getPlayerChunkPos()
|
||||||
{
|
{
|
||||||
|
LocalPlayer player = this.getPlayer();
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
return new DhChunkPos(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
ChunkPos playerPos = new ChunkPos(this.getPlayer().blockPosition());
|
ChunkPos playerPos = new ChunkPos(player.blockPosition());
|
||||||
#else
|
#else
|
||||||
ChunkPos playerPos = this.getPlayer().chunkPosition();
|
ChunkPos playerPos = player.chunkPosition();
|
||||||
#endif
|
#endif
|
||||||
return new DhChunkPos(playerPos.x, playerPos.z);
|
return new DhChunkPos(playerPos.x, playerPos.z);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-3
@@ -19,7 +19,11 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#elif MC_VER >= MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.opengl.GlStateManager;
|
||||||
|
#endif
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
@@ -148,7 +152,10 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
public void glBlendFunc(int sfactor, int dfactor)
|
public void glBlendFunc(int sfactor, int dfactor)
|
||||||
{
|
{
|
||||||
GL32.glBlendFunc(sfactor, dfactor);
|
GL32.glBlendFunc(sfactor, dfactor);
|
||||||
GlStateManager._blendFunc(sfactor, dfactor);
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
GlStateManager._blendFunc(sfactor, dfactor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/** @see GL32#glBlendFuncSeparate */
|
/** @see GL32#glBlendFuncSeparate */
|
||||||
@Override
|
@Override
|
||||||
@@ -180,7 +187,15 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
/** @see GL32#glDeleteBuffers(int) */
|
/** @see GL32#glDeleteBuffers(int) */
|
||||||
@Override
|
@Override
|
||||||
public void glDeleteBuffers(int buffer)
|
public void glDeleteBuffers(int buffer)
|
||||||
{ GlStateManager._glDeleteBuffers(buffer); }
|
{
|
||||||
|
GL32.glDeleteBuffers(buffer);
|
||||||
|
|
||||||
|
// MC's implementation has a bug where it will throw:
|
||||||
|
// GL_INVALID_OPERATION in glBufferData(immutable)
|
||||||
|
// when attempting to delete Storage Buffers
|
||||||
|
// So we need to manually delete the buffers ourselves
|
||||||
|
//GlStateManager._glDeleteBuffers(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// culling //
|
// culling //
|
||||||
@@ -218,7 +233,7 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
GlStateManager._activeTexture(textureId);
|
GlStateManager._activeTexture(textureId);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE); }
|
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always binds to {@link GL32#GL_TEXTURE_2D}
|
* Always binds to {@link GL32#GL_TEXTURE_2D}
|
||||||
|
|||||||
+143
-11
@@ -33,9 +33,12 @@ 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.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
import net.minecraft.client.renderer.FogRenderer;
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
@@ -43,8 +46,6 @@ import org.joml.Matrix4f;
|
|||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
#if MC_VER >= MC_1_20_2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
@@ -71,6 +72,9 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton that contains everything
|
* A singleton that contains everything
|
||||||
@@ -102,7 +106,19 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
*/
|
*/
|
||||||
public int finalLevelFrameBufferId = -1;
|
public int finalLevelFrameBufferId = -1;
|
||||||
|
|
||||||
|
public boolean colorTextureCastFailLogged = false;
|
||||||
|
public boolean depthTextureCastFailLogged = false;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
#else
|
||||||
|
private static FogRenderer mcFogRenderer = null;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3f getLookAtVector()
|
public Vec3f getLookAtVector()
|
||||||
@@ -115,11 +131,22 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
/** Unless you really need to know if the player is blind, use {@link MinecraftRenderWrapper#isFogStateSpecial()}/{@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */
|
/** Unless you really need to know if the player is blind, use {@link MinecraftRenderWrapper#isFogStateSpecial()}/{@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */
|
||||||
public boolean playerHasBlindingEffect()
|
public boolean playerHasBlindingEffect()
|
||||||
{
|
{
|
||||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
if (MC.player == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (MC.player.getActiveEffectsMap() == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -152,7 +179,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
Math.max(0f, Math.min(colorValues[2], 1f)), // b
|
Math.max(0f, Math.min(colorValues[2], 1f)), // b
|
||||||
Math.max(0f, Math.min(colorValues[3], 1f)) // a
|
Math.max(0f, Math.min(colorValues[3], 1f)) // a
|
||||||
);
|
);
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
Vector4f colorValues = FogRenderer.computeFogColor(MC.gameRenderer.getMainCamera(), partialTicks, MC.level, 1, MC.gameRenderer.getDarkenWorldAmount(partialTicks));
|
Vector4f colorValues = FogRenderer.computeFogColor(MC.gameRenderer.getMainCamera(), partialTicks, MC.level, 1, MC.gameRenderer.getDarkenWorldAmount(partialTicks));
|
||||||
return new Color(
|
return new Color(
|
||||||
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
||||||
@@ -160,6 +187,31 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||||
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (mcFogRenderer == null)
|
||||||
|
{
|
||||||
|
mcFogRenderer = new FogRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MC.level == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return Color.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isFoggy =
|
||||||
|
MC.level.effects().isFoggyAt(
|
||||||
|
MC.gameRenderer.getMainCamera().getBlockPosition().getX(),
|
||||||
|
MC.gameRenderer.getMainCamera().getBlockPosition().getZ())
|
||||||
|
|| MC.gui.getBossOverlay().shouldCreateWorldFog();
|
||||||
|
Vector4f colorValues = mcFogRenderer.setupFog(MC.gameRenderer.getMainCamera(), MC.options.getEffectiveRenderDistance(), isFoggy, MC.deltaTracker, MC.gameRenderer.getDarkenWorldAmount(MC.deltaTracker.getGameTimeDeltaPartialTick(true)), MC.level);
|
||||||
|
return new Color(
|
||||||
|
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
||||||
|
Math.max(0f, Math.min(colorValues.y, 1f)), // g
|
||||||
|
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||||
|
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// getSpecialFogColor() is the same as getFogColor()
|
// getSpecialFogColor() is the same as getFogColor()
|
||||||
@@ -250,6 +302,26 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
|
|
||||||
private RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
private RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mcRendersToFrameBuffer()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean runningLegacyOpenGL()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_16_5
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBuffer()
|
public int getTargetFrameBuffer()
|
||||||
{
|
{
|
||||||
@@ -259,27 +331,87 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
return this.finalLevelFrameBufferId;
|
return this.finalLevelFrameBufferId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
return this.getRenderTarget().frameBufferId;
|
return this.getRenderTarget().frameBufferId;
|
||||||
|
#else
|
||||||
|
// MC renders to a texture and then directly to the default FBO now
|
||||||
|
// we need to draw to their texture instead of the FBO
|
||||||
|
return 0; // 0 is the ID for the default frame buffer
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearTargetFrameBuffer() { this.finalLevelFrameBufferId = -1; }
|
public void clearTargetFrameBuffer() { this.finalLevelFrameBufferId = -1; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDepthTextureId() { return this.getRenderTarget().getDepthTextureId(); }
|
public int getDepthTextureId()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return this.getRenderTarget().getDepthTextureId();
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GlTexture glTexture = (GlTexture) this.getRenderTarget().getDepthTexture();
|
||||||
|
if (glTexture == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glTexture.glId();
|
||||||
|
}
|
||||||
|
catch (ClassCastException e)
|
||||||
|
{
|
||||||
|
// only log this error once per session
|
||||||
|
if (!this.depthTextureCastFailLogged)
|
||||||
|
{
|
||||||
|
this.depthTextureCastFailLogged = true;
|
||||||
|
LOGGER.error("Unable to cast render Target depth texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public int getColorTextureId() { return this.getRenderTarget().getColorTextureId(); }
|
public int getColorTextureId()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return this.getRenderTarget().getColorTextureId();
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GlTexture glTexture = (GlTexture) this.getRenderTarget().getColorTexture();
|
||||||
|
if (glTexture == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glTexture.glId();
|
||||||
|
}
|
||||||
|
catch (ClassCastException e)
|
||||||
|
{
|
||||||
|
// only log this error once per session
|
||||||
|
if (!this.colorTextureCastFailLogged)
|
||||||
|
{
|
||||||
|
this.colorTextureCastFailLogged = true;
|
||||||
|
LOGGER.error("Unable to cast render Target color texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportWidth()
|
public int getTargetFrameBufferViewportWidth()
|
||||||
{
|
{
|
||||||
return getRenderTarget().viewWidth;
|
return this.getRenderTarget().viewWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportHeight()
|
public int getTargetFrameBufferViewportHeight()
|
||||||
{
|
{
|
||||||
return getRenderTarget().viewHeight;
|
return this.getRenderTarget().viewHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+18
-1
@@ -21,8 +21,10 @@ package com.seibel.distanthorizons.common.wrappers.misc;
|
|||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -30,6 +32,7 @@ import java.nio.ByteBuffer;
|
|||||||
public class LightMapWrapper implements ILightMapWrapper
|
public class LightMapWrapper implements ILightMapWrapper
|
||||||
{
|
{
|
||||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||||
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
private int textureId = 0;
|
private int textureId = 0;
|
||||||
|
|
||||||
@@ -49,6 +52,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
|
|
||||||
public void uploadLightmap(NativeImage image)
|
public void uploadLightmap(NativeImage image)
|
||||||
{
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
int currentTexture = GLMC.getActiveTexture();
|
int currentTexture = GLMC.getActiveTexture();
|
||||||
if (this.textureId == 0)
|
if (this.textureId == 0)
|
||||||
{
|
{
|
||||||
@@ -59,14 +63,27 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
GLMC.glBindTexture(this.textureId);
|
GLMC.glBindTexture(this.textureId);
|
||||||
}
|
}
|
||||||
image.upload(0, 0, 0, false);
|
image.upload(0, 0, 0, false);
|
||||||
GLMC.glBindTexture(currentTexture);
|
|
||||||
|
// getActiveTexture() may return textures that aren't valid and attempting to bind them will
|
||||||
|
// throw a GL error in MC 1.21.1
|
||||||
|
if (GL32.glIsTexture(currentTexture))
|
||||||
|
{
|
||||||
|
GLMC.glBindTexture(currentTexture);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
private void createLightmap(NativeImage image)
|
private void createLightmap(NativeImage image)
|
||||||
{
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
this.textureId = GLMC.glGenTextures();
|
this.textureId = GLMC.glGenTextures();
|
||||||
GLMC.glBindTexture(this.textureId);
|
GLMC.glBindTexture(this.textureId);
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
||||||
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||||
|
#else
|
||||||
|
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLightmapId(int minecraftLightmapTetxureId)
|
public void setLightmapId(int minecraftLightmapTetxureId)
|
||||||
|
|||||||
+11
-2
@@ -54,8 +54,10 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
|||||||
{
|
{
|
||||||
#if MC_VER < MC_1_20_1
|
#if MC_VER < MC_1_20_1
|
||||||
level = this.getServerPlayer().getLevel();
|
level = this.getServerPlayer().getLevel();
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
level = this.getServerPlayer().serverLevel();
|
level = this.getServerPlayer().serverLevel();
|
||||||
|
#else
|
||||||
|
level = this.getServerPlayer().level();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +72,14 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewDistance() { return this.getServerPlayer().server.getPlayerList().getViewDistance(); }
|
public int getViewDistance()
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
return this.getServerPlayer().server.getPlayerList().getViewDistance();
|
||||||
|
#else
|
||||||
|
return this.getServerPlayer().getServer().getPlayerList().getViewDistance();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SocketAddress getRemoteAddress()
|
public SocketAddress getRemoteAddress()
|
||||||
|
|||||||
+49
-8
@@ -25,7 +25,6 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkSource;
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -33,7 +32,12 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
@@ -42,6 +46,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
#else
|
#else
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
#endif
|
#endif
|
||||||
@@ -49,7 +54,12 @@ import com.seibel.distanthorizons.core.util.ColorUtil;
|
|||||||
public class ClientLevelWrapper implements IClientLevelWrapper
|
public class ClientLevelWrapper implements IClientLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
||||||
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); // TODO can leak
|
/**
|
||||||
|
* weak references are to prevent rare issues
|
||||||
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
|
* and/or for servers were the level object isn't consistent
|
||||||
|
*/
|
||||||
|
private static final Map<ClientLevel, WeakReference<ClientLevelWrapper>> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
||||||
|
|
||||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||||
@@ -57,6 +67,10 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
private final ClientLevel level;
|
private final ClientLevel level;
|
||||||
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockCache = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/** cached method reference to reduce GC overhead */
|
||||||
|
private final Function<BlockState, ClientBlockStateColorCache> cachedBlockColorCacheFunction = (blockState) -> this.createBlockColorCache(blockState);
|
||||||
|
|
||||||
|
|
||||||
private BlockStateWrapper dirtBlockWrapper;
|
private BlockStateWrapper dirtBlockWrapper;
|
||||||
private BiomeWrapper plainsBiomeWrapper;
|
private BiomeWrapper plainsBiomeWrapper;
|
||||||
@Deprecated // TODO circular references are bad
|
@Deprecated // TODO circular references are bad
|
||||||
@@ -72,9 +86,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============//
|
//==================//
|
||||||
// wrapper logic //
|
// instance methods //
|
||||||
//===============//
|
//==================//
|
||||||
|
|
||||||
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
|
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
|
||||||
|
|
||||||
@@ -96,7 +110,31 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new);
|
|
||||||
|
WeakReference<ClientLevelWrapper> levelRef = LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.get(level);
|
||||||
|
if (levelRef != null)
|
||||||
|
{
|
||||||
|
ClientLevelWrapper levelWrapper = levelRef.get();
|
||||||
|
if (levelWrapper != null)
|
||||||
|
{
|
||||||
|
return levelWrapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.compute(level, (newLevel, newLevelRef) ->
|
||||||
|
{
|
||||||
|
if (newLevelRef != null)
|
||||||
|
{
|
||||||
|
ClientLevelWrapper oldLevelWrapper = newLevelRef.get();
|
||||||
|
if (oldLevelWrapper != null)
|
||||||
|
{
|
||||||
|
return newLevelRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WeakReference<>(new ClientLevelWrapper(newLevel));
|
||||||
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -141,10 +179,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
{
|
{
|
||||||
ClientBlockStateColorCache blockColorCache = this.blockCache.computeIfAbsent(
|
ClientBlockStateColorCache blockColorCache = this.blockCache.computeIfAbsent(
|
||||||
((BlockStateWrapper) blockWrapper).blockState,
|
((BlockStateWrapper) blockWrapper).blockState,
|
||||||
(block) -> new ClientBlockStateColorCache(block, this));
|
this.cachedBlockColorCacheFunction);
|
||||||
|
|
||||||
return blockColorCache.getColor((BiomeWrapper) biome, pos);
|
return blockColorCache.getColor((BiomeWrapper) biome, pos);
|
||||||
}
|
}
|
||||||
|
/** used by {@link ClientLevelWrapper#cachedBlockColorCacheFunction} */
|
||||||
|
private ClientBlockStateColorCache createBlockColorCache(BlockState block) { return new ClientBlockStateColorCache(block, this); }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDirtBlockColor()
|
public int getDirtBlockColor()
|
||||||
@@ -265,7 +306,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
@Override
|
@Override
|
||||||
public void onUnload()
|
public void onUnload()
|
||||||
{
|
{
|
||||||
LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level);
|
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.remove(this.level);
|
||||||
this.parentDhLevel = null;
|
this.parentDhLevel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-33
@@ -28,72 +28,80 @@ import net.minecraft.world.level.dimension.DimensionType;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author James Seibel
|
* @author James Seibel
|
||||||
* @version 2022-9-16
|
|
||||||
*/
|
*/
|
||||||
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
||||||
{
|
{
|
||||||
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
|
private static final ConcurrentMap<String, DimensionTypeWrapper> DIMENSION_WRAPPER_BY_NAME = new ConcurrentHashMap<>();
|
||||||
private final DimensionType dimensionType;
|
private final DimensionType dimensionType;
|
||||||
|
|
||||||
public DimensionTypeWrapper(DimensionType dimensionType)
|
|
||||||
{
|
|
||||||
this.dimensionType = dimensionType;
|
//=============//
|
||||||
}
|
// Constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public DimensionTypeWrapper(DimensionType dimensionType) { this.dimensionType = dimensionType; }
|
||||||
|
|
||||||
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
||||||
{
|
{
|
||||||
//first we check if the biome has already been wrapped
|
String dimName = getName(dimensionType);
|
||||||
if (dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
|
|
||||||
|
// check if the dimension has already been wrapped
|
||||||
|
if (DIMENSION_WRAPPER_BY_NAME.containsKey(dimName)
|
||||||
|
&& DIMENSION_WRAPPER_BY_NAME.get(dimName) != null)
|
||||||
{
|
{
|
||||||
return dimensionTypeWrapperMap.get(dimensionType);
|
return DIMENSION_WRAPPER_BY_NAME.get(dimName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//if it hasn't been created yet, we create it and save it in the map
|
// create the missing wrapper
|
||||||
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
||||||
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
|
DIMENSION_WRAPPER_BY_NAME.put(dimName, dimensionTypeWrapper);
|
||||||
|
|
||||||
//we return the newly created wrapper
|
|
||||||
return dimensionTypeWrapper;
|
return dimensionTypeWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearMap()
|
public static void clearMap() { DIMENSION_WRAPPER_BY_NAME.clear(); }
|
||||||
{
|
|
||||||
dimensionTypeWrapperMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String getDimensionName()
|
|
||||||
|
//=================//
|
||||||
|
// wrapper methods //
|
||||||
|
//=================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return getName(this.dimensionType); }
|
||||||
|
public static String getName(DimensionType dimensionType)
|
||||||
{
|
{
|
||||||
#if MC_VER <= MC_1_16_5
|
#if MC_VER <= MC_1_16_5
|
||||||
// effectsLocation() is marked as client only, so using the backing field directly
|
// effectsLocation() is marked as client only, so using the backing field directly
|
||||||
return dimensionType.effectsLocation.getPath();
|
return dimensionType.effectsLocation.getPath();
|
||||||
#else
|
#else
|
||||||
return this.dimensionType.effectsLocation().getPath();
|
return dimensionType.effectsLocation().getPath();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasCeiling()
|
public boolean hasCeiling() { return this.dimensionType.hasCeiling(); }
|
||||||
{
|
|
||||||
return this.dimensionType.hasCeiling();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasSkyLight()
|
public boolean hasSkyLight() { return this.dimensionType.hasSkyLight(); }
|
||||||
{
|
|
||||||
return this.dimensionType.hasSkyLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getWrappedMcObject()
|
public Object getWrappedMcObject() { return this.dimensionType; }
|
||||||
{
|
|
||||||
return this.dimensionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// there's definitely a better way of doing this, but it should work well enough for now
|
// there's definitely a better way of doing this, but it should work well enough for now
|
||||||
@Override
|
@Override
|
||||||
public boolean isTheEnd() { return this.getDimensionName().equalsIgnoreCase("the_end"); }
|
public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCoordinateScale() { return this.dimensionType.coordinateScale(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
@@ -105,9 +113,10 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DimensionTypeWrapper other = (DimensionTypeWrapper) obj;
|
DimensionTypeWrapper other = (DimensionTypeWrapper) obj;
|
||||||
return other.getDimensionName().equals(this.getDimensionName());
|
return other.getName().equals(this.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-10
@@ -20,6 +20,10 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.world;
|
package com.seibel.distanthorizons.common.wrappers.world;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||||
@@ -38,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;
|
||||||
|
|
||||||
@@ -57,7 +62,11 @@ import org.apache.logging.log4j.Logger;
|
|||||||
public class ServerLevelWrapper implements IServerLevelWrapper
|
public class ServerLevelWrapper implements IServerLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper> LEVEL_WRAPPER_BY_SERVER_LEVEL = new ConcurrentHashMap<>();
|
/**
|
||||||
|
* weak references are to prevent rare issues
|
||||||
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
|
*/
|
||||||
|
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
|
|
||||||
private final ServerLevel level;
|
private final ServerLevel level;
|
||||||
@Deprecated // TODO circular references are bad
|
@Deprecated // TODO circular references are bad
|
||||||
@@ -70,15 +79,29 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
public static ServerLevelWrapper getWrapper(ServerLevel level)
|
public static ServerLevelWrapper getWrapper(ServerLevel level)
|
||||||
{ return LEVEL_WRAPPER_BY_SERVER_LEVEL.computeIfAbsent(level, ServerLevelWrapper::new); }
|
{
|
||||||
|
return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) ->
|
||||||
|
{
|
||||||
|
if (levelRef != null)
|
||||||
|
{
|
||||||
|
ServerLevelWrapper oldLevelWrapper = levelRef.get();
|
||||||
|
if (oldLevelWrapper != null)
|
||||||
|
{
|
||||||
|
return levelRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WeakReference<>(new ServerLevelWrapper(newLevel));
|
||||||
|
}).get();
|
||||||
|
}
|
||||||
|
|
||||||
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========//
|
//==================//
|
||||||
// methods //
|
// instance methods //
|
||||||
//=========//
|
//==================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getMcSaveFolder()
|
public File getMcSaveFolder()
|
||||||
@@ -93,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +204,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
public ServerLevel getWrappedMcObject() { return this.level; }
|
public ServerLevel getWrappedMcObject() { return this.level; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); }
|
public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+50
-31
@@ -113,7 +113,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
||||||
() -> Config.Common.Logging.logWorldGenLoadEvent.get());
|
() -> Config.Common.Logging.logWorldGenLoadEvent.get());
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
|
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
|
||||||
|
#else
|
||||||
|
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING);
|
||||||
|
#endif
|
||||||
|
|
||||||
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
|
||||||
@@ -125,7 +129,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
* pull chunks using their async method), or if there
|
* pull chunks using their async method), or if there
|
||||||
* was an issue with the sync pulling method.
|
* was an issue with the sync pulling method.
|
||||||
*/
|
*/
|
||||||
private boolean pullExistingChunkAsync = false;
|
private boolean pullExistingChunkUsingMcAsyncMethod = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -241,19 +245,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
|
|
||||||
if (MOD_CHECKER.isModLoaded("c2me"))
|
if (MOD_CHECKER.isModLoaded("c2me"))
|
||||||
{
|
{
|
||||||
EVENT_LOGGER.info("C2ME detected: DH's pre-existing chunk accessing will use async methods handled by C2ME.");
|
EVENT_LOGGER.info("C2ME detected: DH's pre-existing chunk accessing will use methods handled by C2ME.");
|
||||||
this.pullExistingChunkAsync = true;
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//IOWorker ioWorker = level.getChunkSource().chunkMap.worker;
|
|
||||||
//
|
|
||||||
// #if MC_VER <= MC_1_18_2
|
|
||||||
// return CompletableFuture.completedFuture(ioWorker.load(chunkPos));
|
|
||||||
// #else
|
|
||||||
//
|
|
||||||
//// storage will be null if C2ME is installed
|
|
||||||
//if (ioWorker.storage != null)
|
|
||||||
|
|
||||||
this.params = new GlobalParameters(serverlevel);
|
this.params = new GlobalParameters(serverlevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +337,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
// world generation //
|
// world generation //
|
||||||
//==================//
|
//==================//
|
||||||
|
|
||||||
|
// TODO this is already being run on a generator thread,
|
||||||
|
// why are we passing in an executor?
|
||||||
/** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */
|
/** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */
|
||||||
public CompletableFuture<Void> generateLodFromListAsync(GenerationEvent genEvent, Executor executor) throws RejectedExecutionException, InterruptedException
|
public CompletableFuture<Void> generateLodFromListAsync(GenerationEvent genEvent, Executor executor) throws RejectedExecutionException, InterruptedException
|
||||||
{
|
{
|
||||||
@@ -385,10 +382,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
.map((chunkPos) -> this.createEmptyOrPreExistingChunkAsync(chunkPos.x, chunkPos.z, chunkSkyLightingByDhPos, chunkBlockLightingByDhPos, generatedChunkByDhPos))
|
.map((chunkPos) -> this.createEmptyOrPreExistingChunkAsync(chunkPos.x, chunkPos.z, chunkSkyLightingByDhPos, chunkBlockLightingByDhPos, generatedChunkByDhPos))
|
||||||
.toArray(CompletableFuture[]::new);
|
.toArray(CompletableFuture[]::new);
|
||||||
|
|
||||||
|
// join to prevent an issue where DH queues too many tasks or something(?)
|
||||||
|
// also allows file IO to run in parallel so no one thread is waiting on disk IO (this is only an issue when C2ME is present)
|
||||||
|
CompletableFuture.allOf(readFutures).join();
|
||||||
|
|
||||||
// future chain for generation
|
// future chain for generation
|
||||||
return CompletableFuture.allOf(readFutures)
|
return CompletableFuture.runAsync(() ->
|
||||||
.thenRunAsync(() ->
|
|
||||||
{
|
{
|
||||||
// offset 1 chunk in both X and Z direction so we can generate an even number of chunks wide
|
// offset 1 chunk in both X and Z direction so we can generate an even number of chunks wide
|
||||||
// while still submitting an odd number width to MC's internal generators
|
// while still submitting an odd number width to MC's internal generators
|
||||||
@@ -424,7 +423,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
|
|
||||||
ChunkAccess centerChunk = regionChunks.stream()
|
ChunkAccess centerChunk = regionChunks.stream()
|
||||||
.filter((chunk) -> chunk.getPos().x == centerX && chunk.getPos().z == centerZ)
|
.filter((chunk) -> chunk.getPos().x == centerX && chunk.getPos().z == centerZ)
|
||||||
.findFirst().get();
|
.findFirst()
|
||||||
|
.orElseGet(() -> regionChunks.getFirst());
|
||||||
|
|
||||||
genEvent.refreshTimeout();
|
genEvent.refreshTimeout();
|
||||||
DhLitWorldGenRegion region = new DhLitWorldGenRegion(
|
DhLitWorldGenRegion region = new DhLitWorldGenRegion(
|
||||||
@@ -591,6 +591,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
return newChunk;
|
return newChunk;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// TODO FIXME this method can be called up to 25 times for the same chunk position, why?
|
||||||
private CompletableFuture<CompoundTag> getChunkNbtDataAsync(ChunkPos chunkPos)
|
private CompletableFuture<CompoundTag> getChunkNbtDataAsync(ChunkPos chunkPos)
|
||||||
{
|
{
|
||||||
ServerLevel level = this.params.level;
|
ServerLevel level = this.params.level;
|
||||||
@@ -609,7 +610,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
// storage will be null if C2ME is installed
|
// storage will be null if C2ME is installed
|
||||||
if (!this.pullExistingChunkAsync && ioWorker.storage != null)
|
if (!this.pullExistingChunkUsingMcAsyncMethod && ioWorker.storage != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -623,7 +624,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
// ioWorker.storage
|
// ioWorker.storage
|
||||||
// but just in case
|
// but just in case
|
||||||
EVENT_LOGGER.error("Unexpected issue pulling pre-existing chunk ["+chunkPos+"], falling back to async chunk pulling. This may cause server-tick lag.", e);
|
EVENT_LOGGER.error("Unexpected issue pulling pre-existing chunk ["+chunkPos+"], falling back to async chunk pulling. This may cause server-tick lag.", e);
|
||||||
this.pullExistingChunkAsync = true;
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
|
|
||||||
// try again now using the async method
|
// try again now using the async method
|
||||||
return this.getChunkNbtDataAsync(chunkPos);
|
return this.getChunkNbtDataAsync(chunkPos);
|
||||||
@@ -632,32 +633,42 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// log if we unexpectedly weren't able to run the sync chunk pulling
|
// log if we unexpectedly weren't able to run the sync chunk pulling
|
||||||
if (!this.pullExistingChunkAsync)
|
if (!this.pullExistingChunkUsingMcAsyncMethod)
|
||||||
{
|
{
|
||||||
// this shouldn't happen, but just in case
|
// this shouldn't happen, but just in case
|
||||||
EVENT_LOGGER.info("Unable to pull pre-existing chunk using synchronous method. Falling back to async method. this may cause server-tick lag.");
|
EVENT_LOGGER.info("Unable to pull pre-existing chunk using synchronous method. Falling back to async method. this may cause server-tick lag.");
|
||||||
this.pullExistingChunkAsync = true;
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//GET_CHUNK_COUNT_REF.incrementAndGet();
|
||||||
|
|
||||||
// When running in vanilla MC on versions before 1.21.4,
|
// When running in vanilla MC on versions before 1.21.4,
|
||||||
// DH would attempt to run loadAsync on this same thread via a threading mixin,
|
// DH would attempt to run loadAsync on this same thread via a threading mixin,
|
||||||
// to prevent causing lag on the server thread.
|
// to prevent causing lag on the server thread.
|
||||||
// However, if a mod like C2ME is installed this will run on a C2ME thread instead.
|
// However, if a mod like C2ME is installed this will run on a C2ME thread instead.
|
||||||
return ioWorker.loadAsync(chunkPos)
|
return ioWorker.loadAsync(chunkPos)
|
||||||
.thenApply(optional -> optional.orElse(null))
|
.thenApply(optional ->
|
||||||
.exceptionally((throwable) ->
|
|
||||||
{
|
|
||||||
// unwrap the CompletionException if necessary
|
|
||||||
Throwable actualThrowable = throwable;
|
|
||||||
while (actualThrowable instanceof CompletionException completionException)
|
|
||||||
{
|
{
|
||||||
actualThrowable = completionException.getCause();
|
// Debugging note:
|
||||||
}
|
// If there are reports of extreme memory use when C2ME is installed, that probably means
|
||||||
|
// this method is queuing a lot of tasks (1,000+), which causes C2ME to explode.
|
||||||
LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
|
|
||||||
return null;
|
//GET_CHUNK_COUNT_REF.decrementAndGet();
|
||||||
});
|
//PREF_LOGGER.info("chunk getter count ["+F3Screen.NUMBER_FORMAT.format(GET_CHUNK_COUNT_REF.get())+"]");
|
||||||
|
return optional.orElse(null);
|
||||||
|
})
|
||||||
|
.exceptionally((throwable) ->
|
||||||
|
{
|
||||||
|
// unwrap the CompletionException if necessary
|
||||||
|
Throwable actualThrowable = throwable;
|
||||||
|
while (actualThrowable instanceof CompletionException completionException)
|
||||||
|
{
|
||||||
|
actualThrowable = completionException.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -871,7 +882,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
chunkLevel = generateUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
chunkLevel = generateUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||||
|
#else
|
||||||
|
level.getChunkSource().addTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||||
|
#endif
|
||||||
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap); // probably not the most optimal to run updates here, but fast enough
|
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap); // probably not the most optimal to run updates here, but fast enough
|
||||||
ChunkHolder holder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
ChunkHolder holder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
||||||
if (holder == null)
|
if (holder == null)
|
||||||
@@ -908,7 +923,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
chunkLevel = chunkWasGeneratedUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
chunkLevel = chunkWasGeneratedUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||||
|
#else
|
||||||
|
level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// mitigate OOM issues in vanilla chunk system: see https://github.com/pop4959/Chunky/pull/383
|
// mitigate OOM issues in vanilla chunk system: see https://github.com/pop4959/Chunky/pull/383
|
||||||
level.getChunkSource().chunkMap.tick(() -> false);
|
level.getChunkSource().chunkMap.tick(() -> false);
|
||||||
|
|||||||
+454
-149
@@ -29,6 +29,9 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.shorts.ShortList;
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||||||
@@ -83,11 +86,13 @@ import net.minecraft.world.level.chunk.status.ChunkType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|
||||||
public class ChunkLoader
|
public class ChunkLoader
|
||||||
{
|
{
|
||||||
private static boolean zeroChunkPosErrorLogged = false;
|
private static final AtomicBoolean ZERO_CHUNK_POS_ERROR_LOGGED_REF = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||||
@@ -103,6 +108,8 @@ public class ChunkLoader
|
|||||||
|
|
||||||
private static boolean lightingSectionErrorLogged = false;
|
private static boolean lightingSectionErrorLogged = false;
|
||||||
|
|
||||||
|
private static final ConcurrentHashMap<String, Object> LOGGED_ERROR_MESSAGE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============//
|
//============//
|
||||||
@@ -117,19 +124,16 @@ public class ChunkLoader
|
|||||||
CompoundTag tagLevel = chunkData;
|
CompoundTag tagLevel = chunkData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
|
int chunkX = tagGetInt(tagLevel,"xPos");
|
||||||
|
int chunkZ = tagGetInt(tagLevel, "zPos");
|
||||||
|
ChunkPos actualPos = new ChunkPos(chunkX, chunkZ);
|
||||||
|
|
||||||
if (!Objects.equals(chunkPos, actualPos))
|
if (!Objects.equals(chunkPos, actualPos))
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_18_2
|
if (chunkX == 0 && chunkZ == 0)
|
||||||
if (actualPos.equals(ChunkPos.ZERO))
|
|
||||||
#else
|
|
||||||
if (actualPos.equals(ChunkPos.INVALID_CHUNK_POS))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (!zeroChunkPosErrorLogged)
|
if (!ZERO_CHUNK_POS_ERROR_LOGGED_REF.getAndSet(true))
|
||||||
{
|
{
|
||||||
zeroChunkPosErrorLogged = true;
|
|
||||||
|
|
||||||
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
||||||
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
||||||
"This might happen if the world was created using an external program. \n" +
|
"This might happen if the world was created using an external program. \n" +
|
||||||
@@ -158,7 +162,7 @@ public class ChunkLoader
|
|||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
||||||
return null;
|
return null;
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
|
|
||||||
BlendingData blendingData = readBlendingData(tagLevel);
|
BlendingData blendingData = readBlendingData(tagLevel);
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
@@ -168,17 +172,42 @@ public class ChunkLoader
|
|||||||
if (chunkType == #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK #else ChunkType.PROTOCHUNK #endif && blendingData == null)
|
if (chunkType == #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK #else ChunkType.PROTOCHUNK #endif && blendingData == null)
|
||||||
return null;
|
return null;
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
// ignore blending data, there appears to be an issue with parsing it in 1.21.6
|
||||||
|
BlendingData blendingData = null;
|
||||||
|
|
||||||
|
if (chunkType == ChunkType.PROTOCHUNK)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
long inhabitedTime = tagGetLong(tagLevel, "InhabitedTime");
|
||||||
|
|
||||||
//================== Read params for making the LevelChunk ==================
|
//================== Read params for making the LevelChunk ==================
|
||||||
UpgradeData upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
|
||||||
? new UpgradeData(tagLevel.getCompound(TAG_UPGRADE_DATA)#if MC_VER >= MC_1_17_1 , level #endif )
|
|
||||||
: UpgradeData.EMPTY;
|
|
||||||
|
|
||||||
boolean isLightOn = tagLevel.getBoolean("isLightOn");
|
UpgradeData upgradeData = 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");
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
||||||
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
||||||
@@ -195,17 +224,21 @@ public class ChunkLoader
|
|||||||
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
||||||
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
||||||
#else
|
#else
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
#else
|
#elif MC_VER < MC_1_21_4
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||||
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||||
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
#endif
|
#else
|
||||||
|
// do we need the ticks for what we're doing?
|
||||||
|
LevelChunkTicks<Block> blockTicks = new LevelChunkTicks<>();
|
||||||
|
LevelChunkTicks<Fluid> fluidTicks = new LevelChunkTicks<>();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
||||||
@@ -215,14 +248,13 @@ public class ChunkLoader
|
|||||||
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null);
|
fluidTicks, inhabitedTime, levelChunkSections, null);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
||||||
#endif
|
#endif
|
||||||
// Set some states after object creation
|
// Set some states after object creation
|
||||||
chunk.setLightCorrect(isLightOn);
|
chunk.setLightCorrect(isLightOn);
|
||||||
readHeightmaps(chunk, chunkData);
|
readHeightmaps(chunk, chunkData);
|
||||||
readPostPocessings(chunk, chunkData);
|
//readPostPocessings(chunk, chunkData);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
@@ -249,88 +281,125 @@ public class ChunkLoader
|
|||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
||||||
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
||||||
|
|
||||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
ListTag tagSections = tagGetListTag(chunkData, "Sections", 10);
|
||||||
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
if (tagSections == null || tagSections.isEmpty())
|
||||||
ListTag tagSections = chunkData.getList("Sections", 10);
|
|
||||||
if (tagSections.isEmpty()) tagSections = chunkData.getList("sections", 10);
|
|
||||||
|
|
||||||
for (int j = 0; j < tagSections.size(); ++j)
|
|
||||||
{
|
{
|
||||||
CompoundTag tagSection = tagSections.getCompound(j);
|
tagSections = tagGetListTag(chunkData, "sections", 10);
|
||||||
int sectionYPos = tagSection.getByte("Y");
|
}
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
if (tagSections != null)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < tagSections.size(); ++j)
|
||||||
{
|
{
|
||||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
CompoundTag tagSection = tagGetCompoundTag(tagSections, j);
|
||||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
if (tagSection == null)
|
||||||
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
|
|
||||||
PalettedContainer<Holder<Biome>> biomeContainer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
blockStateContainer = tagSection.contains("block_states", 10)
|
|
||||||
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
.getOrThrow(false, LOGGER::error)
|
|
||||||
#else
|
|
||||||
.getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null))
|
|
||||||
#endif
|
|
||||||
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
biomeContainer = tagSection.contains("biomes", 10)
|
|
||||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
|
||||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
|
||||||
if (tagSection.contains("biomes", 10))
|
|
||||||
{
|
{
|
||||||
biomeContainer =
|
continue;
|
||||||
biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
.getOrThrow(false, LOGGER::error);
|
|
||||||
#else
|
|
||||||
.getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
final int sectionYPos = tagGetByte(tagSection, "Y");
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||||
{
|
{
|
||||||
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
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
|
||||||
|
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
boolean containsBlockStates;
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
containsBlockStates = tagSection.contains("block_states", 10);
|
||||||
|
#else
|
||||||
|
containsBlockStates = tagSection.contains("block_states");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (containsBlockStates)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||||
|
#else
|
||||||
|
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blockStateContainer = new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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 (containsBiomes)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||||
|
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||||
|
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||||
|
#else
|
||||||
|
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||||
|
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||||
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
biomes.getHolderOrThrow(Biomes.PLAINS),
|
biomes.getHolderOrThrow(Biomes.PLAINS),
|
||||||
#else
|
#else
|
||||||
biomes.getOrThrow(Biomes.PLAINS),
|
biomes.getOrThrow(Biomes.PLAINS),
|
||||||
#endif
|
#endif
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_1
|
||||||
|
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||||
|
#else
|
||||||
|
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_1
|
}
|
||||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
|
||||||
#else
|
|
||||||
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return chunkSections;
|
return chunkSections;
|
||||||
}
|
}
|
||||||
@@ -340,57 +409,108 @@ public class ChunkLoader
|
|||||||
#else ChunkType #endif
|
#else ChunkType #endif
|
||||||
readChunkType(CompoundTag tagLevel)
|
readChunkType(CompoundTag tagLevel)
|
||||||
{
|
{
|
||||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
String statusString = tagGetString(tagLevel,"Status");
|
||||||
if (chunkStatus != null)
|
if (statusString != null)
|
||||||
{
|
{
|
||||||
return chunkStatus.getChunkType();
|
ChunkStatus chunkStatus = ChunkStatus.byName(statusString);
|
||||||
|
if (chunkStatus != null)
|
||||||
|
{
|
||||||
|
return chunkStatus.getChunkType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
#if MC_VER <= MC_1_20_4
|
||||||
#if MC_VER <= MC_1_20_4 ChunkStatus.ChunkType.PROTOCHUNK;
|
return ChunkStatus.ChunkType.PROTOCHUNK;
|
||||||
#else ChunkType.PROTOCHUNK; #endif
|
#else
|
||||||
|
return ChunkType.PROTOCHUNK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
CompoundTag tagHeightmaps = tagGetCompoundTag(chunkData, "Heightmaps");
|
||||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
if (tagHeightmaps != null)
|
||||||
{
|
{
|
||||||
String heightmap = type.getSerializationKey();
|
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||||
if (tagHeightmaps.contains(heightmap, 12))
|
|
||||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
|
||||||
}
|
|
||||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
|
||||||
}
|
|
||||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
|
||||||
for (int i = 0; i < tagPostProcessings.size(); ++i)
|
|
||||||
{
|
|
||||||
ListTag listTag3 = tagPostProcessings.getList(i);
|
|
||||||
for (int j = 0; j < listTag3.size(); ++j)
|
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_3
|
String heightmap = type.getSerializationKey();
|
||||||
chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
#if MC_VER < MC_1_21_5
|
||||||
|
if (tagHeightmaps.contains(heightmap, 12))
|
||||||
|
{
|
||||||
|
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
chunk.addPackedPostProcess(ShortList.of(listTag3.getShort(j)), i);
|
if (tagHeightmaps.contains(heightmap))
|
||||||
|
{
|
||||||
|
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmap);
|
||||||
|
if (optionalHeightmap.isPresent())
|
||||||
|
{
|
||||||
|
chunk.setHeightmap(type, optionalHeightmap.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#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
|
#if MC_VER >= MC_1_18_2
|
||||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
BlendingData blendingData = null;
|
BlendingData blendingData = null;
|
||||||
if (chunkData.contains("blending_data", 10))
|
|
||||||
|
|
||||||
|
boolean containsBlendingData;
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
containsBlendingData = chunkData.contains("blending_data", 10);
|
||||||
|
#else
|
||||||
|
containsBlendingData = chunkData.contains("blending_data");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (containsBlendingData)
|
||||||
{
|
{
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
try
|
||||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
|
{
|
||||||
#else
|
#if MC_VER < MC_1_21_3
|
||||||
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null));
|
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null);
|
||||||
#endif
|
#else
|
||||||
|
// blending data appears to have changed as of 1.21.6 causing a class cast exception here due to it being wrapped in a Java.Optional
|
||||||
|
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message == null || message.trim().isEmpty())
|
||||||
|
{
|
||||||
|
message = "Failed to parse blending data";
|
||||||
|
}
|
||||||
|
|
||||||
|
logParsingWarningOnce(message, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return blendingData;
|
return blendingData;
|
||||||
}
|
}
|
||||||
@@ -467,33 +587,37 @@ public class ChunkLoader
|
|||||||
|
|
||||||
|
|
||||||
// if null all lights = 0
|
// if null all lights = 0
|
||||||
byte[] blockLightNibbleArray = chunkSectionCompoundTag.getByteArray("BlockLight");
|
byte[] blockLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "BlockLight");
|
||||||
byte[] skyLightNibbleArray = chunkSectionCompoundTag.getByteArray("SkyLight");
|
byte[] skyLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "SkyLight");
|
||||||
|
|
||||||
// if any sky light was found then all lights above will be max brightness
|
if (blockLightNibbleArray != null
|
||||||
if (skyLightNibbleArray.length != 0)
|
&& skyLightNibbleArray != null)
|
||||||
{
|
{
|
||||||
foundSkyLight = true;
|
// if any sky light was found then all lights above will be max brightness
|
||||||
}
|
if (skyLightNibbleArray.length != 0)
|
||||||
|
|
||||||
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
|
||||||
{
|
|
||||||
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
|
||||||
{
|
{
|
||||||
// chunk sections are also 16 blocks tall
|
foundSkyLight = true;
|
||||||
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
}
|
||||||
|
|
||||||
|
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||||
|
{
|
||||||
|
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||||
{
|
{
|
||||||
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
// chunk sections are also 16 blocks tall
|
||||||
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||||
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
|
||||||
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
|
||||||
{
|
{
|
||||||
skyLight = LodUtil.MAX_MC_LIGHT;
|
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
||||||
|
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
||||||
|
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
||||||
|
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
||||||
|
{
|
||||||
|
skyLight = LodUtil.MAX_MC_LIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
||||||
|
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||||
|
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
|
||||||
blockLightStorage.set(relX, y, relZ, blockLight);
|
|
||||||
skyLightStorage.set(relX, y, relZ, skyLight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,13 +639,194 @@ public class ChunkLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// logging //
|
||||||
|
//=========//
|
||||||
|
|
||||||
private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
||||||
{
|
{
|
||||||
LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
||||||
{
|
{
|
||||||
LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logParsingWarningOnce(String message) { logParsingWarningOnce(message, null); }
|
||||||
|
private static void logParsingWarningOnce(String message, Exception e)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.",
|
||||||
|
e);
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RuntimeException logErrorAndReturnException(String message)
|
||||||
|
{
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Currently we want to ignore these errors, if returning null is a problem, we can change this later
|
||||||
|
return null; //new RuntimeException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//====================//
|
||||||
|
// tag helper methods //
|
||||||
|
//====================//
|
||||||
|
|
||||||
|
// TODO move into separate file (this file is getting long)
|
||||||
|
// these tag helpers are to simplify tag accessing between MC versions
|
||||||
|
|
||||||
|
/** defaults to "false" if the tag isn't present */
|
||||||
|
private static boolean tagGetBoolean(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getBoolean(key);
|
||||||
|
#else
|
||||||
|
return tag.getBoolean(key).orElse(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static byte tagGetByte(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByte(key);
|
||||||
|
#else
|
||||||
|
return tag.getByte(key).orElse((byte)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static short tagGetShort(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getShort(index);
|
||||||
|
#else
|
||||||
|
return tag.getShort(index).orElse((short)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static int tagGetInt(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getInt(key).orElse(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
private static long tagGetLong(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getLong(key).orElse(0L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static String tagGetString(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getString(key);
|
||||||
|
#else
|
||||||
|
return tag.getString(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static byte[] tagGetByteArray(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByteArray(key);
|
||||||
|
#else
|
||||||
|
return tag.getByteArray(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static CompoundTag tagGetCompoundTag(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(key);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static CompoundTag tagGetCompoundTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(index);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(index).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* defaults to null if the tag isn't present
|
||||||
|
* @param elementType unused after MC 1.21.5
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private static ListTag tagGetListTag(CompoundTag tag, String key, int elementType)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(key, elementType);
|
||||||
|
#else
|
||||||
|
return tag.getList(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
private static ListTag tagGetListTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(index);
|
||||||
|
#else
|
||||||
|
return tag.getList(index).orElse(null);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
@@ -229,8 +229,16 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
{
|
{
|
||||||
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
||||||
if (chunkAccess instanceof LevelChunk)
|
if (chunkAccess instanceof LevelChunk)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
|
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
|
||||||
|
#else
|
||||||
|
chunkAccess.setBlockState(blockPos, blockState, /*flags*/0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is for post ticking for water on gen and stuff like that. Not enabled
|
// This is for post ticking for water on gen and stuff like that. Not enabled
|
||||||
// for now.
|
// for now.
|
||||||
// if (blockState.hasPostProcess(this, blockPos))
|
// if (blockState.hasPostProcess(this, blockPos))
|
||||||
|
|||||||
+1
-1
Submodule coreSubProjects updated: 863bfbaff5...435cbde238
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "fabric-loom" version "1.8-SNAPSHOT"
|
id "fabric-loom" version "1.10-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -226,6 +228,14 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//LOGGER.info("\n\n" +
|
||||||
|
// "Level Render\n" +
|
||||||
|
// "Mc MVM: \n" + modelViewMatrix.toString() + "\n" +
|
||||||
|
// "Mc Proj: \n" + projectionMatrix.toString()
|
||||||
|
//);
|
||||||
|
|
||||||
|
|
||||||
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
|
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
|
||||||
modelViewMatrix,
|
modelViewMatrix,
|
||||||
projectionMatrix,
|
projectionMatrix,
|
||||||
@@ -274,6 +284,17 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
// rendered in MixinLevelRenderer
|
||||||
|
#else
|
||||||
|
ClientApi.INSTANCE.renderDeferredLodsForShaders(ClientLevelWrapper.getWrapper(renderContext.world()),
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
this.clientApi.renderFade(
|
this.clientApi.renderFade(
|
||||||
modelViewMatrix,
|
modelViewMatrix,
|
||||||
projectionMatrix,
|
projectionMatrix,
|
||||||
@@ -316,9 +337,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);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.fabric;
|
package com.seibel.distanthorizons.fabric;
|
||||||
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
|
||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
import com.seibel.distanthorizons.core.config.ConfigBase;
|
||||||
@@ -90,8 +91,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);
|
||||||
@@ -126,7 +127,8 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void subscribeClientStartedEvent(Runnable eventHandler) { ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); }
|
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||||
|
{ ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
||||||
|
|||||||
+2
-6
@@ -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);
|
||||||
|
|||||||
+106
-15
@@ -22,31 +22,51 @@ package com.seibel.distanthorizons.fabric.mixins.client;
|
|||||||
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.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.renderer.FogRenderer;
|
|
||||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
import net.minecraft.world.level.material.FogType;
|
import net.minecraft.world.level.material.FogType;
|
||||||
#else
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
import net.minecraft.world.level.material.FogType;
|
import net.minecraft.world.level.material.FogType;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
import com.mojang.blaze3d.shaders.FogShape;
|
import com.mojang.blaze3d.shaders.FogShape;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
import net.minecraft.client.renderer.FogParameters;
|
import net.minecraft.client.renderer.FogParameters;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.material.FogType;
|
||||||
|
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.fog.FogData;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@Mixin(FogRenderer.class)
|
@Mixin(FogRenderer.class)
|
||||||
@@ -66,18 +86,23 @@ public class MixinFogRenderer
|
|||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
@Inject(at = @At("RETURN"), method = "setupFog")
|
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
|
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
|
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
|
||||||
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
|
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
|
||||||
|
#else
|
||||||
|
@Unique
|
||||||
|
private static void unused()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
#if MC_VER < MC_1_21_6
|
||||||
|
boolean cancelFog = cancelFog(camera, fogMode);
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
boolean cancelFog = cancelFog(camera);
|
||||||
|
#else
|
||||||
|
boolean cancelFog = cancelFog();
|
||||||
|
#endif
|
||||||
|
|
||||||
Entity entity = camera.getEntity();
|
if (cancelFog)
|
||||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
|
||||||
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
|
|
||||||
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
|
||||||
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
|
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
@@ -85,10 +110,74 @@ public class MixinFogRenderer
|
|||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
callback.setReturnValue(FogParameters.NO_FOG);
|
callback.setReturnValue(FogParameters.NO_FOG);
|
||||||
|
#else
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
#else
|
||||||
|
|
||||||
|
// In MC's FogRenderer they clamp the "renderDistanceEnd" fog field to the render distance,
|
||||||
|
// which prevents us from disabling the vanilla fog.
|
||||||
|
// This mixin fires after they set the "renderDistanceEnd" so we can change it.
|
||||||
|
@WrapOperation(
|
||||||
|
method = "setupFog",
|
||||||
|
at = @At(
|
||||||
|
value = "FIELD",
|
||||||
|
target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F",
|
||||||
|
opcode = org.objectweb.asm.Opcodes.PUTFIELD
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private void onSetRenderDistanceEnd(FogData instance, float value, Operation<Void> original)
|
||||||
|
{
|
||||||
|
if (cancelFog())
|
||||||
|
{
|
||||||
|
instance.environmentalStart = A_REALLY_REALLY_BIG_VALUE;
|
||||||
|
instance.environmentalEnd = A_EVEN_LARGER_VALUE;
|
||||||
|
|
||||||
|
instance.renderDistanceStart = A_REALLY_REALLY_BIG_VALUE;
|
||||||
|
instance.renderDistanceEnd = A_EVEN_LARGER_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always call the original with the modified or original value
|
||||||
|
original.call(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
private static boolean cancelFog(Camera camera, FogMode fogMode)
|
||||||
|
#else
|
||||||
|
private static boolean cancelFog()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
|
#else
|
||||||
|
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||||
|
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||||
|
|
||||||
|
boolean cancelFog = !isSpecialFog;
|
||||||
|
cancelFog = cancelFog && cameraNotInFluid;
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
cancelFog = cancelFog && (fogMode == FogMode.FOG_TERRAIN);
|
||||||
|
#endif
|
||||||
|
cancelFog = cancelFog && !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial();
|
||||||
|
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||||
|
|
||||||
|
return cancelFog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
@@ -105,4 +194,6 @@ public class MixinFogRenderer
|
|||||||
return cameraNotInFluid;
|
return cameraNotInFluid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-39
@@ -19,51 +19,54 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
#else
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||||
|
import org.joml.Matrix4fc;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
#endif
|
#endif
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import com.seibel.distanthorizons.fabric.FabricClientProxy;
|
||||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import net.minecraft.client.Camera;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
/**
|
import org.apache.logging.log4j.Logger;
|
||||||
* This class is used to mix in my rendering code
|
|
||||||
* before Minecraft starts rendering blocks.
|
|
||||||
* If this wasn't done, and we used Forge's
|
|
||||||
* render last event, the LODs would render on top
|
|
||||||
* of the normal terrain.
|
|
||||||
*
|
|
||||||
* This is also the mixin for rendering the clouds
|
|
||||||
*
|
|
||||||
* @author coolGi
|
|
||||||
* @author James Seibel
|
|
||||||
* @version 12-31-2021
|
|
||||||
*/
|
|
||||||
@Mixin(LevelRenderer.class)
|
@Mixin(LevelRenderer.class)
|
||||||
public class MixinLevelRenderer
|
public class MixinLevelRenderer
|
||||||
{
|
{
|
||||||
@Shadow
|
@Shadow
|
||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
@Inject(at = @At("HEAD"),
|
@Inject(at = @At("HEAD"),
|
||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
|
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
|
||||||
@@ -84,51 +87,65 @@ public class MixinLevelRenderer
|
|||||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
@Inject(at = @At("HEAD"),
|
@Inject(at = @At("HEAD"),
|
||||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
||||||
|
#else
|
||||||
|
@Inject(at = @At("HEAD"), method = "prepareChunkRenders", cancellable = true)
|
||||||
|
private void prepareChunkRenders(Matrix4fc projectionMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if MC_VER == MC_1_16_5
|
#if MC_VER == MC_1_16_5
|
||||||
// get the matrices from the OpenGL fixed pipeline
|
// get the matrices from the OpenGL fixed pipeline
|
||||||
float[] mcProjMatrixRaw = new float[16];
|
float[] mcProjMatrixRaw = new float[16];
|
||||||
GL32.glGetFloatv(GL32.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
GL32.glGetFloatv(GL32.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||||
mcProjectionMatrix.transpose();
|
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
|
||||||
|
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||||
|
|
||||||
#elif MC_VER <= MC_1_20_4
|
#elif MC_VER <= MC_1_20_4
|
||||||
// get the matrices directly from MC
|
// get the matrices directly from MC
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
#else
|
#else
|
||||||
// MC combined the model view and projection matricies
|
// MC combined the model view and projection matricies
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
Mat4f mcProjectionMatrix = new Mat4f();
|
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f();
|
||||||
mcProjectionMatrix.setIdentity();
|
ClientApi.RENDER_STATE.mcProjectionMatrix.setIdentity();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO move this into a common place
|
// TODO move this into a common place
|
||||||
float frameTime;
|
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER < MC_1_21_1
|
||||||
frameTime = Minecraft.getInstance().getFrameTime();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getFrameTime();
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||||
#else
|
#else
|
||||||
frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//LOGGER.info("\n\n" +
|
||||||
|
// "Level Mixin\n" +
|
||||||
|
// "Mc MVM: \n" + mcModelViewMatrix.toString() + "\n" +
|
||||||
|
// "Mc Proj: \n" + mcProjectionMatrix.toString()
|
||||||
|
//);
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
if (renderType.equals(RenderType.translucent()))
|
if (renderType.equals(RenderType.translucent()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
|
ClientApi.INSTANCE.renderDeferredLodsForShaders(ClientLevelWrapper.getWrapper(this.level),
|
||||||
mcModelViewMatrix,
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
mcProjectionMatrix,
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
frameTime
|
ClientApi.RENDER_STATE.frameTime
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// rendering handled via Fabric Api render event
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME completely disables rendering when sodium is installed
|
// FIXME completely disables rendering when sodium is installed
|
||||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||||
@@ -137,4 +154,6 @@ public class MixinLevelRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-5
@@ -34,21 +34,34 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@Mixin(LightTexture.class)
|
@Mixin(LightTexture.class)
|
||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
private NativeImage lightPixels;
|
private NativeImage lightPixels;
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
private TextureTarget target;
|
private TextureTarget target;
|
||||||
|
#else
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private GpuTexture texture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
@@ -63,8 +76,11 @@ public class MixinLightTexture
|
|||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
#else
|
#elif MC_VER < MC_1_21_5
|
||||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||||
|
#else
|
||||||
|
GlTexture glTexture = (GlTexture) this.texture;
|
||||||
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(glTexture.glId(), clientLevel);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-10
@@ -76,15 +76,25 @@ public abstract class MixinMinecraft
|
|||||||
|
|
||||||
if (SelfUpdater.onStart() || DEBUG_ALWAYS_SHOW_UPDATER)
|
if (SelfUpdater.onStart() || DEBUG_ALWAYS_SHOW_UPDATER)
|
||||||
{
|
{
|
||||||
instance.setScreen(new UpdateModScreen(
|
try
|
||||||
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
{
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
instance.setScreen(new UpdateModScreen(
|
||||||
));
|
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
||||||
}
|
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
||||||
else
|
));
|
||||||
{
|
return;
|
||||||
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// info instead of error since this can be ignored and probably just means
|
||||||
|
// there isn't a new DH version available
|
||||||
|
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the screen back to the vanilla screen as if nothing ever happened
|
||||||
|
// if not done the game will crash
|
||||||
|
instance.setScreen(guiScreen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -124,14 +134,13 @@ public abstract class MixinMinecraft
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
Minecraft.getInstance().setScreen(new UpdateModScreen(
|
Minecraft.getInstance().setScreen(new UpdateModScreen(
|
||||||
// TODO: Change to runnable, instead of tittle screen
|
// TODO: Change to runnable, instead of tittle screen
|
||||||
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
||||||
versionId
|
versionId
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// info instead of error since this can be ignored and probably just means
|
// info instead of error since this can be ignored and probably just means
|
||||||
// there isn't a new DH version available
|
// there isn't a new DH version available
|
||||||
|
|||||||
+7
@@ -1,12 +1,15 @@
|
|||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#endif
|
||||||
import com.mojang.blaze3d.platform.TextureUtil;
|
import com.mojang.blaze3d.platform.TextureUtil;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets Minecraft's LOD Bias (looks similar to mipmaps)
|
* Sets Minecraft's LOD Bias (looks similar to mipmaps)
|
||||||
*
|
*
|
||||||
@@ -15,6 +18,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
@Mixin(TextureUtil.class)
|
@Mixin(TextureUtil.class)
|
||||||
public class MixinTextureUtil
|
public class MixinTextureUtil
|
||||||
{
|
{
|
||||||
|
// TODO fix for MC 1.21.5+
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
|
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
|
||||||
private static void setLodBias(int target, int pname, float param)
|
private static void setLodBias(int target, int pname, float param)
|
||||||
@@ -27,5 +33,6 @@ public class MixinTextureUtil
|
|||||||
GlStateManager._texParameter(target, pname, biasValue);
|
GlStateManager._texParameter(target, pname, biasValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-15
@@ -1,24 +1,16 @@
|
|||||||
package com.seibel.distanthorizons.fabric.mixins.server;
|
package com.seibel.distanthorizons.fabric.mixins.server;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_4
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
|
||||||
|
|
||||||
import net.minecraft.Util;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
/**
|
@Mixin(Entity.class)
|
||||||
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
|
public class MixinLevelTicks<T>
|
||||||
* This is just a dummy class/mixin to make the compiler happy.
|
|
||||||
*
|
|
||||||
* @see MixinUtilBackgroundThread
|
|
||||||
*/
|
|
||||||
//@Mixin(net.minecraft.minecraft.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
|
|
||||||
@Mixin(Util.class)
|
|
||||||
public class MixinLevelTicks
|
|
||||||
{
|
{
|
||||||
|
// dummy mixin to make the loader happy
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
||||||
@@ -31,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(LevelTicks.class)
|
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
||||||
public class MixinLevelTicks<T>
|
public class MixinLevelTicks<T>
|
||||||
{
|
{
|
||||||
// TODO put in a common location
|
// TODO put in a common location
|
||||||
@@ -41,7 +33,7 @@ public class MixinLevelTicks<T>
|
|||||||
|
|
||||||
|
|
||||||
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
||||||
private void schedule(ScheduledTick<T> tick, CallbackInfo ci)
|
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
||||||
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
||||||
@@ -52,4 +44,5 @@ public class MixinLevelTicks<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+12
-12
@@ -46,8 +46,8 @@ public class TestGenericWorldGenerator implements IDhApiWorldGenerator
|
|||||||
public byte getSmallestDataDetailLevel() { return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
|
public byte getSmallestDataDetailLevel() { return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
|
||||||
@Override
|
@Override
|
||||||
public byte getLargestDataDetailLevel()
|
public byte getLargestDataDetailLevel()
|
||||||
//{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel + 12); }
|
{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel + 12); }
|
||||||
{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
|
//{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -105,43 +105,43 @@ public class TestGenericWorldGenerator implements IDhApiWorldGenerator
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
blockResourceLocation = "minecraft:red_wool";
|
blockResourceLocation = "minecraft:red_wool";
|
||||||
maxHeight = 60;
|
maxHeight = 20;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
blockResourceLocation = "minecraft:orange_wool";
|
blockResourceLocation = "minecraft:orange_wool";
|
||||||
maxHeight = 70;
|
maxHeight = 30;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
blockResourceLocation = "minecraft:yellow_wool";
|
blockResourceLocation = "minecraft:yellow_wool";
|
||||||
maxHeight = 80;
|
maxHeight = 40;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
blockResourceLocation = "minecraft:lime_wool";
|
blockResourceLocation = "minecraft:lime_wool";
|
||||||
maxHeight = 90;
|
maxHeight = 50;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
blockResourceLocation = "minecraft:cyan_wool";
|
blockResourceLocation = "minecraft:cyan_wool";
|
||||||
maxHeight = 100;
|
maxHeight = 60;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
blockResourceLocation = "minecraft:blue_wool";
|
blockResourceLocation = "minecraft:blue_wool";
|
||||||
maxHeight = 100;
|
maxHeight = 70;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
blockResourceLocation = "minecraft:magenta_wool";
|
blockResourceLocation = "minecraft:magenta_wool";
|
||||||
maxHeight = 110;
|
maxHeight = 80;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
blockResourceLocation = "minecraft:white_wool";
|
blockResourceLocation = "minecraft:white_wool";
|
||||||
maxHeight = 120;
|
maxHeight = 90;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
blockResourceLocation = "minecraft:gray_wool";
|
blockResourceLocation = "minecraft:gray_wool";
|
||||||
maxHeight = 120;
|
maxHeight = 100;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
blockResourceLocation = "minecraft:black_wool";
|
blockResourceLocation = "minecraft:black_wool";
|
||||||
maxHeight = 140;
|
maxHeight = 110;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
|
|||||||
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
|
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
|
||||||
|
|
||||||
// override the core DH world generator for this level
|
// override the core DH world generator for this level
|
||||||
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level);
|
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level); // TODO biomes are broken for some reason
|
||||||
IDhApiWorldGenerator exampleWorldGen = new TestGenericWorldGenerator(event.value.levelWrapper);
|
IDhApiWorldGenerator exampleWorldGen = new TestGenericWorldGenerator(event.value.levelWrapper);
|
||||||
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
|
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -43,11 +43,22 @@ import net.minecraft.world.phys.AABB;
|
|||||||
|
|
||||||
public class SodiumAccessor implements ISodiumAccessor
|
public class SodiumAccessor implements ISodiumAccessor
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* True if sodium 0.5 or less is present. <br>
|
||||||
|
* This field is public because it's also used to check if we need Indium to be present. <br>
|
||||||
|
* We need Indium if Sodium 0.5 or less is present.
|
||||||
|
*/
|
||||||
|
public static final boolean isSodiumV5OrLess;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER >= MC_1_20_1
|
||||||
private static MethodHandle setFogOcclusionMethod;
|
private static MethodHandle setFogOcclusionMethod;
|
||||||
private static Object sodiumPerformanceOptions;
|
private static Object sodiumPerformanceOptions;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static {
|
||||||
|
isSodiumV5OrLess = !classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//======================//
|
//======================//
|
||||||
@@ -72,8 +83,7 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
{
|
{
|
||||||
if (sodiumPerformanceOptions == null)
|
if (sodiumPerformanceOptions == null)
|
||||||
{
|
{
|
||||||
boolean sodiumV6 = classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
if (isSodiumV5OrLess)
|
||||||
if (!sodiumV6)
|
|
||||||
{
|
{
|
||||||
// sodium 0.5
|
// sodium 0.5
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"server.MixinEntity",
|
"server.MixinEntity",
|
||||||
"server.MixinServerPlayer",
|
"server.MixinServerPlayer",
|
||||||
"server.MixinTracingExecutor",
|
"server.MixinTracingExecutor",
|
||||||
"server.MixinUtilBackgroundThread",
|
"server.MixinUtilBackgroundThread",
|
||||||
"server.MixinLevelTicks"
|
"server.MixinLevelTicks"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
|||||||
@@ -24,13 +24,17 @@ import com.seibel.distanthorizons.common.util.ProxyUtil;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
@@ -52,6 +56,7 @@ import net.minecraft.world.level.chunk.ChunkAccess;
|
|||||||
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
@@ -75,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();
|
||||||
|
|
||||||
|
|
||||||
@@ -90,7 +96,13 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
public void registerEvents()
|
public void registerEvents()
|
||||||
{
|
{
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
ForgePluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived);
|
|
||||||
|
// handles singleplayer, LAN, and connecting to a server
|
||||||
|
PACKET_SENDER.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||||
|
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -118,14 +118,14 @@ public class ForgeMain extends AbstractModInitializer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
||||||
{
|
{ MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }
|
||||||
MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); });
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||||
{
|
{
|
||||||
// FIXME What event is this?
|
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
|
||||||
|
// to signify readiness other than FmlClientSetupEvent
|
||||||
|
eventHandler.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,10 +82,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public ForgeServerProxy(boolean isDedicated)
|
public ForgeServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; }
|
||||||
{
|
|
||||||
this.isDedicated = isDedicated;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ public class MixinLevelRenderer
|
|||||||
}
|
}
|
||||||
else if (renderType.equals(RenderType.translucent()))
|
else if (renderType.equals(RenderType.translucent()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
ClientApi.INSTANCE.renderDeferredLodsForShaders(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render fade
|
// render fade
|
||||||
|
|||||||
+19
-9
@@ -57,15 +57,25 @@ public class MixinMinecraft
|
|||||||
|
|
||||||
if (SelfUpdater.onStart())
|
if (SelfUpdater.onStart())
|
||||||
{
|
{
|
||||||
instance.setScreen(new UpdateModScreen(
|
try
|
||||||
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
{
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
instance.setScreen(new UpdateModScreen(
|
||||||
));
|
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
||||||
}
|
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
||||||
else
|
));
|
||||||
{
|
return;
|
||||||
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// info instead of error since this can be ignored and probably just means
|
||||||
|
// there isn't a new DH version available
|
||||||
|
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the screen back to the vanilla screen as if nothing ever happened
|
||||||
|
// if not done the game will crash
|
||||||
|
instance.setScreen(guiScreen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -108,7 +118,7 @@ public class MixinMinecraft
|
|||||||
versionId
|
versionId
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// info instead of error since this can be ignored and probably just means
|
// info instead of error since this can be ignored and probably just means
|
||||||
// there isn't a new DH version available
|
// there isn't a new DH version available
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@ org.gradle.caching=true
|
|||||||
|
|
||||||
# Mod Info
|
# Mod Info
|
||||||
mod_name=DistantHorizons
|
mod_name=DistantHorizons
|
||||||
mod_version=2.3.0-b-dev
|
mod_version=2.3.4-b
|
||||||
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
|
||||||
@@ -18,14 +18,14 @@ mod_issues=https://gitlab.com/jeseibel/distant-horizons/-/issues
|
|||||||
mod_discord=https://discord.gg/xAB8G4cENx
|
mod_discord=https://discord.gg/xAB8G4cENx
|
||||||
|
|
||||||
# Global Plugin Versions
|
# Global Plugin Versions
|
||||||
manifold_version=2024.1.37
|
manifold_version=2025.1.20
|
||||||
# 2023.1.17 can be used if there are mystery Java compiler issues
|
# 2023.1.17 can be used if there are mystery Java compiler issues
|
||||||
nightconfig_version=3.6.6
|
nightconfig_version=3.6.6
|
||||||
lz4_version=1.8.0
|
lz4_version=1.8.0
|
||||||
xz_version=1.9
|
xz_version=1.9
|
||||||
|
# Before updating, read relocate_natives/README.md
|
||||||
sqlite_jdbc_version=3.47.2.0
|
sqlite_jdbc_version=3.47.2.0
|
||||||
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
||||||
# (at least until we can fix the gradle script so core and main can use/shade different fastutil versions)
|
|
||||||
fastutil_version=8.2.1
|
fastutil_version=8.2.1
|
||||||
#svgSalamander_version=1.1.3
|
#svgSalamander_version=1.1.3
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ versionStr=
|
|||||||
|
|
||||||
# This defines what MC version Intellij will use for the preprocessor
|
# This defines what MC version Intellij will use for the preprocessor
|
||||||
# and what version is used automatically by build and run commands
|
# and what version is used automatically by build and run commands
|
||||||
mcVer=1.21.4
|
mcVer=1.21.8
|
||||||
|
|
||||||
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
||||||
#minecraftMemoryJavaArg="-Xmx4G"
|
#minecraftMemoryJavaArg="-Xmx4G"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
+52
-17
@@ -78,13 +78,6 @@ public class NeoforgeClientProxy 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 Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
// private static SimpleChannel multiversePluginChannel;
|
|
||||||
|
|
||||||
// Not the cleanest way of passing this to the LOD renderer, but it'll have to do for now
|
|
||||||
public static Mat4f currentModelViewMatrix = new Mat4f();
|
|
||||||
public static Mat4f currentProjectionMatrix = new Mat4f();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,16 +237,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// rendering //
|
// rendering //
|
||||||
//===========//
|
//===========//
|
||||||
|
|
||||||
@SubscribeEvent
|
#if MC_VER < MC_1_21_6
|
||||||
public void beforeLevelRenderEvent(RenderLevelStageEvent event)
|
|
||||||
{
|
|
||||||
if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_SKY)
|
|
||||||
{
|
|
||||||
currentModelViewMatrix = McObjectConverter.Convert(event.getModelViewMatrix());
|
|
||||||
currentProjectionMatrix = McObjectConverter.Convert(event.getProjectionMatrix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void afterLevelRenderEvent(RenderLevelStageEvent event)
|
public void afterLevelRenderEvent(RenderLevelStageEvent event)
|
||||||
{
|
{
|
||||||
@@ -272,6 +256,56 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void afterLevelEntityRenderEvent(RenderLevelStageEvent.AfterEntities event)
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.renderFade(
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime,
|
||||||
|
ClientLevelWrapper.getWrapper((ClientLevel)event.getLevel())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void afterLevelTranslucentRenderEvent(RenderLevelStageEvent.AfterTranslucentBlocks event)
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.renderDeferredLodsForShaders(ClientLevelWrapper.getWrapper((ClientLevel)event.getLevel()),
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void afterLevelRenderEvent(RenderLevelStageEvent.AfterLevel event)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// should generally only need to be set once per game session
|
||||||
|
// allows DH to render directly to Optifine's level frame buffer,
|
||||||
|
// allowing better shader support
|
||||||
|
MinecraftRenderWrapper.INSTANCE.finalLevelFrameBufferId = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||||
|
}
|
||||||
|
catch (Exception | Error e)
|
||||||
|
{
|
||||||
|
LOGGER.error("Unexpected error in afterLevelRenderEvent: "+e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ClientApi.INSTANCE.renderFadeOpaque(
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime,
|
||||||
|
ClientLevelWrapper.getWrapper((ClientLevel)event.getLevel())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -282,4 +316,5 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import com.mojang.brigadier.CommandDispatcher;
|
|||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
@@ -49,8 +50,13 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
#if MC_VER < MC_1_20_6
|
#if MC_VER < MC_1_20_6
|
||||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||||
|
#elif MC_VER < MC_1_21_8
|
||||||
|
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
#else
|
#else
|
||||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import net.neoforged.neoforge.client.network.event.RegisterClientPayloadHandlersEvent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,11 +70,21 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
{
|
{
|
||||||
public NeoforgeMain(IEventBus eventBus)
|
public NeoforgeMain(IEventBus eventBus)
|
||||||
{
|
{
|
||||||
eventBus.addListener((FMLClientSetupEvent e) -> {
|
// handles singleplayer, LAN, and connecting to a server
|
||||||
|
eventBus.addListener((FMLClientSetupEvent e) ->
|
||||||
|
{
|
||||||
this.onInitializeClient();
|
this.onInitializeClient();
|
||||||
eventBus.addListener(this::registerNetworkingClient);
|
eventBus.addListener(this::registerNetworkingClientServer);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_8
|
||||||
|
#else
|
||||||
|
eventBus.addListener(this::registerClientPayloadEvent);
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
eventBus.addListener((FMLDedicatedServerSetupEvent e) -> {
|
|
||||||
|
// handles dedicated servers
|
||||||
|
eventBus.addListener((FMLDedicatedServerSetupEvent e) ->
|
||||||
|
{
|
||||||
this.onInitializeServer();
|
this.onInitializeServer();
|
||||||
eventBus.addListener(this::registerNetworkingServer);
|
eventBus.addListener(this::registerNetworkingServer);
|
||||||
});
|
});
|
||||||
@@ -79,11 +95,26 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
//============//
|
//============//
|
||||||
// networking //
|
// networking //
|
||||||
//============//
|
//============//
|
||||||
public void registerNetworkingClient(RegisterPayloadHandlersEvent event)
|
|
||||||
{ NeoforgePluginPacketSender.setPacketHandler(event, ClientApi.INSTANCE::pluginMessageReceived); }
|
public void registerNetworkingClientServer(RegisterPayloadHandlersEvent event)
|
||||||
|
{
|
||||||
|
NeoforgePluginPacketSender.setPacketHandler(event, (IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||||
|
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||||
|
});
|
||||||
|
}
|
||||||
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
|
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
|
||||||
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
|
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_8
|
||||||
|
#else
|
||||||
|
public void registerClientPayloadEvent(RegisterClientPayloadHandlersEvent event)
|
||||||
|
{ NeoforgePluginPacketSender.registerClientPacketHandler(event); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -124,7 +155,9 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
@Override
|
@Override
|
||||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||||
{
|
{
|
||||||
// FIXME What event is this?
|
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
|
||||||
|
// to signify readiness other than FmlClientSetupEvent
|
||||||
|
eventHandler.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+32
-1
@@ -14,10 +14,19 @@ import java.util.Optional;
|
|||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_8
|
||||||
|
#else
|
||||||
|
import net.neoforged.neoforge.client.network.ClientPacketDistributor;
|
||||||
|
import net.neoforged.neoforge.client.network.event.RegisterClientPayloadHandlersEvent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
|
public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
|
||||||
{
|
{
|
||||||
private static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> packetConsumer;
|
private static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> packetConsumer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void setPacketHandler(RegisterPayloadHandlersEvent event, Consumer<AbstractNetworkMessage> consumer)
|
public static void setPacketHandler(RegisterPayloadHandlersEvent event, Consumer<AbstractNetworkMessage> consumer)
|
||||||
{ setPacketHandler(event, (player, buffer) -> consumer.accept(buffer)); }
|
{ setPacketHandler(event, (player, buffer) -> consumer.accept(buffer)); }
|
||||||
public static void setPacketHandler(RegisterPayloadHandlersEvent event, BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
public static void setPacketHandler(RegisterPayloadHandlersEvent event, BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
||||||
@@ -39,9 +48,31 @@ public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_8
|
||||||
|
#else
|
||||||
|
public static void registerClientPacketHandler(RegisterClientPayloadHandlersEvent event)
|
||||||
|
{
|
||||||
|
// as of MC 1.21.7 Neo added a separate client network register
|
||||||
|
// https://github.com/neoforged/NeoForge/pull/2272
|
||||||
|
event.register(CommonPacketPayload.TYPE, (payload, context) ->
|
||||||
|
{
|
||||||
|
if (payload.message() != null)
|
||||||
|
{
|
||||||
|
packetConsumer.accept(null, payload.message());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendToServer(AbstractNetworkMessage message)
|
public void sendToServer(AbstractNetworkMessage message)
|
||||||
{ PacketDistributor.sendToServer(new CommonPacketPayload(message)); }
|
{
|
||||||
|
#if MC_VER < MC_1_21_8
|
||||||
|
PacketDistributor.sendToServer(new CommonPacketPayload(message));
|
||||||
|
#else
|
||||||
|
ClientPacketDistributor.sendToServer(new CommonPacketPayload(message));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
|
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
|
||||||
|
|||||||
+117
-31
@@ -22,67 +22,87 @@ package com.seibel.distanthorizons.neoforge.mixins.client;
|
|||||||
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.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.renderer.FogRenderer;
|
|
||||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
import net.minecraft.world.level.material.FogType;
|
import net.minecraft.world.level.material.FogType;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
import net.minecraft.world.level.material.FogType;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
import com.mojang.blaze3d.shaders.FogShape;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import net.minecraft.client.renderer.FogParameters;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
#else
|
#else
|
||||||
import net.minecraft.client.renderer.FogParameters;
|
|
||||||
import net.minecraft.world.level.material.FogType;
|
import net.minecraft.world.level.material.FogType;
|
||||||
import org.joml.Vector4f;
|
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import net.minecraft.client.renderer.fog.FogData;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Mixin(FogRenderer.class)
|
@Mixin(FogRenderer.class)
|
||||||
public class MixinFogRenderer
|
public class MixinFogRenderer
|
||||||
{
|
{
|
||||||
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
|
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
|
||||||
|
@Unique
|
||||||
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
||||||
|
@Unique
|
||||||
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER == MC_1_17_1 || MC_VER == MC_1_18_2
|
#if MC_VER < MC_1_19_2
|
||||||
@Inject(at = @At("RETURN"),
|
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
|
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback)
|
||||||
remap = false)
|
|
||||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float partTick, CallbackInfo callback)
|
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
@Inject(at = @At("RETURN"),
|
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
|
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
|
||||||
remap = true)
|
#elif MC_VER < MC_1_21_6
|
||||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float partTick, CallbackInfo callback)
|
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
|
||||||
|
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
|
||||||
#else
|
#else
|
||||||
@Inject(at = @At("RETURN"),
|
@Unique
|
||||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;Lorg/joml/Vector4f;FZF)Lnet/minecraft/client/renderer/FogParameters;",
|
private static void unused()
|
||||||
remap = true, cancellable = true)
|
|
||||||
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float partTick, CallbackInfoReturnable<FogParameters> callback)
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
#if MC_VER < MC_1_21_6
|
||||||
|
boolean cancelFog = cancelFog(camera, fogMode);
|
||||||
|
#elif MC_VER < MC_1_21_6
|
||||||
|
boolean cancelFog = cancelFog(camera);
|
||||||
|
#else
|
||||||
|
boolean cancelFog = cancelFog();
|
||||||
|
#endif
|
||||||
|
|
||||||
Entity entity = camera.getEntity();
|
if (cancelFog)
|
||||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
|
||||||
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
|
|
||||||
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
|
||||||
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
|
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
@@ -90,12 +110,77 @@ public class MixinFogRenderer
|
|||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
||||||
#else
|
#elif MC_VER < MC_1_21_6
|
||||||
callback.setReturnValue(FogParameters.NO_FOG);
|
callback.setReturnValue(FogParameters.NO_FOG);
|
||||||
|
#else
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
#else
|
||||||
|
|
||||||
|
// In MC's FogRenderer they clamp the "renderDistanceEnd" fog field to the render distance,
|
||||||
|
// which prevents us from disabling the vanilla fog.
|
||||||
|
// This mixin fires after they set the "renderDistanceEnd" so we can change it.
|
||||||
|
@WrapOperation(
|
||||||
|
method = "setupFog",
|
||||||
|
at = @At(
|
||||||
|
value = "FIELD",
|
||||||
|
target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F",
|
||||||
|
opcode = org.objectweb.asm.Opcodes.PUTFIELD
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private void onSetRenderDistanceEnd(FogData instance, float value, Operation<Void> original)
|
||||||
|
{
|
||||||
|
if (cancelFog())
|
||||||
|
{
|
||||||
|
instance.environmentalStart = A_REALLY_REALLY_BIG_VALUE;
|
||||||
|
instance.environmentalEnd = A_EVEN_LARGER_VALUE;
|
||||||
|
|
||||||
|
instance.renderDistanceStart = A_REALLY_REALLY_BIG_VALUE;
|
||||||
|
instance.renderDistanceEnd = A_EVEN_LARGER_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always call the original with the modified or original value
|
||||||
|
original.call(instance, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
private static boolean cancelFog(Camera camera, FogMode fogMode)
|
||||||
|
#else
|
||||||
|
private static boolean cancelFog()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
|
#else
|
||||||
|
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||||
|
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||||
|
|
||||||
|
boolean cancelFog = !isSpecialFog;
|
||||||
|
cancelFog = cancelFog && cameraNotInFluid;
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
cancelFog = cancelFog && (fogMode == FogMode.FOG_TERRAIN);
|
||||||
|
#endif
|
||||||
|
cancelFog = cancelFog && !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial();
|
||||||
|
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||||
|
|
||||||
|
return cancelFog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
private static boolean cameraNotInFluid(Camera camera)
|
private static boolean cameraNotInFluid(Camera camera)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
@@ -110,4 +195,5 @@ public class MixinFogRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+111
-77
@@ -19,39 +19,53 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
#if MC_VER < MC_1_21_6
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
import com.mojang.math.Matrix4f;
|
|
||||||
#else
|
|
||||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
|
||||||
import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy;
|
|
||||||
import net.minecraft.client.Camera;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
#endif
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.DeltaTracker;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Matrix4fc;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to mix in DH's rendering code
|
* This class is used to mix in DH's rendering code
|
||||||
* before Minecraft starts rendering blocks.
|
* before Minecraft starts rendering blocks.
|
||||||
@@ -70,73 +84,66 @@ public class MixinLevelRenderer
|
|||||||
#endif
|
#endif
|
||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
|
||||||
@Inject(at = @At("HEAD"),
|
|
||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
|
#if MC_VER < MC_1_21_6
|
||||||
cancellable = true)
|
@Inject(at = @At("HEAD"), method = "renderSectionLayer", cancellable = true)
|
||||||
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#elif MC_VER < MC_1_19_4
|
|
||||||
@Inject(at = @At("HEAD"),
|
|
||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
|
|
||||||
cancellable = true)
|
|
||||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
|
||||||
#elif MC_VER < MC_1_20_2
|
|
||||||
@Inject(at = @At("HEAD"),
|
|
||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
|
||||||
cancellable = true)
|
|
||||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
|
||||||
#elif MC_VER < MC_1_20_6
|
|
||||||
@Inject(at = @At("HEAD"),
|
|
||||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
|
||||||
cancellable = true)
|
|
||||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
|
||||||
#else
|
#else
|
||||||
@Inject(at = @At("HEAD"),
|
@Inject(at = @At("HEAD"), method = "renderLevel", cancellable = true)
|
||||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
private void onRenderLevel(GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker, boolean renderBlockOutline, Camera camera, Matrix4f positionMatrix, Matrix4f projectionMatrix, GpuBufferSlice gpuBufferSlice, Vector4f skyColor, boolean thinFog, CallbackInfo callback)
|
||||||
cancellable = true)
|
#endif
|
||||||
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
#if MC_VER == MC_1_16_5
|
#if MC_VER < MC_1_21_6
|
||||||
// get the matrices from the OpenGL fixed pipeline
|
// MC combined the model view and projection matricies
|
||||||
float[] mcProjMatrixRaw = new float[16];
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
|
||||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
|
||||||
mcProjectionMatrix.transpose();
|
|
||||||
|
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
|
||||||
|
|
||||||
#elif MC_VER <= MC_1_20_4
|
|
||||||
// get the matrices directly from MC
|
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
|
||||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
|
||||||
#else
|
#else
|
||||||
// get the matrices from neoForge's render event.
|
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
// We can't call the renderer there because we don't have access to the level that's being rendered
|
|
||||||
Mat4f mcModelViewMatrix = NeoforgeClientProxy.currentModelViewMatrix;
|
|
||||||
Mat4f mcProjectionMatrix = NeoforgeClientProxy.currentProjectionMatrix;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//LOGGER.info("\n\n" +
|
||||||
|
// "Level Mixin\n" +
|
||||||
|
// "Mc MVM: \n" + ClientApi.RENDER_STATE.mcModelViewMatrix.toString() + "\n" +
|
||||||
|
// "Mc Proj: \n" + ClientApi.RENDER_STATE.mcProjectionMatrix.toString()
|
||||||
|
//);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float frameTime;
|
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER < MC_1_21_1
|
||||||
frameTime = Minecraft.getInstance().getFrameTime();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getFrameTime();
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||||
#else
|
#else
|
||||||
frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
|
||||||
|
// only crash during development
|
||||||
|
if (ModInfo.IS_DEV_BUILD)
|
||||||
|
{
|
||||||
|
ClientApi.RENDER_STATE.canRenderOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
// render LODs
|
// render LODs
|
||||||
if (renderType.equals(RenderType.solid()))
|
if (renderType.equals(RenderType.solid()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level),
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime);
|
||||||
}
|
}
|
||||||
else if (renderType.equals(RenderType.translucent()))
|
else if (renderType.equals(RenderType.translucent()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
ClientApi.INSTANCE.renderDeferredLodsForShaders(ClientLevelWrapper.getWrapper(this.level),
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render fade
|
// render fade
|
||||||
@@ -146,21 +153,22 @@ public class MixinLevelRenderer
|
|||||||
if (renderType.equals(RenderType.cutout()))
|
if (renderType.equals(RenderType.cutout()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderFadeOpaque(
|
ClientApi.INSTANCE.renderFadeOpaque(
|
||||||
mcModelViewMatrix,
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
mcProjectionMatrix,
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
frameTime,
|
ClientApi.RENDER_STATE.frameTime,
|
||||||
ClientLevelWrapper.getWrapper(this.level)
|
ClientLevelWrapper.getWrapper(this.level)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (renderType.equals(RenderType.tripwire()))
|
else if (renderType.equals(RenderType.tripwire()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderFade(
|
ClientApi.INSTANCE.renderFade(
|
||||||
mcModelViewMatrix,
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
mcProjectionMatrix,
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
frameTime,
|
ClientApi.RENDER_STATE.frameTime,
|
||||||
ClientLevelWrapper.getWrapper(this.level)
|
ClientLevelWrapper.getWrapper(this.level)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||||
{
|
{
|
||||||
@@ -169,4 +177,30 @@ public class MixinLevelRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_6
|
||||||
|
|
||||||
|
// formerly handled in renderChunkLayer()
|
||||||
|
|
||||||
|
#else
|
||||||
|
@Inject(at = @At("HEAD"), method = "prepareChunkRenders", cancellable = true)
|
||||||
|
private void renderChunkLayer(Matrix4fc modelViewMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||||
|
{
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
|
||||||
|
|
||||||
|
// only crash during development
|
||||||
|
if (ModInfo.IS_DEV_BUILD)
|
||||||
|
{
|
||||||
|
ClientApi.RENDER_STATE.canRenderOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level),
|
||||||
|
ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||||
|
ClientApi.RENDER_STATE.mcProjectionMatrix,
|
||||||
|
ClientApi.RENDER_STATE.frameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-22
@@ -19,17 +19,12 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -37,30 +32,33 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
@Mixin(LightTexture.class)
|
@Mixin(LightTexture.class)
|
||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private NativeImage lightPixels;
|
private NativeImage lightPixels;
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
|
@Shadow
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Final
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
private TextureTarget target;
|
||||||
{
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
|
||||||
if (mc == null || mc.getWrappedClientLevel() == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private GpuTexture texture;
|
||||||
|
#endif
|
||||||
|
|
||||||
@Shadow @Final private TextureTarget target;
|
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
@@ -70,9 +68,17 @@ public class MixinLightTexture
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
|
#elif MC_VER < MC_1_21_5
|
||||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||||
|
#else
|
||||||
|
GlTexture glTexture = (GlTexture) this.texture;
|
||||||
|
MinecraftRenderWrapper.INSTANCE.setLightmapId(glTexture.glId(), clientLevel);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -76,14 +76,13 @@ public class MixinMinecraft
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
Minecraft.getInstance().setScreen(new UpdateModScreen(
|
Minecraft.getInstance().setScreen(new UpdateModScreen(
|
||||||
// TODO: Change to runnable, instead of tittle screen
|
// TODO: Change to runnable, instead of tittle screen
|
||||||
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
||||||
versionId
|
versionId
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// info instead of error since this can be ignored and probably just means
|
// info instead of error since this can be ignored and probably just means
|
||||||
// there isn't a new DH version available
|
// there isn't a new DH version available
|
||||||
|
|||||||
+6
@@ -1,6 +1,8 @@
|
|||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
#endif
|
||||||
import com.mojang.blaze3d.platform.TextureUtil;
|
import com.mojang.blaze3d.platform.TextureUtil;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -15,6 +17,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
@Mixin(TextureUtil.class)
|
@Mixin(TextureUtil.class)
|
||||||
public class MixinTextureUtil
|
public class MixinTextureUtil
|
||||||
{
|
{
|
||||||
|
// TODO fix for MC 1.21.5+
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
|
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
|
||||||
private static void setLodBias(int target, int pname, float param)
|
private static void setLodBias(int target, int pname, float param)
|
||||||
@@ -27,5 +32,6 @@ public class MixinTextureUtil
|
|||||||
GlStateManager._texParameter(target, pname, biasValue);
|
GlStateManager._texParameter(target, pname, biasValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-15
@@ -1,35 +1,27 @@
|
|||||||
package com.seibel.distanthorizons.neoforge.mixins.server;
|
package com.seibel.distanthorizons.neoforge.mixins.server;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_4
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
/**
|
@Mixin(Entity.class)
|
||||||
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
|
|
||||||
* This is just a dummy class/mixin to make the compiler happy.
|
|
||||||
*
|
|
||||||
* @see MixinUtilBackgroundThread
|
|
||||||
*/
|
|
||||||
@Mixin(Util.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
|
|
||||||
public class MixinLevelTicks<T>
|
public class MixinLevelTicks<T>
|
||||||
{
|
{
|
||||||
|
// dummy mixin to make the loader happy
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
||||||
|
|
||||||
import net.minecraft.world.ticks.LevelTicks;
|
import net.minecraft.world.ticks.LevelTicks;
|
||||||
import net.minecraft.world.ticks.ScheduledTick;
|
import net.minecraft.world.ticks.ScheduledTick;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(LevelTicks.class)
|
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
||||||
public class MixinLevelTicks<T>
|
public class MixinLevelTicks<T>
|
||||||
{
|
{
|
||||||
// TODO put in a common location
|
// TODO put in a common location
|
||||||
@@ -39,7 +31,7 @@ public class MixinLevelTicks<T>
|
|||||||
|
|
||||||
|
|
||||||
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
||||||
private void schedule(ScheduledTick<T> tick, CallbackInfo ci)
|
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
||||||
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
||||||
@@ -50,4 +42,5 @@ public class MixinLevelTicks<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ loaderVersion = "*" # // mandatory. Allow all forge versions as we are definding
|
|||||||
license = "LGPL"
|
license = "LGPL"
|
||||||
issueTrackerURL = "${issues}"
|
issueTrackerURL = "${issues}"
|
||||||
|
|
||||||
|
# https://docs.neoforged.net/docs/gettingstarted/modfiles/#neoforgemodstoml
|
||||||
|
|
||||||
|
|
||||||
[[mods]] #//mandatory
|
[[mods]] #//mandatory
|
||||||
modId = "distanthorizons" #//mandatory
|
modId = "distanthorizons" #//mandatory
|
||||||
@@ -32,4 +34,11 @@ issueTrackerURL = "${issues}"
|
|||||||
type = "required"
|
type = "required"
|
||||||
versionRange = "${compatible_forgemc_versions}" # Where we set what version of mc it is avalible for
|
versionRange = "${compatible_forgemc_versions}" # Where we set what version of mc it is avalible for
|
||||||
ordering = "NONE"
|
ordering = "NONE"
|
||||||
side = "BOTH"
|
side = "BOTH"
|
||||||
|
|
||||||
|
[[dependencies.distanthorizons]]
|
||||||
|
modId = "neoforge"
|
||||||
|
type = "required"
|
||||||
|
versionRange = "${neoforge_version_range}"
|
||||||
|
ordering = "NONE"
|
||||||
|
side = "BOTH"
|
||||||
|
|||||||
@@ -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.
@@ -0,0 +1,110 @@
|
|||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import requests
|
||||||
|
import tarfile
|
||||||
|
import zipfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def get_platform_specific_filename():
|
||||||
|
system = platform.system()
|
||||||
|
machine = platform.machine()
|
||||||
|
|
||||||
|
if system == "Darwin":
|
||||||
|
if machine == "arm64":
|
||||||
|
return "apple-codesign-*-aarch64-apple-darwin.tar.gz"
|
||||||
|
else:
|
||||||
|
return "apple-codesign-*-x86_64-apple-darwin.tar.gz"
|
||||||
|
elif system == "Linux":
|
||||||
|
if machine == "aarch64":
|
||||||
|
return "apple-codesign-*-aarch64-unknown-linux-musl.tar.gz"
|
||||||
|
else:
|
||||||
|
return "apple-codesign-*-x86_64-unknown-linux-musl.tar.gz"
|
||||||
|
elif system == "Windows":
|
||||||
|
if machine.endswith("64"):
|
||||||
|
return "apple-codesign-*-x86_64-pc-windows-msvc.zip"
|
||||||
|
else:
|
||||||
|
return "apple-codesign-*-i686-pc-windows-msvc.zip"
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unsupported platform: {system} {machine}")
|
||||||
|
|
||||||
|
|
||||||
|
def download_and_unpack():
|
||||||
|
dest_dir = Path("./apple-codesign")
|
||||||
|
|
||||||
|
repo_url = "https://api.github.com/repos/indygreg/apple-platform-rs/releases/latest"
|
||||||
|
dest_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# Fetch the latest release info from GitHub
|
||||||
|
print("Fetching latest release information...")
|
||||||
|
response = requests.get(repo_url)
|
||||||
|
response.raise_for_status()
|
||||||
|
release_data = response.json()
|
||||||
|
|
||||||
|
# Ensure release data has assets
|
||||||
|
if "assets" not in release_data:
|
||||||
|
raise Exception("Release data does not contain assets.")
|
||||||
|
|
||||||
|
# Determine the correct asset
|
||||||
|
platform_filename = get_platform_specific_filename()
|
||||||
|
asset = next((asset for asset in release_data["assets"] if asset["name"].startswith("apple-codesign-") and asset["name"].endswith(platform_filename.split("*")[-1])), None)
|
||||||
|
|
||||||
|
if not asset:
|
||||||
|
raise Exception(f"No matching asset found for platform: {platform_filename}")
|
||||||
|
|
||||||
|
# Download the archive
|
||||||
|
print(f"Downloading {asset['name']}...")
|
||||||
|
download_url = asset["browser_download_url"]
|
||||||
|
archive_path = dest_dir / asset["name"]
|
||||||
|
|
||||||
|
with requests.get(download_url, stream=True) as r:
|
||||||
|
r.raise_for_status()
|
||||||
|
with open(archive_path, "wb") as f:
|
||||||
|
for chunk in r.iter_content(chunk_size=8192):
|
||||||
|
f.write(chunk)
|
||||||
|
|
||||||
|
print(f"Downloaded to {archive_path}")
|
||||||
|
|
||||||
|
# Extract the archive
|
||||||
|
print("Extracting archive...")
|
||||||
|
temp_extract_dir = dest_dir / "temp_extract"
|
||||||
|
temp_extract_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
if archive_path.suffix == ".zip":
|
||||||
|
with zipfile.ZipFile(archive_path, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(temp_extract_dir)
|
||||||
|
elif archive_path.suffixes[-2:] == [".tar", ".gz"]:
|
||||||
|
with tarfile.open(archive_path, "r:gz") as tar_ref:
|
||||||
|
tar_ref.extractall(temp_extract_dir)
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unknown archive format: {archive_path}")
|
||||||
|
|
||||||
|
# Move contents of the root directory inside the archive to dest_dir
|
||||||
|
root_dir = next(temp_extract_dir.iterdir()) # Assuming only one root directory
|
||||||
|
for item in root_dir.iterdir():
|
||||||
|
target_path = dest_dir / item.name
|
||||||
|
if target_path.exists():
|
||||||
|
if target_path.is_dir():
|
||||||
|
os.rmdir(target_path)
|
||||||
|
else:
|
||||||
|
os.remove(target_path)
|
||||||
|
item.rename(target_path)
|
||||||
|
|
||||||
|
# Clean up temporary directories
|
||||||
|
for item in temp_extract_dir.iterdir():
|
||||||
|
if item.is_dir():
|
||||||
|
os.rmdir(item)
|
||||||
|
temp_extract_dir.rmdir()
|
||||||
|
|
||||||
|
print(f"Extracted to {dest_dir}")
|
||||||
|
|
||||||
|
# Clean up the archive
|
||||||
|
os.remove(archive_path)
|
||||||
|
print(f"Removed archive {archive_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
download_and_unpack()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import sys
|
||||||
|
import lief
|
||||||
|
import subprocess
|
||||||
|
import download_codesign
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Parse the input binary & xit if binary is invalid
|
||||||
|
output_path = sys.argv[1]
|
||||||
|
binary = lief.parse(sys.stdin.buffer.read())
|
||||||
|
if binary is None:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Remove signature from Mac binaries
|
||||||
|
if isinstance(binary, lief.MachO.Binary):
|
||||||
|
binary.remove_signature()
|
||||||
|
|
||||||
|
# Write the modified binary to the output path
|
||||||
|
binary.write(output_path)
|
||||||
|
|
||||||
|
# Sign Mac binaries (required to make them usable because apple)
|
||||||
|
if isinstance(binary, lief.MachO.Binary):
|
||||||
|
print(f"Signing {output_path}...")
|
||||||
|
|
||||||
|
# Check if the Apple code-signing files are available, if not, download them
|
||||||
|
if not Path("./apple-codesign/COPYING").exists():
|
||||||
|
download_codesign.download_and_unpack()
|
||||||
|
|
||||||
|
# Run the code-signing process
|
||||||
|
sign_process = subprocess.Popen(["./apple-codesign/rcodesign", "sign", output_path], shell=False,
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
sign_process.wait()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\activate
|
||||||
|
pip install -r requirements.txt
|
||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
python -m venv .venv
|
||||||
|
. ./.venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user