Compare commits
189 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69645994c9 | |||
| fdcbb0594d | |||
| e5711b4ddb | |||
| cb1a617b92 | |||
| 4187eaf112 | |||
| 084de2b3f1 | |||
| 7b0a9d4843 | |||
| c42f800db5 | |||
| 300ef3745f | |||
| 5a9fdb3314 | |||
| 8708ca3048 | |||
| 9cfdbdc0ca | |||
| 48f82b0966 | |||
| 75f7ef0085 | |||
| 270776a782 | |||
| 21fff72521 | |||
| a860a9740d | |||
| a2105699fa | |||
| ea4838c791 | |||
| 9168543945 | |||
| 460996d8cd | |||
| c3948abc40 | |||
| 8ed902f6f2 | |||
| 15dda30050 | |||
| 26428ff905 | |||
| 4419ab4b8c | |||
| 5d50994beb | |||
| ce9f843048 | |||
| 8c934b4982 | |||
| 9ae41865f3 | |||
| ade7a8d8dc | |||
| 461dad9fe8 | |||
| b832e77ac2 | |||
| 66c41e49db | |||
| 0f968255e0 | |||
| ed50161cfd | |||
| 7e18acdb8f | |||
| 5c05fdd9fa | |||
| afca4d837f | |||
| 6db3795fa5 | |||
| 21fe38da8e | |||
| 340c0bc586 | |||
| 77c7ebc0d0 | |||
| f55cb4b320 | |||
| 9d3c88f0b2 | |||
| e397a3e47a | |||
| 4ff315de91 | |||
| 2fb1c43d7c | |||
| 58b5fac20b | |||
| ec238d29c6 | |||
| dac36c9e34 | |||
| caca05c0f0 | |||
| 5ce7eae7c0 | |||
| 2c38401637 | |||
| 489fe753f5 | |||
| 2293afc2d3 | |||
| b48adeb3e3 | |||
| 438186cb70 | |||
| c86ff4acae | |||
| e27e1bc2d7 | |||
| 336bf2ea26 | |||
| e72c08b0bc | |||
| 4ced316304 | |||
| d486878876 | |||
| b0b0b38bf8 | |||
| 9e43896864 | |||
| d09ddf57d3 | |||
| 486edac1d8 | |||
| 3b3731a137 | |||
| 563ec70154 | |||
| 175f5ed6d6 | |||
| 1e63607233 | |||
| 4dd8be23fa | |||
| 7fac5b4c6e | |||
| f2ec1ecf3f | |||
| 2674e6b2e9 | |||
| bcbe3f0fb7 | |||
| f85108ed11 | |||
| 2bc5169ce5 | |||
| 1edd809708 | |||
| 475111b38b | |||
| b44a967e56 | |||
| acea685e75 | |||
| 20f15a6b39 | |||
| debf52418c | |||
| cf71491381 | |||
| 0a4a8466cf | |||
| 31fac60d34 | |||
| c335020c2f | |||
| 4db4f2fbc6 | |||
| f9f4a208e7 | |||
| b5fa5936b3 | |||
| 6ceabe7895 | |||
| ec3d8afbfc | |||
| e9a0c6d097 | |||
| 0238568370 | |||
| 74be00e025 | |||
| c10af6dd04 | |||
| 85ee5ac833 | |||
| 21877d67a5 | |||
| ae33a79d6e | |||
| 9204b357d8 | |||
| 78b1b74036 | |||
| 864c5b5f86 | |||
| b271c8e119 | |||
| 79bdae5b8b | |||
| d5dc9f6b79 | |||
| a50f13caa0 | |||
| 75b3649a97 | |||
| 69adb54b91 | |||
| 458c1ae7e0 | |||
| a647551d26 | |||
| 3a45bdd2a2 | |||
| 4806cd2445 | |||
| af7f90f128 | |||
| f72ad60f58 | |||
| 6015afbf4c | |||
| 0369ae63f3 | |||
| 278d5063fb | |||
| a64e72034e | |||
| fcdb56660c | |||
| 0c26261cd5 | |||
| b50525fff9 | |||
| 92e403823b | |||
| e02f56f4ef | |||
| aa4681e044 | |||
| 1c9130c3f1 | |||
| c3597cd843 | |||
| d4a52ac5a3 | |||
| 1b9d14e7b4 | |||
| 0ea27b676e | |||
| cd73608b07 | |||
| 03fc22f611 | |||
| cc251e46b0 | |||
| 7aa0bfefec | |||
| 9bdad5e4f1 | |||
| baebb7323d | |||
| 8a3175f345 | |||
| dc58efb301 | |||
| c9ac4b2ada | |||
| 6e1ec476ed | |||
| d1aa5a524b | |||
| 5c661a3a76 | |||
| d29e9085a1 | |||
| d392de3c0d | |||
| 7209193f8f | |||
| ed4f644a3f | |||
| 34038684a7 | |||
| 6fe6694c82 | |||
| 8e52f1aca5 | |||
| 5ce3dda2d5 | |||
| f4f81f4d7f | |||
| 7c37a5c370 | |||
| b495ac4799 | |||
| 2ddeaf50eb | |||
| 3721ebea6e | |||
| 98f8a87362 | |||
| 10a743ddef | |||
| 95c896f964 | |||
| 040bc16874 | |||
| 35d3fdb473 | |||
| 549f7510f7 | |||
| fab64d8477 | |||
| 4a6a35f617 | |||
| 2b519a826f | |||
| 445c01b5ae | |||
| 0f08bd540e | |||
| 77088465f9 | |||
| affe014433 | |||
| 4c06bf6dbd | |||
| dcab616385 | |||
| 89b7d08e9b | |||
| 724e318221 | |||
| a40d62d46a | |||
| 2f6b4c079b | |||
| 951e3c0271 | |||
| 84825c2d09 | |||
| ec627e2eba | |||
| 06bc9a349f | |||
| ff6c4e227b | |||
| a4d46ffe94 | |||
| bd5c140782 | |||
| 229c3f7c91 | |||
| 693369bc08 | |||
| d109fe6c43 | |||
| 3c9d3707cf | |||
| 6e53564835 | |||
| 2480fe0d86 | |||
| 691c9d3f45 |
+1
-2
@@ -5,7 +5,6 @@ root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
@@ -688,7 +687,7 @@ ij_markdown_wrap_text_inside_blockquotes = true
|
||||
ij_toml_keep_indents_on_empty_lines = false
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
ij_yaml_align_values_properties = do_not_align
|
||||
ij_yaml_autoinsert_sequence_marker = true
|
||||
ij_yaml_block_mapping_on_new_line = false
|
||||
|
||||
@@ -29,7 +29,6 @@ buildAllJars/
|
||||
relocate_natives/.venv/
|
||||
relocate_natives/__pycache__/
|
||||
relocate_natives/apple-codesign/
|
||||
relocate_natives/cache/
|
||||
|
||||
# file from notepad++
|
||||
*.bak
|
||||
|
||||
+9
-5
@@ -17,9 +17,6 @@ variables:
|
||||
# These can be extended so code is a bit less duplicated
|
||||
.build_java:
|
||||
#image: eclipse-temurin:17
|
||||
before_script:
|
||||
- apt-get update
|
||||
- apt-get install python3 python3-pip python-is-python3 python3-venv -y --no-install-recommends
|
||||
cache:
|
||||
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
||||
policy: pull-push
|
||||
@@ -38,13 +35,20 @@ build:
|
||||
stage: build
|
||||
parallel:
|
||||
matrix:
|
||||
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4"]
|
||||
- MC_VER: [
|
||||
"1.21.10", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1",
|
||||
"1.20.6", "1.20.4", "1.20.2", "1.20.1",
|
||||
"1.19.4", "1.19.2",
|
||||
"1.18.2",
|
||||
"1.17.1",
|
||||
"1.16.5"
|
||||
]
|
||||
script:
|
||||
# this both runs the unit tests and assembles the code
|
||||
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||
- ./gradlew build -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||
- ./gradlew mergeJars -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./Merged/* . || true
|
||||
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./build/merged/* . || true
|
||||
artifacts:
|
||||
name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||
paths:
|
||||
|
||||
+17
-79
@@ -13,13 +13,13 @@ plugins {
|
||||
id "com.github.johnrengelman.shadow" version '8.1.1' apply false
|
||||
|
||||
// Plugin to create merged jars
|
||||
id "io.github.pacifistmc.forgix" version "1.2.9"
|
||||
id "io.github.pacifistmc.forgix" version "1.3.4"
|
||||
|
||||
// Manifold preprocessor
|
||||
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
||||
|
||||
// Architectury is used here only as a replacement for forge's own loom
|
||||
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
|
||||
id "dev.architectury.loom" version "1.11-SNAPSHOT" apply false
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,10 @@ def writeBuildGradlePredefine(List<String> mcVers, int mcIndex)
|
||||
String verStr = mcVers[i].replace(".", "_");
|
||||
sb.append("MC_" + verStr + "=" + i.toString() + "\n");
|
||||
|
||||
if (mcIndex == i)
|
||||
if (mcIndex == i)
|
||||
{
|
||||
sb.append("MC_VER=" + i.toString() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,63 +69,16 @@ project.gradle.ext.getProperties().each { prop ->
|
||||
// Sets up manifold stuff
|
||||
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
|
||||
|
||||
|
||||
|
||||
|
||||
// Sets up the version string (the name we use for our jar)
|
||||
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
|
||||
// Forgix settings (used for merging jars)
|
||||
forgix {
|
||||
|
||||
String loaderHyphenSeparatedList = ((String)gradle.builds_for).replaceAll(",", "-");
|
||||
|
||||
group = "com.seibel.distanthorizons"
|
||||
mergedJarName = "DistantHorizons-${loaderHyphenSeparatedList}-${rootProject.versionStr}.jar"
|
||||
|
||||
if (findProject(":forge"))
|
||||
forge {
|
||||
jarLocation = "build/libs/DistantHorizons-forge-${rootProject.versionStr}.jar"
|
||||
}
|
||||
|
||||
if (findProject(":neoforge"))
|
||||
custom {
|
||||
projectName = "neoforge"
|
||||
jarLocation = "build/libs/DistantHorizons-neoforge-${rootProject.versionStr}.jar"
|
||||
}
|
||||
|
||||
if (findProject(":fabric"))
|
||||
fabric {
|
||||
jarLocation = "build/libs/DistantHorizons-fabric-${rootProject.versionStr}.jar"
|
||||
}
|
||||
|
||||
if (findProject(":quilt"))
|
||||
quilt {
|
||||
jarLocation = "build/libs/DistantHorizons-quilt-${rootProject.versionStr}.jar"
|
||||
}
|
||||
|
||||
removeDuplicate "com.seibel.distanthorizons"
|
||||
}
|
||||
|
||||
|
||||
class NativeTransformer implements Transformer {
|
||||
private boolean enabled = false
|
||||
private final HashMap<String, String> replacements = new HashMap()
|
||||
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||
private var nativeRelocator
|
||||
|
||||
public File rootDir
|
||||
|
||||
NativeTransformer() {
|
||||
try {
|
||||
int exitCode = Runtime.getRuntime().exec(new String[]{"python", "--version"}).waitFor()
|
||||
if (exitCode == 0) {
|
||||
enabled = true
|
||||
}
|
||||
} catch (IOException e) {
|
||||
println(e)
|
||||
}
|
||||
}
|
||||
|
||||
void relocateNative(String target, String replacement) {
|
||||
if (replacement.length() > target.length()) {
|
||||
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||
@@ -132,22 +87,15 @@ class NativeTransformer implements Transformer {
|
||||
replacements.put(target, replacement)
|
||||
}
|
||||
|
||||
void before(Closure closure) {
|
||||
if (enabled)
|
||||
closure.run()
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||
return enabled && replacements.keySet().stream().anyMatch {
|
||||
return replacements.keySet().stream().anyMatch {
|
||||
element.name.startsWith(it as String)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(@Nonnull TransformerContext context) {
|
||||
println("Transforming $context.path...")
|
||||
byte[] content = context.is.readAllBytes()
|
||||
|
||||
if (nativeRelocator == null) {
|
||||
@@ -299,7 +247,8 @@ subprojects { p ->
|
||||
// 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}")
|
||||
|
||||
|
||||
forgeShadowMe("com.github.luben:zstd-jni:1.5.7-4")
|
||||
|
||||
// Compression
|
||||
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
||||
@@ -395,16 +344,13 @@ subprojects { p ->
|
||||
// Sqlite Database
|
||||
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
||||
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
||||
relocate "org.sqlite", "dh_sqlite", {
|
||||
exclude "org/sqlite/native/**"
|
||||
}
|
||||
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||
|
||||
transform(NativeTransformer) {
|
||||
rootDir = project.rootDir
|
||||
|
||||
before {
|
||||
relocate "org.sqlite", "dh_sqlite", {
|
||||
exclude "org/sqlite/native/**"
|
||||
}
|
||||
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||
}
|
||||
|
||||
relocateNative "org/sqlite", "dh_sqlite"
|
||||
relocateNative "org_sqlite", "dh_1sqlite"
|
||||
}
|
||||
@@ -502,6 +448,8 @@ subprojects { p ->
|
||||
|
||||
fabric_incompatibility_list : fabric_incompatibility_list,
|
||||
fabric_recommend_list : fabric_recommend_list,
|
||||
|
||||
neoforge_version_range : neoforge_version_range,
|
||||
]
|
||||
|
||||
// replace any properties in the sub-projects with the values defined here
|
||||
@@ -582,8 +530,9 @@ allprojects { p ->
|
||||
apply plugin: "java"
|
||||
apply plugin: "maven-publish"
|
||||
|
||||
// Sets the name of the jar, the version will contain the name of the project if it isn't the root project
|
||||
archivesBaseName = rootProject.mod_name
|
||||
version = project.name + "-" + rootProject.versionStr
|
||||
version = (project == rootProject ? "" : project.name + "-") + rootProject.versionStr
|
||||
group = rootProject.maven_group
|
||||
|
||||
// this is the text that appears at the top of the overview (home) page
|
||||
@@ -748,14 +697,3 @@ allprojects { p ->
|
||||
withSourcesJar()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Delete the merged folder when running clean
|
||||
task cleanMergedJars() {
|
||||
def mergedFolder = file("Merged")
|
||||
if (mergedFolder.exists()) {
|
||||
delete(mergedFolder)
|
||||
}
|
||||
}
|
||||
// add cleanMergedJars to the end of the "clean" task
|
||||
tasks["clean"].finalizedBy(cleanMergedJars)
|
||||
|
||||
@@ -22,7 +22,7 @@ for d in versionProperties/*; do
|
||||
echo "==================== Merging $version ===================="
|
||||
sh gradlew mergeJars -PmcVer=$version
|
||||
if [ $? != 0 ]; then continue; fi
|
||||
|
||||
|
||||
echo "==================== Moving jar ===================="
|
||||
mv Merged/*.jar buildAllJars/
|
||||
mv build/merged/*.jar buildAllJars/
|
||||
done
|
||||
|
||||
+6
-3
@@ -15,12 +15,15 @@ for %%f in (versionProperties\*) do (
|
||||
@rem Clean out the folders, build it, and merge it
|
||||
echo ==================== Cleaning workspace to build !version! ====================
|
||||
call .\gradlew.bat clean
|
||||
echo ==================== Building !version! ====================
|
||||
|
||||
echo ==================== Building !version! ====================
|
||||
call .\gradlew.bat build -PmcVer="!version!"
|
||||
echo ==================== Merging !version! ====================
|
||||
|
||||
echo ==================== Merging !version! ====================
|
||||
call .\gradlew.bat mergeJars -PmcVer="!version!"
|
||||
|
||||
echo ==================== Moving jar ====================
|
||||
move Merged\*.jar buildAllJars\
|
||||
move build\merged\*.jar buildAllJars\
|
||||
)
|
||||
|
||||
endlocal
|
||||
|
||||
@@ -12,14 +12,15 @@ class NativeRelocator
|
||||
/**
|
||||
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||
* Executes the appropriate preparation script based on the OS.
|
||||
*
|
||||
* @throws Exception if the preparation script fails or an unsupported OS is detected.
|
||||
*/
|
||||
NativeRelocator(Path rootDirectory) throws Exception
|
||||
NativeRelocator(Path rootDirectory)
|
||||
{
|
||||
this.rootDirectory = rootDirectory;
|
||||
this.cacheRoot = this.rootDirectory.resolve("cache");
|
||||
|
||||
}
|
||||
|
||||
private void prepare() throws Exception
|
||||
{
|
||||
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
||||
{
|
||||
return;
|
||||
@@ -33,7 +34,10 @@ class NativeRelocator
|
||||
{
|
||||
processBuilder.command("powershell", "-ExecutionPolicy", "Bypass", "./prepare.ps1");
|
||||
}
|
||||
else if (os.contains("nix") || os.contains("nux") || os.contains("mac"))
|
||||
else if (os.contains("nix")
|
||||
|| os.contains("nux")
|
||||
|| os.contains("mac")
|
||||
|| os.contains("freebsd"))
|
||||
{
|
||||
processBuilder.command("./prepare.sh");
|
||||
}
|
||||
@@ -196,6 +200,9 @@ class NativeRelocator
|
||||
return Files.readAllBytes(outputFilePath);
|
||||
}
|
||||
|
||||
System.out.println("Relocating to " + outputPath + "...");
|
||||
this.prepare();
|
||||
|
||||
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||
{
|
||||
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
||||
|
||||
+19
-11
@@ -5,6 +5,7 @@ import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDh
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
|
||||
import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
||||
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.DhDebugScreenEntry;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
@@ -66,7 +67,7 @@ public abstract class AbstractModInitializer
|
||||
{
|
||||
DependencySetup.createClientBindings();
|
||||
|
||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client.");
|
||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client, firing DhApiBeforeDhInitEvent...");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||
|
||||
this.startup();
|
||||
@@ -77,13 +78,18 @@ public abstract class AbstractModInitializer
|
||||
|
||||
this.initializeModCompat();
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||
|
||||
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
||||
this.initConfig();
|
||||
logModIncompatibilityWarnings(); // needs to be called after config loading
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
// debug screen rendering handled via a mixin
|
||||
#else
|
||||
DhDebugScreenEntry.register();
|
||||
#endif
|
||||
|
||||
this.subscribeClientStartedEvent(this::postInit);
|
||||
}
|
||||
|
||||
@@ -91,7 +97,7 @@ public abstract class AbstractModInitializer
|
||||
{
|
||||
DependencySetup.createServerBindings();
|
||||
|
||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server.");
|
||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server, firing DhApiBeforeDhInitEvent event...");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||
|
||||
this.startup();
|
||||
@@ -106,8 +112,7 @@ public abstract class AbstractModInitializer
|
||||
|
||||
this.initializeModCompat();
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized.");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
||||
|
||||
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer = new CommandInitializer(dispatcher); });
|
||||
|
||||
@@ -121,7 +126,7 @@ public abstract class AbstractModInitializer
|
||||
|
||||
this.checkForUpdates();
|
||||
|
||||
LOGGER.info("Dedicated server initialized at " + server.getServerDirectory());
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,7 +168,7 @@ public abstract class AbstractModInitializer
|
||||
|
||||
private void initConfig()
|
||||
{
|
||||
ConfigBase.INSTANCE = new ConfigBase(ModInfo.ID, ModInfo.NAME, Config.class, ModInfo.CONFIG_FILE_VERSION);
|
||||
ConfigBase.RunFirstTimeSetup();
|
||||
Config.completeDelayedSetup();
|
||||
}
|
||||
|
||||
@@ -183,9 +188,12 @@ public abstract class AbstractModInitializer
|
||||
|
||||
private void postInit()
|
||||
{
|
||||
LOGGER.info("Post-Initializing Mod");
|
||||
LOGGER.info("Running Delayed setup...");
|
||||
this.runDelayedSetup();
|
||||
LOGGER.info("Mod Post-Initialized");
|
||||
LOGGER.info("Delayed setup complete, firing DhApiAfterDhInitEvent event...");
|
||||
|
||||
// should be fired after all delayed setup so singletons and config can be accessed
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
-4
@@ -1,6 +1,7 @@
|
||||
package com.seibel.distanthorizons.common;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
||||
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
|
||||
@@ -30,6 +31,16 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||
#endif
|
||||
|
||||
// "Forge byte" is an unused packet ID. We have our own system which works with all mod loaders,
|
||||
// so we're just accounting for it by reading the protocol version as a byte instead of a short in Forge, to keep cross-loader compatibility
|
||||
private final boolean forgeByteInProtocolVersion;
|
||||
|
||||
|
||||
public AbstractPluginPacketSender() { this(false); }
|
||||
public AbstractPluginPacketSender(boolean forgeByteInProtocolVersion)
|
||||
{
|
||||
this.forgeByteInProtocolVersion = forgeByteInProtocolVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
|
||||
@@ -41,7 +52,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
@Override
|
||||
public abstract void sendToServer(AbstractNetworkMessage message);
|
||||
|
||||
public static AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||
public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||
{
|
||||
AbstractNetworkMessage message = null;
|
||||
|
||||
@@ -49,7 +60,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
{
|
||||
in.markReaderIndex();
|
||||
|
||||
int protocolVersion = in.readShort();
|
||||
int protocolVersion = this.forgeByteInProtocolVersion ? in.readByte() : in.readShort();
|
||||
if (protocolVersion != ModInfo.PROTOCOL_VERSION)
|
||||
{
|
||||
return new IncompatibleMessageInternalEvent(protocolVersion);
|
||||
@@ -82,11 +93,19 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
}
|
||||
}
|
||||
|
||||
public static void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
|
||||
public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
|
||||
{
|
||||
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild
|
||||
Objects.requireNonNull(message);
|
||||
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
||||
|
||||
if (this.forgeByteInProtocolVersion)
|
||||
{
|
||||
out.writeByte(ModInfo.PROTOCOL_VERSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.seibel.distanthorizons.common;
|
||||
|
||||
#if MC_VER >= MC_1_20_6
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
@@ -12,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) implements CustomPacketPayload
|
||||
{
|
||||
public static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE);
|
||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -23,11 +26,11 @@ public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) impl
|
||||
@NotNull
|
||||
@Override
|
||||
public CommonPacketPayload decode(@NotNull FriendlyByteBuf in)
|
||||
{ return new CommonPacketPayload(AbstractPluginPacketSender.decodeMessage(in)); }
|
||||
{ return new CommonPacketPayload(PACKET_SENDER.decodeMessage(in)); }
|
||||
|
||||
@Override
|
||||
public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload)
|
||||
{ AbstractPluginPacketSender.encodeMessage(out, payload.message()); }
|
||||
{ PACKET_SENDER.encodeMessage(out, payload.message()); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-5
@@ -59,13 +59,9 @@ public class DependencySetup
|
||||
DependencySetupDoneCheck.isDone = true;
|
||||
}
|
||||
|
||||
//@Environment(EnvType.SERVER)
|
||||
public static void createServerBindings()
|
||||
{
|
||||
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftServerWrapper.INSTANCE);
|
||||
}
|
||||
{ SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftServerWrapper.INSTANCE); }
|
||||
|
||||
//@Environment(EnvType.CLIENT)
|
||||
public static void createClientBindings()
|
||||
{
|
||||
SingletonInjector.INSTANCE.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
|
||||
|
||||
+6
-2
@@ -49,7 +49,9 @@ public class McObjectConverter
|
||||
@Deprecated
|
||||
public static Mat4f Convert(
|
||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#else org.joml.Matrix4f #endif
|
||||
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||
#else org.joml.Matrix4fc
|
||||
#endif
|
||||
mcMatrix)
|
||||
{
|
||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||
@@ -63,7 +65,9 @@ public class McObjectConverter
|
||||
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
|
||||
private static void storeMatrix(
|
||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#else org.joml.Matrix4f #endif
|
||||
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||
#else org.joml.Matrix4fc
|
||||
#endif
|
||||
matrix,
|
||||
FloatBuffer buffer)
|
||||
{
|
||||
|
||||
+10
-1
@@ -71,7 +71,16 @@ public class VersionConstants implements IVersionConstants
|
||||
#elif MC_VER == MC_1_21_3
|
||||
return "1.21.3";
|
||||
#elif MC_VER == MC_1_21_4
|
||||
return "1.21_4";
|
||||
return "1.21.4";
|
||||
#elif MC_VER == MC_1_21_5
|
||||
return "1.21.5";
|
||||
#elif MC_VER == MC_1_21_6
|
||||
return "1.21.6";
|
||||
#elif MC_VER == MC_1_21_8
|
||||
return "1.21.8";
|
||||
|
||||
#elif MC_VER == MC_1_21_10
|
||||
return "1.21.10";
|
||||
#else
|
||||
ERROR MC version constant missing
|
||||
#endif
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
|
||||
|
||||
public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
{
|
||||
protected final BiomeWrapper biomeWrapper;
|
||||
|
||||
protected final int smoothingRadiusInBlocks;
|
||||
protected final FullDataSourceV2 fullDataSource;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public AbstractDhTintGetter(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
||||
{
|
||||
this.biomeWrapper = biomeWrapper;
|
||||
this.fullDataSource = fullDataSource;
|
||||
this.smoothingRadiusInBlocks = Config.Client.Advanced.Graphics.Quality.lodBiomeBlending.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// shared methods //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
{
|
||||
// determine how wide this data source is so we can determine
|
||||
// if blending should be used
|
||||
byte dataSourceDetailLevel = DhSectionPos.getDetailLevel(this.fullDataSource.getPos());
|
||||
// convert from section detail level to absolute detail level
|
||||
dataSourceDetailLevel = (byte)(dataSourceDetailLevel - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
int dataSourceLodWidthInBlocks = DhSectionPos.getDetailLevelWidthInBlocks(dataSourceDetailLevel);
|
||||
|
||||
// don't do any smoothing if smoothing is disabled or if the LOD
|
||||
// is to large for block-based smoothing to show up
|
||||
if (this.smoothingRadiusInBlocks == 0
|
||||
|| dataSourceLodWidthInBlocks > this.smoothingRadiusInBlocks)
|
||||
{
|
||||
return colorResolver.getColor(this.unwrapBiome(this.biomeWrapper.biome), blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
|
||||
|
||||
// use a rolling average to calculate the color
|
||||
int dataPointCount = 0;
|
||||
int rollingRed = 0;
|
||||
int rollingGreen = 0;
|
||||
int rollingBlue = 0;
|
||||
|
||||
int xMin = blockPos.getX() - this.smoothingRadiusInBlocks;
|
||||
int xMax = blockPos.getX() + this.smoothingRadiusInBlocks;
|
||||
|
||||
int zMin = blockPos.getZ() - this.smoothingRadiusInBlocks;
|
||||
int zMax = blockPos.getZ() + this.smoothingRadiusInBlocks;
|
||||
|
||||
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable(0, blockPos.getY(), 0);
|
||||
for (int x = xMin; x < xMax; x++)
|
||||
{
|
||||
for (int z = zMin; z < zMax; z++)
|
||||
{
|
||||
mutableBlockPos.setX(x);
|
||||
mutableBlockPos.setZ(z);
|
||||
|
||||
// this can return the same position/datapoint for larger LODs duplicating work,
|
||||
// however for small smoothing ranges that isn't a big deal and for large LODs
|
||||
// we ignore smoothing anyway
|
||||
long dataPoint = this.fullDataSource.getAtBlockPos(mutableBlockPos);
|
||||
if (dataPoint == FullDataPointUtil.EMPTY_DATA_POINT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the color for this nearby position
|
||||
int id = FullDataPointUtil.getId(dataPoint);
|
||||
BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id);
|
||||
int color = colorResolver.getColor(this.unwrapBiome(biomeWrapper.biome), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
|
||||
|
||||
// rolling average
|
||||
rollingRed += ColorUtil.getRed(color);
|
||||
rollingGreen += ColorUtil.getGreen(color);
|
||||
rollingBlue += ColorUtil.getBlue(color);
|
||||
|
||||
dataPointCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if no data was present (rarely possible)
|
||||
// just use the default center's color
|
||||
if (dataPointCount == 0)
|
||||
{
|
||||
return colorResolver.getColor(this.unwrapBiome(this.biomeWrapper.biome), blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
|
||||
int colorInt = ColorUtil.argbToInt(
|
||||
255, // blending often ignores alpha, having it always 255 prevents multiplication issues later
|
||||
rollingRed / dataPointCount,
|
||||
rollingGreen / dataPointCount,
|
||||
rollingBlue / dataPointCount);
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
protected Biome unwrapBiome(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
return biome.value();
|
||||
#else
|
||||
return biome;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+82
-59
@@ -47,6 +47,7 @@ import net.minecraft.core.registries.Registries;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
#endif
|
||||
@@ -130,14 +131,6 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
//LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
|
||||
}
|
||||
|
||||
/** should only be used to create {@link BiomeWrapper#EMPTY_WRAPPER} */
|
||||
private BiomeWrapper()
|
||||
{
|
||||
this.biome = null;
|
||||
this.serialString = EMPTY_BIOME_STRING;
|
||||
this.hashCode = Objects.hash(this.serialString);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
@@ -286,64 +279,16 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
BiomeWrapper foundWrapper = EMPTY_WRAPPER;
|
||||
try
|
||||
{
|
||||
// parse the resource location
|
||||
int separatorIndex = resourceLocationString.indexOf(":");
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
try
|
||||
{
|
||||
#if MC_VER < MC_1_21_1
|
||||
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#else
|
||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "].");
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
Level level = (Level) levelWrapper.getWrappedMcObject();
|
||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||
|
||||
boolean success;
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#elif MC_VER < MC_1_21_3
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#else
|
||||
Holder<Biome> biome;
|
||||
Optional<Holder.Reference<Biome>> optionalBiomeHolder = registryAccess.lookupOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
if (optionalBiomeHolder.isPresent())
|
||||
{
|
||||
Biome unwrappedBiome = optionalBiomeHolder.get().value();
|
||||
success = (unwrappedBiome != null);
|
||||
biome = new Holder.Direct<>(unwrappedBiome);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
biome = null;
|
||||
}
|
||||
#endif
|
||||
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess);
|
||||
|
||||
|
||||
|
||||
if (!success)
|
||||
if (!deserializeResult.success)
|
||||
{
|
||||
if (!brokenResourceLocationStrings.contains(resourceLocationString))
|
||||
{
|
||||
@@ -354,7 +299,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
}
|
||||
|
||||
|
||||
foundWrapper = (BiomeWrapper) getBiomeWrapper(biome, levelWrapper);
|
||||
foundWrapper = (BiomeWrapper) getBiomeWrapper(deserializeResult.biome, levelWrapper);
|
||||
return foundWrapper;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -368,4 +313,82 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException
|
||||
{
|
||||
// parse the resource location
|
||||
int separatorIndex = resourceLocationString.indexOf(":");
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
try
|
||||
{
|
||||
#if MC_VER < MC_1_21_1
|
||||
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#else
|
||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "].");
|
||||
}
|
||||
|
||||
|
||||
boolean success;
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#elif MC_VER < MC_1_21_3
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#else
|
||||
Holder<Biome> biome;
|
||||
Optional<Holder.Reference<Biome>> optionalBiomeHolder = registryAccess.lookupOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
if (optionalBiomeHolder.isPresent())
|
||||
{
|
||||
Biome unwrappedBiome = optionalBiomeHolder.get().value();
|
||||
success = (unwrappedBiome != null);
|
||||
biome = new Holder.Direct<>(unwrappedBiome);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
biome = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new BiomeDeserializeResult(success, biome);
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
public static class BiomeDeserializeResult
|
||||
{
|
||||
public final boolean success;
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
public final Biome biome;
|
||||
#else
|
||||
public final Holder<Biome> biome;
|
||||
#endif
|
||||
|
||||
public BiomeDeserializeResult(boolean success, #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome)
|
||||
{
|
||||
this.success = success;
|
||||
this.biome = biome;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+78
-29
@@ -81,6 +81,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
public static final BlockStateWrapper AIR = new BlockStateWrapper(null, null);
|
||||
|
||||
public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt";
|
||||
public static final String WATER_RESOURCE_LOCATION_STRING = "minecraft:water";
|
||||
|
||||
public static HashSet<IBlockStateWrapper> rendererIgnoredBlocks = null;
|
||||
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
|
||||
@@ -97,16 +98,14 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
/** technically final, but since it requires a method call to generate it can't be marked as such */
|
||||
private String serialString;
|
||||
private final int hashCode;
|
||||
/**
|
||||
* Cached opacity value, -1 if not populated. <br>
|
||||
* Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE}
|
||||
*/
|
||||
private int opacity = -1;
|
||||
/** Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE} */
|
||||
private final int opacity;
|
||||
/** used by the Iris shader mod to determine how each LOD should be rendered */
|
||||
private byte blockMaterialId = 0;
|
||||
|
||||
private final boolean isBeaconBlock;
|
||||
private final boolean isBeaconBaseBlock;
|
||||
private final boolean allowsBeaconBeamPassage;
|
||||
/** null if this block can't tint beacons */
|
||||
private final Color beaconTintColor;
|
||||
private final Color mapColor;
|
||||
@@ -163,9 +162,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
this.serialString = this.serialize(levelWrapper);
|
||||
this.hashCode = Objects.hash(this.serialString);
|
||||
this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index;
|
||||
this.opacity = this.calculateOpacity();
|
||||
|
||||
String lowercaseSerial = this.serialString.toLowerCase();
|
||||
|
||||
|
||||
// beacon blocks
|
||||
String lowercaseSerial = this.serialString.toLowerCase();
|
||||
boolean isBeaconBaseBlock = false;
|
||||
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
|
||||
{
|
||||
@@ -201,6 +203,39 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
this.beaconTintColor = beaconTintColor;
|
||||
|
||||
|
||||
// allow/deny beacon beam passage
|
||||
boolean allowsBeaconBeamPassage;
|
||||
if (this.blockState != null)
|
||||
{
|
||||
// get block properties (defaults to the values used by air)
|
||||
boolean canOcclude = this.getCanOcclude();
|
||||
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||
|
||||
if (lowercaseSerial.contains("minecraft:bedrock"))
|
||||
{
|
||||
// bedrock is a special case fully opaque block that does allow beacons through
|
||||
allowsBeaconBeamPassage = true;
|
||||
}
|
||||
else if (propagatesSkyLightDown || !canOcclude)
|
||||
{
|
||||
// stairs, cake, fences, etc.
|
||||
allowsBeaconBeamPassage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-opaque blocks (glass, mob spawners, etc.)
|
||||
// all allow beacons through
|
||||
allowsBeaconBeamPassage = (this.opacity != LodUtil.BLOCK_FULLY_OPAQUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// air allows beacons through
|
||||
allowsBeaconBeamPassage = true;
|
||||
}
|
||||
this.allowsBeaconBeamPassage = allowsBeaconBeamPassage;
|
||||
|
||||
|
||||
int mcColor = 0;
|
||||
if (this.blockState != null)
|
||||
{
|
||||
@@ -344,28 +379,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
//=================//
|
||||
|
||||
@Override
|
||||
public int getOpacity()
|
||||
public int getOpacity() { return this.opacity; }
|
||||
private int calculateOpacity()
|
||||
{
|
||||
// use the cached opacity value if possible
|
||||
if (this.opacity != -1)
|
||||
{
|
||||
return this.opacity;
|
||||
}
|
||||
|
||||
|
||||
// get block properties (default to the values used by air)
|
||||
boolean canOcclude = false;
|
||||
boolean propagatesSkyLightDown = true;
|
||||
if (this.blockState != null)
|
||||
{
|
||||
canOcclude = this.blockState.canOcclude();
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||
#else
|
||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
|
||||
#endif
|
||||
}
|
||||
// get block properties (defaults to the values used by air)
|
||||
boolean canOcclude = this.getCanOcclude();
|
||||
boolean propagatesSkyLightDown = this.getPropagatesSkyLightDown();
|
||||
|
||||
|
||||
|
||||
@@ -398,9 +417,37 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
}
|
||||
|
||||
|
||||
this.opacity = opacity;
|
||||
return this.opacity;
|
||||
return opacity;
|
||||
}
|
||||
private boolean getCanOcclude()
|
||||
{
|
||||
// defaults to the value used by air
|
||||
boolean canOcclude = false;
|
||||
if (this.blockState != null)
|
||||
{
|
||||
canOcclude = this.blockState.canOcclude();
|
||||
}
|
||||
|
||||
return canOcclude;
|
||||
}
|
||||
private boolean getPropagatesSkyLightDown()
|
||||
{
|
||||
// defaults to the value used by air
|
||||
boolean propagatesSkyLightDown = true;
|
||||
if (this.blockState != null)
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
||||
#else
|
||||
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
|
||||
#endif
|
||||
}
|
||||
|
||||
return propagatesSkyLightDown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
||||
@@ -473,6 +520,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; }
|
||||
@Override
|
||||
public boolean isBeaconTintBlock() { return this.beaconTintColor != null; }
|
||||
@Override
|
||||
public boolean allowsBeaconBeamPassage() { return this.allowsBeaconBeamPassage; }
|
||||
|
||||
@Override
|
||||
public Color getMapColor() { return this.mapColor; }
|
||||
|
||||
+109
-28
@@ -20,6 +20,8 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
@@ -40,11 +42,18 @@ import java.util.Random;
|
||||
#endif
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
#else
|
||||
import net.minecraft.client.renderer.block.model.BlockModelPart;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This stores and calculates the colors
|
||||
* the given {@link BlockState} should have based
|
||||
@@ -56,6 +65,8 @@ public class ClientBlockStateColorCache
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
// TODO it isn't that we need the level, but that we need the adjacent data
|
||||
// maybe we can pass in the full data source?
|
||||
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
||||
private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>();
|
||||
|
||||
@@ -84,7 +95,9 @@ public class ClientBlockStateColorCache
|
||||
private static final RandomSource RANDOM = RandomSource.create();
|
||||
#endif
|
||||
|
||||
private final IClientLevelWrapper levelWrapper;
|
||||
private final IClientLevelWrapper clientLevelWrapper;
|
||||
private final BlockStateWrapper blockStateWrapper;
|
||||
|
||||
private final BlockState blockState;
|
||||
private final LevelReader level;
|
||||
|
||||
@@ -167,8 +180,10 @@ public class ClientBlockStateColorCache
|
||||
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper samplingLevel)
|
||||
{
|
||||
this.blockState = blockState;
|
||||
this.levelWrapper = samplingLevel;
|
||||
this.clientLevelWrapper = samplingLevel;
|
||||
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
||||
this.blockStateWrapper = BlockStateWrapper.fromBlockState(this.blockState, this.clientLevelWrapper);
|
||||
|
||||
this.resolveColors();
|
||||
}
|
||||
|
||||
@@ -196,9 +211,7 @@ public class ClientBlockStateColorCache
|
||||
List<BakedQuad> quads = null;
|
||||
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
||||
{
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
||||
|
||||
quads = this.getQuadsForDirection(direction);
|
||||
if (quads != null && !quads.isEmpty()
|
||||
&& !(
|
||||
this.blockState.getBlock() instanceof RotatedPillarBlock
|
||||
@@ -212,19 +225,37 @@ public class ClientBlockStateColorCache
|
||||
|
||||
if (quads == null || quads.isEmpty())
|
||||
{
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(this.blockState).getQuads(this.blockState, null, RANDOM);
|
||||
quads = this.getUnculledQuads();
|
||||
}
|
||||
|
||||
if (quads != null && !quads.isEmpty())
|
||||
if (quads != null
|
||||
&& !quads.isEmpty()
|
||||
&& quads.get(0) != null)
|
||||
{
|
||||
this.needPostTinting = quads.get(0).isTinted();
|
||||
this.needShade = quads.get(0).isShade();
|
||||
this.tintIndex = quads.get(0).getTintIndex();
|
||||
BakedQuad firstQuad = quads.get(0);
|
||||
|
||||
this.needPostTinting = firstQuad.isTinted();
|
||||
#if MC_VER <= MC_1_21_4
|
||||
this.needShade = firstQuad.isShade();
|
||||
this.tintIndex = firstQuad.getTintIndex();
|
||||
#else
|
||||
this.needShade = firstQuad.shade();
|
||||
this.tintIndex = firstQuad.tintIndex();
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
#if MC_VER < MC_1_17_1 quads.get(0).sprite,
|
||||
#else quads.get(0).getSprite(), #endif
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
firstQuad.sprite,
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#elif MC_VER < MC_1_21_5
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.getSprite(),
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#else
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.sprite(),
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -232,8 +263,7 @@ public class ClientBlockStateColorCache
|
||||
this.needPostTinting = false;
|
||||
this.needShade = false;
|
||||
this.tintIndex = 0;
|
||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
this.baseColor = this.getParticleIconColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -242,10 +272,17 @@ public class ClientBlockStateColorCache
|
||||
this.needPostTinting = true;
|
||||
this.needShade = false;
|
||||
this.tintIndex = 0;
|
||||
this.baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
this.baseColor = this.getParticleIconColor();
|
||||
}
|
||||
|
||||
|
||||
//String serialString = this.blockStateWrapper.getSerialString();
|
||||
//if (serialString.contains("minecraft:water")
|
||||
// || serialString.contains("grass"))
|
||||
//{
|
||||
// BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
||||
//}
|
||||
|
||||
this.isColorResolved = true;
|
||||
}
|
||||
finally
|
||||
@@ -253,6 +290,35 @@ public class ClientBlockStateColorCache
|
||||
RESOLVE_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); }
|
||||
@Nullable
|
||||
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
|
||||
{
|
||||
List<BakedQuad> quads = null;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM);
|
||||
#else
|
||||
List<BlockModelPart> blockModelPartList = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(this.blockState).collectParts(RANDOM);
|
||||
|
||||
quads = new ArrayList<>();
|
||||
if (blockModelPartList != null)
|
||||
{
|
||||
for (int i = 0; i < blockModelPartList.size(); i++)
|
||||
{
|
||||
// if direction is null this will return the unculled quads
|
||||
quads.addAll(blockModelPartList.get(i).getQuads(direction));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return quads;
|
||||
}
|
||||
|
||||
//TODO: Perhaps make this not just use the first frame?
|
||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
||||
{
|
||||
@@ -364,16 +430,18 @@ public class ClientBlockStateColorCache
|
||||
* This method was suggested by IMS from the Iris/Sodium team.
|
||||
* That's where the numbers and code are based.
|
||||
*/
|
||||
private static int linearToSrgb(float c)
|
||||
private static int linearToSrgb(float color)
|
||||
{
|
||||
if (!(c > MIN_SRGB_BOUND)) {
|
||||
c = MIN_SRGB_BOUND;
|
||||
if (!(color > MIN_SRGB_BOUND))
|
||||
{
|
||||
color = MIN_SRGB_BOUND;
|
||||
}
|
||||
|
||||
if (c > MAX_SRGB_BOUND) {
|
||||
c = MAX_SRGB_BOUND;
|
||||
if (color > MAX_SRGB_BOUND)
|
||||
{
|
||||
color = MAX_SRGB_BOUND;
|
||||
}
|
||||
int inputBits = Float.floatToRawIntBits(c);
|
||||
int inputBits = Float.floatToRawIntBits(color);
|
||||
int entry = linearToSrgbTable[((inputBits - MIN_SRGB_BITS) >> 20)];
|
||||
|
||||
int bias = (entry >>> 16) << 9;
|
||||
@@ -383,13 +451,20 @@ public class ClientBlockStateColorCache
|
||||
return (bias + (scale * t)) >>> 16;
|
||||
}
|
||||
|
||||
private int getParticleIconColor()
|
||||
{
|
||||
return calculateColorFromTexture(
|
||||
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// public getter //
|
||||
//===============//
|
||||
|
||||
public int getColor(BiomeWrapper biome, DhBlockPos pos)
|
||||
public int getColor(BiomeWrapper biome, FullDataSourceV2 fullDataSource, DhBlockPos pos)
|
||||
{
|
||||
// only get the tint if the block needs to be tinted
|
||||
if (!this.needPostTinting)
|
||||
@@ -414,12 +489,15 @@ public class ClientBlockStateColorCache
|
||||
try
|
||||
{
|
||||
tintColor = Minecraft.getInstance().getBlockColors()
|
||||
.getColor(this.blockState, new TintWithoutLevelOverrider(biome, this.levelWrapper), McObjectConverter.Convert(pos), this.tintIndex);
|
||||
.getColor(this.blockState,
|
||||
new TintWithoutLevelSmoothOverrider(biome, fullDataSource), // TODO can this object be cached?
|
||||
McObjectConverter.Convert(pos),
|
||||
this.tintIndex);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// this exception generally occurs if the tint requires other blocks besides itself
|
||||
LOGGER.debug("Unable to use ["+TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
|
||||
LOGGER.debug("Unable to use ["+TintWithoutLevelSmoothOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
|
||||
BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
||||
}
|
||||
}
|
||||
@@ -430,7 +508,10 @@ public class ClientBlockStateColorCache
|
||||
// this logic can't be used all the time due to it breaking some blocks tinting
|
||||
// specifically oceans don't render correctly
|
||||
tintColor = Minecraft.getInstance().getBlockColors()
|
||||
.getColor(this.blockState, new TintGetterOverrideFast(this.level), McObjectConverter.Convert(pos), this.tintIndex);
|
||||
.getColor(this.blockState,
|
||||
new TintGetterOverrideSmooth(this.level, biome, fullDataSource), // TODO can this object be cached?
|
||||
McObjectConverter.Convert(pos),
|
||||
this.tintIndex);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
-194
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 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.block;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.*;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class TintGetterOverrideFast implements BlockAndTintGetter
|
||||
{
|
||||
LevelReader parent;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public TintGetterOverrideFast(LevelReader parent) { this.parent = parent; }
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
private Biome _getBiome(BlockPos pos)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
return this.parent.getBiome(pos).value();
|
||||
#else
|
||||
return parent.getBiome(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) { return colorResolver.getColor(this._getBiome(blockPos), blockPos.getX(), blockPos.getZ()); }
|
||||
|
||||
@Override
|
||||
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
|
||||
|
||||
@Override
|
||||
public LevelLightEngine getLightEngine() { return this.parent.getLightEngine(); }
|
||||
|
||||
@Override
|
||||
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) { return this.parent.getBrightness(lightLayer, blockPos); }
|
||||
|
||||
@Override
|
||||
public int getRawBrightness(BlockPos blockPos, int i) { return this.parent.getRawBrightness(blockPos, i); }
|
||||
|
||||
@Override
|
||||
public boolean canSeeSky(BlockPos blockPos) { return this.parent.canSeeSky(blockPos); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockEntity getBlockEntity(BlockPos blockPos) { return this.parent.getBlockEntity(blockPos); }
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos blockPos) { return this.parent.getBlockState(blockPos); }
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos blockPos) { return this.parent.getFluidState(blockPos); }
|
||||
|
||||
@Override
|
||||
public int getLightEmission(BlockPos blockPos) { return this.parent.getLightEmission(blockPos); }
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMaxLightLevel() { return parent.getMaxLightLevel(); }
|
||||
#else
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public Stream<BlockState> getBlockStates(AABB aABB)
|
||||
{ return this.parent.getBlockStates(aABB); }
|
||||
|
||||
@Override
|
||||
public BlockHitResult clip(ClipContext clipContext)
|
||||
{ return this.parent.clip(clipContext); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState)
|
||||
{ return this.parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState); }
|
||||
|
||||
@Override
|
||||
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier)
|
||||
{ return this.parent.getBlockFloorHeight(voxelShape, supplier); }
|
||||
|
||||
@Override
|
||||
public double getBlockFloorHeight(BlockPos blockPos) { return this.parent.getBlockFloorHeight(blockPos); }
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMaxBuildHeight() { return this.parent.getMaxBuildHeight(); }
|
||||
#else
|
||||
@Override
|
||||
public int getMaxY() { return this.parent.getMaxY(); }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// post MC 1.17 //
|
||||
//==============//
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
@Override
|
||||
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType)
|
||||
{ return this.parent.getBlockEntity(blockPos, blockEntityType); }
|
||||
|
||||
@Override
|
||||
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext)
|
||||
{ return this.parent.isBlockInLine(clipBlockStateContext); }
|
||||
|
||||
@Override
|
||||
public int getHeight() { return this.parent.getHeight(); }
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMinBuildHeight() { return this.parent.getMinBuildHeight(); }
|
||||
#else
|
||||
@Override
|
||||
public int getMinY() { return this.parent.getMinY(); }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public int getSectionsCount() { return this.parent.getSectionsCount(); }
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMinSection() { return this.parent.getMinSection(); }
|
||||
#else
|
||||
@Override
|
||||
public int getMinSectionY() { return BlockAndTintGetter.super.getMinSectionY(); }
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMaxSection() { return this.parent.getMaxSection(); }
|
||||
#else
|
||||
@Override
|
||||
public int getMaxSectionY() { return this.parent.getMaxSectionY(); }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public boolean isOutsideBuildHeight(BlockPos blockPos) { return this.parent.isOutsideBuildHeight(blockPos); }
|
||||
|
||||
@Override
|
||||
public boolean isOutsideBuildHeight(int i) { return this.parent.isOutsideBuildHeight(i); }
|
||||
|
||||
@Override
|
||||
public int getSectionIndex(int i) { return this.parent.getSectionIndex(i); }
|
||||
|
||||
@Override
|
||||
public int getSectionIndexFromSectionY(int i) { return this.parent.getSectionIndexFromSectionY(i); }
|
||||
|
||||
@Override
|
||||
public int getSectionYFromSectionIndex(int i) { return this.parent.getSectionYFromSectionIndex(i); }
|
||||
#endif
|
||||
}
|
||||
+10
-45
@@ -19,12 +19,10 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Cursor3D;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.*;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -40,10 +38,9 @@ import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class TintGetterOverrideSmooth implements BlockAndTintGetter
|
||||
public class TintGetterOverrideSmooth extends AbstractDhTintGetter
|
||||
{
|
||||
LevelReader parent;
|
||||
public int smoothingRange;
|
||||
private final LevelReader parent;
|
||||
|
||||
|
||||
|
||||
@@ -51,10 +48,10 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange)
|
||||
{
|
||||
public TintGetterOverrideSmooth(LevelReader parent, BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
||||
{
|
||||
super(biomeWrapper, fullDataSource);
|
||||
this.parent = parent;
|
||||
this.smoothingRange = smoothingRange;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,41 +60,6 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
private Biome _getBiome(BlockPos pos)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
return this.parent.getBiome(pos).value();
|
||||
#else
|
||||
return parent.getBiome(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
{
|
||||
int i = smoothingRange;
|
||||
if (i == 0)
|
||||
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||
int j = (i * 2 + 1) * (i * 2 + 1);
|
||||
int k = 0;
|
||||
int l = 0;
|
||||
int m = 0;
|
||||
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
|
||||
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
while (cursor3D.advance())
|
||||
{
|
||||
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
|
||||
int n = colorResolver.getColor(this._getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
|
||||
k += (n & 0xFF0000) >> 16;
|
||||
l += (n & 0xFF00) >> 8;
|
||||
m += n & 0xFF;
|
||||
}
|
||||
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) { return this.calculateBlockTint(blockPos, colorResolver); }
|
||||
|
||||
@Override
|
||||
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
|
||||
|
||||
@@ -185,7 +147,7 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
|
||||
public int getMinSection() { return this.parent.getMinSection(); }
|
||||
#else
|
||||
@Override
|
||||
public int getMinSectionY() { return BlockAndTintGetter.super.getMinSectionY(); }
|
||||
public int getMinSectionY() { return super.getMinSectionY(); }
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@@ -211,4 +173,7 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
|
||||
@Override
|
||||
public int getSectionYFromSectionIndex(int i) { return this.parent.getSectionYFromSectionIndex(i); }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
-158
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 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.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.Direction;
|
||||
import net.minecraft.world.level.*;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
|
||||
public class TintWithoutLevelOverrider implements BlockAndTintGetter
|
||||
{
|
||||
/**
|
||||
* This will only ever be null if there was an issue with {@link IClientLevelWrapper#getPlainsBiomeWrapper()}
|
||||
* but {@link Nullable} is there just in case.
|
||||
*/
|
||||
@Nullable
|
||||
private final Biome biome;
|
||||
|
||||
|
||||
|
||||
public TintWithoutLevelOverrider(BiomeWrapper biomeWrapper, IClientLevelWrapper clientLevelWrapper)
|
||||
{
|
||||
// try to get the wrapped biome
|
||||
Biome unwrappedBiome = null;
|
||||
if (biomeWrapper.biome != null)
|
||||
{
|
||||
unwrappedBiome = unwrap(biomeWrapper.biome);
|
||||
}
|
||||
|
||||
if(unwrappedBiome == null)
|
||||
{
|
||||
// we are looking at the empty biome wrapper, try using plains as a backup
|
||||
BiomeWrapper plainsBiomeWrapper = ((BiomeWrapper) clientLevelWrapper.getPlainsBiomeWrapper());
|
||||
if (plainsBiomeWrapper != null)
|
||||
{
|
||||
unwrappedBiome = unwrap(plainsBiomeWrapper.biome);
|
||||
}
|
||||
}
|
||||
|
||||
this.biome = unwrappedBiome;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||
{
|
||||
if (this.biome != null)
|
||||
{
|
||||
return colorResolver.getColor(this.biome, blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// hopefully unneeded debug color
|
||||
return ColorUtil.CYAN;
|
||||
}
|
||||
}
|
||||
|
||||
private static Biome unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
return biome.value();
|
||||
#else
|
||||
return biome;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// unused methods //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public float getShade(@NotNull Direction direction, boolean shade)
|
||||
{
|
||||
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||
}
|
||||
@Override
|
||||
public @NotNull LevelLightEngine getLightEngine()
|
||||
{
|
||||
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(@NotNull BlockPos pos)
|
||||
{
|
||||
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlockState(@NotNull BlockPos pos)
|
||||
{
|
||||
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||
}
|
||||
@Override
|
||||
public @NotNull FluidState getFluidState(@NotNull BlockPos pos)
|
||||
{
|
||||
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// post MC 1.17 //
|
||||
//==============//
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{ throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Override
|
||||
public int getMinBuildHeight()
|
||||
{ throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||
#else
|
||||
@Override
|
||||
public int getMinY()
|
||||
{ throw new UnsupportedOperationException("ERROR: getMinY() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
+4
-60
@@ -19,37 +19,24 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
|
||||
public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
|
||||
public class TintWithoutLevelSmoothOverrider extends AbstractDhTintGetter
|
||||
{
|
||||
final BiomeWrapper biome;
|
||||
public int smoothingRange;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public TintWithoutLevelSmoothOverrider(BiomeWrapper biome, int smoothingRange)
|
||||
{
|
||||
this.biome = biome;
|
||||
this.smoothingRange = smoothingRange;
|
||||
}
|
||||
public TintWithoutLevelSmoothOverrider(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
||||
{ super(biomeWrapper, fullDataSource); }
|
||||
|
||||
|
||||
|
||||
@@ -57,49 +44,6 @@ public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
{
|
||||
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
|
||||
}
|
||||
private Biome _unwrap(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
return biome.value();
|
||||
#else
|
||||
return biome;
|
||||
#endif
|
||||
}
|
||||
|
||||
// public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
// {
|
||||
// int i = smoothingRange;
|
||||
// if (i == 0)
|
||||
// return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||
// int j = (i * 2 + 1) * (i * 2 + 1);
|
||||
// int k = 0;
|
||||
// int l = 0;
|
||||
// int m = 0;
|
||||
// Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
|
||||
// BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
// while (cursor3D.advance())
|
||||
// {
|
||||
// mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
|
||||
// int n;
|
||||
// if (LodCommonMain.forgeMethodCaller != null) {
|
||||
// n = LodCommonMain.forgeMethodCaller.colorResolverGetColor(colorResolver, _getBiome(mutableBlockPos),
|
||||
// mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
// } else {
|
||||
// n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
// }
|
||||
//
|
||||
// k += (n & 0xFF0000) >> 16;
|
||||
// l += (n & 0xFF00) >> 8;
|
||||
// m += n & 0xFF;
|
||||
// }
|
||||
// return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public float getShade(Direction direction, boolean shade)
|
||||
{ throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
||||
|
||||
+737
-392
File diff suppressed because it is too large
Load Diff
+89
@@ -0,0 +1,89 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
// not supported for older MC versions
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.components.debug.DebugScreenDisplayer;
|
||||
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
// not supported for older MC versions
|
||||
public class DhDebugScreenEntry
|
||||
{}
|
||||
#else
|
||||
public class DhDebugScreenEntry implements net.minecraft.client.gui.components.debug.DebugScreenEntry
|
||||
{
|
||||
public static void register()
|
||||
{
|
||||
// This method is private, so its access will need to be widened
|
||||
DebugScreenEntries.register(
|
||||
// The id, this will be displayed on the options screen
|
||||
ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, "distant_horizons"),
|
||||
// The screen entry
|
||||
new DhDebugScreenEntry()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(@NotNull DebugScreenDisplayer displayer, @Nullable Level level, @Nullable LevelChunk clientChunk, @Nullable LevelChunk serverChunk)
|
||||
{
|
||||
List<String> messageList = new ArrayList<>();
|
||||
F3Screen.addStringToDisplay(messageList);
|
||||
|
||||
for (String message : messageList)
|
||||
{
|
||||
displayer.addLine(message);
|
||||
}
|
||||
|
||||
//// The following will display like so if it is the only entry on the screen:
|
||||
//// First left! First Right!
|
||||
////
|
||||
//// Hello world! Random text!
|
||||
//// Lorem ipsum.
|
||||
//// I am another group!
|
||||
//// I am one group This will appear after with no line breaks!
|
||||
//// All in a row
|
||||
//// Provided in a list.
|
||||
////
|
||||
//
|
||||
//displayer.addLine("Hello world!");
|
||||
//displayer.addLine("Lorem ipsum.");
|
||||
//displayer.addLine("Random text!");
|
||||
//
|
||||
//// These will be displayed first
|
||||
//displayer.addPriorityLine("First left!");
|
||||
//displayer.addPriorityLine("First right!");
|
||||
//
|
||||
//// These will be grouped separately based on the key
|
||||
//displayer.addToGroup(GROUP_ONE, List.of(
|
||||
// "I am one group",
|
||||
// "All in a row",
|
||||
// "Provided in a list."
|
||||
//));
|
||||
//
|
||||
//displayer.addToGroup(GROUP_TWO, "I am another group!");
|
||||
//displayer.addToGroup(GROUP_TWO, "This will appear after with no line breaks!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowed(boolean reducedDebugInfo)
|
||||
{
|
||||
// Always show regardless of accessibility option
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -52,6 +52,27 @@ public class DhScreen extends Screen
|
||||
{
|
||||
renderTooltip(guiStack, comp, x, y);
|
||||
}
|
||||
#elif MC_VER < MC_1_21_6
|
||||
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||
{
|
||||
guiStack.drawCenteredString(font, text, x, y, color);
|
||||
}
|
||||
protected void DhDrawString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||
{
|
||||
guiStack.drawString(font, text, x, y, color);
|
||||
}
|
||||
//protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
||||
//{
|
||||
// guiStack.renderTooltip(font, text, x, y);
|
||||
//}
|
||||
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
|
||||
{
|
||||
guiStack.renderComponentTooltip(font, comp, x, y);
|
||||
}
|
||||
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
|
||||
{
|
||||
guiStack.renderTooltip(font, text, x, y);
|
||||
}
|
||||
#else
|
||||
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
|
||||
{
|
||||
@@ -61,17 +82,20 @@ public class DhScreen extends Screen
|
||||
{
|
||||
guiStack.drawString(font, text, x, y, color);
|
||||
}
|
||||
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
||||
{
|
||||
guiStack.renderTooltip(font, text, x, y);
|
||||
}
|
||||
//protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
|
||||
//{
|
||||
// //guiStack.renderTooltip(font, text, x, y);
|
||||
//}
|
||||
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
|
||||
{
|
||||
guiStack.renderComponentTooltip(font, comp, x, y);
|
||||
guiStack.setComponentTooltipForNextFrame(font, comp, x, y);
|
||||
}
|
||||
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
|
||||
{
|
||||
guiStack.renderTooltip(font, text, x, y);
|
||||
guiStack.setTooltipForNextFrame(font, text, x, y);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+30
-16
@@ -1,40 +1,54 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
||||
import com.seibel.distanthorizons.core.config.gui.ConfigScreen;
|
||||
import com.seibel.distanthorizons.core.config.gui.JavaScreenHandlerScreen;
|
||||
import com.seibel.distanthorizons.core.config.gui.OpenGLConfigScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public class GetConfigScreen
|
||||
{
|
||||
public static type useScreen = type.Classic;
|
||||
protected static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public enum type
|
||||
public static EType useScreen = EType.Classic;
|
||||
|
||||
public enum EType
|
||||
{
|
||||
Classic,
|
||||
@Deprecated
|
||||
OpenGL, // This was just an attempt, it didn't work out, and we are going to change to javafx soon (as soon as that works)
|
||||
JavaFX;
|
||||
JavaSwing;
|
||||
}
|
||||
|
||||
public static Screen getScreen(Screen parent)
|
||||
{
|
||||
// Generate the language
|
||||
// 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));
|
||||
// TODO it'd be nice to have this run automatically on startup
|
||||
// but this will only work once MC has added our lang file,
|
||||
// which won't be for sure added until we request a GUI
|
||||
if (ModInfo.IS_DEV_BUILD)
|
||||
{
|
||||
String missingLangEntries = ConfigBase.INSTANCE.generateLang(true, true);
|
||||
|
||||
// trim to remove any newlines/spaces
|
||||
// that may be present when no lang entries need changing
|
||||
// then we can check length != 0 if any items are missing and need adding
|
||||
String trimmedMissingEntries = missingLangEntries.trim();
|
||||
if (!trimmedMissingEntries.isEmpty())
|
||||
{
|
||||
LOGGER.warn("One or more language entries is missing:");
|
||||
LOGGER.warn(missingLangEntries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (useScreen)
|
||||
{
|
||||
case Classic:
|
||||
return ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
|
||||
case OpenGL:
|
||||
MinecraftScreen.getScreen(parent, new OpenGLConfigScreen(), ModInfo.ID + ".title");
|
||||
return null;
|
||||
// case JavaFX -> MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
||||
case JavaFX:
|
||||
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
||||
case JavaSwing:
|
||||
//return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
||||
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
||||
default:
|
||||
throw new IllegalArgumentException("No config screen implementation defined for ["+useScreen+"].");
|
||||
}
|
||||
|
||||
+40
-37
@@ -24,26 +24,26 @@ public class MinecraftScreen
|
||||
private static class ConfigScreenRenderer extends DhScreen
|
||||
{
|
||||
private final Screen parent;
|
||||
private ConfigListWidget list;
|
||||
private ConfigListWidget configListWidget;
|
||||
private AbstractScreen screen;
|
||||
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
public static net.minecraft.network.chat.TranslatableComponent translate(String str, Object... args)
|
||||
{
|
||||
return new net.minecraft.network.chat.TranslatableComponent(str, args);
|
||||
}
|
||||
{ return new net.minecraft.network.chat.TranslatableComponent(str, args); }
|
||||
#else
|
||||
public static net.minecraft.network.chat.MutableComponent translate(String str, Object... args)
|
||||
{
|
||||
return net.minecraft.network.chat.Component.translatable(str, args);
|
||||
}
|
||||
#endif
|
||||
{ return net.minecraft.network.chat.Component.translatable(str, args); }
|
||||
#endif
|
||||
|
||||
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
|
||||
{
|
||||
super(translate(translationName));
|
||||
#if MC_VER < MC_1_21_10
|
||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
|
||||
#else
|
||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().handle();
|
||||
#endif
|
||||
this.parent = parent;
|
||||
this.screen = screen;
|
||||
}
|
||||
@@ -53,20 +53,22 @@ public class MinecraftScreen
|
||||
{
|
||||
super.init(); // Init Minecraft's screen
|
||||
Window mcWindow = this.minecraft.getWindow();
|
||||
screen.width = mcWindow.getWidth();
|
||||
screen.height = mcWindow.getHeight();
|
||||
screen.scaledWidth = this.width;
|
||||
screen.scaledHeight = this.height;
|
||||
screen.init(); // Init our own config screen
|
||||
this.screen.width = mcWindow.getWidth();
|
||||
this.screen.height = mcWindow.getHeight();
|
||||
this.screen.scaledWidth = this.width;
|
||||
this.screen.scaledHeight = this.height;
|
||||
this.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.configListWidget = 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
|
||||
this.list.setRenderBackground(false); // Disable from rendering
|
||||
{
|
||||
this.configListWidget.setRenderBackground(false); // Disable from rendering
|
||||
}
|
||||
#endif
|
||||
|
||||
this.addWidget(this.list); // Add the tint to the things to be rendered
|
||||
this.addWidget(this.configListWidget); // Add the tint to the things to be rendered
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,14 +80,17 @@ public class MinecraftScreen
|
||||
{
|
||||
#if MC_VER < MC_1_20_2
|
||||
this.renderBackground(matrices); // Render background
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||
#else
|
||||
// background blur is already being rendered, rendering again causes the game to crash
|
||||
#endif
|
||||
this.list.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
|
||||
|
||||
screen.mouseX = mouseX;
|
||||
screen.mouseY = mouseY;
|
||||
screen.render(delta); // Render everything on the main screen
|
||||
this.configListWidget.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
|
||||
|
||||
this.screen.mouseX = mouseX;
|
||||
this.screen.mouseY = mouseY;
|
||||
this.screen.render(delta); // Render everything on the main screen
|
||||
|
||||
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
|
||||
}
|
||||
@@ -95,41 +100,39 @@ public class MinecraftScreen
|
||||
{
|
||||
super.resize(mc, width, height); // Resize Minecraft's screen
|
||||
Window mcWindow = this.minecraft.getWindow();
|
||||
screen.width = mcWindow.getWidth();
|
||||
screen.height = mcWindow.getHeight();
|
||||
screen.scaledWidth = this.width;
|
||||
screen.scaledHeight = this.height;
|
||||
screen.onResize(); // Resize our screen
|
||||
this.screen.width = mcWindow.getWidth();
|
||||
this.screen.height = mcWindow.getHeight();
|
||||
this.screen.scaledWidth = this.width;
|
||||
this.screen.scaledHeight = this.height;
|
||||
this.screen.onResize(); // Resize our screen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
super.tick(); // Tick Minecraft's screen
|
||||
screen.tick(); // Tick our screen
|
||||
if (screen.close) // If we decide to close the screen, then actually close the screen
|
||||
onClose();
|
||||
this.screen.tick(); // Tick our screen
|
||||
if (this.screen.close) // If we decide to close the screen, then actually close the screen
|
||||
{
|
||||
this.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
screen.onClose(); // Close our screen
|
||||
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
|
||||
this.screen.onClose(); // Close our screen
|
||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Goto the parent screen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilesDrop(@NotNull List<Path> files)
|
||||
{
|
||||
screen.onFilesDrop(files);
|
||||
}
|
||||
{ this.screen.onFilesDrop(files); }
|
||||
|
||||
// For checking if it should close when you press the escape key
|
||||
@Override
|
||||
public boolean shouldCloseOnEsc()
|
||||
{
|
||||
return screen.shouldCloseOnEsc;
|
||||
}
|
||||
{ return this.screen.shouldCloseOnEsc; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
+20
-2
@@ -39,9 +39,13 @@ import net.minecraft.client.renderer.GameRenderer;
|
||||
#elif MC_VER < MC_1_20_2
|
||||
import net.minecraft.client.gui.components.ImageButton;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
#else
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderPipelines;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -172,9 +176,15 @@ public class TexturedButtonWidget extends Button
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
matrices.blitSprite(SPRITES.get(this.active, this.isHoveredOrFocused()), this.getX(), this.getY(), this.getWidth(), this.getHeight());
|
||||
#elif MC_VER < MC_1_21_6
|
||||
matrices.blitSprite(
|
||||
RenderType::guiTextured,
|
||||
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||
this.getX(), this.getY(),
|
||||
this.getWidth(), this.getHeight());
|
||||
#else
|
||||
matrices.blitSprite(
|
||||
RenderType::guiTextured,
|
||||
RenderPipelines.GUI_TEXTURED,
|
||||
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||
this.getX(), this.getY(),
|
||||
this.getWidth(), this.getHeight());
|
||||
@@ -196,7 +206,7 @@ public class TexturedButtonWidget extends Button
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
matrices.blit(this.textureResourceLocation, this.getX(), this.getY(), this.u, this.v + (this.hoveredVOffset * i), this.width, this.height, this.textureWidth, this.textureHeight);
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
matrices.blit(
|
||||
RenderType::guiTextured,
|
||||
this.textureResourceLocation,
|
||||
@@ -204,6 +214,14 @@ public class TexturedButtonWidget extends Button
|
||||
this.u, this.v + (this.hoveredVOffset * i),
|
||||
this.width, this.height,
|
||||
this.textureWidth, this.textureHeight);
|
||||
#else
|
||||
matrices.blit(
|
||||
RenderPipelines.GUI_TEXTURED,
|
||||
this.textureResourceLocation,
|
||||
this.getX(), this.getY(),
|
||||
this.u, this.v + (this.hoveredVOffset * i),
|
||||
this.width, this.height,
|
||||
this.textureWidth, this.textureHeight);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
+20
-23
@@ -74,6 +74,7 @@ public class ChangelogScreen extends DhScreen
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.setupChangelog(versionID);
|
||||
@@ -175,9 +176,12 @@ public class ChangelogScreen extends DhScreen
|
||||
{
|
||||
#if MC_VER < MC_1_20_2
|
||||
this.renderBackground(matrices); // Render background
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||
#else
|
||||
// background blur is already being rendered, rendering again causes the game to crash
|
||||
#endif
|
||||
|
||||
if (!this.usable)
|
||||
{
|
||||
return;
|
||||
@@ -249,42 +253,35 @@ public class ChangelogScreen extends DhScreen
|
||||
private final Component text;
|
||||
private final List<AbstractWidget> children = new ArrayList<>();
|
||||
|
||||
private ButtonEntry(Component text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
private ButtonEntry(Component text) { this.text = text; }
|
||||
|
||||
public static ButtonEntry create(Component text)
|
||||
{
|
||||
return new ButtonEntry(text);
|
||||
}
|
||||
{ return new ButtonEntry(text); }
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
@Override
|
||||
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
{
|
||||
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
|
||||
}
|
||||
#else
|
||||
{ GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF); }
|
||||
#elif MC_VER < MC_1_21_10
|
||||
@Override
|
||||
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
{
|
||||
matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF);
|
||||
}
|
||||
{ matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF); }
|
||||
#else
|
||||
@Override
|
||||
public void renderContent(GuiGraphics matrices, int y, int x, boolean hovered, float tickDelta)
|
||||
{ matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF); }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public List<? extends GuiEventListener> children()
|
||||
{
|
||||
return this.children;
|
||||
}
|
||||
public List<? extends GuiEventListener> children() { return this.children; }
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
@Override
|
||||
public List<? extends NarratableEntry> narratables()
|
||||
{
|
||||
return this.children;
|
||||
}
|
||||
public List<? extends NarratableEntry> narratables() { return this.children; }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+22
-6
@@ -169,8 +169,10 @@ public class UpdateModScreen extends DhScreen
|
||||
{
|
||||
#if MC_VER < MC_1_20_2
|
||||
this.renderBackground(matrices); // Render background
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||
#else
|
||||
// background blur is already being rendered, rendering again causes the game to crash
|
||||
#endif
|
||||
|
||||
// TODO: add the tooltips for the buttons
|
||||
@@ -178,16 +180,30 @@ public class UpdateModScreen extends DhScreen
|
||||
// TODO: Add tooltips
|
||||
|
||||
// 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.text2", currentVer, nextVer),
|
||||
this.width / 2, this.height / 2 - 20, 0x52FD52);
|
||||
this.DhDrawCenteredString(matrices, this.font,
|
||||
Translatable(ModInfo.ID + ".updater.text1"),
|
||||
this.width / 2, this.height / 2 - 35,
|
||||
#if MC_VER < MC_1_21_6
|
||||
0xFFFFFF // RGB
|
||||
#else
|
||||
0xFFFFFFFF // ARGB
|
||||
#endif
|
||||
);
|
||||
this.DhDrawCenteredString(matrices, this.font,
|
||||
Translatable(ModInfo.ID + ".updater.text2", this.currentVer, this.nextVer),
|
||||
this.width / 2, this.height / 2 - 20,
|
||||
#if MC_VER < MC_1_21_6
|
||||
0x52FD52 // RGB
|
||||
#else
|
||||
0xFF52FD52 // ARGB
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
|
||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen
|
||||
}
|
||||
|
||||
}
|
||||
+14
-1
@@ -33,6 +33,7 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
@@ -306,10 +307,22 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GLProxy.hasInstance())
|
||||
{
|
||||
// rendering setup hasn't finished
|
||||
return;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
player.sendMessage(new TextComponent(string), getPlayer().getUUID());
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_10
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
||||
#else
|
||||
|
||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
||||
{
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -19,7 +19,11 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
#else
|
||||
import com.mojang.blaze3d.opengl.GlStateManager;
|
||||
#endif
|
||||
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
@@ -148,7 +152,10 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
||||
public void glBlendFunc(int sfactor, int dfactor)
|
||||
{
|
||||
GL32.glBlendFunc(sfactor, dfactor);
|
||||
GlStateManager._blendFunc(sfactor, dfactor);
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
GlStateManager._blendFunc(sfactor, dfactor);
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#glBlendFuncSeparate */
|
||||
@Override
|
||||
@@ -226,7 +233,7 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
||||
GlStateManager._activeTexture(textureId);
|
||||
}
|
||||
@Override
|
||||
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE); }
|
||||
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); }
|
||||
|
||||
/**
|
||||
* Always binds to {@link GL32#GL_TEXTURE_2D}
|
||||
|
||||
+154
-18
@@ -25,7 +25,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.seibel.distanthorizons.common.wrappers.WrapperFactory;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
|
||||
@@ -33,9 +32,12 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
#if MC_VER < MC_1_17_1
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
#else
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_19_4
|
||||
@@ -43,8 +45,6 @@ import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
#else
|
||||
#endif
|
||||
#if MC_VER >= MC_1_20_2
|
||||
#endif
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -71,22 +71,21 @@ import net.minecraft.world.phys.Vec3;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
#if MC_VER >= MC_1_21_5
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
#else
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A singleton that contains everything
|
||||
* related to rendering in Minecraft.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 12-12-2021
|
||||
*/
|
||||
//@Environment(EnvType.CLIENT)
|
||||
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
|
||||
|
||||
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
|
||||
|
||||
@@ -102,7 +101,19 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
*/
|
||||
public int finalLevelFrameBufferId = -1;
|
||||
|
||||
public boolean colorTextureCastFailLogged = false;
|
||||
public boolean depthTextureCastFailLogged = false;
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
#else
|
||||
private static FogRenderer mcFogRenderer = null;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
@@ -115,11 +126,22 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
/** Unless you really need to know if the player is blind, use {@link MinecraftRenderWrapper#isFogStateSpecial()}/{@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */
|
||||
public boolean playerHasBlindingEffect()
|
||||
{
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
||||
if (MC.player == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (MC.player.getActiveEffectsMap() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
||||
#if MC_VER >= MC_1_19_2
|
||||
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
||||
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
||||
#endif
|
||||
;
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,7 +174,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
Math.max(0f, Math.min(colorValues[2], 1f)), // b
|
||||
Math.max(0f, Math.min(colorValues[3], 1f)) // a
|
||||
);
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
Vector4f colorValues = FogRenderer.computeFogColor(MC.gameRenderer.getMainCamera(), partialTicks, MC.level, 1, MC.gameRenderer.getDarkenWorldAmount(partialTicks));
|
||||
return new Color(
|
||||
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
||||
@@ -160,6 +182,31 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||
);
|
||||
#else
|
||||
|
||||
if (mcFogRenderer == null)
|
||||
{
|
||||
mcFogRenderer = new FogRenderer();
|
||||
}
|
||||
|
||||
if (MC.level == null)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
boolean isFoggy =
|
||||
MC.level.effects().isFoggyAt(
|
||||
MC.gameRenderer.getMainCamera().getBlockPosition().getX(),
|
||||
MC.gameRenderer.getMainCamera().getBlockPosition().getZ())
|
||||
|| MC.gui.getBossOverlay().shouldCreateWorldFog();
|
||||
Vector4f colorValues = mcFogRenderer.setupFog(MC.gameRenderer.getMainCamera(), MC.options.getEffectiveRenderDistance(), isFoggy, MC.deltaTracker, MC.gameRenderer.getDarkenWorldAmount(MC.deltaTracker.getGameTimeDeltaPartialTick(true)), MC.level);
|
||||
return new Color(
|
||||
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
||||
Math.max(0f, Math.min(colorValues.y, 1f)), // g
|
||||
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||
);
|
||||
#endif
|
||||
}
|
||||
// getSpecialFogColor() is the same as getFogColor()
|
||||
@@ -248,7 +295,27 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
return height;
|
||||
}
|
||||
|
||||
private RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||
protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||
|
||||
@Override
|
||||
public boolean mcRendersToFrameBuffer()
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runningLegacyOpenGL()
|
||||
{
|
||||
#if MC_VER <= MC_1_16_5
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTargetFrameBuffer()
|
||||
@@ -259,27 +326,96 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
return this.finalLevelFrameBufferId;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().frameBufferId;
|
||||
#else
|
||||
// MC renders to a texture and then directly to the default FBO now
|
||||
// we need to draw to their texture instead of the FBO
|
||||
return 0; // 0 is the ID for the default frame buffer
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTargetFrameBuffer() { this.finalLevelFrameBufferId = -1; }
|
||||
|
||||
@Override
|
||||
public int getDepthTextureId() { return this.getRenderTarget().getDepthTextureId(); }
|
||||
public int getDepthTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().getDepthTextureId();
|
||||
#else
|
||||
try
|
||||
{
|
||||
GlTexture glTexture = (GlTexture) this.getRenderTarget().getDepthTexture();
|
||||
if (glTexture == null)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
return 0;
|
||||
}
|
||||
|
||||
return glTexture.glId();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// only log this error once per session
|
||||
if (!this.depthTextureCastFailLogged)
|
||||
{
|
||||
this.depthTextureCastFailLogged = true;
|
||||
LOGGER.error("Unable to cast render Target depth texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@Override
|
||||
public int getColorTextureId() { return this.getRenderTarget().getColorTextureId(); }
|
||||
public int getColorTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().getColorTextureId();
|
||||
#else
|
||||
try
|
||||
{
|
||||
GlTexture glTexture = (GlTexture) this.getRenderTarget().getColorTexture();
|
||||
if (glTexture == null)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
return 0;
|
||||
}
|
||||
|
||||
return glTexture.glId();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// only log this error once per session
|
||||
if (!this.colorTextureCastFailLogged)
|
||||
{
|
||||
this.colorTextureCastFailLogged = true;
|
||||
LOGGER.error("Unable to cast render Target color texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTargetFrameBufferViewportWidth()
|
||||
{
|
||||
return getRenderTarget().viewWidth;
|
||||
#if MC_VER < MC_1_21_10
|
||||
return this.getRenderTarget().viewWidth;
|
||||
#else
|
||||
return this.getRenderTarget().width;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTargetFrameBufferViewportHeight()
|
||||
{
|
||||
return getRenderTarget().viewHeight;
|
||||
#if MC_VER < MC_1_21_10
|
||||
return this.getRenderTarget().viewHeight;
|
||||
#else
|
||||
return this.getRenderTarget().height;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
@@ -52,6 +52,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
|
||||
public void uploadLightmap(NativeImage image)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
int currentTexture = GLMC.getActiveTexture();
|
||||
if (this.textureId == 0)
|
||||
{
|
||||
@@ -69,13 +70,20 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
{
|
||||
GLMC.glBindTexture(currentTexture);
|
||||
}
|
||||
#else
|
||||
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||
#endif
|
||||
}
|
||||
private void createLightmap(NativeImage image)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
this.textureId = GLMC.glGenTextures();
|
||||
GLMC.glBindTexture(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);
|
||||
#else
|
||||
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.5"); // TODO that MC version number is wrong, when did we actually start using setLightmapId()?
|
||||
#endif
|
||||
}
|
||||
|
||||
public void setLightmapId(int minecraftLightmapTetxureId)
|
||||
|
||||
+3
-14
@@ -54,8 +54,10 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
||||
{
|
||||
#if MC_VER < MC_1_20_1
|
||||
level = this.getServerPlayer().getLevel();
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
level = this.getServerPlayer().serverLevel();
|
||||
#else
|
||||
level = this.getServerPlayer().level();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -69,19 +71,6 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
||||
return new Vec3d(position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewDistance() { return this.getServerPlayer().server.getPlayerList().getViewDistance(); }
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteAddress()
|
||||
{
|
||||
#if MC_VER >= MC_1_19_4
|
||||
return this.getServerPlayer().connection.getRemoteAddress();
|
||||
#else // < 1.19.4
|
||||
return this.getServerPlayer().connection.connection.getRemoteAddress();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
|
||||
+92
-11
@@ -7,6 +7,7 @@ import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.*;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
@@ -25,7 +26,6 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,7 +33,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
#if MC_VER <= MC_1_20_4
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
@@ -42,6 +47,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
#endif
|
||||
@@ -49,7 +55,12 @@ import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
||||
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); // TODO can leak
|
||||
/**
|
||||
* weak references are to prevent rare issues
|
||||
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||
* and/or for servers were the level object isn't consistent
|
||||
*/
|
||||
private static final Map<ClientLevel, WeakReference<ClientLevelWrapper>> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
||||
|
||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||
@@ -57,7 +68,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
private final ClientLevel level;
|
||||
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockCache = new ConcurrentHashMap<>();
|
||||
|
||||
/** cached method reference to reduce GC overhead */
|
||||
private final Function<BlockState, ClientBlockStateColorCache> cachedBlockColorCacheFunction = (blockState) -> this.createBlockColorCache(blockState);
|
||||
|
||||
|
||||
private BlockStateWrapper dirtBlockWrapper;
|
||||
private BlockStateWrapper waterBlockWrapper;
|
||||
private BiomeWrapper plainsBiomeWrapper;
|
||||
@Deprecated // TODO circular references are bad
|
||||
private IDhLevel parentDhLevel;
|
||||
@@ -72,10 +88,28 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// wrapper logic //
|
||||
//===============//
|
||||
//==================//
|
||||
// instance methods //
|
||||
//==================//
|
||||
|
||||
/**
|
||||
* can be used when speed is important and the same level is likely to be passed in,
|
||||
* IE rendering.
|
||||
*/
|
||||
@Nullable
|
||||
public static IClientLevelWrapper getWrapperIfDifferent(@Nullable IClientLevelWrapper levelWrapper, @NotNull ClientLevel level)
|
||||
{
|
||||
ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper;
|
||||
if (clientLevelWrapper == null
|
||||
|| clientLevelWrapper.level != level)
|
||||
{
|
||||
return getWrapper(level);
|
||||
}
|
||||
|
||||
return clientLevelWrapper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
|
||||
|
||||
@Nullable
|
||||
@@ -96,7 +130,31 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
}
|
||||
}
|
||||
|
||||
return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new);
|
||||
|
||||
WeakReference<ClientLevelWrapper> levelRef = LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.get(level);
|
||||
if (levelRef != null)
|
||||
{
|
||||
ClientLevelWrapper levelWrapper = levelRef.get();
|
||||
if (levelWrapper != null)
|
||||
{
|
||||
return levelWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.compute(level, (newLevel, newLevelRef) ->
|
||||
{
|
||||
if (newLevelRef != null)
|
||||
{
|
||||
ClientLevelWrapper oldLevelWrapper = newLevelRef.get();
|
||||
if (oldLevelWrapper != null)
|
||||
{
|
||||
return newLevelRef;
|
||||
}
|
||||
}
|
||||
|
||||
return new WeakReference<>(new ClientLevelWrapper(newLevel));
|
||||
}).get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -137,14 +195,17 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
//====================//
|
||||
|
||||
@Override
|
||||
public int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockWrapper)
|
||||
public int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockWrapper)
|
||||
{
|
||||
ClientBlockStateColorCache blockColorCache = this.blockCache.computeIfAbsent(
|
||||
((BlockStateWrapper) blockWrapper).blockState,
|
||||
(block) -> new ClientBlockStateColorCache(block, this));
|
||||
this.cachedBlockColorCacheFunction);
|
||||
|
||||
return blockColorCache.getColor((BiomeWrapper) biome, pos);
|
||||
return blockColorCache.getColor((BiomeWrapper) biome, fullDataSource, pos);
|
||||
}
|
||||
/** used by {@link ClientLevelWrapper#cachedBlockColorCacheFunction} */
|
||||
private ClientBlockStateColorCache createBlockColorCache(BlockState block) { return new ClientBlockStateColorCache(block, this); }
|
||||
|
||||
|
||||
@Override
|
||||
public int getDirtBlockColor()
|
||||
@@ -163,7 +224,27 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
}
|
||||
}
|
||||
|
||||
return this.getBlockColor(DhBlockPos.ZERO,BiomeWrapper.EMPTY_WRAPPER, this.dirtBlockWrapper);
|
||||
return this.getBlockColor(DhBlockPos.ZERO, BiomeWrapper.EMPTY_WRAPPER, null, this.dirtBlockWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaterBlockColor()
|
||||
{
|
||||
if (this.waterBlockWrapper == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.waterBlockWrapper = (BlockStateWrapper) BlockStateWrapper.deserialize(BlockStateWrapper.WATER_RESOURCE_LOCATION_STRING, this);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
LOGGER.warn("Unable to get water color with resource location ["+BlockStateWrapper.WATER_RESOURCE_LOCATION_STRING+"] with level ["+this+"].", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return this.getBlockColor(DhBlockPos.ZERO, BiomeWrapper.EMPTY_WRAPPER, null, this.waterBlockWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,7 +346,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
@Override
|
||||
public void onUnload()
|
||||
{
|
||||
LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level);
|
||||
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.remove(this.level);
|
||||
this.parentDhLevel = null;
|
||||
}
|
||||
|
||||
|
||||
+35
-10
@@ -20,6 +20,10 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.world;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||
@@ -38,6 +42,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
|
||||
@@ -57,7 +62,11 @@ import org.apache.logging.log4j.Logger;
|
||||
public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper> LEVEL_WRAPPER_BY_SERVER_LEVEL = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* weak references are to prevent rare issues
|
||||
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||
*/
|
||||
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
private final ServerLevel level;
|
||||
@Deprecated // TODO circular references are bad
|
||||
@@ -70,15 +79,29 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
//==============//
|
||||
|
||||
public static ServerLevelWrapper getWrapper(ServerLevel level)
|
||||
{ return LEVEL_WRAPPER_BY_SERVER_LEVEL.computeIfAbsent(level, ServerLevelWrapper::new); }
|
||||
{
|
||||
return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) ->
|
||||
{
|
||||
if (levelRef != null)
|
||||
{
|
||||
ServerLevelWrapper oldLevelWrapper = levelRef.get();
|
||||
if (oldLevelWrapper != null)
|
||||
{
|
||||
return levelRef;
|
||||
}
|
||||
}
|
||||
|
||||
return new WeakReference<>(new ServerLevelWrapper(newLevel));
|
||||
}).get();
|
||||
}
|
||||
|
||||
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
//==================//
|
||||
// instance methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public File getMcSaveFolder()
|
||||
@@ -93,10 +116,12 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
@Override
|
||||
public String getWorldFolderName()
|
||||
{
|
||||
#if MC_VER >= MC_1_17_1
|
||||
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
|
||||
#else // <= 1.16.5
|
||||
return this.level.getServer().getWorldScreenshotFile().getParentFile().getName();
|
||||
// Need specifically overworld since it's the only dimension that is stored in a server root folder
|
||||
|
||||
#if MC_VER >= MC_1_21_3
|
||||
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString();
|
||||
#else // <= 1.21.3
|
||||
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -179,7 +204,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
public ServerLevel getWrappedMcObject() { return this.level; }
|
||||
|
||||
@Override
|
||||
public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); }
|
||||
public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); }
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
+48
-25
@@ -50,6 +50,9 @@ import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepBiomes;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures;
|
||||
@@ -60,10 +63,7 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepSurfa
|
||||
|
||||
import net.minecraft.server.level.*;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.UpgradeData;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.chunk.storage.IOWorker;
|
||||
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
||||
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||
@@ -73,19 +73,17 @@ import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
#if MC_VER >= MC_1_19_4
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#else
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#elif MC_VER <= MC_1_19_2
|
||||
import net.minecraft.core.Registry;
|
||||
#else
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_20_4
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
#else
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -113,7 +111,13 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
||||
() -> Config.Common.Logging.logWorldGenLoadEvent.get());
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
|
||||
#elif MC_VER < MC_1_21_10
|
||||
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING);
|
||||
#else
|
||||
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* flags */0);
|
||||
#endif
|
||||
|
||||
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||
|
||||
@@ -170,6 +174,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
@NotNull
|
||||
public static final ImmutableMap<EDhApiWorldGenerationStep, Integer> WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP;
|
||||
public static final int MAX_WORLD_GEN_CHUNK_BORDER_NEEDED;
|
||||
|
||||
@@ -201,11 +206,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
builder.put(EDhApiWorldGenerationStep.LIGHT, 0);
|
||||
WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP = builder.build();
|
||||
|
||||
// TODO this is a test to see if the additional boarder is actually necessary or not.
|
||||
// If world generators end up having infinite loops or other unexplained issues,
|
||||
// this should be set back to the commented out logic below
|
||||
// in James' testing as of 2025-09-13 a border here of 2
|
||||
// and a getChunkPosToGenerateStream() radius of 14 provided more accurate
|
||||
// structure generation, however it also caused extreme server lag
|
||||
// a border of 0 here and a getChunkPosToGenerateStream() radius of 8 provided
|
||||
// good-enough structure generation while not lagging the server
|
||||
MAX_WORLD_GEN_CHUNK_BORDER_NEEDED = 0;
|
||||
//MAX_WORLD_GEN_CHUNK_BORDER_NEEDED = WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.values().stream().mapToInt(Integer::intValue).max().getAsInt();
|
||||
}
|
||||
|
||||
public BatchGenerationEnvironment(IDhServerLevel serverlevel)
|
||||
@@ -383,7 +389,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
CompletableFuture.allOf(readFutures).join();
|
||||
|
||||
// future chain for generation
|
||||
return CompletableFuture.runAsync(() ->
|
||||
return CompletableFuture.runAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
// offset 1 chunk in both X and Z direction so we can generate an even number of chunks wide
|
||||
// while still submitting an odd number width to MC's internal generators
|
||||
@@ -406,10 +414,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
int centerZ = refPosZ + radius + zOffset;
|
||||
|
||||
// get/create the list of chunks we're going to generate
|
||||
IEmptyChunkRetrievalFunc fallbackFunc =
|
||||
IEmptyChunkRetrievalFunc fallbackFunc =
|
||||
(chunkPosX, chunkPosZ) -> Objects.requireNonNull(
|
||||
generatedChunkByDhPos.get(new DhChunkPos(chunkPosX, chunkPosZ)),
|
||||
() -> String.format("Requested chunk [%d, %d] unavailable during world generation", chunkPosX, chunkPosZ));
|
||||
generatedChunkByDhPos.get(new DhChunkPos(chunkPosX, chunkPosZ)),
|
||||
() -> String.format("Requested chunk [%d, %d] unavailable during world generation", chunkPosX, chunkPosZ));
|
||||
|
||||
ArrayGridList<ChunkAccess> regionChunks = new ArrayGridList<>(
|
||||
refSize,
|
||||
@@ -431,7 +439,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
// this method shouldn't be necessary since we're passing in a pre-populated
|
||||
// list of chunks, but just in case
|
||||
fallbackFunc
|
||||
);
|
||||
);
|
||||
lightGetterAdaptor.setRegion(region);
|
||||
genEvent.threadedParam.makeStructFeat(region, this.params);
|
||||
|
||||
@@ -520,7 +528,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
genEvent.threadedParam.perf.recordEvent(genEvent.timer);
|
||||
PREF_LOGGER.debugInc(genEvent.timer.toString());
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EVENT_LOGGER.error("Unexpected error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
/** @param extraRadius in both the positive and negative directions */
|
||||
private static Stream<ChunkPos> getChunkPosToGenerateStream(int genMinX, int genMinZ, int width, int extraRadius)
|
||||
@@ -559,7 +572,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
if (Config.Common.LodBuilding.pullLightingForPregeneratedChunks.get())
|
||||
{
|
||||
// attempt to get chunk lighting
|
||||
ChunkLoader.CombinedChunkLightStorage combinedLights = ChunkLoader.readLight(newChunk, chunkData);
|
||||
ChunkFileReader.CombinedChunkLightStorage combinedLights = ChunkFileReader.readLight(newChunk, chunkData);
|
||||
if (combinedLights != null)
|
||||
{
|
||||
chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage);
|
||||
@@ -689,7 +702,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
LOAD_LOGGER.debug("DistantHorizons: Loading chunk [" + chunkPos + "] from disk.");
|
||||
|
||||
@Nullable
|
||||
ChunkAccess chunk = ChunkLoader.read(level, chunkPos, chunkData);
|
||||
ChunkAccess chunk = ChunkFileReader.read(level, chunkPos, chunkData);
|
||||
if (chunk != null)
|
||||
{
|
||||
if (Config.Common.LodBuilding.assumePreExistingChunksAreFinished.get())
|
||||
@@ -731,8 +744,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registries.BIOME), null);
|
||||
#elif MC_VER < MC_1_21_3
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registries.BIOME), null);
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_10
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().lookupOrThrow(Registries.BIOME), null);
|
||||
#else
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, PalettedContainerFactory.create(level.registryAccess()), null);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -878,7 +893,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
chunkLevel = generateUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||
#else
|
||||
level.getChunkSource().addTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||
#endif
|
||||
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap); // probably not the most optimal to run updates here, but fast enough
|
||||
ChunkHolder holder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
||||
if (holder == null)
|
||||
@@ -915,7 +934,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
chunkLevel = chunkWasGeneratedUpToFeatures ? ChunkLevel.byStatus(ChunkStatus.FEATURES) : 33;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, pos, chunkLevel, pos);
|
||||
#else
|
||||
level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, pos, 0);
|
||||
#endif
|
||||
|
||||
// mitigate OOM issues in vanilla chunk system: see https://github.com/pop4959/Chunky/pull/383
|
||||
level.getChunkSource().chunkMap.tick(() -> false);
|
||||
@@ -1066,8 +1089,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
}
|
||||
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 - WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); }
|
||||
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, 0); }
|
||||
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); }
|
||||
//private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, 0); }
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
+431
-153
@@ -29,7 +29,9 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
||||
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||||
@@ -84,17 +86,23 @@ import net.minecraft.world.level.chunk.status.ChunkType;
|
||||
#endif
|
||||
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
public class ChunkLoader
|
||||
public class ChunkFileReader
|
||||
{
|
||||
private static boolean zeroChunkPosErrorLogged = false;
|
||||
private static final AtomicBoolean ZERO_CHUNK_POS_ERROR_LOGGED_REF = new AtomicBoolean(false);
|
||||
|
||||
#if MC_VER >= MC_1_19_2
|
||||
|
||||
#if MC_VER >= MC_1_21_10
|
||||
// BLOCK_STATE_CODEC can no longer be statically created since
|
||||
// it needs a level reference
|
||||
#elif MC_VER >= MC_1_19_2
|
||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||
#elif MC_VER >= MC_1_18_2
|
||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||
#endif
|
||||
|
||||
private static final String TAG_UPGRADE_DATA = "UpgradeData";
|
||||
private static final String BLOCK_TICKS_TAG_18 = "block_ticks";
|
||||
private static final String FLUID_TICKS_TAG_18 = "fluid_ticks";
|
||||
@@ -120,19 +128,16 @@ public class ChunkLoader
|
||||
CompoundTag tagLevel = chunkData;
|
||||
#endif
|
||||
|
||||
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
|
||||
int chunkX = tagGetInt(tagLevel,"xPos");
|
||||
int chunkZ = tagGetInt(tagLevel, "zPos");
|
||||
ChunkPos actualPos = new ChunkPos(chunkX, chunkZ);
|
||||
|
||||
if (!Objects.equals(chunkPos, actualPos))
|
||||
{
|
||||
#if MC_VER >= MC_1_18_2
|
||||
if (actualPos.equals(ChunkPos.ZERO))
|
||||
#else
|
||||
if (actualPos.equals(ChunkPos.INVALID_CHUNK_POS))
|
||||
#endif
|
||||
if (chunkX == 0 && chunkZ == 0)
|
||||
{
|
||||
if (!zeroChunkPosErrorLogged)
|
||||
if (!ZERO_CHUNK_POS_ERROR_LOGGED_REF.getAndSet(true))
|
||||
{
|
||||
zeroChunkPosErrorLogged = true;
|
||||
|
||||
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
||||
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
||||
"This might happen if the world was created using an external program. \n" +
|
||||
@@ -161,7 +166,7 @@ public class ChunkLoader
|
||||
#if MC_VER < MC_1_18_2
|
||||
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
||||
return null;
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
|
||||
BlendingData blendingData = readBlendingData(tagLevel);
|
||||
#if MC_VER < MC_1_19_2
|
||||
@@ -171,17 +176,42 @@ public class ChunkLoader
|
||||
if (chunkType == #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK #else ChunkType.PROTOCHUNK #endif && blendingData == null)
|
||||
return null;
|
||||
#endif
|
||||
#else
|
||||
|
||||
// ignore blending data, there appears to be an issue with parsing it in 1.21.6
|
||||
BlendingData blendingData = null;
|
||||
|
||||
if (chunkType == ChunkType.PROTOCHUNK)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
||||
long inhabitedTime = tagGetLong(tagLevel, "InhabitedTime");
|
||||
|
||||
//================== Read params for making the LevelChunk ==================
|
||||
UpgradeData upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
||||
? new UpgradeData(tagLevel.getCompound(TAG_UPGRADE_DATA)#if MC_VER >= MC_1_17_1 , level #endif )
|
||||
: UpgradeData.EMPTY;
|
||||
|
||||
boolean isLightOn = tagLevel.getBoolean("isLightOn");
|
||||
UpgradeData upgradeData = UpgradeData.EMPTY;
|
||||
// commented out 2025-06-04 as a test to see if the upgrade data
|
||||
// is actually necessary for DH or if it can be ignored
|
||||
// (if it can't be ignored we'll need to handle null responses from tagGetCompoundTag())
|
||||
//
|
||||
//#if MC_VER < MC_1_17_1
|
||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA))
|
||||
// : UpgradeData.EMPTY;
|
||||
//#elif MC_VER < MC_1_21_5
|
||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
||||
// : UpgradeData.EMPTY;
|
||||
//#else
|
||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA)
|
||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
||||
// : UpgradeData.EMPTY;
|
||||
//#endif
|
||||
|
||||
|
||||
boolean isLightOn = tagGetBoolean(tagLevel, "isLightOn");
|
||||
#if MC_VER < MC_1_18_2
|
||||
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
||||
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
||||
@@ -198,17 +228,21 @@ public class ChunkLoader
|
||||
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
||||
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
||||
#else
|
||||
#if MC_VER < MC_1_19_4
|
||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
#else
|
||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
#endif
|
||||
#if MC_VER < MC_1_19_4
|
||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
#elif MC_VER < MC_1_21_4
|
||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
||||
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
||||
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
#else
|
||||
// do we need the ticks for what we're doing?
|
||||
LevelChunkTicks<Block> blockTicks = new LevelChunkTicks<>();
|
||||
LevelChunkTicks<Fluid> fluidTicks = new LevelChunkTicks<>();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
||||
@@ -218,18 +252,25 @@ public class ChunkLoader
|
||||
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
||||
fluidTicks, inhabitedTime, levelChunkSections, null);
|
||||
#else
|
||||
|
||||
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
||||
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
||||
#endif
|
||||
// Set some states after object creation
|
||||
chunk.setLightCorrect(isLightOn);
|
||||
readHeightmaps(chunk, chunkData);
|
||||
readPostPocessings(chunk, chunkData);
|
||||
//readPostPocessings(chunk, chunkData);
|
||||
return chunk;
|
||||
}
|
||||
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
// BLOCK_STATE_CODEC is created statically
|
||||
// TODO clean up this code separation
|
||||
#else
|
||||
final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainerFactory.create(level.registryAccess()).blockStatesContainerCodec();
|
||||
#endif
|
||||
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
#if MC_VER < MC_1_19_4
|
||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
@@ -247,95 +288,142 @@ public class ChunkLoader
|
||||
#elif MC_VER < MC_1_21_3
|
||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_10
|
||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||
#else
|
||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
||||
biomes.holderByNameCodec(), PalettedContainerFactory.create(level.registryAccess()).biomeStrategy(), biomes.getOrThrow(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)
|
||||
ListTag tagSections = tagGetListTag(chunkData, "Sections", 10);
|
||||
if (tagSections == null || tagSections.isEmpty())
|
||||
{
|
||||
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))
|
||||
tagSections = tagGetListTag(chunkData, "sections", 10);
|
||||
}
|
||||
|
||||
|
||||
if (tagSections != null)
|
||||
{
|
||||
for (int j = 0; j < tagSections.size(); ++j)
|
||||
{
|
||||
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
|
||||
CompoundTag tagSection = tagGetCompoundTag(tagSections, j);
|
||||
if (tagSection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
blockStateContainer = tagSection.contains("block_states", 10)
|
||||
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states"))
|
||||
final int sectionYPos = tagGetByte(tagSection, "Y");
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
||||
{
|
||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
||||
tagSection.getLongArray("BlockStates"));
|
||||
levelChunkSection.recalcBlockCounts();
|
||||
if (!levelChunkSection.isEmpty())
|
||||
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
||||
= levelChunkSection;
|
||||
}
|
||||
#else
|
||||
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||
if (sectionId >= 0 && sectionId < chunkSections.length)
|
||||
{
|
||||
PalettedContainer<BlockState> blockStateContainer;
|
||||
#if MC_VER < MC_1_18_2
|
||||
PalettedContainer<Biome> biomeContainer;
|
||||
#else
|
||||
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||
#endif
|
||||
|
||||
|
||||
boolean containsBlockStates;
|
||||
#if MC_VER < MC_1_21_5
|
||||
containsBlockStates = tagSection.contains("block_states", 10);
|
||||
#else
|
||||
containsBlockStates = tagSection.contains("block_states");
|
||||
#endif
|
||||
|
||||
if (containsBlockStates)
|
||||
{
|
||||
#if MC_VER < MC_1_20_6
|
||||
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||
#if MC_VER < MC_1_20_6
|
||||
.getOrThrow(false, (message) -> logWarningOnce(message))
|
||||
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||
#else
|
||||
.getOrThrow((message) -> logErrorAndReturnException(message))
|
||||
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
||||
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||
#endif
|
||||
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#else
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
blockStateContainer = new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||
#else
|
||||
blockStateContainer = PalettedContainerFactory.create(level.registryAccess()).createForBlockStates();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (tagSection.contains("biomes", 10))
|
||||
{
|
||||
biomeContainer =
|
||||
biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes"))
|
||||
#if MC_VER < MC_1_18_2
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#else
|
||||
|
||||
|
||||
boolean containsBiomes;
|
||||
#if MC_VER < MC_1_21_5
|
||||
containsBiomes = tagSection.contains("biomes", 10);
|
||||
#else
|
||||
containsBiomes = tagSection.contains("biomes");
|
||||
#endif
|
||||
|
||||
if (containsBiomes)
|
||||
{
|
||||
#if MC_VER < MC_1_20_6
|
||||
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||
#else
|
||||
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
||||
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
||||
#if MC_VER < MC_1_20_6
|
||||
.getOrThrow(false, (message) -> logWarningOnce(message));
|
||||
#else
|
||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
||||
#if MC_VER < MC_1_21_3
|
||||
biomes.getHolderOrThrow(Biomes.PLAINS),
|
||||
#else
|
||||
biomes.getOrThrow(Biomes.PLAINS),
|
||||
#endif
|
||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
biomeContainer = new PalettedContainer<Holder<Biome>>(
|
||||
biomes.asHolderIdMap(),
|
||||
biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#elif MC_VER < MC_1_21_10
|
||||
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
||||
biomes.getOrThrow(Biomes.PLAINS),
|
||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#else
|
||||
biomeContainer = PalettedContainerFactory.create(level.registryAccess()).createForBiomes();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||
#else
|
||||
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -345,57 +433,108 @@ public class ChunkLoader
|
||||
#else ChunkType #endif
|
||||
readChunkType(CompoundTag tagLevel)
|
||||
{
|
||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
||||
if (chunkStatus != null)
|
||||
String statusString = tagGetString(tagLevel,"Status");
|
||||
if (statusString != null)
|
||||
{
|
||||
return chunkStatus.getChunkType();
|
||||
ChunkStatus chunkStatus = ChunkStatus.byName(statusString);
|
||||
if (chunkStatus != null)
|
||||
{
|
||||
return chunkStatus.getChunkType();
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
#if MC_VER <= MC_1_20_4 ChunkStatus.ChunkType.PROTOCHUNK;
|
||||
#else ChunkType.PROTOCHUNK; #endif
|
||||
#if MC_VER <= MC_1_20_4
|
||||
return ChunkStatus.ChunkType.PROTOCHUNK;
|
||||
#else
|
||||
return ChunkType.PROTOCHUNK;
|
||||
#endif
|
||||
}
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
CompoundTag tagHeightmaps = tagGetCompoundTag(chunkData, "Heightmaps");
|
||||
if (tagHeightmaps != null)
|
||||
{
|
||||
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 i = 0; i < tagPostProcessings.size(); ++i)
|
||||
{
|
||||
ListTag listTag3 = tagPostProcessings.getList(i);
|
||||
for (int j = 0; j < listTag3.size(); ++j)
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
||||
String heightmap = type.getSerializationKey();
|
||||
#if MC_VER < MC_1_21_5
|
||||
if (tagHeightmaps.contains(heightmap, 12))
|
||||
{
|
||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||
}
|
||||
#else
|
||||
chunk.addPackedPostProcess(ShortList.of(listTag3.getShort(j)), i);
|
||||
if (tagHeightmaps.contains(heightmap))
|
||||
{
|
||||
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmap);
|
||||
if (optionalHeightmap.isPresent())
|
||||
{
|
||||
chunk.setHeightmap(type, optionalHeightmap.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||
}
|
||||
}
|
||||
// commented out as a test as of 2025-06-04 to see if this is actually necessary for DH
|
||||
// DH probably doesn't need any chunk post-processing data
|
||||
//private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||
//{
|
||||
// ListTag tagPostProcessings = tagGetListTag(chunkData,"PostProcessing", 9);
|
||||
// if (tagPostProcessings != null)
|
||||
// {
|
||||
// for (int i = 0; i < tagPostProcessings.size(); ++i)
|
||||
// {
|
||||
// ListTag listTag3 = tagGetListTag(tagPostProcessings, i);
|
||||
// for (int j = 0; j < listTag3.size(); ++j)
|
||||
// {
|
||||
// #if MC_VER < MC_1_21_3
|
||||
// chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
||||
// #else
|
||||
// chunk.addPackedPostProcess(ShortList.of(tagGetShort(listTag3, j)), i);
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
#if MC_VER >= MC_1_18_2
|
||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||
{
|
||||
BlendingData blendingData = null;
|
||||
if (chunkData.contains("blending_data", 10))
|
||||
|
||||
|
||||
boolean containsBlendingData;
|
||||
#if MC_VER < MC_1_21_5
|
||||
containsBlendingData = chunkData.contains("blending_data", 10);
|
||||
#else
|
||||
containsBlendingData = chunkData.contains("blending_data");
|
||||
#endif
|
||||
|
||||
if (containsBlendingData)
|
||||
{
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null);
|
||||
#else
|
||||
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null));
|
||||
#endif
|
||||
try
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null);
|
||||
#else
|
||||
// blending data appears to have changed as of 1.21.6 causing a class cast exception here due to it being wrapped in a Java.Optional
|
||||
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
String message = e.getMessage();
|
||||
if (message == null || message.trim().isEmpty())
|
||||
{
|
||||
message = "Failed to parse blending data";
|
||||
}
|
||||
|
||||
logParsingWarningOnce(message, e);
|
||||
}
|
||||
}
|
||||
return blendingData;
|
||||
}
|
||||
@@ -472,33 +611,37 @@ public class ChunkLoader
|
||||
|
||||
|
||||
// if null all lights = 0
|
||||
byte[] blockLightNibbleArray = chunkSectionCompoundTag.getByteArray("BlockLight");
|
||||
byte[] skyLightNibbleArray = chunkSectionCompoundTag.getByteArray("SkyLight");
|
||||
byte[] blockLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "BlockLight");
|
||||
byte[] skyLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "SkyLight");
|
||||
|
||||
// if any sky light was found then all lights above will be max brightness
|
||||
if (skyLightNibbleArray.length != 0)
|
||||
if (blockLightNibbleArray != null
|
||||
&& skyLightNibbleArray != null)
|
||||
{
|
||||
foundSkyLight = true;
|
||||
}
|
||||
|
||||
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||
{
|
||||
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||
// if any sky light was found then all lights above will be max brightness
|
||||
if (skyLightNibbleArray.length != 0)
|
||||
{
|
||||
// chunk sections are also 16 blocks tall
|
||||
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||
foundSkyLight = true;
|
||||
}
|
||||
|
||||
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||
{
|
||||
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||
{
|
||||
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
||||
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
||||
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
||||
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
||||
// chunk sections are also 16 blocks tall
|
||||
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||
{
|
||||
skyLight = LodUtil.MAX_MC_LIGHT;
|
||||
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
||||
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
||||
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
||||
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
||||
{
|
||||
skyLight = LodUtil.MAX_MC_LIGHT;
|
||||
}
|
||||
|
||||
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
||||
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||
}
|
||||
|
||||
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
||||
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -547,9 +690,14 @@ public class ChunkLoader
|
||||
});
|
||||
}
|
||||
|
||||
private static void logWarningOnce(String message) { logWarningOnce(message, null); }
|
||||
private static void logWarningOnce(String message, Exception e)
|
||||
private static void logParsingWarningOnce(String message) { logParsingWarningOnce(message, null); }
|
||||
private static void logParsingWarningOnce(String message, Exception e)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||
{
|
||||
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||
@@ -576,6 +724,136 @@ public class ChunkLoader
|
||||
|
||||
|
||||
|
||||
//====================//
|
||||
// tag helper methods //
|
||||
//====================//
|
||||
|
||||
// TODO move into separate file (this file is getting long)
|
||||
// these tag helpers are to simplify tag accessing between MC versions
|
||||
|
||||
/** defaults to "false" if the tag isn't present */
|
||||
private static boolean tagGetBoolean(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getBoolean(key);
|
||||
#else
|
||||
return tag.getBoolean(key).orElse(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to "0" if the tag isn't present */
|
||||
private static byte tagGetByte(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getByte(key);
|
||||
#else
|
||||
return tag.getByte(key).orElse((byte)0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to "0" if the tag isn't present */
|
||||
private static short tagGetShort(ListTag tag, int index)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getShort(index);
|
||||
#else
|
||||
return tag.getShort(index).orElse((short)0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to "0" if the tag isn't present */
|
||||
private static int tagGetInt(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getInt(key);
|
||||
#else
|
||||
return tag.getInt(key).orElse(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to "0" if the tag isn't present */
|
||||
private static long tagGetLong(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getInt(key);
|
||||
#else
|
||||
return tag.getLong(key).orElse(0L);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static String tagGetString(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getString(key);
|
||||
#else
|
||||
return tag.getString(key).orElse(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static byte[] tagGetByteArray(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getByteArray(key);
|
||||
#else
|
||||
return tag.getByteArray(key).orElse(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static CompoundTag tagGetCompoundTag(CompoundTag tag, String key)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getCompound(key);
|
||||
#else
|
||||
return tag.getCompound(key).orElse(null);
|
||||
#endif
|
||||
}
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static CompoundTag tagGetCompoundTag(ListTag tag, int index)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getCompound(index);
|
||||
#else
|
||||
return tag.getCompound(index).orElse(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* defaults to null if the tag isn't present
|
||||
* @param elementType unused after MC 1.21.5
|
||||
*/
|
||||
@Nullable
|
||||
private static ListTag tagGetListTag(CompoundTag tag, String key, int elementType)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getList(key, elementType);
|
||||
#else
|
||||
return tag.getList(key).orElse(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** defaults to null if the tag isn't present */
|
||||
@Nullable
|
||||
private static ListTag tagGetListTag(ListTag tag, int index)
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
return tag.getList(index);
|
||||
#else
|
||||
return tag.getList(index).orElse(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
+8
@@ -229,8 +229,16 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
||||
{
|
||||
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
||||
if (chunkAccess instanceof LevelChunk)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
|
||||
#else
|
||||
chunkAccess.setBlockState(blockPos, blockState, /*flags*/0);
|
||||
#endif
|
||||
|
||||
// This is for post ticking for water on gen and stuff like that. Not enabled
|
||||
// for now.
|
||||
// if (blockState.hasPostProcess(this, blockPos))
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
#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 abstract class AbstractWorldGenStep
|
||||
{
|
||||
public abstract void generateGroup(
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers);
|
||||
|
||||
public abstract ChunkStatus getChunkStatus();
|
||||
|
||||
|
||||
|
||||
/** @return the list of chunks that have an earlier status and can be generated */
|
||||
protected ArrayList<ChunkAccess> getChunksToGenerate(List<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
ArrayList<ChunkAccess> chunksToGenerate = new ArrayList<>();
|
||||
|
||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||
{
|
||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||
if (chunkWrapper.getStatus().isOrAfter(this.getChunkStatus()))
|
||||
{
|
||||
// this chunk has already generated this step
|
||||
continue;
|
||||
}
|
||||
else if (chunk instanceof ProtoChunk)
|
||||
{
|
||||
chunkWrapper.trySetStatus(this.getChunkStatus());
|
||||
chunksToGenerate.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
return chunksToGenerate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+21
-24
@@ -20,12 +20,13 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
@@ -40,39 +41,35 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
public final class StepBiomes
|
||||
public final class StepBiomes extends AbstractWorldGenStep
|
||||
{
|
||||
public static final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
public static final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkWrapper> chunkWrappers)
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||
|
||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||
{
|
||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||
{
|
||||
// this chunk has already generated this step
|
||||
continue;
|
||||
}
|
||||
else if (chunk instanceof ProtoChunk)
|
||||
{
|
||||
chunkWrapper.trySetStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = this.getChunksToGenerate(chunkWrappers);
|
||||
for (ChunkAccess chunk : chunksToDo)
|
||||
{
|
||||
#if MC_VER < MC_1_18_2
|
||||
|
||||
+19
-1
@@ -37,8 +37,10 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
public final class StepFeatures
|
||||
|
||||
public final class StepFeatures extends AbstractWorldGenStep
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -48,10 +50,22 @@ public final class StepFeatures
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
@@ -88,6 +102,10 @@ public final class StepFeatures
|
||||
|
||||
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
|
||||
}
|
||||
catch (ConcurrentModificationException e) // ReportedException
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warn("Unexpected issue when generating features for chunk at pos ["+chunkWrapper.getChunkPos()+"], error: ["+e.getMessage()+"].", e);
|
||||
|
||||
+17
-4
@@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
@@ -41,7 +43,7 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
public final class StepNoise
|
||||
public final class StepNoise extends AbstractWorldGenStep
|
||||
{
|
||||
private static final ChunkStatus STATUS = ChunkStatus.NOISE;
|
||||
|
||||
@@ -49,15 +51,26 @@ public final class StepNoise
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkWrapper> chunkWrappers)
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||
|
||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||
|
||||
+18
-4
@@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
@@ -37,7 +39,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
|
||||
public final class StepStructureReference
|
||||
public final class StepStructureReference extends AbstractWorldGenStep
|
||||
{
|
||||
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
||||
|
||||
@@ -45,15 +47,26 @@ public final class StepStructureReference
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkWrapper> chunkWrappers)
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||
@@ -67,6 +80,7 @@ public final class StepStructureReference
|
||||
else if (chunk instanceof ProtoChunk)
|
||||
{
|
||||
chunkWrapper.trySetStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-38
@@ -27,7 +27,9 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -42,7 +44,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
|
||||
public final class StepStructureStart
|
||||
public final class StepStructureStart extends AbstractWorldGenStep
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
||||
@@ -52,42 +54,27 @@ public final class StepStructureStart
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
public static class StructStartCorruptedException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = -8987434342051563358L;
|
||||
|
||||
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
super("StructStartCorruptedException");
|
||||
super.initCause(e);
|
||||
fillInStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkWrapper> chunkWrappers) throws InterruptedException
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||
|
||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||
{
|
||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
||||
{
|
||||
// this chunk has already generated this step
|
||||
continue;
|
||||
}
|
||||
else if (chunk instanceof ProtoChunk)
|
||||
{
|
||||
chunkWrapper.trySetStatus(STATUS);
|
||||
}
|
||||
}
|
||||
ArrayList<ChunkAccess> chunksToDo = this.getChunksToGenerate(chunkWrappers);
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
if (this.environment.params.worldGenSettings.generateFeatures())
|
||||
@@ -101,12 +88,6 @@ public final class StepStructureStart
|
||||
#endif
|
||||
for (ChunkAccess chunk : chunksToDo)
|
||||
{
|
||||
// System.out.println("StepStructureStart: "+chunk.getPos());
|
||||
|
||||
// there are a few cases where the structure generator call may lock up (either due to teleporting or leaving the world).
|
||||
// hopefully allowing interrupts here will prevent that from happening.
|
||||
BatchGenerationEnvironment.throwIfThreadInterrupted();
|
||||
|
||||
// hopefully this shouldn't cause any performance issues (this step is generally quite quick so hopefully it should be fine)
|
||||
// and should prevent some concurrency issues
|
||||
STRUCTURE_PLACEMENT_LOCK.lock();
|
||||
@@ -151,8 +132,6 @@ public final class StepStructureStart
|
||||
{
|
||||
// the structure logic failed again, log it and move on
|
||||
LOGGER.error("Unable to create structure starts for " + chunk.getPos() + ". This is an error with MC's world generation. Ignoring and continuing generation. Error: " + secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code
|
||||
|
||||
//throw new StepStructureStart.StructStartCorruptedException(secondEx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-3
@@ -26,6 +26,8 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
@@ -37,7 +39,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
|
||||
public final class StepSurface
|
||||
public final class StepSurface extends AbstractWorldGenStep
|
||||
{
|
||||
private static final ChunkStatus STATUS = ChunkStatus.SURFACE;
|
||||
|
||||
@@ -45,13 +47,25 @@ public final class StepSurface
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment) { this.environment = batchGenerationEnvironment; }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public ChunkStatus getChunkStatus() { return STATUS; }
|
||||
|
||||
@Override
|
||||
public void generateGroup(
|
||||
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkWrapper> chunkWrappers)
|
||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||
{
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
accessWidener v1 named
|
||||
|
||||
# used when determining where to save files to
|
||||
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/nio/file/Path;
|
||||
# used to help determine what folder a clientLevel is
|
||||
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
|
||||
|
||||
# used when rendering
|
||||
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F
|
||||
accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/client/DeltaTracker$Timer;
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer level Lnet/minecraft/client/multiplayer/ClientLevel;
|
||||
|
||||
|
||||
# used for grabbing vanilla rendered chunks
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||
|
||||
# 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
|
||||
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
||||
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
||||
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
|
||||
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
|
||||
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
|
||||
|
||||
# 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;
|
||||
accessible method net/minecraft/client/gui/components/debug/DebugScreenEntries register (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/gui/components/debug/DebugScreenEntry;)Lnet/minecraft/resources/ResourceLocation;
|
||||
|
||||
# hacky stuff
|
||||
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||
|
||||
|
||||
+1
-1
Submodule coreSubProjects updated: f9bd7e2daf...ba2681d7b2
+49
-7
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "fabric-loom" version "1.8-SNAPSHOT"
|
||||
id "fabric-loom" version "1.10-SNAPSHOT"
|
||||
}
|
||||
|
||||
loom {
|
||||
@@ -72,19 +72,27 @@ dependencies {
|
||||
// runtimeOnly "javax.annotation:javax.annotation-api:1.3.2"
|
||||
// compileOnly "javax.annotation:javax.annotation-api:1.3.2"
|
||||
// modImplementation "javax.annotation:javax.annotation-api:1.3.2"
|
||||
|
||||
|
||||
// Fabric API
|
||||
addModJar(fabricApi.module("fabric-api-base", rootProject.fabric_api_version))
|
||||
addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version))
|
||||
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
||||
if (buildVersionBefore(minecraft_version, "1.21.10"))
|
||||
{
|
||||
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
||||
}
|
||||
else // > 1.21.10
|
||||
{
|
||||
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
||||
addModJar(fabricApi.module("fabric-resource-loader-v1", 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))
|
||||
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
|
||||
addModJar(fabricApi.module("fabric-entity-events-v1", rootProject.fabric_api_version))
|
||||
if (minecraft_version >= "1.19.2")
|
||||
addModJar(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version))
|
||||
else // < 1.19.2
|
||||
if (buildVersionBefore(minecraft_version, "1.19.2"))
|
||||
addModJar(fabricApi.module("fabric-command-api-v1", rootProject.fabric_api_version))
|
||||
else
|
||||
addModJar(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version))
|
||||
|
||||
// used by mod menu in MC 1.20.6+
|
||||
addModJar(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version))
|
||||
@@ -143,6 +151,40 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean buildVersionBefore(String minecraft_version, String compareVersion)
|
||||
{
|
||||
int sortValue = sortSemanticVersionOldestToNewest(minecraft_version, compareVersion);
|
||||
return sortValue == -1;
|
||||
}
|
||||
/**
|
||||
* input format: "major.minor.patch"
|
||||
* needed so we can sort versions with different length strings
|
||||
* IE: 1.21.1 should come before 1.21.10
|
||||
*/
|
||||
private static int sortSemanticVersionOldestToNewest(String version1, String version2)
|
||||
{
|
||||
String[] parts1 = version1.split("\\.");
|
||||
String[] parts2 = version2.split("\\.");
|
||||
|
||||
int major1 = Integer.parseInt(parts1[0]);
|
||||
int major2 = Integer.parseInt(parts2[0]);
|
||||
if (major1 != major2)
|
||||
{
|
||||
return Integer.compare(major1, major2);
|
||||
}
|
||||
|
||||
int minor1 = Integer.parseInt(parts1[1]);
|
||||
int minor2 = Integer.parseInt(parts2[1]);
|
||||
if (minor1 != minor2)
|
||||
{
|
||||
return Integer.compare(minor1, minor2);
|
||||
}
|
||||
|
||||
int patch1 = Integer.parseInt(parts1[2]);
|
||||
int patch2 = Integer.parseInt(parts2[2]);
|
||||
return Integer.compare(patch1, patch2);
|
||||
}
|
||||
|
||||
|
||||
task deleteResources(type: Delete) {
|
||||
delete file("build/resources/main")
|
||||
|
||||
@@ -24,25 +24,24 @@ import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
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.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -60,7 +59,10 @@ import java.nio.FloatBuffer;
|
||||
#endif
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||
#endif
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
@@ -82,6 +84,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private final ClientApi clientApi = ClientApi.INSTANCE;
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi
|
||||
@@ -101,6 +104,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
||||
LOGGER.info("Registering Fabric Client Events");
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// register mod accessors //
|
||||
//========================//
|
||||
@@ -215,76 +219,83 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
||||
// render event //
|
||||
//==============//
|
||||
|
||||
// TODO wait for fabric to re-add their rendering API
|
||||
#if MC_VER < MC_1_21_10
|
||||
WorldRenderEvents.AFTER_SETUP.register((renderContext) ->
|
||||
{
|
||||
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
|
||||
Mat4f modelViewMatrix;
|
||||
#if MC_VER < MC_1_20_6
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
#else
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
#endif
|
||||
|
||||
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
|
||||
modelViewMatrix,
|
||||
projectionMatrix,
|
||||
#if MC_VER < MC_1_21_1
|
||||
renderContext.tickDelta()
|
||||
#else
|
||||
renderContext.tickCounter().getGameTimeDeltaTicks()
|
||||
#endif
|
||||
);
|
||||
#if MC_VER < MC_1_21_1
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickDelta();
|
||||
#else
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickCounter().getGameTimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, renderContext.world());
|
||||
|
||||
|
||||
this.clientApi.renderLods();
|
||||
});
|
||||
|
||||
|
||||
// TODO add to forge and neo
|
||||
WorldRenderEvents.AFTER_ENTITIES.register((renderContext) ->
|
||||
{
|
||||
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
|
||||
Mat4f modelViewMatrix;
|
||||
#if MC_VER < MC_1_20_6
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
#else
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
#endif
|
||||
|
||||
this.clientApi.renderFadeOpaque(
|
||||
modelViewMatrix,
|
||||
projectionMatrix,
|
||||
#if MC_VER < MC_1_21_1
|
||||
renderContext.tickDelta(),
|
||||
#else
|
||||
renderContext.tickCounter().getGameTimeDeltaTicks(),
|
||||
#endif
|
||||
ClientLevelWrapper.getWrapper(renderContext.world())
|
||||
);
|
||||
#if MC_VER < MC_1_21_1
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickDelta();
|
||||
#else
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickCounter().getGameTimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, renderContext.world());
|
||||
|
||||
|
||||
this.clientApi.renderFadeOpaque();
|
||||
});
|
||||
|
||||
// TODO add to forge and neo
|
||||
WorldRenderEvents.AFTER_TRANSLUCENT.register((renderContext) ->
|
||||
{
|
||||
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||
|
||||
Mat4f modelViewMatrix;
|
||||
#if MC_VER < MC_1_20_6
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
|
||||
#else
|
||||
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
|
||||
#endif
|
||||
|
||||
this.clientApi.renderFade(
|
||||
modelViewMatrix,
|
||||
projectionMatrix,
|
||||
#if MC_VER < MC_1_21_1
|
||||
renderContext.tickDelta(),
|
||||
#else
|
||||
renderContext.tickCounter().getGameTimeDeltaTicks(),
|
||||
#endif
|
||||
ClientLevelWrapper.getWrapper(renderContext.world())
|
||||
);
|
||||
#if MC_VER < MC_1_21_1
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickDelta();
|
||||
#else
|
||||
ClientApi.RENDER_STATE.frameTime = renderContext.tickCounter().getGameTimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, renderContext.world());
|
||||
|
||||
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
// rendered in MixinLevelRenderer
|
||||
#else
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
#endif
|
||||
|
||||
this.clientApi.renderFadeTransparent();
|
||||
});
|
||||
#endif
|
||||
|
||||
|
||||
// Debug keyboard event
|
||||
@@ -316,9 +327,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
||||
#else
|
||||
ClientPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (client, handler, buffer, packetSender) ->
|
||||
{
|
||||
// Forge packet ID
|
||||
buffer.readByte();
|
||||
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
|
||||
AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
|
||||
if (message != null)
|
||||
{
|
||||
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||
@@ -336,18 +345,18 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
||||
// Check all keys we need
|
||||
for (int keyCode = GLFW.GLFW_KEY_A; keyCode <= GLFW.GLFW_KEY_Z; keyCode++)
|
||||
{
|
||||
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode))
|
||||
{
|
||||
currentKeyDown.add(keyCode);
|
||||
}
|
||||
//if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode))
|
||||
//{
|
||||
// currentKeyDown.add(keyCode);
|
||||
//}
|
||||
}
|
||||
|
||||
for (int keyCode : KEY_TO_CHECK_FOR)
|
||||
{
|
||||
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode))
|
||||
{
|
||||
currentKeyDown.add(keyCode);
|
||||
}
|
||||
//if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode))
|
||||
//{
|
||||
// currentKeyDown.add(keyCode);
|
||||
//}
|
||||
}
|
||||
|
||||
// Diff and trigger events
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.seibel.distanthorizons.fabric;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
||||
@@ -90,8 +91,8 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
||||
{
|
||||
ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor());
|
||||
|
||||
// If sodium is installed Indium is also necessary in order to use the Fabric rendering API
|
||||
if (!modChecker.isModLoaded("indium"))
|
||||
// If sodium is installed Indium is also necessary for versions 0.5 and less in order to use the Fabric rendering API
|
||||
if (!modChecker.isModLoaded("indium") && SodiumAccessor.isSodiumV5OrLess)
|
||||
{
|
||||
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
||||
LOGGER.fatal(indiumMissingMessage);
|
||||
@@ -126,7 +127,8 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void subscribeClientStartedEvent(Runnable eventHandler) { ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); }
|
||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||
{ ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); }
|
||||
|
||||
@Override
|
||||
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
||||
|
||||
+2
-6
@@ -22,9 +22,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
|
||||
ClientPlayNetworking.send(new CommonPacketPayload(message));
|
||||
#else // < 1.20.6
|
||||
FriendlyByteBuf buffer = PacketByteBufs.create();
|
||||
// Forge packet ID
|
||||
buffer.writeByte(0);
|
||||
AbstractPluginPacketSender.encodeMessage(buffer, message);
|
||||
this.encodeMessage(buffer, message);
|
||||
ClientPlayNetworking.send(WRAPPER_PACKET_RESOURCE, buffer);
|
||||
#endif
|
||||
}
|
||||
@@ -36,9 +34,7 @@ public class FabricPluginPacketSender extends AbstractPluginPacketSender
|
||||
ServerPlayNetworking.send(serverPlayer, new CommonPacketPayload(message));
|
||||
#else // < 1.20.6
|
||||
FriendlyByteBuf buffer = PacketByteBufs.create();
|
||||
// Forge packet ID
|
||||
buffer.writeByte(0);
|
||||
AbstractPluginPacketSender.encodeMessage(buffer, message);
|
||||
this.encodeMessage(buffer, message);
|
||||
ServerPlayNetworking.send(serverPlayer, WRAPPER_PACKET_RESOURCE, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.seibel.distanthorizons.fabric;
|
||||
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkProcessingEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.DhApiEventRegister;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLoadEvent;
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
@@ -7,11 +9,14 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.fabric.testing.TestChunkInputReplacerEvent;
|
||||
import com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
@@ -32,11 +37,8 @@ import com.seibel.distanthorizons.common.CommonPacketPayload;
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
|
||||
#endif
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* This handles all events sent to the server,
|
||||
* and is the starting point for most of the mod.
|
||||
@@ -48,6 +50,8 @@ import java.util.function.Supplier;
|
||||
public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final ServerApi SERVER_API = ServerApi.INSTANCE;
|
||||
@SuppressWarnings("unused")
|
||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
private final boolean isDedicatedServer;
|
||||
@@ -93,10 +97,11 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
||||
ServerTickEvents.END_SERVER_TICK.register((server) -> SERVER_API.serverTickEvent());
|
||||
|
||||
|
||||
// can be enabled to test world gen overrides without having to build a separate API project
|
||||
// can be enabled to test overrides/events without having to build a separate API project
|
||||
if (false)
|
||||
{
|
||||
DhApiEventRegister.on(DhApiLevelLoadEvent.class, new TestWorldGenBindingEvent());
|
||||
DhApi.events.bind(DhApiChunkProcessingEvent.class, new TestChunkInputReplacerEvent());
|
||||
}
|
||||
|
||||
|
||||
@@ -192,9 +197,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
||||
#else
|
||||
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
|
||||
{
|
||||
// Forge packet ID
|
||||
buffer.readByte();
|
||||
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
|
||||
AbstractNetworkMessage message = PACKET_SENDER.decodeMessage(buffer);
|
||||
if (message != null)
|
||||
{
|
||||
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 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;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public class MixinChunkSectionsToRender
|
||||
{ /* rendering before was handled via Fabric API events */ }
|
||||
#else
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.chunk.ChunkSectionLayerGroup;
|
||||
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ChunkSectionsToRender.class)
|
||||
public class MixinChunkSectionsToRender
|
||||
{
|
||||
|
||||
|
||||
// needs to fire at HEAD with a lower than normal order (less than 1000)
|
||||
// otherwise it will be canceled by Sodium
|
||||
@Inject(at = @At("HEAD"), method = "renderGroup", order = 800)
|
||||
private void renderDeferredLayer(ChunkSectionLayerGroup chunkSectionLayerGroup, CallbackInfo ci)
|
||||
{
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, Minecraft.getInstance().levelRenderer.level);
|
||||
|
||||
|
||||
if (chunkSectionLayerGroup == ChunkSectionLayerGroup.TRANSLUCENT)
|
||||
{
|
||||
ClientApi.INSTANCE.renderFadeTransparent();
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
}
|
||||
else if (chunkSectionLayerGroup == ChunkSectionLayerGroup.TRIPWIRE)
|
||||
{
|
||||
ClientApi.INSTANCE.renderFadeOpaque();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+4
-1
@@ -12,12 +12,15 @@ import java.util.List;
|
||||
@Mixin(DebugScreenOverlay.class)
|
||||
public class MixinDebugScreenOverlay
|
||||
{
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
@Inject(method = "getSystemInformation", at = @At("RETURN"))
|
||||
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
|
||||
{
|
||||
List<String> messages = cir.getReturnValue();
|
||||
F3Screen.addStringToDisplay(messages);
|
||||
}
|
||||
#else
|
||||
// handled by DhDebugScreenEntry for MC versions after 1.21.10
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+106
-15
@@ -22,31 +22,51 @@ package com.seibel.distanthorizons.fabric.mixins.client;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
#else
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.client.renderer.FogParameters;
|
||||
import org.joml.Vector4f;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#else
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
#endif
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
@@ -66,18 +86,23 @@ public class MixinFogRenderer
|
||||
#elif MC_VER < MC_1_21_3
|
||||
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
|
||||
#else
|
||||
@Unique
|
||||
private static void unused()
|
||||
#endif
|
||||
{
|
||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||
#if MC_VER < MC_1_21_6
|
||||
boolean cancelFog = cancelFog(camera, fogMode);
|
||||
#elif MC_VER < MC_1_21_6
|
||||
boolean cancelFog = cancelFog(camera);
|
||||
#else
|
||||
boolean cancelFog = cancelFog();
|
||||
#endif
|
||||
|
||||
Entity entity = camera.getEntity();
|
||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
|
||||
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
||||
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
|
||||
if (cancelFog)
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||
@@ -85,10 +110,74 @@ public class MixinFogRenderer
|
||||
#elif MC_VER < MC_1_21_3
|
||||
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
callback.setReturnValue(FogParameters.NO_FOG);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
#else
|
||||
|
||||
// In MC's FogRenderer they clamp the "renderDistanceEnd" fog field to the render distance,
|
||||
// which prevents us from disabling the vanilla fog.
|
||||
// This mixin fires after they set the "renderDistanceEnd" so we can change it.
|
||||
@WrapOperation(
|
||||
method = "setupFog",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F",
|
||||
opcode = org.objectweb.asm.Opcodes.PUTFIELD
|
||||
)
|
||||
)
|
||||
private void onSetRenderDistanceEnd(FogData instance, float value, Operation<Void> original)
|
||||
{
|
||||
if (cancelFog())
|
||||
{
|
||||
instance.environmentalStart = A_REALLY_REALLY_BIG_VALUE;
|
||||
instance.environmentalEnd = A_EVEN_LARGER_VALUE;
|
||||
|
||||
instance.renderDistanceStart = A_REALLY_REALLY_BIG_VALUE;
|
||||
instance.renderDistanceEnd = A_EVEN_LARGER_VALUE;
|
||||
}
|
||||
|
||||
// Always call the original with the modified or original value
|
||||
original.call(instance, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@Unique
|
||||
#if MC_VER < MC_1_21_6
|
||||
private static boolean cancelFog(Camera camera, FogMode fogMode)
|
||||
#else
|
||||
private static boolean cancelFog()
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_21_6
|
||||
Entity entity = camera.getEntity();
|
||||
#else
|
||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
Entity entity = camera.getEntity();
|
||||
#endif
|
||||
|
||||
|
||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||
|
||||
boolean cancelFog = !isSpecialFog;
|
||||
cancelFog = cancelFog && cameraNotInFluid;
|
||||
#if MC_VER < MC_1_21_6
|
||||
cancelFog = cancelFog && (fogMode == FogMode.FOG_TERRAIN);
|
||||
#endif
|
||||
cancelFog = cancelFog && !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial();
|
||||
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||
|
||||
return cancelFog;
|
||||
}
|
||||
|
||||
@Unique
|
||||
@@ -105,4 +194,6 @@ public class MixinFogRenderer
|
||||
return cameraNotInFluid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+112
-48
@@ -19,51 +19,78 @@
|
||||
|
||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
#if MC_VER < MC_1_19_4
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
#else
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import org.joml.Matrix4f;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_10
|
||||
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
||||
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector4f;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
#else
|
||||
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
||||
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.state.LevelRenderState;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector4f;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import net.minecraft.client.Camera;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* This class is used to mix in my rendering code
|
||||
* before Minecraft starts rendering blocks.
|
||||
* If this wasn't done, and we used Forge's
|
||||
* render last event, the LODs would render on top
|
||||
* of the normal terrain.
|
||||
*
|
||||
* This is also the mixin for rendering the clouds
|
||||
*
|
||||
* @author coolGi
|
||||
* @author James Seibel
|
||||
* @version 12-31-2021
|
||||
*/
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class MixinLevelRenderer
|
||||
{
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
|
||||
@Unique
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
|
||||
@@ -84,57 +111,94 @@ public class MixinLevelRenderer
|
||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
||||
cancellable = true)
|
||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
@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)
|
||||
#elif MC_VER < MC_1_21_10
|
||||
@Inject(at = @At("HEAD"), method = "prepareChunkRenders", cancellable = true)
|
||||
private void prepareChunkRenders(Matrix4fc projectionMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||
#else
|
||||
@Inject(at = @At("HEAD"), method = "renderLevel")
|
||||
private void renderLevel(
|
||||
GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker,
|
||||
boolean renderBlockOutline, Camera camera,
|
||||
Matrix4f positionMatrix, Matrix4f projectionMatrix, Matrix4f idkMatrix, GpuBufferSlice gpuBufferSlice,
|
||||
Vector4f skyColor, boolean thinFog, CallbackInfo callback)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER == MC_1_16_5
|
||||
// get the matrices from the OpenGL fixed pipeline
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL32.glGetFloatv(GL32.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
mcProjectionMatrix.transpose();
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
|
||||
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
|
||||
#elif MC_VER <= MC_1_20_4
|
||||
// get the matrices directly from MC
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
#elif MC_VER < MC_1_21_10
|
||||
// MC combined the model view and projection matricies
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f();
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix.setIdentity();
|
||||
#else
|
||||
// MC combined the model view and projection matricies
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
Mat4f mcProjectionMatrix = new Mat4f();
|
||||
mcProjectionMatrix.setIdentity();
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(positionMatrix);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
#endif
|
||||
|
||||
// TODO move this into a common place
|
||||
float frameTime;
|
||||
#if MC_VER < MC_1_21_1
|
||||
frameTime = Minecraft.getInstance().getFrameTime();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getFrameTime();
|
||||
#elif MC_VER < MC_1_21_3
|
||||
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
#else
|
||||
frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
|
||||
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
if (renderType.equals(RenderType.translucent()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
|
||||
mcModelViewMatrix,
|
||||
mcProjectionMatrix,
|
||||
frameTime
|
||||
);
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
}
|
||||
|
||||
// FIXME completely disables rendering when sodium is installed
|
||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
callback.cancel();
|
||||
}
|
||||
#elif MC_VER < MC_1_21_10
|
||||
// rendering handled via Fabric Api render event
|
||||
#else
|
||||
// handled here and in MixinChunkSectionsToRender
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
// rendering handled via Fabric Api render event
|
||||
#else
|
||||
@Inject(at = @At("HEAD"), method = "prepareChunkRenders")
|
||||
private void prepareChunkRenders(Matrix4fc modelViewMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||
{
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
|
||||
|
||||
// only crash during development
|
||||
if (ModInfo.IS_DEV_BUILD)
|
||||
{
|
||||
ClientApi.RENDER_STATE.canRenderOrThrow();
|
||||
}
|
||||
|
||||
ClientApi.INSTANCE.renderLods();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+24
-6
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.fabric.mixins.client;
|
||||
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.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
|
||||
@@ -34,21 +35,34 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||
#else
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
#endif
|
||||
|
||||
@Mixin(LightTexture.class)
|
||||
public class MixinLightTexture
|
||||
{
|
||||
@Shadow
|
||||
@Final
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Shadow
|
||||
@Final
|
||||
private NativeImage lightPixels;
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_5
|
||||
@Shadow
|
||||
@Final
|
||||
private TextureTarget target;
|
||||
#else
|
||||
@Shadow
|
||||
@Final
|
||||
private GpuTexture texture;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||
{
|
||||
@@ -60,11 +74,15 @@ public class MixinLightTexture
|
||||
|
||||
|
||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
|
||||
renderWrapper.updateLightmap(this.lightPixels, clientLevel);
|
||||
#elif MC_VER < MC_1_21_5
|
||||
renderWrapper.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||
#else
|
||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||
GlTexture glTexture = (GlTexture) this.texture;
|
||||
renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -1,12 +1,15 @@
|
||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
#endif
|
||||
import com.mojang.blaze3d.platform.TextureUtil;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
|
||||
/**
|
||||
* Sets Minecraft's LOD Bias (looks similar to mipmaps)
|
||||
*
|
||||
@@ -15,6 +18,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
@Mixin(TextureUtil.class)
|
||||
public class MixinTextureUtil
|
||||
{
|
||||
// TODO fix for MC 1.21.5+
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
|
||||
private static void setLodBias(int target, int pname, float param)
|
||||
@@ -27,5 +33,6 @@ public class MixinTextureUtil
|
||||
GlStateManager._texParameter(target, pname, biasValue);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.seibel.distanthorizons.fabric.mixins.server;
|
||||
|
||||
#if MC_VER < MC_1_21_4
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public class MixinLevelTicks<T>
|
||||
{
|
||||
// dummy mixin to make the loader happy
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
||||
|
||||
import net.minecraft.world.ticks.LevelTicks;
|
||||
import net.minecraft.world.ticks.ScheduledTick;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
||||
public class MixinLevelTicks<T>
|
||||
{
|
||||
// TODO put in a common location
|
||||
private static boolean isWorldGenThread()
|
||||
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
|
||||
|
||||
|
||||
|
||||
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
||||
{
|
||||
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
||||
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
||||
if (isWorldGenThread())
|
||||
{
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package com.seibel.distanthorizons.fabric.testing;
|
||||
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkProcessingEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TestChunkInputReplacerEvent extends DhApiChunkProcessingEvent
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
private static final String REPLACEMENT_BLOCK_STATE_NAMESPACE = "minecraft:stone";
|
||||
|
||||
private IDhApiBlockStateWrapper stoneBlockWrapper = null;
|
||||
private boolean initialBlockSetupComplete = false;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void blockOrBiomeChangedDuringChunkProcessing(DhApiEventParam<EventParam> event)
|
||||
{
|
||||
if (!this.initialBlockSetupComplete)
|
||||
{
|
||||
// this method can be called on multiple threads
|
||||
synchronized (this)
|
||||
{
|
||||
this.initialBlockSetupComplete = true;
|
||||
try
|
||||
{
|
||||
this.stoneBlockWrapper = DhApi.Delayed.wrapperFactory.getDefaultBlockStateWrapper(REPLACEMENT_BLOCK_STATE_NAMESPACE, event.value.levelWrapper);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.error("Unable to get ["+REPLACEMENT_BLOCK_STATE_NAMESPACE+"] block replacement cannot continue and is now disabled, error: ["+e.getMessage()+"].", e);
|
||||
DhApi.events.unbind(DhApiChunkProcessingEvent.class, this.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will happen if the initial setup fails until the unbind call is processed
|
||||
// which likely won't happen until the current chunk has finished processing
|
||||
if (this.stoneBlockWrapper == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// replace any dirt or grass block with stone
|
||||
IDhApiBlockStateWrapper block = event.value.currentBlock;
|
||||
if (block.getSerialString().contains("grass_block")
|
||||
|| block.getSerialString().contains("dirt"))
|
||||
{
|
||||
event.value.setBlockOverride(this.stoneBlockWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-2
@@ -10,11 +10,9 @@ import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
|
||||
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
+12
-2
@@ -43,11 +43,22 @@ import net.minecraft.world.phys.AABB;
|
||||
|
||||
public class SodiumAccessor implements ISodiumAccessor
|
||||
{
|
||||
/**
|
||||
* True if sodium 0.5 or less is present. <br>
|
||||
* This field is public because it's also used to check if we need Indium to be present. <br>
|
||||
* We need Indium if Sodium 0.5 or less is present.
|
||||
*/
|
||||
public static final boolean isSodiumV5OrLess;
|
||||
|
||||
#if MC_VER >= MC_1_20_1
|
||||
private static MethodHandle setFogOcclusionMethod;
|
||||
private static Object sodiumPerformanceOptions;
|
||||
#endif
|
||||
|
||||
static {
|
||||
isSodiumV5OrLess = !classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
@@ -72,8 +83,7 @@ public class SodiumAccessor implements ISodiumAccessor
|
||||
{
|
||||
if (sodiumPerformanceOptions == null)
|
||||
{
|
||||
boolean sodiumV6 = classPresent("net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer");
|
||||
if (!sodiumV6)
|
||||
if (isSodiumV5OrLess)
|
||||
{
|
||||
// sodium 0.5
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"server.MixinEntity",
|
||||
"server.MixinServerPlayer",
|
||||
"server.MixinTracingExecutor",
|
||||
"server.MixinUtilBackgroundThread"
|
||||
"server.MixinUtilBackgroundThread",
|
||||
"server.MixinLevelTicks"
|
||||
],
|
||||
"client": [
|
||||
"client.MixinClientLevel",
|
||||
@@ -16,6 +17,7 @@
|
||||
"client.MixinDebugScreenOverlay",
|
||||
"client.MixinFogRenderer",
|
||||
"client.MixinLevelRenderer",
|
||||
"client.MixinChunkSectionsToRender",
|
||||
"client.MixinLightTexture",
|
||||
"client.MixinMinecraft",
|
||||
"client.MixinOptionsScreen",
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
@@ -79,6 +80,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
|
||||
@@ -96,7 +98,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
// handles singleplayer, LAN, and connecting to a server
|
||||
ForgePluginPacketSender.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||
PACKET_SENDER.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
|
||||
{
|
||||
ClientApi.INSTANCE.pluginMessageReceived(message);
|
||||
ServerApi.INSTANCE.pluginMessageReceived(player, message);
|
||||
|
||||
@@ -118,14 +118,14 @@ public class ForgeMain extends AbstractModInitializer
|
||||
|
||||
@Override
|
||||
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); });
|
||||
}
|
||||
{ MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }
|
||||
|
||||
@Override
|
||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||
{
|
||||
// FIXME What event is this?
|
||||
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
|
||||
// to signify readiness other than FmlClientSetupEvent
|
||||
eventHandler.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,16 +45,18 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
|
||||
);
|
||||
#endif
|
||||
|
||||
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
|
||||
public ForgePluginPacketSender() { super(true); }
|
||||
|
||||
public void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
|
||||
{
|
||||
setPacketHandler((player, message) -> consumer.accept(message));
|
||||
this.setPacketHandler((player, message) -> consumer.accept(message));
|
||||
}
|
||||
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
||||
public void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
||||
{
|
||||
#if MC_VER >= MC_1_20_2
|
||||
PLUGIN_CHANNEL.messageBuilder(MessageWrapper.class, 0)
|
||||
.encoder((wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message))
|
||||
.decoder(in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)))
|
||||
.encoder((wrapper, out) -> this.encodeMessage(out, wrapper.message))
|
||||
.decoder(in -> new MessageWrapper(this.decodeMessage(in)))
|
||||
.consumerNetworkThread((wrapper, context) ->
|
||||
{
|
||||
if (wrapper.message != null)
|
||||
@@ -73,8 +75,8 @@ public class ForgePluginPacketSender extends AbstractPluginPacketSender
|
||||
.add();
|
||||
#else // < 1.20.2
|
||||
PLUGIN_CHANNEL.registerMessage(0, MessageWrapper.class,
|
||||
(wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message),
|
||||
in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)),
|
||||
(wrapper, out) -> this.encodeMessage(out, wrapper.message),
|
||||
in -> new MessageWrapper(this.decodeMessage(in)),
|
||||
(wrapper, context) ->
|
||||
{
|
||||
if (wrapper.message != null)
|
||||
|
||||
@@ -7,7 +7,9 @@ import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -51,6 +53,8 @@ import java.util.function.Supplier;
|
||||
|
||||
public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); }
|
||||
#else
|
||||
@@ -68,7 +72,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
if (this.isDedicated)
|
||||
{
|
||||
ForgePluginPacketSender.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
|
||||
PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-28
@@ -129,34 +129,35 @@ public class MixinLevelRenderer
|
||||
// get the matrices from the OpenGL fixed pipeline
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
mcProjectionMatrix.transpose();
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
|
||||
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
|
||||
#else
|
||||
// get the matrices directly from MC
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
#endif
|
||||
|
||||
|
||||
float frameTime;
|
||||
#if MC_VER < MC_1_21_1
|
||||
frameTime = Minecraft.getInstance().getFrameTime();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getFrameTime();
|
||||
#else
|
||||
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
|
||||
|
||||
|
||||
// only render before solid blocks
|
||||
if (renderType.equals(RenderType.solid()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||
ClientApi.INSTANCE.renderLods();
|
||||
}
|
||||
else if (renderType.equals(RenderType.translucent()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
}
|
||||
|
||||
// render fade
|
||||
@@ -165,27 +166,11 @@ public class MixinLevelRenderer
|
||||
// we need to trigger for the renderType after those passes are done
|
||||
if (renderType.equals(RenderType.cutout()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderFadeOpaque(
|
||||
mcModelViewMatrix,
|
||||
mcProjectionMatrix,
|
||||
frameTime,
|
||||
ClientLevelWrapper.getWrapper(this.level)
|
||||
);
|
||||
ClientApi.INSTANCE.renderFadeOpaque();
|
||||
}
|
||||
else if (renderType.equals(RenderType.tripwire()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderFade(
|
||||
mcModelViewMatrix,
|
||||
mcProjectionMatrix,
|
||||
frameTime,
|
||||
ClientLevelWrapper.getWrapper(this.level)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
callback.cancel();
|
||||
ClientApi.INSTANCE.renderFadeTransparent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -5,8 +5,8 @@ org.gradle.caching=true
|
||||
|
||||
# Mod Info
|
||||
mod_name=DistantHorizons
|
||||
mod_version=2.3.1-b
|
||||
api_version=4.0.0
|
||||
mod_version=2.3.5-b
|
||||
api_version=4.1.0
|
||||
maven_group=com.seibel.distanthorizons
|
||||
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.
|
||||
@@ -18,20 +18,23 @@ mod_issues=https://gitlab.com/jeseibel/distant-horizons/-/issues
|
||||
mod_discord=https://discord.gg/xAB8G4cENx
|
||||
|
||||
# Global Plugin Versions
|
||||
manifold_version=2024.1.37
|
||||
manifold_version=2025.1.27
|
||||
# 2023.1.17 can be used if there are mystery Java compiler issues
|
||||
nightconfig_version=3.6.6
|
||||
lz4_version=1.8.0
|
||||
xz_version=1.9
|
||||
# Before updating, read relocate_natives/README.md
|
||||
sqlite_jdbc_version=3.47.2.0
|
||||
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
||||
# (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
|
||||
|
||||
# Minecraft related libraries (included in MC's jar)
|
||||
log4j_version=2.23.1
|
||||
lwjgl_version=3.3.1
|
||||
# if we actually want to use LWJGL methods, this needs to be a MC version variable
|
||||
# since different MC versions have different LWJGL versions that aren't compatible
|
||||
# 3.3.3 is for MC 1.21.8
|
||||
lwjgl_version=3.3.3
|
||||
joml_version=1.10.2
|
||||
|
||||
# Architectury config
|
||||
@@ -51,7 +54,7 @@ versionStr=
|
||||
|
||||
# This defines what MC version Intellij will use for the preprocessor
|
||||
# and what version is used automatically by build and run commands
|
||||
mcVer=1.21.4
|
||||
mcVer=1.21.10
|
||||
|
||||
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
||||
#minecraftMemoryJavaArg="-Xmx4G"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+53
-33
@@ -21,16 +21,13 @@ package com.seibel.distanthorizons.neoforge;
|
||||
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
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.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
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.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -40,7 +37,6 @@ import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.event.level.ChunkEvent;
|
||||
import net.neoforged.neoforge.event.level.LevelEvent;
|
||||
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
|
||||
@@ -62,29 +58,14 @@ import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of the mod.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 2023-7-27
|
||||
*/
|
||||
public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
// private static SimpleChannel multiversePluginChannel;
|
||||
|
||||
// Not the cleanest way of passing this to the LOD renderer, but it'll have to do for now
|
||||
public static Mat4f currentModelViewMatrix = new Mat4f();
|
||||
public static Mat4f currentProjectionMatrix = new Mat4f();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@@ -244,16 +225,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
@SubscribeEvent
|
||||
public void beforeLevelRenderEvent(RenderLevelStageEvent event)
|
||||
{
|
||||
if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_SKY)
|
||||
{
|
||||
currentModelViewMatrix = McObjectConverter.Convert(event.getModelViewMatrix());
|
||||
currentProjectionMatrix = McObjectConverter.Convert(event.getProjectionMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
@SubscribeEvent
|
||||
public void afterLevelRenderEvent(RenderLevelStageEvent event)
|
||||
{
|
||||
@@ -272,14 +244,62 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void afterLevelEntityRenderEvent(RenderLevelStageEvent.AfterEntities event)
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, (ClientLevel)event.getLevel());
|
||||
#else
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, event.getLevelRenderer().level);
|
||||
#endif
|
||||
|
||||
ClientApi.INSTANCE.renderFadeTransparent();
|
||||
}
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
private static LevelAccessor GetEventLevel(LevelEvent e) { return e.getLevel(); }
|
||||
@SubscribeEvent
|
||||
public void afterLevelTranslucentRenderEvent(RenderLevelStageEvent.AfterTranslucentBlocks event)
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, (ClientLevel)event.getLevel());
|
||||
#else
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, event.getLevelRenderer().level);
|
||||
#endif
|
||||
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void afterLevelRenderEvent(RenderLevelStageEvent.AfterLevel event)
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, (ClientLevel)event.getLevel());
|
||||
#else
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, event.getLevelRenderer().level);
|
||||
#endif
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// should generally only need to be set once per game session
|
||||
// allows DH to render directly to Optifine's level frame buffer,
|
||||
// allowing better shader support
|
||||
MinecraftRenderWrapper.INSTANCE.finalLevelFrameBufferId = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||
}
|
||||
catch (Exception | Error e)
|
||||
{
|
||||
LOGGER.error("Unexpected error in afterLevelRenderEvent: "+e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
||||
ClientApi.INSTANCE.renderFadeOpaque();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,16 +22,18 @@ package com.seibel.distanthorizons.neoforge;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.neoforge.wrappers.NeoforgeMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.neoforge.wrappers.modAccessor.ModChecker;
|
||||
import com.seibel.distanthorizons.neoforge.wrappers.modAccessor.OptifineAccessor;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
@@ -51,9 +53,13 @@ import java.util.function.Consumer;
|
||||
|
||||
#if MC_VER < MC_1_20_6
|
||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||
#elif MC_VER < MC_1_21_8
|
||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
#else
|
||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import net.neoforged.neoforge.client.network.event.RegisterClientPayloadHandlersEvent;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -72,6 +78,11 @@ public class NeoforgeMain extends AbstractModInitializer
|
||||
{
|
||||
this.onInitializeClient();
|
||||
eventBus.addListener(this::registerNetworkingClientServer);
|
||||
|
||||
#if MC_VER < MC_1_21_8
|
||||
#else
|
||||
eventBus.addListener(this::registerClientPayloadEvent);
|
||||
#endif
|
||||
});
|
||||
|
||||
// handles dedicated servers
|
||||
@@ -99,6 +110,12 @@ public class NeoforgeMain extends AbstractModInitializer
|
||||
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
|
||||
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
|
||||
|
||||
#if MC_VER < MC_1_21_8
|
||||
#else
|
||||
public void registerClientPayloadEvent(RegisterClientPayloadHandlersEvent event)
|
||||
{ NeoforgePluginPacketSender.registerClientPacketHandler(event); }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -111,6 +128,10 @@ public class NeoforgeMain extends AbstractModInitializer
|
||||
{
|
||||
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new NeoforgePluginPacketSender());
|
||||
|
||||
// replace MC RenderWrapper with more specific neoforge version
|
||||
SingletonInjector.INSTANCE.unbind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE); // TODO replace with a replaceOrBind for simplicity
|
||||
SingletonInjector.INSTANCE.bind(IMinecraftRenderWrapper.class, NeoforgeMinecraftRenderWrapper.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,7 +162,9 @@ public class NeoforgeMain extends AbstractModInitializer
|
||||
@Override
|
||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||
{
|
||||
// FIXME What event is this?
|
||||
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
|
||||
// to signify readiness other than FmlClientSetupEvent
|
||||
eventHandler.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+32
-1
@@ -14,10 +14,19 @@ import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
#if MC_VER < MC_1_21_8
|
||||
#else
|
||||
import net.neoforged.neoforge.client.network.ClientPacketDistributor;
|
||||
import net.neoforged.neoforge.client.network.event.RegisterClientPayloadHandlersEvent;
|
||||
#endif
|
||||
|
||||
|
||||
public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
|
||||
{
|
||||
private static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> packetConsumer;
|
||||
|
||||
|
||||
|
||||
public static void setPacketHandler(RegisterPayloadHandlersEvent event, Consumer<AbstractNetworkMessage> consumer)
|
||||
{ setPacketHandler(event, (player, buffer) -> consumer.accept(buffer)); }
|
||||
public static void setPacketHandler(RegisterPayloadHandlersEvent event, BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
||||
@@ -39,9 +48,31 @@ public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
|
||||
});
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_8
|
||||
#else
|
||||
public static void registerClientPacketHandler(RegisterClientPayloadHandlersEvent event)
|
||||
{
|
||||
// as of MC 1.21.7 Neo added a separate client network register
|
||||
// https://github.com/neoforged/NeoForge/pull/2272
|
||||
event.register(CommonPacketPayload.TYPE, (payload, context) ->
|
||||
{
|
||||
if (payload.message() != null)
|
||||
{
|
||||
packetConsumer.accept(null, payload.message());
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public void sendToServer(AbstractNetworkMessage message)
|
||||
{ PacketDistributor.sendToServer(new CommonPacketPayload(message)); }
|
||||
{
|
||||
#if MC_VER < MC_1_21_8
|
||||
PacketDistributor.sendToServer(new CommonPacketPayload(message));
|
||||
#else
|
||||
ClientPacketDistributor.sendToServer(new CommonPacketPayload(message));
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
|
||||
|
||||
@@ -152,8 +152,12 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
|
||||
private static ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
|
||||
private static ServerLevelWrapper getServerLevelWrapper(ResourceKey<Level> resourceKey, PlayerEvent event)
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
//noinspection DataFlowIssue (possible NPE after getServer())
|
||||
return getServerLevelWrapper(event.getEntity().getServer().getLevel(resourceKey));
|
||||
#else
|
||||
return getServerLevelWrapper(event.getEntity().level().getServer().getLevel(resourceKey));
|
||||
#endif
|
||||
}
|
||||
|
||||
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event) { return ServerPlayerWrapper.getWrapper((ServerPlayer) event.getEntity()); }
|
||||
|
||||
+9
@@ -1,5 +1,6 @@
|
||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -8,16 +9,24 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
#else
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||
#endif
|
||||
|
||||
@Mixin(DebugScreenOverlay.class)
|
||||
public class MixinDebugScreenOverlay
|
||||
{
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
@Inject(method = "getSystemInformation", at = @At("RETURN"))
|
||||
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
|
||||
{
|
||||
List<String> messages = cir.getReturnValue();
|
||||
F3Screen.addStringToDisplay(messages);
|
||||
}
|
||||
#else
|
||||
// handled by DhDebugScreenEntry for MC versions after 1.21.10
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+117
-31
@@ -22,67 +22,87 @@ package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
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.Inject;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.client.renderer.FogParameters;
|
||||
import org.joml.Vector4f;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#else
|
||||
import net.minecraft.client.renderer.FogParameters;
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import org.joml.Vector4f;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
public class MixinFogRenderer
|
||||
{
|
||||
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
|
||||
@Unique
|
||||
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
||||
@Unique
|
||||
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
||||
|
||||
|
||||
|
||||
#if MC_VER == MC_1_17_1 || MC_VER == MC_1_18_2
|
||||
@Inject(at = @At("RETURN"),
|
||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
|
||||
remap = false)
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float partTick, CallbackInfo callback)
|
||||
#if MC_VER < MC_1_19_2
|
||||
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_21_3
|
||||
@Inject(at = @At("RETURN"),
|
||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
|
||||
remap = true)
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float partTick, CallbackInfo callback)
|
||||
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_21_6
|
||||
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
|
||||
#else
|
||||
@Inject(at = @At("RETURN"),
|
||||
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;Lorg/joml/Vector4f;FZF)Lnet/minecraft/client/renderer/FogParameters;",
|
||||
remap = true, cancellable = true)
|
||||
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float partTick, CallbackInfoReturnable<FogParameters> callback)
|
||||
@Unique
|
||||
private static void unused()
|
||||
#endif
|
||||
{
|
||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||
#if MC_VER < MC_1_21_6
|
||||
boolean cancelFog = cancelFog(camera, fogMode);
|
||||
#elif MC_VER < MC_1_21_6
|
||||
boolean cancelFog = cancelFog(camera);
|
||||
#else
|
||||
boolean cancelFog = cancelFog();
|
||||
#endif
|
||||
|
||||
Entity entity = camera.getEntity();
|
||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
|
||||
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
||||
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
|
||||
if (cancelFog)
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||
@@ -90,12 +110,77 @@ public class MixinFogRenderer
|
||||
#elif MC_VER < MC_1_21_3
|
||||
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
||||
#else
|
||||
#elif MC_VER < MC_1_21_6
|
||||
callback.setReturnValue(FogParameters.NO_FOG);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
#else
|
||||
|
||||
// In MC's FogRenderer they clamp the "renderDistanceEnd" fog field to the render distance,
|
||||
// which prevents us from disabling the vanilla fog.
|
||||
// This mixin fires after they set the "renderDistanceEnd" so we can change it.
|
||||
@WrapOperation(
|
||||
method = "setupFog",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F",
|
||||
opcode = org.objectweb.asm.Opcodes.PUTFIELD
|
||||
)
|
||||
)
|
||||
private void onSetRenderDistanceEnd(FogData instance, float value, Operation<Void> original)
|
||||
{
|
||||
if (cancelFog())
|
||||
{
|
||||
instance.environmentalStart = A_REALLY_REALLY_BIG_VALUE;
|
||||
instance.environmentalEnd = A_EVEN_LARGER_VALUE;
|
||||
|
||||
instance.renderDistanceStart = A_REALLY_REALLY_BIG_VALUE;
|
||||
instance.renderDistanceEnd = A_EVEN_LARGER_VALUE;
|
||||
}
|
||||
|
||||
// Always call the original with the modified or original value
|
||||
original.call(instance, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@Unique
|
||||
#if MC_VER < MC_1_21_6
|
||||
private static boolean cancelFog(Camera camera, FogMode fogMode)
|
||||
#else
|
||||
private static boolean cancelFog()
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_21_6
|
||||
Entity entity = camera.getEntity();
|
||||
#else
|
||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
Entity entity = camera.getEntity();
|
||||
#endif
|
||||
|
||||
|
||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||
|
||||
boolean cancelFog = !isSpecialFog;
|
||||
cancelFog = cancelFog && cameraNotInFluid;
|
||||
#if MC_VER < MC_1_21_6
|
||||
cancelFog = cancelFog && (fogMode == FogMode.FOG_TERRAIN);
|
||||
#endif
|
||||
cancelFog = cancelFog && !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial();
|
||||
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||
|
||||
return cancelFog;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static boolean cameraNotInFluid(Camera camera)
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
@@ -110,4 +195,5 @@ public class MixinFogRenderer
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+108
-99
@@ -19,48 +19,53 @@
|
||||
|
||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
#if MC_VER < MC_1_19_4
|
||||
import com.mojang.math.Matrix4f;
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy;
|
||||
import net.minecraft.client.Camera;
|
||||
#if MC_VER < MC_1_21_6
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import org.joml.Matrix4f;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
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 net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||
import org.joml.Matrix4f;
|
||||
#else
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to mix in DH's rendering code
|
||||
* before Minecraft starts rendering blocks.
|
||||
* If this wasn't done, and we used Forge's
|
||||
* render last event, the LODs would render on top
|
||||
* of the normal terrain. <br><br>
|
||||
*
|
||||
* This is also the mixin for rendering the clouds
|
||||
*/
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy;
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class MixinLevelRenderer
|
||||
{
|
||||
@@ -70,73 +75,67 @@ public class MixinLevelRenderer
|
||||
#endif
|
||||
private ClientLevel level;
|
||||
|
||||
@Unique
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
|
||||
cancellable = true)
|
||||
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_19_4
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
|
||||
cancellable = true)
|
||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_20_2
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
||||
cancellable = true)
|
||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_20_6
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
|
||||
cancellable = true)
|
||||
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double camX, double camY, double camZ, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
@Inject(at = @At("HEAD"), method = "renderSectionLayer")
|
||||
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||
#elif MC_VER < MC_1_21_10
|
||||
@Inject(at = @At("HEAD"), method = "renderLevel")
|
||||
private void onRenderLevel(
|
||||
GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker,
|
||||
boolean renderBlockOutline, Camera camera,
|
||||
Matrix4f positionMatrix, Matrix4f projectionMatrix, GpuBufferSlice gpuBufferSlice,
|
||||
Vector4f skyColor, boolean thinFog, 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
|
||||
@Inject(at = @At("HEAD"), method = "renderLevel")
|
||||
private void renderLevel(
|
||||
GraphicsResourceAllocator resourceAllocator, DeltaTracker deltaTracker,
|
||||
boolean renderBlockOutline, Camera camera,
|
||||
Matrix4f positionMatrix, Matrix4f projectionMatrix, Matrix4f idkMatrix, GpuBufferSlice gpuBufferSlice,
|
||||
Vector4f skyColor, boolean thinFog, CallbackInfo callback)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER == MC_1_16_5
|
||||
// get the matrices from the OpenGL fixed pipeline
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
mcProjectionMatrix.transpose();
|
||||
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
|
||||
#elif MC_VER <= MC_1_20_4
|
||||
// get the matrices directly from MC
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
#if MC_VER < MC_1_21_6
|
||||
// MC combined the model view and projection matricies
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
|
||||
ClientApi.RENDER_STATE.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;
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
float frameTime;
|
||||
#if MC_VER < MC_1_21_1
|
||||
frameTime = Minecraft.getInstance().getFrameTime();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getFrameTime();
|
||||
#elif MC_VER < MC_1_21_3
|
||||
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
|
||||
#else
|
||||
frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||
ClientApi.RENDER_STATE.frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
|
||||
#endif
|
||||
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
|
||||
// only crash during development
|
||||
if (ModInfo.IS_DEV_BUILD)
|
||||
{
|
||||
ClientApi.RENDER_STATE.canRenderOrThrow();
|
||||
}
|
||||
|
||||
// render LODs
|
||||
if (renderType.equals(RenderType.solid()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||
ClientApi.INSTANCE.renderLods();
|
||||
}
|
||||
else if (renderType.equals(RenderType.translucent()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, frameTime);
|
||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||
}
|
||||
|
||||
// render fade
|
||||
@@ -145,28 +144,38 @@ public class MixinLevelRenderer
|
||||
// we need to trigger for the renderType after those passes are done
|
||||
if (renderType.equals(RenderType.cutout()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderFadeOpaque(
|
||||
mcModelViewMatrix,
|
||||
mcProjectionMatrix,
|
||||
frameTime,
|
||||
ClientLevelWrapper.getWrapper(this.level)
|
||||
);
|
||||
ClientApi.INSTANCE.renderFadeOpaque();
|
||||
}
|
||||
else if (renderType.equals(RenderType.tripwire()))
|
||||
{
|
||||
ClientApi.INSTANCE.renderFade(
|
||||
mcModelViewMatrix,
|
||||
mcProjectionMatrix,
|
||||
frameTime,
|
||||
ClientLevelWrapper.getWrapper(this.level)
|
||||
);
|
||||
}
|
||||
|
||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
callback.cancel();
|
||||
ClientApi.INSTANCE.renderFadeTransparent();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if MC_VER < MC_1_21_6
|
||||
|
||||
// formerly handled in renderChunkLayer()
|
||||
|
||||
#else
|
||||
@Inject(at = @At("HEAD"), method = "prepareChunkRenders")
|
||||
private void renderChunkLayer(Matrix4fc modelViewMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||
{
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
|
||||
|
||||
// only crash during development
|
||||
if (ModInfo.IS_DEV_BUILD)
|
||||
{
|
||||
ClientApi.RENDER_STATE.canRenderOrThrow();
|
||||
}
|
||||
|
||||
ClientApi.INSTANCE.renderLods();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+39
-23
@@ -19,17 +19,14 @@
|
||||
|
||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||
|
||||
|
||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.neoforge.wrappers.NeoforgeTextureUnwrapper;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -37,30 +34,37 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
#elif MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||
#elif MC_VER < MC_1_21_10
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
#else
|
||||
import net.neoforged.neoforge.client.blaze3d.validation.ValidationGpuTexture;
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
#endif
|
||||
|
||||
@Mixin(LightTexture.class)
|
||||
public class MixinLightTexture
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
@Shadow
|
||||
@Shadow
|
||||
@Final
|
||||
private NativeImage lightPixels;
|
||||
|
||||
|
||||
@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);
|
||||
}
|
||||
#elif MC_VER < MC_1_21_5
|
||||
@Shadow
|
||||
@Final
|
||||
private TextureTarget target;
|
||||
#else
|
||||
@Shadow
|
||||
@Final
|
||||
private GpuTexture texture;
|
||||
#endif
|
||||
|
||||
@Shadow @Final private TextureTarget target;
|
||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||
{
|
||||
@@ -70,9 +74,21 @@ public class MixinLightTexture
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
#if MC_VER < MC_1_21_3
|
||||
renderWrapper.updateLightmap(this.lightPixels, clientLevel);
|
||||
#elif MC_VER < MC_1_21_5
|
||||
renderWrapper.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||
#elif MC_VER < MC_1_21_10
|
||||
GlTexture glTexture = (GlTexture) this.texture;
|
||||
renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
|
||||
#else
|
||||
int id = NeoforgeTextureUnwrapper.getGlTextureIdFromGpuTexture(this.texture);
|
||||
renderWrapper.setLightmapId(id, clientLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
+6
@@ -1,6 +1,8 @@
|
||||
package com.seibel.distanthorizons.neoforge.mixins.client;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
#endif
|
||||
import com.mojang.blaze3d.platform.TextureUtil;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -15,6 +17,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
@Mixin(TextureUtil.class)
|
||||
public class MixinTextureUtil
|
||||
{
|
||||
// TODO fix for MC 1.21.5+
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
|
||||
private static void setLodBias(int target, int pname, float param)
|
||||
@@ -27,5 +32,6 @@ public class MixinTextureUtil
|
||||
GlStateManager._texParameter(target, pname, biasValue);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.seibel.distanthorizons.neoforge.mixins.server;
|
||||
|
||||
#if MC_VER < MC_1_21_4
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public class MixinLevelTicks<T>
|
||||
{
|
||||
// dummy mixin to make the loader happy
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
||||
import net.minecraft.world.ticks.LevelTicks;
|
||||
import net.minecraft.world.ticks.ScheduledTick;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
||||
public class MixinLevelTicks<T>
|
||||
{
|
||||
// TODO put in a common location
|
||||
private static boolean isWorldGenThread()
|
||||
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
|
||||
|
||||
|
||||
|
||||
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
||||
{
|
||||
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
||||
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
||||
if (isWorldGenThread())
|
||||
{
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.seibel.distanthorizons.neoforge.wrappers;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
#else
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
import net.neoforged.neoforge.client.blaze3d.validation.ValidationGpuTexture;
|
||||
#endif
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public class NeoforgeMinecraftRenderWrapper extends MinecraftRenderWrapper
|
||||
{
|
||||
public static final NeoforgeMinecraftRenderWrapper INSTANCE = new NeoforgeMinecraftRenderWrapper();
|
||||
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getDepthTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
// no special handling required,
|
||||
// both neo/fabric uses the same back end objects
|
||||
return super.getDepthTextureId();
|
||||
#else
|
||||
try
|
||||
{
|
||||
GpuTexture gpuTexture = this.getRenderTarget().getDepthTexture();
|
||||
int id = NeoforgeTextureUnwrapper.getGlTextureIdFromGpuTexture(gpuTexture);
|
||||
return id;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// only log this error once per session
|
||||
if (!this.depthTextureCastFailLogged)
|
||||
{
|
||||
this.depthTextureCastFailLogged = true;
|
||||
LOGGER.error("Unable to cast render Target depth texture to GlTexture. MC or a rendering mod may have changed the object type.", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColorTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_10
|
||||
// no special handling required,
|
||||
// both neo/fabric uses the same back end objects
|
||||
return super.getColorTextureId();
|
||||
#else
|
||||
try
|
||||
{
|
||||
GpuTexture gpuTexture = this.getRenderTarget().getColorTexture();
|
||||
int id = NeoforgeTextureUnwrapper.getGlTextureIdFromGpuTexture(gpuTexture);
|
||||
return id;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// only log this error once per session
|
||||
if (!this.colorTextureCastFailLogged)
|
||||
{
|
||||
this.colorTextureCastFailLogged = true;
|
||||
LOGGER.error("Unable to cast render Target color texture to ValidationGpuTexture or GlTexture. MC, Neoforge, or a rendering mod may have changed the object type.", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.seibel.distanthorizons.neoforge.wrappers;
|
||||
|
||||
#if MC_VER < MC_1_21_10
|
||||
public class NeoforgeTextureUnwrapper
|
||||
{ /* not needed for older MC versions */ }
|
||||
#else
|
||||
|
||||
import com.mojang.blaze3d.opengl.GlTexture;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
import net.neoforged.neoforge.client.blaze3d.validation.ValidationGpuTexture;
|
||||
|
||||
public class NeoforgeTextureUnwrapper
|
||||
{
|
||||
/**
|
||||
* if Neoforge texture validation is enabled the GlTexture object will be wrapped with a
|
||||
* Neoforge specific ValidationGpuTexture object.
|
||||
* This helper allows us to get the underlying OpenGL texture ID
|
||||
* regardless of what Neoforge returns.
|
||||
*/
|
||||
public static int getGlTextureIdFromGpuTexture(GpuTexture gpuTexture) throws ClassCastException
|
||||
{
|
||||
GlTexture glTexture;
|
||||
|
||||
if (gpuTexture instanceof ValidationGpuTexture)
|
||||
{
|
||||
ValidationGpuTexture validationTexture = (ValidationGpuTexture) gpuTexture;
|
||||
glTexture = (GlTexture)validationTexture.getRealTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexture = (GlTexture) gpuTexture;
|
||||
}
|
||||
|
||||
int id = glTexture.glId();
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -8,7 +8,8 @@
|
||||
"server.MixinServerPlayer",
|
||||
"server.MixinTFChunkGenerator",
|
||||
"server.MixinTracingExecutor",
|
||||
"server.MixinUtilBackgroundThread"
|
||||
"server.MixinUtilBackgroundThread",
|
||||
"server.MixinLevelTicks"
|
||||
],
|
||||
"client": [
|
||||
"client.MixinClientPacketListener",
|
||||
|
||||
@@ -3,6 +3,8 @@ loaderVersion = "*" # // mandatory. Allow all forge versions as we are definding
|
||||
license = "LGPL"
|
||||
issueTrackerURL = "${issues}"
|
||||
|
||||
# https://docs.neoforged.net/docs/gettingstarted/modfiles/#neoforgemodstoml
|
||||
|
||||
|
||||
[[mods]] #//mandatory
|
||||
modId = "distanthorizons" #//mandatory
|
||||
@@ -32,4 +34,11 @@ issueTrackerURL = "${issues}"
|
||||
type = "required"
|
||||
versionRange = "${compatible_forgemc_versions}" # Where we set what version of mc it is avalible for
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
side = "BOTH"
|
||||
|
||||
[[dependencies.distanthorizons]]
|
||||
modId = "neoforge"
|
||||
type = "required"
|
||||
versionRange = "${neoforge_version_range}"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
This directory contains the native files of libraries that were modified for relocation. They will be copied from here during the normal build steps.
|
||||
|
||||
Before adding/updating a library, make sure you have Python 3.8+ installed and check the instructions below.
|
||||
|
||||
How to add a library's natives:
|
||||
|
||||
1. In `build.gradle`:
|
||||
|
||||
- Make sure the target package is the same length or shorter (untested) than the source package. Underscores in native methods will be mapped to `_1` so account for that as well.
|
||||
- Exclude the native files and add them as `relocateNative` (see example).
|
||||
|
||||
Example:
|
||||
|
||||
```groovy
|
||||
relocate "org.sqlite", "dh_sqlite", {
|
||||
exclude "org/sqlite/native/**"
|
||||
}
|
||||
|
||||
transform(NativeTransformer) {
|
||||
// NativeTransformer configuration
|
||||
rootDir = project.rootDir
|
||||
|
||||
// Replace native strings, e.g. used in calls back to Java
|
||||
relocateNative "org/sqlite", "dh_sqlite"
|
||||
// Rename native methods used when calling from Java
|
||||
relocateNative "org_sqlite", "dh_1sqlite"
|
||||
}
|
||||
```
|
||||
|
||||
How to update a library's natives:
|
||||
|
||||
1. Delete the library's folder in cache/.
|
||||
2. It will repopulate during the next build.
|
||||
|
||||
Why does this step exist?
|
||||
|
||||
- Native files are not handled by the shadow plugin correctly.
|
||||
- I preferred it as a more streamlined approach, although a bit hacky.
|
||||
- Possible alternatives:
|
||||
- Use edited libraries' source code: although more straightforward, it requires maintaining and updating the repositories for the libraries being added
|
||||
- Interfacing with the necessary libraries directly: an absolute mess for technical reasons
|
||||
|
||||
What are libraries used?
|
||||
|
||||
- LIEF: for fixing binaries after replacing strings
|
||||
- apple-codesign: for re-signing Mac binaries, since their signatures get invalidated after previous steps
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user