Compare commits
168 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c8b3f3cda | |||
| a9a6a19307 | |||
| 208fc69eb7 | |||
| eb1a062934 | |||
| 132251341f | |||
| 2bac5f933a | |||
| 2e565aa83a | |||
| 4e9d0f4861 | |||
| 7216b193e8 | |||
| c33a5bf814 | |||
| 97756a5196 | |||
| 377f7d23e3 | |||
| 7005202384 | |||
| 99e8f57bac | |||
| afddf4168e | |||
| fbffdc0c9f | |||
| e6d3647490 | |||
| 13363ff363 | |||
| 7f98e4b1eb | |||
| 408460b0ae | |||
| b69ef5835d | |||
| 0428fa0912 | |||
| 9f3124fa56 | |||
| fbbdab73c6 | |||
| ee9441c521 | |||
| a9e0fd5d9b | |||
| 98464889ca | |||
| eed5fd60c6 | |||
| ac43cd5496 | |||
| 1f16a7c808 | |||
| 39e4c70754 | |||
| 82eb27af4c | |||
| 07a0779ca4 | |||
| 2adba02a38 | |||
| 9dd76db3fc | |||
| 97dacf2429 | |||
| 1c189e162a | |||
| f7a0fff869 | |||
| 2f985d0926 | |||
| 2a3c544fba | |||
| 09d133b994 | |||
| 26a4223ecf | |||
| e2943fdcaf | |||
| f1053251b4 | |||
| be1dcaf43c | |||
| a899d988fc | |||
| 06b5b2c514 | |||
| 864a19b79f | |||
| 8974323406 | |||
| 46c9e0103a | |||
| 02203466ed | |||
| 87b22ea1cc | |||
| d26327a930 | |||
| 469d2bdcb7 | |||
| 5516603a0c | |||
| b737adc3da | |||
| f3a8afeee3 | |||
| a4501f86e9 | |||
| 095fff96ff | |||
| a23211d061 | |||
| b57ea41686 | |||
| 62fb5ffb73 | |||
| 99c713967b | |||
| 9f3de07bd8 | |||
| cd74117de3 | |||
| e7d7033548 | |||
| 34db7c9dac | |||
| 272841aae9 | |||
| 389b09a5cd | |||
| 84bd876c71 | |||
| 7e45051ffd | |||
| 5570f3a313 | |||
| f4e71f7012 | |||
| 601d4e6e3a | |||
| a12092c1a1 | |||
| 94ad118c5d | |||
| 48e2978438 | |||
| 96b4c1a9e8 | |||
| cc4a69c10c | |||
| 7293677ddb | |||
| 0f2ff20375 | |||
| 7706240acb | |||
| 4cf48fd997 | |||
| 2708c1ee11 | |||
| ebb0f6ebad | |||
| 2c263a2549 | |||
| 955524c632 | |||
| 564e0d3263 | |||
| c533b2e8ea | |||
| 6073d8122a | |||
| 71ca26bba9 | |||
| 75a51be28c | |||
| a66e4ba157 | |||
| 55d5bca76d | |||
| f81026c707 | |||
| e86af817e0 | |||
| e0fd2b2f7a | |||
| f2b9e428d3 | |||
| 5b2497b9d4 | |||
| e78424def4 | |||
| e2c94de6e6 | |||
| daa3caf684 | |||
| 5991aa42d9 | |||
| ff6a5aae69 | |||
| 80d9b4540b | |||
| 4998991ebe | |||
| 14343569fe | |||
| be6cc5ff4e | |||
| 0ad3391bea | |||
| 582d998e2e | |||
| c00ee26075 | |||
| 4c9f70a52f | |||
| 29481bc123 | |||
| e274c9e004 | |||
| 73988f0308 | |||
| c4a9e7a2a7 | |||
| af6dca6e5e | |||
| a49720a221 | |||
| 12a66e70c9 | |||
| 00d8aa356b | |||
| d40d94a565 | |||
| c1f798793e | |||
| 8fe4ad454c | |||
| 17022f2df2 | |||
| 7fa4bc35f6 | |||
| 85df9c5ef4 | |||
| 45d4f390a9 | |||
| e7b60b7562 | |||
| 2615177907 | |||
| a83d7e2a26 | |||
| 8a2182e238 | |||
| d45455092c | |||
| da18469fd4 | |||
| 6b5bae9bee | |||
| e29a7786e4 | |||
| 55a837ca5e | |||
| 94cba6cf67 | |||
| 294685df00 | |||
| 2642b7a9a4 | |||
| 45594e4e47 | |||
| 54cd1a2e48 | |||
| a20fb982ec | |||
| 184d61e637 | |||
| 06ea56767f | |||
| 1f6e137759 | |||
| c7cf7885ae | |||
| 8e98444887 | |||
| 9bfe2e8233 | |||
| 21f4adc769 | |||
| 3b10ca5809 | |||
| 6cc8284747 | |||
| 6254f7156f | |||
| 0fa03701a4 | |||
| 49125cae47 | |||
| 3298857d0c | |||
| d939cbeb96 | |||
| 54d254be73 | |||
| d433fdea62 | |||
| ffa1c54ff3 | |||
| 019ac6dec3 | |||
| 08d3da47f4 | |||
| 348ac2b734 | |||
| fe014b4985 | |||
| b7f6f3b900 | |||
| 3c76ed71d8 | |||
| 5de1998913 | |||
| 05c0f030cb | |||
| bd85329589 |
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# use Eclipse's JDK
|
# use Eclipse's JDK
|
||||||
# The ci should always use a unix(-like) OS to work
|
# The ci should always use a unix(-like) OS to work
|
||||||
image: eclipse-temurin:17
|
image: eclipse-temurin:21
|
||||||
|
|
||||||
# all stages need to be defined here
|
# all stages need to be defined here
|
||||||
# TODO: Make stages depend on what is in versionProperties
|
# TODO: Make stages depend on what is in versionProperties
|
||||||
@@ -30,7 +30,7 @@ build:
|
|||||||
stage: build
|
stage: build
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4"]
|
- 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"]
|
||||||
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/;
|
||||||
|
|||||||
+93
-86
@@ -2,16 +2,18 @@ plugins {
|
|||||||
id "java"
|
id "java"
|
||||||
|
|
||||||
// Plugin to put dependencies inside our final jar
|
// Plugin to put dependencies inside our final jar
|
||||||
id "com.github.johnrengelman.shadow" version '7.1.2' 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.6"
|
id "io.github.pacifistmc.forgix" version "1.2.9"
|
||||||
|
|
||||||
// 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.5-SNAPSHOT" apply false
|
id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false
|
||||||
|
|
||||||
|
id 'xyz.wagyourtail.jvmdowngrader' version '0.9.1' apply true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -27,17 +29,17 @@ def writeBuildGradlePredefine(List<String> mcVers, int mcIndex)
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append("# DON'T TOUCH THIS FILE, This is handled by the build script\n");
|
sb.append("# DON'T TOUCH THIS FILE, This is handled by the build script\n");
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < mcVers.size(); i++)
|
for (int i = 0; i < mcVers.size(); i++)
|
||||||
{
|
{
|
||||||
String verStr = mcVers[i].replace(".", "_");
|
String verStr = mcVers[i].replace(".", "_");
|
||||||
sb.append("MC_" + verStr + "=" + i.toString() + "\n");
|
sb.append("MC_" + verStr + "=" + i.toString() + "\n");
|
||||||
|
|
||||||
if (mcIndex == i)
|
if (mcIndex == i)
|
||||||
sb.append("MC_VER=" + i.toString() + "\n");
|
sb.append("MC_VER=" + i.toString() + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if this is a development build
|
// Check if this is a development build
|
||||||
if (mod_version.toLowerCase().contains("dev"))
|
if (mod_version.toLowerCase().contains("dev"))
|
||||||
@@ -54,7 +56,7 @@ def writeBuildGradlePredefine(List<String> mcVers, int mcIndex)
|
|||||||
// Transfers the values set in settings.gradle to the rest of the project
|
// Transfers the values set in settings.gradle to the rest of the project
|
||||||
project.gradle.ext.getProperties().each { prop ->
|
project.gradle.ext.getProperties().each { prop ->
|
||||||
rootProject.ext.set(prop.key, prop.value)
|
rootProject.ext.set(prop.key, prop.value)
|
||||||
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
|
//println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
|
||||||
}
|
}
|
||||||
// Sets up manifold stuff
|
// Sets up manifold stuff
|
||||||
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
|
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
|
||||||
@@ -102,22 +104,20 @@ subprojects { p ->
|
|||||||
// Apply plugins
|
// Apply plugins
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
apply plugin: "com.github.johnrengelman.shadow"
|
apply plugin: "com.github.johnrengelman.shadow"
|
||||||
|
apply plugin: "xyz.wagyourtail.jvmdowngrader"
|
||||||
if (isMinecraftSubProject)
|
if (isMinecraftSubProject)
|
||||||
apply plugin: "systems.manifold.manifold-gradle-plugin"
|
apply plugin: "systems.manifold.manifold-gradle-plugin"
|
||||||
|
|
||||||
// Apply forge's loom
|
// Apply forge's loom
|
||||||
if (
|
if ( (findProject(":forge") && p == project(":forge")) || (findProject(":neoforge") && p == project(":neoforge")) )
|
||||||
(findProject(":forge") && p == project(":forge")) ||
|
apply plugin: "dev.architectury.loom"
|
||||||
(findProject(":neoforge") && p == project(":neoforge"))
|
|
||||||
)
|
|
||||||
apply plugin: "dev.architectury.loom"
|
|
||||||
|
|
||||||
|
|
||||||
// Set the manifold version (may not be required tough)
|
// Set the manifold version (may not be required tough)
|
||||||
manifold {
|
manifold {
|
||||||
manifoldVersion = rootProject.manifold_version
|
manifoldVersion = rootProject.manifold_version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// set up custom configurations (configurations are a way to handle dependencies)
|
// set up custom configurations (configurations are a way to handle dependencies)
|
||||||
configurations {
|
configurations {
|
||||||
@@ -173,12 +173,12 @@ subprojects { p ->
|
|||||||
//=====================//
|
//=====================//
|
||||||
// shared dependencies //
|
// shared dependencies //
|
||||||
//=====================//
|
//=====================//
|
||||||
|
|
||||||
// Manifold
|
// Manifold
|
||||||
if (isMinecraftSubProject) {
|
if (isMinecraftSubProject) {
|
||||||
annotationProcessor("systems.manifold:manifold-preprocessor:${rootProject.manifold_version}")
|
annotationProcessor("systems.manifold:manifold-preprocessor:${rootProject.manifold_version}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log4j
|
// Log4j
|
||||||
// TODO: Change to shadowMe later to work in the standalone jar
|
// TODO: Change to shadowMe later to work in the standalone jar
|
||||||
// We cannot do this now as it would break Quilt
|
// We cannot do this now as it would break Quilt
|
||||||
@@ -190,31 +190,43 @@ subprojects { p ->
|
|||||||
forgeShadowMe("org.joml:joml:${rootProject.joml_version}")
|
forgeShadowMe("org.joml:joml:${rootProject.joml_version}")
|
||||||
else
|
else
|
||||||
implementation("org.joml:joml:${rootProject.joml_version}")
|
implementation("org.joml:joml:${rootProject.joml_version}")
|
||||||
|
|
||||||
// JUnit tests
|
// JUnit tests
|
||||||
implementation("org.junit.jupiter:junit-jupiter:5.8.2")
|
implementation("org.junit.jupiter:junit-jupiter:5.8.2")
|
||||||
implementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
implementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
||||||
implementation("junit:junit:4.13")
|
implementation("junit:junit:4.13")
|
||||||
|
|
||||||
|
// FastUtil
|
||||||
|
// 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
|
||||||
|
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
|
||||||
|
|
||||||
|
|
||||||
|
// Compression
|
||||||
|
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
||||||
|
forgeShadowMe("org.tukaani:xz:${rootProject.xz_version}") // LZMA
|
||||||
|
|
||||||
|
// Sqlite Database
|
||||||
|
forgeShadowMe("org.xerial:sqlite-jdbc:${rootProject.sqlite_jdbc_version}")
|
||||||
|
|
||||||
|
|
||||||
// NightConfig (includes Toml & Json)
|
// NightConfig (includes Toml & Json)
|
||||||
// needs to be here and in core to prevent compiler errors
|
|
||||||
forgeShadowMe("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
|
forgeShadowMe("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
|
||||||
forgeShadowMe("com.electronwill.night-config:json:${rootProject.nightconfig_version}")
|
forgeShadowMe("com.electronwill.night-config:json:${rootProject.nightconfig_version}")
|
||||||
|
|
||||||
// Compression
|
// SVG (not needed atm)
|
||||||
// needs to be here and in core to prevent compiler errors
|
// forgeShadowMe("com.formdev:svgSalamander:${rootProject.svgSalamander_version}")
|
||||||
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
|
||||||
|
// Netty
|
||||||
|
// Breaks 1.16.5
|
||||||
|
//forgeShadowMe("io.netty:netty-all:${rootProject.netty_version}")
|
||||||
|
|
||||||
// Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing
|
// Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing
|
||||||
forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") {
|
forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") {
|
||||||
exclude group: "org.lwjgl", module: "lwjgl" // This module is imported by Minecraft so exclude it
|
exclude group: "org.lwjgl", module: "lwjgl" // This module is imported by Minecraft so exclude it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========================//
|
//==========================//
|
||||||
// conditional dependencies //
|
// conditional dependencies //
|
||||||
//==========================//
|
//==========================//
|
||||||
@@ -264,26 +276,55 @@ subprojects { p ->
|
|||||||
if (isMinecraftSubProject && p != project(":common")) {
|
if (isMinecraftSubProject && p != project(":common")) {
|
||||||
configurations.push(project.configurations.shadowCommon) // Shadow the common subproject
|
configurations.push(project.configurations.shadowCommon) // Shadow the common subproject
|
||||||
relocate "com.seibel.distanthorizons.common", "loaderCommon.${p.name}.com.seibel.distanthorizons.common" // Move the loader files to a different location
|
relocate "com.seibel.distanthorizons.common", "loaderCommon.${p.name}.com.seibel.distanthorizons.common" // Move the loader files to a different location
|
||||||
|
|
||||||
if (findProject(":fabricLike") && p != project(":fabricLike")) {
|
if (findProject(":fabricLike") && p != project(":fabricLike")) {
|
||||||
configurations.push(project.configurations.shadowFabricLike) // Shadow the fabricLike subproject
|
configurations.push(project.configurations.shadowFabricLike) // Shadow the fabricLike subproject
|
||||||
relocate "com.seibel.distanthorizons.fabriclike", "loaderCommon.${p.name}.com.seibel.distanthorizons.fabriclike" // Move the loader files to a different location
|
relocate "com.seibel.distanthorizons.fabriclike", "loaderCommon.${p.name}.com.seibel.distanthorizons.fabriclike" // Move the loader files to a different location
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def librariesLocation = "distanthorizons.libraries"
|
def librariesLocation = "DistantHorizons.libraries"
|
||||||
|
|
||||||
// SVG (not needed atm)
|
// LWJGL
|
||||||
// relocate "com.kitfox.svg", "${librariesLocation}.kitfox.svg"
|
// Only ever shadow the dependencies we use otherwise some stuff would break when running on an external client
|
||||||
|
relocate "org.lwjgl.system.jawt", "${librariesLocation}.lwjgl.system.jawt"
|
||||||
|
|
||||||
// Compression (LZ4)
|
// Compression (LZ4)
|
||||||
relocate "net.jpountz", "${librariesLocation}.jpountz"
|
relocate "net.jpountz", "${librariesLocation}.jpountz"
|
||||||
|
|
||||||
|
// Sqlite Database
|
||||||
|
//At the moment, there is a bug in this library which doesnt allow it to be relocated
|
||||||
|
// relocate "org.sqlite", "${librariesLocation}.sqlite"
|
||||||
|
|
||||||
|
// JOML
|
||||||
|
if (project.hasProperty("embed_joml") && embed_joml == "true")
|
||||||
|
relocate "org.joml", "${librariesLocation}.joml"
|
||||||
|
|
||||||
|
// NightConfig (includes Toml & Json)
|
||||||
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
|
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
|
||||||
|
|
||||||
|
// SVG (not needed atm)
|
||||||
|
// relocate "com.kitfox.svg", "${librariesLocation}.kitfox.svg"
|
||||||
|
|
||||||
|
// Netty
|
||||||
|
relocate "io.netty", "${librariesLocation}.netty"
|
||||||
|
|
||||||
mergeServiceFiles()
|
mergeServiceFiles()
|
||||||
}
|
}
|
||||||
// Using jar.finalizedBy(shadowJar) causes issues so we do this scuffed bypass
|
|
||||||
jar.dependsOn(shadowJar)
|
// For downgrading the Java version of our project to match the minimum Java version required by the selected Minecraft version.
|
||||||
|
task jarDowngrade(type: xyz.wagyourtail.jvmdg.gradle.task.DowngradeJar) {
|
||||||
|
inputFile = tasks.shadowJar.archiveFile
|
||||||
|
downgradeTo = JavaVersion.toVersion(rootProject.java_version as Integer)
|
||||||
|
archiveClassifier = "downgraded-${rootProject.java_version}"
|
||||||
|
}
|
||||||
|
task apiDowngrade(type: xyz.wagyourtail.jvmdg.gradle.task.ShadeJar) {
|
||||||
|
inputFile = jarDowngrade.archiveFile
|
||||||
|
downgradeTo = JavaVersion.toVersion(rootProject.java_version as Integer)
|
||||||
|
archiveClassifier = "downgraded-${rootProject.java_version}-shaded-java-api"
|
||||||
|
}
|
||||||
|
// We're using a custom downgrade task so we disable the original downgrade tasks
|
||||||
|
downgradeJar.enabled = false
|
||||||
|
shadeDowngradedApi.enabled = false
|
||||||
|
|
||||||
|
|
||||||
// Put stuff from gradle.properties into the mod info
|
// Put stuff from gradle.properties into the mod info
|
||||||
@@ -297,6 +338,7 @@ subprojects { p ->
|
|||||||
"fabric.mod.json",
|
"fabric.mod.json",
|
||||||
"quilt.mod.json",
|
"quilt.mod.json",
|
||||||
"META-INF/mods.toml",
|
"META-INF/mods.toml",
|
||||||
|
"META-INF/neoforge.mods.toml",
|
||||||
|
|
||||||
// The mixins for each of the loaders
|
// The mixins for each of the loaders
|
||||||
"DistantHorizons."+ p.name +".fabricLike.mixins.json"
|
"DistantHorizons."+ p.name +".fabricLike.mixins.json"
|
||||||
@@ -322,7 +364,7 @@ subprojects { p ->
|
|||||||
// TODO: Find something we can use so we can basically re-map only when the jar is shadowed and relocated
|
// TODO: Find something we can use so we can basically re-map only when the jar is shadowed and relocated
|
||||||
// println p.tasks.findByName('shadowJar')
|
// println p.tasks.findByName('shadowJar')
|
||||||
|
|
||||||
|
|
||||||
// These "hasProperty"'s are so that they can be passed through the cli (ie in the CI)
|
// These "hasProperty"'s are so that they can be passed through the cli (ie in the CI)
|
||||||
try {
|
try {
|
||||||
if (infoGitCommit == "null")
|
if (infoGitCommit == "null")
|
||||||
@@ -358,14 +400,14 @@ 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,
|
||||||
]
|
]
|
||||||
|
|
||||||
// replace any properties in the sub-projects with the values defined here
|
// replace any properties in the sub-projects with the values defined here
|
||||||
inputs.properties replaceProperties
|
inputs.properties replaceProperties
|
||||||
replaceProperties.put "project", project
|
replaceProperties.put "project", project
|
||||||
filesMatching(resourceTargets) {
|
filesMatching(resourceTargets) {
|
||||||
expand replaceProperties
|
expand replaceProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
intoTargets.each { target ->
|
intoTargets.each { target ->
|
||||||
if (file(target).exists()) {
|
if (file(target).exists()) {
|
||||||
copy {
|
copy {
|
||||||
@@ -433,11 +475,11 @@ allprojects { p ->
|
|||||||
|
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
apply plugin: "maven-publish"
|
apply plugin: "maven-publish"
|
||||||
|
|
||||||
archivesBaseName = rootProject.mod_name
|
archivesBaseName = rootProject.mod_name
|
||||||
version = project.name + "-" + rootProject.versionStr
|
version = 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
|
||||||
// and is used when bookmarking a page
|
// and is used when bookmarking a page
|
||||||
javadoc.title = rootProject.mod_name + "-" + project.name
|
javadoc.title = rootProject.mod_name + "-" + project.name
|
||||||
@@ -492,15 +534,17 @@ allprojects { p ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required for ModMenu
|
// VanillaGradle and Mixins in common
|
||||||
maven { url "https://maven.terraformersmc.com/" }
|
|
||||||
|
|
||||||
// Required for Mixins & VanillaGradle
|
|
||||||
maven { url "https://repo.spongepowered.org/maven/" }
|
maven { url "https://repo.spongepowered.org/maven/" }
|
||||||
|
|
||||||
// Required for Canvas (mod)
|
// Canvas mod
|
||||||
maven { url "https://maven.vram.io/" }
|
maven { url "https://maven.vram.io/" }
|
||||||
|
// ModMenu mod
|
||||||
|
maven { url "https://maven.terraformersmc.com/" }
|
||||||
|
|
||||||
|
// neoforge
|
||||||
|
maven { url "https://maven.neoforged.net/releases/" }
|
||||||
|
|
||||||
// These 3 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
|
// These 3 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
|
||||||
flatDir {
|
flatDir {
|
||||||
dirs "${rootDir}/mods/fabric"
|
dirs "${rootDir}/mods/fabric"
|
||||||
@@ -523,44 +567,6 @@ allprojects { p ->
|
|||||||
// TODO: If neoforged is ever needed, should we use that, or call it a forge mod?
|
// TODO: If neoforged is ever needed, should we use that, or call it a forge mod?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds some dependencies that are in vanilla but not in core
|
|
||||||
if (p == project(":core")) {
|
|
||||||
OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem;
|
|
||||||
|
|
||||||
// Set the OS lwjgl is using to the current os
|
|
||||||
project.ext.lwjglNatives = "natives-" + os.toFamilyName()
|
|
||||||
|
|
||||||
dependencies { // All of these dependencies are in Vanilla Minecraft, but we need to depend on it as we arent importing Minecraft in the core
|
|
||||||
// Imports most of lwjgl's libraries (well, only the ones that we need)
|
|
||||||
implementation platform("org.lwjgl:lwjgl-bom:${rootProject.lwjgl_version}") // TODO: Use Minecraft's version for lwjgl_version (which changes in nearly every version) instead of a hard defined version for all versions
|
|
||||||
|
|
||||||
// REMEMBER: Dont shadow stuff here, these are just the libs that are included in Minecraft so that the core can use
|
|
||||||
implementation "org.lwjgl:lwjgl"
|
|
||||||
implementation "org.lwjgl:lwjgl-assimp"
|
|
||||||
implementation "org.lwjgl:lwjgl-glfw"
|
|
||||||
implementation "org.lwjgl:lwjgl-openal"
|
|
||||||
implementation "org.lwjgl:lwjgl-opengl"
|
|
||||||
implementation "org.lwjgl:lwjgl-stb"
|
|
||||||
implementation "org.lwjgl:lwjgl-tinyfd"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
|
|
||||||
runtimeOnly "org.lwjgl:lwjgl-tinyfd::$lwjglNatives"
|
|
||||||
implementation "org.joml:joml:${rootProject.joml_version}"
|
|
||||||
|
|
||||||
|
|
||||||
// Some other dependencies
|
|
||||||
implementation("org.jetbrains:annotations:16.0.2")
|
|
||||||
implementation("com.google.code.findbugs:jsr305:3.0.2")
|
|
||||||
implementation("com.google.common:google-collect:0.5")
|
|
||||||
implementation("com.google.guava:guava:31.1-jre")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
task copyCommonLoaderResources(type: Copy) {
|
task copyCommonLoaderResources(type: Copy) {
|
||||||
from project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
|
from project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
into(file(p.file("build/resources/main")))
|
into(file(p.file("build/resources/main")))
|
||||||
@@ -582,16 +588,17 @@ allprojects { p ->
|
|||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
if (isMinecraftSubProject) {
|
if (isMinecraftSubProject) {
|
||||||
options.release = rootProject.java_version as Integer
|
options.release = rootProject.java_version as Integer // Neoforge complains without this
|
||||||
options.compilerArgs += ["-Xplugin:Manifold"]
|
options.compilerArgs += ["-Xplugin:Manifold"]
|
||||||
} else {
|
|
||||||
options.release = 8; // Core & Api should use Java 8 no matter what
|
|
||||||
//options.release = rootProject.java_version as Integer // But if you want to test some stuff, then this can be enabled
|
|
||||||
}
|
}
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the project's actual Java version (it's recommended to use this over the `options.release` method above)
|
||||||
java {
|
java {
|
||||||
|
sourceCompatibility = rootProject.java_version
|
||||||
|
targetCompatibility = rootProject.java_version
|
||||||
|
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
|
|
||||||
|
// temporary fix for broken spongepowered version
|
||||||
|
buildscript {
|
||||||
|
configurations.configureEach {
|
||||||
|
resolutionStrategy {
|
||||||
|
force 'org.spongepowered:vanillagradle:0.2.1-20240507.024226-82'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "org.spongepowered.gradle.vanilla" version "0.2.1-SNAPSHOT"
|
id "org.spongepowered.gradle.vanilla" version "0.2.1-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public abstract class AbstractModInitializer
|
|||||||
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
|
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||||
|
|
||||||
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandDispatcher = dispatcher; });
|
this.subscribeRegisterCommandsEvent(dispatcher -> this.commandDispatcher = dispatcher);
|
||||||
|
|
||||||
this.subscribeServerStartingEvent(server ->
|
this.subscribeServerStartingEvent(server ->
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -26,6 +26,6 @@ public class DependencySetupDoneCheck
|
|||||||
// TODO move to DependencySetup
|
// TODO move to DependencySetup
|
||||||
public static boolean isDone = false;
|
public static boolean isDone = false;
|
||||||
// TODO why is this here and what is its purpose?
|
// TODO why is this here and what is its purpose?
|
||||||
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> { return false; });
|
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-28
@@ -26,7 +26,7 @@ import java.util.function.Consumer;
|
|||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
@@ -102,33 +102,17 @@ public class McObjectConverter
|
|||||||
lodDirections = new EDhDirection[lodDirs.length];
|
lodDirections = new EDhDirection[lodDirs.length];
|
||||||
for (EDhDirection lodDir : lodDirs)
|
for (EDhDirection lodDir : lodDirs)
|
||||||
{
|
{
|
||||||
Direction dir;
|
Direction dir = switch (lodDir.name().toUpperCase()) {
|
||||||
switch (lodDir.name().toUpperCase())
|
case "DOWN" -> Direction.DOWN;
|
||||||
{
|
case "UP" -> Direction.UP;
|
||||||
case "DOWN":
|
case "NORTH" -> Direction.NORTH;
|
||||||
dir = Direction.DOWN;
|
case "SOUTH" -> Direction.SOUTH;
|
||||||
break;
|
case "WEST" -> Direction.WEST;
|
||||||
case "UP":
|
case "EAST" -> Direction.EAST;
|
||||||
dir = Direction.UP;
|
default -> null;
|
||||||
break;
|
};
|
||||||
case "NORTH":
|
|
||||||
dir = Direction.NORTH;
|
if (dir == null)
|
||||||
break;
|
|
||||||
case "SOUTH":
|
|
||||||
dir = Direction.SOUTH;
|
|
||||||
break;
|
|
||||||
case "WEST":
|
|
||||||
dir = Direction.WEST;
|
|
||||||
break;
|
|
||||||
case "EAST":
|
|
||||||
dir = Direction.EAST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dir = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == null)
|
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Invalid direction on init mapping: " + lodDir);
|
throw new IllegalArgumentException("Invalid direction on init mapping: " + lodDir);
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-22
@@ -32,6 +32,7 @@ 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.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
@@ -54,9 +55,6 @@ import java.util.HashSet;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This handles creating abstract wrapper objects.
|
* This handles creating abstract wrapper objects.
|
||||||
*
|
|
||||||
* @author James Seibel
|
|
||||||
* @version 2022-12-5
|
|
||||||
*/
|
*/
|
||||||
public class WrapperFactory implements IWrapperFactory
|
public class WrapperFactory implements IWrapperFactory
|
||||||
{
|
{
|
||||||
@@ -81,17 +79,56 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDhApiBiomeWrapper getBiomeWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException
|
||||||
|
{
|
||||||
|
if (!(levelWrapper instanceof ILevelWrapper))
|
||||||
|
{
|
||||||
|
throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException
|
||||||
|
{
|
||||||
|
if (!(levelWrapper instanceof ILevelWrapper))
|
||||||
|
{
|
||||||
|
throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); }
|
public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); }
|
||||||
|
@Override
|
||||||
|
public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper) // TODO is there a way we could get this without the levelWrapper? it isn't necessary but would clean up the code a bit
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBlockStateWrapper deserializeBlockStateWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BlockStateWrapper.deserialize(str, levelWrapper); }
|
public IBlockStateWrapper deserializeBlockStateWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BlockStateWrapper.deserialize(str, levelWrapper); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBlockStateWrapper getAirBlockStateWrapper() { return BlockStateWrapper.AIR; }
|
public IBlockStateWrapper getAirBlockStateWrapper() { return BlockStateWrapper.AIR; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashSet<IBlockStateWrapper> getRendererIgnoredBlocks(ILevelWrapper levelWrapper) { return BlockStateWrapper.getRendererIgnoredBlocks(levelWrapper); }
|
public HashSet<IBlockStateWrapper> getRendererIgnoredBlocks(ILevelWrapper levelWrapper) { return BlockStateWrapper.getRendererIgnoredBlocks(levelWrapper); }
|
||||||
|
@Override
|
||||||
|
public HashSet<IBlockStateWrapper> getRendererIgnoredCaveBlocks(ILevelWrapper levelWrapper) { return BlockStateWrapper.getRendererIgnoredCaveBlocks(levelWrapper); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetRendererIgnoredCaveBlocks() { BlockStateWrapper.clearRendererIgnoredCaveBlocks(); }
|
||||||
|
@Override
|
||||||
|
public void resetRendererIgnoredBlocksSet() { BlockStateWrapper.clearRendererIgnoredBlocks(); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,25 +155,23 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_21
|
||||||
else if (objectArray.length == 2)
|
else if (objectArray.length == 2)
|
||||||
{
|
{
|
||||||
// correct number of parameters from the API
|
// correct number of parameters from the API
|
||||||
|
|
||||||
// chunk
|
// chunk
|
||||||
if (!(objectArray[0] instanceof ChunkAccess))
|
if (!(objectArray[0] instanceof ChunkAccess chunk))
|
||||||
{
|
{
|
||||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||||
}
|
}
|
||||||
ChunkAccess chunk = (ChunkAccess) objectArray[0];
|
|
||||||
|
|
||||||
// level / light source
|
// level / light source
|
||||||
if (!(objectArray[1] instanceof Level))
|
if (!(objectArray[1] instanceof Level level))
|
||||||
{
|
{
|
||||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||||
}
|
}
|
||||||
// the level is needed for the DH level wrapper...
|
// the level is needed for the DH level wrapper...
|
||||||
Level level = (Level) objectArray[1];
|
|
||||||
// ...the LevelReader is needed for chunk lighting
|
// ...the LevelReader is needed for chunk lighting
|
||||||
LevelReader lightSource = level;
|
LevelReader lightSource = level;
|
||||||
|
|
||||||
@@ -183,7 +218,7 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
{
|
{
|
||||||
String[] expectedClassNames;
|
String[] expectedClassNames;
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_21
|
||||||
expectedClassNames = new String[]
|
expectedClassNames = new String[]
|
||||||
{
|
{
|
||||||
ChunkAccess.class.getName(),
|
ChunkAccess.class.getName(),
|
||||||
@@ -208,11 +243,10 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
// confirm the API level wrapper is also a Core wrapper
|
// confirm the API level wrapper is also a Core wrapper
|
||||||
if (!(levelWrapper instanceof ILevelWrapper))
|
if (!(levelWrapper instanceof ILevelWrapper coreLevelWrapper))
|
||||||
{
|
{
|
||||||
throw new ClassCastException("Unable to cast... only DH provided IDhApiLevelWrapper's can be used."); // TODO
|
throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"].");
|
||||||
}
|
}
|
||||||
ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -231,7 +265,7 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
|
|
||||||
Biome biome = (Biome) objectArray[0];
|
Biome biome = (Biome) objectArray[0];
|
||||||
return BiomeWrapper.getBiomeWrapper(biome, coreLevelWrapper);
|
return BiomeWrapper.getBiomeWrapper(biome, coreLevelWrapper);
|
||||||
#elif MC_VER <= MC_1_20_4
|
#elif MC_VER <= MC_1_21
|
||||||
if (!(objectArray[0] instanceof Holder) || !(((Holder<?>) objectArray[0]).value() instanceof Biome))
|
if (!(objectArray[0] instanceof Holder) || !(((Holder<?>) objectArray[0]).value() instanceof Biome))
|
||||||
{
|
{
|
||||||
throw new ClassCastException(createBiomeWrapperErrorMessage(objectArray));
|
throw new ClassCastException(createBiomeWrapperErrorMessage(objectArray));
|
||||||
@@ -254,7 +288,7 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
expectedClassNames = new String[] { Biome.class.getName() };
|
expectedClassNames = new String[] { Biome.class.getName() };
|
||||||
#elif MC_VER <= MC_1_20_4
|
#elif MC_VER <= MC_1_21
|
||||||
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
|
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
|
||||||
#else
|
#else
|
||||||
// See preprocessor comment in createChunkWrapper() for full documentation
|
// See preprocessor comment in createChunkWrapper() for full documentation
|
||||||
@@ -267,25 +301,23 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
public IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
public IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
// confirm the API level wrapper is also a Core wrapper
|
// confirm the API level wrapper is also a Core wrapper
|
||||||
if (!(levelWrapper instanceof ILevelWrapper))
|
if (!(levelWrapper instanceof ILevelWrapper coreLevelWrapper))
|
||||||
{
|
{
|
||||||
throw new ClassCastException("Unable to cast... only DH provided IDhApiLevelWrapper's can be used."); // TODO
|
throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"].");
|
||||||
}
|
}
|
||||||
ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_21
|
||||||
if (objectArray.length != 1)
|
if (objectArray.length != 1)
|
||||||
{
|
{
|
||||||
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
||||||
}
|
}
|
||||||
if (!(objectArray[0] instanceof BlockState))
|
if (!(objectArray[0] instanceof BlockState blockState))
|
||||||
{
|
{
|
||||||
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockState blockState = (BlockState) objectArray[0];
|
|
||||||
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
|
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
|
||||||
#else
|
#else
|
||||||
// See preprocessor comment in createChunkWrapper() for full documentation (not a typo, check createChunkWrapper()'s else statement for full documentation)
|
// See preprocessor comment in createChunkWrapper() for full documentation (not a typo, check createChunkWrapper()'s else statement for full documentation)
|
||||||
@@ -302,7 +334,7 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
|
|
||||||
#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
|
||||||
expectedClassNames = new String[] { Biome.class.getName() };
|
expectedClassNames = new String[] { Biome.class.getName() };
|
||||||
#elif MC_VER <= MC_1_20_4
|
#elif MC_VER <= MC_1_21
|
||||||
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
|
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
|
||||||
#else
|
#else
|
||||||
// See preprocessor comment in createChunkWrapper() for full documentation
|
// See preprocessor comment in createChunkWrapper() for full documentation
|
||||||
|
|||||||
+84
-48
@@ -32,8 +32,6 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
|
|
||||||
#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;
|
||||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||||
@@ -66,9 +64,13 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> WRAPPER_BY_BIOME = new ConcurrentHashMap<>();
|
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> WRAPPER_BY_BIOME = new ConcurrentHashMap<>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static final String EMPTY_STRING = "EMPTY";
|
public static final ConcurrentHashMap<String, BiomeWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public static final String EMPTY_BIOME_STRING = "EMPTY";
|
||||||
public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null);
|
public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null);
|
||||||
|
|
||||||
|
public static final String PLAINS_RESOURCE_LOCATION_STRING = "minecraft:plains";
|
||||||
|
|
||||||
/** keep track of broken biomes so we don't log every time */
|
/** keep track of broken biomes so we don't log every time */
|
||||||
private static final HashSet<String> brokenResourceLocationStrings = new HashSet<>();
|
private static final HashSet<String> brokenResourceLocationStrings = new HashSet<>();
|
||||||
|
|
||||||
@@ -131,7 +133,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
private BiomeWrapper()
|
private BiomeWrapper()
|
||||||
{
|
{
|
||||||
this.biome = null;
|
this.biome = null;
|
||||||
this.serialString = EMPTY_STRING;
|
this.serialString = EMPTY_BIOME_STRING;
|
||||||
this.hashCode = Objects.hash(this.serialString);
|
this.hashCode = Objects.hash(this.serialString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +148,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
{
|
{
|
||||||
if (this == EMPTY_WRAPPER)
|
if (this == EMPTY_WRAPPER)
|
||||||
{
|
{
|
||||||
return EMPTY_STRING;
|
return EMPTY_BIOME_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
@@ -193,22 +195,23 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
|
|
||||||
public String serialize(ILevelWrapper levelWrapper)
|
public String serialize(ILevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
if (this.serialString != null)
|
if (this.biome == null)
|
||||||
{
|
{
|
||||||
return this.serialString;
|
return EMPTY_BIOME_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// we can't generate a serial string if the level is null
|
// we can't generate a serial string if the level is null
|
||||||
if (levelWrapper == null)
|
if (levelWrapper == null)
|
||||||
{
|
{
|
||||||
if (!emptyLevelSerializeFailLogged)
|
if (!emptyLevelSerializeFailLogged)
|
||||||
{
|
{
|
||||||
emptyLevelSerializeFailLogged = true;
|
emptyLevelSerializeFailLogged = true;
|
||||||
LOGGER.warn("Unable to serialize biome: ["+this.biome+"] because the passed in level wrapper is null. Future errors won't be logged.");
|
LOGGER.warn("Unable to serialize biome: [" + this.biome + "] because the passed in level wrapper is null. Future errors of this type won't be logged.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return EMPTY_STRING;
|
return EMPTY_BIOME_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -248,70 +251,103 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
return this.serialString;
|
return this.serialString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO would it be worth while to cache these objects in a ConcurrentHashMap<string, IBiomeWrapper>?
|
||||||
public static IBiomeWrapper deserialize(String resourceLocationString, ILevelWrapper levelWrapper) throws IOException
|
public static IBiomeWrapper deserialize(String resourceLocationString, ILevelWrapper levelWrapper) throws IOException
|
||||||
{
|
{
|
||||||
if (resourceLocationString.equals(EMPTY_STRING))
|
// we need the final string for the concurrent hash map later
|
||||||
|
final String finalResourceStateString = resourceLocationString;
|
||||||
|
|
||||||
|
if (resourceLocationString.equals(EMPTY_BIOME_STRING))
|
||||||
{
|
{
|
||||||
if (!emptyStringWarningLogged)
|
if (!emptyStringWarningLogged)
|
||||||
{
|
{
|
||||||
emptyStringWarningLogged = true;
|
emptyStringWarningLogged = true;
|
||||||
LOGGER.warn("[" + EMPTY_STRING + "] biome string deserialized. This may mean the level was null when a save was attempted, a file saving error, or a biome saving error. Future errors will not be logged.");
|
LOGGER.warn("[" + EMPTY_BIOME_STRING + "] biome string deserialized. This may mean the level was null when a save was attempted, a file saving error, or a biome saving error. Future errors will not be logged.");
|
||||||
}
|
}
|
||||||
return EMPTY_WRAPPER;
|
return EMPTY_WRAPPER;
|
||||||
}
|
}
|
||||||
else if (resourceLocationString.trim().isEmpty() || resourceLocationString.equals(""))
|
else if (resourceLocationString.trim().isEmpty() || resourceLocationString.isEmpty())
|
||||||
{
|
{
|
||||||
LOGGER.warn("Null biome string deserialized.");
|
LOGGER.warn("Null biome string deserialized.");
|
||||||
return EMPTY_WRAPPER;
|
return EMPTY_WRAPPER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WRAPPER_BY_RESOURCE_LOCATION.containsKey(finalResourceStateString))
|
||||||
|
|
||||||
// parse the resource location
|
|
||||||
int separatorIndex = resourceLocationString.indexOf(":");
|
|
||||||
if (separatorIndex == -1)
|
|
||||||
{
|
{
|
||||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
return WRAPPER_BY_RESOURCE_LOCATION.get(finalResourceStateString);
|
||||||
}
|
}
|
||||||
ResourceLocation resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if no wrapper is found, default to the empty wrapper
|
||||||
|
BiomeWrapper foundWrapper = EMPTY_WRAPPER;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Level level = (Level)levelWrapper.getWrappedMcObject();
|
// parse the resource location
|
||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
int separatorIndex = resourceLocationString.indexOf(":");
|
||||||
|
if (separatorIndex == -1)
|
||||||
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);
|
|
||||||
#else
|
|
||||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
|
||||||
success = (unwrappedBiome != null);
|
|
||||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
{
|
||||||
if (!brokenResourceLocationStrings.contains(resourceLocationString))
|
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||||
{
|
|
||||||
brokenResourceLocationStrings.add(resourceLocationString);
|
|
||||||
LOGGER.warn("Unable to deserialize biome from string: [" + resourceLocationString + "]");
|
|
||||||
}
|
|
||||||
return EMPTY_WRAPPER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBiomeWrapper(biome, levelWrapper);
|
ResourceLocation resourceLocation;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||||
|
#else
|
||||||
|
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Level level = (Level) levelWrapper.getWrappedMcObject();
|
||||||
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
|
|
||||||
|
boolean success;
|
||||||
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
|
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||||
|
success = (biome != null);
|
||||||
|
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||||
|
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||||
|
success = (unwrappedBiome != null);
|
||||||
|
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||||
|
#else
|
||||||
|
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||||
|
success = (unwrappedBiome != null);
|
||||||
|
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
if (!brokenResourceLocationStrings.contains(resourceLocationString))
|
||||||
|
{
|
||||||
|
brokenResourceLocationStrings.add(resourceLocationString);
|
||||||
|
LOGGER.warn("Unable to deserialize biome from string: [" + resourceLocationString + "]");
|
||||||
|
}
|
||||||
|
return EMPTY_WRAPPER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foundWrapper = (BiomeWrapper) getBiomeWrapper(biome, levelWrapper);
|
||||||
|
return foundWrapper;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new IOException("Failed to deserialize the string [" + finalResourceStateString + "] into a BiomeWrapper: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
finally
|
||||||
{
|
{
|
||||||
throw new IOException("Failed to deserialize the string [" + resourceLocationString + "] into a BiomeWrapper: " + e.getMessage(), e);
|
WRAPPER_BY_RESOURCE_LOCATION.putIfAbsent(finalResourceStateString, foundWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+271
-115
@@ -19,7 +19,12 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||||
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.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
@@ -29,10 +34,13 @@ import net.minecraft.world.level.block.Block;
|
|||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.SoundType;
|
import net.minecraft.world.level.block.SoundType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
#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
|
||||||
@@ -65,15 +73,15 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
|
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
|
||||||
|
public static final ConcurrentHashMap<String, BlockStateWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static final String AIR_STRING = "AIR";
|
public static final String AIR_STRING = "AIR";
|
||||||
public static final BlockStateWrapper AIR = new BlockStateWrapper(null, null);
|
public static final BlockStateWrapper AIR = new BlockStateWrapper(null, null);
|
||||||
|
|
||||||
public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt";
|
public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt";
|
||||||
|
|
||||||
// TODO: Make this changeable through the config
|
|
||||||
public static final String[] RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS = { AIR_STRING, "minecraft:barrier", "minecraft:structure_void", "minecraft:light", "minecraft:tripwire" };
|
|
||||||
public static HashSet<IBlockStateWrapper> rendererIgnoredBlocks = null;
|
public static HashSet<IBlockStateWrapper> rendererIgnoredBlocks = 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> BrokenResourceLocations = new HashSet<>();
|
||||||
@@ -88,11 +96,16 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
private final int hashCode;
|
private final int hashCode;
|
||||||
/**
|
/**
|
||||||
* Cached opacity value, -1 if not populated. <br>
|
* Cached opacity value, -1 if not populated. <br>
|
||||||
* Should be between {@link IBlockStateWrapper#FULLY_OPAQUE} and {@link IBlockStateWrapper#FULLY_OPAQUE}
|
* Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE}
|
||||||
*/
|
*/
|
||||||
private int opacity = -1;
|
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 irisBlockMaterialId = 0;
|
private byte blockMaterialId = 0;
|
||||||
|
|
||||||
|
private final boolean isBeaconBlock;
|
||||||
|
private final boolean isBeaconBaseBlock;
|
||||||
|
private final boolean isGlassBlock;
|
||||||
|
private final Color mapColor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -125,16 +138,46 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
this.serialString = this.serialize(levelWrapper);
|
this.serialString = this.serialize(levelWrapper);
|
||||||
this.hashCode = Objects.hash(this.serialString);
|
this.hashCode = Objects.hash(this.serialString);
|
||||||
this.irisBlockMaterialId = this.calculateIrisBlockMaterialId();
|
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
||||||
|
|
||||||
//LOGGER.trace("Created BlockStateWrapper ["+this.serialString+"] for ["+blockState+"] with material ID ["+this.irisBlockMaterialId+"]");
|
String lowercaseSerial = this.serialString.toLowerCase();
|
||||||
|
boolean isBeaconBaseBlock = false;
|
||||||
|
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
||||||
|
{
|
||||||
|
String baseBlockName = LodUtil.BEACON_BASE_BLOCK_NAME_LIST.get(i);
|
||||||
|
if (lowercaseSerial.contains(baseBlockName))
|
||||||
|
{
|
||||||
|
isBeaconBaseBlock = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isBeaconBaseBlock = isBeaconBaseBlock;
|
||||||
|
this.isBeaconBlock = lowercaseSerial.contains("minecraft:beacon");
|
||||||
|
this.isGlassBlock = lowercaseSerial.contains("glass");
|
||||||
|
|
||||||
|
int mcColor = 0;
|
||||||
|
if (this.blockState != null)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_1
|
||||||
|
mcColor = this.blockState.getMaterial().getColor().col;
|
||||||
|
#else
|
||||||
|
mcColor = this.blockState.getMapColor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).col;
|
||||||
|
#endif
|
||||||
|
this.mapColor = ColorUtil.toColorObjRGB(mcColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.mapColor = new Color(0,0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOGGER.trace("Created BlockStateWrapper ["+this.serialString+"] for ["+blockState+"] with material ID ["+this.EDhApiBlockMaterialId+"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//====================//
|
||||||
// helper methods //
|
// LodBuilder methods //
|
||||||
//================//
|
//====================//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires a {@link ILevelWrapper} since {@link BlockStateWrapper#deserialize(String,ILevelWrapper)} also requires one.
|
* Requires a {@link ILevelWrapper} since {@link BlockStateWrapper#deserialize(String,ILevelWrapper)} also requires one.
|
||||||
@@ -148,37 +191,104 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
return rendererIgnoredBlocks;
|
return rendererIgnoredBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
||||||
|
baseIgnoredBlock.add(AIR_STRING);
|
||||||
|
rendererIgnoredBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper);
|
||||||
|
return rendererIgnoredBlocks;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Requires a {@link ILevelWrapper} since {@link BlockStateWrapper#deserialize(String,ILevelWrapper)} also requires one.
|
||||||
|
* This way the method won't accidentally be called before the deserialization can be completed.
|
||||||
|
*/
|
||||||
|
public static HashSet<IBlockStateWrapper> getRendererIgnoredCaveBlocks(ILevelWrapper levelWrapper)
|
||||||
|
{
|
||||||
|
// use the cached version if possible
|
||||||
|
if (rendererIgnoredCaveBlocks != null)
|
||||||
|
{
|
||||||
|
return rendererIgnoredCaveBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
||||||
|
baseIgnoredBlock.add(AIR_STRING);
|
||||||
|
rendererIgnoredCaveBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper);
|
||||||
|
return rendererIgnoredCaveBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearRendererIgnoredBlocks() { rendererIgnoredBlocks = null; }
|
||||||
|
public static void clearRendererIgnoredCaveBlocks() { rendererIgnoredCaveBlocks = null; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lod builder helpers //
|
||||||
|
|
||||||
|
private static HashSet<IBlockStateWrapper> getBlockWrappers(ConfigEntry<String> config, HashSet<String> baseResourceLocations, ILevelWrapper levelWrapper)
|
||||||
|
{
|
||||||
|
// get the base blocks
|
||||||
|
HashSet<String> blockStringList = new HashSet<>();
|
||||||
|
if (baseResourceLocations != null)
|
||||||
|
{
|
||||||
|
blockStringList.addAll(baseResourceLocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the config blocks
|
||||||
|
String ignoreBlockCsv = config.get();
|
||||||
|
if (ignoreBlockCsv != null)
|
||||||
|
{
|
||||||
|
blockStringList.addAll(List.of(ignoreBlockCsv.split(",")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return getBlockWrappers(blockStringList, levelWrapper);
|
||||||
|
}
|
||||||
|
private static HashSet<IBlockStateWrapper> getBlockWrappers(HashSet<String> blockResourceLocationSet, ILevelWrapper levelWrapper)
|
||||||
|
{
|
||||||
// deserialize each of the given resource locations
|
// deserialize each of the given resource locations
|
||||||
HashSet<IBlockStateWrapper> blockStateWrappers = new HashSet<>();
|
HashSet<IBlockStateWrapper> blockStateWrappers = new HashSet<>();
|
||||||
for (String blockResourceLocation : RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS)
|
for (String blockResourceLocation : blockResourceLocationSet)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BlockStateWrapper DefaultBlockStateToIgnore = (BlockStateWrapper) deserialize(blockResourceLocation, levelWrapper);
|
if (blockResourceLocation == null)
|
||||||
blockStateWrappers.add(DefaultBlockStateToIgnore);
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
if (DefaultBlockStateToIgnore == AIR)
|
continue;
|
||||||
|
}
|
||||||
|
String cleanedResourceLocation = blockResourceLocation.trim();
|
||||||
|
if (cleanedResourceLocation.length() == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add all possible blockstates (to account for light blocks with different light values and such)
|
|
||||||
List<BlockState> blockStatesToIgnore = DefaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates();
|
BlockStateWrapper defaultBlockStateToIgnore = (BlockStateWrapper) deserialize(cleanedResourceLocation, levelWrapper);
|
||||||
for (BlockState blockState : blockStatesToIgnore)
|
blockStateWrappers.add(defaultBlockStateToIgnore);
|
||||||
|
|
||||||
|
if (defaultBlockStateToIgnore != AIR)
|
||||||
{
|
{
|
||||||
BlockStateWrapper newBlockToIgnore = BlockStateWrapper.fromBlockState(blockState, levelWrapper);
|
// add all possible blockstates (to account for light blocks with different light values and such)
|
||||||
blockStateWrappers.add(newBlockToIgnore);
|
List<BlockState> blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates();
|
||||||
|
for (BlockState blockState : blockStatesToIgnore)
|
||||||
|
{
|
||||||
|
BlockStateWrapper newBlockToIgnore = BlockStateWrapper.fromBlockState(blockState, levelWrapper);
|
||||||
|
blockStateWrappers.add(newBlockToIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// air is a special case so it must be handled separately
|
||||||
|
blockStateWrappers.add(AIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
LOGGER.warn("Unable to deserialize rendererIgnoredBlock with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e);
|
LOGGER.warn("Unable to deserialize block with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unexpected error deserializing block with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rendererIgnoredBlocks = blockStateWrappers;
|
return blockStateWrappers;
|
||||||
return rendererIgnoredBlocks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -201,23 +311,23 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
int opacity;
|
int opacity;
|
||||||
if (this.isAir())
|
if (this.isAir())
|
||||||
{
|
{
|
||||||
opacity = FULLY_TRANSPARENT;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
||||||
}
|
}
|
||||||
else if (this.isLiquid() && !this.blockState.canOcclude())
|
else if (this.isLiquid() && !this.blockState.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 = FULLY_TRANSPARENT + 1;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1;
|
||||||
}
|
}
|
||||||
else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))
|
else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))
|
||||||
{
|
{
|
||||||
opacity = FULLY_TRANSPARENT;
|
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// default for all other blocks
|
// default for all other blocks
|
||||||
opacity = FULLY_OPAQUE;
|
opacity = LodUtil.BLOCK_FULLY_OPAQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,7 +396,17 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getIrisBlockMaterialId() { return this.irisBlockMaterialId; }
|
public boolean isBeaconBlock() { return this.isBeaconBlock; }
|
||||||
|
@Override
|
||||||
|
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
||||||
|
@Override
|
||||||
|
public boolean isGlassBlock() { return this.isGlassBlock; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getMapColor() { return this.mapColor; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getMaterialId() { return this.blockMaterialId; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return this.getSerialString(); }
|
public String toString() { return this.getSerialString(); }
|
||||||
@@ -339,103 +459,139 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
/** will only work if a level is currently loaded */
|
/** will only work if a level is currently loaded */
|
||||||
public static IBlockStateWrapper deserialize(String resourceStateString, ILevelWrapper levelWrapper) throws IOException
|
public static IBlockStateWrapper deserialize(String resourceStateString, ILevelWrapper levelWrapper) throws IOException
|
||||||
{
|
{
|
||||||
if (resourceStateString.equals(AIR_STRING) || resourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case
|
// we need the final string for the concurrent hash map later
|
||||||
|
final String finalResourceStateString = resourceStateString;
|
||||||
|
|
||||||
|
if (finalResourceStateString.equals(AIR_STRING) || finalResourceStateString.isEmpty()) // the empty string shouldn't normally happen, but just in case
|
||||||
{
|
{
|
||||||
return AIR;
|
return AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attempt to use the existing wrapper
|
||||||
|
if (WRAPPER_BY_RESOURCE_LOCATION.containsKey(finalResourceStateString))
|
||||||
// try to parse out the BlockState
|
|
||||||
String blockStatePropertiesString = null; // will be null if no properties were included
|
|
||||||
int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR);
|
|
||||||
if (stateSeparatorIndex != -1)
|
|
||||||
{
|
{
|
||||||
// blockstate properties found
|
return WRAPPER_BY_RESOURCE_LOCATION.get(finalResourceStateString);
|
||||||
blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex + STATE_STRING_SEPARATOR.length());
|
|
||||||
resourceStateString = resourceStateString.substring(0, stateSeparatorIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the resource location
|
|
||||||
int resourceSeparatorIndex = resourceStateString.indexOf(RESOURCE_LOCATION_SEPARATOR);
|
|
||||||
if (resourceSeparatorIndex == -1)
|
|
||||||
{
|
|
||||||
throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "].");
|
|
||||||
}
|
|
||||||
ResourceLocation resourceLocation = new ResourceLocation(resourceStateString.substring(0, resourceSeparatorIndex), resourceStateString.substring(resourceSeparatorIndex + 1));
|
|
||||||
|
|
||||||
|
|
||||||
|
// if no wrapper is found, default to air
|
||||||
// attempt to get the BlockState from all possible BlockStates
|
BlockStateWrapper foundWrapper = AIR;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// try to parse out the BlockState
|
||||||
#if MC_VER > MC_1_17_1
|
String blockStatePropertiesString = null; // will be null if no properties were included
|
||||||
// use the given level if possible, otherwise try using the currently loaded one
|
int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR);
|
||||||
Level level = (levelWrapper != null ? (Level)levelWrapper.getWrappedMcObject() : null);
|
if (stateSeparatorIndex != -1)
|
||||||
level = (level == null ? Minecraft.getInstance().level : level);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Block block;
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
|
||||||
block = Registry.BLOCK.get(resourceLocation);
|
|
||||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
|
||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
|
||||||
block = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).get(resourceLocation);
|
|
||||||
#else
|
|
||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
|
||||||
block = registryAccess.registryOrThrow(Registries.BLOCK).get(resourceLocation);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (block == null)
|
|
||||||
{
|
{
|
||||||
// shouldn't normally happen, but here to make the compiler happy
|
// blockstate properties found
|
||||||
if (!BrokenResourceLocations.contains(resourceLocation))
|
blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex + STATE_STRING_SEPARATOR.length());
|
||||||
{
|
resourceStateString = resourceStateString.substring(0, stateSeparatorIndex);
|
||||||
BrokenResourceLocations.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.");
|
|
||||||
}
|
// parse the resource location
|
||||||
return AIR;
|
int separatorIndex = resourceStateString.indexOf(RESOURCE_LOCATION_SEPARATOR);
|
||||||
|
if (separatorIndex == -1)
|
||||||
|
{
|
||||||
|
throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation resourceLocation;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
||||||
|
#else
|
||||||
|
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new IOException("No Resource Location found for the string: [" + resourceStateString + "] Error: [" + e.getMessage() + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// attempt to find the blockstate from all possibilities
|
|
||||||
BlockState foundState = null;
|
|
||||||
if (blockStatePropertiesString != null)
|
|
||||||
{
|
|
||||||
List<BlockState> possibleStateList = block.getStateDefinition().getPossibleStates();
|
|
||||||
for (BlockState possibleState : possibleStateList)
|
|
||||||
{
|
|
||||||
String possibleStatePropertiesString = serializeBlockStateProperties(possibleState);
|
|
||||||
if (possibleStatePropertiesString.equals(blockStatePropertiesString))
|
|
||||||
{
|
|
||||||
foundState = possibleState;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use the default if no state was found or given
|
// attempt to get the BlockState from all possible BlockStates
|
||||||
if (foundState == null)
|
try
|
||||||
{
|
{
|
||||||
if (blockStatePropertiesString != null)
|
|
||||||
|
#if MC_VER > MC_1_17_1
|
||||||
|
// use the given level if possible, otherwise try using the currently loaded one
|
||||||
|
Level level = (levelWrapper != null ? (Level) levelWrapper.getWrappedMcObject() : null);
|
||||||
|
level = (level == null ? Minecraft.getInstance().level : level);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Block block;
|
||||||
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
|
block = Registry.BLOCK.get(resourceLocation);
|
||||||
|
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||||
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
|
block = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).get(resourceLocation);
|
||||||
|
#else
|
||||||
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
|
block = registryAccess.registryOrThrow(Registries.BLOCK).get(resourceLocation);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (block == null)
|
||||||
{
|
{
|
||||||
// we should have found a blockstate, but didn't
|
// shouldn't normally happen, but here to make the compiler happy
|
||||||
if (!BrokenResourceLocations.contains(resourceLocation))
|
if (!BrokenResourceLocations.contains(resourceLocation))
|
||||||
{
|
{
|
||||||
BrokenResourceLocations.add(resourceLocation);
|
BrokenResourceLocations.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 with the resourceLocation [" + resourceLocation + "] and properties: [" + blockStatePropertiesString + "]. Air will be used instead, some data may be lost.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return AIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// attempt to find the blockstate from all possibilities
|
||||||
|
BlockState foundState = null;
|
||||||
|
if (blockStatePropertiesString != null)
|
||||||
|
{
|
||||||
|
List<BlockState> possibleStateList = block.getStateDefinition().getPossibleStates();
|
||||||
|
for (BlockState possibleState : possibleStateList)
|
||||||
|
{
|
||||||
|
String possibleStatePropertiesString = serializeBlockStateProperties(possibleState);
|
||||||
|
if (possibleStatePropertiesString.equals(blockStatePropertiesString))
|
||||||
|
{
|
||||||
|
foundState = possibleState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foundState = block.defaultBlockState();
|
// use the default if no state was found or given
|
||||||
|
if (foundState == null)
|
||||||
|
{
|
||||||
|
if (blockStatePropertiesString != null)
|
||||||
|
{
|
||||||
|
// we should have found a blockstate, but didn't
|
||||||
|
if (!BrokenResourceLocations.contains(resourceLocation))
|
||||||
|
{
|
||||||
|
BrokenResourceLocations.add(resourceLocation);
|
||||||
|
LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foundState = block.defaultBlockState();
|
||||||
|
}
|
||||||
|
|
||||||
|
foundWrapper = new BlockStateWrapper(foundState, levelWrapper);
|
||||||
|
return foundWrapper;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new IOException("Failed to deserialize the string [" + finalResourceStateString + "] into a BlockStateWrapper: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return new BlockStateWrapper(foundState, levelWrapper);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
finally
|
||||||
{
|
{
|
||||||
throw new IOException("Failed to deserialize the string [" + resourceStateString + "] into a BlockStateWrapper: " + e.getMessage(), e);
|
// put if absent in case two threads deserialize at the same time
|
||||||
|
// unfortunately we can't put everything in a computeIfAbsent() since we also throw exceptions
|
||||||
|
WRAPPER_BY_RESOURCE_LOCATION.putIfAbsent(finalResourceStateString, foundWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +603,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|
|
||||||
// alphabetically sort the list so they are always in the same order
|
// alphabetically sort the list so they are always in the same order
|
||||||
List<net.minecraft.world.level.block.state.properties.Property<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
|
List<net.minecraft.world.level.block.state.properties.Property<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
|
||||||
sortedBlockPropteryList.sort((a, b) -> a.getName().compareTo(b.getName()));
|
sortedBlockPropteryList.sort(Comparator.comparing(Property::getName));
|
||||||
|
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
@@ -475,11 +631,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
// Iris methods //
|
// Iris methods //
|
||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
private byte calculateIrisBlockMaterialId()
|
private EDhApiBlockMaterial calculateEDhApiBlockMaterialId()
|
||||||
{
|
{
|
||||||
if (this.blockState == null)
|
if (this.blockState == null)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.AIR;
|
return EDhApiBlockMaterial.AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -492,15 +648,15 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|| serialString.contains("mushroom")
|
|| serialString.contains("mushroom")
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.LEAVES;
|
return EDhApiBlockMaterial.LEAVES;
|
||||||
}
|
}
|
||||||
else if (this.blockState.is(Blocks.LAVA))
|
else if (this.blockState.is(Blocks.LAVA))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.LAVA;
|
return EDhApiBlockMaterial.LAVA;
|
||||||
}
|
}
|
||||||
else if (this.isLiquid() || this.blockState.is(Blocks.WATER))
|
else if (this.isLiquid() || this.blockState.is(Blocks.WATER))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.WATER;
|
return EDhApiBlockMaterial.WATER;
|
||||||
}
|
}
|
||||||
else if (this.blockState.getSoundType() == SoundType.WOOD
|
else if (this.blockState.getSoundType() == SoundType.WOOD
|
||||||
|| serialString.contains("root")
|
|| serialString.contains("root")
|
||||||
@@ -509,7 +665,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.WOOD;
|
return EDhApiBlockMaterial.WOOD;
|
||||||
}
|
}
|
||||||
else if (this.blockState.getSoundType() == SoundType.METAL
|
else if (this.blockState.getSoundType() == SoundType.METAL
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
@@ -521,11 +677,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.METAL;
|
return EDhApiBlockMaterial.METAL;
|
||||||
}
|
}
|
||||||
else if (serialString.contains("grass_block"))
|
else if (serialString.contains("grass_block"))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.GRASS;
|
return EDhApiBlockMaterial.GRASS;
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
serialString.contains("dirt")
|
serialString.contains("dirt")
|
||||||
@@ -535,7 +691,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|| serialString.contains("mycelium")
|
|| serialString.contains("mycelium")
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.DIRT;
|
return EDhApiBlockMaterial.DIRT;
|
||||||
}
|
}
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER >= MC_1_17_1
|
||||||
else if (this.blockState.getSoundType() == SoundType.DEEPSLATE
|
else if (this.blockState.getSoundType() == SoundType.DEEPSLATE
|
||||||
@@ -544,37 +700,37 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|| this.blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE
|
|| this.blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE
|
||||||
|| serialString.contains("deepslate") )
|
|| serialString.contains("deepslate") )
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.DEEPSLATE;
|
return EDhApiBlockMaterial.DEEPSLATE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (this.serialString.contains("snow"))
|
else if (this.serialString.contains("snow"))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.SNOW;
|
return EDhApiBlockMaterial.SNOW;
|
||||||
}
|
}
|
||||||
else if (serialString.contains("sand"))
|
else if (serialString.contains("sand"))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.SAND;
|
return EDhApiBlockMaterial.SAND;
|
||||||
}
|
}
|
||||||
else if (serialString.contains("terracotta"))
|
else if (serialString.contains("terracotta"))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.TERRACOTTA;
|
return EDhApiBlockMaterial.TERRACOTTA;
|
||||||
}
|
}
|
||||||
else if (this.blockState.is(BlockTags.BASE_STONE_NETHER))
|
else if (this.blockState.is(BlockTags.BASE_STONE_NETHER))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.NETHER_STONE;
|
return EDhApiBlockMaterial.NETHER_STONE;
|
||||||
}
|
}
|
||||||
else if (serialString.contains("stone")
|
else if (serialString.contains("stone")
|
||||||
|| serialString.contains("ore"))
|
|| serialString.contains("ore"))
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.STONE;
|
return EDhApiBlockMaterial.STONE;
|
||||||
}
|
}
|
||||||
else if (this.blockState.getLightEmission() > 0)
|
else if (this.blockState.getLightEmission() > 0)
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.ILLUMINATED;
|
return EDhApiBlockMaterial.ILLUMINATED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return IrisBlockMaterial.UNKOWN;
|
return EDhApiBlockMaterial.UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+60
-12
@@ -19,14 +19,20 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.*;
|
import net.minecraft.world.level.*;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
@@ -35,18 +41,54 @@ import net.minecraft.core.Holder;
|
|||||||
|
|
||||||
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
||||||
{
|
{
|
||||||
final BiomeWrapper biome;
|
/**
|
||||||
|
* This will only ever be null if there was an issue with {@link IClientLevelWrapper#getPlainsBiomeWrapper()}
|
||||||
|
* but {@link Nullable} is there just in case.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private final Biome biome;
|
||||||
|
|
||||||
public TintWithoutLevelOverrider(BiomeWrapper biome)
|
|
||||||
|
|
||||||
|
public TintWithoutLevelOverrider(BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||||
{
|
{
|
||||||
this.biome = biome;
|
// try to get the wrapped biome
|
||||||
|
Biome unwrappedBiome = null;
|
||||||
|
if (biomeWrapper.biome != null)
|
||||||
|
{
|
||||||
|
unwrappedBiome = unwrap(biomeWrapper.biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unwrappedBiome == null)
|
||||||
|
{
|
||||||
|
// we are looking at the empty biome wrapper, try using plains as a backup
|
||||||
|
BiomeWrapper plainsBiomeWrapper = ((BiomeWrapper) clientLevelWrapper.getPlainsBiomeWrapper());
|
||||||
|
if (plainsBiomeWrapper != null)
|
||||||
|
{
|
||||||
|
unwrappedBiome = unwrap(plainsBiomeWrapper.biome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.biome = unwrappedBiome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||||
{
|
{
|
||||||
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
|
if (this.biome != null)
|
||||||
|
{
|
||||||
|
return colorResolver.getColor(this.biome, blockPos.getX(), blockPos.getZ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// hopefully unneeded debug color
|
||||||
|
return ColorUtil.CYAN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private 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
|
||||||
return biome.value();
|
return biome.value();
|
||||||
@@ -55,30 +97,36 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// unused methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getShade(Direction direction, boolean shade)
|
public float getShade(@NotNull Direction direction, boolean shade)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public LevelLightEngine getLightEngine()
|
public @NotNull LevelLightEngine getLightEngine()
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||||
}
|
}
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity getBlockEntity(BlockPos pos)
|
public BlockEntity getBlockEntity(@NotNull BlockPos pos)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlockState(BlockPos pos)
|
public @NotNull BlockState getBlockState(@NotNull BlockPos pos)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public FluidState getFluidState(BlockPos pos)
|
public @NotNull FluidState getFluidState(@NotNull BlockPos pos)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-9
@@ -54,7 +54,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ClientBlockStateCache
|
public class ClientBlockStateCache
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
||||||
@@ -66,15 +65,20 @@ public class ClientBlockStateCache
|
|||||||
public static final RandomSource random = RandomSource.create();
|
public static final RandomSource random = RandomSource.create();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public final IClientLevelWrapper levelWrapper;
|
||||||
public final BlockState blockState;
|
public final BlockState blockState;
|
||||||
public final LevelReader level;
|
public final LevelReader level;
|
||||||
public final BlockPos pos;
|
public final BlockPos pos;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ClientBlockStateCache(BlockState blockState, IClientLevelWrapper samplingLevel, DhBlockPos samplingPos)
|
public ClientBlockStateCache(BlockState blockState, IClientLevelWrapper samplingLevel, DhBlockPos samplingPos)
|
||||||
{
|
{
|
||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
level = (LevelReader) samplingLevel.getWrappedMcObject();
|
this.levelWrapper = samplingLevel;
|
||||||
pos = McObjectConverter.Convert(samplingPos);
|
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
||||||
resolveColors();
|
this.pos = McObjectConverter.Convert(samplingPos);
|
||||||
|
this.resolveColors();
|
||||||
//LOGGER.info("ClientBlocKCache created for {}", blockState);
|
//LOGGER.info("ClientBlocKCache created for {}", blockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,12 +312,12 @@ public class ClientBlockStateCache
|
|||||||
}
|
}
|
||||||
if (quads != null && !quads.isEmpty())
|
if (quads != null && !quads.isEmpty())
|
||||||
{
|
{
|
||||||
needPostTinting = quads.get(0).isTinted();
|
needPostTinting = quads.getFirst().isTinted();
|
||||||
needShade = quads.get(0).isShade();
|
needShade = quads.getFirst().isShade();
|
||||||
tintIndex = quads.get(0).getTintIndex();
|
tintIndex = quads.getFirst().getTintIndex();
|
||||||
baseColor = calculateColorFromTexture(
|
baseColor = calculateColorFromTexture(
|
||||||
#if MC_VER < MC_1_17_1 quads.get(0).sprite,
|
#if MC_VER < MC_1_17_1 quads.get(0).sprite,
|
||||||
#else quads.get(0).getSprite(), #endif
|
#else quads.getFirst().getSprite(), #endif
|
||||||
ColorMode.getColorMode(blockState.getBlock()));
|
ColorMode.getColorMode(blockState.getBlock()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -363,7 +367,7 @@ public class ClientBlockStateCache
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
tintColor = Minecraft.getInstance().getBlockColors()
|
tintColor = Minecraft.getInstance().getBlockColors()
|
||||||
.getColor(this.blockState, new TintWithoutLevelOverrider(biome), McObjectConverter.Convert(pos), this.tintIndex);
|
.getColor(this.blockState, new TintWithoutLevelOverrider(biome, this.levelWrapper), McObjectConverter.Convert(pos), this.tintIndex);
|
||||||
}
|
}
|
||||||
catch (UnsupportedOperationException e)
|
catch (UnsupportedOperationException e)
|
||||||
{
|
{
|
||||||
|
|||||||
-239
@@ -1,239 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.chunk;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compact, efficient storage for light levels.
|
|
||||||
* all blocks only take up 4 bits in total,
|
|
||||||
* and if a 16x16x16 area is detected to have the same light level in all positions,
|
|
||||||
* then we store a single byte for that light level, instead of 2 kilobytes.
|
|
||||||
*
|
|
||||||
* @author Builderb0y
|
|
||||||
*/
|
|
||||||
public class ChunkLightStorage
|
|
||||||
{
|
|
||||||
/** the minimum Y level in the chunk which this storage is storing light levels for (inclusive). */
|
|
||||||
public int minY;
|
|
||||||
/** the maximum Y level in the chunk which this storage is storing light levels for (exclusive). */
|
|
||||||
public int maxY;
|
|
||||||
|
|
||||||
/** the data stored in this storage, split up into 16x16x16 areas. */
|
|
||||||
public LightSection[] lightSections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the get method is called on a Y position above what's stored
|
|
||||||
* this value will be returned. <br><br>
|
|
||||||
*
|
|
||||||
* This needs to be manually defined since sky and block lights behave differently
|
|
||||||
* for values both above and below what's defined.
|
|
||||||
*/
|
|
||||||
public int aboveMaxYValue;
|
|
||||||
/** @see ChunkLightStorage#aboveMaxYValue */
|
|
||||||
public int belowMinYValue;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
|
||||||
// constructor //
|
|
||||||
//=============//
|
|
||||||
|
|
||||||
public ChunkLightStorage(int minY, int maxY, int aboveMaxYValue, int belowMinYValue)
|
|
||||||
{
|
|
||||||
this.minY = minY;
|
|
||||||
this.maxY = maxY;
|
|
||||||
|
|
||||||
this.aboveMaxYValue = aboveMaxYValue;
|
|
||||||
this.belowMinYValue = belowMinYValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=====================//
|
|
||||||
// getters and setters //
|
|
||||||
//=====================//
|
|
||||||
|
|
||||||
public int get(int x, int y, int z)
|
|
||||||
{
|
|
||||||
if (y < this.minY)
|
|
||||||
{
|
|
||||||
return this.belowMinYValue;
|
|
||||||
}
|
|
||||||
else if (y >= this.maxY)
|
|
||||||
{
|
|
||||||
return this.aboveMaxYValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (this.lightSections != null)
|
|
||||||
{
|
|
||||||
LightSection lightSection = this.lightSections[BitShiftUtil.divideByPowerOfTwo(y - this.minY, 4)];
|
|
||||||
if (lightSection != null)
|
|
||||||
{
|
|
||||||
return lightSection.get(x, y, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int x, int y, int z, int lightLevel)
|
|
||||||
{
|
|
||||||
if (y < this.minY || y >= this.maxY)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//populate array if it doesn't exist.
|
|
||||||
if (this.lightSections == null)
|
|
||||||
{
|
|
||||||
this.lightSections = new LightSection[BitShiftUtil.divideByPowerOfTwo(this.maxY - this.minY, 4)];
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = (y - this.minY) >> 4;
|
|
||||||
LightSection lightSection = this.lightSections[index];
|
|
||||||
|
|
||||||
//populate lightSection in array if it doesn't exist.
|
|
||||||
if (lightSection == null)
|
|
||||||
{
|
|
||||||
lightSection = new LightSection(0);
|
|
||||||
this.lightSections[index] = lightSection;
|
|
||||||
}
|
|
||||||
lightSection.set(x, y, z, lightLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
|
||||||
// helper classes //
|
|
||||||
//================//
|
|
||||||
|
|
||||||
public static class LightSection
|
|
||||||
{
|
|
||||||
public byte constantValue;
|
|
||||||
public long[] data;
|
|
||||||
public short[] counts;
|
|
||||||
|
|
||||||
public LightSection(int initialValue)
|
|
||||||
{
|
|
||||||
this.constantValue = (byte) (initialValue);
|
|
||||||
this.counts = new short[16];
|
|
||||||
this.counts[initialValue] = 16 * 16 * 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int get(int x, int y, int z)
|
|
||||||
{
|
|
||||||
if (this.constantValue >= 0)
|
|
||||||
{
|
|
||||||
return this.constantValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
x &= 15;
|
|
||||||
y &= 15;
|
|
||||||
z &= 15;
|
|
||||||
long bits = this.data[(z << 4) | x];
|
|
||||||
return ((int) (bits >>> (y << 2))) & 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int x, int y, int z, int lightLevel)
|
|
||||||
{
|
|
||||||
int oldLightLevel = -1;
|
|
||||||
if (this.constantValue >= 0)
|
|
||||||
{
|
|
||||||
oldLightLevel = this.constantValue;
|
|
||||||
|
|
||||||
//if the light level didn't change, then there's nothing to do.
|
|
||||||
if (oldLightLevel == lightLevel) return;
|
|
||||||
|
|
||||||
//if we are a constant value and need to change something,
|
|
||||||
//then that means we need to convert to a non-constant value.
|
|
||||||
this.data = DataRecycler.get();
|
|
||||||
|
|
||||||
//repeat oldLightLevel 16 times as a bit pattern.
|
|
||||||
long payload = oldLightLevel;
|
|
||||||
payload |= payload << 4;
|
|
||||||
payload |= payload << 8;
|
|
||||||
payload |= payload << 16;
|
|
||||||
payload |= payload << 32;
|
|
||||||
|
|
||||||
//fill our data with our constant value.
|
|
||||||
Arrays.fill(this.data, payload);
|
|
||||||
|
|
||||||
//we are no longer a constant value.
|
|
||||||
this.constantValue = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
x &= 15;
|
|
||||||
y &= 15;
|
|
||||||
z &= 15;
|
|
||||||
int index = (z << 4) | x;
|
|
||||||
long bits = this.data[index];
|
|
||||||
//if we weren't a constant value before, now's the time to initialize oldLightLevel.
|
|
||||||
if (oldLightLevel < 0)
|
|
||||||
{
|
|
||||||
oldLightLevel = ((int) (bits >>> (y << 2))) & 15;
|
|
||||||
}
|
|
||||||
//clear the 4 bits that correspond to the light level at x, y, z...
|
|
||||||
bits &= ~(15L << (y << 2));
|
|
||||||
//...and then re-populate those bits with the new light level.
|
|
||||||
bits |= ((long) (lightLevel)) << (y << 2);
|
|
||||||
//store the updated bits in our data.
|
|
||||||
this.data[index] = bits;
|
|
||||||
|
|
||||||
//we have one less of the old light level...
|
|
||||||
this.counts[oldLightLevel]--;
|
|
||||||
//...and one more of the new level.
|
|
||||||
//if the number associated with the new level is now 4096 (AKA 16 ^ 3),
|
|
||||||
//then this implies every position in this section has the same light level,
|
|
||||||
//and therefore we can convert back to a constant value.
|
|
||||||
if (++this.counts[lightLevel] == 4096)
|
|
||||||
{
|
|
||||||
this.constantValue = (byte) (lightLevel);
|
|
||||||
DataRecycler.reclaim(this.data);
|
|
||||||
this.data = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DataRecycler
|
|
||||||
{
|
|
||||||
private static final ArrayList<long[]> recycled = new ArrayList<>(256);
|
|
||||||
|
|
||||||
static synchronized long[] get()
|
|
||||||
{
|
|
||||||
if (recycled.isEmpty())
|
|
||||||
{
|
|
||||||
return new long[256];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return recycled.remove(recycled.size() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static synchronized void reclaim(long[] data) { if (recycled.size() < 256) recycled.add(data); }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+104
-141
@@ -25,20 +25,18 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.Dh
|
|||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
|
||||||
import net.minecraft.client.multiplayer.ClientChunkCache;
|
import net.minecraft.client.multiplayer.ClientChunkCache;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.LevelReader;
|
import net.minecraft.world.level.LevelReader;
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
|
||||||
@@ -73,15 +71,19 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
|
|||||||
import net.minecraft.core.SectionPos;
|
import net.minecraft.core.SectionPos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public class ChunkWrapper implements IChunkWrapper
|
public class ChunkWrapper implements IChunkWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
|
|
||||||
/** useful for debugging, but can slow down chunk operations quite a bit due to being called every time. */
|
|
||||||
private static final boolean RUN_RELATIVE_POS_INDEX_VALIDATION = ModInfo.IS_DEV_BUILD;
|
|
||||||
|
|
||||||
/** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */
|
/** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */
|
||||||
private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos());
|
private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new);
|
||||||
|
|
||||||
|
|
||||||
private final ChunkAccess chunk;
|
private final ChunkAccess chunk;
|
||||||
@@ -103,6 +105,8 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
private int minNonEmptyHeight = Integer.MIN_VALUE;
|
private int minNonEmptyHeight = Integer.MIN_VALUE;
|
||||||
private int maxNonEmptyHeight = Integer.MAX_VALUE;
|
private int maxNonEmptyHeight = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private int blockBiomeHashCode = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Due to vanilla `isClientLightReady()` not being designed for use by a non-render thread, it may return 'true'
|
* Due to vanilla `isClientLightReady()` not being designed for use by a non-render thread, it may return 'true'
|
||||||
* before the light engine has ticked, (right after all light changes is marked by the engine to be processed).
|
* before the light engine has ticked, (right after all light changes is marked by the engine to be processed).
|
||||||
@@ -142,30 +146,34 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
|
|
||||||
|
|
||||||
//=========//
|
//=========//
|
||||||
// methods //
|
// getters //
|
||||||
//=========//
|
//=========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight()
|
public int getHeight() { return getHeight(this.chunk); }
|
||||||
|
public static int getHeight(ChunkAccess chunk)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
return 255;
|
return 255;
|
||||||
#else
|
#else
|
||||||
return this.chunk.getHeight();
|
return chunk.getHeight();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMinBuildHeight()
|
public int getMinBuildHeight() { return getMinBuildHeight(this.chunk); }
|
||||||
|
public static int getMinBuildHeight(ChunkAccess chunk)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
return this.chunk.getMinBuildHeight();
|
return chunk.getMinBuildHeight();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxBuildHeight() { return this.chunk.getMaxBuildHeight(); }
|
public int getMaxBuildHeight() { return getMaxBuildHeight(this.chunk); }
|
||||||
|
public static int getMaxBuildHeight(ChunkAccess chunk) { return chunk.getMaxBuildHeight(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMinNonEmptyHeight()
|
public int getMinNonEmptyHeight()
|
||||||
@@ -215,6 +223,9 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
LevelChunkSection[] sections = this.chunk.getSections();
|
LevelChunkSection[] sections = this.chunk.getSections();
|
||||||
for (int index = sections.length-1; index >= 0; index--)
|
for (int index = sections.length-1; index >= 0; index--)
|
||||||
{
|
{
|
||||||
|
// update at each position to fix using the max height if the chunk is empty
|
||||||
|
this.maxNonEmptyHeight = this.getChunkSectionMinHeight(index) + 16;
|
||||||
|
|
||||||
if (sections[index] == null)
|
if (sections[index] == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -222,7 +233,7 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
|
|
||||||
if (!isChunkSectionEmpty(sections[index]))
|
if (!isChunkSectionEmpty(sections[index]))
|
||||||
{
|
{
|
||||||
this.maxNonEmptyHeight = this.getChunkSectionMinHeight(index) + 16;
|
// non-empty section found
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,15 +250,7 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
return section.hasOnlyAir();
|
return section.hasOnlyAir();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
private int getChunkSectionMinHeight(int index)
|
private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getMinBuildHeight(); }
|
||||||
{
|
|
||||||
// convert from an index to a block coordinate
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
|
||||||
return this.chunk.getSections()[index].bottomBlockY();
|
|
||||||
#else
|
|
||||||
return this.chunk.getSectionYFromSectionIndex(index) * 16;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -257,7 +260,6 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
public int getLightBlockingHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); }
|
public int getLightBlockingHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBiomeWrapper getBiome(int relX, int relY, int relZ)
|
public IBiomeWrapper getBiome(int relX, int relY, int relZ)
|
||||||
{
|
{
|
||||||
@@ -281,11 +283,35 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBlockStateWrapper getBlockState(int relX, int relY, int relZ)
|
||||||
|
{
|
||||||
|
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ);
|
||||||
|
|
||||||
|
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
|
||||||
|
|
||||||
|
blockPos.setX(relX);
|
||||||
|
blockPos.setY(relY);
|
||||||
|
blockPos.setZ(relZ);
|
||||||
|
|
||||||
|
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DhChunkPos getChunkPos() { return this.chunkPos; }
|
public DhChunkPos getChunkPos() { return this.chunkPos; }
|
||||||
|
|
||||||
public ChunkAccess getChunk() { return this.chunk; }
|
public ChunkAccess getChunk() { return this.chunk; }
|
||||||
|
|
||||||
|
public ChunkStatus getStatus() { return getStatus(this.getChunk()); }
|
||||||
|
public static ChunkStatus getStatus(ChunkAccess chunk)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
return chunk.getStatus();
|
||||||
|
#else
|
||||||
|
return chunk.getPersistedStatus();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); }
|
public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); }
|
||||||
@Override
|
@Override
|
||||||
@@ -295,8 +321,11 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
@Override
|
@Override
|
||||||
public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); }
|
public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); }
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLongChunkPos() { return this.chunk.getPos().toLong(); }
|
|
||||||
|
//==========//
|
||||||
|
// lighting //
|
||||||
|
//==========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; }
|
public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; }
|
||||||
@@ -304,8 +333,6 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
@Override
|
@Override
|
||||||
public void setUseDhLighting(boolean useDhLighting) { this.useDhLighting = useDhLighting; }
|
public void setUseDhLighting(boolean useDhLighting) { this.useDhLighting = useDhLighting; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLightCorrect()
|
public boolean isLightCorrect()
|
||||||
{
|
{
|
||||||
@@ -318,9 +345,8 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
#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
|
||||||
return false; // MC's lighting engine doesn't work consistently enough to trust for 1.16 or 1.17
|
return false; // MC's lighting engine doesn't work consistently enough to trust for 1.16 or 1.17
|
||||||
#else
|
#else
|
||||||
if (this.chunk instanceof LevelChunk)
|
if (this.chunk instanceof LevelChunk levelChunk)
|
||||||
{
|
{
|
||||||
LevelChunk levelChunk = (LevelChunk) this.chunk;
|
|
||||||
if (levelChunk.getLevel() instanceof ClientLevel)
|
if (levelChunk.getLevel() instanceof ClientLevel)
|
||||||
{
|
{
|
||||||
// connected to a server
|
// connected to a server
|
||||||
@@ -358,13 +384,11 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
{
|
{
|
||||||
if (this.blockLightStorage == null)
|
if (this.blockLightStorage == null)
|
||||||
{
|
{
|
||||||
this.blockLightStorage = new ChunkLightStorage(
|
this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(this);
|
||||||
this.getMinBuildHeight(), this.getMaxBuildHeight(),
|
|
||||||
// positions above and below the handled area should be unlit
|
|
||||||
LodUtil.MIN_MC_LIGHT, LodUtil.MIN_MC_LIGHT);
|
|
||||||
}
|
}
|
||||||
return this.blockLightStorage;
|
return this.blockLightStorage;
|
||||||
}
|
}
|
||||||
|
public void setBlockLightStorage(ChunkLightStorage lightStorage) { this.blockLightStorage = lightStorage; }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -384,13 +408,11 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
{
|
{
|
||||||
if (this.skyLightStorage == null)
|
if (this.skyLightStorage == null)
|
||||||
{
|
{
|
||||||
this.skyLightStorage = new ChunkLightStorage(
|
this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(this);
|
||||||
this.getMinBuildHeight(), this.getMaxBuildHeight(),
|
|
||||||
// positions above should be lit but positions below should be unlit
|
|
||||||
LodUtil.MAX_MC_LIGHT, LodUtil.MIN_MC_LIGHT);
|
|
||||||
}
|
}
|
||||||
return this.skyLightStorage;
|
return this.skyLightStorage;
|
||||||
}
|
}
|
||||||
|
public void setSkyLightStorage(ChunkLightStorage lightStorage) { this.skyLightStorage = lightStorage; }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -451,64 +473,13 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
this.chunk.findBlockLightSources((blockPos, blockState) ->
|
this.chunk.findBlockLightSources((blockPos, blockState) ->
|
||||||
{
|
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
|
||||||
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.blockLightPosList;
|
return this.blockLightPosList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doNearbyChunksExist()
|
|
||||||
{
|
|
||||||
if (this.lightSource instanceof DhLitWorldGenRegion)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int dx = -1; dx <= 1; dx++)
|
|
||||||
{
|
|
||||||
for (int dz = -1; dz <= 1; dz++)
|
|
||||||
{
|
|
||||||
if (dx == 0 && dz == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (this.lightSource.getChunk(dx + this.chunk.getPos().x, dz + this.chunk.getPos().z, ChunkStatus.BIOMES, false) == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LevelReader getColorResolver() { return this.lightSource; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockStateWrapper getBlockState(int relX, int relY, int relZ)
|
|
||||||
{
|
|
||||||
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ);
|
|
||||||
|
|
||||||
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
|
|
||||||
|
|
||||||
blockPos.setX(relX);
|
|
||||||
blockPos.setY(relY);
|
|
||||||
blockPos.setZ(relZ);
|
|
||||||
|
|
||||||
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; }
|
|
||||||
|
|
||||||
|
|
||||||
public static void syncedUpdateClientLightStatus()
|
public static void syncedUpdateClientLightStatus()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
@@ -533,9 +504,8 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
/** Should be called after client light updates are triggered. */
|
/** Should be called after client light updates are triggered. */
|
||||||
private void updateIsClientLightingCorrect()
|
private void updateIsClientLightingCorrect()
|
||||||
{
|
{
|
||||||
if (this.chunk instanceof LevelChunk && ((LevelChunk) this.chunk).getLevel() instanceof ClientLevel)
|
if (this.chunk instanceof LevelChunk levelChunk && ((LevelChunk) this.chunk).getLevel() instanceof ClientLevel)
|
||||||
{
|
{
|
||||||
LevelChunk levelChunk = (LevelChunk) this.chunk;
|
|
||||||
ClientChunkCache clientChunkCache = ((ClientLevel) levelChunk.getLevel()).getChunkSource();
|
ClientChunkCache clientChunkCache = ((ClientLevel) levelChunk.getLevel()).getChunkSource();
|
||||||
this.isMcClientLightingCorrect = clientChunkCache.getChunkForLighting(this.chunk.getPos().x, this.chunk.getPos().z) != null &&
|
this.isMcClientLightingCorrect = clientChunkCache.getChunkForLighting(this.chunk.getPos().x, this.chunk.getPos().z) != null &&
|
||||||
#if MC_VER <= MC_1_17_1
|
#if MC_VER <= MC_1_17_1
|
||||||
@@ -568,64 +538,57 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//===============//
|
||||||
// helper methods //
|
// other methods //
|
||||||
//================//
|
//===============//
|
||||||
|
|
||||||
/** used to prevent accidentally attempting to get/set values outside this chunk's boundaries */
|
@Override
|
||||||
private void throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(int x, int y, int z) throws IndexOutOfBoundsException
|
public boolean doNearbyChunksExist()
|
||||||
{
|
{
|
||||||
if (!RUN_RELATIVE_POS_INDEX_VALIDATION)
|
if (this.lightSource instanceof DhLitWorldGenRegion)
|
||||||
{
|
{
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int dx = -1; dx <= 1; dx++)
|
||||||
// FIXME +1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the constructor
|
|
||||||
int minHeight = this.getMinBuildHeight();
|
|
||||||
int maxHeight = this.getMaxBuildHeight() + 1;
|
|
||||||
|
|
||||||
if (x < 0 || x >= LodUtil.CHUNK_WIDTH
|
|
||||||
|| z < 0 || z >= LodUtil.CHUNK_WIDTH
|
|
||||||
|| y < minHeight || y > maxHeight)
|
|
||||||
{
|
{
|
||||||
String errorMessage = "Relative position [" + x + "," + y + "," + z + "] out of bounds. \n" +
|
for (int dz = -1; dz <= 1; dz++)
|
||||||
"X/Z must be between 0 and 15 (inclusive) \n" +
|
{
|
||||||
"Y must be between [" + minHeight + "] and [" + maxHeight + "] (inclusive).";
|
if (dx == 0 && dz == 0)
|
||||||
throw new IndexOutOfBoundsException(errorMessage);
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (this.lightSource.getChunk(dx + this.chunk.getPos().x, dz + this.chunk.getPos().z, ChunkStatus.BIOMES, false) == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a 3D position into a 1D array index. <br><br>
|
|
||||||
*
|
|
||||||
* Source: <br>
|
|
||||||
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
|
|
||||||
*/
|
|
||||||
public int relativeBlockPosToIndex(int xRel, int y, int zRel)
|
|
||||||
{
|
|
||||||
int yRel = y - this.getMinBuildHeight();
|
|
||||||
return (zRel * LodUtil.CHUNK_WIDTH * this.getHeight()) + (yRel * LodUtil.CHUNK_WIDTH) + xRel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a 3D position into a 1D array index. <br><br>
|
|
||||||
*
|
|
||||||
* Source: <br>
|
|
||||||
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
|
|
||||||
*/
|
|
||||||
public DhBlockPos indexToRelativeBlockPos(int index)
|
|
||||||
{
|
|
||||||
final int zRel = index / (LodUtil.CHUNK_WIDTH * this.getHeight());
|
|
||||||
index -= (zRel * LodUtil.CHUNK_WIDTH * this.getHeight());
|
|
||||||
|
|
||||||
final int y = index / LodUtil.CHUNK_WIDTH;
|
return true;
|
||||||
final int yRel = y + this.getMinBuildHeight();
|
|
||||||
|
|
||||||
final int xRel = index % LodUtil.CHUNK_WIDTH;
|
|
||||||
return new DhBlockPos(xRel, yRel, zRel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); }
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
//public int hashCode()
|
||||||
|
//{
|
||||||
|
// if (this.blockBiomeHashCode == 0)
|
||||||
|
// {
|
||||||
|
// this.blockBiomeHashCode = this.getBlockBiomeHashCode();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return this.blockBiomeHashCode;
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-27
@@ -98,6 +98,7 @@ public class ClassicConfigGUI
|
|||||||
public static final int SpaceFromRightScreen = 10;
|
public static final int SpaceFromRightScreen = 10;
|
||||||
public static final int ButtonWidthSpacing = 5;
|
public static final int ButtonWidthSpacing = 5;
|
||||||
public static final int ResetButtonWidth = 40;
|
public static final int ResetButtonWidth = 40;
|
||||||
|
public static final int ResetButtonHeight = 20;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,9 +145,9 @@ public class ClassicConfigGUI
|
|||||||
case 0:
|
case 0:
|
||||||
((EntryInfo) info.guiValue).error = null; break;
|
((EntryInfo) info.guiValue).error = null; break;
|
||||||
case -1:
|
case -1:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin())); break;
|
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry<?>) info).getMin())); break;
|
||||||
case 1:
|
case 1:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax())); break;
|
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry<?>) info).getMax())); break;
|
||||||
case 2:
|
case 2:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid")); break;
|
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid")); break;
|
||||||
}
|
}
|
||||||
@@ -157,19 +158,22 @@ public class ClassicConfigGUI
|
|||||||
// button.active = entries.stream().allMatch(e -> e.inLimits);
|
// button.active = entries.stream().allMatch(e -> e.inLimits);
|
||||||
|
|
||||||
|
|
||||||
if (((ConfigEntry) info).isValid(value) == 0 && info.getType() != List.class)
|
if (info.getType() == String.class
|
||||||
|
|| info.getType() == List.class)
|
||||||
|
{
|
||||||
|
((ConfigEntry) info).uiSetWithoutSaving(stringValue);
|
||||||
|
}
|
||||||
|
else if (((ConfigEntry) info).isValid(value) == 0)
|
||||||
{
|
{
|
||||||
if (!cast)
|
if (!cast)
|
||||||
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(value);
|
((ConfigEntry) info).uiSetWithoutSaving(value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(value.intValue());
|
((ConfigEntry) info).uiSetWithoutSaving(value.intValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// else if (((ConfigEntry) info).isValidMemoryAddress() == 0)
|
|
||||||
// {
|
|
||||||
// if (((List<String>) info.get()).size() == ((EntryInfo) info.guiValue).index)
|
|
||||||
// info.uiSet(((List<String>) info.get()).add(""));
|
|
||||||
// info.uiSet(((List<String>) info.get()).set(((EntryInfo) info.guiValue).index, Arrays.stream(((EntryInfo) info.guiValue).tempValue.replace("[", "").replace("]", "").split(", ")).collect(Collectors.toList()).get(0)));
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -231,7 +235,7 @@ public class ClassicConfigGUI
|
|||||||
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
|
|
||||||
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach(Runnable::run);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,17 +248,23 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changelog button
|
// Changelog button
|
||||||
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() && Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE)
|
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() && !ModInfo.IS_DEV_BUILD) // we only have changelogs for stable builds
|
||||||
{
|
{
|
||||||
this.addBtn(new TexturedButtonWidget(
|
this.addBtn(new TexturedButtonWidget(
|
||||||
// Where the button is on the screen
|
// Where the button is on the screen
|
||||||
this.width - 28, this.height - 28,
|
this.width - 28, this.height - 28,
|
||||||
// Width and height of the button
|
// Width and height of the button
|
||||||
20, 20,
|
20, 20,
|
||||||
// Offset
|
// texture UV Offset
|
||||||
0, 0,
|
0, 0,
|
||||||
// Some textuary stuff
|
// Some textuary stuff
|
||||||
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
|
0,
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#else
|
||||||
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#endif
|
||||||
|
20, 20,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
(buttonWidget) -> {
|
(buttonWidget) -> {
|
||||||
ChangelogScreen changelogScreen = new ChangelogScreen(this);
|
ChangelogScreen changelogScreen = new ChangelogScreen(this);
|
||||||
@@ -269,18 +279,25 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addBtn(MakeBtn(Translatable("distanthorizons.general.cancel"), this.width / 2 - 154, this.height - 28, 150, 20, button -> {
|
addBtn(MakeBtn(Translatable("distanthorizons.general.cancel"),
|
||||||
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
this.width / 2 - 154, this.height - 28,
|
||||||
Objects.requireNonNull(minecraft).setScreen(parent);
|
150, 20,
|
||||||
}));
|
button ->
|
||||||
|
{
|
||||||
|
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(parent);
|
||||||
|
}));
|
||||||
doneButton = addBtn(MakeBtn(Translatable("distanthorizons.general.done"), this.width / 2 + 4, this.height - 28, 150, 20, (button) -> {
|
doneButton = 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(minecraft).setScreen(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);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
|
||||||
if (this.minecraft != null && this.minecraft.level != null)
|
if (this.minecraft != null && this.minecraft.level != null)
|
||||||
this.list.setRenderBackground(false);
|
this.list.setRenderBackground(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
this.addWidget(this.list);
|
this.addWidget(this.list);
|
||||||
|
|
||||||
@@ -302,7 +319,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach(Runnable::run);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,20 +328,21 @@ public class ClassicConfigGUI
|
|||||||
initEntry(info, this.translationPrefix);
|
initEntry(info, this.translationPrefix);
|
||||||
Component name = Translatable(translationPrefix + info.getNameWCategory());
|
Component name = Translatable(translationPrefix + info.getNameWCategory());
|
||||||
|
|
||||||
|
|
||||||
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
|
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
|
||||||
{
|
{
|
||||||
Button.OnPress btnAction = button -> {
|
Button.OnPress btnAction = button -> {
|
||||||
((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(minecraft).setScreen(this);
|
||||||
};
|
};
|
||||||
int a = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
|
int posX = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
|
||||||
int b = 0;
|
int posZ = 0;
|
||||||
int c = ConfigScreenConfigs.ResetButtonWidth;
|
|
||||||
int d = 20;
|
|
||||||
|
|
||||||
Button resetButton = MakeBtn(Translatable("distanthorizons.general.reset").withStyle(ChatFormatting.RED), a, b, c, d, btnAction);
|
Button resetButton = MakeBtn(Translatable("distanthorizons.general.reset").withStyle(ChatFormatting.RED),
|
||||||
|
posX, posZ, ConfigScreenConfigs.ResetButtonWidth, ConfigScreenConfigs.ResetButtonHeight,
|
||||||
|
btnAction);
|
||||||
|
|
||||||
if (((EntryInfo) info.guiValue).widget instanceof Map.Entry)
|
if (((EntryInfo) info.guiValue).widget instanceof Map.Entry)
|
||||||
{
|
{
|
||||||
@@ -358,9 +376,7 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
if (ConfigUIButton.class.isAssignableFrom(info.getClass()))
|
if (ConfigUIButton.class.isAssignableFrom(info.getClass()))
|
||||||
{
|
{
|
||||||
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 -> ((ConfigUIButton) info).runAction()));
|
||||||
((ConfigUIButton) info).runAction();
|
|
||||||
}));
|
|
||||||
this.list.addButton(widget, null, null, null);
|
this.list.addButton(widget, null, null, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -428,7 +444,9 @@ public class ClassicConfigGUI
|
|||||||
String key = translationPrefix + (newInfo.category.isEmpty() ? "" : newInfo.category + ".") + newInfo.getName() + ".@tooltip";
|
String key = translationPrefix + (newInfo.category.isEmpty() ? "" : newInfo.category + ".") + newInfo.getName() + ".@tooltip";
|
||||||
|
|
||||||
if (((EntryInfo) newInfo.guiValue).error != null && text.equals(name))
|
if (((EntryInfo) newInfo.guiValue).error != null && text.equals(name))
|
||||||
|
{
|
||||||
DhRenderTooltip(matrices, font, ((EntryInfo) newInfo.guiValue).error.getValue(), mouseX, mouseY);
|
DhRenderTooltip(matrices, font, ((EntryInfo) newInfo.guiValue).error.getValue(), mouseX, mouseY);
|
||||||
|
}
|
||||||
else if (I18n.exists(key) && (text != null && text.equals(name)))
|
else if (I18n.exists(key) && (text != null && text.equals(name)))
|
||||||
{
|
{
|
||||||
List<Component> list = new ArrayList<>();
|
List<Component> list = new ArrayList<>();
|
||||||
|
|||||||
+9
-10
@@ -25,19 +25,18 @@ public class GetConfigScreen
|
|||||||
// This shouldn't be here, but I need a way to test it after Minecraft inits its assets
|
// This shouldn't be here, but I need a way to test it after Minecraft inits its assets
|
||||||
//System.out.println(ConfigBase.INSTANCE.generateLang(false, true));
|
//System.out.println(ConfigBase.INSTANCE.generateLang(false, true));
|
||||||
|
|
||||||
switch (useScreen)
|
return switch (useScreen)
|
||||||
{
|
{
|
||||||
case Classic:
|
case Classic -> ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
|
||||||
return ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
|
case OpenGL ->
|
||||||
case OpenGL:
|
{
|
||||||
MinecraftScreen.getScreen(parent, new OpenGLConfigScreen(), ModInfo.ID + ".title");
|
MinecraftScreen.getScreen(parent, new OpenGLConfigScreen(), ModInfo.ID + ".title");
|
||||||
return null;
|
yield null;
|
||||||
|
}
|
||||||
// case JavaFX -> MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
// case JavaFX -> MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
||||||
case JavaFX:
|
case JavaFX -> MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
||||||
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
default -> throw new IllegalArgumentException("No config screen implementation defined for [" + useScreen + "].");
|
||||||
default:
|
};
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -15,12 +15,12 @@ public class GuiHelper
|
|||||||
/**
|
/**
|
||||||
* Helper static methods for versional compat
|
* Helper static methods for versional compat
|
||||||
*/
|
*/
|
||||||
public static Button MakeBtn(Component base, int a, int b, int c, int d, Button.OnPress action)
|
public static Button MakeBtn(Component base, int posX, int posZ, int width, int height, Button.OnPress action)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
return new Button(a, b, c, d, base, action);
|
return new Button(posX, posZ, width, height, base, action);
|
||||||
#else
|
#else
|
||||||
return Button.builder(base, action).bounds(a, b, c, d).build();
|
return Button.builder(base, action).bounds(posX, posZ, width, height).build();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
@@ -60,8 +60,12 @@ public class MinecraftScreen
|
|||||||
screen.init(); // Init our own config screen
|
screen.init(); // Init our own config screen
|
||||||
|
|
||||||
this.list = new ConfigListWidget(this.minecraft, this.width, this.height, 0, 0, 25); // Select the area to tint
|
this.list = new ConfigListWidget(this.minecraft, this.width, this.height, 0, 0, 25); // Select the area to tint
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
|
||||||
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
|
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
|
||||||
this.list.setRenderBackground(false); // Disable from rendering
|
this.list.setRenderBackground(false); // Disable from rendering
|
||||||
|
#endif
|
||||||
|
|
||||||
this.addWidget(this.list); // Add the tint to the things to be rendered
|
this.addWidget(this.list); // Add the tint to the things to be rendered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -101,11 +101,17 @@ public class ChangelogScreen extends DhScreen
|
|||||||
this.changelog.add("");
|
this.changelog.add("");
|
||||||
this.changelog.add("");
|
this.changelog.add("");
|
||||||
|
|
||||||
|
String changelog = ModrinthGetter.changeLogs.get(versionID);
|
||||||
|
if (changelog == null)
|
||||||
|
{
|
||||||
|
// in case something goes wrong this will prevent null pointers
|
||||||
|
changelog = "";
|
||||||
|
}
|
||||||
|
|
||||||
// Get the release changelog and split it by the new lines
|
// Get the release changelog and split it by the new lines
|
||||||
String[] unwrappedChangelog = // Arrays.asList could be used if a list object is desired here vs List.of which is only available for Java 9+
|
String[] unwrappedChangelog = // Arrays.asList could be used if a list object is desired here vs List.of which is only available for Java 9+
|
||||||
new MarkdownFormatter.MinecraftFormat().convertTo( // This formats markdown to minecraft's "§" characters
|
// This formats markdown to minecraft's "§" charactersnew MarkdownFormatter.MinecraftFormat().convertTo(
|
||||||
ModrinthGetter.changeLogs.get(versionID)
|
new MarkdownFormatter.MinecraftFormat().convertTo(changelog).split("\\n");
|
||||||
).split("\\n");
|
|
||||||
// Makes the words wrap around to not go off the screen
|
// Makes the words wrap around to not go off the screen
|
||||||
for (String str : unwrappedChangelog)
|
for (String str : unwrappedChangelog)
|
||||||
{
|
{
|
||||||
@@ -128,9 +134,7 @@ public class ChangelogScreen extends DhScreen
|
|||||||
|
|
||||||
|
|
||||||
this.addBtn( // Close
|
this.addBtn( // Close
|
||||||
MakeBtn(Translatable(ModInfo.ID + ".general.back"), 5, this.height - 25, 100, 20, (btn) -> {
|
MakeBtn(Translatable(ModInfo.ID + ".general.back"), 5, this.height - 25, 100, 20, (btn) -> this.onClose())
|
||||||
this.onClose();
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -168,10 +172,9 @@ public class ChangelogScreen extends DhScreen
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
this.changelogArea.render(matrices, mouseX, mouseY, delta); // Render the changelog
|
// render order matters, otherwise on 1.20.6+ the blurred background will render on top of the text
|
||||||
|
|
||||||
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
|
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
|
||||||
|
this.changelogArea.render(matrices, mouseX, mouseY, delta); // Render the changelog
|
||||||
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
|
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-21
@@ -41,16 +41,18 @@ public class UpdateModScreen extends DhScreen
|
|||||||
super(Translatable(ModInfo.ID + ".updater.title"));
|
super(Translatable(ModInfo.ID + ".updater.title"));
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.newVersionID = newVersionID;
|
this.newVersionID = newVersionID;
|
||||||
|
|
||||||
switch (Config.Client.Advanced.AutoUpdater.updateBranch.get()) {
|
|
||||||
case STABLE:
|
EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get());
|
||||||
currentVer = ModInfo.VERSION;
|
if (updateBranch == EDhApiUpdateBranch.STABLE)
|
||||||
nextVer = ModrinthGetter.releaseNames.get(this.newVersionID);
|
{
|
||||||
break;
|
this.currentVer = ModInfo.VERSION;
|
||||||
case NIGHTLY:
|
this.nextVer = ModrinthGetter.releaseNames.get(this.newVersionID);
|
||||||
currentVer = ModJarInfo.Git_Commit.substring(0,7);
|
}
|
||||||
nextVer = this.newVersionID.substring(0,7);
|
else
|
||||||
break;
|
{
|
||||||
|
this.currentVer = ModJarInfo.Git_Commit.substring(0,7);
|
||||||
|
this.nextVer = this.newVersionID.substring(0,7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +75,13 @@ public class UpdateModScreen extends DhScreen
|
|||||||
// Offset
|
// Offset
|
||||||
0, 0,
|
0, 0,
|
||||||
// Some textuary stuff
|
// Some textuary stuff
|
||||||
0, new ResourceLocation(ModInfo.ID, "logo.png"), 130, 65,
|
0,
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
new ResourceLocation(ModInfo.ID, "logo.png"),
|
||||||
|
#else
|
||||||
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
|
||||||
|
#endif
|
||||||
|
130, 65,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
// For now it goes to the client option by default
|
// For now it goes to the client option by default
|
||||||
(buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
|
(buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
|
||||||
@@ -88,7 +96,7 @@ public class UpdateModScreen extends DhScreen
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE)
|
if (!ModInfo.IS_DEV_BUILD)
|
||||||
{
|
{
|
||||||
this.addBtn(new TexturedButtonWidget(
|
this.addBtn(new TexturedButtonWidget(
|
||||||
// Where the button is on the screen
|
// Where the button is on the screen
|
||||||
@@ -98,7 +106,13 @@ public class UpdateModScreen extends DhScreen
|
|||||||
// Offset
|
// Offset
|
||||||
0, 0,
|
0, 0,
|
||||||
// Some textuary stuff
|
// Some textuary stuff
|
||||||
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
|
0,
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#else
|
||||||
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#endif
|
||||||
|
20, 20,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
|
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
|
||||||
// Add a title to the button
|
// Add a title to the button
|
||||||
@@ -121,9 +135,7 @@ public class UpdateModScreen extends DhScreen
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
this.addBtn( // Later (not now)
|
this.addBtn( // Later (not now)
|
||||||
MakeBtn(Translatable(ModInfo.ID + ".updater.later"), this.width / 2 + 2, this.height / 2 + 70, 100, 20, (btn) -> {
|
MakeBtn(Translatable(ModInfo.ID + ".updater.later"), this.width / 2 + 2, this.height / 2 + 70, 100, 20, (btn) -> this.onClose())
|
||||||
this.onClose();
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
this.addBtn( // Never
|
this.addBtn( // Never
|
||||||
MakeBtn(Translatable(ModInfo.ID + ".updater.never"), this.width / 2 - 102, this.height / 2 + 70, 100, 20, (btn) -> {
|
MakeBtn(Translatable(ModInfo.ID + ".updater.never"), this.width / 2 - 102, this.height / 2 + 70, 100, 20, (btn) -> {
|
||||||
@@ -147,17 +159,15 @@ public class UpdateModScreen extends DhScreen
|
|||||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: add the tooltips for the buttons
|
||||||
|
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
|
||||||
|
// 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);
|
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text1"), this.width / 2, this.height / 2 - 35, 0xFFFFFF);
|
||||||
DhDrawCenteredString(matrices, this.font,
|
DhDrawCenteredString(matrices, this.font,
|
||||||
Translatable(ModInfo.ID + ".updater.text2", currentVer, nextVer),
|
Translatable(ModInfo.ID + ".updater.text2", currentVer, nextVer),
|
||||||
this.width / 2, this.height / 2 - 20, 0x52FD52);
|
this.width / 2, this.height / 2 - 20, 0x52FD52);
|
||||||
|
|
||||||
// TODO: add the tooltips for the buttons
|
|
||||||
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
|
|
||||||
|
|
||||||
// TODO: Add tooltips
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+71
-82
@@ -31,6 +31,7 @@ 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.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
|
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
@@ -43,6 +44,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|||||||
|
|
||||||
import net.minecraft.CrashReport;
|
import net.minecraft.CrashReport;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ServerData;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@@ -59,16 +61,15 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* A singleton that wraps the Minecraft object.
|
* A singleton that wraps the Minecraft object.
|
||||||
*
|
*
|
||||||
* @author James Seibel
|
* @author James Seibel
|
||||||
* @version 3-5-2022
|
|
||||||
*/
|
*/
|
||||||
//@Environment(EnvType.CLIENT)
|
|
||||||
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
||||||
|
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||||
|
|
||||||
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
||||||
|
|
||||||
public final Minecraft mc = Minecraft.getInstance();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The lightmap for the current:
|
* The lightmap for the current:
|
||||||
@@ -99,10 +100,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
* This doesn't affect OpenGL objects in any way.
|
* This doesn't affect OpenGL objects in any way.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clearFrameObjectCache()
|
public void clearFrameObjectCache() { this.lightMap = null; }
|
||||||
{
|
|
||||||
lightMap = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -118,10 +116,10 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case AUTO:
|
case AUTO:
|
||||||
if (this.mc.level != null)
|
if (MINECRAFT.level != null)
|
||||||
{
|
{
|
||||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||||
return this.mc.level.getShade(mcDir, true);
|
return MINECRAFT.level.getShade(mcDir, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -129,20 +127,12 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ENABLED:
|
case ENABLED:
|
||||||
switch (lodDirection)
|
return switch (lodDirection) {
|
||||||
{
|
case DOWN -> 0.5F;
|
||||||
case DOWN:
|
default -> 1.0F;
|
||||||
return 0.5F;
|
case NORTH, SOUTH -> 0.8F;
|
||||||
default:
|
case WEST, EAST -> 0.6F;
|
||||||
case UP:
|
};
|
||||||
return 1.0F;
|
|
||||||
case NORTH:
|
|
||||||
case SOUTH:
|
|
||||||
return 0.8F;
|
|
||||||
case WEST:
|
|
||||||
case EAST:
|
|
||||||
return 0.6F;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DISABLED:
|
case DISABLED:
|
||||||
return 1.0F;
|
return 1.0F;
|
||||||
@@ -150,47 +140,63 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasSinglePlayerServer() { return mc.hasSingleplayerServer(); }
|
public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); }
|
||||||
@Override
|
@Override
|
||||||
public boolean clientConnectedToDedicatedServer() { return mc.getCurrentServer() != null && !this.hasSinglePlayerServer(); }
|
public boolean clientConnectedToDedicatedServer() { return MINECRAFT.getCurrentServer() != null && !this.hasSinglePlayerServer(); }
|
||||||
|
@Override
|
||||||
|
public boolean connectedToReplay() { return !MINECRAFT.hasSingleplayerServer() && MINECRAFT.getCurrentServer() == null; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerName() { return mc.getCurrentServer().name; }
|
public String getCurrentServerName()
|
||||||
|
{
|
||||||
|
if (this.connectedToReplay())
|
||||||
|
{
|
||||||
|
return ClientOnlySaveStructure.REPLAY_SERVER_FOLDER_NAME;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerData server = MINECRAFT.getCurrentServer();
|
||||||
|
return (server != null) ? server.name : "NULL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerIp() { return mc.getCurrentServer().ip; }
|
public String getCurrentServerIp()
|
||||||
|
{
|
||||||
|
if (this.connectedToReplay())
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerData server = MINECRAFT.getCurrentServer();
|
||||||
|
return (server != null) ? server.ip : "NA";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerVersion()
|
public String getCurrentServerVersion()
|
||||||
{
|
{
|
||||||
return mc.getCurrentServer().version.getString();
|
ServerData server = MINECRAFT.getCurrentServer();
|
||||||
|
return (server != null) ? server.version.getString() : "UNKOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
// Simple gets //
|
// Simple gets //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public LocalPlayer getPlayer()
|
public LocalPlayer getPlayer() { return MINECRAFT.player; }
|
||||||
{
|
|
||||||
return mc.player;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean playerExists()
|
public boolean playerExists() { return MINECRAFT.player != null; }
|
||||||
{
|
|
||||||
return mc.player != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID getPlayerUUID()
|
public UUID getPlayerUUID() { return this.getPlayer().getUUID(); }
|
||||||
{
|
|
||||||
return getPlayer().getUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DhBlockPos getPlayerBlockPos()
|
public DhBlockPos getPlayerBlockPos()
|
||||||
{
|
{
|
||||||
BlockPos playerPos = getPlayer().blockPosition();
|
BlockPos playerPos = this.getPlayer().blockPosition();
|
||||||
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,55 +204,47 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
public DhChunkPos getPlayerChunkPos()
|
public DhChunkPos getPlayerChunkPos()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
ChunkPos playerPos = new ChunkPos(getPlayer().blockPosition());
|
ChunkPos playerPos = new ChunkPos(this.getPlayer().blockPosition());
|
||||||
#else
|
#else
|
||||||
ChunkPos playerPos = getPlayer().chunkPosition();
|
ChunkPos playerPos = this.getPlayer().chunkPosition();
|
||||||
#endif
|
#endif
|
||||||
return new DhChunkPos(playerPos.x, playerPos.z);
|
return new DhChunkPos(playerPos.x, playerPos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelManager getModelManager()
|
|
||||||
{
|
|
||||||
return mc.getModelManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IClientLevelWrapper getWrappedClientLevel()
|
public IClientLevelWrapper getWrappedClientLevel()
|
||||||
{
|
{
|
||||||
if (this.mc.level == null)
|
if (MINECRAFT.level == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ClientLevelWrapper.getWrapperIgnoringOverride(this.mc.level);
|
return ClientLevelWrapper.getWrapperIgnoringOverride(MINECRAFT.level);
|
||||||
}
|
|
||||||
|
|
||||||
/** Please move over to getInstallationDirectory() */
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public File getGameDirectory()
|
|
||||||
{
|
|
||||||
return getInstallationDirectory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IProfilerWrapper getProfiler()
|
public IProfilerWrapper getProfiler()
|
||||||
{
|
{
|
||||||
if (profilerWrapper == null)
|
if (this.profilerWrapper == null)
|
||||||
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
|
{
|
||||||
else if (mc.getProfiler() != profilerWrapper.profiler)
|
this.profilerWrapper = new ProfilerWrapper(MINECRAFT.getProfiler());
|
||||||
profilerWrapper.profiler = mc.getProfiler();
|
}
|
||||||
return profilerWrapper;
|
else if (MINECRAFT.getProfiler() != this.profilerWrapper.profiler)
|
||||||
|
{
|
||||||
|
this.profilerWrapper.profiler = MINECRAFT.getProfiler();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.profilerWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns all worlds available to the server */
|
/** Returns all worlds available to the server */
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<ILevelWrapper> getAllServerWorlds()
|
public ArrayList<ILevelWrapper> getAllServerWorlds()
|
||||||
{
|
{
|
||||||
ArrayList<ILevelWrapper> worlds = new ArrayList<ILevelWrapper>();
|
ArrayList<ILevelWrapper> worlds = new ArrayList<>();
|
||||||
|
|
||||||
Iterable<ServerLevel> serverWorlds = mc.getSingleplayerServer().getAllLevels();
|
Iterable<ServerLevel> serverWorlds = MINECRAFT.getSingleplayerServer().getAllLevels();
|
||||||
for (ServerLevel world : serverWorlds)
|
for (ServerLevel world : serverWorlds)
|
||||||
{
|
{
|
||||||
worlds.add(ServerLevelWrapper.getWrapper(world));
|
worlds.add(ServerLevelWrapper.getWrapper(world));
|
||||||
@@ -260,12 +258,12 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
@Override
|
@Override
|
||||||
public void sendChatMessage(String string)
|
public void sendChatMessage(String string)
|
||||||
{
|
{
|
||||||
LocalPlayer p = getPlayer();
|
LocalPlayer player = this.getPlayer();
|
||||||
if (p == null) return;
|
if (player == null) return;
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
p.sendMessage(new TextComponent(string), getPlayer().getUUID());
|
player.sendMessage(new TextComponent(string), getPlayer().getUUID());
|
||||||
#else
|
#else
|
||||||
p.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string));
|
player.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,24 +288,15 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getOptionsObject()
|
public Object getOptionsObject() { return MINECRAFT.options; }
|
||||||
{
|
|
||||||
return mc.options;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDedicatedServer()
|
public boolean isDedicatedServer() { return false; }
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getInstallationDirectory()
|
public File getInstallationDirectory() { return MINECRAFT.gameDirectory; }
|
||||||
{
|
|
||||||
return mc.gameDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeOnRenderThread(Runnable runnable) { this.mc.execute(runnable); }
|
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -12,16 +12,20 @@ public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper
|
|||||||
private MinecraftDedicatedServerWrapper() { }
|
private MinecraftDedicatedServerWrapper() { }
|
||||||
public DedicatedServer dedicatedServer = null;
|
public DedicatedServer dedicatedServer = null;
|
||||||
@Override
|
@Override
|
||||||
public boolean isDedicatedServer()
|
public boolean isDedicatedServer() { return true; }
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public File getInstallationDirectory()
|
public File getInstallationDirectory()
|
||||||
{
|
{
|
||||||
if (dedicatedServer == null)
|
if (this.dedicatedServer == null)
|
||||||
|
{
|
||||||
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!");
|
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!");
|
||||||
return dedicatedServer.getServerDirectory();
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
return this.dedicatedServer.getServerDirectory();
|
||||||
|
#else
|
||||||
|
return this.dedicatedServer.getServerDirectory().toFile();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-16
@@ -21,10 +21,9 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||||
@@ -37,10 +36,10 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
#else
|
#else
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
@@ -54,9 +53,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOpt
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
@@ -80,7 +79,6 @@ import net.minecraft.world.level.material.FogType;
|
|||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.joml.Matrix4f;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +103,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
||||||
* Requiring the use of multiple {@link LightMapWrapper}.
|
* Requiring the use of multiple {@link LightMapWrapper}.
|
||||||
*/
|
*/
|
||||||
public HashMap<IDimensionTypeWrapper, LightMapWrapper> lightmapByDimensionType = new HashMap<>();
|
public ConcurrentHashMap<IDimensionTypeWrapper, LightMapWrapper> lightmapByDimensionType = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the render buffer that should be used when displaying levels to the screen.
|
* Holds the render buffer that should be used when displaying levels to the screen.
|
||||||
@@ -211,15 +209,24 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
{
|
{
|
||||||
if (MC.level.dimensionType().hasSkyLight())
|
if (MC.level.dimensionType().hasSkyLight())
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
float frameTime;
|
||||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), MC.getFrameTime());
|
#if MC_VER < MC_1_21
|
||||||
|
frameTime = MC.getFrameTime();
|
||||||
#else
|
#else
|
||||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
|
frameTime = MC.getTimer().getRealtimeDeltaTicks();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_17_1
|
||||||
|
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime);
|
||||||
|
#else
|
||||||
|
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
|
||||||
#endif
|
#endif
|
||||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return new Color(0, 0, 0);
|
return new Color(0, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -405,11 +412,8 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
// so this will have to do for now
|
// so this will have to do for now
|
||||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||||
|
|
||||||
if (!this.lightmapByDimensionType.containsKey(dimensionType))
|
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||||
{
|
wrapper.uploadLightmap(lightPixels);
|
||||||
this.lightmapByDimensionType.put(dimensionType, new LightMapWrapper());
|
|
||||||
}
|
|
||||||
this.lightmapByDimensionType.get(dimensionType).uploadLightmap(lightPixels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -36,14 +36,6 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
|
|
||||||
public LightMapWrapper() { }
|
public LightMapWrapper() { }
|
||||||
|
|
||||||
private void createLightmap(NativeImage image)
|
|
||||||
{
|
|
||||||
this.textureId = GL32.glGenTextures();
|
|
||||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
|
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
|
||||||
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========//
|
//=========//
|
||||||
@@ -53,14 +45,25 @@ public class LightMapWrapper implements ILightMapWrapper
|
|||||||
public void uploadLightmap(NativeImage image)
|
public void uploadLightmap(NativeImage image)
|
||||||
{
|
{
|
||||||
int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
|
|
||||||
if (this.textureId == 0)
|
if (this.textureId == 0)
|
||||||
{
|
{
|
||||||
this.createLightmap(image);
|
this.createLightmap(image);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
|
||||||
|
}
|
||||||
image.upload(0, 0, 0, false);
|
image.upload(0, 0, 0, false);
|
||||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind);
|
GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind);
|
||||||
}
|
}
|
||||||
|
private void createLightmap(NativeImage image)
|
||||||
|
{
|
||||||
|
this.textureId = GL32.glGenTextures();
|
||||||
|
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
|
||||||
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
|
||||||
|
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bind()
|
public void bind()
|
||||||
|
|||||||
+68
-9
@@ -1,7 +1,7 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.world;
|
package com.seibel.distanthorizons.common.wrappers.world;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper;
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||||
@@ -9,7 +9,7 @@ import com.seibel.distanthorizons.common.wrappers.block.cache.ClientBlockDetailM
|
|||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
|
import com.seibel.distanthorizons.core.level.*;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
@@ -19,13 +19,11 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
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.level.chunk.ChunkStatus;
|
|
||||||
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,16 +31,27 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
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<>();
|
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); // TODO can leak
|
||||||
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 final ClientLevel level;
|
private final ClientLevel level;
|
||||||
private final ClientBlockDetailMap blockMap = new ClientBlockDetailMap(this);
|
private final ClientBlockDetailMap blockMap = new ClientBlockDetailMap(this);
|
||||||
|
|
||||||
private BlockStateWrapper dirtBlockWrapper;
|
private BlockStateWrapper dirtBlockWrapper;
|
||||||
|
private BiomeWrapper plainsBiomeWrapper;
|
||||||
|
@Deprecated // TODO circular references are bad
|
||||||
|
private IDhLevel parentDhLevel;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +91,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Iterable<ServerLevel> serverLevels = MinecraftClientWrapper.INSTANCE.mc.getSingleplayerServer().getAllLevels();
|
Iterable<ServerLevel> serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels();
|
||||||
|
|
||||||
// attempt to find the server level with the same dimension type
|
// attempt to find the server level with the same dimension type
|
||||||
// TODO this assumes only one level per dimension type, the SubDimensionLevelMatcher will need to be added for supporting multiple levels per dimension
|
// TODO this assumes only one level per dimension type, the SubDimensionLevelMatcher will need to be added for supporting multiple levels per dimension
|
||||||
@@ -139,6 +148,26 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
return this.blockMap.getColor(this.dirtBlockWrapper.blockState, BiomeWrapper.EMPTY_WRAPPER, DhBlockPos.ZERO);
|
return this.blockMap.getColor(this.dirtBlockWrapper.blockState, BiomeWrapper.EMPTY_WRAPPER, DhBlockPos.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBiomeWrapper getPlainsBiomeWrapper()
|
||||||
|
{
|
||||||
|
if (this.plainsBiomeWrapper == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.plainsBiomeWrapper = (BiomeWrapper) BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, this);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
LOGGER.warn("Unable to get planes biome with resource location ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"] with level ["+this+"].", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.plainsBiomeWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
|
public IDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
|
||||||
|
|
||||||
@@ -154,7 +183,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); }
|
public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight() { return this.level.getHeight(); }
|
public int getMaxHeight() { return this.level.getHeight(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMinHeight()
|
public int getMinHeight()
|
||||||
@@ -203,7 +232,37 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
public ClientLevel getWrappedMcObject() { return this.level; }
|
public ClientLevel getWrappedMcObject() { return this.level; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnload() { LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level); }
|
public void onUnload()
|
||||||
|
{
|
||||||
|
LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level);
|
||||||
|
this.parentDhLevel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// generic rendering //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDhApiCustomRenderRegister getRenderRegister()
|
||||||
|
{
|
||||||
|
if (this.parentDhLevel == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.parentDhLevel.getGenericRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
|
|||||||
+33
-22
@@ -23,12 +23,14 @@ import java.io.File;
|
|||||||
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;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.cache.ServerBlockDetailMap;
|
import com.seibel.distanthorizons.common.wrappers.block.cache.ServerBlockDetailMap;
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
@@ -41,7 +43,12 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
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;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -54,8 +61,9 @@ 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<>();
|
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper> LEVEL_WRAPPER_BY_SERVER_LEVEL = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
final ServerLevel level;
|
private final ServerLevel level;
|
||||||
ServerBlockDetailMap blockMap = new ServerBlockDetailMap(this);
|
@Deprecated // TODO circular references are bad
|
||||||
|
private IDhLevel parentDhLevel;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -76,19 +84,6 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
// methods //
|
// methods //
|
||||||
//=========//
|
//=========//
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IClientLevelWrapper tryGetClientLevelWrapper()
|
|
||||||
{
|
|
||||||
MinecraftClientWrapper client = MinecraftClientWrapper.INSTANCE;
|
|
||||||
if (client.mc.level == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ClientLevelWrapper.getWrapper(client.mc.level);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getSaveFolder()
|
public File getSaveFolder()
|
||||||
{
|
{
|
||||||
@@ -122,7 +117,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight()
|
public int getMaxHeight()
|
||||||
{
|
{
|
||||||
return level.getHeight();
|
return level.getHeight();
|
||||||
}
|
}
|
||||||
@@ -136,6 +131,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
return level.getMinBuildHeight();
|
return level.getMinBuildHeight();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IChunkWrapper tryGetChunk(DhChunkPos pos)
|
public IChunkWrapper tryGetChunk(DhChunkPos pos)
|
||||||
{
|
{
|
||||||
@@ -166,18 +162,33 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerLevel getWrappedMcObject()
|
public ServerLevel getWrappedMcObject() { return this.level; }
|
||||||
{
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); }
|
public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDhApiCustomRenderRegister getRenderRegister()
|
||||||
{
|
{
|
||||||
return "Wrapped{" + level.toString() + "@" + getDimensionType().getDimensionName() + "}";
|
if (this.parentDhLevel == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.parentDhLevel.getGenericRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDimensionType().getDimensionName() + "}"; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+252
-186
@@ -35,6 +35,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|||||||
import com.seibel.distanthorizons.core.util.objects.EventTimer;
|
import com.seibel.distanthorizons.core.util.objects.EventTimer;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvironmentWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvironmentWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
@@ -66,7 +67,6 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.chunk.UpgradeData;
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
@@ -79,6 +79,12 @@ import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
|||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Total: 3.135214124s
|
Total: 3.135214124s
|
||||||
=====================================
|
=====================================
|
||||||
@@ -104,8 +110,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
||||||
() -> Config.Client.Advanced.Logging.logWorldGenLoadEvent.get());
|
() -> Config.Client.Advanced.Logging.logWorldGenLoadEvent.get());
|
||||||
|
|
||||||
//TODO: Make actual proper support for StarLight
|
|
||||||
|
|
||||||
public static class PerfCalculator
|
public static class PerfCalculator
|
||||||
{
|
{
|
||||||
private static final String[] TIME_NAMES = {
|
private static final String[] TIME_NAMES = {
|
||||||
@@ -143,7 +147,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
if (index == -1) continue;
|
if (index == -1) continue;
|
||||||
times.get(index).add(e.timeNs);
|
times.get(index).add(e.timeNs);
|
||||||
}
|
}
|
||||||
times.get(0).add(event.getTotalTimeNs());
|
times.getFirst().add(event.getTotalTimeNs());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
@@ -289,6 +293,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================//
|
||||||
|
// synchronization //
|
||||||
|
//=================//
|
||||||
|
|
||||||
public <T> T joinSync(CompletableFuture<T> future)
|
public <T> T joinSync(CompletableFuture<T> future)
|
||||||
{
|
{
|
||||||
@@ -339,8 +346,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
}
|
}
|
||||||
else if (event.hasTimeout(Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get(), TimeUnit.SECONDS))
|
else if (event.hasTimeout(Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get(), TimeUnit.SECONDS))
|
||||||
{
|
{
|
||||||
EVENT_LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
EVENT_LOGGER.warn(
|
||||||
EVENT_LOGGER.info("Dump PrefEvent: " + event.timer);
|
"Batching World Generator: [" + event + "] timed out and terminated after ["+Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get()+"] seconds. " +
|
||||||
|
"\nYour computer might be overloaded or your world gen mods might be causing world gen to take longer than expected. " +
|
||||||
|
"\nEither increase DH's world gen timeout or reduce your computer's CPU load.");
|
||||||
|
EVENT_LOGGER.debug("Dump PrefEvent: " + event.timer);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!event.terminate())
|
if (!event.terminate())
|
||||||
@@ -363,31 +373,196 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ProtoChunk EmptyChunk(ServerLevel level, ChunkPos chunkPos)
|
|
||||||
{
|
|
||||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY
|
|
||||||
#if MC_VER >= MC_1_17_1 , level #endif
|
|
||||||
#if MC_VER >= MC_1_18_2 , level.registryAccess().registryOrThrow(
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
Registry.BIOME_REGISTRY
|
|
||||||
#else
|
|
||||||
Registries.BIOME
|
|
||||||
#endif
|
|
||||||
), null #endif
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkAccess loadOrMakeChunk(ChunkPos chunkPos)
|
|
||||||
|
//==================//
|
||||||
|
// world generation //
|
||||||
|
//==================//
|
||||||
|
|
||||||
|
public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException
|
||||||
|
{
|
||||||
|
EVENT_LOGGER.debug("Lod Generate Event: " + genEvent.minPos);
|
||||||
|
|
||||||
|
ArrayGridList<ChunkWrapper> chunkWrapperList;
|
||||||
|
DhLitWorldGenRegion region;
|
||||||
|
DummyLightEngine dummyLightEngine;
|
||||||
|
LightGetterAdaptor adaptor;
|
||||||
|
|
||||||
|
int borderSize = MaxBorderNeeded;
|
||||||
|
int refSize = genEvent.size + borderSize * 2;
|
||||||
|
int refPosX = genEvent.minPos.x - borderSize;
|
||||||
|
int refPosZ = genEvent.minPos.z - borderSize;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ArrayGridList<ChunkAccess> totalChunks;
|
||||||
|
|
||||||
|
adaptor = new LightGetterAdaptor(this.params.level);
|
||||||
|
dummyLightEngine = new DummyLightEngine(adaptor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============================//
|
||||||
|
// try getting existing chunks //
|
||||||
|
//=============================//
|
||||||
|
|
||||||
|
HashMap<DhChunkPos, ChunkLightStorage> chunkSkyLightingByDhPos = new HashMap<>();
|
||||||
|
HashMap<DhChunkPos, ChunkLightStorage> chunkBlockLightingByDhPos = new HashMap<>();
|
||||||
|
IEmptyChunkGeneratorFunc emptyChunkGeneratorFunc = (int x, int z) ->
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||||
|
DhChunkPos dhChunkPos = new DhChunkPos(x, z);
|
||||||
|
ChunkAccess newChunk = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// get the chunk
|
||||||
|
CompoundTag chunkData = this.getChunkNbtData(chunkPos);
|
||||||
|
newChunk = this.loadOrMakeChunk(chunkPos, chunkData);
|
||||||
|
|
||||||
|
if (Config.Client.Advanced.LodBuilding.pullLightingForPregeneratedChunks.get())
|
||||||
|
{
|
||||||
|
// attempt to get chunk lighting
|
||||||
|
ChunkLoader.CombinedChunkLightStorage combinedLights = ChunkLoader.readLight(newChunk, chunkData);
|
||||||
|
if (combinedLights != null)
|
||||||
|
{
|
||||||
|
chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage);
|
||||||
|
chunkBlockLightingByDhPos.put(dhChunkPos, combinedLights.blockLightStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (RuntimeException loadChunkError)
|
||||||
|
{
|
||||||
|
// Continue...
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newChunk == null)
|
||||||
|
{
|
||||||
|
newChunk = new ProtoChunk(chunkPos, UpgradeData.EMPTY
|
||||||
|
#if MC_VER >= MC_1_17_1 , this.params.level #endif
|
||||||
|
#if MC_VER >= MC_1_18_2 , this.params.biomes, null #endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newChunk;
|
||||||
|
};
|
||||||
|
totalChunks = new ArrayGridList<>(refSize, (x, z) -> emptyChunkGeneratorFunc.generate(x + refPosX, z + refPosZ));
|
||||||
|
|
||||||
|
int radius = refSize / 2;
|
||||||
|
int centerX = refPosX + radius;
|
||||||
|
int centerZ = refPosZ + radius;
|
||||||
|
|
||||||
|
ChunkAccess centerChunk = totalChunks.stream().filter(chunk -> chunk.getPos().x == centerX && chunk.getPos().z == centerZ).findFirst().get();
|
||||||
|
|
||||||
|
genEvent.refreshTimeout();
|
||||||
|
region = new DhLitWorldGenRegion(
|
||||||
|
centerX, centerZ,
|
||||||
|
centerChunk,
|
||||||
|
this.params.level, dummyLightEngine, totalChunks,
|
||||||
|
ChunkStatus.STRUCTURE_STARTS, radius, emptyChunkGeneratorFunc);
|
||||||
|
adaptor.setRegion(region);
|
||||||
|
genEvent.threadedParam.makeStructFeat(region, this.params);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================//
|
||||||
|
// create chunk wrappers //
|
||||||
|
//=======================//
|
||||||
|
|
||||||
|
chunkWrapperList = new ArrayGridList<>(totalChunks.gridSize);
|
||||||
|
totalChunks.forEachPos((x, z) ->
|
||||||
|
{
|
||||||
|
ChunkAccess chunk = totalChunks.get(x, z);
|
||||||
|
if (chunk != null)
|
||||||
|
{
|
||||||
|
// wrap the chunk
|
||||||
|
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, region, this.serverlevel.getLevelWrapper());
|
||||||
|
chunkWrapperList.set(x, z, chunkWrapper);
|
||||||
|
|
||||||
|
// try setting the wrapper's lighting
|
||||||
|
if (chunkBlockLightingByDhPos.containsKey(chunkWrapper.getChunkPos()))
|
||||||
|
{
|
||||||
|
chunkWrapper.setBlockLightStorage(chunkBlockLightingByDhPos.get(chunkWrapper.getChunkPos()));
|
||||||
|
chunkWrapper.setSkyLightStorage(chunkSkyLightingByDhPos.get(chunkWrapper.getChunkPos()));
|
||||||
|
chunkWrapper.setUseDhLighting(true);
|
||||||
|
chunkWrapper.setIsDhLightCorrect(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================//
|
||||||
|
// generate chunks //
|
||||||
|
//=================//
|
||||||
|
|
||||||
|
this.generateDirect(genEvent, chunkWrapperList, borderSize, genEvent.targetGenerationStep, region);
|
||||||
|
genEvent.timer.nextEvent("cleanup");
|
||||||
|
}
|
||||||
|
catch (StepStructureStart.StructStartCorruptedException f)
|
||||||
|
{
|
||||||
|
genEvent.threadedParam.markAsInvalid();
|
||||||
|
throw (RuntimeException) f.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayGridList<ChunkWrapper> finalGenChunks = GetCutoutFrom(chunkWrapperList, borderSize);
|
||||||
|
for (int offsetY = 0; offsetY < finalGenChunks.gridSize; offsetY++)
|
||||||
|
{
|
||||||
|
for (int offsetX = 0; offsetX < finalGenChunks.gridSize; offsetX++)
|
||||||
|
{
|
||||||
|
ChunkWrapper wrappedChunk = finalGenChunks.get(offsetX, offsetY);
|
||||||
|
ChunkAccess target = wrappedChunk.getChunk();
|
||||||
|
if (target instanceof LevelChunk)
|
||||||
|
{
|
||||||
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
|
((LevelChunk) target).setLoaded(true);
|
||||||
|
#else
|
||||||
|
((LevelChunk) target).loaded = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wrappedChunk.isLightCorrect())
|
||||||
|
{
|
||||||
|
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isFull = ChunkWrapper.getStatus(target) == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
boolean isPartial = target.isOldNoiseGeneration();
|
||||||
|
#endif
|
||||||
|
if (isFull)
|
||||||
|
{
|
||||||
|
LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||||
|
genEvent.resultConsumer.accept(wrappedChunk);
|
||||||
|
}
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
else if (isPartial)
|
||||||
|
{
|
||||||
|
LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||||
|
genEvent.resultConsumer.accept(wrappedChunk);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (ChunkWrapper.getStatus(target) == ChunkStatus.EMPTY)
|
||||||
|
{
|
||||||
|
genEvent.resultConsumer.accept(wrappedChunk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
genEvent.resultConsumer.accept(wrappedChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
genEvent.timer.complete();
|
||||||
|
genEvent.refreshTimeout();
|
||||||
|
if (PREF_LOGGER.canMaybeLog())
|
||||||
|
{
|
||||||
|
genEvent.threadedParam.perf.recordEvent(genEvent.timer);
|
||||||
|
PREF_LOGGER.infoInc("{}", genEvent.timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private CompoundTag getChunkNbtData(ChunkPos chunkPos)
|
||||||
{
|
{
|
||||||
ServerLevel level = this.params.level;
|
ServerLevel level = this.params.level;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//====================//
|
|
||||||
// get the chunk data //
|
|
||||||
//====================//
|
|
||||||
|
|
||||||
CompoundTag chunkData = null;
|
CompoundTag chunkData = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -420,15 +595,15 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e);
|
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return chunkData;
|
||||||
|
}
|
||||||
//========================//
|
private ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
// convert the chunk data //
|
{
|
||||||
//========================//
|
ServerLevel level = this.params.level;
|
||||||
|
|
||||||
if (chunkData == null)
|
if (chunkData == null)
|
||||||
{
|
{
|
||||||
return EmptyChunk(level, chunkPos);
|
return CreateEmptyChunk(level, chunkPos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -440,154 +615,28 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOAD_LOGGER.error(
|
LOAD_LOGGER.error(
|
||||||
"DistantHorizons: couldn't load or make chunk at ["+chunkPos+"]." +
|
"DistantHorizons: couldn't load or make chunk at ["+chunkPos+"]." +
|
||||||
"Please try optimizing your world to fix this issue. \n" +
|
"Please try optimizing your world to fix this issue. \n" +
|
||||||
"World optimization can be done from the singleplayer world selection screen.\n" +
|
"World optimization can be done from the singleplayer world selection screen.\n" +
|
||||||
"Error: ["+e.getMessage()+"]."
|
"Error: ["+e.getMessage()+"]."
|
||||||
, e);
|
, e);
|
||||||
|
|
||||||
return EmptyChunk(level, chunkPos);
|
return CreateEmptyChunk(level, chunkPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static ProtoChunk CreateEmptyChunk(ServerLevel level, ChunkPos chunkPos)
|
||||||
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border)
|
|
||||||
{
|
{
|
||||||
return new ArrayGridList<>(total, border, total.gridSize - border);
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY
|
||||||
}
|
#if MC_VER >= MC_1_17_1 , level #endif
|
||||||
|
#if MC_VER >= MC_1_18_2 , level.registryAccess().registryOrThrow(
|
||||||
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step)
|
#if MC_VER < MC_1_19_4
|
||||||
{
|
Registry.BIOME_REGISTRY
|
||||||
return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step));
|
#else
|
||||||
}
|
Registries.BIOME
|
||||||
|
#endif
|
||||||
public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException
|
), null #endif
|
||||||
{
|
);
|
||||||
EVENT_LOGGER.debug("Lod Generate Event: " + genEvent.minPos);
|
|
||||||
|
|
||||||
ArrayGridList<ChunkWrapper> chunkWrapperList;
|
|
||||||
DhLitWorldGenRegion region;
|
|
||||||
DummyLightEngine lightEngine;
|
|
||||||
LightGetterAdaptor adaptor;
|
|
||||||
|
|
||||||
int borderSize = MaxBorderNeeded;
|
|
||||||
int refSize = genEvent.size + borderSize * 2;
|
|
||||||
int refPosX = genEvent.minPos.x - borderSize;
|
|
||||||
int refPosZ = genEvent.minPos.z - borderSize;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ArrayGridList<ChunkAccess> totalChunks;
|
|
||||||
|
|
||||||
adaptor = new LightGetterAdaptor(this.params.level);
|
|
||||||
lightEngine = new DummyLightEngine(adaptor);
|
|
||||||
|
|
||||||
EmptyChunkGenerator generator = (int x, int z) ->
|
|
||||||
{
|
|
||||||
ChunkPos chunkPos = new ChunkPos(x, z);
|
|
||||||
ChunkAccess target = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
target = this.loadOrMakeChunk(chunkPos);
|
|
||||||
}
|
|
||||||
catch (RuntimeException e2)
|
|
||||||
{
|
|
||||||
// Continue...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target == null)
|
|
||||||
{
|
|
||||||
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY
|
|
||||||
#if MC_VER >= MC_1_17_1 , params.level #endif
|
|
||||||
#if MC_VER >= MC_1_18_2 , params.biomes, null #endif
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
};
|
|
||||||
|
|
||||||
totalChunks = new ArrayGridList<>(refSize, (x, z) -> generator.generate(x + refPosX, z + refPosZ));
|
|
||||||
|
|
||||||
genEvent.refreshTimeout();
|
|
||||||
region = new DhLitWorldGenRegion(params.level, lightEngine, totalChunks,
|
|
||||||
ChunkStatus.STRUCTURE_STARTS, refSize / 2, generator);
|
|
||||||
adaptor.setRegion(region);
|
|
||||||
genEvent.threadedParam.makeStructFeat(region, params);
|
|
||||||
|
|
||||||
|
|
||||||
chunkWrapperList = new ArrayGridList<>(totalChunks.gridSize);
|
|
||||||
totalChunks.forEachPos((x, z) ->
|
|
||||||
{
|
|
||||||
ChunkAccess chunk = totalChunks.get(x, z);
|
|
||||||
if (chunk != null)
|
|
||||||
{
|
|
||||||
chunkWrapperList.set(x, z, new ChunkWrapper(chunk, region, serverlevel.getLevelWrapper()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.generateDirect(genEvent, chunkWrapperList, borderSize, genEvent.targetGenerationStep, region);
|
|
||||||
genEvent.timer.nextEvent("cleanup");
|
|
||||||
}
|
|
||||||
catch (StepStructureStart.StructStartCorruptedException f)
|
|
||||||
{
|
|
||||||
genEvent.threadedParam.markAsInvalid();
|
|
||||||
throw (RuntimeException) f.getCause();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayGridList<ChunkWrapper> finalGenChunks = GetCutoutFrom(chunkWrapperList, borderSize);
|
|
||||||
for (int offsetY = 0; offsetY < finalGenChunks.gridSize; offsetY++)
|
|
||||||
{
|
|
||||||
for (int offsetX = 0; offsetX < finalGenChunks.gridSize; offsetX++)
|
|
||||||
{
|
|
||||||
ChunkWrapper wrappedChunk = finalGenChunks.get(offsetX, offsetY);
|
|
||||||
ChunkAccess target = wrappedChunk.getChunk();
|
|
||||||
if (target instanceof LevelChunk)
|
|
||||||
{
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
|
||||||
((LevelChunk) target).setLoaded(true);
|
|
||||||
#else
|
|
||||||
((LevelChunk) target).loaded = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wrappedChunk.isLightCorrect())
|
|
||||||
{
|
|
||||||
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
boolean isPartial = target.isOldNoiseGeneration();
|
|
||||||
#endif
|
|
||||||
if (isFull)
|
|
||||||
{
|
|
||||||
LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
|
||||||
genEvent.resultConsumer.accept(wrappedChunk);
|
|
||||||
}
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
else if (isPartial)
|
|
||||||
{
|
|
||||||
LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
|
||||||
genEvent.resultConsumer.accept(wrappedChunk);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (target.getStatus() == ChunkStatus.EMPTY)
|
|
||||||
{
|
|
||||||
genEvent.resultConsumer.accept(wrappedChunk);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
genEvent.resultConsumer.accept(wrappedChunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
genEvent.timer.complete();
|
|
||||||
genEvent.refreshTimeout();
|
|
||||||
if (PREF_LOGGER.canMaybeLog())
|
|
||||||
{
|
|
||||||
genEvent.threadedParam.perf.recordEvent(genEvent.timer);
|
|
||||||
PREF_LOGGER.infoInc("{}", genEvent.timer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateDirect(
|
public void generateDirect(
|
||||||
@@ -604,9 +653,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
chunksToGenerate.forEach((chunkWrapper) ->
|
chunksToGenerate.forEach((chunkWrapper) ->
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk instanceof ProtoChunk)
|
if (chunk instanceof ProtoChunk protoChunk)
|
||||||
{
|
{
|
||||||
ProtoChunk protoChunk = ((ProtoChunk) chunk);
|
|
||||||
|
|
||||||
protoChunk.setLightEngine(region.getLightEngine());
|
protoChunk.setLightEngine(region.getLightEngine());
|
||||||
}
|
}
|
||||||
@@ -689,7 +737,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
for (int i = 0; i < chunksToGenerate.size(); i++) // regular for loop since enhanced for loops increase GC pressure slightly
|
for (int i = 0; i < chunksToGenerate.size(); i++) // regular for loop since enhanced for loops increase GC pressure slightly
|
||||||
{
|
{
|
||||||
ChunkWrapper chunkWrapper = chunksToGenerate.get(i);
|
ChunkWrapper chunkWrapper = chunksToGenerate.get(i);
|
||||||
if (chunkWrapper.getChunk().getStatus() != ChunkStatus.EMPTY)
|
if (chunkWrapper.getStatus() != ChunkStatus.EMPTY)
|
||||||
{
|
{
|
||||||
iChunkWrapperList.add(chunkWrapper);
|
iChunkWrapperList.add(chunkWrapper);
|
||||||
}
|
}
|
||||||
@@ -710,19 +758,19 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
// if this isn't done everything else afterward may fail
|
// if this isn't done everything else afterward may fail
|
||||||
Heightmap.primeHeightmaps(((ChunkWrapper)centerChunk).getChunk(), ChunkStatus.FEATURES.heightmapsAfter());
|
Heightmap.primeHeightmaps(((ChunkWrapper)centerChunk).getChunk(), ChunkStatus.FEATURES.heightmapsAfter());
|
||||||
|
|
||||||
// populate the lighting
|
// pre-generated chunks should have lighting but new ones won't
|
||||||
DhLightingEngine.INSTANCE.lightChunk(centerChunk, iChunkWrapperList, maxSkyLight);
|
if (!centerChunk.isLightCorrect())
|
||||||
|
{
|
||||||
|
DhLightingEngine.INSTANCE.lightChunk(centerChunk, iChunkWrapperList, maxSkyLight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
genEvent.refreshTimeout();
|
genEvent.refreshTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); }
|
||||||
|
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step)); }
|
||||||
|
|
||||||
public interface EmptyChunkGenerator
|
|
||||||
{
|
|
||||||
ChunkAccess generate(int x, int z);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getEventCount() { return this.generationEventList.size(); }
|
public int getEventCount() { return this.generationEventList.size(); }
|
||||||
@@ -771,6 +819,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
return genEvent.future;
|
return genEvent.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before code that may run for an extended period of time. <br>
|
* Called before code that may run for an extended period of time. <br>
|
||||||
* This is necessary to allow canceling world gen since waiting
|
* This is necessary to allow canceling world gen since waiting
|
||||||
@@ -784,4 +838,16 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface IEmptyChunkGeneratorFunc
|
||||||
|
{
|
||||||
|
ChunkAccess generate(int x, int z);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+322
-138
@@ -22,9 +22,14 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.Dynamic;
|
import com.mojang.serialization.Dynamic;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
|
|
||||||
@@ -44,6 +49,7 @@ import net.minecraft.core.registries.Registries;
|
|||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.nbt.NbtOps;
|
import net.minecraft.nbt.NbtOps;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.*;
|
import net.minecraft.world.level.*;
|
||||||
@@ -76,6 +82,14 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
|||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_20_6
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkType;
|
||||||
|
#elif MC_VER == MC_1_21
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkType;
|
||||||
|
#endif
|
||||||
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
|
||||||
|
|
||||||
@@ -95,133 +109,13 @@ public class ChunkLoader
|
|||||||
private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks";
|
private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks";
|
||||||
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
|
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
private static boolean lightingSectionErrorLogged = false;
|
||||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
BlendingData blendingData = null;
|
|
||||||
if (chunkData.contains("blending_data", 10))
|
|
||||||
{
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
|
||||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
|
|
||||||
}
|
|
||||||
return blendingData;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
|
||||||
#else
|
|
||||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registries.BIOME);
|
|
||||||
#endif
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
|
||||||
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
|
||||||
#elif MC_VER < MC_1_19_2
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
|
|
||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
|
||||||
#else
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
|
||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
int i = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
|
||||||
LevelChunkSection[] chunkSections = new LevelChunkSection[i];
|
|
||||||
|
|
||||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
|
||||||
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
|
||||||
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);
|
|
||||||
int sectionYPos = tagSection.getByte("Y");
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
|
||||||
{
|
|
||||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
|
||||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
|
||||||
tagSection.getLongArray("BlockStates"));
|
|
||||||
levelChunkSection.recalcBlockCounts();
|
|
||||||
if (!levelChunkSection.isEmpty())
|
|
||||||
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
|
||||||
= levelChunkSection;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
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 -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
|
||||||
: 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
|
|
||||||
biomeContainer = tagSection.contains("biomes", 10)
|
|
||||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)).getOrThrow(false, LOGGER::error)
|
|
||||||
: new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), 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
|
|
||||||
|
|
||||||
}
|
|
||||||
return chunkSections;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
|
||||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
|
||||||
{
|
|
||||||
String heightmap = type.getSerializationKey();
|
|
||||||
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)
|
//============//
|
||||||
{
|
// read chunk //
|
||||||
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
//============//
|
||||||
for (int n = 0; n < tagPostProcessings.size(); ++n)
|
|
||||||
{
|
|
||||||
ListTag listTag3 = tagPostProcessings.getList(n);
|
|
||||||
for (int o = 0; o < listTag3.size(); ++o)
|
|
||||||
{
|
|
||||||
chunk.addPackedPostProcess(listTag3.getShort(o), n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ChunkStatus.ChunkType readChunkType(CompoundTag tagLevel)
|
|
||||||
{
|
|
||||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
|
||||||
if (chunkStatus != null)
|
|
||||||
{
|
|
||||||
return chunkStatus.getChunkType();
|
|
||||||
}
|
|
||||||
return ChunkStatus.ChunkType.PROTOCHUNK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData)
|
public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
{
|
{
|
||||||
@@ -262,19 +156,27 @@ public class ChunkLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkStatus.ChunkType chunkType = readChunkType(tagLevel);
|
#if MC_VER < MC_1_20_6
|
||||||
#if MC_VER < MC_1_18_2
|
ChunkStatus.ChunkType chunkType;
|
||||||
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
|
||||||
return null;
|
|
||||||
#else
|
#else
|
||||||
BlendingData blendingData = readBlendingData(tagLevel);
|
ChunkType chunkType;
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
|
||||||
return null;
|
|
||||||
#else
|
|
||||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && blendingData == null)
|
|
||||||
return null;
|
|
||||||
#endif
|
#endif
|
||||||
|
chunkType = readChunkType(tagLevel);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
||||||
|
return null;
|
||||||
|
#else
|
||||||
|
|
||||||
|
BlendingData blendingData = readBlendingData(tagLevel);
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
||||||
|
return null;
|
||||||
|
#else
|
||||||
|
if (chunkType == #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK #else ChunkType.PROTOCHUNK #endif && blendingData == null)
|
||||||
|
return null;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
||||||
@@ -331,10 +233,292 @@ public class ChunkLoader
|
|||||||
readPostPocessings(chunk, chunkData);
|
readPostPocessings(chunk, chunkData);
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
private static void logErrors(ChunkPos chunkPos, int i, String string)
|
|
||||||
{
|
{
|
||||||
LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string);
|
#if MC_VER >= MC_1_18_2
|
||||||
|
#if MC_VER < MC_1_19_4
|
||||||
|
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||||
|
#else
|
||||||
|
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
#endif
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
||||||
|
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
|
||||||
|
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
||||||
|
#else
|
||||||
|
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
||||||
|
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
||||||
|
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
||||||
|
|
||||||
|
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||||
|
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
||||||
|
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);
|
||||||
|
int sectionYPos = tagSection.getByte("Y");
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||||
|
{
|
||||||
|
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
||||||
|
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
||||||
|
tagSection.getLongArray("BlockStates"));
|
||||||
|
levelChunkSection.recalcBlockCounts();
|
||||||
|
if (!levelChunkSection.isEmpty())
|
||||||
|
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
||||||
|
= levelChunkSection;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
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<>(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
|
||||||
|
|
||||||
|
biomeContainer = tagSection.contains("biomes", 10)
|
||||||
|
? 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
|
||||||
|
: new PalettedContainer<>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), 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
|
||||||
|
|
||||||
|
}
|
||||||
|
return chunkSections;
|
||||||
|
}
|
||||||
|
private static
|
||||||
|
#if MC_VER < MC_1_20_6 ChunkStatus.ChunkType
|
||||||
|
#elif MC_VER < MC_1_21 ChunkType
|
||||||
|
#else ChunkType #endif
|
||||||
|
readChunkType(CompoundTag tagLevel)
|
||||||
|
{
|
||||||
|
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
||||||
|
if (chunkStatus != null)
|
||||||
|
{
|
||||||
|
return chunkStatus.getChunkType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
#if MC_VER <= MC_1_20_4 ChunkStatus.ChunkType.PROTOCHUNK;
|
||||||
|
#else ChunkType.PROTOCHUNK; #endif
|
||||||
|
}
|
||||||
|
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
||||||
|
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||||
|
{
|
||||||
|
String heightmap = type.getSerializationKey();
|
||||||
|
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 n = 0; n < tagPostProcessings.size(); ++n)
|
||||||
|
{
|
||||||
|
ListTag listTag3 = tagPostProcessings.getList(n);
|
||||||
|
for (int o = 0; o < listTag3.size(); ++o)
|
||||||
|
{
|
||||||
|
chunk.addPackedPostProcess(listTag3.getShort(o), n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
BlendingData blendingData = null;
|
||||||
|
if (chunkData.contains("blending_data", 10))
|
||||||
|
{
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||||
|
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
|
||||||
|
}
|
||||||
|
return blendingData;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================//
|
||||||
|
// read chunk lighting //
|
||||||
|
//=====================//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://minecraft.wiki/w/Chunk_format
|
||||||
|
*/
|
||||||
|
public static CombinedChunkLightStorage readLight(ChunkAccess chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_17_1
|
||||||
|
// MC 1.16 and 1.17 doesn't have the necessary NBT info
|
||||||
|
return null;
|
||||||
|
#else
|
||||||
|
|
||||||
|
CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getMinBuildHeight(chunk), ChunkWrapper.getMaxBuildHeight(chunk));
|
||||||
|
ChunkLightStorage blockLightStorage = combinedStorage.blockLightStorage;
|
||||||
|
ChunkLightStorage skyLightStorage = combinedStorage.skyLightStorage;
|
||||||
|
|
||||||
|
boolean foundSkyLight = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// get NBT tags info //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
Tag chunkSectionTags = chunkData.get("sections");
|
||||||
|
if (chunkSectionTags == null)
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("No sections found for chunk at pos ["+chunk.getPos()+"] chunk data may be out of date.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (!(chunkSectionTags instanceof ListTag))
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("Chunk section tag list have unexpected type ["+chunkSectionTags.getClass().getName()+"], expected ["+ListTag.class.getName()+"].");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ListTag chunkSectionListTag = (ListTag) chunkSectionTags;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// get lighting info //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
for (int sectionIndex = 0; sectionIndex < chunkSectionListTag.size(); sectionIndex++)
|
||||||
|
{
|
||||||
|
Tag chunkSectionTag = chunkSectionListTag.get(sectionIndex);
|
||||||
|
if (!(chunkSectionTag instanceof CompoundTag chunkSectionCompoundTag))
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("Chunk section tag has an unexpected type ["+chunkSectionTag.getClass().getName()+"], expected ["+CompoundTag.class.getName()+"].");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if null all lights = 0
|
||||||
|
byte[] blockLightNibbleArray = chunkSectionCompoundTag.getByteArray("BlockLight");
|
||||||
|
byte[] skyLightNibbleArray = chunkSectionCompoundTag.getByteArray("SkyLight");
|
||||||
|
|
||||||
|
// if any sky light was found then all lights above will be max brightness
|
||||||
|
if (skyLightNibbleArray.length != 0)
|
||||||
|
{
|
||||||
|
foundSkyLight = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||||
|
{
|
||||||
|
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.getMinBuildHeight(chunk);
|
||||||
|
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||||
|
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedStorage;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/** source: https://minecraft.wiki/w/Chunk_format#Block_Format */
|
||||||
|
private static byte getNibbleAtIndex(byte[] arr, int index)
|
||||||
|
{
|
||||||
|
if (index % 2 == 0)
|
||||||
|
{
|
||||||
|
return (byte)(arr[index/2] & 0x0F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (byte)((arr[index/2]>>4) & 0x0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
public static class CombinedChunkLightStorage
|
||||||
|
{
|
||||||
|
public ChunkLightStorage blockLightStorage;
|
||||||
|
public ChunkLightStorage skyLightStorage;
|
||||||
|
|
||||||
|
public CombinedChunkLightStorage(int minY, int maxY)
|
||||||
|
{
|
||||||
|
this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(minY, maxY);
|
||||||
|
this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(minY, maxY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_21
|
||||||
|
|
||||||
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
|
||||||
|
public class DhGenerationChunkHolder extends GenerationChunkHolder
|
||||||
|
{
|
||||||
|
|
||||||
|
public DhGenerationChunkHolder(ChunkPos pos)
|
||||||
|
{
|
||||||
|
super(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTicketLevel() { return 0; }
|
||||||
|
@Override
|
||||||
|
public int getQueueLevel() { return 0; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+39
-8
@@ -20,9 +20,10 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
@@ -52,11 +53,23 @@ import net.minecraft.world.level.block.Blocks;
|
|||||||
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.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.*;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_21
|
||||||
|
import net.minecraft.util.StaticCache2D;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public class DhLitWorldGenRegion extends WorldGenRegion
|
public class DhLitWorldGenRegion extends WorldGenRegion
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
||||||
@@ -65,13 +78,13 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
|
|
||||||
|
|
||||||
public final DummyLightEngine lightEngine;
|
public final DummyLightEngine lightEngine;
|
||||||
public final BatchGenerationEnvironment.EmptyChunkGenerator generator;
|
public final BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator;
|
||||||
public final int writeRadius;
|
public final int writeRadius;
|
||||||
public final int size;
|
public final int size;
|
||||||
|
|
||||||
private final ChunkPos firstPos;
|
private final ChunkPos firstPos;
|
||||||
private final List<ChunkAccess> cache;
|
private final List<ChunkAccess> cache;
|
||||||
private final Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
|
private final Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Present to reduce the chance that we accidentally break underlying MC code that isn't thread safe,
|
* Present to reduce the chance that we accidentally break underlying MC code that isn't thread safe,
|
||||||
@@ -106,12 +119,30 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
|
|
||||||
|
|
||||||
public DhLitWorldGenRegion(
|
public DhLitWorldGenRegion(
|
||||||
|
int centerChunkX, int centerChunkZ,
|
||||||
|
ChunkAccess centerChunk,
|
||||||
ServerLevel serverLevel, DummyLightEngine lightEngine,
|
ServerLevel serverLevel, DummyLightEngine lightEngine,
|
||||||
List<ChunkAccess> chunkList, ChunkStatus chunkStatus, int writeRadius,
|
List<ChunkAccess> chunkList, ChunkStatus chunkStatus, int writeRadius,
|
||||||
BatchGenerationEnvironment.EmptyChunkGenerator generator)
|
BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator)
|
||||||
{
|
{
|
||||||
super(serverLevel, chunkList #if MC_VER >= MC_1_17_1 , chunkStatus, writeRadius #endif );
|
#if MC_VER == MC_1_16_5
|
||||||
this.firstPos = chunkList.get(0).getPos();
|
super(serverLevel, chunkList);
|
||||||
|
#elif MC_VER < MC_1_21
|
||||||
|
super(serverLevel, chunkList, chunkStatus, writeRadius);
|
||||||
|
#else
|
||||||
|
super(serverLevel,
|
||||||
|
StaticCache2D.create(
|
||||||
|
centerChunkX, centerChunkZ,
|
||||||
|
writeRadius * 2, (x,z) -> new DhGenerationChunkHolder(new ChunkPos(x, z))),
|
||||||
|
new ChunkStep(chunkStatus,
|
||||||
|
// reverse is needed because MC uses the index of the chunkStatus to determine how many items are in the list instead of the actual list count
|
||||||
|
new ChunkDependencies(ImmutableList.copyOf(ChunkStatus.getStatusList()).reverse()),
|
||||||
|
new ChunkDependencies(ImmutableList.copyOf(ChunkStatus.getStatusList()).reverse()),
|
||||||
|
writeRadius, (WorldGenContext var1, ChunkStep var2, StaticCache2D<GenerationChunkHolder> var3, ChunkAccess var4) -> null),
|
||||||
|
centerChunk);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
this.firstPos = chunkList.getFirst().getPos();
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
this.lightEngine = lightEngine;
|
this.lightEngine = lightEngine;
|
||||||
this.writeRadius = writeRadius;
|
this.writeRadius = writeRadius;
|
||||||
@@ -274,7 +305,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
private ChunkAccess getChunkAccess(int chunkX, int chunkZ, ChunkStatus chunkStatus, boolean returnNonNull)
|
private ChunkAccess getChunkAccess(int chunkX, int chunkZ, ChunkStatus chunkStatus, boolean returnNonNull)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = this.superHasChunk(chunkX, chunkZ) ? this.superGetChunk(chunkX, chunkZ) : null;
|
ChunkAccess chunk = this.superHasChunk(chunkX, chunkZ) ? this.superGetChunk(chunkX, chunkZ) : null;
|
||||||
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus))
|
if (chunk != null && ChunkWrapper.getStatus(chunk).isOrAfter(chunkStatus))
|
||||||
{
|
{
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -23,15 +23,24 @@ import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||||
|
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER >= MC_1_17_1
|
||||||
import net.minecraft.world.level.LevelHeightAccessor;
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.LightChunkGetter;
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER >= MC_1_20_1
|
||||||
import net.minecraft.world.level.chunk.LightChunk;
|
import net.minecraft.world.level.chunk.LightChunk;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class LightGetterAdaptor implements LightChunkGetter
|
public class LightGetterAdaptor implements LightChunkGetter
|
||||||
{
|
{
|
||||||
private final BlockGetter heightGetter;
|
private final BlockGetter heightGetter;
|
||||||
|
|||||||
+7
-1
@@ -17,6 +17,10 @@ import java.nio.file.Path;
|
|||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated should be replaced with net.minecraft.world.level.chunk.storage.IOWorker to
|
* @deprecated should be replaced with net.minecraft.world.level.chunk.storage.IOWorker to
|
||||||
* prevent potential file corruption and issues with the C2ME mod.
|
* prevent potential file corruption and issues with the C2ME mod.
|
||||||
@@ -180,8 +184,10 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
Path regionFilePath = storageFolderPath.resolve("r." + pos.getRegionX() + "." + pos.getRegionZ() + ".mca");
|
Path regionFilePath = storageFolderPath.resolve("r." + pos.getRegionX() + "." + pos.getRegionZ() + ".mca");
|
||||||
#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
|
||||||
rFile = new RegionFile(regionFilePath.toFile(), storageFolderPath.toFile(), false);
|
rFile = new RegionFile(regionFilePath.toFile(), storageFolderPath.toFile(), false);
|
||||||
#else
|
#elif MC_VER <= MC_1_20_4
|
||||||
rFile = new RegionFile(regionFilePath, storageFolderPath, false);
|
rFile = new RegionFile(regionFilePath, storageFolderPath, false);
|
||||||
|
#else
|
||||||
|
rFile = new RegionFile(new RegionStorageInfo("level", null, "level type"), regionFilePath, storageFolderPath, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.regionFileCache.add(new RegionFileCache(ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ()), rFile));
|
this.regionFileCache.add(new RegionFileCache(ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ()), rFile));
|
||||||
|
|||||||
+7
-4
@@ -35,7 +35,6 @@ import net.minecraft.server.level.WorldGenRegion;
|
|||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.WorldGenLevel;
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||||
@@ -57,6 +56,12 @@ import net.minecraft.world.level.levelgen.structure.StructureStart;
|
|||||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class WorldGenStructFeatManager extends #if MC_VER < MC_1_19_2 StructureFeatureManager #else StructureManager #endif
|
public class WorldGenStructFeatManager extends #if MC_VER < MC_1_19_2 StructureFeatureManager #else StructureManager #endif
|
||||||
@@ -226,11 +231,9 @@ public class WorldGenStructFeatManager extends #if MC_VER < MC_1_19_2 StructureF
|
|||||||
Map<Structure, LongSet> map = chunk.getAllReferences();
|
Map<Structure, LongSet> map = chunk.getAllReferences();
|
||||||
|
|
||||||
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
|
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
|
||||||
Iterator<Map.Entry<Structure, LongSet>> var5 = map.entrySet().iterator();
|
|
||||||
|
|
||||||
while (var5.hasNext())
|
for (Map.Entry<Structure, LongSet> entry : map.entrySet())
|
||||||
{
|
{
|
||||||
Map.Entry<Structure, LongSet> entry = var5.next();
|
|
||||||
Structure configuredStructureFeature = entry.getKey();
|
Structure configuredStructureFeature = entry.getKey();
|
||||||
if (predicate.test(configuredStructureFeature))
|
if (predicate.test(configuredStructureFeature))
|
||||||
{
|
{
|
||||||
|
|||||||
+30
-11
@@ -27,15 +27,19 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGeneratio
|
|||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
#endif
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
public final class StepBiomes
|
public final class StepBiomes
|
||||||
{
|
{
|
||||||
public static final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
public static final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||||
@@ -52,29 +56,44 @@ public final class StepBiomes
|
|||||||
List<ChunkWrapper> chunkWrappers)
|
List<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
|
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||||
|
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
{
|
||||||
chunksToDo.add(chunk);
|
// this chunk has already generated this step
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
for (ChunkAccess chunk : chunksToDo)
|
||||||
{
|
{
|
||||||
// System.out.println("StepBiomes: "+chunk.getPos());
|
// System.out.println("StepBiomes: "+chunk.getPos());
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
environment.params.generator.createBiomes(environment.params.biomes, chunk);
|
this.environment.params.generator.createBiomes(this.environment.params.biomes, chunk);
|
||||||
#elif MC_VER < MC_1_19_2
|
#elif MC_VER < MC_1_19_2
|
||||||
chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
|
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#elif MC_VER < MC_1_19_4
|
#elif MC_VER < MC_1_19_4
|
||||||
chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, environment.params.randomState, Blender.of(worldGenRegion),
|
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
|
||||||
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
|
#elif MC_VER < MC_1_21
|
||||||
|
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#else
|
#else
|
||||||
chunk = environment.joinSync(environment.params.generator.createBiomes(Runnable::run, environment.params.randomState, Blender.of(worldGenRegion),
|
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.randomState, Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-4
@@ -27,11 +27,16 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public final class StepFeatures
|
public final class StepFeatures
|
||||||
{
|
{
|
||||||
@@ -54,14 +59,18 @@ public final class StepFeatures
|
|||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk.getStatus().isOrAfter(STATUS))
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
{
|
{
|
||||||
|
// this chunk has already generated this step
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (chunk instanceof ProtoChunk)
|
||||||
if (chunk instanceof ProtoChunk)
|
|
||||||
{
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+24
-11
@@ -28,17 +28,19 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParame
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
|
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
#if MC_VER >= MC_1_17_1
|
|
||||||
#endif
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
#endif
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
public final class StepNoise
|
public final class StepNoise
|
||||||
{
|
{
|
||||||
private static final ChunkStatus STATUS = ChunkStatus.NOISE;
|
private static final ChunkStatus STATUS = ChunkStatus.NOISE;
|
||||||
@@ -56,13 +58,21 @@ public final class StepNoise
|
|||||||
List<ChunkWrapper> chunkWrappers)
|
List<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
|
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||||
|
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
chunksToDo.add(chunk);
|
chunksToDo.add(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,15 +80,18 @@ public final class StepNoise
|
|||||||
{
|
{
|
||||||
// System.out.println("StepNoise: "+chunk.getPos());
|
// System.out.println("StepNoise: "+chunk.getPos());
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
|
this.environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
|
||||||
#elif MC_VER < MC_1_18_2
|
#elif MC_VER < MC_1_18_2
|
||||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run,
|
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#elif MC_VER < MC_1_19_2
|
#elif MC_VER < MC_1_19_2
|
||||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
||||||
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
|
#elif MC_VER < MC_1_21
|
||||||
|
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), this.environment.params.randomState,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#else
|
#else
|
||||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), environment.params.randomState,
|
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Blender.of(worldGenRegion), this.environment.params.randomState,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
#endif
|
#endif
|
||||||
UncheckedInterruptedException.throwIfInterrupted();
|
UncheckedInterruptedException.throwIfInterrupted();
|
||||||
|
|||||||
+22
-7
@@ -27,12 +27,16 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGeneratio
|
|||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
#endif
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public final class StepStructureReference
|
public final class StepStructureReference
|
||||||
{
|
{
|
||||||
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
||||||
@@ -50,14 +54,25 @@ public final class StepStructureReference
|
|||||||
List<ChunkWrapper> chunkWrappers)
|
List<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
|
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||||
|
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
{
|
||||||
chunksToDo.add(chunk);
|
// this chunk has already generated this step
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
for (ChunkAccess chunk : chunksToDo)
|
||||||
|
|||||||
+20
-5
@@ -30,10 +30,16 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParame
|
|||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public final class StepStructureStart
|
public final class StepStructureStart
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||||
@@ -70,20 +76,29 @@ public final class StepStructureStart
|
|||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (!chunk.getStatus().isOrAfter(STATUS))
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
{
|
{
|
||||||
|
// this chunk has already generated this step
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
chunksToDo.add(chunk);
|
chunksToDo.add(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
if (environment.params.worldGenSettings.generateFeatures())
|
if (this.environment.params.worldGenSettings.generateFeatures())
|
||||||
{
|
{
|
||||||
#elif MC_VER < MC_1_19_4
|
#elif MC_VER < MC_1_19_4
|
||||||
if (environment.params.worldGenSettings.generateStructures()) {
|
if (this.environment.params.worldGenSettings.generateStructures()) {
|
||||||
#else
|
#else
|
||||||
if (environment.params.worldOptions.generateStructures())
|
if (this.environment.params.worldOptions.generateStructures())
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
for (ChunkAccess chunk : chunksToDo)
|
||||||
|
|||||||
+22
-5
@@ -28,9 +28,14 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParame
|
|||||||
|
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public final class StepSurface
|
public final class StepSurface
|
||||||
{
|
{
|
||||||
@@ -53,9 +58,21 @@ public final class StepSurface
|
|||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||||
((ProtoChunk) chunk).setStatus(STATUS);
|
{
|
||||||
chunksToDo.add(chunk);
|
// this chunk has already generated this step
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
#else
|
||||||
|
((ProtoChunk) chunk).setPersistedStatus(STATUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
for (ChunkAccess chunk : chunksToDo)
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
accessWidener v1 named
|
||||||
|
|
||||||
|
# used when determining where to save files to
|
||||||
|
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
|
||||||
|
|
||||||
|
# used when rendering
|
||||||
|
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
|
||||||
|
|
||||||
|
# used for grabbing vanilla rendered chunks
|
||||||
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
|
#accessible method net/minecraft/client/renderer/LevelRenderer renderSectionLayer (Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V
|
||||||
|
|
||||||
|
# world generation
|
||||||
|
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
||||||
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|
||||||
|
# lod generation from save file
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/IOWorker storage Lnet/minecraft/world/level/chunk/storage/RegionFileStorage;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage regionCache Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage folder Ljava/nio/file/Path;
|
||||||
|
|
||||||
|
# grabbing textures
|
||||||
|
accessible class net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture
|
||||||
|
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameX (I)I
|
||||||
|
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameY (I)I
|
||||||
|
accessible field net/minecraft/client/renderer/texture/SpriteContents animatedTexture Lnet/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture;
|
||||||
|
accessible field net/minecraft/client/renderer/texture/SpriteContents originalImage Lcom/mojang/blaze3d/platform/NativeImage;
|
||||||
|
|
||||||
|
# UI stuff
|
||||||
|
accessible field net/minecraft/client/gui/components/AbstractButton SPRITES Lnet/minecraft/client/gui/components/WidgetSprites;
|
||||||
|
# Handles inserting the config button
|
||||||
|
accessible field net/minecraft/client/gui/layouts/HeaderAndFooterLayout headerFrame Lnet/minecraft/client/gui/layouts/FrameLayout;
|
||||||
|
accessible field net/minecraft/client/gui/layouts/FrameLayout children Ljava/util/List;
|
||||||
|
accessible class net/minecraft/client/gui/layouts/FrameLayout$ChildContainer
|
||||||
|
accessible field net/minecraft/client/gui/layouts/LinearLayout wrapped Lnet/minecraft/client/gui/layouts/GridLayout;
|
||||||
|
|
||||||
|
# hacky stuff
|
||||||
|
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
|
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
|
accessible field net/minecraft/client/gui/components/AbstractSelectionList scrollAmount D # Hack to bypass vanilla's setScrollAmount's clamp
|
||||||
|
|
||||||
|
|
||||||
+1
-1
Submodule coreSubProjects updated: b41e54e6a6...f767215ff0
+15
-12
@@ -23,8 +23,8 @@ loom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
remapJar {
|
remapJar {
|
||||||
inputFile = shadowJar.archiveFile
|
inputFile = shadeDowngradedApi.archiveFile
|
||||||
dependsOn shadowJar
|
dependsOn shadeDowngradedApi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ def addMod(path, enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
minecraft "com.mojang:minecraft:${minecraft_version}"
|
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||||
mappings loom.layered() {
|
mappings loom.layered() {
|
||||||
// Mojmap mappings
|
// Mojmap mappings
|
||||||
officialMojangMappings()
|
officialMojangMappings()
|
||||||
@@ -69,13 +69,15 @@ dependencies {
|
|||||||
addModJar(fabricApi.module("fabric-events-interaction-v0", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-events-interaction-v0", rootProject.fabric_api_version))
|
||||||
addModJar(fabricApi.module("fabric-rendering-v1", rootProject.fabric_api_version)) // TODO: Remove this as it is only needed in 1 line (FabricClientProxy)
|
addModJar(fabricApi.module("fabric-rendering-v1", rootProject.fabric_api_version)) // TODO: Remove this as it is only needed in 1 line (FabricClientProxy)
|
||||||
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
|
||||||
|
|
||||||
|
// used by mod menu in MC 1.20.6+
|
||||||
|
addModJar(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version))
|
||||||
|
addModJar(fabricApi.module("fabric-key-binding-api-v1", rootProject.fabric_api_version))
|
||||||
|
|
||||||
|
|
||||||
// Mod Menu
|
// Mod Menu
|
||||||
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}")
|
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Starlight
|
// Starlight
|
||||||
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
||||||
|
|
||||||
@@ -89,22 +91,23 @@ dependencies {
|
|||||||
modImplementation(fabricApi.module("fabric-rendering-data-attachment-v1", rootProject.fabric_api_version))
|
modImplementation(fabricApi.module("fabric-rendering-data-attachment-v1", rootProject.fabric_api_version))
|
||||||
modImplementation(fabricApi.module("fabric-rendering-fluids-v1", rootProject.fabric_api_version))
|
modImplementation(fabricApi.module("fabric-rendering-fluids-v1", rootProject.fabric_api_version))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lithium
|
// Lithium
|
||||||
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
|
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
|
||||||
|
|
||||||
// Iris
|
// Iris
|
||||||
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
|
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
|
||||||
|
|
||||||
// BCLib
|
// BCLib
|
||||||
addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
|
addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
|
||||||
|
|
||||||
// Canvas
|
// Canvas
|
||||||
addMod("io.vram:canvas-fabric-${project.canvas_version}", rootProject.enable_canvas)
|
addMod("io.vram:canvas-fabric-${project.canvas_version}", rootProject.enable_canvas)
|
||||||
|
|
||||||
// Immersive Portals
|
// Immersive Portals
|
||||||
if (rootProject.enable_immersive_portals == "1")
|
if (rootProject.enable_immersive_portals == "1") {
|
||||||
modCompileOnly ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}")
|
modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}")
|
||||||
|
}
|
||||||
else if (rootProject.enable_immersive_portals == "2") {
|
else if (rootProject.enable_immersive_portals == "2") {
|
||||||
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}") {
|
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}") {
|
||||||
exclude(group: "net.fabricmc.fabric-api")
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.fabric;
|
package com.seibel.distanthorizons.fabric;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
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;
|
||||||
@@ -27,15 +29,14 @@ import com.mojang.blaze3d.platform.InputConstants;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
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.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
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.fabric.wrappers.modAccessor.SodiumAccessor;
|
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor;
|
||||||
//import io.netty.buffer.ByteBuf;
|
//import io.netty.buffer.ByteBuf;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
@@ -52,12 +53,14 @@ import net.minecraft.client.gui.screens.TitleScreen;
|
|||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
#endif
|
#endif
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +106,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// tick events //
|
// tick events //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register((client) -> { ClientApi.INSTANCE.clientTickEvent(); });
|
ClientTickEvents.START_CLIENT_TICK.register((client) -> ClientApi.INSTANCE.clientTickEvent());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -119,6 +122,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
});
|
});
|
||||||
|
|
||||||
// (kinda) block break event
|
// (kinda) block break event
|
||||||
|
// Since fabric doesn't have a client-side break-block API event, this is the next best thing
|
||||||
AttackBlockCallback.EVENT.register((player, level, interactionHand, blockPos, direction) ->
|
AttackBlockCallback.EVENT.register((player, level, interactionHand, blockPos, direction) ->
|
||||||
{
|
{
|
||||||
// if we have access to the server, use the chunk save event instead
|
// if we have access to the server, use the chunk save event instead
|
||||||
@@ -126,18 +130,27 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
{
|
{
|
||||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ()))
|
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ()))
|
||||||
{
|
{
|
||||||
// Since fabric doesn't have a client-side break-block API event, this is the next best thing
|
// executor to prevent locking up the render/event thread
|
||||||
ChunkAccess chunk = level.getChunk(blockPos);
|
// if the getChunk() takes longer than expected
|
||||||
if (chunk != null)
|
// (which can be caused by certain mods)
|
||||||
|
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
|
if (executor != null)
|
||||||
{
|
{
|
||||||
//LOGGER.trace("attack block at blockPos: " + blockPos);
|
executor.execute(() ->
|
||||||
|
{
|
||||||
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
|
ChunkAccess chunk = level.getChunk(blockPos);
|
||||||
SharedApi.INSTANCE.chunkBlockChangedEvent(
|
if (chunk != null)
|
||||||
new ChunkWrapper(chunk, level, wrappedLevel),
|
{
|
||||||
wrappedLevel
|
//LOGGER.trace("attack block at blockPos: " + blockPos);
|
||||||
);
|
|
||||||
}
|
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
|
||||||
|
SharedApi.INSTANCE.chunkBlockChangedEvent(
|
||||||
|
new ChunkWrapper(chunk, level, wrappedLevel),
|
||||||
|
wrappedLevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,27 +159,37 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
});
|
});
|
||||||
|
|
||||||
// (kinda) block place event
|
// (kinda) block place event
|
||||||
|
// Since fabric doesn't have a client-side place-block API event, this is the next best thing
|
||||||
UseBlockCallback.EVENT.register((player, level, hand, hitResult) ->
|
UseBlockCallback.EVENT.register((player, level, hand, hitResult) ->
|
||||||
{
|
{
|
||||||
// if we have access to the server, use the chunk save event instead
|
// if we have access to the server, use the chunk save event instead
|
||||||
if (MC.clientConnectedToDedicatedServer())
|
if (MC.clientConnectedToDedicatedServer())
|
||||||
{
|
{
|
||||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ()))
|
if (hitResult.getType() == HitResult.Type.BLOCK
|
||||||
|
&& !hitResult.isInside())
|
||||||
{
|
{
|
||||||
// Since fabric doesn't have a client-side place-block API event, this is the next best thing
|
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ()))
|
||||||
if (hitResult.getType() == HitResult.Type.BLOCK
|
|
||||||
&& !hitResult.isInside())
|
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = level.getChunk(hitResult.getBlockPos());
|
// executor to prevent locking up the render/event thread
|
||||||
if (chunk != null)
|
// if the getChunk() takes longer than expected
|
||||||
|
// (which can be caused by certain mods)
|
||||||
|
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
|
if (executor != null)
|
||||||
{
|
{
|
||||||
//LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos());
|
executor.execute(() ->
|
||||||
|
{
|
||||||
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
|
ChunkAccess chunk = level.getChunk(hitResult.getBlockPos());
|
||||||
SharedApi.INSTANCE.chunkBlockChangedEvent(
|
if (chunk != null)
|
||||||
new ChunkWrapper(chunk, level, wrappedLevel),
|
{
|
||||||
wrappedLevel
|
//LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos());
|
||||||
);
|
|
||||||
|
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
|
||||||
|
SharedApi.INSTANCE.chunkBlockChangedEvent(
|
||||||
|
new ChunkWrapper(chunk, level, wrappedLevel),
|
||||||
|
wrappedLevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,10 +215,24 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
|
|
||||||
WorldRenderEvents.AFTER_SETUP.register((renderContext) ->
|
WorldRenderEvents.AFTER_SETUP.register((renderContext) ->
|
||||||
{
|
{
|
||||||
|
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||||
|
|
||||||
|
Mat4f modelViewMatrix;
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||||
|
#else
|
||||||
|
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||||
|
#endif
|
||||||
|
|
||||||
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
|
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
|
||||||
McObjectConverter.Convert(renderContext.matrixStack().last().pose()),
|
modelViewMatrix,
|
||||||
McObjectConverter.Convert(renderContext.projectionMatrix()),
|
projectionMatrix,
|
||||||
renderContext.tickDelta());
|
#if MC_VER < MC_1_21
|
||||||
|
renderContext.tickDelta()
|
||||||
|
#else
|
||||||
|
renderContext.tickCounter().getGameTimeDeltaTicks()
|
||||||
|
#endif
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Debug keyboard event
|
// Debug keyboard event
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
// If sodium is installed Indium is also necessary in order to use the Fabric rendering API
|
// If sodium is installed Indium is also necessary in order to use the Fabric rendering API
|
||||||
if (!modChecker.isModLoaded("indium"))
|
if (!modChecker.isModLoaded("indium"))
|
||||||
{
|
{
|
||||||
String indiumMissingMessage = ModInfo.READABLE_NAME + " now relies on 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);
|
||||||
|
|
||||||
if (!GraphicsEnvironment.isHeadless())
|
if (!GraphicsEnvironment.isHeadless())
|
||||||
|
|||||||
-69
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
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.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(DynamicTexture.class)
|
|
||||||
public class MixinDynamicTexture implements ILightTextureMarker
|
|
||||||
{
|
|
||||||
/** Used to prevent accidentally using other dynamic textures as a lightmap */
|
|
||||||
@Unique
|
|
||||||
private boolean isLightTexture = false;
|
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
private NativeImage pixels;
|
|
||||||
|
|
||||||
@Inject(method = "upload()V", at = @At("HEAD"))
|
|
||||||
public void updateLightTexture(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
// since the light map is always updated on the client render thread we should be able to access the client level at the same time
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
|
||||||
if (!this.isLightTexture
|
|
||||||
|| mc == null
|
|
||||||
|| mc.getWrappedClientLevel() == null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ApiShared.LOGGER.info("Lightmap update");
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.pixels, clientLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markLightTexture() { this.isLightTexture = true; }
|
|
||||||
|
|
||||||
}
|
|
||||||
+27
-13
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.fabric.mixins.client;
|
|||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
#else
|
#else
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
#endif
|
#endif
|
||||||
@@ -29,23 +30,17 @@ 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.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import net.minecraft.client.Camera;
|
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.GameRenderer;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import net.minecraft.client.Camera;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
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.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@@ -84,33 +79,49 @@ public class MixinLevelRenderer
|
|||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
method = "renderChunkLayer(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 cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#else
|
#elif MC_VER < MC_1_20_6
|
||||||
@Inject(at = @At("HEAD"),
|
@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",
|
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
|
||||||
|
@Inject(at = @At("HEAD"),
|
||||||
|
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
||||||
|
cancellable = true)
|
||||||
|
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo 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];
|
||||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
GL32.glGetFloatv(GL32.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||||
mcProjectionMatrix.transpose();
|
mcProjectionMatrix.transpose();
|
||||||
|
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||||
|
|
||||||
#else
|
#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());
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
|
#else
|
||||||
|
// MC combined the model view and projection matricies
|
||||||
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
|
Mat4f mcProjectionMatrix = new Mat4f();
|
||||||
|
mcProjectionMatrix.setIdentity();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (renderType.equals(RenderType.translucent())) {
|
if (renderType.equals(RenderType.translucent()))
|
||||||
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
|
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
|
||||||
mcModelViewMatrix,
|
mcModelViewMatrix,
|
||||||
mcProjectionMatrix,
|
mcProjectionMatrix,
|
||||||
Minecraft.getInstance().getFrameTime());
|
#if MC_VER < MC_1_21
|
||||||
|
Minecraft.getInstance().getFrameTime()
|
||||||
|
#else
|
||||||
|
Minecraft.getInstance().getTimer().getRealtimeDeltaTicks()
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME completely disables rendering when sodium is installed
|
// FIXME completely disables rendering when sodium is installed
|
||||||
@@ -126,9 +137,12 @@ public class MixinLevelRenderer
|
|||||||
#elif MC_VER < MC_1_20_1
|
#elif MC_VER < MC_1_20_1
|
||||||
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
|
||||||
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
||||||
|
#elif MC_VER < MC_1_20_6
|
||||||
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
||||||
|
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
||||||
#else
|
#else
|
||||||
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
||||||
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
private void callAfterRunUpdates(CallbackInfo ci)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ChunkWrapper.syncedUpdateClientLightStatus();
|
ChunkWrapper.syncedUpdateClientLightStatus();
|
||||||
|
|||||||
+19
-7
@@ -20,9 +20,14 @@
|
|||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||||
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
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;
|
||||||
@@ -35,13 +40,20 @@ public class MixinLightTexture
|
|||||||
{
|
{
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private DynamicTexture lightTexture;
|
private NativeImage lightPixels;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
public void markLightTexture(CallbackInfo ci)
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
//
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
((ILightTextureMarker) this.lightTexture).markLightTexture();
|
if (mc == null || mc.getWrappedClientLevel() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-10
@@ -8,10 +8,12 @@ import com.seibel.distanthorizons.core.jar.installer.GitlabGetter;
|
|||||||
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
||||||
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
import net.minecraft.client.Minecraft;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.TitleScreen;
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
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 org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
@@ -25,6 +27,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
@Mixin(Minecraft.class)
|
@Mixin(Minecraft.class)
|
||||||
public class MixinMinecraft
|
public class MixinMinecraft
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Can be enabled for testing the auto updater UI. <br/>
|
||||||
|
* will always show the auto updater if set to true.
|
||||||
|
*/
|
||||||
|
@Unique
|
||||||
|
private static final boolean DEBUG_ALWAYS_SHOW_UPDATER = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_2
|
#if MC_VER < MC_1_20_2
|
||||||
#if MC_VER == MC_1_20_1
|
#if MC_VER == MC_1_20_1
|
||||||
@Redirect(
|
@Redirect(
|
||||||
@@ -41,13 +52,13 @@ public class MixinMinecraft
|
|||||||
public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get()) // Don't do anything if the user doesn't want it
|
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() && !DEBUG_ALWAYS_SHOW_UPDATER) // Don't do anything if the user doesn't want it
|
||||||
{
|
{
|
||||||
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SelfUpdater.onStart())
|
if (SelfUpdater.onStart() || DEBUG_ALWAYS_SHOW_UPDATER)
|
||||||
{
|
{
|
||||||
instance.setScreen(new UpdateModScreen(
|
instance.setScreen(new UpdateModScreen(
|
||||||
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
|
||||||
@@ -69,17 +80,31 @@ public class MixinMinecraft
|
|||||||
private void buildInitialScreens(Runnable runnable)
|
private void buildInitialScreens(Runnable runnable)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() // Don't do anything if the user doesn't want it
|
DEBUG_ALWAYS_SHOW_UPDATER ||
|
||||||
&& SelfUpdater.onStart()
|
(
|
||||||
)
|
// Don't do anything if the user doesn't want it
|
||||||
|
Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get()
|
||||||
|
&& SelfUpdater.onStart()
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
runnable = () -> {
|
runnable = () ->
|
||||||
|
{
|
||||||
|
String versionId;
|
||||||
|
EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get());
|
||||||
|
if (updateBranch == EDhApiUpdateBranch.STABLE)
|
||||||
|
{
|
||||||
|
versionId = ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versionId = GitlabGetter.INSTANCE.projectPipelines.getFirst().get("sha");
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE
|
versionId
|
||||||
? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion())
|
|
||||||
: GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-28
@@ -23,7 +23,6 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import net.minecraft.client.gui.screens.OptionsScreen;
|
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
@@ -31,51 +30,127 @@ import net.minecraft.network.chat.TranslatableComponent;
|
|||||||
#endif
|
#endif
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
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 org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
import net.minecraft.client.gui.layouts.LinearLayout;
|
||||||
|
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
import net.minecraft.client.gui.screens.OptionsScreen;
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.gui.screens.options.OptionsScreen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a button to the menu to goto the config
|
* Adds a button to the menu to goto the config
|
||||||
*
|
*
|
||||||
* @author coolGi
|
* @author coolGi
|
||||||
* @version 12-02-2021
|
* @version 2024-5-20
|
||||||
*/
|
*/
|
||||||
@Mixin(OptionsScreen.class)
|
@Mixin(OptionsScreen.class)
|
||||||
public class MixinOptionsScreen extends Screen
|
public class MixinOptionsScreen extends Screen
|
||||||
{
|
{
|
||||||
// Get the texture for the button
|
/** Texture used for the config opening button */
|
||||||
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
@Unique
|
||||||
protected MixinOptionsScreen(Component title)
|
private static final ResourceLocation ICON_TEXTURE =
|
||||||
{
|
#if MC_VER < MC_1_21
|
||||||
super(title);
|
new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
||||||
}
|
#else
|
||||||
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
|
||||||
|
#endif
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "init")
|
|
||||||
|
@Unique
|
||||||
|
private TexturedButtonWidget optionsButton = null;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
protected HeaderAndFooterLayout layout;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
protected MixinOptionsScreen(Component title) { super(title); }
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "init")
|
||||||
private void lodconfig$init(CallbackInfo ci)
|
private void lodconfig$init(CallbackInfo ci)
|
||||||
{
|
{
|
||||||
if (Config.Client.optionsButton.get())
|
if (Config.Client.optionsButton.get())
|
||||||
this. #if MC_VER < MC_1_17_1 addButton #else addRenderableWidget #endif
|
{
|
||||||
(new TexturedButtonWidget(
|
#if MC_VER < MC_1_17_1
|
||||||
// Where the button is on the screen
|
this.addButton(this.getOptionsButton());
|
||||||
this.width / 2 - 180, this.height / 6 - 12,
|
#elif MC_VER < MC_1_20_6
|
||||||
// Width and height of the button
|
this.addRenderableWidget(this.getOptionsButton());
|
||||||
20, 20,
|
#else
|
||||||
// Offset
|
|
||||||
0, 0,
|
// add the button so it's rendered
|
||||||
// Some textuary stuff
|
this.addRenderableWidget(this.getOptionsButton());
|
||||||
20, ICON_TEXTURE, 20, 40,
|
|
||||||
// Create the button and tell it where to go
|
// add the button to the correct location in the UI
|
||||||
// For now it goes to the client option by default
|
// TODO is there a better way to do this instead of using access transformers to inject into the exact UI elements?
|
||||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
|
LinearLayout layout = (LinearLayout) this.layout.headerFrame.children.getFirst().child;
|
||||||
// Add a title to the utton
|
|
||||||
#if MC_VER < MC_1_19_2
|
// determine how wide the other option buttons are so we can put our botton to the left of them all
|
||||||
new TranslatableComponent(ModInfo.ID + ".title")));
|
AtomicInteger width = new AtomicInteger(0);
|
||||||
#else
|
layout.visitChildren(x -> width.addAndGet(x.getWidth()));
|
||||||
Component.translatable(ModInfo.ID + ".title")));
|
width.addAndGet(-10); // padding between the DH button and the FOV slider
|
||||||
#endif
|
|
||||||
|
layout.wrapped.addChild(this.getOptionsButton(), 1, 2, (settings) -> settings.paddingLeft(width.get() * -1));
|
||||||
|
layout.arrangeElements();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
public TexturedButtonWidget getOptionsButton()
|
||||||
|
{
|
||||||
|
if (this.optionsButton == null)
|
||||||
|
{
|
||||||
|
this.optionsButton
|
||||||
|
= new TexturedButtonWidget(
|
||||||
|
// Where the button is on the screen
|
||||||
|
this.width / 2 - 180, this.height / 6 - 12,
|
||||||
|
// Width and height of the button
|
||||||
|
20, 20,
|
||||||
|
// texture UV Offset
|
||||||
|
0, 0,
|
||||||
|
// Some textuary stuff
|
||||||
|
20, ICON_TEXTURE, 20, 40,
|
||||||
|
// Create the button and tell it where to go
|
||||||
|
// For now it goes to the client option by default
|
||||||
|
(buttonWidget) -> Objects.requireNonNull(this.minecraft).setScreen(GetConfigScreen.getScreen(this)),
|
||||||
|
// Add a title to the button
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
new TranslatableComponent(ModInfo.ID + ".title"));
|
||||||
|
#else
|
||||||
|
Component.translatable(ModInfo.ID + ".title"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.optionsButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-60
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.server.unsafe;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
|
|
||||||
//FIXME: Is this still needed?
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
|
|
||||||
import net.minecraft.util.ThreadingDetector;
|
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
|
|
||||||
* FIXME: Recheck this
|
|
||||||
*/
|
|
||||||
@Mixin(ThreadingDetector.class)
|
|
||||||
public class MixinThreadingDetector
|
|
||||||
{
|
|
||||||
@Mutable
|
|
||||||
@Shadow
|
|
||||||
private Semaphore lock;
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
private void setSemaphore(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
this.lock = new Semaphore(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
|
|
||||||
@Mixin(ServerLevel.class)
|
|
||||||
public class MixinThreadingDetector { } //FIXME: Is there some way to make this file just not be added?
|
|
||||||
#endif
|
|
||||||
+1
-1
@@ -32,7 +32,7 @@ public class ModMenuIntegration implements ModMenuApi
|
|||||||
@Override
|
@Override
|
||||||
public ConfigScreenFactory<?> getModConfigScreenFactory()
|
public ConfigScreenFactory<?> getModConfigScreenFactory()
|
||||||
{
|
{
|
||||||
return parent -> GetConfigScreen.getScreen(parent);
|
return GetConfigScreen::getScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,11 +1,11 @@
|
|||||||
package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
|
package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IBCLibAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IBCLibAccessor;
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 || MC_VER == MC_1_20_4 // These versions either don't have BCLib, or the implementation is different
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 || MC_VER == MC_1_20_4 || MC_VER == MC_1_20_6 // These versions either don't have BCLib, or the implementation is different
|
||||||
#elif MC_VER == MC_1_18_2
|
#elif MC_VER == MC_1_18_2
|
||||||
import ru.bclib.config.ClientConfig;
|
import ru.bclib.config.ClientConfig;
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
#else
|
#elif MC_VER < MC_1_21
|
||||||
import org.betterx.bclib.config.ClientConfig;
|
import org.betterx.bclib.config.ClientConfig;
|
||||||
import org.betterx.bclib.config.Configs;
|
import org.betterx.bclib.config.Configs;
|
||||||
#endif
|
#endif
|
||||||
@@ -17,7 +17,8 @@ public class BCLibAccessor implements IBCLibAccessor
|
|||||||
|
|
||||||
public void setRenderCustomFog(boolean newValue)
|
public void setRenderCustomFog(boolean newValue)
|
||||||
{
|
{
|
||||||
#if !(MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 || MC_VER == MC_1_20_4) // These versions either don't have BCLib, or the implementation is different
|
// only some MC versions have BCLib and require this fix
|
||||||
|
#if (MC_VER > MC_1_17_1 && MC_VER < MC_1_20_4)
|
||||||
|
|
||||||
// Change the value of CUSTOM_FOG_RENDERING in the bclib client config
|
// Change the value of CUSTOM_FOG_RENDERING in the bclib client config
|
||||||
// This disabled fog from rendering within bclib
|
// This disabled fog from rendering within bclib
|
||||||
|
|||||||
+4
@@ -22,7 +22,11 @@ package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
|
|||||||
#if MC_VER >= MC_1_19_4
|
#if MC_VER >= MC_1_19_4
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.coderbot.iris.Iris;
|
import net.coderbot.iris.Iris;
|
||||||
|
#else
|
||||||
|
import net.irisshaders.iris.Iris;
|
||||||
|
#endif
|
||||||
import net.irisshaders.iris.api.v0.IrisApi;
|
import net.irisshaders.iris.api.v0.IrisApi;
|
||||||
|
|
||||||
public class IrisAccessor implements IIrisAccessor
|
public class IrisAccessor implements IIrisAccessor
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ public class ModChecker implements IModChecker
|
|||||||
@Override
|
@Override
|
||||||
public File modLocation(String modid)
|
public File modLocation(String modid)
|
||||||
{
|
{
|
||||||
return new File(FabricLoader.getInstance().getModContainer(modid).get().getOrigin().getPaths().get(0).toUri());
|
return new File(FabricLoader.getInstance().getModContainer(modid).get().getOrigin().getPaths().getFirst().toUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -24,7 +24,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
@@ -69,11 +69,9 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER >= MC_1_20_1
|
||||||
// TODO: This is just a tmp solution, use a proper solution later
|
// TODO: This is just a tmp solution, use a proper solution later
|
||||||
return MC_RENDER.getMaximumRenderedChunks().stream().filter((DhChunkPos chunk) -> {
|
return MC_RENDER.getMaximumRenderedChunks().stream().filter((DhChunkPos chunk) -> (renderer.isBoxVisible(
|
||||||
return (renderer.isBoxVisible(
|
chunk.getMinBlockX() + 1, height.getMinBuildHeight() + 1, chunk.getMinBlockZ() + 1,
|
||||||
chunk.getMinBlockX() + 1, height.getMinBuildHeight() + 1, chunk.getMinBlockZ() + 1,
|
chunk.getMinBlockX() + 15, height.getMaxBuildHeight() - 1, chunk.getMinBlockZ() + 15))).collect(Collectors.toCollection(HashSet::new));
|
||||||
chunk.getMinBlockX() + 15, height.getMaxBuildHeight() - 1, chunk.getMinBlockZ() + 15));
|
|
||||||
}).collect(Collectors.toCollection(HashSet::new));
|
|
||||||
#elif MC_VER >= MC_1_18_2
|
#elif MC_VER >= MC_1_18_2
|
||||||
// 0b11 = Lighted chunk & loaded chunk
|
// 0b11 = Lighted chunk & loaded chunk
|
||||||
return renderer.getChunkTracker().getChunks(0b00).filter(
|
return renderer.getChunkTracker().getChunks(0b00).filter(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "com.seibel.distanthorizons.fabric.mixins",
|
"package": "com.seibel.distanthorizons.fabric.mixins",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"server.unsafe.MixinThreadingDetector",
|
|
||||||
"server.MixinChunkGenerator",
|
"server.MixinChunkGenerator",
|
||||||
"server.MixinChunkMap",
|
"server.MixinChunkMap",
|
||||||
"server.MixinUtilBackgroundThread"
|
"server.MixinUtilBackgroundThread"
|
||||||
@@ -15,7 +14,6 @@
|
|||||||
"client.MixinFogRenderer",
|
"client.MixinFogRenderer",
|
||||||
"client.MixinGameRenderer",
|
"client.MixinGameRenderer",
|
||||||
"client.MixinLevelRenderer",
|
"client.MixinLevelRenderer",
|
||||||
"client.MixinDynamicTexture",
|
|
||||||
"client.MixinLightTexture",
|
"client.MixinLightTexture",
|
||||||
"client.MixinOptionsScreen",
|
"client.MixinOptionsScreen",
|
||||||
"client.MixinMinecraft",
|
"client.MixinMinecraft",
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"suggests": {
|
"suggests": {
|
||||||
"blendium": "*"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"breaks": $fabric_incompatibility_list,
|
"breaks": $fabric_incompatibility_list,
|
||||||
|
|||||||
+15
-3
@@ -4,7 +4,7 @@ plugins {
|
|||||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21
|
||||||
|
|
||||||
architectury {
|
architectury {
|
||||||
platformSetupLoomIde()
|
platformSetupLoomIde()
|
||||||
@@ -51,8 +51,8 @@ loom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
remapJar {
|
remapJar {
|
||||||
inputFile = shadowJar.archiveFile
|
inputFile = shadeDowngradedApi.archiveFile
|
||||||
dependsOn shadowJar
|
dependsOn shadeDowngradedApi
|
||||||
}
|
}
|
||||||
|
|
||||||
def addMod(path, enabled) {
|
def addMod(path, enabled) {
|
||||||
@@ -78,6 +78,18 @@ dependencies {
|
|||||||
|
|
||||||
addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft)
|
addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft)
|
||||||
|
|
||||||
|
|
||||||
|
if ( // Only run on MC 1.20.6 or later
|
||||||
|
// FIXME: Add an environment variable for the Major, Minor, and Patch version number of Minecraft
|
||||||
|
minecraft_version.split("\\.")[1].toInteger() >= 20 &&
|
||||||
|
(
|
||||||
|
minecraft_version.split("\\.").length > 1 && // Incase there isn't a minor version
|
||||||
|
minecraft_version.split("\\.")[2].toInteger() >= 6
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// (potential) hack fix, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+
|
||||||
|
implementation('net.sf.jopt-simple:jopt-simple:5.0.4') //{ version { strictly '5.0.4' } }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task deleteResources(type: Delete) {
|
task deleteResources(type: Delete) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
|||||||
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.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;
|
||||||
@@ -65,6 +66,8 @@ import net.minecraftforge.event.TickEvent;
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This handles all events sent to the client,
|
* This handles all events sent to the client,
|
||||||
* and is the starting point for most of the mod.
|
* and is the starting point for most of the mod.
|
||||||
@@ -144,7 +147,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
public void clientLevelUnloadEvent(WorldEvent.Unload event)
|
public void clientLevelUnloadEvent(WorldEvent.Unload event)
|
||||||
#else
|
#else
|
||||||
public void clientLevelUnloadEvent(LevelEvent.Load event)
|
public void clientLevelUnloadEvent(LevelEvent.Unload event)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LOGGER.info("level unload");
|
LOGGER.info("level unload");
|
||||||
@@ -186,8 +189,15 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
LevelAccessor level = event.getLevel();
|
LevelAccessor level = event.getLevel();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ChunkAccess chunk = level.getChunk(event.getPos());
|
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
this.onBlockChangeEvent(level, chunk);
|
if (executor != null)
|
||||||
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
ChunkAccess chunk = level.getChunk(event.getPos());
|
||||||
|
this.onBlockChangeEvent(level, chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
|
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
|
||||||
@@ -205,8 +215,15 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
LevelAccessor level = event.getLevel();
|
LevelAccessor level = event.getLevel();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ChunkAccess chunk = level.getChunk(event.getPos());
|
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
this.onBlockChangeEvent(level, chunk);
|
if (executor != null)
|
||||||
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
ChunkAccess chunk = level.getChunk(event.getPos());
|
||||||
|
this.onBlockChangeEvent(level, chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
|
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
|
||||||
{
|
{
|
||||||
@@ -328,9 +345,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
#elif MC_VER >= MC_1_18_2
|
#elif MC_VER >= MC_1_18_2
|
||||||
if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS)
|
if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS)
|
||||||
#else
|
#else
|
||||||
// FIXME: Is this the correct location for 1.16 & 1.17???
|
if (event.type.equals(TickEvent.RenderTickEvent.Type.RENDER))
|
||||||
// I couldnt find anything for rendering after the level, so is rendering after overlays ok?
|
|
||||||
if (event.type.equals(TickEvent.RenderTickEvent.Type.WORLD))
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.forge.mixins.client;
|
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
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.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@Mixin(DynamicTexture.class)
|
|
||||||
public abstract class MixinDynamicTexture implements ILightTextureMarker
|
|
||||||
{
|
|
||||||
/** Used to prevent accidentally using other dynamic textures as a lightmap */
|
|
||||||
@Unique
|
|
||||||
private boolean isLightTexture = false;
|
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
private NativeImage pixels;
|
|
||||||
|
|
||||||
@Inject(method = "upload()V", at = @At("HEAD"))
|
|
||||||
public void updateLightTexture(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
// since the light map is always updated on the client render thread we should be able to access the client level at the same time
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
|
||||||
if (!this.isLightTexture
|
|
||||||
|| mc == null
|
|
||||||
|| mc.getWrappedClientLevel() == null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ApiShared.LOGGER.info("Lightmap update");
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.pixels, clientLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markLightTexture() { this.isLightTexture = true; }
|
|
||||||
|
|
||||||
}
|
|
||||||
+14
-8
@@ -22,6 +22,10 @@ package com.seibel.distanthorizons.forge.mixins.client;
|
|||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
#else
|
#else
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
@@ -34,13 +38,9 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import net.minecraft.client.Camera;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
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;
|
||||||
@@ -49,7 +49,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;
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
@@ -68,7 +68,8 @@ import org.lwjgl.opengl.GL15;
|
|||||||
@Mixin(LevelRenderer.class)
|
@Mixin(LevelRenderer.class)
|
||||||
public class MixinLevelRenderer
|
public class MixinLevelRenderer
|
||||||
{
|
{
|
||||||
@Shadow
|
@Nullable
|
||||||
|
@Shadow //# if MC_VER >= MC_1_20_4 (remap = false) # endif
|
||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
@Unique
|
@Unique
|
||||||
private static float previousPartialTicks = 0;
|
private static float previousPartialTicks = 0;
|
||||||
@@ -111,11 +112,16 @@ public class MixinLevelRenderer
|
|||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
method = "renderChunkLayer(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 cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#else
|
#elif MC_VER < MC_1_20_4
|
||||||
@Inject(at = @At("HEAD"),
|
@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",
|
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
|
||||||
|
@Inject(at = @At("HEAD"),
|
||||||
|
method = "renderSectionLayer",
|
||||||
|
cancellable = true)
|
||||||
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// get MC's model view and projection matrices
|
// get MC's model view and projection matrices
|
||||||
|
|||||||
+21
-7
@@ -20,10 +20,13 @@
|
|||||||
package com.seibel.distanthorizons.forge.mixins.client;
|
package com.seibel.distanthorizons.forge.mixins.client;
|
||||||
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -35,11 +38,22 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
@Mixin(LightTexture.class)
|
@Mixin(LightTexture.class)
|
||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
@Shadow
|
@Shadow //# if MC_VER >= MC_1_20_4 (remap = false) # endif
|
||||||
@Final
|
@Final
|
||||||
private DynamicTexture lightTexture;
|
private NativeImage lightPixels;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
public void markLightTexture(CallbackInfo ci) { ((ILightTextureMarker) this.lightTexture).markLightTexture(); }
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
if (mc == null || mc.getWrappedClientLevel() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-2
@@ -73,11 +73,23 @@ public class MixinMinecraft
|
|||||||
&& SelfUpdater.onStart()
|
&& SelfUpdater.onStart()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
runnable = () -> {
|
runnable = () ->
|
||||||
|
{
|
||||||
|
String versionId;
|
||||||
|
EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get());
|
||||||
|
if (updateBranch == EDhApiUpdateBranch.STABLE)
|
||||||
|
{
|
||||||
|
versionId = ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versionId = GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha");
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()) : GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
versionId
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
-156
@@ -1,156 +0,0 @@
|
|||||||
package com.seibel.distanthorizons.forge.mixins.client;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
|
||||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.DimensionTypeWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.file.structure.LocalSaveStructure;
|
|
||||||
import com.seibel.distanthorizons.core.level.DhServerLevel;
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.util.worldupdate.WorldUpgrader;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.dimension.DimensionType;
|
|
||||||
import net.minecraft.world.level.dimension.LevelStem;
|
|
||||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
|
||||||
import net.minecraft.world.level.storage.DimensionDataStorage;
|
|
||||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
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.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
#if FALSE
|
|
||||||
@Mixin(WorldUpgrader.class)
|
|
||||||
public class MixinWorldUpgrader {
|
|
||||||
static class FakeLevelWrapper implements IServerLevelWrapper {
|
|
||||||
private Path saveFolder;
|
|
||||||
private LevelStem stem;
|
|
||||||
private DimensionType dimension;
|
|
||||||
private DimensionTypeWrapper dimensionTypeWrapper;
|
|
||||||
|
|
||||||
public FakeLevelWrapper(LevelStorageSource.LevelStorageAccess storage, WorldGenSettings gen, ResourceKey<Level> dim) {
|
|
||||||
saveFolder = storage.getDimensionPath(dim);
|
|
||||||
stem = gen.dimensions().getOrThrow(WorldGenSettings.levelToLevelStem(dim));
|
|
||||||
dimension = stem.typeHolder().value();
|
|
||||||
dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(dimension);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EDhApiLevelType getLevelType() {
|
|
||||||
return EDhApiLevelType.SERVER_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IDhApiDimensionTypeWrapper getDimensionType() {
|
|
||||||
return dimensionTypeWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBlockLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSkyLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasCeiling() {
|
|
||||||
return dimension.hasCeiling();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasSkyLight() {
|
|
||||||
return dimension.hasSkyLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight() {
|
|
||||||
return dimension.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMinHeight() {
|
|
||||||
return dimension.minY();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockStateWrapper getBlockState(DhBlockPos pos) {
|
|
||||||
return BlockStateWrapper.AIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBiomeWrapper getBiome(DhBlockPos pos) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getWrappedMcObject() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IClientLevelWrapper tryGetClientLevelWrapper() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getSaveFolder() {
|
|
||||||
return saveFolder.toFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private DhServerLevel dhServerLevel;
|
|
||||||
@Unique
|
|
||||||
private FakeLevelWrapper fakeLevelWrapper;
|
|
||||||
@Unique
|
|
||||||
public LocalSaveStructure saveStructure;
|
|
||||||
|
|
||||||
@Shadow @Final
|
|
||||||
private DimensionDataStorage overworldDataStorage;
|
|
||||||
@Shadow @Final
|
|
||||||
private LevelStorageSource.LevelStorageAccess levelStorage;
|
|
||||||
@Shadow @Final
|
|
||||||
private WorldGenSettings worldGenSettings;
|
|
||||||
|
|
||||||
@Inject(method = "Lnet/minecraft/util/worldupdate/WorldUpgrader;work()V",
|
|
||||||
at = @At(value = "INVOKE")
|
|
||||||
)
|
|
||||||
private void initWorldUpgrade() {
|
|
||||||
saveStructure = new LocalSaveStructure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "Lnet/minecraft/util/worldupdate/WorldUpgrader;work()V",
|
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/worldupdate/WorldUpgrader;getAllChunkPos(Lnet/minecraft/resources/ResourceKey;)Ljava/util/List;", shift = At.Shift.AFTER),
|
|
||||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
|
||||||
)
|
|
||||||
private void startWorldUpgrade(CallbackInfo info, ResourceKey resourceKey) {
|
|
||||||
ResourceKey<Level> key = resourceKey;
|
|
||||||
fakeLevelWrapper = new FakeLevelWrapper(levelStorage, worldGenSettings, key);
|
|
||||||
dhServerLevel = new DhServerLevel(saveStructure, fakeLevelWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.forge.mixins.server.unsafe;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
|
|
||||||
import net.minecraft.util.ThreadingDetector;
|
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
|
|
||||||
* FIXME: Recheck this // STILL check this
|
|
||||||
*/
|
|
||||||
@Mixin(ThreadingDetector.class)
|
|
||||||
public class MixinThreadingDetector
|
|
||||||
{
|
|
||||||
@Mutable
|
|
||||||
@Shadow
|
|
||||||
private Semaphore lock;
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
private void setSemaphore(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
this.lock = new Semaphore(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
||||||
|
|
||||||
@Mixin(ChunkGenerator.class)
|
|
||||||
public class MixinThreadingDetector { }
|
|
||||||
#endif
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "com.seibel.distanthorizons.forge.mixins",
|
"package": "com.seibel.distanthorizons.forge.mixins",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"server.unsafe.MixinThreadingDetector",
|
|
||||||
"server.MixinUtilBackgroundThread",
|
"server.MixinUtilBackgroundThread",
|
||||||
"server.MixinChunkGenerator",
|
"server.MixinChunkGenerator",
|
||||||
"server.MixinTFChunkGenerator"
|
"server.MixinTFChunkGenerator"
|
||||||
@@ -14,7 +13,6 @@
|
|||||||
"client.MixinFogRenderer",
|
"client.MixinFogRenderer",
|
||||||
"client.MixinGameRenderer",
|
"client.MixinGameRenderer",
|
||||||
"client.MixinLevelRenderer",
|
"client.MixinLevelRenderer",
|
||||||
"client.MixinDynamicTexture",
|
|
||||||
"client.MixinLightTexture",
|
"client.MixinLightTexture",
|
||||||
"client.MixinOptionsScreen",
|
"client.MixinOptionsScreen",
|
||||||
"client.MixinTextureUtil"
|
"client.MixinTextureUtil"
|
||||||
|
|||||||
+12
-10
@@ -5,12 +5,12 @@ org.gradle.caching=true
|
|||||||
|
|
||||||
# Mod Info
|
# Mod Info
|
||||||
mod_name=DistantHorizons
|
mod_name=DistantHorizons
|
||||||
mod_version=2.0.3-a-dev
|
mod_version=2.1.3-a-dev
|
||||||
api_version=1.1.0
|
api_version=3.0.0
|
||||||
maven_group=com.seibel.distanthorizons
|
maven_group=com.seibel.distanthorizons
|
||||||
mod_readable_name=Distant Horizons
|
mod_readable_name=Distant Horizons
|
||||||
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
|
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
|
||||||
# Note: In forge's mods.toml this is hard coded because Architectury throws an error with setting it as a varuable
|
# Note: In forge's mods.toml this is hard coded because Architectury throws an error with setting it as a variable
|
||||||
mod_authors=["James Seibel", "Leonardo Amato", "Cola", "coolGi", "Ran", "Leetom"]
|
mod_authors=["James Seibel", "Leonardo Amato", "Cola", "coolGi", "Ran", "Leetom"]
|
||||||
mod_homepage=https://modrinth.com/mod/distanthorizons
|
mod_homepage=https://modrinth.com/mod/distanthorizons
|
||||||
mod_source=https://gitlab.com/jeseibel/distant-horizons
|
mod_source=https://gitlab.com/jeseibel/distant-horizons
|
||||||
@@ -18,17 +18,19 @@ 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.9
|
manifold_version=2023.1.17
|
||||||
|
# 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
|
||||||
zstd_version=1.5.5-11
|
|
||||||
xz_version=1.9
|
xz_version=1.9
|
||||||
sqlite_jdbc_version=3.43.0.0
|
sqlite_jdbc_version=3.43.0.0
|
||||||
fastutil_version=8.5.13
|
# 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
|
||||||
#svgSalamander_version=1.1.3
|
#svgSalamander_version=1.1.3
|
||||||
|
|
||||||
# Minecraft related libaries (included in MC's jar)
|
# Minecraft related libraries (included in MC's jar)
|
||||||
log4j_version=2.20.0
|
log4j_version=2.23.1
|
||||||
netty_version=4.1.94.Final
|
netty_version=4.1.94.Final
|
||||||
lwjgl_version=3.3.1
|
lwjgl_version=3.3.1
|
||||||
joml_version=1.10.2
|
joml_version=1.10.2
|
||||||
@@ -47,7 +49,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.20.4
|
mcVer=1.21
|
||||||
|
|
||||||
# Defines the maximum amount of memory Minecraft is allowed when run in a developement 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.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
+5
-35
@@ -11,41 +11,17 @@ architectury {
|
|||||||
neoForge()
|
neoForge()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this is already defined in the main settings.gradle file, why doesn't it work unless also defined here? (If compiling does work without this block feel free to remove)
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
name "Neoforge"
|
|
||||||
url "https://maven.neoforged.net/releases/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//loom {
|
|
||||||
// forge {
|
|
||||||
// convertAccessWideners.set(true)
|
|
||||||
// extraAccessWideners.add("lod.accesswidener")
|
|
||||||
// mixinConfigs("DistantHorizons.mixins.json")
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
silentMojangMappingsLicense() // Shut the licencing warning
|
silentMojangMappingsLicense() // Shut the licencing warning
|
||||||
accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
|
accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
|
||||||
neoForge {
|
neoForge {
|
||||||
// Access wideners are now defined in the `remapJar.atAccessWideners`
|
// Access wideners are defined in the `remapJar.atAccessWideners`
|
||||||
// convertAccessWideners = true
|
|
||||||
// extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
|
|
||||||
|
|
||||||
// Mixins are now defined in the `mods.toml`
|
// Mixins are defined in the `mods.toml`
|
||||||
// mixinConfigs = [
|
|
||||||
// "DistantHorizons.mixins.json"
|
|
||||||
// ]
|
|
||||||
}
|
}
|
||||||
mixin {
|
mixin {
|
||||||
// Mixins are now defined in the `mods.toml`
|
// Mixins are defined in the `mods.toml`
|
||||||
// mixinConfigs = [
|
|
||||||
// "DistantHorizons.mixins.json"
|
|
||||||
// ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// "runs" isn't required, but when we do need it then it can be useful
|
// "runs" isn't required, but when we do need it then it can be useful
|
||||||
@@ -67,8 +43,8 @@ loom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
remapJar {
|
remapJar {
|
||||||
inputFile = shadowJar.archiveFile
|
inputFile = apiDowngrade.archiveFile
|
||||||
dependsOn shadowJar
|
dependsOn apiDowngrade
|
||||||
// classifier null
|
// classifier null
|
||||||
|
|
||||||
atAccessWideners.add("distanthorizons.accesswidener")
|
atAccessWideners.add("distanthorizons.accesswidener")
|
||||||
@@ -118,9 +94,3 @@ sourcesJar {
|
|||||||
dependsOn commonSources
|
dependsOn commonSources
|
||||||
from commonSources.archiveFile.map { zipTree(it) }
|
from commonSources.archiveFile.map { zipTree(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
//components.java {
|
|
||||||
// withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
|
||||||
// skip()
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|||||||
+72
-20
@@ -21,19 +21,21 @@ package com.seibel.distanthorizons.neoforge;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
import com.seibel.distanthorizons.common.util.ProxyUtil;
|
import com.seibel.distanthorizons.common.util.ProxyUtil;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
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.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.util.math.Mat4f;
|
||||||
|
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.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.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
//import io.netty.buffer.ByteBuf;
|
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
@@ -54,10 +56,16 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.neoforged.neoforge.client.event.InputEvent;
|
import net.neoforged.neoforge.client.event.InputEvent;
|
||||||
import net.neoforged.neoforge.event.TickEvent;
|
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
import net.neoforged.neoforge.event.TickEvent;
|
||||||
|
#else
|
||||||
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This handles all events sent to the client,
|
* This handles all events sent to the client,
|
||||||
* and is the starting point for most of the mod.
|
* and is the starting point for most of the mod.
|
||||||
@@ -72,8 +80,10 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
|
|
||||||
// private static SimpleChannel multiversePluginChannel;
|
// 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();
|
||||||
|
|
||||||
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -90,6 +100,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// tick events //
|
// tick events //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void clientTickEvent(TickEvent.ClientTickEvent event)
|
public void clientTickEvent(TickEvent.ClientTickEvent event)
|
||||||
{
|
{
|
||||||
@@ -98,6 +109,13 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
ClientApi.INSTANCE.clientTickEvent();
|
ClientApi.INSTANCE.clientTickEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
@SubscribeEvent
|
||||||
|
public void clientTickEvent(ClientTickEvent.Pre event)
|
||||||
|
{
|
||||||
|
ClientApi.INSTANCE.clientTickEvent();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -111,28 +129,26 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
LOGGER.info("level load");
|
LOGGER.info("level load");
|
||||||
|
|
||||||
LevelAccessor level = event.getLevel();
|
LevelAccessor level = event.getLevel();
|
||||||
if (!(level instanceof ClientLevel))
|
if (!(level instanceof ClientLevel clientLevel))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientLevel clientLevel = (ClientLevel) level;
|
|
||||||
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel);
|
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel);
|
||||||
// TODO this causes a crash due to level being set to null somewhere
|
// TODO this causes a crash due to level being set to null somewhere
|
||||||
ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper);
|
ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper);
|
||||||
}
|
}
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void clientLevelUnloadEvent(LevelEvent.Load event)
|
public void clientLevelUnloadEvent(LevelEvent.Unload event)
|
||||||
{
|
{
|
||||||
LOGGER.info("level unload");
|
LOGGER.info("level unload");
|
||||||
|
|
||||||
LevelAccessor level = event.getLevel();
|
LevelAccessor level = event.getLevel();
|
||||||
if (!(level instanceof ClientLevel))
|
if (!(level instanceof ClientLevel clientLevel))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientLevel clientLevel = (ClientLevel) level;
|
|
||||||
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel);
|
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel);
|
||||||
ClientApi.INSTANCE.clientLevelUnloadEvent(clientLevelWrapper);
|
ClientApi.INSTANCE.clientLevelUnloadEvent(clientLevelWrapper);
|
||||||
}
|
}
|
||||||
@@ -151,12 +167,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
|
// executor to prevent locking up the render/event thread
|
||||||
|
// if the getChunk() takes longer than expected
|
||||||
LevelAccessor level = event.getLevel();
|
// (which can be caused by certain mods)
|
||||||
|
var executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
ChunkAccess chunk = level.getChunk(event.getPos());
|
if (executor != null)
|
||||||
this.onBlockChangeEvent(level, chunk);
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
|
||||||
|
|
||||||
|
LevelAccessor level = event.getLevel();
|
||||||
|
ChunkAccess chunk = level.getChunk(event.getPos());
|
||||||
|
this.onBlockChangeEvent(level, chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
|
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
|
||||||
@@ -166,12 +191,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
|
// executor to prevent locking up the render/event thread
|
||||||
|
// if the getChunk() takes longer than expected
|
||||||
LevelAccessor level = event.getLevel();
|
// (which can be caused by certain mods)
|
||||||
|
var executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
ChunkAccess chunk = level.getChunk(event.getPos());
|
if (executor != null)
|
||||||
this.onBlockChangeEvent(level, chunk);
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
|
||||||
|
|
||||||
|
LevelAccessor level = event.getLevel();
|
||||||
|
ChunkAccess chunk = level.getChunk(event.getPos());
|
||||||
|
this.onBlockChangeEvent(level, chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
|
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
|
||||||
{
|
{
|
||||||
@@ -281,6 +315,16 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// rendering //
|
// rendering //
|
||||||
//===========//
|
//===========//
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@@ -301,4 +345,12 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,13 +35,18 @@ import net.neoforged.fml.ModLoadingContext;
|
|||||||
import net.neoforged.fml.common.Mod;
|
import net.neoforged.fml.common.Mod;
|
||||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent;
|
import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent;
|
||||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
|
||||||
import net.neoforged.neoforge.common.NeoForge;
|
import net.neoforged.neoforge.common.NeoForge;
|
||||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||||
import net.neoforged.neoforge.event.server.ServerStartingEvent;
|
import net.neoforged.neoforge.event.server.ServerStartingEvent;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||||
|
#else
|
||||||
|
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize and setup the Mod. <br>
|
* Initialize and setup the Mod. <br>
|
||||||
* If you are looking for the real start of the mod
|
* If you are looking for the real start of the mod
|
||||||
@@ -70,14 +75,20 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
{
|
{
|
||||||
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class,
|
ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class,
|
||||||
() -> new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> GetConfigScreen.getScreen(parent)));
|
() -> new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> GetConfigScreen.getScreen(parent)));
|
||||||
|
#else
|
||||||
|
ModLoadingContext.get().registerExtensionPoint(IConfigScreenFactory.class,
|
||||||
|
// TODO fix potential null pointer
|
||||||
|
() -> (client, parent) -> GetConfigScreen.getScreen(parent));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
||||||
{
|
{
|
||||||
NeoForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); });
|
NeoForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> eventHandler.accept(e.getDispatcher()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,7 +100,7 @@ public class NeoforgeMain extends AbstractModInitializer
|
|||||||
@Override
|
@Override
|
||||||
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
||||||
{
|
{
|
||||||
NeoForge.EVENT_BUS.addListener((ServerStartingEvent e) -> { eventHandler.accept(e.getServer()); });
|
NeoForge.EVENT_BUS.addListener((ServerStartingEvent e) -> eventHandler.accept(e.getServer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+15
-3
@@ -12,7 +12,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.neoforged.neoforge.common.NeoForge;
|
import net.neoforged.neoforge.common.NeoForge;
|
||||||
import net.neoforged.neoforge.event.TickEvent;
|
|
||||||
import net.neoforged.neoforge.event.level.ChunkEvent;
|
import net.neoforged.neoforge.event.level.ChunkEvent;
|
||||||
import net.neoforged.neoforge.event.level.LevelEvent;
|
import net.neoforged.neoforge.event.level.LevelEvent;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
@@ -20,11 +19,17 @@ import net.neoforged.bus.api.SubscribeEvent;
|
|||||||
import net.neoforged.neoforge.event.server.ServerAboutToStartEvent;
|
import net.neoforged.neoforge.event.server.ServerAboutToStartEvent;
|
||||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
|
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
import net.neoforged.neoforge.event.TickEvent;
|
||||||
|
#else
|
||||||
|
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
|
public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
|
||||||
{
|
{
|
||||||
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
||||||
@@ -58,7 +63,7 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// events //
|
// events //
|
||||||
//========//
|
//========//
|
||||||
|
|
||||||
// ServerTickEvent (at end)
|
#if MC_VER < MC_1_20_6
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||||
{
|
{
|
||||||
@@ -67,6 +72,13 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
this.serverApi.serverTickEvent();
|
this.serverApi.serverTickEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
@SubscribeEvent
|
||||||
|
public void serverTickEvent(ServerTickEvent.Post event)
|
||||||
|
{
|
||||||
|
this.serverApi.serverTickEvent();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ServerWorldLoadEvent
|
// ServerWorldLoadEvent
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|||||||
-75
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
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.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(DynamicTexture.class)
|
|
||||||
public abstract class MixinDynamicTexture implements ILightTextureMarker
|
|
||||||
{
|
|
||||||
/** Used to prevent accidentally using other dynamic textures as a lightmap */
|
|
||||||
@Unique
|
|
||||||
private boolean isLightTexture = false;
|
|
||||||
|
|
||||||
@Shadow
|
|
||||||
#if MC_VER >= MC_1_20_4
|
|
||||||
(remap = false)
|
|
||||||
#endif
|
|
||||||
@Final
|
|
||||||
private NativeImage pixels;
|
|
||||||
|
|
||||||
@Inject(method = "upload()V", at = @At("HEAD"))
|
|
||||||
public void updateLightTexture(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
// since the light map is always updated on the client render thread we should be able to access the client level at the same time
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
|
||||||
if (!this.isLightTexture
|
|
||||||
|| mc == null
|
|
||||||
|| mc.getWrappedClientLevel() == null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ApiShared.LOGGER.info("Lightmap update");
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
|
||||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.pixels, clientLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markLightTexture() { this.isLightTexture = true; }
|
|
||||||
|
|
||||||
}
|
|
||||||
+29
-32
@@ -19,10 +19,13 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
#else
|
#else
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy;
|
||||||
import net.minecraft.client.Camera;
|
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.GameRenderer;
|
||||||
@@ -34,7 +37,6 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
|
||||||
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;
|
||||||
@@ -67,30 +69,6 @@ public class MixinLevelRenderer
|
|||||||
(remap = false)
|
(remap = false)
|
||||||
#endif
|
#endif
|
||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
@Unique
|
|
||||||
private static float previousPartialTicks = 0;
|
|
||||||
|
|
||||||
// TODO: Is there any reason why this is here? Can it be deleted?
|
|
||||||
public MixinLevelRenderer()
|
|
||||||
{
|
|
||||||
throw new NullPointerException("Null cannot be cast to non-null type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
|
||||||
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
|
|
||||||
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
|
|
||||||
#else
|
|
||||||
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
|
|
||||||
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float partialTicks, double cameraX, double cameraY, double cameraZ, CallbackInfo ci)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
// FIXME this is only called when clouds are enabled and vanilla render distance is far enough
|
|
||||||
// not having the partial ticks doesn't appear to be critical currently, but might cause weird issues down the line
|
|
||||||
|
|
||||||
// get the partial ticks since renderBlockLayer doesn't
|
|
||||||
// have access to them
|
|
||||||
previousPartialTicks = partialTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
@@ -108,14 +86,18 @@ public class MixinLevelRenderer
|
|||||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
method = "renderChunkLayer(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 cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
#else
|
#elif MC_VER < MC_1_20_6
|
||||||
@Inject(at = @At("HEAD"),
|
@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",
|
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)
|
||||||
#endif
|
#else
|
||||||
|
@Inject(at = @At("HEAD"),
|
||||||
|
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
||||||
|
cancellable = true)
|
||||||
|
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// get MC's model view and projection matrices
|
|
||||||
#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];
|
||||||
@@ -125,22 +107,33 @@ public class MixinLevelRenderer
|
|||||||
|
|
||||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||||
|
|
||||||
#else
|
#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());
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
|
#else
|
||||||
|
// get the matrices from neoForge's render event.
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
float frameTime;
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
frameTime = Minecraft.getInstance().getFrameTime();
|
||||||
|
#else
|
||||||
|
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||||
|
#endif
|
||||||
|
|
||||||
// only render before solid blocks
|
// only render before solid blocks
|
||||||
if (renderType.equals(RenderType.solid()))
|
if (renderType.equals(RenderType.solid()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(level), mcModelViewMatrix, mcProjectionMatrix, Minecraft.getInstance().getFrameTime());
|
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||||
}
|
}
|
||||||
else if (renderType.equals(RenderType.translucent()))
|
else if (renderType.equals(RenderType.translucent()))
|
||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(level), mcModelViewMatrix, mcProjectionMatrix, Minecraft.getInstance().getFrameTime());
|
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||||
@@ -155,12 +148,16 @@ public class MixinLevelRenderer
|
|||||||
#elif MC_VER < MC_1_20_1
|
#elif MC_VER < MC_1_20_1
|
||||||
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
|
||||||
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
||||||
|
#elif MC_VER < MC_1_20_6
|
||||||
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
||||||
|
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
||||||
#else
|
#else
|
||||||
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
|
||||||
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
|
private void callAfterRunUpdates(CallbackInfo ci)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ChunkWrapper.syncedUpdateClientLightStatus();
|
ChunkWrapper.syncedUpdateClientLightStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-8
@@ -20,10 +20,13 @@
|
|||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||||
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.util.ILightTextureMarker;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -36,13 +39,21 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
public class MixinLightTexture
|
public class MixinLightTexture
|
||||||
{
|
{
|
||||||
@Shadow
|
@Shadow
|
||||||
#if MC_VER >= MC_1_20_4
|
|
||||||
(remap = false)
|
|
||||||
#endif
|
|
||||||
@Final
|
@Final
|
||||||
private DynamicTexture lightTexture;
|
private NativeImage lightPixels;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
public void markLightTexture(CallbackInfo ci) { ((ILightTextureMarker) this.lightTexture).markLightTexture(); }
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
if (mc == null || mc.getWrappedClientLevel() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
|
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-37
@@ -8,6 +8,7 @@ import com.seibel.distanthorizons.core.jar.installer.GitlabGetter;
|
|||||||
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
||||||
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.TitleScreen;
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -24,41 +25,44 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
@Mixin(Minecraft.class)
|
@Mixin(Minecraft.class)
|
||||||
public class MixinMinecraft
|
public class MixinMinecraft
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_20_2
|
// commented out due to a bug with Manifold and having nested preprocessors
|
||||||
#if MC_VER == MC_1_20_1
|
// and since neoforge doesn't work for anything before MC 1.20.6 anyway it doesn't need to be included
|
||||||
@Redirect(
|
|
||||||
method = "Lnet/minecraft/client/Minecraft;setInitialScreen(Lcom/mojang/realmsclient/client/RealmsClient;Lnet/minecraft/server/packs/resources/ReloadInstance;Lnet/minecraft/client/main/GameConfig$QuickPlayData;)V",
|
//#if MC_VER < MC_1_20_2
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
|
//#if MC_VER == MC_1_20_1
|
||||||
)
|
//@Redirect(
|
||||||
public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
// method = "Lnet/minecraft/client/Minecraft;setInitialScreen(Lcom/mojang/realmsclient/client/RealmsClient;Lnet/minecraft/server/packs/resources/ReloadInstance;Lnet/minecraft/client/main/GameConfig$QuickPlayData;)V",
|
||||||
{
|
// at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
|
||||||
#else
|
//)
|
||||||
@Redirect(
|
//public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
||||||
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
|
//{
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
|
//#else
|
||||||
)
|
//@Redirect(
|
||||||
public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
// method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
|
||||||
{
|
// at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
|
||||||
#endif
|
//)
|
||||||
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get()) // Don't do anything if the user doesn't want it
|
//public void onOpenScreen(Minecraft instance, Screen guiScreen)
|
||||||
{
|
//{
|
||||||
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
//#endif
|
||||||
return;
|
// if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get()) // Don't do anything if the user doesn't want it
|
||||||
}
|
// {
|
||||||
|
// instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
||||||
if (SelfUpdater.onStart())
|
// return;
|
||||||
{
|
// }
|
||||||
instance.setScreen(new UpdateModScreen(
|
//
|
||||||
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
|
// if (SelfUpdater.onStart())
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EUpdateBranch.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
|
||||||
else
|
// (Config.Client.Advanced.AutoUpdater.updateBranch.get() == EUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
||||||
{
|
// ));
|
||||||
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
// }
|
||||||
}
|
// else
|
||||||
}
|
// {
|
||||||
#endif
|
// instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//#endif
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_2
|
#if MC_VER >= MC_1_20_2
|
||||||
@Redirect(
|
@Redirect(
|
||||||
@@ -72,11 +76,23 @@ public class MixinMinecraft
|
|||||||
&& SelfUpdater.onStart()
|
&& SelfUpdater.onStart()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
runnable = () -> {
|
runnable = () ->
|
||||||
|
{
|
||||||
|
String versionId;
|
||||||
|
EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get());
|
||||||
|
if (updateBranch == EDhApiUpdateBranch.STABLE)
|
||||||
|
{
|
||||||
|
versionId = ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versionId = GitlabGetter.INSTANCE.projectPipelines.getFirst().get("sha");
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()) : GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
|
versionId
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-28
@@ -23,7 +23,6 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import net.minecraft.client.gui.screens.OptionsScreen;
|
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
@@ -31,51 +30,127 @@ import net.minecraft.network.chat.TranslatableComponent;
|
|||||||
#endif
|
#endif
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
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 org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
import net.minecraft.client.gui.layouts.LinearLayout;
|
||||||
|
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21
|
||||||
|
import net.minecraft.client.gui.screens.OptionsScreen;
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.gui.screens.options.OptionsScreen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a button to the menu to goto the config
|
* Adds a button to the menu to goto the config
|
||||||
*
|
*
|
||||||
* @author coolGi
|
* @author coolGi
|
||||||
* @version 12-02-2021
|
* @version 2024-5-20
|
||||||
*/
|
*/
|
||||||
@Mixin(OptionsScreen.class)
|
@Mixin(OptionsScreen.class)
|
||||||
public class MixinOptionsScreen extends Screen
|
public class MixinOptionsScreen extends Screen
|
||||||
{
|
{
|
||||||
// Get the texture for the button
|
/** Texture used for the config opening button */
|
||||||
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
@Unique
|
||||||
protected MixinOptionsScreen(Component title)
|
private static final ResourceLocation ICON_TEXTURE =
|
||||||
{
|
#if MC_VER < MC_1_21
|
||||||
super(title);
|
new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
||||||
}
|
#else
|
||||||
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
|
||||||
|
#endif
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "init")
|
|
||||||
|
@Unique
|
||||||
|
private TexturedButtonWidget optionsButton = null;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
protected HeaderAndFooterLayout layout;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
protected MixinOptionsScreen(Component title) { super(title); }
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "init")
|
||||||
private void lodconfig$init(CallbackInfo ci)
|
private void lodconfig$init(CallbackInfo ci)
|
||||||
{
|
{
|
||||||
if (Config.Client.optionsButton.get())
|
if (Config.Client.optionsButton.get())
|
||||||
this. #if MC_VER < MC_1_17_1 addButton #else addRenderableWidget #endif
|
{
|
||||||
(new TexturedButtonWidget(
|
#if MC_VER < MC_1_17_1
|
||||||
// Where the button is on the screen
|
this.addButton(this.getOptionsButton());
|
||||||
this.width / 2 - 180, this.height / 6 - 12,
|
#elif MC_VER < MC_1_20_6
|
||||||
// Width and height of the button
|
this.addRenderableWidget(this.getOptionsButton());
|
||||||
20, 20,
|
#else
|
||||||
// Offset
|
|
||||||
0, 0,
|
// add the button so it's rendered
|
||||||
// Some textuary stuff
|
this.addRenderableWidget(this.getOptionsButton());
|
||||||
20, ICON_TEXTURE, 20, 40,
|
|
||||||
// Create the button and tell it where to go
|
// add the button to the correct location in the UI
|
||||||
// For now it goes to the client option by default
|
// TODO is there a better way to do this instead of using access transformers to inject into the exact UI elements?
|
||||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
|
LinearLayout layout = (LinearLayout) this.layout.headerFrame.children.getFirst().child;
|
||||||
// Add a title to the button
|
|
||||||
#if MC_VER < MC_1_19_2
|
// determine how wide the other option buttons are so we can put our botton to the left of them all
|
||||||
new TranslatableComponent(ModInfo.ID + ".title")));
|
AtomicInteger width = new AtomicInteger(0);
|
||||||
#else
|
layout.visitChildren(x -> width.addAndGet(x.getWidth()));
|
||||||
Component.translatable(ModInfo.ID + ".title")));
|
width.addAndGet(-10); // padding between the DH button and the FOV slider
|
||||||
#endif
|
|
||||||
|
layout.wrapped.addChild(this.getOptionsButton(), 1, 2, (settings) -> settings.paddingLeft(width.get() * -1));
|
||||||
|
layout.arrangeElements();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
public TexturedButtonWidget getOptionsButton()
|
||||||
|
{
|
||||||
|
if (this.optionsButton == null)
|
||||||
|
{
|
||||||
|
this.optionsButton
|
||||||
|
= new TexturedButtonWidget(
|
||||||
|
// Where the button is on the screen
|
||||||
|
this.width / 2 - 180, this.height / 6 - 12,
|
||||||
|
// Width and height of the button
|
||||||
|
20, 20,
|
||||||
|
// texture UV Offset
|
||||||
|
0, 0,
|
||||||
|
// Some textuary stuff
|
||||||
|
20, ICON_TEXTURE, 20, 40,
|
||||||
|
// Create the button and tell it where to go
|
||||||
|
// For now it goes to the client option by default
|
||||||
|
(buttonWidget) -> Objects.requireNonNull(this.minecraft).setScreen(GetConfigScreen.getScreen(this)),
|
||||||
|
// Add a title to the button
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
new TranslatableComponent(ModInfo.ID + ".title"));
|
||||||
|
#else
|
||||||
|
Component.translatable(ModInfo.ID + ".title"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.optionsButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-126
@@ -1,126 +0,0 @@
|
|||||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
|
||||||
|
|
||||||
#if FALSE
|
|
||||||
@Mixin(WorldUpgrader.class)
|
|
||||||
public class MixinWorldUpgrader {
|
|
||||||
static class FakeLevelWrapper implements IServerLevelWrapper {
|
|
||||||
private Path saveFolder;
|
|
||||||
private LevelStem stem;
|
|
||||||
private DimensionType dimension;
|
|
||||||
private DimensionTypeWrapper dimensionTypeWrapper;
|
|
||||||
|
|
||||||
public FakeLevelWrapper(LevelStorageSource.LevelStorageAccess storage, WorldGenSettings gen, ResourceKey<Level> dim) {
|
|
||||||
saveFolder = storage.getDimensionPath(dim);
|
|
||||||
stem = gen.dimensions().getOrThrow(WorldGenSettings.levelToLevelStem(dim));
|
|
||||||
dimension = stem.typeHolder().value();
|
|
||||||
dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(dimension);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EDhApiLevelType getLevelType() {
|
|
||||||
return EDhApiLevelType.SERVER_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IDhApiDimensionTypeWrapper getDimensionType() {
|
|
||||||
return dimensionTypeWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBlockLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSkyLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasCeiling() {
|
|
||||||
return dimension.hasCeiling();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasSkyLight() {
|
|
||||||
return dimension.hasSkyLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight() {
|
|
||||||
return dimension.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMinHeight() {
|
|
||||||
return dimension.minY();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockStateWrapper getBlockState(DhBlockPos pos) {
|
|
||||||
return BlockStateWrapper.AIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBiomeWrapper getBiome(DhBlockPos pos) {
|
|
||||||
throw new UnsupportedOperationException("Not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getWrappedMcObject() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IClientLevelWrapper tryGetClientLevelWrapper() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getSaveFolder() {
|
|
||||||
return saveFolder.toFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private DhServerLevel dhServerLevel;
|
|
||||||
@Unique
|
|
||||||
private FakeLevelWrapper fakeLevelWrapper;
|
|
||||||
@Unique
|
|
||||||
public LocalSaveStructure saveStructure;
|
|
||||||
|
|
||||||
@Shadow @Final
|
|
||||||
private DimensionDataStorage overworldDataStorage;
|
|
||||||
@Shadow @Final
|
|
||||||
private LevelStorageSource.LevelStorageAccess levelStorage;
|
|
||||||
@Shadow @Final
|
|
||||||
private WorldGenSettings worldGenSettings;
|
|
||||||
|
|
||||||
@Inject(method = "Lnet/minecraft/util/worldupdate/WorldUpgrader;work()V",
|
|
||||||
at = @At(value = "INVOKE")
|
|
||||||
)
|
|
||||||
private void initWorldUpgrade() {
|
|
||||||
saveStructure = new LocalSaveStructure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "Lnet/minecraft/util/worldupdate/WorldUpgrader;work()V",
|
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/worldupdate/WorldUpgrader;getAllChunkPos(Lnet/minecraft/resources/ResourceKey;)Ljava/util/List;", shift = At.Shift.AFTER),
|
|
||||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
|
||||||
)
|
|
||||||
private void startWorldUpgrade(CallbackInfo info, ResourceKey resourceKey) {
|
|
||||||
ResourceKey<Level> key = resourceKey;
|
|
||||||
fakeLevelWrapper = new FakeLevelWrapper(levelStorage, worldGenSettings, key);
|
|
||||||
dhServerLevel = new DhServerLevel(saveStructure, fakeLevelWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 James Seibel
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.neoforge.mixins.server.unsafe;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
|
|
||||||
import net.minecraft.util.ThreadingDetector;
|
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
|
|
||||||
* FIXME: Recheck this // STILL check this
|
|
||||||
*/
|
|
||||||
@Mixin(ThreadingDetector.class)
|
|
||||||
public class MixinThreadingDetector
|
|
||||||
{
|
|
||||||
@Mutable
|
|
||||||
@Shadow
|
|
||||||
private Semaphore lock;
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
private void setSemaphore(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
this.lock = new Semaphore(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
|
||||||
|
|
||||||
@Mixin(ChunkGenerator.class)
|
|
||||||
public class MixinThreadingDetector { }
|
|
||||||
#endif
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "com.seibel.distanthorizons.neoforge.mixins",
|
"package": "com.seibel.distanthorizons.neoforge.mixins",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"server.unsafe.MixinThreadingDetector",
|
|
||||||
"server.MixinUtilBackgroundThread",
|
"server.MixinUtilBackgroundThread",
|
||||||
"server.MixinChunkGenerator",
|
"server.MixinChunkGenerator",
|
||||||
"server.MixinTFChunkGenerator"
|
"server.MixinTFChunkGenerator"
|
||||||
@@ -14,7 +13,6 @@
|
|||||||
"client.MixinFogRenderer",
|
"client.MixinFogRenderer",
|
||||||
"client.MixinGameRenderer",
|
"client.MixinGameRenderer",
|
||||||
"client.MixinLevelRenderer",
|
"client.MixinLevelRenderer",
|
||||||
"client.MixinDynamicTexture",
|
|
||||||
"client.MixinLightTexture",
|
"client.MixinLightTexture",
|
||||||
"client.MixinOptionsScreen",
|
"client.MixinOptionsScreen",
|
||||||
"client.MixinTextureUtil"
|
"client.MixinTextureUtil"
|
||||||
|
|||||||
+3
-4
@@ -24,13 +24,12 @@ issueTrackerURL = "${issues}"
|
|||||||
acceptableRemoteVersions = "*"
|
acceptableRemoteVersions = "*"
|
||||||
|
|
||||||
# We may need this to make forge (lexforge) & neoforge work together
|
# We may need this to make forge (lexforge) & neoforge work together
|
||||||
#[[mixins]]
|
[[mixins]]
|
||||||
# config = "DistantHorizons.neoforge.mixins.json"
|
config = "DistantHorizons.neoforge.mixins.json"
|
||||||
|
|
||||||
[[dependencies.distanthorizons]]
|
[[dependencies.distanthorizons]]
|
||||||
modId = "minecraft"
|
modId = "minecraft"
|
||||||
mandatory = true # Forge syntax
|
type = "required"
|
||||||
type = "required" # Neoforge syntax
|
|
||||||
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"
|
||||||
@@ -33,6 +33,12 @@ pluginManagement {
|
|||||||
name "ParchmentMC"
|
name "ParchmentMC"
|
||||||
url "https://maven.parchmentmc.org"
|
url "https://maven.parchmentmc.org"
|
||||||
}
|
}
|
||||||
|
maven { // Used for downgrading Java versions
|
||||||
|
url "https://maven.wagyourtail.xyz/releases"
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url "https://maven.wagyourtail.xyz/snapshots"
|
||||||
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fabric_api_version=0.42.0+1.16
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "*" }
|
fabric_incompatibility_list={ "iris": "*" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fabric_api_version=0.46.1+1.17
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "*" }
|
fabric_incompatibility_list={ "iris": "*" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ fabric_api_version=0.76.0+1.18.2
|
|||||||
canvas_version=mc118:1.0.2616
|
canvas_version=mc118:1.0.2616
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "*" }
|
fabric_incompatibility_list={ "iris": "*" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fabric_api_version=0.76.1+1.19.2
|
|||||||
canvas_version=mc119-1.0.2480
|
canvas_version=mc119-1.0.2480
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "*" }
|
fabric_incompatibility_list={ "iris": "*" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ fabric_api_version=0.87.1+1.19.4
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "*" }
|
fabric_incompatibility_list={ "iris": "*" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ accessWidenerVersion=1_20
|
|||||||
builds_for=fabric,forge
|
builds_for=fabric,forge
|
||||||
|
|
||||||
# Fabric loader
|
# Fabric loader
|
||||||
fabric_loader_version=0.14.24
|
fabric_loader_version=0.15.6
|
||||||
fabric_api_version=0.90.4+1.20.1
|
fabric_api_version=0.90.4+1.20.1
|
||||||
# Fabric mod versions
|
# Fabric mod versions
|
||||||
modmenu_version=7.2.2
|
modmenu_version=7.2.2
|
||||||
@@ -21,7 +21,7 @@ fabric_api_version=0.90.4+1.20.1
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ accessWidenerVersion=1_20_2
|
|||||||
builds_for=fabric,forge
|
builds_for=fabric,forge
|
||||||
|
|
||||||
# Fabric loader
|
# Fabric loader
|
||||||
fabric_loader_version=0.14.24
|
fabric_loader_version=0.15.6
|
||||||
fabric_api_version=0.90.4+1.20.2
|
fabric_api_version=0.90.4+1.20.2
|
||||||
# Fabric mod versions
|
# Fabric mod versions
|
||||||
modmenu_version=8.0.0
|
modmenu_version=8.0.0
|
||||||
@@ -21,7 +21,7 @@ fabric_api_version=0.90.4+1.20.2
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ builds_for=fabric,forge
|
|||||||
# neoforge can be added once the issue with mixins has been resolved
|
# neoforge can be added once the issue with mixins has been resolved
|
||||||
|
|
||||||
# Fabric loader
|
# Fabric loader
|
||||||
fabric_loader_version=0.15.1
|
fabric_loader_version=0.15.6
|
||||||
fabric_api_version=0.91.2+1.20.4
|
fabric_api_version=0.91.2+1.20.4
|
||||||
# Fabric mod versions
|
# Fabric mod versions
|
||||||
modmenu_version=9.0.0-pre.1
|
modmenu_version=9.0.0-pre.1
|
||||||
@@ -22,7 +22,7 @@ fabric_api_version=0.91.2+1.20.4
|
|||||||
canvas_version=
|
canvas_version=
|
||||||
|
|
||||||
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
||||||
fabric_recommend_list={ "indium": "*" }
|
fabric_recommend_list={}
|
||||||
|
|
||||||
# Fabric mod run
|
# Fabric mod run
|
||||||
# 0 = Don't enable and don't run
|
# 0 = Don't enable and don't run
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# 1.20.6 version
|
||||||
|
java_version=21
|
||||||
|
minecraft_version=1.20.6
|
||||||
|
parchment_version=1.20.6:2024.05.01
|
||||||
|
compatible_minecraft_versions=["1.20.6"]
|
||||||
|
accessWidenerVersion=1_20_6
|
||||||
|
builds_for=fabric,neoforge
|
||||||
|
# forge is broken due to gradle/build script issues
|
||||||
|
|
||||||
|
# Fabric loader
|
||||||
|
fabric_loader_version=0.15.10
|
||||||
|
fabric_api_version=0.97.8+1.20.6
|
||||||
|
# Fabric mod versions
|
||||||
|
modmenu_version=10.0.0-beta.1
|
||||||
|
starlight_version_fabric=
|
||||||
|
phosphor_version_fabric=
|
||||||
|
lithium_version=
|
||||||
|
sodium_version=mc1.20.6-0.5.8
|
||||||
|
iris_version=1.7.0+1.20.6
|
||||||
|
bclib_version=
|
||||||
|
immersive_portals_version=
|
||||||
|
canvas_version=
|
||||||
|
|
||||||
|
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
||||||
|
fabric_recommend_list={}
|
||||||
|
|
||||||
|
# Fabric mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight=0
|
||||||
|
enable_phosphor=0
|
||||||
|
enable_sodium=1
|
||||||
|
enable_lithium=0
|
||||||
|
enable_iris=1
|
||||||
|
enable_bclib=0
|
||||||
|
enable_immersive_portals=0
|
||||||
|
enable_canvas=0
|
||||||
|
|
||||||
|
# (Neo)Forge loader
|
||||||
|
forge_version=50.0.19
|
||||||
|
neoforge_version=20.6.70-beta
|
||||||
|
# (Neo)Forge mod versions
|
||||||
|
starlight_version_forge=
|
||||||
|
terraforged_version=
|
||||||
|
|
||||||
|
# (Neo)Forge mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight_forge=0
|
||||||
|
enable_terraforged=0
|
||||||
|
enable_terrafirmacraft=0
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# 1.21 version
|
||||||
|
java_version=21
|
||||||
|
minecraft_version=1.21
|
||||||
|
parchment_version=1.20.6:2024.05.01
|
||||||
|
compatible_minecraft_versions=["1.21.0"]
|
||||||
|
accessWidenerVersion=1_20_6
|
||||||
|
builds_for=fabric,neoforge
|
||||||
|
# forge is broken due to gradle/build script issues
|
||||||
|
|
||||||
|
# Fabric loader
|
||||||
|
fabric_loader_version=0.15.11
|
||||||
|
fabric_api_version=0.100.1+1.21
|
||||||
|
# Fabric mod versions
|
||||||
|
modmenu_version=11.0.0-beta.1
|
||||||
|
starlight_version_fabric=
|
||||||
|
phosphor_version_fabric=
|
||||||
|
lithium_version=
|
||||||
|
sodium_version=mc1.21-0.5.9
|
||||||
|
iris_version=1.7.1+1.21
|
||||||
|
bclib_version=
|
||||||
|
immersive_portals_version=
|
||||||
|
canvas_version=
|
||||||
|
|
||||||
|
fabric_incompatibility_list={ "iris": "<=1.6.20" }
|
||||||
|
fabric_recommend_list={}
|
||||||
|
|
||||||
|
# Fabric mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight=0
|
||||||
|
enable_phosphor=0
|
||||||
|
enable_sodium=1
|
||||||
|
enable_lithium=0
|
||||||
|
enable_iris=1
|
||||||
|
enable_bclib=0
|
||||||
|
enable_immersive_portals=0
|
||||||
|
enable_canvas=0
|
||||||
|
|
||||||
|
# (Neo)Forge loader
|
||||||
|
forge_version=50.0.19
|
||||||
|
neoforge_version=21.0.4-beta
|
||||||
|
# (Neo)Forge mod versions
|
||||||
|
starlight_version_forge=
|
||||||
|
terraforged_version=
|
||||||
|
|
||||||
|
# (Neo)Forge mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight_forge=0
|
||||||
|
enable_terraforged=0
|
||||||
|
enable_terrafirmacraft=0
|
||||||
Reference in New Issue
Block a user